mdPage

Simple documentation tool

GITHUB


mdpage

Build Status LICENSE Donate Buy me a coffee

mdPage is a minimal, opinionated, command line utility (and Rust crate) for creating single-page HTML documentation from markdown files. At it's simplest basic form of usage, it takes no input and should generate practical documentation from all markdown files in a folder.

Indeed this very documentation is generated using mdpage tool with some minor configuration and serves as an example of generated output.

The basic goal is simply to generate a self-contained single page HTML file for all documentation in a folder (and immediate subdirectories). The tool has some opinions on structure and patterns used, and has limited configuration and customization options. It purposefully lacks in features, to let you focus on creating the content and not waste time on style or format of the output.

mdpage

Build Status LICENSE Donate Buy me a coffee

mdPage is a minimal, opinionated, command line utility (and Rust crate) for creating single-page HTML documentation from markdown files. At it's simplest basic form of usage, it takes no input and should generate practical documentation from all markdown files in a folder.

Indeed this very documentation is generated using mdpage tool with some minor configuration and serves as an example of generated output.

The basic goal is simply to generate a self-contained single page HTML file for all documentation in a folder (and immediate subdirectories). The tool has some opinions on structure and patterns used, and has limited configuration and customization options. It purposefully lacks in features, to let you focus on creating the content and not waste time on style or format of the output.

Installation


Install from binaries

Precompiled binaries are provided for major platforms on a best-effort basis. Visit the releases page to download the appropriate version for your platform.


Install from source

mdPage can also be installed from source.

Pre-requisite

mdPage is written in Rust and therefore needs to be compiled with Cargo. If you haven't already installed Rust, please go ahead and install it now.

Install Crates.io version

Installing mdPage is relatively easy if you already have Rust and Cargo installed. You just have to type this snippet in your terminal:

cargo install mdpage

This will fetch the source code for the latest release from Crates.io and compile it. You will have to add Cargo's bin directory to your PATH.

Run mdpage --help in your terminal to verify if it works. Congratulations, you have installed mdPage!

Usage

mdpage tool takes a singe argument, the root path directory where all the content is located.

$ mdpage --help
mdpage 0.1.1
Generate simple documentation

USAGE:
    mdpage [FLAGS] [OPTIONS] <path>

FLAGS:
        --full-page    Generate full page documentation
    -h, --help         Prints help information
    -V, --version      Prints version information

OPTIONS:
    -o, --output <output>        The output file
        --subtitle <subtitle>    Subtitle of the document
        --title <title>          Title of the document

ARGS:
    <path>    Path for the directory containing data

The result of running the tool is always an index.html file.

Example workflow:

$ ls ./examples/basic | sort
page1.md
page2.md
readme.md

$ mdpage ./examples/basic

$ ls ./examples/basic | sort
index.html
page1.md
page2.md
readme.md

This is exacly how the basic was generated!

The title of the generated documents is automatically inferred from the readme.md (or index.md) document's heading, or, if not possible, from the directory name. Similarly the page links in the menu are inferred from the file headings, or, if not possible, from the file name.

mdPage expects all contents to be in the immediate directory as root of the content and immediate subdirectories. It makes certain assumptions about structure and meaning. The content in subdirectories is separated out and used as different "sections" in the menu. Similar to the rules stated above, the section title is inferred from heading readme.md (or index.md) or, if not possible, from the directory name.

Take a look at the sections example for an idea of how that works and what the result looks like.

We can customize some things via command line options such as title, subtitle, and whether to generate a single full page document (no JavaScript "pagination").

$ mdpage ./docs/examples/full_page --full-page --title "Full Page" --subtitle "Full page example"

See the resulting full page example.

All of this and more can be controlled via a configuration file, but the basic idea is that the tool in most cases should just work.


Debug logging

mdPage uses env_logger crate, which can be used to enable logging.

RUST_LOG=info mdpage .

or for debug level logging:

RUST_LOG=debug mdpage .

Configuration

Configs must be located in the root folder, and named either mdpage.json or mdpage.toml. mdpage.json takes precedence.

Other than top-level strings in the config, there are two main object types part of the configuration. There are "Link" objects used in the "links" property to specify script or style links. There are also "Content" objects which are used to specify the main page, header, footer, and the different contents and menu items.

Link

Links have the following properties:

  • link_type - has to be either "script" for a script link; or "style" or "stylesheet" to specify a stylesheet link.
  • src - the URL to be applied to the <link> element
  • integrity - the integrity tag to be applied for SRI
  • crossorigin - the crossorigin tag to be applied for SRI

Content

The content object has the following properties:

  • is_heading - A boolean flag to specify that the object is a heading in the menu. In this case it must have "label" specified to be displayed in the menu.
  • is_break - A boolean flag to specify a line break in the menu.
  • label - The string to be used as label for the content in the menu.
  • url - The URL for an external link. If specified the menu will be a link to this URL.
  • markdown - The optional raw markdown to be converted into HTML for the content. Usually this would be read from a file.
  • html - The raw markdown to be converted into HTML for the content. This is generated by converting the markdown contents.
  • file - The markdown or HTML file used for the content. We read this into markdown property and convert it to HTML content to be displayed. If label is not specified, we also infer the title for the content from the heading in markdown content.
  • dir - As an alternative to file we can specify the directory path used to build contents. The content will be sourced from all the files and immediate subdirectories in the path.

Main

The main config property is the main content. We automatically infer this from readme.md or index.md in the root folder, but it can be customized.

Header

The header config property is the custom header content to be displayed at the top of the page. We automatically build this based on "title" (which we infer from main file or root directory) and "subtitle". If root folder has header.md that is automatically used as header property of the config if one is not specified. The header can be customized using header property to center content or add logos or custom buttons.

Footer

The footer config property is the custom footer content to be displayed at the top of the page. If root folder has footer.md that is automatically used as footer property of the config if one is not specified. The footer can be customized using footer property to center content or add logos or custom buttons.

Style

Custom styles can be added within the style property. We use a forked / customized version of Milligram so all the same classes are available in markdown and HTML content.

Script

Custom JavaScript can be added within the script config property.

Examples

{
    "label": "Reference",
    "is_heading: true
}

This will create a "REFERENCE" heading in the menu to separate a section of menu items.

{
    "file": "guide.md"
}

And guide.md starts with # User's Guide markdown content. This will create a menu item with label "User's Guide" and the content for that menu item will be the converted content of the file. We can customize the label using label property:

{
    "label": "Guide",
    "file": "guide.md"
}

We can also explicitely use HTML files, which will be included in the result:

{
    "label": "HTML content",
    "file": "page.html"
}

A custom header can be created with custom logo using something like this in `header.md`:

```markdown
<center>
<a href="/">
<img src="static/logo.png" width="96" height="96">

<br>
<br>

# My Project

##### Some title
</a>

<a class="button button-outline" href="https://github.com/my/link">GITHUB</a>
</center>

Example config with descriptions.

full_page = false       # whether to do full page or not
title = "My Document"   # title used in header and title of the document
subtitle = "Something"  # subtitle used in header
author = "Joe Smith"    # author used in metadata
icon = "favicon.ico"    # favicon link

# We can add several links to be used in the head of the document
# This can be used to add extra scripts or styles, such as highlight.js
# Script properties can have SRI fields for "integrity" and "crossorigin"
[[links]]
link_type = "script"    # link_type has to be either "script" or "style" or "stylesheet"
src = "https://cdnjs.example.com/highlight.min.js"
integrity = "sha256-1zu+3BnLYV9LdiY85uXMzii="
crossorigin = "anonymous"

[[links]]
link_type = "script"
src = "https://cdnjs.example.com/json.min.js"

[[links]]
link_type = "style"
src = "https://cdnjs.example.com/styles/github.min.css"

# We can specify a script to be run when document is loaded
script = "(function () { hljs.initHighlightingOnLoad(); })()"

# We can specify custom style which will be applied as well
style = "body { color: #222222; }"

# This is the main page. 
# We automatically look for index.md or readme.md
[main]
file = "main.md"

# Footer
# Content can have markdown directly which we convert to HTML
[footer]
markdown = "<center>### My footer</center>"

# These are the contents. The order determines the order of menu items.

# This is a heading of a section in the menu
[[contents]]
label = "Heading"
is_heading = true

[[contents]]
label = "Home"      # Custom label otherwise we infer it from file contents
file = "index.md"

[[contents]]
file = "install.md"

# We can have raw markdown
[[contents]]
label = "Raw Markdown"  
markdown = """
## Raw content\n\n \
We can specify markdown content like this.\
"""

# We can have raw HTML
[[contents]]
label = "Raw HTML"
html = """
<h1>Some HTML Content</h1> \
<h4>Some content.</h4> \
<img src=\"http://placekitten.com/200/200\"> \
<br><br> \
<p>This is paragraph of raw HTML content.</p>\
"""

# This will add a line break in the menu so we can start another section
[[contents]]
is_break = true

[[contents]]
label = "Links"
is_heading = true

[[contents]]
label = "External Link"
url = "https://github.com"      # An external link

Examples

All examples can be viewed on GitHub.

Basic

Basic example

No custom configuration.

Structure:

./docs/examples/basic
├── page1.md
├── page2.md
└── readme.md

Command:

$ mdpage ./docs/examples/basic

Sections

No custom configuration. Demonstrates how different directories are automatically treated as different sections of content.

Sections example

Structure:

./docs/examples/sections
├── index.md
├── guide
│  ├── install.md
│  └── readme.md
└── reference
   ├── api.md
   └── config.md

Command:

$ mdpage ./docs/examples/sections

Full page

Full page example

Using command line to specify custom title, subtitle, and full page options. Automatically injects footer because we have footer.md.

Structure:

./docs/examples/full_page
├── index.md
├── code.md
├── footer.md
├── guide
│  ├── install.md
│  └── readme.md
└── reference
   ├── api.md
   └── config.md

Command:

$ mdpage ./docs/examples/full_page --full-page --title "Full Page" --subtitle "Full page example"

Config

Customized build using mdpage.json file. Specifies script and style links to add highlight.js support. Specifies content to control order of menu items and sections, and to add external links.

Config example

Structure:

./docs/examples/config
├── mdpage.json
├── page1.md
└── readme.md

Command:

$ mdpage ./docs/examples/config

Single page

Single page examples.

Just index

Single Page

Dir config

Config using dir content property to specify sections.

Dir example

./docs/examples/config_dir
├── index.md
└── mdpage.json

mdpage.json"

{
    "subtitle": "Dir config example",
    "contents": [
        {
            "dir": "../sections"
        },
        {
            "file": "../config/page1.md"
        },
        {
            "dir": "../basic"
        },
        {
            "file": "../single_index/readme.md"
        },
        {
            "dir": "../single_page"
        }
    ]
}

mdPage

This documentation is created using mdPage using a header and footer, and a config file to customize content.

Structure:

./docs
├── config.md
├── examples.md
├── footer.md
├── header.md
├── index.html
├── index.md
├── install.md
├── usage.md
├── TODO.md
├── mdpage.toml
├── static
│  ├── logo-192x192.png
│  └── favicon.ico
├── examples
   ├── basic
   ├── config
   ├── full_page
   └── sections

Command:

$ mdpage ./docs

The markdown content in examples subdirectories is automatically ignored since it's too deep. mdpage only looks at content in immediate subdirectories.


❤️

Say Thanks!