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 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.
Precompiled binaries are provided for major platforms on a best-effort basis. Visit the releases page to download the appropriate version for your platform.
mdPage can also be installed from source.
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.
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!
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.
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 .
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.
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>
elementintegrity
- the integrity
tag to be applied for SRIcrossorigin
- the crossorigin
tag to be applied for SRIThe 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.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.
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.
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.
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.
Custom JavaScript can be added within the script
config property.
{
"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
All examples can be viewed on GitHub.
No custom configuration.
Structure:
./docs/examples/basic
├── page1.md
├── page2.md
└── readme.md
Command:
$ mdpage ./docs/examples/basic
No custom configuration. Demonstrates how different directories are automatically treated as different sections of content.
Structure:
./docs/examples/sections
├── index.md
├── guide
│ ├── install.md
│ └── readme.md
└── reference
├── api.md
└── config.md
Command:
$ mdpage ./docs/examples/sections
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"
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.
Structure:
./docs/examples/config
├── mdpage.json
├── page1.md
└── readme.md
Command:
$ mdpage ./docs/examples/config
Single page examples.
Config using dir
content property to specify sections.
./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"
}
]
}
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!