# `MishkaCmsCore.Runtime.PageBuilder.Snippets`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/page_builder/snippets.ex#L5)

The Studio's snippet list, over `MishkaCmsCore.Runtime.Snippet`.

What the panel needs beyond the stored row — how many blocks a snippet holds, how big it is, what
colour its swatch is — is DERIVED from the markup here rather than stored beside it, so a snippet
can never claim three blocks while holding one.

Saving takes a serialised subtree. `MishkaCmsCore.Runtime.PageBuilder.EditorSession` already knows
how to cut one out (`Tree.subtree/2` + `Serializer.to_heex/1`) for the clipboard; a snippet is that
same string kept past the session.

# `delete`

```elixir
@spec delete(String.t(), map() | nil) :: :ok | {:error, term()}
```

Deletes one snippet by id, as `actor`.

A site user may delete only its own site's snippets: not a global one, and not another site's.
The id alone is not authority, because it travels in a `phx-value-id` that anyone can type — a
snippet the actor cannot read is `{:error, :not_found}`, whether it is gone or someone else's.

# `list`

```elixir
@spec list(map()) :: [map()]
```

The snippets one editor should offer: this site's plus the global ones, for this section, filtered
by the Studio's chip. Read as `opts[:actor]`, who sees only the sections whose builder they may
open.

`filter` is `"all"`, `"page"` or `"global"` — the chips as they are written in the panel.

# `row`

```elixir
@spec row(struct()) :: map()
```

One stored snippet as the panel draws it.

Public because the Studio's list is a Gervaz table now: the table hands its template Ash records,
and every value the row shows beyond `name` is read off `source` rather than stored beside it. One
derivation site, whether the caller came through `list/1` or through the table.

# `save`

```elixir
@spec save(map()) :: {:ok, map()} | {:error, term()}
```

Saves `source` under `name`, as `opts[:actor]`.

Refuses markup that does not parse: a snippet that cannot be inserted is worse than no snippet,
because the failure surfaces later and somewhere else. A master names the site (`nil` offers it to
every site); a site user saves into their own site.

# `sections`

```elixir
@spec sections() :: [atom()]
```

The editor sections a snippet can belong to.

# `source`

```elixir
@spec source(String.t(), map() | nil) :: String.t() | nil
```

One snippet's markup, or `nil` — what the insert path needs and nothing more.

Read as `actor`: a site user inserts its own site's snippets and the global ones, which is what
`list/1` offers it. Another site's stays invisible.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
