# `MishkaCmsCore.Runtime.DraftPreviewAssets`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.5-alpha.5/lib/mishka_cms_core/runtime/draft_preview_assets.ex#L5)

Temporary, isolated CSS and compiled module for a runtime preview — a draft (Page/Layout/ErrorPage)
or a live original reached by its `preview_token` — NEVER the live site bundle or the live page
module.

The CSS is compiled on every request and kept nowhere (`css/2`): the saved stylesheets, Tailwind
over the record's own markup (so a draft with brand-new classes is styled), and a draft's own
element CSS (`element_css`) laid over its document's row as its publish writes it. A draft's CSS
therefore lives in the draft alone, and goes when the draft is published or deleted. Served at
`/_preview/:resource/:token/css` (see `MishkaCmsWeb.DraftPreviewController`), and linked by
`MishkaCmsWeb.DraftPreviewLive`. JS is NOT compiled per-draft — the preview is a real LiveView
that loads the site's existing JS bundle, which already exports every active hook (a draft
template's `phx-hook` references `JsHook` rows in that bundle), so hooks run with no extra work.
The token records the site its JS belongs to in `AssetsState` (`remember_site/2`) — the record's
own, or for a global record the host's it is opened on — so the bundle is handed to whoever holds
the link, by that site's state (`site/1`), on an address `served_on?/2` allows.

A page or a layout is drawn by its compiled module (`ensure_module/2`), built by the compiler its
site uses, so its own helpers and the live components it nests render as on the published page.
The module is named after the token, so a draft never replaces the live one, and is compiled again
only when the record was saved since or is opened on another site. `purge/1` unloads it with the
site, and `MishkaCmsWeb.DraftPreviewLive` unloads it when the preview closes.

# `css`

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

The preview's temporary CSS, compiled now from the record as it is, as the site's own CSS is: the
host shell, the global and the site's saved stylesheets, the record's own markup, and a draft's
own element CSS laid over its document's element-CSS row (`element_css`, see
`MishkaCmsCore.Runtime.Authoring.Drafts`).

`asset_site` is the site a record with none of its own — a global layout — is compiled against:
the host the preview is opened on.

NOTHING IS CACHED. A preview is opened to see the draft as it stands, so it is compiled on every
call, a Tailwind pass of a few seconds. One record compiles one at a time: its markup is written
to a temporary folder named after it, which a second compile alongside would delete under the
first. Returns `{:ok, css}` or `:error`.

# `ensure_module`

The module a Page, Layout or one of their drafts is previewed with, compiled if missing or older
than the record, against `asset_site`'s hooks. `{:ok, module}`, or `{:error, message}` when it
does not compile.

A compile is the `[:mishka_cms, :runtime, :draft_preview, :compile]` span, with the `module` as its
metadata: it starts in the calling process before it asks for the module's lock, and stops with
the answer.

# `purge`

Delete the record's preview site and its compiled module (on publish / discard).

# `remember_site`

Records the site the preview's assets under the record's token belong to: the record's own, or for
a global record `asset_site`, the host's it is opened on.

# `served_on?`

```elixir
@spec served_on?(String.t() | nil, map() | nil) :: boolean()
```

Whether a preview of a record of `site_id` (`nil` for a global one) may be served on the address of
`current_site`, the site the request's host resolved to.

The master site's address serves every site's previews, and a site's own address serves its own.
A global record belongs to every site, so any site's address serves it. Another site's address,
or a request no site answers for, serves nothing: a preview of site A is never shown on site B.

    served_on?(site_a_id, %{id: site_a_id, master: false})  #=> true
    served_on?(site_a_id, %{id: master_id, master: true})   #=> true
    served_on?(site_a_id, %{id: site_b_id, master: false})  #=> false
    served_on?(nil, %{id: site_b_id, master: false})        #=> true

# `site`

The site the preview's assets under `token` belong to: `{:ok, site_id}`, `{:ok, nil}` for a global
record opened with no site, or `:error` when no preview has been opened under it.

# `unload_module`

Unloads the record's preview module. A process still drawing it keeps the old code, and the next
`ensure_module/2` compiles it again.

---

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