Skip to content

pawamoy/mkdocs-manpage

Repository files navigation

MkDocs Manpage

ci documentation pypi version gitpod gitter

MkDocs plugin to generate a manpage from the documentation site.

Requirements

Pandoc must be installed and available as pandoc.

Installation

With pip:

pip install mkdocs-manpage[preprocess]

With pipx:

python3.8 -m pip install --user pipx
pipx install mkdocs-manpage[preprocess]

Usage

# mkdocs.yml
plugins:
- manpage:
    pages:
    - title: My Project  # defaults to site name
      output: share/man/man1/my-project.1
      inputs:
      - index.md
      - usage.md
    - title: my-project API
      header: Python Library APIs  # defaults to common header for section 3 (see `man man`)
      output: share/man/man3/my_project.3
      inputs:
      - reference/my_project/*.md

To enable/disable the plugin with an environment variable:

# mkdocs.yml
plugins:
- manpage:
    enabled: !ENV [MANPAGE, false]

Then set the environment variable and run MkDocs:

MANPAGE=true mkdocs build

Pre-processing HTML

This plugin works by concatenating the HTML from all selected pages into a single file that is then converted to a manual page using Pandoc.

With a complete conversion, the final manual page will not look so good. For example images and SVG will be rendered as long strings of data and/or URIs. So this plugin allows users to pre-process the HTML, to remove unwanted HTML elements before converting the whole thing to a manpage.

First, you must make sure to install the preprocess extra:

pip install mkdocs-manpage[preprocess]

To pre-process the HTML, we use BeautifulSoup. Users have to write their own preprocess function in order to modify the soup returned by BeautifulSoup:

from bs4 import BeautifulSoup, Tag


def to_remove(tag: Tag) -> bool:
    # remove images and SVGs
    if tag.name in {"img", "svg"}:
        return True
    # remove links containing images or SVGs
    if tag.name == "a" and tag.img and to_remove(tag.img):
        return True
    # remove permalinks
    if tag.name == "a" and "headerlink" in tag.get("class", ()):
        return True
    return False


def preprocess(soup: BeautifulSoup, output: str) -> None:
    for element in soup.find_all(to_remove):
        element.decompose()

Then, instruct the plugin to use this module and its preprocess function:

plugins:
- manpage:
    preprocess: scripts/preprocess.py

See the documentation of both [BeautifulSoup][bs4.BeautifulSoup] and [Tag][bs4.Tag] to know what methods are available to correctly select the elements to remove.

The alternative to HTML processing for improving the final manpage is disabling some options from other plugins/extensions:

  • no source code through mkdocstrings:

    - mkdocstrings:
        handlers:
          python:
            options:
              show_source: !ENV [SHOW_SOURCE, true]
  • no permalink through toc:

    markdown_extensions:
    - toc:
        permalink: !ENV [PERMALINK, true]

Then set these environment variables before building the documentation and generating the manpage:

export MANPAGE=true
export PERMALINK=false
export SHOW_SOURCE=false
mkdocs build