Skip to main content

Markdown → typed AST → JSON / Markdown / HTML, with a pluggable widget system.

Project description

markast

markast

Markdown → typed AST → JSON / Markdown / HTML

Parse Markdown into a structured, typed tree your front-end can render — natively, server-side, or as JSON.

Version Python License Docs

Docs · Documentación (ES) · Examples


from markast import parse

doc = parse("# Hello\n\nA paragraph with **bold** and a [link](https://example.com).")

doc.to_json()       # str — ship to any client renderer
doc.to_markdown()   # str — roundtrip
doc.to_html()       # str — server-side render

Why a tree, not HTML?

HTML is a one-way street. Once your content is rendered, the structure is gone — clients can't restyle headings per platform, can't swap a :::video for a native player, can't extract a TOC without re-parsing.

markast keeps the meaning intact. Parse once, render anywhere:

  • Native mobile renders headings with platform typography.
  • The web renders :::video as a custom player; the terminal renders it as a link.
  • Search indexes the same structured nodes that drive the UI.
  • One source of content powers a docs site, a CMS preview, and a CLI.

What you get

Layer What it gives you
🌳 AST Typed nodes (TypedDict), walker/visitor, JSON-Schema export, factory helpers
🧱 Widgets :::widget containers with typed params, named slots, validation — and a per-parser registry, no global state
🛡️ Rules Validation diagnostics that never crash — bad content is repaired and a warning is emitted
⚙️ Transforms AST → AST passes: normalize, slugify, TOC, autolink
🔀 Renderers Markdown (full roundtrip) and HTML (server-side) — both subclassable
🧰 Parser CommonMark + GFM (tables, strikethrough, tasklists, autolinks) + footnotes + custom containers
⌨️ CLI markast parse file.md --format json

Install

pip install markast

30-second tour

from markast import Parser
from markast.widgets import BaseWidget, WidgetParam

class CalloutWidget(BaseWidget):
    name = "callout"
    params = {
        "level": WidgetParam(str, default="info", choices=["info", "warn", "error"]),
        "title": WidgetParam(str, default=None),
    }

parser = Parser(widgets=[CalloutWidget], transforms=["normalize", "slugify"])

doc = parser.parse("""
# Welcome

:::callout level=warn title="Heads up"
This is **important** content.
:::
""")

print(doc.to_json(indent=2))
print(doc.to_html())

parser.parse(...) always returns a valid Document. Invalid input is repaired and reported on doc.warnings — the parser never raises on user content.

Documentation

Full docs live at cursland.github.io/markast (English / Español, light & dark).

🚀 Getting started Install, parse, render
🌳 AST reference Every node type and field
🧱 Widgets Built-ins and authoring your own
⚙️ Transforms Built-in passes and custom transforms
🔀 Renderers Markdown, HTML, and subclassing
🧭 Walker & utilities Traverse and mutate the AST safely
🌐 Client integration Patterns for any front-end
🧩 Extending Custom rules, plugins, tokenizers

Examples

Runnable scripts in examples/:

Status

1.0.0 — first stable release. Backwards-compatible changes follow semver.

License

MIT © cursland

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

markast-1.0.0.tar.gz (63.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

markast-1.0.0-py3-none-any.whl (71.0 kB view details)

Uploaded Python 3

File details

Details for the file markast-1.0.0.tar.gz.

File metadata

  • Download URL: markast-1.0.0.tar.gz
  • Upload date:
  • Size: 63.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for markast-1.0.0.tar.gz
Algorithm Hash digest
SHA256 af8c135ee3ae8d39b165751e3b1d3fd5a030251055d271070f4a84126dfe7453
MD5 fca0883e52afdfdc14ba24f14ce14008
BLAKE2b-256 b0443f6823333da338dcb7e32c5f7bd70df82c708637e07bcbcafa7890e501a9

See more details on using hashes here.

File details

Details for the file markast-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: markast-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 71.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for markast-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 79635f01b6b67a9c123d163705c7c0c1816445ad58854123c29a0a23b6d4f60d
MD5 2bbfa78e1fc26f124d98a257f868950c
BLAKE2b-256 07492c0c0ac7f9ec59ba751add40282dbef19c7b88bae76ba7fe1948ab088cec

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page