= Stag User Manual
:author: Michał Góral
:toc: left
:url-python-markdown: https://python-markdown.github.io/
:url-jinja-templates: https://jinja.palletsprojects.com/en/3.0.x/templates/

Stag (abbreviation from "static generator") is a lightweight, customizable
and easily extensible generator of static web pages. It is format-agnostic,
but comes bundled with support for Markdown input files.

This manual focuses on end-user part of 

== Plugins

Almost every part of stag is a plugin. There are 3 types of them:

readers:::
  plugins responsible for reading the files

generators:::
  plugins responsible for generating the output data from the input returned
  by readers

writers:::
  plugins responsible for writing output to the files, generating templates,
  copying static files etc.

The order of running plugins is: readers → generators → writers. The order of
plugins inside a single category of plugins can be configured in config.toml.

You can easily add custom plugins. Stag reads their path from the
`pluginspath` setting in config.toml. By default it is _plugins_ directory
relative to the root directory of the project.

.Plugins configuration
----
pluginspath = "path/to/myplugins"
readers = ["markdown", "static"]
generators = ["macros", "markdown"]
writers = ["theme", "copy"]
----

NOTE: once you add custom plugins, remember to add them to the appropriate
      lists in config.toml. You ensure this way their order of execution.
      Also remember about adding built-in plugins if you wish to continue
      using them, because otherwise they will be overriden.

=== Readers

Readers are invoked one after the other. The first one which is able to read
a specific file is used to do so and the remaining ones are discarded.
Because of this behaviour, readers are best ordered from the most specific
one (like readers for specific file types) to the most generic ones (like
built-in xref:_static[static reader]).

=== Generators and writers

Stag tries to run all generators and all writers on all pages. Generators and
writers decide for themselves if they should process pages.

This prevents having huge, monolithic, unmaintanable plugins. Instead we have
many small plugins, which can focus on specific tasks.

== Built-in plugins

=== markdown

For Markdown stag provides both reader and generator.

Markdown reader reads Markdown files, which can have optional front matter
with metadata, which is also saved by the reader. Front matter is expected to
be in TOML format, delimited with `+++` (3 plus signs) from the top and
bottom.

.Example Markdown file with front matter
----
+++
title = "My First Stag Page!"
date = 2021-09-02
tags = ["site", "something else"]
+++
This was a **triumph**!
----

Markdown generator takes input provided by the Markdown reader and generates
HTML data from it. It uses {url-python-markdown}[Python Markdown] package.
Its extensions are enabled through `plugins.markdown.extensions` list.

Both reader and writer share `plugins.markdown` table in config.toml.

.Example markdown configuration
----
[plugins.markdown]
extensions = ["sane_list", "smarty", "footnotes"]
----

=== theme

Theme extension is a writer which uses {url-jinja-templates}[Jinja
Template Engine] to create files from the output produced by generators.

It is configured in `plugins.theme` table. Most important setting is _name_,
which is a path to the directory from which templates will be read. Other
important sub-table is `[plugins.theme.templates]`, which contains settings
for default templates used for certain.

==== Template type deduction

To produce a page, theme plugin needs to know which template should be used
from the available ones. It does so by deducing a type of a page:

. first it takes `page.output.type` to know the expected file type of the
  produced file
. then it takes the content type of the page from the page metadata
  (`page.output.metadata["type"]`). It is set by the user and can be
  anything.
. if page has no type in its metadata, the plugin does its best to detect the
  kind of the page:
.. if it is a taxonomy landing page, its type is set to
   `plugins.theme.templates.taxonomy` (by default: _taxonomy_)
.. if it is a list page (page which lists subpages), its type is set to
   `plugins.theme.templates.list` (by default: _list_)
.. otherwise its type is taken from `plugins.theme.templates.page` (by
   default: _page_)
. last, page type and extension are joined together to form a name of
  template which will be used to render the output.

There might be a situation when deduced template isn't available. In such
case, theme plugin provides a very basic built-in template and informs users
about the situation with appropriate error prints.

.Template deduction with user-defined type
====
Suppose the following Markdown page:

----
+++
title = ""
type = "mypage"
+++
----

This page will use _mypage.html_ template, because the output of Markdown
rendering is html file and the type selected by the user for this page is
"mypage".
====

.Template deduction without user-defined type
====
Consider the following Markdown page:

----
+++
title = ""
+++

Here theme must deduce the name, because there's no one provided by the user.
It is an ordinary page, so it will be taken from
`plugins.theme.templates.page`. If this setting wasn't changed, the template
which will be rendered from _page.html_.
----
====

.Name clash?
====
Consider the following Markdown page:

----
+++
title = ""
type = "taxonomy"
+++
----

and the following configuration:

----
[plugins.theme.templates]
taxonomy = "somethingelse"
----

The output page will be rendered from _taxonomy.html_, *not* from
_somethingelse.html_, because the _type_ keyword in metadata directly maps to
the name of the used template, not to the default value from config.toml.
====

=== macros

Macros is a generator which provides a capability to use Jinja macros inside
input files (e.g. in Markdown). It enabled a system which resembles
"shortcodes" known from other static site generators.

To enable macros you must configure path to the directory which contains
Jinja templates with macros definitions. Macros use `[plugins.macros]` table
in config.toml to do that.

.Example macros configuration
----
[plugins.macros]
path = "directory/with/macros"
----

.Example of file which use a macro
----
+++
title = "My Page"
++++

{% from "macros.html" import mymacro %}

Ordinary content {{ mymacro(foo="bar") }} rest of ordinary content.
----

=== static

Reader used to generate page information for all files which it encounters,
without any further parsing. This information is typically used by the
xref:_copy[copy writer].

Typically, it should be the last reader used.

=== copy

Writer used to copy static files. It automatically copies all the files which
were not processed by any generator.

== Taxonomies

Taxonomies are automatically generated collections of pages (e.g. tags or
categories). They must be enabled in config.toml and are generated from
metadata of content files.

.Enabling 2 taxonomies in config.toml
----
[[taxonomies]]
key = "tags"
singular = "tag"
plural = "tags"

[[taxonomies]]
key = "category"
plural = "categories"
----

Once defined, stag scans metadata of files and groups files which have the same
metadata:

.Setting terms of taxonomy on a page
----
tags = ["foo", "bar"]
category = "my category"
----

Each taxonomy generates a taxonomy landing page and a list of term pages.
(think of _tags/foo_, _tags/bar_ etc.):

Taxonomy Landing Page:::
  it contains data regarding taxonomy itself and a list of term pages, which
  can be accessed from `page.list`.
Term Pages:::
  each of them contains a list of ordinary pages, which belong to the term
  (e.g. which have a specific tag); they can be accessed from `page.list`.
  Additionaly they have `metadata['taxonomy']` set with a name of parent
  taxonomy.

NOTE: Taxonomies are generated after generators are all done, but before
      writers.

=== Rendering taxonomies

Taxonomies are rendered like the ordinary pages (see
xref:_template_type_deduction[Template type deduction], but they use
different default template. Both landing and term pages use *list* template
(e.g. _list.html_). This can be customised in two ways:

. Default templates for all taxonomy/term pages can be changed in
  `[plugins.theme.templates]` section.
+
.Setting different default templates for taxonomy page and terms pages
----
[plugins.theme.templates]
taxonomy = "mytaxonomy"
list = "mylist"
----
. If stag finds a file which would result with the same URL as taxonomy or
  term page, it incorporates it instead of throwing a usual error:
.. Metadata of the file is preserved, but missing entries necessary for
   taxonomies are created: this can be used to pass custom metadata to Jinja
   and template. For example `type` can be explicitly set, which will result
   in choosing a different template.
.. File content is preserved.
.. page lists and taxonomy data is added to the `page` object and overrides
   any previous entries.
+
====
For example, to add a metadata to the "tags" taxomony, create a file
_tags.md_ or _tags/index.md_ inside your content, with the following content:

.Page for taxonomy landing page (tags.md)
----
++++
title = "List of tags"
mymetadata = "My Metadata"
----

.Page for a single tag (tags/mytag.md)
----
title = "Special case of mytag"
mytagmetadata = "special metadata"
----
====
