MishkaCmsCore.Builder.Furnishing (Mishka CMS Core v0.0.1)

Copy Markdown View Source

What a component says it should look like the moment it is dropped — declared by whoever wrote it, rather than guessed by this CMS.

Why this exists

MishkaCmsCore.Runtime.PageBuilder.Starter can furnish a dropped component without being told anything: it reads Phoenix's own inner_block convention and the conventional slot names, and falls back to a generic line. That works, and it works for a kit this install has never seen — but it is inference. The word "alert" in a component's name is a guess about what the component means, and nobody who ships a component library should have to name things this CMS's way to get a good drop.

So a component may declare its own, and a declaration always wins:

"extra": {
  "furnishing": {
    "body": "<tr><td>Ada Lovelace</td><td>Active</td></tr>",
    "slots": [
      {"name": "header", "body": "Name"},
      {"name": "header", "body": "Status"},
      {"name": "option", "body": "First choice", "attrs": {"value": "one"}}
    ]
  }
}

Both keys are optional. body alone furnishes the content between the tags; slots alone furnishes a component whose content is a list of entries; declaring body: "" explicitly says "put nothing inside", which a spinner wants and the heuristics would otherwise override.

Untrusted by construction

This is a third party's JSON, on the same footing as the bundle itself — see MishkaCmsCore.UiKit.Contract, which is why anything malformed answers :none and the heuristics take over, rather than raising into a palette render. A slot entry that fails validation is dropped on its own; the rest of the furnishing stands.

Two things it deliberately does NOT do. It does not accept a function or a module reference: a furnishing may travel through a MishkaInstaller hook payload, which is plain-map only — the MishkaCmsCore.Dashboard.Widget rule. And it does not template anything; the strings are HEEx fragments written verbatim, so a component that wants a random id asks for one through the ordinary seeding path rather than through a placeholder syntax invented here.

Summary

Functions

Reads a declared furnishing, or answers :none when there is none to read.

Whether a declaration says anything at all.

A sample %MishkaCmsCore.Builder.Furnishing{} populated from defaults + type-based fallbacks.

Types

t()

@type t() :: %MishkaCmsCore.Builder.Furnishing{
  attrs: map() | nil,
  body: String.t() | nil,
  declares_body: boolean() | nil,
  slots: list() | nil
}

Functions

build(declared)

@spec build(term()) :: {:ok, t()} | :none

Reads a declared furnishing, or answers :none when there is none to read.

:none is not a failure — most components declare nothing, and the heuristics are the answer for them. It is also what a malformed declaration gets, for the reason in the moduledoc.

builder(attrs_or_input, error \\ false)

empty?(arg1)

@spec empty?(t()) :: boolean()

Whether a declaration says anything at all.

A furnishing that validated but carries neither a body nor a slot is treated as absent, so a kit writing "furnishing": {} does not silently strip the content the heuristics would have given.

enforce_keys()

enforce_keys(field)

example()

A sample %MishkaCmsCore.Builder.Furnishing{} populated from defaults + type-based fallbacks.

keys()

keys(field)