Metadata-Version: 2.4
Name: markwright
Version: 0.1.0
Summary: Python-Markdown extensions ported from DigitalOcean's do-markdownit
Keywords: markdown,python-markdown,do-markdownit,mkdocs,hugo
Author: Mason Egger
Author-email: Mason Egger <mason@masonegger.com>
License-Expression: MIT
License-File: LICENSE
License-File: LICENSE-Apache-2.0
License-File: NOTICE
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Text Processing :: Markup :: Markdown
Requires-Dist: markdown>=3.4
Requires-Dist: pymdown-extensions>=10.5
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/MasonEgger/markwright
Project-URL: Repository, https://github.com/MasonEgger/markwright
Project-URL: Documentation, https://masonegger.github.io/markwright/
Description-Content-Type: text/markdown

# markwright

A Python port of DigitalOcean's [`do-markdownit`](https://github.com/digitalocean/do-markdownit) JavaScript library.

These are [Python-Markdown](https://python-markdown.github.io/) extensions that bring DigitalOcean's markdown syntax (highlighted text, labeled code fences, and a set of media embeds) to any tool built on Python-Markdown, including [MkDocs](https://www.mkdocs.org/), Flask, or a plain script.
The port maintains compatibility with the original `do-markdownit` HTML output, so rendered pages match what DigitalOcean produces.
A bundled command-line tool, `mw`, runs the same extensions as pre and post filters around any renderer, so the syntax also works in toolchains that are not built on Python-Markdown, like Hugo.

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

```bash
uv add markwright
```

or

```bash
pip install markwright
```

To work against a local checkout, install it editable:

```bash
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.

```yaml
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.

```python
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:

```python
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.

```bash
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 list` prints every extension and the stages it provides.

Your renderer must pass raw HTML and HTML comments through.
Hugo is a worked, tested example: see the [Hugo guide](https://masonegger.github.io/markwright/integrations/hugo/).
The full command and flag reference is in the [CLI docs](https://masonegger.github.io/markwright/cli/).

## Syntax at a Glance

````text
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](https://masonegger.github.io/markwright/) for every flag and the exact HTML each one produces.

## Development

This project uses [`uv`](https://docs.astral.sh/uv/) and [`just`](https://github.com/casey/just).

```bash
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](LICENSE).

It is a port of [`do-markdownit`](https://github.com/digitalocean/do-markdownit) by DigitalOcean, which is licensed under the Apache License 2.0.
See the [NOTICE](NOTICE) file for attribution details.
