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

Adds the blog's posts, categories, bloggers, teams and the tags that ask to be indexed to a
site's `/sitemap.xml`, through the
`seo:sitemap:urls` mishka_installer hook `MishkaCmsCore.Runtime.Compilers.SitemapCompiler` fires
when it builds a site's sitemap. A post, a category, a tag, a blogger or a team written rebuilds its
site's sitemap, because those resources list
`MishkaCmsCore.Runtime.Resources.Notifiers.SitemapRefresh`.

Core lists the blog's pages whose only capture is the language. `/:lang/blog/:slug` also holds a
slug only this extension can fill, so core hands such a page over in the payload's `pages`, and
this fills it. A page is listed exactly when its own head lets a search engine index it, so every
row a visitor can open at an indexable address is listed, with or without posts:

  * a published post, at the post page, with `lastmod` its `updated_at` and `images` its
    `featured_image_url`, or none when it has no such image;
  * an active category, at its page, with `lastmod` its `updated_at`;
  * a blogger who is not archived, and an active team, at its page in each language the page
    answers, with `lastmod` its `updated_at`;
  * a tag only when its own `seo_tags` hold a robots meta that says `index`: a public tag's page
    says `noindex` (`MishkaBlog.Plugins.PageSeo`) unless its own robots meta replaces that.

Each row at its own language and slug, at the address the site's URL mode gives it
(`MishkaCmsCore.Runtime.Languages.url/3`). A kind is listed only while `pages` holds its page —
the page whose `extra` says it shows that kind (`"blog:post"`, `"blog:category"`, `"blog:tag"`,
`"blog:author"`, `"blog:team"`), which every page `MishkaBlog.Provision` writes says — so a page
switched off, closed to visitors or marked noindex lists nothing — and a row only in a
language that page answers (`PageEditions.served_languages/2`), so no address here 404s. A row
that opens with a permission, or whose own `seo_tags` hold a robots meta saying `noindex` or
`none`, is left out as such a page is (`PageEditions.listed?/2`): a post or a category in a locked
category is too, as its page asks for that category's
(`MishkaBlog.Resources.Calculations.EffectivePermissions`).

A kind whose page names permissions lists nothing: the build reads as a guest, and a guest is
shown no post, category, tag, blogger or team whose page is closed to them
(`MishkaBlog.Resources.Preparations.OpenToActor`).

The addresses follow the payload's `urls` as a stream, and nothing is read while the hook runs:
the build reads the rows as it reads the stream, through `:public_list` as the blog's pages read
them, on the payload's site, as a guest — a build has nobody signed in behind it, and a crawler is
a guest — a hundred at a time after the last one read
(`MishkaCmsCore.Runtime.Compilers.SitemapCompiler.stream_rows/2`). Each row is listed once, since
a slug is unique on its site. 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()
```

---

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