Sidebar LogoHomeInstallationUsageIndexIndexGitHub </> Back Next Plugins

Plugins


About plugins

Plugins automate and simplify typical tasks and make the documentation more structural and easy to use.

The main approach used by this program is no interference in the Markdown syntax. So the documentation content must be readable in plain text even without processing by this program. Plugins provide extra possibilities for the templates processing and visualization.

See here for an example of how plugins are defined in the argument file.


"relative-paths" plugin

Motivation

The program generates static HTML pages that reference other pages and resources like CSS and pictures. The generated HTML pages may be located in different places of the project structure, so the same resources must be referenced differently from different pages.

In the following example:

$ tree -L 2 --charset=ascii --dirsfirst
.
|-- doc
|   |-- about.html
|   `-- styles.css
|-- pict
|   `-- logo.png
`-- readme.html

the reference to styles.css is:

This plugin automatically recalculates relative paths for certain pages depending on their location and avoids manual definition of these paths for every page individually. It also allows substitution of such paths inside the documents.

Definition

Here's an example of the plugin definition:

{
    "documents": [
        { "input": "readme.txt", "output": "readme.html", "title": "Home" },
        { "input": "doc_src/about.txt", "output": "doc/about.html", "title": "About" }
    ],
    "plugins": {
        "relative-paths": {
            "markers": ["path"],
            "paths": {
                "resource_path": "doc/",
                "pict": "doc/pict/"
            }
        }
    }
}

This is the new syntax. The previous syntax (that doesn't support substitution inside documents) is also supported:

        "relative-paths": { "resource_path": "doc/" }

In this example, resource_path and pict are path codes, and the corresponding values are paths themselves.

The plugin considers the paths and the current page location being relative to the same location, that is the program invocation current directory in this case. When it calculates the path with the code resource_path then:

Usage

Include the following tag to the template:

<link rel="stylesheet" type="text/css" href="{{resource_path}}styles.css"/>

That's it. When a document using this template is generated, this tag will be replaced with the desired path.

For substitution inside a document insert the text like this:

![](<!--path pict-->logo.png) 

After the page is generated this fragment will look like this:

For page readme.html For page doc/about.html
![](pict/logo.png) ![](../pict/logo.png)

"page-flows" plugin

Motivation

Sidebar provides quick access to different project pages. It's often very helpful to put a sequence of pages that are intended to be read in order. Doing it manually is pretty cumbersome and error-prone.

This plugin defines such pages sequences and and provides them for easy manipulation in templates.

Definition

Note

You may want to also look at the new syntax described here.

In the "plugins" sections:

{
    "documents": [
        { "input": "page1.txt", "output": "page1.html", "title": "Page 1" },
        { "input": "page2.txt", "output": "doc/page2.html", "title": "Page 2" },
        { "input": "page3.txt", "output": "doc/page3.html", "title": "Page 3" }
    ],
    "plugins": {
        "page-flows": {
            "sidebar": [
                { "link": "page1.html", "title": "Page 1" },
                { "link": "doc/page2.html", "title": "Page 2", "class": "align_right" },
                { "link": "doc/page3.html", "title": "Page 3", "highlight": true },
                { "link": "www.google.com", "title": "Search", "external": true }
            ]
        }
    }
}

Here we see the page flow sidebar that contains four link definitions. Each link definition has main attributes link, title, external. Also other arbitrary attributes (like class and highlight) may be added and then used in the templates (will be discussed below).

In the above example the three pages are defined twice. To avoid such repetition the page flows may be defined directly in the "documents" section:

{
    "documents": [
        { "input": "page1.txt", "title": "Page 1", "page-flows": ["sidebar"] },
        { "input": "page2.txt", "title": "Page 2", "page-flows": ["sidebar"] },
        { "input": "page3.txt", "title": "Page 3", "page-flows": ["sidebar"] }
    ],
    "plugins": {
        "page-flows": {}
    }
}

But the plugin itself must be activated to make it work. So even if all page flows are defined in the "documents" section the plugin empty definition must be added to the "plugins" section.

The "page-flows" document definition may be carried out to the "default" section (not demonstrated here). Several page flows may be defined and a single page may be a part of several page flows.

Usage

In a template, each page flow is accessible by its name (sidebar in this example) and provides the following structured data:

Field Description
{{sidebar}} Iterable, returns pages
{{sidebar.previous}} Previous page if exists
{{sidebar.current}} Current page if exists
{{sidebar.next}} Next page if exists
{{sidebar.has_navigation}} Boolean, true if ether previous or next page exist
{{sidebar.not_empty}} Boolean, true if contains at least one page

The page has the following structure:

Field Description
{{link}} The link that references the page. Recalculated for the current page
{{title}} The title of the page
{{external}} Boolean, external pages can never be current
{{first}} Boolean, true if this is the first page in the sequence
{{last}} Boolean, true if this is the last page in the sequence
{{class}} Example of a custom arbitrary attribute

This data is calculated for every page that uses this template. So for the current page we can know the previous and the next pages and render the navigations. Here's a simple example:

{{#sidebar.previous}}<a href="{{link}}">[PREVIOUS]</a>{{/sidebar.previous}}
{{#sidebar.next}}<a href="{{link}}">[NEXT]</a>{{/sidebar.next}}

Explanation

{{#sidebar.previous}}...{{/sidebar.previous}} means that if sidebar.previous value exists then the enclosed content is rendered. sidebar.previous value is a page and has attribute link that is used in the rendered block.

Also for the current page we have the whole page sequence of the page flow and can render this list in the sidebar. As we know which page or pages are current, we can highlight this links. Here's a simplified example of how the sidebar items may be rendered:

<ul>{{#sidebar}}
<li><a class="sidebarItem{{#current}} selected{{/current}}" href="{{link}}">{{title}}</a></li>
{{/sidebar}}</ul>

Explanation

{{#sidebar}}...{{/sidebar}} means that for each item in the sidebar value (that is iterable) render the enclosed content. The items are pages and their attributes link, title and current are used in the rendered block.

This documentation demonstrates pretty typical usage of this plugin. Also see the template doc_src/templates/multipage.html and the argument file md2html_args.json for more understanding of correspondence between the plugin's definition and usage.

New syntax

In version 1.0.3 new syntax was introduced. The following example demonstrates the differences:

.  .  .
    "plugins": {
        "page-flows": {
            "sections": { "groups": ["sidebar"] },
            "header": [
                { "link": "readme.html", "title": "Home" },
                { "link": "doc/content/sections/installation.html", "title": "Installation" },
                { "link": "doc/content/sections/usage.html", "title": "Usage" }
            ],
            "useful_links": { "title": "Useful links", "groups": ["sidebar"], "items": [
                { "link": "https://mustache.github.io/", "title": "Mustache", "external": true },
                { "link": "https://json.org/", "title": "JSON", "external": true }
            ]}
        },
    }
.  .  .

The useful_links page flow is defined using the full syntax. The page flow has a title, a list of groups and the content defined by the items attributes. The content definition is a list of the pages just the same way as in the old syntax.

The sections page flow defines only the necessary attributes. The title is an empty string by default. The content is empty initially and it may be defined in the documents section.

The header page flow uses the old syntax. Two syntaxes may be used in the same argument file that makes the previously written documentation compatible with the new version of the program.

The purpose of this change is to remove specific elements from the templates and to avoid boilerplates. Now sidebar page flows may be defined solely in the argument file and the template file in the documentation project may be updated with the other one taken from the outside without subsequent customization. Here's a sidebar block that may be defined for the above argument file fragment:

{{#sidebar}}
{{#title}}<h3>{{.}}</h3>{{/title}}
{{#.}}<a class="sidebar_item{{#current}} selected{{/current}}" href="{{link}}">{{title}}</a>
{{/.}}
{{/sidebar}}

The sidebar variable contains a list of page flows for which it's defined (here there are two such page flows). As each page flow now has a title then this title may be conditionally rendered using the Mustache syntax. Elements {{#.}} and {{/.}} represent a current page flow that here is represented as a number of links. Current links are highlighted with the selected CSS class.


"page-variables" plugin

Motivation

This plugin extracts variables from document source texts and provides these variables to be used in the template.

Definition

    "plugins": {
        "page-variables": {"variables": {"only-at-page-start": true} }
    }

This means that variables will be extracted from the page metadata blocks with marker variables and only from those blocks that are the first non-blank text on the page. This is the definition of the default marker so it may be simplified to "page-variables": {}, and this is the recommended form.

Usage

For the above plugin definition the metadata blocks may look like:

<!--variables {"title": "My page", "noPageTitle": true}-->

The marker is variables and it is case insensitive. The variables are title and noPageTitle and the tags {{title}} and {{noPageTitle}} will be replaced with the defined values when this page is processed.

The page metadata blocks will be removed from the source text if they are recognized and processed by the defined markers.

The metadata content must be a valid JSON [json].

Note

Opening <!-- and closing markers --> must not be used inside the metadata section. Also consecutive hyphens -- inside HTML comments may probably be a problem in some browsers. In JSON strings, Unicode entities may be used to resolve these issues, i.e. string "<!\u002D-text-\u002D>" will be interpreted as "<!--text-->". Still, depending on the page content and the context, opening and closing markers, even when escaped in JSON, may cause unexpected result. Check it first if you really need to use these symbols.


"variables" plugin

Motivation

This plugin defines variables that are not bound to certain pages. Actually such values may be included directly into the template with no need of using this plugin. But when the same template is used by several projects it may be convenient to define some template variable parts that different projects may substitute using their argument files.

Definition

"variables": {"logo": "<img src=\"logo.png\" />" }

Usage

Tag (or tags) {{{logo}}} in the template will be substituted in the template. (Note that in this case three pairs of curly braces are used to avoid HTML-escaping on substitution.)


"index" plugin

Motivation

Some terms, abbreviations and other kind of keywords may be defined, described and mentioned in different pages within the documentation. Searching such keywords may be hard, especially if the documentation is large. This plugin allows marking such points on the pages as index entries and then collects these entries and put them together on a separate index page. See the index page of this documentation as an example.

Definition

"plugins": {
    "index": {"index": {"output": "index_page.html", "title": "Index", "index-cache": "index_cache.json", 
                        "index-cache-relative": true, "letters": true, "letters-block": true }
            }
}

This example defines one index with marker index. It's possible to define several indexes with different markers.

All possible properties are listed in the table below. They are mostly the same as those of the documents section so see that section for the absent descriptions.

Name Type Required Default Description
output-root string No
output string Yes Index page that must be created: absolute or relative to the output-root property value
title string No
template string No
link-css array of string No
include-css array of string No
no-css boolean No
add-link-css array of string No
add-include-css array of string No
page-flows array of string No
add-page-flows array of string No
verbose boolean No
report boolean No
index-cache string Yes Index cache file (see the note below)
index-cache-relative boolean No false true means that the index cache file location is defined relative to the index page location
letters boolean No false true means that the index page content will be divided by the terms first letters
letters-block boolean No false true means that all terms first letters will be listed at the top of the index page

Index cache file

Index page is generated using the entries from all the documents but the program may regenerate the documentation project partially, i.e. it may regenerate only those documents that were changed or added since the previous program run. In order to always generate a complete index page the program uses an index cache file that keeps the collected index entries between the runs.

In some cases a forceful full regeneration (with -f flag or "force": true option, see here for more details) is required, for example, if the "index" plugin is activated on an existing project or if the index cache file is deleted.

Index cache file is a generated artifact so in case of any problem it may be manually deleted and the further forceful full documents regeneration may resolve the problem.

Usage

Index entries may be added in two different ways:

The index marker is case-insensitive. If the above two entries are added then the index page will be generated with terms "term 1", "Term 2" and "term 3" in the sorted order.

In the index page, the term list will be included into a <div class="index-content"> element. The term first letter delimiters will look like this:

<p class="index-letter" id="index_letter_A">A</p>

The terms themselves will look like this:

<p class="index-entry"><a href="usage.html#index_entry_1" title="Usage">argument file</a></p>

The first letter link block will look like this:

<p class="index_letters">
    <a href="#index_letter_A">A</a>
    <a href="#index_letter_C">C</a>
    .  .  .
</p>

The above information allows define desirable styling with CSS.


"page-links" plugin

Motivation

HTML pages inside documentation usually reference each other using links. A link specifies its target relative to the page where it's placed. When the target page is moved or renamed the link need to be modified accordingly, otherwise it won't work. And what's worse, all pages that reference the relocated page need to be found and modified. This plugin automatically calculates link target pages location thus eliminating the need of specifying them manually.

Definition

To make this plugin work the target document must have a code. Here is an example of an argument file that uses this plugin:

{
    "documents": [
        { "input": "page1.txt", "code": "p1" },
        { "input": "subdir/page2.txt", "code-from-variable": "code" }
    ],
    "plugins": {
        "page-variables": {},
        "page-links": { "markers": ["page"] }
    }
}

The first page has a code p1 specified in the document definition. The second page has a code (let's say p2) specified in the page metadata (see the "page-variables" plugin), variable code. If page metadata is used then "page-variables" plugin must be activated.

Marker page is defined in the "page-links" plugin. There may be several markers.

Usage

On the page page1.txt the following link to the page subdir/page2.txt may be added: [](<!--page p2-->#some_anchor) and the plugin will convert it to [](subdir/page2.html#some_anchor). Consequently link [](<!--page p1-->) on the second page will become [](../page1.html).

Attention

  1. If a page is moved or renamed, some other pages may need to be regenerated to reflected this change. But those pages may be up-to-date, so a forceful full regeneration may be required (with -f flag or "force": true option, see here for more details).
  2. Changing a page's code will invalidate all links that reference this page by its code.

"ignore" plugin

Motivation

Different plugins fulfill page metadata substitution. But sometimes it's required to show a metadata block without substitutions. To achieve that, there are methods that use direct HTML inclusions and masking, but they are quite tedious and cumbersome. This plugin gives an easy way of doing that.

Definition

Here is an example of an argument file that uses this plugin:

{
    "documents": [
        { "input": "page1.txt" }
    ],
    "plugins": {
        "ignore": { "markers": ["ignore"] }
    }
}

The example shows the default marker usage, so the other, and recommended, way is the following definition: "ignore": { }. There may be several markers if required.

Usage

Let's consider two different code blocks:

![](../../pict/logo.png)

and

![](<!--path pict-->logo.png)

In the first block the source text is ![](<!--path pict-->logo.png) and substitution is fulfilled, while in the second block the source text is ![](<!--ignore path pict-->logo.png) so substitution is omitted.


"wrap-code" plugin

Motivation

Pages may contain links to source code files like Java (*.java), Python (*.py), XML (*.xml), and so on. When viewing such pages locally (as HTML files) the linked files are often opened by browsers as text. When the page is published and is viewed by URL, the browsers will often offer downloading the linked files that's very inconvenient and significantly slows down the documentation usage.

The "wrap-code" plugin wraps source code files into HTML pages and provides links to these wrapping pages.

Definition

The plugin definition may look like this:

    "plugins": {
        . . .
        "wrap-code": {
            "wrap_java": {"style": "code", "input-root": "projects/", "output-root": "doc/code",
                "template": "doc_src/templates/code.html", "variables": {"noPageTitle": true}},
            "wrap_xml": {"style": "xml", "input-root": "projects/", "output-root": "doc/code",
                "template": "doc_src/templates/code.html", "variables": {"noPageTitle": true}}
        }
        . . .
    }

In this example wrap_java and wrap_xml are markers to be used in the placeholders (see below). The markers define the wrapping HTML page generation options: where to take the source code files, where to place the wrapping HTML pages, which rendering style and template to use.

Note

The style parameter may be defined directly per each page metadata, see below. So just one wrap-code definition may be used and customized directly in place.

All possible properties are listed in the table below. They are mostly the same as those of the documents section so see that section for the absent descriptions.

Name Type Required Default Description
input-root string No
output-root string No
template string No
link-css array of string No
include-css array of string No
no-css boolean No
add-link-css array of string No
add-include-css array of string No
verbose boolean No
report boolean No
style string No empty string style, like code, shell, etc.
variables object No empty additional variables to be used in the template

Usage

Let's say there's the file projects/hello/Main.java with some content. To link this file in a source text, use something like this:

The main class is [here](<!--wrap_java hello/Main.java-->).

The alternative form is:

The main class is [here](<!--wrap_java {"file": "hello/Main.java", "style": "code"}-->).

As the result, the new file doc/code/hello/Main.java.html will be generated based on the following transformed content:

````code
<the file content here>
````

The source text will be transformed like this:

The main class is [here](../code/hello/Main.java.html).

An example may be viewed here. Also see the argument file md2html_args.json in this project.

The following additional variables may be used in the template:

Variable Description
{{wrap_code_path}} Path to the wrapped file
{{wrap_code_file_name}} The wrapped file name

Note

The wrapping HTML file will be generated (or regenerated) only if the source text is processed. To assure regeneration, use -f flag or "force": true option (see here for more details).


"include-file" plugin

Motivation

When writing and running program code, it may be desired to place some source code into the documentation. Just copy-pasting will require updating documentation each time the source code is changed. "wrap-code" plugin may help by generating a separate page for this code. But if the source text is small it may be better to show it directly in the text where it's described. This plugin does such kind of inclusion.

Definition

The plugin is defined the following way:

    "plugins": {
        . . .
        "include-file": [
            { "markers": ["include_code"], "root-dir": "sample_code/", "trim": "all" },
            { "markers": ["include_text1", "include_text2"], "root-dir": "sample_text/",
                "recursive": true, "start-with": "<body>", "end-with": "</body>",
                "start-marker": "// INCLUDE FROM HERE", "end-marker": "// INCLUDE UP TO HERE" }
        ],
        . . .
    }

In this example:

Usage

By adding the following content on the page:

````code
<!--include_code_part hello/Main.java-->
````

we will get the following output:

public class Main {
    // method start
    public static void main(String[] args) {
        System.out.println("Hi!");
    }
    // method end
}

For a certain file, custom parameters may be defined the following way:

````code
<!--include_code_part {"file": "hello/Main.java", "start-marker": "// method start",
"end-marker": "// method end", "trim": "empty-lines"}-->
````

The result will look like this:

    public static void main(String[] args) {
        System.out.println("Hi!");
    }

"replace" plugin

Motivation

This plugin makes replacements by template. It may be helpful for contracting long and recurring fragments. Probably, long and cumbersome HTML inclusions are the first fragments that may be addressed by this plugin.

Important

This plugin must be used with care. When used too much, it may become a replacement for the Markdown syntax, and that, in its turn, may significantly reduce the documents readability and compatibility in source text.

Definition

The plugin is defined the following way:

    "plugins": {
        . . .
        "replace": [
            { "markers": ["red"], "replace-with": "<span style=\"color:red;\">${1}</span>" },
            { "markers": ["blue"], "replace-with": "<span style=\"color:blue;\">${1}</span>" },
            { "markers": ["pict"], "replace-with": "![](<!--path pict-->${1})", "recursive": true }
        ],
        . . .
    }

In this example:

Usage

The content may be added the following ways:

The output will be the same in both cases:

<span style="color:red;">some text </span>

This result may look like this: some text .

If there are not enough values provided for the template, the missing positions will be replaced with empty strings.

 


Back Next