MishkaChelekom.CmsBundleExporter (Mishka Chelekom v0.0.9-alpha.20)

Copy Markdown View Source

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

component_params()

@type component_params() :: map()

js_hook()

@type js_hook() :: %{required(String.t()) => term()}

Functions

convert(exs_source, eex_source, kit_name, kit_version, opts \\ [])

@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) — when true, encode template/body strings as "base64:" <> Base.encode64(...). Default false.
  • :extra_siblings (MapSet<String.t()>) — public-function names from OTHER .exs files in the same kit. Templates that reference them (e.g. tabs.eex calling <.scroll_area/>) get rewritten to the runtime-helper form just like same-file siblings. Default empty MapSet.

list_public_defs(exs_source, eex_source)

@spec list_public_defs(String.t(), String.t()) ::
  {:ok, [String.t()]} | {:error, term()}

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).