Converts a Mishka Chelekom .exs + .eex source pair into the
final Runtime.Component create-params shape consumed by the
MishkaCMS UI-kit installer (schema mishka.ui_kit.bundle.v3).
This module owns every kit-specific decision. The MishkaCMS-side
installer is a trivial loader: Jason.decode! + Ash.bulk_create.
No re-narrowing, no rewriting, no slug-guessing happens at install
time. Whatever this module emits is what lands in the database.
Pipeline
1. `read_exs/1` eval `.exs`, get name/args/scripts
2. `render_maximal/2` EEx-eval with all-options assigns
3. `parse_ast/1` `Code.string_to_quoted!`
4. `walk/1` collect public defs, private defps,
attr/slot decls bound to each def,
module attributes, prelude (alias/
import/use) with Tier-1 dedup
5. `resolve_aliased_attrs/2` map `attr :x, JS, ...` → struct type
with full module path
6. `drop_unrepresentable_defaults/1` strip struct/map/call AST
defaults that can't survive JSON
7. `rewrite_sibling_refs/3` HEEx tokenizer pass on every public
fn's `~H""` content; rewrite sibling
tags to `<.component component_name=
"<kit>-<X-slug>" .../>`
8. `slug_names/2` apply lowercase + hyphen rewrite to
every emitted name
9. `emit_components/3` one component-params per public def
Summary
Functions
Convert one .exs + .eex pair into an ordered list of v3
component-params (one entry per public function in the source) plus
the script entries from the .exs's scripts: field.
Lightweight pre-pass: returns just the public-function names from a
.exs+.eex pair. Used by the Mix task to harvest the kit-wide set
before invoking convert/5 per file (so cross-file <.X/> refs
rewrite correctly).
Types
Functions
@spec convert(String.t(), String.t(), String.t(), String.t(), keyword()) :: {:ok, %{components: [component_params()], scripts: [map()]}} | {:error, term()}
Convert one .exs + .eex pair into an ordered list of v3
component-params (one entry per public function in the source) plus
the script entries from the .exs's scripts: field.
Options
:base64(boolean) — whentrue, encodetemplate/bodystrings as"base64:" <> Base.encode64(...). Defaultfalse.:extra_siblings(MapSet<String.t()>) — public-function names from OTHER.exsfiles in the same kit. Templates that reference them (e.g.tabs.eexcalling<.scroll_area/>) get rewritten to the runtime-helper form just like same-file siblings. Default empty MapSet.
Lightweight pre-pass: returns just the public-function names from a
.exs+.eex pair. Used by the Mix task to harvest the kit-wide set
before invoking convert/5 per file (so cross-file <.X/> refs
rewrite correctly).