# Options and Flags

This page explains how to control parsing and rendering behavior through keyword arguments, the [Options](../reference/Options.md#multimark.Options) bitmask, or a combination of both.


# Two Ways to Configure

Every renderer accepts configuration through two complementary mechanisms: boolean keyword arguments and an [Options](../reference/Options.md#multimark.Options) bitmask. You can use either one or both together. They are merged with a bitwise OR, so there is no conflict between them.

The keyword arguments cover the most commonly used flags:


``` python
from multimark import markdown_to_html

# Using keyword arguments
markdown_to_html("'Hello' -- world...", smart=True)
```


    '<p>'Hello' - world…</p>\n'


The [Options](../reference/Options.md#multimark.Options) enum covers every flag, including GFM-specific ones that have no keyword shortcut:


``` python
from multimark import markdown_to_html, Options

# Using the Options bitmask
markdown_to_html("'Hello' -- world...", options=Options.SMART)
```


    '<p>'Hello' - world…</p>\n'


Both calls produce the same result. The keyword style is more readable for one or two flags; the bitmask style is more concise when combining many flags into a reusable configuration.


# Available Keyword Arguments

Every renderer accepts these boolean keywords (all default to `False`):

| Keyword      | Effect                                                    |
|--------------|-----------------------------------------------------------|
| `hardbreaks` | Render soft line breaks as `<br />` (HTML) or equivalent  |
| `smart`      | Convert ASCII quotes and dashes to typographic characters |
| `normalize`  | Consolidate adjacent text nodes in the AST                |
| `unsafe`     | Allow raw HTML and dangerous URLs to pass through         |
| `footnotes`  | Enable footnote syntax (`[^label]`)                       |

Additionally, [markdown_to_html](../reference/markdown_to_html.md#multimark.markdown_to_html) and [markdown_to_xml](../reference/markdown_to_xml.md#multimark.markdown_to_xml) accept `sourcepos` (include source position data in the output), while [markdown_to_latex](../reference/markdown_to_latex.md#multimark.markdown_to_latex), [markdown_to_man](../reference/markdown_to_man.md#multimark.markdown_to_man), and [markdown_to_commonmark](../reference/markdown_to_commonmark.md#multimark.markdown_to_commonmark) accept `width` (line wrapping column, where `0` means no wrapping).


# The Options Enum

The [Options](../reference/Options.md#multimark.Options) class is an `IntFlag` enumeration. Each member corresponds to a cmark-gfm option bit. Because it is an `IntFlag`, members can be combined with the `|` operator.


``` python
from multimark import Options

# Combine multiple flags
opts = Options.SMART | Options.UNSAFE | Options.FOOTNOTES
print(f"Combined value: {opts}")
print(f"Individual flags: {opts!r}")
```


    Combined value: 140288
    Individual flags: <Options.UNSAFE|SMART|FOOTNOTES: 140288>


## All Available Flags

The full set of flags includes several GFM-specific options that have no keyword argument equivalent.

<span class="gd-details-chevron" aria-hidden="true"></span><img src="data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iaGVpZ2h0OjFlbTt3aWR0aDoxZW07dmVydGljYWwtYWxpZ246LTAuMTI1ZW07Zm9udC1zaXplOmluaGVyaXQ7b3ZlcmZsb3c6dmlzaWJsZTtwb3NpdGlvbjpyZWxhdGl2ZTsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld2JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLSBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJnZC1kZXRhaWxzLWljb24iIGFyaWEtaGlkZGVuPSJ0cnVlIj48cGF0aCBkPSJNMyA1aC4wMSIgLz48cGF0aCBkPSJNMyAxMmguMDEiIC8+PHBhdGggZD0iTTMgMTloLjAxIiAvPjxwYXRoIGQ9Ik04IDVoMTMiIC8+PHBhdGggZD0iTTggMTJoMTMiIC8+PHBhdGggZD0iTTggMTloMTMiIC8+PC9zdmc+" class="gd-details-icon" />Complete Options reference


| Flag | Keyword Equivalent | Description |
|----|----|----|
| `DEFAULT` | (none needed) | No flags set (value `0`) |
| `SOURCEPOS` | `sourcepos=True` | Include source position attributes |
| `HARDBREAKS` | `hardbreaks=True` | Render soft breaks as hard breaks |
| `UNSAFE` | `unsafe=True` | Allow raw HTML passthrough |
| `NOBREAKS` | (none) | Render soft breaks as spaces |
| `NORMALIZE` | `normalize=True` | Consolidate adjacent text nodes |
| `VALIDATE_UTF8` | (none) | Replace invalid UTF-8 sequences |
| `SMART` | `smart=True` | Typographic quote/dash conversion |
| `GITHUB_PRE_LANG` | (none) | Use `lang` attribute on `<pre>` instead of `class` on `<code>` |
| `LIBERAL_HTML_TAG` | (none) | Be more permissive with HTML tag parsing |
| `FOOTNOTES` | `footnotes=True` | Enable footnote syntax |
| `STRIKETHROUGH_DOUBLE_TILDE` | (none) | Require `~~` for strikethrough (not `~`) |
| `FULL_INFO_STRING` | (none) | Include full info string in code block attributes |


# Combining Keywords and Bitmask

When you pass both keyword arguments and an `options` bitmask, they are merged together. This lets you use keywords for common flags and the bitmask for GFM-specific ones.


``` python
from multimark import markdown_to_html, Options

# smart=True sets SMART, options adds GITHUB_PRE_LANG
fence = "```"
code_block = f"'Hello' -- world\n\n{fence}python\nprint('hi')\n{fence}\n"
print(markdown_to_html(
    code_block,
    smart=True,
    options=Options.GITHUB_PRE_LANG,
))
```


    <p>'Hello' - world</p>
    <pre lang="python"><code>print('hi')
    </code></pre>


Notice how the code block uses `<pre lang="python">` instead of the default `<code class="language-python">`. The `GITHUB_PRE_LANG` flag changed the attribute style, while `smart=True` handled the punctuation.


# Reusable Configurations

For applications that render many documents with the same settings, define your options once and reuse them.


``` python
from multimark import markdown_to_html, Options

# A configuration for rendering user-generated content safely
SAFE_GFM = Options.SMART | Options.VALIDATE_UTF8 | Options.STRIKETHROUGH_DOUBLE_TILDE

def render_comment(text: str) -> str:
    """Render a user comment with safe defaults."""
    return markdown_to_html(
        text,
        extensions=["table", "strikethrough", "autolink", "tasklist"],
        options=SAFE_GFM,
    )

render_comment("'Hello' -- check out https://example.com")
```


    '<p>'Hello' - check out [https://example.com](https://example.com)</p>\n'


This pattern keeps rendering configuration centralized and easy to audit. If you later need to adjust the options, you change one definition rather than updating every call site.


# The SAFE vs. UNSAFE Distinction

The `SAFE` and `UNSAFE` flags are complementary. `SAFE` is the legacy name for the default behavior (strip raw HTML). `UNSAFE` explicitly opts in to allowing raw HTML.


``` python
from multimark import markdown_to_html

raw_html = "<marquee>Dangerous!</marquee>"

# Default: raw HTML is stripped
print("Safe:", markdown_to_html(raw_html))

# With unsafe=True: raw HTML passes through
print("Unsafe:", markdown_to_html(raw_html, unsafe=True))
```


    Safe: <p><!-- raw HTML omitted -->Dangerous!<!-- raw HTML omitted --></p>

    Unsafe: <p><marquee>Dangerous!</marquee></p>


When building applications that accept Markdown from untrusted sources, always leave `unsafe` at its default value of `False`. The cost of stripping raw HTML is negligible compared to the security risk of XSS vulnerabilities.
