Module serial::markdown
Markdown.
Unlike json.h/xml.h/html.h, Markdown doesn't map onto the generic Value tree (std/serial/value.h) — it's document markup (headings, paragraphs, lists, emphasis), not key/value data — so this is its own AST, parsed from CommonMark (plus opt-in GitHub-flavored and documentation-site extensions) and rendered to HTML or back to Markdown.
Blocks: ATX and setext headings, paragraphs, thematic breaks, block quotes, bullet and ordered lists (nested, tight or loose, items holding any blocks), fenced code (``` / ~~~, with an info string) and indented code. Inlines: emphasis and strong emphasis with CommonMark's delimiter rules (no intraword '_'), code spans, backslash escapes, entity and numeric character references, links and images (inline form, with titles; link text holds any inlines), scheme:... and <email> autolinks, hard line breaks. Not supported: reference-style links ('[x][ref]' / '[ref]: url') and footnotes.
Opt-in through MdOptions (MdNode::parse_opts):
tables GFM tables, with column alignment ('| a | b |' + '|:--|--:|')
html raw HTML blocks and inline tags pass through unescaped
(off by default: untrusted input stays inert)
containers '::: kind [title]' ... ':::' blocks (tip, warning,
details, ... — any word), nestable
heading_ids '## Title {#custom-id}', and an id for every other
heading from md_slugify (deduplicated with -1, -2, ...)
strikethrough '~~text~~'
autolinks bare 'https://...', 'http://...' and 'www....' URLs
MdOptions::commonmark() turns all of them off (what MdNode::parse uses); MdOptions::gfm() turns on tables, strikethrough and autolinks.
struct MdOptions o = MdOptions::gfm();
o.html = 1; o.containers = 1; o.heading_ids = 1;
&heap MdNode doc = MdNode::parse_opts(text, &o);
struct String html = doc.render_html();
doc.free();
md_render_html_with renders with a hook that can replace or wrap any node's HTML (rewrite link targets, add heading anchors, highlight code).
Structs
| MdOptions | |
| MdNode |
Functions
| md_slugify | Appends the GitHub/VitePress-style slug of 'text' to 'out': lower-cased; every run of whitespace, ASCII punctuation and control characters becomes one '-'; no leading/trailing '-'; a leading digit gets a '_' prefix. Non-ASCII characters are kept. |
| md_render_html_with |
Macros
| MD_DOC | |
| MD_HEADING | level 1-6; id (with heading_ids) |
| MD_PARAGRAPH | |
| MD_LIST | 'ordered' 1 = "1." / "1)", 0 = "-" "*" "+"; 'start'; 'tight' |
| MD_LIST_ITEM | |
| MD_CODE_BLOCK | 'text' = the code (ends with '\n'); 'info' = the fence's info string |
| MD_BLOCKQUOTE | |
| MD_HR | |
| MD_TEXT | inline: plain text (in 'text', references decoded) |
| MD_BOLD | inline: has children |
| MD_ITALIC | inline: has children |
| MD_CODE_SPAN | inline: 'text' |
| MD_LINK | inline: children = link text; 'text' = URL; 'title' |
| MD_TABLE | children: rows (the first 'header' row is the thead) |
| MD_TABLE_ROW | children: cells; 'header' 1 for the header row |
| MD_TABLE_CELL | inline children; 'align' (MD_ALIGN_*); 'header' |
| MD_CONTAINER | 'info' = kind ("tip"); first child MD_CONTAINER_TITLE when a title was given |
| MD_HTML_BLOCK | 'text' = raw HTML (html option) |
| MD_HTML_INLINE | 'text' = raw HTML tag/comment (html option) |
| MD_IMAGE | inline: children = alt text; 'text' = src; 'title' |
| MD_STRIKE | inline: has children (strikethrough option) |
| MD_BREAK | inline: hard line break |
| MD_CONTAINER_TITLE | inline children: a container's title |
| MD_ALIGN_NONE | |
| MD_ALIGN_LEFT | |
| MD_ALIGN_CENTER | |
| MD_ALIGN_RIGHT |