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

Lists a site's published documentation in its `/sitemap.xml`, through the `seo:sitemap:urls`
mishka_installer hook `MishkaCmsCore.Runtime.Compilers.SitemapCompiler` fires when it builds the
site's sitemap. Its `pages` are the site's indexable pages holding a capture only their owner can
fill; this appends an address for every document and every page of one to its `urls`. A
workspace, version or section written rebuilds its site's sitemap, because those resources list
`MishkaCmsCore.Runtime.Resources.Notifiers.SitemapRefresh`.

Each document is listed at its front page and each page of it at its own, at the paths
`MishkaDocument.Provision.item_paths/0` names, filled with the document's own language and slugs
— a page's own part of the address being the slugs of the pages it is filed under, then its own
(`MishkaDocument.Address.paths/1`) — at the address the site's URL mode gives that language
(`MishkaCmsCore.Runtime.Languages.url/3`). A document with an address of its own is listed there
instead, its pages under it: its front page is a page of the site at a fixed path, which the
sitemap already lists as one, so only its pages are added here. A version's front page is drawn
at its document's own address (`MishkaDocument.Address`), so it is listed as that and never under
its own slug, which is a missing page; a group is only a heading, with no address to list, unless
it has a page of its own (`group_page`), listed at its slug. An
address is listed only while
the site serves its page: the page at that exact path is among `pages`, and it answers the
document's language (`MishkaCmsCore.Runtime.PageEditions.served_languages/2`). A page moved to
another path, taken down, closed to visitors or marked noindex lists nothing.

READ AS A VISITOR WHO IS NOT SIGNED IN, through the public actions, because a sitemap is for
anyone: a document that names a permission, and a page that opens with one — its own, or its
nearest parent page's (`MishkaDocument.Resources.Calculations.EffectivePermissions`) — is left out
of the reads themselves (`MishkaDocument.Resources.Preparations.OpenToActor`), so a locked
document's pages are never read and nothing locked is listed.

And only while its record may be listed (`MishkaCmsCore.Runtime.PageEditions.listed?/2`): a
document whose robots meta says `noindex` or `none` lists neither its front page nor a page of it
that holds no robots meta of its own; a page whose own robots meta says so is left out alone. The
front page of such a document with an address of its own, which core lists as a page of the site,
is taken out of `urls`, as is that of one locked to permissions, not active, in another language,
or not there at all: an address is listed only while a document a visitor may open and a search
engine may index stands at it.

THE SAME ROWS THE PAGES DRAW. `doc-section` finds a document among the active ones, shows the
version an editor marked latest among the published ones — the newest published one when none
is — and that version's approved pages. This reads exactly those, so a draft document, a page
still in review and the pages of an older version (`?v=`) are never listed. A document with no
published version still draws its front page, which its head lets a search engine index, so that
is listed, dated by the document's `updated_at`, and no page of it.

DATED BY WHEN THE PAGE LAST CHANGED. A page's `lastmod` is its `last_modified_at`
(`MishkaDocument.Resources.Calculations.LastModified`): the newest of its own `updated_at`, the
`updated_at` of its approved notes and the time a note of it was archived. A document's front
page is dated by the newest of the document's `updated_at` and those of its pages. The notes are
read in the same query as the pages, so a batch of pages is one read.

READ WHEN THE BUILD READS IT. The addresses are appended as a stream, and nothing is read until
the build reads it: the documents a hundred at a time, the version each of them shows in one read
per hundred, then the pages of those hundred together, a hundred at a time, and their front pages
after them — a front page draws its document's contents, so it last changed when the newest of
them did. Each read starts after the last row the one before it returned
(`MishkaCmsCore.Runtime.Compilers.SitemapCompiler.stream_rows/2`), and however many documents a
site has, one batch of each is held at a time — with the tree of each batch's versions, their
pages' ids, slugs and parents, which is what a page's address is read off. Each address is listed
once: a document's slug is unique on its site, its own address in its language, and a page's slug
among the pages under its parent.

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()]}
```

# `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()
```

---

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