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

What the blog tells the site's layout about each of its pages, through the `runtime:page:frame`
mishka_installer hook `MishkaCmsCore.Runtime.SiteLayout` fires in `handle_params/3`: the bar under
the header, and the languages the record a page shows is written in. The layout draws both, so no
page of the blog draws a bar or a language switcher of its own.

A page is the blog's by its section, `"blog"`, which `MishkaBlog.Provision` files every page under.
A page of another section that shows one of the blog's records, as `MishkaBlog.Plugins.PageRecords`
names them, gets its languages and no bar. Every other page is handed back untouched, before
anything is read.

## The bar

The blog's name in the home design's italic serif, leading to its front page, and its four places
as the design draws them: Posts, Categories, Tags and People (`MishkaBlog.Provision.places/0`).
The one the reader is in is marked: a post, a category and a tag are in Posts, a blogger and a team
are in People, and every other page is in the place whose page it is. That is the design's own
rule: it has no page of a category or a tag, only the Posts screen narrowed to one (opening a
category from Categories, or a tag from Tags, lands on it), and its bar marks the screen, so
Posts, whatever the reader came from. The search box is the list pages' own, beside their title,
as the design draws it; the bar has no trailing part, and nothing that needs a class in the site's
stylesheet.

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. `MishkaBlog.Provision` registers
them (`words/0`) when it sets a site up.

## The languages

The languages THIS record is written in, each at that edition's own slug, address and title:

  * a post, a category and a tag are one row per language, joined by `language_group_id` (the
    master's own id, which the master itself may not carry). Every published edition of the one the
    slug names is offered, the one being read included, at the page's own path with the edition's
    language and slug filled in (`MishkaCmsCore.Runtime.Languages.url/3`). A language the record
    has no edition in is not offered, and a record with a single edition offers none;
  * a blogger and a team are one row in every language, so each language the site publishes in is
    offered, at the same slug;
  * a list page, `/:lang/blog` or the archive, keeps what the layout would offer without a
    plugin: the same path in each language.

None of it is read here. The page read the record once for its head, its frame and its blocks,
as the visitor the frame names (`current_user`, `nil` for a guest), through `:public_list`, with
its other editions loaded in the same read (`source`, `MishkaBlog.PageSource`): an edition the
visitor may open, by its own lock or the one it inherits, is offered, and a guest is offered only
what a guest can read. An edition the visitor may not open is not offered, so its address and its
title are not shown to a reader the blog keeps it from — the one being read included: a record
the visitor may not read is offered in no language, and its page answers them 404.

## The words

`words/0` is what the bar asks the site's translations for. No template holds them, so the
plugin names them on `runtime:translations:used_keys` (`MishkaBlog.Plugins.TranslationKeys`),
where "Remove unused" would otherwise delete them.

Registered in `MishkaBlog.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()]}
```

# `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 `MishkaBlog.Provision` to register and
`MishkaBlog.Plugins.TranslationKeys` to keep: the blog's name, then the name of each place.

---

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