markdown_to_html()

Parse CommonMark/GFM and render as HTML.

Usage

Source

markdown_to_html(
    text,
    *,
    hardbreaks=False,
    smart=False,
    normalize=False,
    sourcepos=False,
    unsafe=False,
    footnotes=False,
    extensions=(),
    options=0
)

Takes a Markdown string and returns the corresponding HTML output. By default, raw HTML embedded in the Markdown is stripped for security (replaced with an HTML comment). Set unsafe=True to allow raw HTML passthrough.

The parser is fully CommonMark spec compliant. When GFM extensions are enabled via extensions=, additional syntax is recognized (tables, strikethrough, autolinks, tag filtering, and task lists).

Parameters

text: str

The Markdown string to parse and render. Can be any length, from a single inline fragment to a full document. Must be a Python str (not bytes).

hardbreaks: bool = False

Render soft line breaks (single newlines within a paragraph) as <br /> tags. By default, this is False and soft breaks are rendered as spaces, matching the CommonMark specification behavior.

smart: bool = False

Convert straight quotes to curly quotes, -- to en-dashes, --- to em-dashes, and ... to ellipses. By default, this is False.

normalize: bool = False

Consolidate adjacent text nodes in the parsed AST before rendering. This can produce slightly cleaner output in edge cases. By default, this is False.

sourcepos: bool = False

Include data-sourcepos attributes on block-level HTML elements indicating their line/column positions in the original Markdown source. Useful for building editors or source-mapping tools. By default, this is False.

unsafe: bool = False

Allow raw HTML and potentially dangerous links to pass through to the output without sanitization. When False (the default), raw HTML blocks and inline HTML are replaced with a comment <!-- raw HTML omitted -->, and dangerous URLs (e.g., javascript:) are suppressed.

footnotes: bool = False

Enable footnote syntax parsing. When True, [^label] markers and [^label]: content definitions are recognized and rendered as numbered footnotes with backlinks. By default, this is False.

extensions: Sequence[str] = ()

A sequence of GFM extension names to enable during parsing. Valid names are "table", "strikethrough", "autolink", "tagfilter", and "tasklist". An empty sequence (the default) parses standard CommonMark only.

options: int = 0
An integer bitmask of Options flags. Build it by OR-ing flags together, e.g., Options.SMART | Options.UNSAFE. This value is combined (via OR) with any named boolean parameters that are set to True, so you can mix both styles freely. Defaults to 0 (no additional flags beyond those set by keyword arguments).

Keyword Arguments Vs. Options Flags

The boolean keyword arguments (smart, unsafe, hardbreaks, etc.) are convenience shortcuts for the most common Options flags. Using smart=True is equivalent to passing options=Options.SMART. When both are provided, they are merged: markdown_to_html(text, smart=True, options=Options.UNSAFE) is the same as options=Options.SMART | Options.UNSAFE.

Some flags (like Options.GITHUB_PRE_LANG, Options.STRIKETHROUGH_DOUBLE_TILDE, and Options.LIBERAL_HTML_TAG) have no keyword shortcut and can only be set via the options parameter.

Returns

str
The rendered HTML string. Block-level elements end with a trailing newline.

Examples

Render basic Markdown to HTML:

from multimark import markdown_to_html

markdown_to_html("**bold** and *italic*")
'<p><strong>bold</strong> and <em>italic</em></p>\n'

Enable smart punctuation:

markdown_to_html('"Hello" -- world...', smart=True)
'<p>“Hello” – world…</p>\n'

Allow raw HTML passthrough:

markdown_to_html("<div>custom</div>", unsafe=True)
'<div>custom</div>\n'

Use GFM table extension:

markdown_to_html(
    "| A | B |\n|---|---|\n| 1 | 2 |\n",
    extensions=["table"],
)
'<table>\n<thead>\n<tr>\n<th>A</th>\n<th>B</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>2</td>\n</tr>\n</tbody>\n</table>\n'

Combine multiple features:

markdown_to_html(
    "~~old~~ -> new\n\nVisit https://example.com\n",
    extensions=["strikethrough", "autolink"],
    smart=True,
)
'<p><del>old</del> -&gt; new</p>\n<p>Visit <a href="https://example.com">https://example.com</a></p>\n'