Skip to content

API reference

Functions

html

html(
    markdown: str,
    /,
    *,
    options: Options = 0,
    broken_link_callback: BrokenLinkCallback | None = None,
    highlight: Theme | HighlightCallback | None = None,
) -> str

Render Markdown to HTML.

The output is not sanitized: raw HTML passes through, as CommonMark requires.

Examples:

html = pyromark.html("# Hello world")
assert html == "<h1>Hello world</h1>\n"

Resolve references the document does not define:

html = pyromark.html(
    "[Hello]", broken_link_callback=lambda link: (f"/{link['reference']}", "")
)
assert html == '<p><a href="/Hello">Hello</a></p>\n'

Highlight code blocks:

html = pyromark.html("~~~python\nx = 1\n~~~", highlight=pyromark.Theme.INSPIRED_GITHUB)

write_html

write_html(
    markdown: str,
    file: SupportsWrite[bytes],
    /,
    *,
    options: Options = 0,
    broken_link_callback: BrokenLinkCallback | None = None,
    highlight: Theme | HighlightCallback | None = None,
) -> None

Like html, but writes UTF-8 into a binary file.

The output goes to file.write() in 64 KiB chunks instead of being returned as one str.

Examples:

import io

file = io.BytesIO()
pyromark.write_html("# Hello world", file)
assert file.getvalue() == b"<h1>Hello world</h1>\n"

events

events(
    markdown: str,
    /,
    *,
    options: Options = 0,
    merge_text: bool = True,
    broken_link_callback: BrokenLinkCallback | None = None,
) -> Iterator[Event]

Iterate over the document's events.

Returns a lazy iterator: wrap it in tuple() if you need a sequence. Adjacent text events are merged unless merge_text=False.

Examples:

for event in pyromark.events("# Hello world"):
    match event:
        case {"Start": {"Heading": {"level": level}}}:
            print(f"{level} heading started")
        case {"Text": text}:
            print(f"Got {text!r}")
        case {"End": {"Heading": level}}:
            print(f"{level} heading ended")

events_with_range

events_with_range(
    markdown: str,
    /,
    *,
    options: Options = 0,
    merge_text: bool = False,
    broken_link_callback: BrokenLinkCallback | None = None,
) -> Iterator[tuple[Event, Range]]

Like events, but yields (event, range) pairs.

Ranges are UTF-8 byte offsets: slice markdown.encode(), not markdown. Text is not merged by default, because each piece has its own range.

Examples:

markdown = "# Hello world"
for event, range_ in pyromark.events_with_range(markdown):
    source = markdown.encode()[range_["start"] : range_["end"]]
    print(event, source.decode())

reference_definitions

reference_definitions(
    markdown: str, /, *, options: Options = 0
) -> dict[str, LinkDef]

Return the document's link reference definitions, keyed by label.

They come in document order. Labels match case-insensitively: of [Foo]: /a and [FOO]: /b, only the first is kept, under "Foo". Only the block level pass runs, so this is cheaper than events.

Examples:

definitions = pyromark.reference_definitions("[foo]: /a 'A'")
assert definitions == {"foo": {"dest": "/a", "title": "A", "span": {"start": 0, "end": 13}}}

Classes

Markdown

Markdown(
    *,
    options: Options = Options(0),
    broken_link_callback: BrokenLinkCallback | None = None,
    highlight: Theme | HighlightCallback | None = None,
)

Parser settings, given once and reused for every call.

Takes the same keyword arguments as html; highlight only affects html and write_html. Instances are immutable, so one can be shared between threads.

Examples:

md = pyromark.Markdown(options=pyromark.Options.ENABLE_TABLES)
assert md.html("# Hello world") == "<h1>Hello world</h1>\n"

events

events(
    markdown: str, /, *, merge_text: bool = True
) -> Iterator[Event]

Same as pyromark.events, with these settings.

events_with_range

events_with_range(
    markdown: str, /, *, merge_text: bool = False
) -> Iterator[tuple[Event, Range]]

Same as pyromark.events_with_range, with these settings.

html

html(markdown: str) -> str

Same as pyromark.html, with these settings.

reference_definitions

reference_definitions(markdown: str) -> dict[str, LinkDef]

Same as pyromark.reference_definitions, with these settings.

write_html

write_html(
    markdown: str, file: SupportsWrite[bytes]
) -> None

Same as pyromark.write_html, with these settings.

Options

Bases: IntFlag

Markdown extensions to enable, combined with |. All are off by default.

Passing bits pulldown-cmark does not define raises ValueError. See pulldown-cmark for the details of each extension.

Examples:

options = (
    pyromark.Options.ENABLE_TABLES
    | pyromark.Options.ENABLE_MATH
    | pyromark.Options.ENABLE_GFM
)

ENABLE_TABLES

ENABLE_TABLES = 1 << 1

Pipe tables, as in GitHub Flavored Markdown.

ENABLE_FOOTNOTES

ENABLE_FOOTNOTES = 1 << 2

Footnotes, referenced with [^1] and defined with [^1]: text.

ENABLE_STRIKETHROUGH

ENABLE_STRIKETHROUGH = 1 << 3

~~strikethrough~~, as in GitHub Flavored Markdown.

ENABLE_TASKLISTS

ENABLE_TASKLISTS = 1 << 4

Task list items, - [ ] and - [x].

ENABLE_SMART_PUNCTUATION

ENABLE_SMART_PUNCTUATION = 1 << 5

Typographic replacements: -- and --- become dashes, ... an ellipsis, and straight quotes become curly ones.

ENABLE_HEADING_ATTRIBUTES

ENABLE_HEADING_ATTRIBUTES = 1 << 6

Headings carrying an id, classes and attributes, as in # text { #id .class1 .class2 myattr other_attr=myvalue }.

ENABLE_YAML_STYLE_METADATA_BLOCKS

ENABLE_YAML_STYLE_METADATA_BLOCKS = 1 << 7

A metadata block opened by a --- line and closed by --- or ....

ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS

ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS = 1 << 8

A metadata block delimited by +++ lines.

ENABLE_OLD_FOOTNOTES

ENABLE_OLD_FOOTNOTES = 1 << 9 | 1 << 2

The older footnote syntax. Includes ENABLE_FOOTNOTES.

ENABLE_MATH

ENABLE_MATH = 1 << 10

$inline$ and $$display$$ formulas, emitted as InlineMath and DisplayMath events.

ENABLE_GFM

ENABLE_GFM = 1 << 11

GitHub alerts: > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING] and > [!CAUTION].

ENABLE_DEFINITION_LIST

ENABLE_DEFINITION_LIST = 1 << 12

Definition lists, a title followed by lines starting with :.

ENABLE_SUPERSCRIPT

ENABLE_SUPERSCRIPT = 1 << 13

^superscript^.

ENABLE_SUBSCRIPT

ENABLE_SUBSCRIPT = 1 << 14

~subscript~.

ENABLE_WIKILINKS = 1 << 15

Obsidian-style [[wikilinks]].

Theme

Bases: StrEnum

Bundled syntax highlighting themes, for the highlight argument.

Themes emit inline styles, so no stylesheet is needed, but the background is fixed and ignores prefers-color-scheme. Pass a callable instead to emit your own classes or to use Pygments. The ~190 languages of bat are recognized by name or file extension; blocks in other languages are left unhighlighted.

Examples:

html = pyromark.html("~~~python\nx = 1\n~~~", highlight=pyromark.Theme.INSPIRED_GITHUB)
assert html.startswith('<pre style="background-color:#ffffff;">')

INSPIRED_GITHUB

INSPIRED_GITHUB = 'InspiredGitHub'

Light, resembling GitHub.

SOLARIZED_DARK

SOLARIZED_DARK = 'Solarized (dark)'

Solarized, dark.

SOLARIZED_LIGHT

SOLARIZED_LIGHT = 'Solarized (light)'

Solarized, light.

BASE16_EIGHTIES_DARK

BASE16_EIGHTIES_DARK = 'base16-eighties.dark'

base16 Eighties, dark.

BASE16_MOCHA_DARK

BASE16_MOCHA_DARK = 'base16-mocha.dark'

base16 Mocha, dark.

BASE16_OCEAN_DARK

BASE16_OCEAN_DARK = 'base16-ocean.dark'

base16 Ocean, dark.

BASE16_OCEAN_LIGHT

BASE16_OCEAN_LIGHT = 'base16-ocean.light'

base16 Ocean, light.

Types

Event

Event: TypeAlias = (
    Literal["SoftBreak", "HardBreak", "Rule"]
    | _Start
    | _End
    | _Text
    | _Code
    | _InlineMath
    | _DisplayMath
    | _Html
    | _InlineHtml
    | _FootnoteReference
    | _TaskListMarker
)

One element of the document.

Match on it to pick out the elements you care about. Every kind and its payload is listed in the events table.

Range

Bases: TypedDict

A region of the source, as UTF-8 byte offsets.

Slice markdown.encode() with it, not markdown, or non-ASCII text shifts the result.

start

start: int

end

end: int

LinkDef

Bases: TypedDict

A link reference definition, as in [label]: /url "title".

dest

dest: str

title

title: str | None

span

span: Range

Bases: TypedDict

A link reference the document does not define.

span

span: Range
link_type: _LinkType

reference

reference: str

BrokenLinkCallback

BrokenLinkCallback: TypeAlias = Callable[
    [BrokenLink], tuple[str, str] | None
]

Resolves a link reference that has no definition.

Returns (destination_url, title), or None to leave the reference as text. If it raises, rendering or iteration stops and the exception propagates.

HighlightCallback

HighlightCallback: TypeAlias = Callable[
    [str | None, str], str | None
]

Renders a code block, given its language and its code.

The language is the first word of the opening fence, or None. Returns the block's HTML, which is inserted verbatim, or None to render the block as usual. If it raises, rendering stops and the exception propagates.