ITADN
noirbizarre/oxydemark
README.md

OxydeMark

CI codecov License: MIT prek

Extensible Markdown pipelines powered by Rust.

Documentation | API reference

Overview

OxydeMark is a Markdown processing engine built around an AST pipeline architecture. It combines a high-performance Rust core for parsing and rendering with Python bindings (via PyO3) for a flexible plugin system.

Markdown Input
    -> Preprocessing Plugins (Python, text-level)
    -> Rust Parser / rushdown (AST generation)
    -> AST exposed to Python (AstNode tree)
    -> AST Transformation Plugins (Python, AST-level)
    -> Rust Renderer (HTML generation)
    -> Postprocessing Plugins (Python, HTML-level)
    -> Final Output

Installation

pip install oxydemark

Wheels are published for Linux, macOS and Windows. As an abi3-py312 build, a single wheel per platform covers Python 3.12 and every later version.

To use the Rust core directly, without any PyO3 dependency:

cargo add oxydemark

To build from a checkout instead:

git clone https://github.com/noirbizarre/oxydemark.git
cd oxydemark
mise install
maturin develop

Quick Start

from oxydemark import OxydeEngine

engine = OxydeEngine()

md = """
# Hello OxydeMark

This is **extensible Markdown**.
"""

html = engine.render(md)
print(html)

For a one-shot conversion without the plugin pipeline, use markdown_to_html; to inspect or transform the tree, use parse and render_ast; to extract headings, a table of contents, a summary and typed frontmatter, use parse_document.

Plugins

A plugin is any object implementing one or more of the preprocess, transform and postprocess hooks. No base class, no registration:

from oxydemark import OxydeEngine
from oxydemark.contrib import AdmonitionPlugin, MentionPlugin


class Shouty:
    def postprocess(self, html: str) -> str:
        return html.upper()


engine = OxydeEngine(plugins=[AdmonitionPlugin(), MentionPlugin(), Shouty()])
print(engine.render("> [!NOTE]\n> Ping @alice\n"))

oxydemark.contrib ships four worked examples (admonitions, shortcodes, mentions, lazy images). See the plugin guide for the full authoring documentation, including the AST value-semantics rules.

Development

See CONTRIBUTING.md for the full development guide.

# Set up tools and hooks
mise install
mise run setup

# Common tasks
mise run build        # Build the Rust crate
mise run test         # Run tests
mise run lint         # Run clippy
mise run fmt          # Format code
mise run ci           # Run all checks
mise run docs         # Build the documentation site

Project Structure

oxydemark/
├── src/                    # Rust core
│   ├── lib.rs              # Crate root, public re-exports
│   ├── api.rs              # Public API, parser/renderer wiring
│   ├── ast.rs              # AstNode definition, arena-to-tree conversion
│   ├── extensions.rs       # Comark parser/renderer extensions
│   ├── html_render.rs      # AST-to-HTML renderer
│   ├── slug.rs             # Anchor slug algorithm
│   ├── error.rs            # OxydeError
│   └── python.rs           # PyO3 binding layer (`python` feature)
├── python/oxydemark/       # Python package
│   ├── __init__.py         # Re-exports from native module
│   ├── api.py              # OxydeEngine, plugin protocols
│   ├── _core.pyi           # Type stub for the native module
│   └── contrib/            # Example plugins (provisional surface)
├── tests/                  # Rust and Python test suites
│   └── compliance/         # Shared fixtures, run by both harnesses
├── benchmarks/             # Markdown library comparison benchmarks
├── docs/                   # Documentation site sources
│   ├── plugins.md          # Plugin authoring guide
│   ├── api/                # API reference pages
│   └── specs/              # OMEPs (design decisions)
├── .github/workflows/      # CI, docs and release pipelines
├── Cargo.toml              # Rust crate configuration
├── pyproject.toml          # Python build config (maturin)
├── mise.toml               # Task runner and tool versions
├── zensical.toml           # Documentation site configuration
├── cliff.toml              # Changelog generation
├── prek.toml               # Pre-commit hooks
├── CONTRIBUTING.md         # Contribution guidelines
└── LICENSE                 # MIT License

Design Decisions

Architectural and tooling decisions are documented as OMEPs (OxydeMark Enhancement Proposals) in docs/specs/. See the OMEP index for the full list.

License

MIT