---------------------------------------------------------------------- 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 ![image](logo.png "alt text"). """ 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: `