Noizu.Tessera.Naming (Noizu.Tessera v0.2.0)

Copy Markdown View Source

Naming conversions of the tessera wire contract (CONTRACT.md §1).

Elixir (spec)DOM / JSRule
attr :display_nameattribute display-namesnake → kebab
prop :tag_listproperty tagListsnake → camel
event "persona-select"CustomEvent persona-selectkebab, verbatim
event "persona-select"binding prop on_persona_select"on_" <> snake
event "persona-select"default action :persona_selectsnake(event)
detail key persona_iddetail key personaIdsnake → camel

Summary

Types

A camelCase DOM name, e.g. "displayName".

A kebab-case DOM name, e.g. "display-name".

A snake_case identifier, e.g. :display_name.

Functions

Converts a camelCase key back to snakecase — mirrors the JS core's snakeKeysDeep: EVERY uppercase char becomes `""+ its lowercase (userID→user_i_d), byte-exact withpriv/js/src/events.mjs`.

Binding-prop name for an event: "on_" <> snake(event) (CONTRACT.md §1).

Default action atom for an event: snake(event) (CONTRACT.md §1).

Event-name grammar (CONTRACT.md §1): kebab-case, at least one hyphen.

kebab-case event/tag name → snake_case atom.

True when the given atom is a contract type.

Wire-contract value types (CONTRACT.md §2).

True when a snake name survives the wire round-trip: snake |> snake_to_camel |> camel_to_snake == snake.

Spec identifier grammar for attr/prop/detail names: snake_case atoms.

snake_case atom → camelCase DOM property / detail key.

snake_case atom → kebab-case DOM attribute name.

Custom-element tag grammar (CONTRACT.md §1): lowercase with a hyphen.

Types

camel()

@type camel() :: String.t()

A camelCase DOM name, e.g. "displayName".

kebab()

@type kebab() :: String.t()

A kebab-case DOM name, e.g. "display-name".

snake()

@type snake() :: atom()

A snake_case identifier, e.g. :display_name.

Functions

camel_to_snake(camel)

@spec camel_to_snake(camel()) :: snake()

Converts a camelCase key back to snakecase — mirrors the JS core's snakeKeysDeep: EVERY uppercase char becomes `""+ its lowercase (userID→user_i_d), byte-exact withpriv/js/src/events.mjs`.

event_binding_prop(event_name)

@spec event_binding_prop(kebab()) :: snake()

Binding-prop name for an event: "on_" <> snake(event) (CONTRACT.md §1).

event_default_action(event_name)

@spec event_default_action(kebab()) :: snake()

Default action atom for an event: snake(event) (CONTRACT.md §1).

event_regex()

@spec event_regex() :: Regex.t()

Event-name grammar (CONTRACT.md §1): kebab-case, at least one hyphen.

kebab_to_snake(kebab)

@spec kebab_to_snake(kebab()) :: snake()

kebab-case event/tag name → snake_case atom.

known_type?(type)

@spec known_type?(atom()) :: boolean()

True when the given atom is a contract type.

known_types()

@spec known_types() :: [atom()]

Wire-contract value types (CONTRACT.md §2).

round_trips?(name)

@spec round_trips?(snake()) :: boolean()

True when a snake name survives the wire round-trip: snake |> snake_to_camel |> camel_to_snake == snake.

The JS core and the Elixir bridge rely on this equivalence; names that do not round-trip would silently change meaning across the bridge. Fails for digit-initial segments (col_2_width → col2Width → col2_width) and for double/trailing underscores (foo__bar, foo_).

snake_regex()

@spec snake_regex() :: Regex.t()

Spec identifier grammar for attr/prop/detail names: snake_case atoms.

snake_to_camel(name)

@spec snake_to_camel(snake()) :: camel()

snake_case atom → camelCase DOM property / detail key.

BYTE-EXACT with the JS core (priv/js/src/events.mjs): split the snake string on "_" and capitalize the first letter of every segment after the first (persona_id → personaId). Note this deliberately DIFFERS from Macro.camelize/1/Macro.underscore/1 for acronyms/digits (Macro.underscore("userID") = user_id, but the JS rule gives user_i_d) — never use Macro.* for contract keys.

snake_to_kebab(name)

@spec snake_to_kebab(snake()) :: kebab()

snake_case atom → kebab-case DOM attribute name.

tag_regex()

@spec tag_regex() :: Regex.t()

Custom-element tag grammar (CONTRACT.md §1): lowercase with a hyphen.