# `MishkaDocument.Plugins.PageFrame`
[🔗](https://github.com/mishka-group/mishka_document/blob/v0.0.1/lib/mishka_document/plugins/page_frame.ex#L5)

Tells the site's layout what only a documentation page knows — the languages the document or the
page it shows is written in, and the bar under the header — through the `runtime:page:frame`
mishka_installer hook `MishkaCmsWeb.RuntimeLive` fires in `handle_params/3`
(`MishkaCmsCore.Runtime.SiteLayout` is the contract: the map it is handed and what it reads
back).

A page is matched by the kind of record it says it shows (`record`, its `extra`'s `"record"`):
`"docs:document"`, a document's front page, or `"docs:page"`, one page of a document — the kinds
`MishkaDocument.Plugins.PageRecords` names, the ones `MishkaDocument.Plugins.PageSeo` answers
for. The library, which shows no record, is matched by its section, `"document"`. Every other page
is handed back untouched, before anything is read.

## The languages

The header's language switcher is the only one the documentation has. On a document's pages it
lists the languages THAT record is written in, each at the address of its own edition, which is
what `language_group_id` says: the editions of a document are the documents sharing it, and the
edition of a page is the page of the other document's latest version that shares its own group,
else the one with the same slug, for a translation nobody linked. The core's default would offer
this same path in every language, and an edition's slugs are its own: the Persian edition of
`/docs/handbook/install` is `/fa/docs/rahnama/nasb`.

  * a document's front page: each edition of the document, titled with its name;
  * a page: each edition that has the page, titled with the page's title there. An edition that
    has no such page is not offered, as a language a record has no edition in never is;
  * an edition is at the address its document has, `/chelekom/docs`, else under the
    documentation's base by its slug (`MishkaDocument.Provision.item_paths/0`), and the page under
    it as `MishkaDocument.Address` writes it, in the address the site's URL mode gives that
    language (`MishkaCmsCore.Runtime.Languages.url/3`). No version number crosses to another
    edition, which numbers its versions on its own: it is read at its latest.

Every edition is read as the visitor, the frame's `current_user`, and none of it is read here: the
page read the document, its other editions with their versions, and the pages of the version
shown once for its head, its frame and its blocks (`source`, `MishkaDocument.PageSource`), and
only the pages of the version each other edition is on are read here, in one read. The edition
being read is offered only when the visitor's own read found it — the document on its front page,
the page among the pages they read on one of its pages — and a visitor it is kept from is offered
no language. Another edition (or, for a page, the page of it) locked to permissions is offered to
a reader who holds one of them, and a guest, or a reader who holds none, is offered only what a
guest can read, so an edition is never named to someone who may not open it. The library keeps
the core's default.

## The bar

Every page of the documentation has the bar, titled `Docs` and linking to the library. A
document's pages add the trail under it, the document and then the page, and the version in a
menu on its trailing side: the kit's `doc-switcher`, which reads the document's versions and the
same page in each of them. It is a component with state of its own, so the bar gives it an `id`
and the page's `params`, and `MishkaDocument.Plugins.ContentComponents` names it for the site's
stylesheet, since only the bar draws it. It reads the versions and their pages as the visitor
too, so the bar hands it the `current_user` the frame names, and the page's rows (`page_source`),
which hold the document, its versions and the pages of the version shown.

The words are the site's own translations (`MishkaCmsCore.Runtime.Translations`), in the language
of the response, and the key itself where nobody has written one. `MishkaDocument.Provision`
registers them (`words/0`) when it sets a site up, and `MishkaDocument.Plugins.UsedTranslationKeys`
names them to "Remove unused".

Registered in MishkaDocument.Application.

# `error_return`

```elixir
@type error_return() ::
  {:error, [%{action: atom(), field: atom(), message: String.t()}]}
```

# `okey_return`

```elixir
@type okey_return() :: {:ok, struct() | map() | module() | [any()]}
```

# `bar_components`

```elixir
@spec bar_components() :: [String.t()]
```

The components the bar draws on a document's pages, by name. No page or layout names them, so
`MishkaDocument.Plugins.ContentComponents` hands them to the site's stylesheet.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `config`

```elixir
@spec config() :: keyword()
```

# `config`

```elixir
@spec config(atom()) :: any()
```

# `enable`

```elixir
@spec enable() :: okey_return() | error_return()
```

# `get`

```elixir
@spec get() :: keyword()
```

# `health_check`

```elixir
@spec health_check() :: :ok | {:degraded, term()} | {:error, term()}
```

Optional. See `c:MishkaInstaller.Event.Hook.health_check/0`. Override to report health.

# `on_dependency_error`

```elixir
@spec on_dependency_error(term()) :: term()
```

Optional. See `c:MishkaInstaller.Event.Hook.on_dependency_error/1`. Override to react.

# `register`

```elixir
@spec register() :: okey_return() | error_return()
```

# `restart`

```elixir
@spec restart() :: okey_return() | error_return()
```

# `start`

```elixir
@spec start() :: okey_return() | error_return()
```

# `start_link`

# `stop`

```elixir
@spec stop() :: okey_return() | error_return()
```

# `unregister`

```elixir
@spec unregister() :: okey_return() | error_return()
```

# `words`

```elixir
@spec words() :: [String.t()]
```

The words the bar asks the site's translations for, for `MishkaDocument.Provision` to register:
the documentation's name.

---

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