Naming conversions of the tessera wire contract (CONTRACT.md §1).
| Elixir (spec) | DOM / JS | Rule |
|---|---|---|
attr :display_name | attribute display-name | snake → kebab |
prop :tag_list | property tagList | snake → camel |
event "persona-select" | CustomEvent persona-select | kebab, verbatim |
event "persona-select" | binding prop on_persona_select | "on_" <> snake |
event "persona-select" | default action :persona_select | snake(event) |
detail key persona_id | detail key personaId | snake → 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
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).
@spec event_regex() :: Regex.t()
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.
@spec known_types() :: [atom()]
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.
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_).
@spec snake_regex() :: Regex.t()
Spec identifier grammar for attr/prop/detail names: snake_case atoms.
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_case atom → kebab-case DOM attribute name.
@spec tag_regex() :: Regex.t()
Custom-element tag grammar (CONTRACT.md §1): lowercase with a hyphen.