Skip to main content

markwright

markwright is a set of Python-Markdown extensions plus a companion command-line tool, mw, for author-friendly markdown: highlighted text, labeled code fences, and a set of media embeds. Use the extensions in any tool built on Python-Markdown (including MkDocs, Flask, or a plain script), or the mw pipeline in toolchains that are not, like Hugo.

The author-facing syntax and HTML output are derived from DigitalOcean's do-markdownit, so rendered pages match what DigitalOcean produces. markwright ports those extensions to Python-Markdown and adds its own pieces on top, most notably the mw CLI, which runs the same extensions as pre and post filters around any renderer.

Full documentation and a live demo: https://masonegger.github.io/markwright/

Features

Each extension is standalone and can be loaded on its own or alongside the others.

  • Highlight wraps <^>text<^> in <mark>, and works inside inline code and fenced code blocks where ==text== cannot reach.
  • Fence adds labels, secondary labels, environment classes, and command-line prefixes (line numbers, $/# prompts, custom prefixes) to code blocks.
  • YouTube turns [youtube ID] into a responsive iframe embed.
  • CodePen embeds a pen with theme, default-tab, and layout options.
  • Twitter embeds a tweet with theme and alignment options.
  • Instagram embeds a post with caption and alignment options.
  • Slideshow builds an image slideshow with navigation arrows.
  • Image Compare renders two images with a draggable before/after slider.

Installation

uv add markwright

or

pip install markwright

To work against a local checkout, install it editable:

uv add --editable ../markwright

Usage

With MkDocs

Add the extensions to mkdocs.yml. Load markwright.fence after pymdownx.superfences and pymdownx.highlight so the code-block HTML is in the shape the fence postprocessor expects.

markdown_extensions:
  - pymdownx.superfences
  - pymdownx.highlight:
      pygments_lang_class: true
  - markwright.highlight
  - markwright.fence:
      allowed_environments:
        - local
        - second
        - third
  - markwright.youtube
  - markwright.codepen
  - markwright.twitter
  - markwright.instagram
  - markwright.slideshow
  - markwright.image_compare

Standalone

The extensions work with Python-Markdown directly, so you can use them in any Python program.

import markdown

md = markdown.Markdown(extensions=[
    "pymdownx.superfences",
    "pymdownx.highlight",
    "markwright.highlight",
    "markwright.fence",
    "markwright.youtube",
    "markwright.codepen",
    "markwright.twitter",
    "markwright.instagram",
    "markwright.slideshow",
    "markwright.image_compare",
])

html = md.convert("This has a <^>highlighted word<^> in it.")
print(html)

Load only what you need:

import markdown

# Just YouTube embeds
md = markdown.Markdown(extensions=["markwright.youtube"])
html = md.convert("[youtube dQw4w9WgXcQ]")

The fence extension expects pymdownx.superfences and pymdownx.highlight to be loaded too. Without them the preprocessor still extracts directives, but the code-block HTML may not match what the postprocessor rewrites.

Command-Line Interface (mw)

For a toolchain that is not built on Python-Markdown, the mw command runs the same extensions as a pair of Unix filters around any renderer: a pre stage on the Markdown source, and a post stage on the rendered HTML.

mw pre < in.md | your-renderer | mw post > out.html
  • mw pre expands the embeds and extracts fence directives into an mw-fence comment.
  • mw post applies the fence styling, resolves the highlights, and injects each embed script once.
  • mw render runs the full pipeline in one shot for callers without their own renderer.
  • mw config prints the resolved configuration and the source of each value.
  • mw list prints every extension and the stages it provides.

Which extensions run, and how each is tuned, come from a markwright.toml (or a [tool.markwright] table in pyproject.toml) that the CLI discovers by walking up from the current directory. See the configuration docs.

Your renderer must pass raw HTML and HTML comments through. Hugo is a worked, tested example: see the Hugo guide. The full command and flag reference is in the CLI docs.

Syntax at a Glance

Highlight:       <^>important<^>

Fenced code with a label and command prompts:
    ```command
    [label deploy.sh]
    ssh root@server
    apt update
    ```

YouTube:         [youtube dQw4w9WgXcQ]
                 [youtube dQw4w9WgXcQ 360 640]
CodePen:         [codepen MattCowley vwPzeX]
                 [codepen MattCowley vwPzeX dark css]
Twitter:         [twitter https://twitter.com/github/status/1234567890]
Instagram:       [instagram https://www.instagram.com/p/CkQuv3_LRgS]
Slideshow:       [slideshow https://picsum.photos/id/10/480/270 https://picsum.photos/id/20/480/270]
Image Compare:   [compare before.jpg after.jpg]

See the extension docs for every flag and the exact HTML each one produces.

Development

This project uses uv and just.

just install           # uv sync
just test              # unit tests, 100% line + branch coverage
just test-integration  # end-to-end Hugo pipeline test (needs hugo)
just lint              # ruff check + ruff format --check
just typecheck         # mypy --strict
just check             # test + lint + typecheck
just docs-serve        # serve the docs site at localhost:8000

just check must pass before a change is complete. The tooling bar is strict: mypy --strict, a clean ruff, and full test coverage.

License

markwright is released under the MIT License.

It is a port of do-markdownit by DigitalOcean, which is licensed under the Apache License 2.0. See the NOTICE file for attribution details.

Metadata

Release files for markwright 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for markwright 0.2.0
File Size Uploaded Provenance
markwright-0.2.0.tar.gz 30.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for markwright 0.2.0
File Interpreter ABI Platform
markwright-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 70.6 kB

Release files / markwright-0.2.0.tar.gz

Download URL markwright-0.2.0.tar.gz
Size 30.0 kB
Tags Source
SHA-256 checksum
How to use checksums
6e1f8eed80d3ef005ba1130c9811caf478fe53a62d467e45ab61da7a49ba626a
BLAKE2b-256 checksum
How to use checksums
6165400ea37f558a54e10c1fbdc5e4639a2b0eebea00a2ee59a8c567f8839cae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / markwright-0.2.0-py3-none-any.whl

Download URL markwright-0.2.0-py3-none-any.whl
Size 40.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2186fc4d2e3b3d1c05c9ce897e3abb6abd57e5c43417688a6851af6f9ceb6836
BLAKE2b-256 checksum
How to use checksums
18edd79e4a4ccbe3e7c317ca68b5c6b70585b421061bcf2be25309c6e6f97092
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for markwright 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page