MD4C (Markdown for C)
repository·master·Indexed 23 days ago
https://github.com/mity/md4cA high-performance, compact, and embeddable Markdown parser written in C, primarily compliant with the CommonMark specification. It utilizes a callback-based 'push model' to render Markdown into various formats without the overhead of an Abstract Syntax Tree (AST). The library includes a dedicated HTML renderer via md4c-html.h and supports numerous extensions such as GitHub-style tables, task lists, footnotes, and LaTeX math spans.
What's inside MD4C
- MD4C (
Compare MD4C with other Markdown parsers
masterWhen choosing a Markdown parser, consider these key differences regarding MD4C:
- Decoupled Parsing and Generation: Unlike many implementations that entangle the parser and HTML generator, MD4C allows you to process input in ways other than just HTML conversion.
- No AST Overhead: Most C/C++ parsers are full DOM-like parsers that construct an Abstract Syntax Tree (AST). MD4C avoids this, resulting in significantly faster performance and a lower memory footprint if you do not explicitly need an AST.
- Linear Parsing Time: MD4C is designed to provide linear or near-linear parsing times even with complex or 'pathological' input patterns. This helps prevent Denial-of-Service (DoS) attacks that target naive parsers with quadratic or worse complexity.
- Input Handling: MD4C follows a 'Garbage In, Garbage Out' (GIGO) philosophy. It does not perform input validation (e.g., checking for well-formed UTF-8). It treats any sequence of bytes as valid input, propagating ill-formed sequences directly to callbacks.
Handle input strings in MD4C
masterMD4C does not work with zero-terminated strings (C-style strings).
Why?
- Correctness: Markdown documents can legally contain the
U+0000character (a zero byte in UTF-8). Using zero-terminated strings would cause the parser to prematurely stop. - Performance: To support zero-terminated strings, the parser would have to copy every text chunk into a temporary buffer to add a null terminator. To avoid this overhead, MD4C passes a pointer directly into the input document along with the length of the text segment to the callback.
Action: When implementing callbacks, always use the provided length parameter rather than relying on a null terminator.
- Correctness: Markdown documents can legally contain the
How to convert Markdown to HTML
masterTo convert Markdown directly to HTML, include
md4c-html.hand link against the MD4C-HTML library (-lmd4c-html). If embedding manually, includemd4c.[hc],md4c-html.[hc], andentity.[hc].Use the
md_html()function, which takes the Markdown input and a callback function. The callback is triggered with chunks of the generated HTML output, which you can then append to a buffer or write to a file.How to use MD4C for parsing Markdown
masterTo use MD4C as a pure parser, include
md4c.hand link against the MD4C library (-lmd4c). Alternatively, you can embed the parser directly by addingmd4c.[hc]to your codebase.The core function is
md_parse(). It uses a push model: as it processes the input, it calls a series of callback functions provided by your application to notify you about the start/end of blocks and spans, and to output textual content. This allows you to convert the Markdown into any custom format or render it directly.Configure Input/Output Encoding
masterMD4C is largely encoding-agnostic and assumes the encoding is compatible with ASCII. However, for Unicode-specific tasks like word boundary detection and link reference matching, you must define a preprocessor macro during the build process:
MD4C_USE_UTF8(Default): Assumes UTF-8 encoding. This is the standard behavior if no macro is specified.MD4C_USE_UTF16(Windows): UsesWCHARinstead ofcharand assumes UTF-16 encoding. Note: You must define this macro both when building MD4C and when includingmd4c.hin your application. This is only supported in the parser; the HTML renderer does not support UTF-16.MD4C_USE_ASCII: Assumes ASCII-only input. Non-ASCII whitespace/punctuation will not be recognized, and link reference matching will only work for[a-zA-Z].
Find MD4C bindings and ports
masterIf you are not using C or C++, you can use the following bindings and ports:
Bindings
Ports
- D Language: commonmark-d
- WebAssembly: markdown-wasm
- C#: Included in Microsoft.UI.Reactor
Configure Markdown extensions with flags
masterBy default, MD4C follows the CommonMark specification. You can enable various extensions by passing specific flags to the parsing functions.
Supported Extensions
MD_FLAG_COLLAPSEWHITESPACE: Collapses non-trivial whitespace into a single space.MD_FLAG_TABLES: Enables GitHub-style tables.MD_FLAG_TASKLISTS: Enables GitHub-style task lists.MD_FLAG_FOOTNOTES: Enables footnote references and definitions.MD_FLAG_STRIKETHROUGH: Enables strike-through spans (e.g.,~foo bar~).MD_FLAG_SPOILERS: Enables spoiler spans (e.g.,||hidden text||). The HTML renderer uses a custom<x-spoiler>tag.MD_FLAG_SUPERSCRIPTS: Enables superscript spans (e.g.,x^2^). The HTML renderer uses<sup>.MD_FLAG_SUBSCRIPTS: Enables subscript spans (e.g.,H~2~O). The HTML renderer uses<sub>.MD_FLAG_HIGHLIGHT: Enables highlight spans (e.g.,==important==). The HTML renderer uses<mark>.MD_FLAG_PERMISSIVEURLAUTOLINKS: Supports permissive URL autolinks.MD_FLAG_PERMISSIVEEMAILAUTOLINKS: Supports permissive e-mail autolinks.MD_FLAG_PERMISSIVEWWWAUTOLINKS: Supports permissive WWW autolinks (assumeshttp:scheme).MD_FLAG_LATEXMATHSPANS: Supports LaTeX math spans ($...$and$$...$$). The HTML renderer uses a custom<x-equation>tag.MD_FLAG_WIKILINKS: Supports wiki-style links ([[link label]]). The HTML renderer uses a custom<x-wikilink>tag.MD_FLAG_UNDERLINE: Uses underscore (_) for underlining instead of emphasis.MD_FLAG_ADMONITIONS: Recognizes GitHub-style admonitions.
Disabling Features
MD_FLAG_NOHTMLSPANS: Disables raw inline HTML.MD_FLAG_NOHTMLBLOCKS: Disables raw HTML blocks.MD_FLAG_NOINDENTEDCODEBLOCKS: Disables indented code blocks.