#markdown #md #web #ssg


Custom Markdown Engine for my personal blog

20 releases

Uses new Rust 2021

0.4.13 Apr 14, 2022
0.4.12 Apr 4, 2022
0.4.11 Mar 28, 2022
0.4.0 Feb 25, 2022
0.2.1 Feb 24, 2022

#2 in #ssg

Download history 82/week @ 2022-06-08 1/week @ 2022-06-15 43/week @ 2022-06-22 3/week @ 2022-06-29 40/week @ 2022-07-06 40/week @ 2022-07-13 41/week @ 2022-07-20 28/week @ 2022-07-27 60/week @ 2022-08-03 1/week @ 2022-08-17 39/week @ 2022-08-24 60/week @ 2022-09-07 5/week @ 2022-09-21

65 downloads per month

MIT license

2.5K SLoC

H Markdown Engine

This is a markdown engine developed for my personal blog. The syntax is dialect of gfm, but not subset or superset of it.

If you're reading this document on github, some elements are not rendered properly. Please visit my blog to see the correct version.

This document is mainly focused on its markdown syntax. If you want to use this engine for your blog, read the crate's document.


Things that are similar to gfm

Don't try edge cases! There must be tons of glitches.

Things that are missing


Code blocks

Not at all.


  • Inserting html tags is not supported, at all!
  • If you want to type <, >, or &, just type as it is.
  • <details> tag is not supported, but it'll be added soon.
  • HTML comment <!-- --> does not work here.
    • If you want to use HTML comment tricks to divide a list, use an empty line instead.

Things that are different


Table rows and delimiter rows resemble that of gfm's table, but a bit more strict. Each cell must be enclosed by two pipes (|), including the first and the last cell. You can set its alignment using colons.

Left aligned Column Centered Column Right aligned Column
Left Center Right
Left Center Right
Left Center Right
Left Center Right
Left Center Right

Code spans

It has limited range of syntax.

  • Inline code spans use single backtick character. Multiple backtick characters're not treated as code spans.
  • If you want backticks inside a code span, that's impossible.

Fenced code blocks

  • Use backticks for delimiter, not tildes.
  • A code fence should not be indented.
  • If the first line of the fenced code is indented N spaces, then up to N spaces of indentation are removed from each line of the content (If present). (If a content line is not indented, it is preserved unchanged. If it is indented less than N spaces, all of the indentation is removed.)
  • A line beginning with 3 or more backticks is counted as a fence.
    • Two fences with a different number of backticks can enclose a fenced code block.
  • The engine uses syntect crate for syntax highlighting.
  • You can enable line-numbering with line_num(n) option. The number n designates the first index.
    ```rust, line_num(0)
    fn main() {
        println!("Hello World!");

    fn add_one(n: i32) -> bool {
        n + 1
fn main() {
    println!("Hello World!");

fn add_one(n: i32) -> bool {
    n + 1


  • This engine only uses * for emphasis, not _.
    • One for italic and two for bold.


  • 1., i., I., a., and A. are the only valid bullets for ordered lists.
    • Which means you cannot set its starting number.
  • There must be a space between the bullet and its content.

Things that are added

Some of these extensions are from pandoc's markdown spec. The others are my custom extensions.


~_Underlines_~ is rendered to Underlines. Underlines may not contain any newline. The first and the last character may not be space.


H~2~O is rendered to H2O. Subscripts may not contain any space or newline.


E=mc^2^ is rendered to E=mc^2^. Superscripts may not contain any space or newline.

Extra tags

HMD has wide variety of tags. It uses double square brackets instead of HTML's angle brackets. All the spaces inside the brackets are ignored.

Some tags have to be properly closed, or it would ruin the rendered html file! The engine does not check whether a tag is closed, so you have to take care of that. Also, be careful not to mix extra tags with other html tags. Most extra tags generate <div> or <span> tags when rendered. Those rendered tags can be mixed with auto-generated <p> tags. To prevent that you should either

  • Open and close a tag within a paragraph.
  • Don't use a tag as an inline element.

If you do something like below,

[[box]] A paragraph

Another paragraph [[/box]]

the result would be like below.

<p><div class="box">A paragraph</p>
<p>Another paragraph</div></p>

It would look fine on most browsers, but not desirable though.


[[box]][[/box]] is rendered to <div class="box"></div>. It draws a box. You can put (almost) everything inside a box. You can even nest boxes!


[[center]][[big]]A box.[[/big]][[/center]]

A table inside a box.
[[box]] A box inside a table inside a box. [[/box]]
But you cannot have a table inside a box inside a table inside a box.
Because you cannot put a table in another table.


Font size

[[big]][[/big]] is rendered to <span class="size_big"></span>.

HMD code Rendered result
[[small]]Small font[[/small]] [[small]]Small font[[/small]]
[[medium]]Medium font[[/medium]] [[medium]]Medium font[[/medium]]
[[big]]Big font[[/big]] [[big]]Big font[[/big]]
[[giant]]Giant font[[/giant]] [[giant]]Giant font[[/giant]]
[[Big]]It's case insensitive![[/Big]] [[Big]]It's case insensitive![[/Big]]

Font color

[[red]][[/red]] is rendered to <span class="color_red"></span>.

HMD code Rendered result
[[red]]rgb(192, 32, 32)[[/red]] [[red]]rgb(192, 32, 32)[[/red]]
[[orange]]rgb(255, 165, 0)[[/orange]] [[orange]]rgb(255, 165, 0)[[/orange]]
[[aqua]]rgb(64, 192, 192)[[/aqua]] [[aqua]]rgb(64, 192, 192)[[/aqua]]
[[green]]rgb(32, 192, 32)[[/green]] [[green]]rgb(32, 192, 32)[[/green]]
[[blue]]rgb(32, 128, 255)[[/blue]] [[blue]]rgb(32, 128, 255)[[/blue]]
[[lime]]rgb(0, 255, 0)[[/lime]] [[lime]]rgb(0, 255, 0)[[/lime]]
[[yellow]]rgb(192, 192, 32)[[/yellow]] [[yellow]]rgb(192, 192, 32)[[/yellow]]
[[violet]]rgb(187, 134, 252)[[/violet]] [[violet]]rgb(187, 134, 252)[[/violet]]
[[white]]rgb(255, 255, 255)[[/white]] [[white]]rgb(255, 255, 255)[[/white]]

Not only fonts!

  • [[red]][[icon=alert, size=42]][[icon=github, size=42]][[/red]]


[[center]], [[left]], [[right]] tags align (almost) everything. They're rendered to <div> tag. So, don't forget to close them.


A centered text,

[[/center]] [[right]]

[[box]] and a right aligned box.[[/box]]



[[icon=rust, size=128]]

You can insert icons with [[icon]] tag. The documentation can be found here.


[[blank]] is rendered to &nbsp;.


Every single character in UTF-8 charset can be rendered with a [[char]] tag. [[char=9650]] is rendered to &#9650;, which is [[char=9650]]. It only supports decimal representation, though. Older browsers may not support some characters.

Table of contents

[[toc]] makes a table of content of the whole article. You cannot inline this tag!


[[math]] x=frac{-b pm sqrt{b sup{2}-4ac}}{2a} [[/math]] is rendered to

[[center]] [[big]]

[[math]] x=frac{-b pm sqrt{b sup{2}-4ac}}{2a} [[/math]]

[[/big]] [[/center]]

For formulas to be rendered, <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> should be included in the rendered HTML file. The script is not supported on IE. For IE, you should include <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>.


~71K SLoC