----------------------------------------------------------------------
This is the API documentation for the multimark library.
----------------------------------------------------------------------
## Renderers
Convert Markdown to various output formats
markdown_to_html(text: 'str', *, hardbreaks: 'bool' = False, smart: 'bool' = False, normalize: 'bool' = False, sourcepos: 'bool' = False, unsafe: 'bool' = False, footnotes: 'bool' = False, extensions: 'Sequence[str]' = (), options: 'int' = 0) -> 'str'
Parse CommonMark/GFM and render as HTML.
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](https://spec.commonmark.org/) 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
Render soft line breaks (single newlines within a paragraph) as `
` tags.
By default, this is `False` and soft breaks are rendered as spaces, matching the
CommonMark specification behavior.
smart : bool
Convert straight quotes to curly quotes, `--` to en-dashes, `---` to em-dashes,
and `...` to ellipses. By default, this is `False`.
normalize : bool
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
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
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 ``, and dangerous
URLs (e.g., `javascript:`) are suppressed.
footnotes : bool
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
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:
```{python}
from multimark import markdown_to_html
markdown_to_html("**bold** and *italic*")
```
Enable smart punctuation:
```{python}
markdown_to_html('"Hello" -- world...', smart=True)
```
Allow raw HTML passthrough:
```{python}
markdown_to_html("
custom
", unsafe=True)
```
Use GFM table extension:
```{python}
markdown_to_html(
"| A | B |\n|---|---|\n| 1 | 2 |\n",
extensions=["table"],
)
```
Combine multiple features:
```{python}
markdown_to_html(
"~~old~~ -> new\n\nVisit https://example.com\n",
extensions=["strikethrough", "autolink"],
smart=True,
)
```
markdown_to_latex(text: 'str', *, hardbreaks: 'bool' = False, smart: 'bool' = False, normalize: 'bool' = False, unsafe: 'bool' = False, footnotes: 'bool' = False, extensions: 'Sequence[str]' = (), width: 'int' = 0, options: 'int' = 0) -> 'str'
Parse CommonMark/GFM and render as LaTeX.
Converts Markdown to LaTeX source suitable for inclusion in a `.tex` document.
Inline formatting maps to LaTeX commands (`\textbf{}`, `\emph{}`, `\texttt{}`),
headings become sectioning commands (`\section{}`, `\subsection{}`, etc.), and
links use `\href{}{}`.
The output is a fragment (not a full document): it does not include
`\documentclass`, `\begin{document}`, or preamble. You can concatenate it into
your own LaTeX document structure.
Parameters
----------
text : str
The Markdown string to parse and render. Must be a Python `str`.
hardbreaks : bool
Render soft line breaks as hard breaks (`\\`). By default, this is `False`.
smart : bool
Convert straight quotes to curly quotes, `--` to en-dashes, `---` to em-dashes,
and `...` to ellipses. By default, this is `False`.
normalize : bool
Consolidate adjacent text nodes in the parsed AST. By default, this is `False`.
unsafe : bool
Allow raw HTML to pass through. Since LaTeX is the target format, raw HTML is
typically irrelevant. By default, this is `False`.
footnotes : bool
Enable footnote syntax parsing. By default, this is `False`.
extensions : Sequence[str]
A sequence of GFM extension names to enable. Valid names are `"table"`,
`"strikethrough"`, `"autolink"`, `"tagfilter"`, and `"tasklist"`.
width : int
The column at which to wrap output lines. Set to `0` (the default) to disable
line wrapping entirely. A value like `80` produces lines of at most 80
characters where possible.
options : int
An integer bitmask of `Options` flags (e.g., `Options.SMART | Options.UNSAFE`).
Merged via OR with any boolean keyword arguments set to `True`.
Defaults to `0`.
Keyword Arguments vs. Options Flags
------------------------------------
The boolean keyword arguments (`smart`, `unsafe`, `hardbreaks`, etc.) are convenience
shortcuts for the most common `Options` flags. When both styles are provided, they
are merged via OR. See `markdown_to_html()` for a detailed explanation.
Returns
-------
str
The rendered LaTeX string.
Examples
--------
Render inline formatting:
```{python}
from multimark import markdown_to_latex
markdown_to_latex("**bold** and *italic*")
```
Render a heading:
```{python}
markdown_to_latex("# Introduction")
```
Enable line wrapping at 72 columns:
```{python}
long_text = "This is a very long paragraph. " * 10
print(markdown_to_latex(long_text, width=72))
```
Use smart punctuation for typographic output:
```{python}
markdown_to_latex('"Hello," she said --- "goodbye."', smart=True)
```
markdown_to_man(text: 'str', *, hardbreaks: 'bool' = False, smart: 'bool' = False, normalize: 'bool' = False, unsafe: 'bool' = False, footnotes: 'bool' = False, extensions: 'Sequence[str]' = (), width: 'int' = 0, options: 'int' = 0) -> 'str'
Parse CommonMark/GFM and render as a groff man page.
Produces groff-format output suitable for use with the `man` command or inclusion
in manual page source files. Inline formatting maps to font switching requests
(`\f[B]`, `\f[I]`, `\f[CR]`), paragraphs use `.PP`, and headings use `.SH` or
`.SS` macros.
The output is a fragment and does not include a `.TH` title header. Wrap it in your
own man page structure to produce a complete manual page.
Parameters
----------
text : str
The Markdown string to parse and render. Must be a Python `str`.
hardbreaks : bool
Render soft line breaks as hard breaks (`.br`). By default, this is `False`.
smart : bool
Convert straight quotes to curly quotes, `--` to en-dashes, `---` to em-dashes,
and `...` to ellipses. By default, this is `False`.
normalize : bool
Consolidate adjacent text nodes in the parsed AST. By default, this is `False`.
unsafe : bool
Allow raw HTML to pass through. Since groff is the target format, raw HTML is
typically irrelevant. By default, this is `False`.
footnotes : bool
Enable footnote syntax parsing. By default, this is `False`.
extensions : Sequence[str]
A sequence of GFM extension names to enable. Valid names are `"table"`,
`"strikethrough"`, `"autolink"`, `"tagfilter"`, and `"tasklist"`.
width : int
The column at which to wrap output lines. Set to `0` (the default) to disable
line wrapping entirely.
options : int
An integer bitmask of `Options` flags (e.g., `Options.SMART | Options.UNSAFE`).
Merged via OR with any boolean keyword arguments set to `True`.
Defaults to `0`.
Keyword Arguments vs. Options Flags
------------------------------------
The boolean keyword arguments (`smart`, `unsafe`, `hardbreaks`, etc.) are convenience
shortcuts for the most common `Options` flags. When both styles are provided, they
are merged via OR. See `markdown_to_html()` for a detailed explanation.
Returns
-------
str
The rendered groff man page string.
Examples
--------
Render a paragraph with bold and italic:
```{python}
from multimark import markdown_to_man
markdown_to_man("**bold** and *italic*")
```
Render a heading:
```{python}
markdown_to_man("## Options")
```
Wrap at 72 columns:
```{python}
long_paragraph = "This is a long paragraph of text. " * 10
print(markdown_to_man(long_paragraph, width=72))
```
markdown_to_commonmark(text: 'str', *, hardbreaks: 'bool' = False, smart: 'bool' = False, normalize: 'bool' = False, unsafe: 'bool' = False, footnotes: 'bool' = False, extensions: 'Sequence[str]' = (), width: 'int' = 0, options: 'int' = 0) -> 'str'
Parse CommonMark/GFM and render back as normalized CommonMark.
Parses the input Markdown into an AST and re-renders it as CommonMark. This
effectively normalizes the formatting: different but semantically equivalent
Markdown inputs (e.g., `*italic*` vs `_italic_`, varying list indentation) will
produce a canonical output form.
This is useful for round-trip testing, canonical formatting, or cleaning up
inconsistently formatted documents. The output of this function, when parsed again,
produces the same AST as the original input.
Parameters
----------
text : str
The Markdown string to parse and normalize. Must be a Python `str`.
hardbreaks : bool
Render soft line breaks as hard breaks (backslash-newline). By default, this is
`False`.
smart : bool
Convert straight quotes to curly quotes, `--` to en-dashes, `---` to em-dashes,
and `...` to ellipses. By default, this is `False`.
normalize : bool
Consolidate adjacent text nodes in the parsed AST. By default, this is `False`.
unsafe : bool
Allow raw HTML to pass through. By default, this is `False`, which replaces raw
HTML with a comment placeholder.
footnotes : bool
Enable footnote syntax parsing. By default, this is `False`.
extensions : Sequence[str]
A sequence of GFM extension names to enable. Valid names are `"table"`,
`"strikethrough"`, `"autolink"`, `"tagfilter"`, and `"tasklist"`.
width : int
The column at which to wrap output lines. Set to `0` (the default) to disable
line wrapping entirely. This is useful for producing line-wrapped output for
version-control-friendly diffs.
options : int
An integer bitmask of `Options` flags (e.g., `Options.SMART | Options.UNSAFE`).
Merged via OR with any boolean keyword arguments set to `True`.
Defaults to `0`.
Keyword Arguments vs. Options Flags
------------------------------------
The boolean keyword arguments (`smart`, `unsafe`, `hardbreaks`, etc.) are convenience
shortcuts for the most common `Options` flags. When both styles are provided, they
are merged via OR. See `markdown_to_html()` for a detailed explanation.
Returns
-------
str
The normalized CommonMark string.
Examples
--------
Normalize inconsistent formatting:
```{python}
from multimark import markdown_to_commonmark
markdown_to_commonmark("_hello_ **world**")
```
Verify round-trip stability (parse, render, re-parse produces the same HTML):
```{python}
from multimark import markdown_to_commonmark, markdown_to_html
original = "**bold** and *italic*"
normalized = markdown_to_commonmark(original)
assert markdown_to_html(original) == markdown_to_html(normalized)
```
Wrap at 80 columns for version-control-friendly output:
```{python}
long_document = "This is a long sentence for demonstration. " * 10
print(markdown_to_commonmark(long_document, width=80))
```
markdown_to_xml(text: 'str', *, hardbreaks: 'bool' = False, smart: 'bool' = False, normalize: 'bool' = False, sourcepos: 'bool' = False, unsafe: 'bool' = False, footnotes: 'bool' = False, extensions: 'Sequence[str]' = (), options: 'int' = 0) -> 'str'
Parse CommonMark/GFM and render as XML.
Produces an XML representation of the parsed abstract syntax tree (AST). Each
Markdown construct is represented as a named element (e.g., ``,
``, ``), with text content preserved in `` elements.
The XML output conforms to the CommonMark DTD and includes an XML declaration and
DOCTYPE. This format is useful for debugging, AST inspection, or piping into
XML-based toolchains.
Parameters
----------
text : str
The Markdown string to parse and render. Must be a Python `str`.
hardbreaks : bool
Render soft line breaks as hard breaks in the AST. By default, this is `False`.
smart : bool
Convert straight quotes to curly quotes, `--` to en-dashes, `---` to em-dashes,
and `...` to ellipses. By default, this is `False`.
normalize : bool
Consolidate adjacent text nodes in the parsed AST. By default, this is `False`.
sourcepos : bool
Include `sourcepos` attributes on elements indicating their line/column
positions in the original Markdown source. By default, this is `False`.
unsafe : bool
Allow raw HTML to pass through. By default, this is `False`.
footnotes : bool
Enable footnote syntax parsing. By default, this is `False`.
extensions : Sequence[str]
A sequence of GFM extension names to enable. Valid names are `"table"`,
`"strikethrough"`, `"autolink"`, `"tagfilter"`, and `"tasklist"`.
options : int
An integer bitmask of `Options` flags (e.g., `Options.SMART | Options.UNSAFE`).
Merged via OR with any boolean keyword arguments set to `True`.
Defaults to `0`.
Keyword Arguments vs. Options Flags
------------------------------------
The boolean keyword arguments (`smart`, `unsafe`, `hardbreaks`, etc.) are convenience
shortcuts for the most common `Options` flags. When both styles are provided, they
are merged via OR. See `markdown_to_html()` for a detailed explanation.
Returns
-------
str
The rendered XML string, including the XML declaration and DOCTYPE.
Examples
--------
Inspect the AST structure of a simple document:
```{python}
from multimark import markdown_to_xml
print(markdown_to_xml("**hello**"))
```
Add source position information:
```{python}
markdown_to_xml("# Title\n\nBody text\n", sourcepos=True)
```
## Options
Parsing and rendering configuration
Options(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
CommonMark/GFM parsing and rendering options.
An `IntFlag` enumeration of all option flags supported by the cmark-gfm library.
Options can be combined using the bitwise OR operator (`|`) and passed to any
renderer's `options=` parameter. This provides a composable, lower-level alternative
to the named boolean keyword arguments available on each renderer function.
Most users will prefer the named keyword arguments (e.g., `smart=True`) for common
options. The `Options` bitmask is useful when you need to combine multiple flags
into a single reusable value, or when working with GFM-specific flags that do not
have dedicated keyword arguments.
Examples
--------
Combine multiple flags with the `|` operator:
```{python}
from multimark import markdown_to_html, Options
opts = Options.SMART | Options.UNSAFE
markdown_to_html('"Hello" -- world', options=opts)
```
Mix a bitmask with named keyword arguments (they are OR'd together):
```{python}
text = "Here's some *text* to convert"
markdown_to_html(text, options=Options.SMART, footnotes=True)
```
Use GFM-specific flags that have no keyword shortcut:
```{python}
markdown_to_html(
"~~deleted~~",
options=Options.STRIKETHROUGH_DOUBLE_TILDE,
extensions=["strikethrough"],
)
```
## Utility
Package information
cmark_version() -> 'str'
Return the version string of the vendored cmark-gfm library.
Reports the version of the bundled cmark-gfm C library that multimark was compiled
against. This is useful for debugging or confirming which release of the underlying
parser is in use.
Returns
-------
str
A version string in the format `"X.Y.Z.gfm.N"` (e.g., `"0.29.0.gfm.13"`).
Examples
--------
```{python}
from multimark import cmark_version
cmark_version()
```
----------------------------------------------------------------------
This is the CLI documentation for the package.
----------------------------------------------------------------------
## CLI: multimark
```
Usage: multimark [OPTIONS] [FILE]
Convert CommonMark/GFM Markdown to various output formats.
Reads Markdown from FILE (or stdin if omitted) and writes the converted
output to stdout or the file specified by --output.
Options:
-t, --to [html|latex|man|commonmark|xml]
Output format.
-o, --output FILENAME Output file (stdout if omitted).
-e, --extension [autolink|strikethrough|table|tagfilter|tasklist]
Enable a GFM extension (repeatable).
--smart Use smart punctuation.
--unsafe Allow raw HTML and dangerous URLs.
--hardbreaks Render softbreaks as hard line breaks.
--sourcepos Include source position attributes (html/xml
only).
--footnotes Enable footnote parsing.
--width INTEGER Wrap output at this column width
(latex/man/commonmark only).
--version Show the version and exit.
--help Show this message and exit.
```
----------------------------------------------------------------------
This is the User Guide documentation for the package.
----------------------------------------------------------------------
## Getting Started
### Introduction
This page gives you a high-level understanding of what multimark does, why it exists, and what you can accomplish with it.
## What Is Multimark?
Multimark is a Python package that provides bindings to
[cmark-gfm](https://github.com/github/cmark-gfm), GitHub's fork of the CommonMark
reference parser. It gives you fast, spec-compliant Markdown parsing and rendering in
five output formats: HTML, LaTeX, groff man pages, XML, and normalized CommonMark.
The C library is vendored and compiled at install time via CFFI, so there are no system
dependencies to manage. You get a single `pip install` and immediate access to the same
Markdown engine that powers GitHub.
## Why Use Multimark?
Most Python Markdown libraries are written in pure Python, which means they trade
performance for portability. Multimark takes a different approach: it wraps a
battle-tested C library that processes millions of documents daily on GitHub. This gives
you parsing speeds that are orders of magnitude faster than pure-Python alternatives,
with guaranteed spec compliance.
Beyond speed, multimark supports the full set of GitHub Flavored Markdown (GFM)
extensions: tables, strikethrough, autolinks, tag filtering, and task lists. These are
the same extensions that GitHub uses when rendering README files, issues, and pull
requests.
## Output Formats at a Glance
Multimark renders parsed Markdown into five distinct formats, each suited to different
use cases.
::: {.details .open summary="Available formats" icon="file-output"}
| Format | Function | Use Case |
|--------|----------|----------|
| HTML | `markdown_to_html()` | Web pages, documentation sites, email |
| LaTeX | `markdown_to_latex()` | Academic papers, PDF generation |
| Man page | `markdown_to_man()` | Unix manual pages |
| XML | `markdown_to_xml()` | AST inspection, toolchain integration |
| CommonMark | `markdown_to_commonmark()` | Normalization, round-trip formatting |
:::
All renderers share the same parser and accept the same set of options, so switching
between output formats requires changing only the function name.
## A Quick Taste
Here is the simplest possible use of multimark: converting a Markdown string to HTML.
```{python}
from multimark import markdown_to_html
markdown_to_html("Hello, **world**!")
```
The function returns the rendered output as a Python string. Every renderer works this
way: pass in Markdown text, get back the rendered result.
## Next Steps
The pages that follow will walk you through installation, a more thorough quickstart,
and then progressively deeper topics. If you prefer to jump straight to the API
reference, each function is fully documented with executable examples in the
[Reference](../reference/index.qmd) section.
### Installation
This page covers everything you need to get multimark installed and working on your system, from prerequisites through verification.
## Requirements
Multimark requires Python 3.9 or later and a C compiler available at install time. The
CFFI build step compiles the vendored cmark-gfm C library into a shared object that
Python loads at runtime.
On most systems, the necessary build tools are already present. If you are working in a
minimal container or a fresh virtual machine, you may need to install a compiler
toolchain first.
::: {.details summary="Platform-specific compiler setup" icon="monitor"}
**macOS**: Install the Xcode command-line tools if you have not already.
```bash
xcode-select --install
```
**Ubuntu / Debian**:
```bash
sudo apt-get install build-essential python3-dev
```
**Windows**: Install the [Build Tools for Visual Studio](https://visualstudio.microsoft.com/visual-cpp-build-tools/).
Select the "Desktop development with C++" workload during installation.
:::
## Installing from PyPI
The recommended way to install multimark is with pip inside a virtual environment.
```bash
python -m pip install multimark
```
This downloads the source distribution, compiles the C extension, and installs the
package. The entire process typically takes a few seconds on modern hardware.
## Installing from Source
For development or to get the latest unreleased changes, clone the repository and
install in editable mode.
```bash
git clone https://github.com/posit-dev/multimark.git
cd multimark
python -m pip install -e ".[dev]"
```
Editable mode means changes to the Python source files take effect immediately without
reinstalling. However, if you modify the C source or the CFFI build script, you need to
rebuild.
## Verifying the Installation
After installing, confirm that the package loads correctly and reports the expected
library version.
```{python}
import multimark
multimark.cmark_version()
```
If this prints a version string like `0.29.0.gfm.13`, the C library was compiled and
linked successfully.
## Dependencies
Multimark has a single runtime dependency: [cffi](https://cffi.readthedocs.io/). The
build process also requires `cffi` (for generating the bindings) and a C compiler.
There are no other third-party dependencies at runtime, keeping the installation
lightweight and conflict-free.
### Quick Start
This page walks you through the essentials of converting Markdown to HTML with multimark, covering inline formatting, block elements, smart punctuation, and safe HTML handling.
## Your First Conversion
The most common task is converting Markdown to HTML. Import the renderer and pass it a
string.
```{python}
from multimark import markdown_to_html
print(markdown_to_html("# Welcome\n\nThis is **bold** and *italic* text.\n"))
```
::: {.callout-tip}
## `print()` vs. bare expressions
Throughout this guide, examples use `print()` to display rendered output. This shows
the string with newlines expanded, making the HTML structure easy to read. Without
`print()`, Python displays the `repr()` of the string (with escaped `\n` characters
and surrounding quotes), which is harder to scan visually.
:::
The output is a complete HTML fragment with proper block-level structure. Headings become
`` through `` elements, paragraphs are wrapped in `
` tags, and inline
formatting maps to `` and ``.
## Working with Inline Formatting
Markdown supports a rich set of inline constructs. Multimark handles all of them
correctly, including nested formatting.
```{python}
text = """
This has **bold**, *italic*, `inline code`, and ***bold italic***.
Here is a [link](https://example.com) and an .
"""
print(markdown_to_html(text))
```
Notice that the raw HTML output includes proper attribute encoding and escaping. Special
characters like `<`, `>`, and `&` in your Markdown text are escaped automatically in the
HTML output.
## Block-Level Elements
Beyond paragraphs and headings, Markdown supports block quotes, code blocks, and lists.
Each renders to its corresponding HTML structure.
```{python}
fence = "```"
blocks = (
"> A block quote with **emphasis**.\n\n"
"- Item one\n"
"- Item two\n"
"- Item three\n\n"
f"{fence}python\n"
"def hello():\n"
' print("Hello!")\n'
f"{fence}\n"
)
print(markdown_to_html(blocks))
```
Fenced code blocks preserve their language annotation in a `class` attribute on the
`` element, which is useful for client-side syntax highlighting libraries.
## Smart Punctuation
Straight quotes and ASCII dashes look fine in source code but feel out of place in
typeset prose. The `smart` option converts them to their typographic equivalents.
```{python}
prose = '"It\'s a beautiful day," she said -- "let\'s go outside..."'
print(markdown_to_html(prose, smart=True))
```
With `smart=True`, double quotes become curly quotes, single quotes become apostrophes,
`--` becomes an en-dash, and `...` becomes an ellipsis character. This produces
publication-quality output from plain ASCII input.
## Handling Raw HTML
By default, multimark strips raw HTML from the input for security. This is the safe
choice when processing untrusted content (user comments, forum posts, uploaded files).
```{python}
# Raw HTML is stripped by default
print(markdown_to_html("Hello
"))
```
When you control the input and need HTML passthrough, set `unsafe=True`.
```{python}
print(markdown_to_html("Hello
", unsafe=True))
```
The `unsafe` flag affects both block-level HTML (like ``) and inline HTML (like
``). It also allows potentially dangerous URL schemes like `javascript:` in links.
Only enable this for content you fully trust.
## What Comes Next
This page covered the basics of HTML rendering with multimark. The following pages
explore GFM extensions, the other output formats, and the options system in depth. Each
builds on what you have seen here, using the same straightforward API pattern: pass
text in, get rendered output back.
## Core Concepts
### GFM Extensions
This page explains the five GitHub Flavored Markdown extensions that multimark supports, with examples showing how each one works and how to combine them.
## What Are GFM Extensions?
GitHub Flavored Markdown (GFM) extends the CommonMark specification with five additional
syntax features. These are the constructs that GitHub recognizes in README files, issues,
and pull requests but that are not part of the base CommonMark spec.
Multimark supports all five GFM extensions through the `extensions` parameter, which
accepts a sequence of extension names. Extensions are disabled by default so that the
parser remains strictly CommonMark-compliant unless you opt in.
```{python}
from multimark import VALID_EXTENSIONS
sorted(VALID_EXTENSIONS)
```
Each extension is independent: you enable only the ones you need.
## Tables
The `table` extension adds pipe-table syntax. Columns are separated by `|` characters,
and a header row is separated from body rows by a line of dashes.
```{python}
from multimark import markdown_to_html
table_md = """\
| Feature | Status |
|------------|--------|
| Tables | ✓ |
| Autolinks | ✓ |
| Tasklists | ✓ |
"""
print(markdown_to_html(table_md, extensions=["table"]))
```
Column alignment is controlled with colons in the separator row: `:---` for left,
`:---:` for center, and `---:` for right. The renderer emits `style="text-align: ..."`
attributes on the `
` and ` | ` elements.
```{python}
aligned = """\
| Left | Center | Right |
|:-----|:------:|------:|
| a | b | c |
"""
print(markdown_to_html(aligned, extensions=["table"]))
```
## Strikethrough
The `strikethrough` extension recognizes `~~text~~` as deleted content, rendering it
with `` tags.
```{python}
print(markdown_to_html("This is ~~no longer~~ relevant.", extensions=["strikethrough"]))
```
Strikethrough works inline alongside other formatting. You can combine it with bold,
italic, and code spans without issue.
```{python}
combined = "~~**bold and struck**~~ and ~~`code struck`~~"
print(markdown_to_html(combined, extensions=["strikethrough"]))
```
## Autolinks
The `autolink` extension automatically converts bare URLs and email addresses into
clickable links without requiring explicit Markdown link syntax.
```{python}
text = """\
Visit https://github.com for more info.
Send feedback to user@example.com.
"""
print(markdown_to_html(text, extensions=["autolink"]))
```
This is the same behavior you see on GitHub: any URL starting with `http://` or
`https://` becomes a link, and email addresses get `mailto:` links.
## Tag Filtering
The `tagfilter` extension suppresses a specific set of HTML tags that could be used for
XSS attacks, even when `unsafe=True` is set. The filtered tags are: ` |