Skip to main content

Python bindings for Quillmark - format-first Markdown rendering

Project description

Quillmark — Python bindings

Python bindings for Quillmark's format-first Markdown rendering engine.

Maintained by TTQ.

Installation

pip install quillmark

Quick Start

from quillmark import Quillmark, Quill, Document, OutputFormat

engine = Quillmark()                       # backend registry + render dispatcher
quill = Quill.from_path("path/to/quill")   # engine-free, validated config data

markdown = """~~~
$quill: my_quill
$kind: main
title: Hello World
~~~

# Hello
"""

parsed = Document.from_markdown(markdown)
result = engine.render(quill, parsed, OutputFormat.PDF)
result.artifacts[0].save("output.pdf")

API surface

The Python surface mirrors the @quillmark/wasm package. Names follow snake_case conventions; the underlying concepts (and shapes of return values) are the same.

Capability principle: a Quill is engine-free, validated config data — quill.metadata is a pure, infallible snapshot of the quill: section. Backend capability (supported_formats / supports_canvas) and rendering (render / open) are resolved by the engine, against a quill; they raise QuillmarkError (UnsupportedBackend) only if the declared backend isn't registered.

Quillmark

engine = Quillmark()
engine.registered_backends()              # ['typst']
engine.render(quill, parsed, OutputFormat.PDF)   # ppi=, pages=, producer= optional
engine.open(quill, parsed)                # RenderSession
engine.supported_formats(quill)           # [OutputFormat.PDF, ...] (raises if backend unregistered)
engine.supports_canvas(quill)             # True iff backend supports canvas preview (non-raising)

Quill

quill = Quill.from_path("path/to/quill")  # pure config load — no backend resolved here

quill.backend_id            # "typst" (declared backend)
quill.blueprint             # auto-generated annotated Markdown blueprint
quill.schema                # structured dict of the quill's document schema
quill.metadata              # pure config snapshot of the quill: section (never raises)
quill.quill_ref             # "name@version"

diags   = quill.validate(parsed)          # list of validation::* diagnostic dicts ([] = valid)
seed    = quill.seed_document()           # starter Document seeded from `example:` values
main    = quill.seed_main()               # just the $kind: main card (dict, like doc.main)
card    = quill.seed_card("note")         # one starter composable card (dict), None if kind undeclared

RenderSession

session = engine.open(quill, parsed)
session.page_count
session.backend_id
session.supports_canvas
session.warnings
session.render(OutputFormat.SVG, pages=[0])

RenderResult / Artifact

result.artifacts            # [Artifact, ...]
result.warnings             # [Diagnostic, ...]
result.format               # OutputFormat
result.render_time_ms       # float

artifact.format             # OutputFormat
artifact.bytes              # bytes
artifact.mime_type          # 'application/pdf', 'image/svg+xml', ...
artifact.save("out.pdf")

Document

doc = Document.from_markdown(markdown)
emitted = doc.to_markdown()

stored   = doc.to_json()
restored = Document.from_json(stored)
maybe    = Document.try_from_json(blob)          # None when not a DTO

Document.schema_version_of(blob)                 # raw tag (incl. unknown futures)
Document.current_schema_version()                # what this build writes

doc.clone()
doc.equals(other)
doc.card_count
doc.main; doc.cards; doc.body; doc.warnings

doc.set_field("title", "New")
doc.push_card(Document.make_card("note", {"x": 1}, "..."))  # or pass a Card from cards/remove_card/seed_card
# insert_card, remove_card, move_card, set_card_kind,
# update_card_field, remove_card_field, update_card_body, ...

Schema model

A field's cell is inferred from whether the schema declares a default::

  • Unendorsed (no default:) — the blueprint renders <must-fill>. An absent Unendorsed field is a non-fatal signal (validation::field_absent) — the render path zero-fills it silently. A surviving <must-fill> sentinel is fatal (validation::must_fill_sentinel). Partial documents are first-class; engine.render(quill, doc) only raises for malformed input.
  • Endorsed (with default:) — the blueprint renders the default value with a ; delete-ok annotation, and the default is used when the document omits the field.

There is no required: axis on FieldSchema.

Error contract

A single exception type — QuillmarkError — is raised for every failure mode. Every raised exception carries a non-empty .diagnostics list of Diagnostic objects. This matches the WASM binding's contract.

try:
    Document.from_markdown(bad_md)
except QuillmarkError as exc:
    for d in exc.diagnostics:
        print(d.severity, d.code, d.message, d.path)

EditError-shaped failures (invalid field names, kind names, out-of-range indices) prefix the message with [EditError::<Variant>] — the same format WASM uses — so callers can pattern-match on the message when they need to.

Changelog

See the changelog and the GitHub Releases page for release notes and version history.

Development

uv venv
uv pip install -e ".[dev]"
uv run pytest

License

Apache-2.0

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

quillmark-0.89.1rc1.tar.gz (2.5 MB view details)

Uploaded Source

Built Distributions

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

quillmark-0.89.1rc1-cp310-abi3-win_amd64.whl (14.0 MB view details)

Uploaded CPython 3.10+Windows x86-64

quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.1 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (15.0 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

quillmark-0.89.1rc1-cp310-abi3-macosx_11_0_arm64.whl (13.8 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file quillmark-0.89.1rc1.tar.gz.

File metadata

  • Download URL: quillmark-0.89.1rc1.tar.gz
  • Upload date:
  • Size: 2.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for quillmark-0.89.1rc1.tar.gz
Algorithm Hash digest
SHA256 7a5ddc3db11d57e8f2f44d3a204f779a16a4cb09ce954288b0f0ffa99504fbc4
MD5 2a446103a2077f42c4f0eacddd2cf01e
BLAKE2b-256 a0d0681c56f107caa94bec5cdc666858923ac7f7aa0d9aecc7f25645e7fbaeb8

See more details on using hashes here.

Provenance

The following attestation bundles were made for quillmark-0.89.1rc1.tar.gz:

Publisher: release.yml on quillmark-org/quillmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quillmark-0.89.1rc1-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for quillmark-0.89.1rc1-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 64c057d32a07778cd5da00c69db652e9d43c8c13a9bfc8563910af923d35dd7c
MD5 acd3d96997df805c4c73c16ce025d63b
BLAKE2b-256 89c0411e49acc1d00368cdaa48c601a01bf18815e7a1a10099da4b579ed9f3d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for quillmark-0.89.1rc1-cp310-abi3-win_amd64.whl:

Publisher: release.yml on quillmark-org/quillmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2fa5ad90400d577ec6c38bf3dc26cc78600918761e0c6f86847a482a2b239772
MD5 366ed5efc655614eacd8267ff95fbb7e
BLAKE2b-256 ad3e4f31b43872236679851b0895e42201defd13b7758dcef9f3eb5ef9f13bf5

See more details on using hashes here.

Provenance

The following attestation bundles were made for quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on quillmark-org/quillmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5b869cddb0cb73666e5e271058877fad9efd32f8f2600cb6f21b870b3f76a782
MD5 7f2bd596594bcd04c648d0dfe903c76b
BLAKE2b-256 1417c76b6905ae4f830c4579f91b52ba3fe45c0fb80255ee569d0a3118cc0911

See more details on using hashes here.

Provenance

The following attestation bundles were made for quillmark-0.89.1rc1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on quillmark-org/quillmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quillmark-0.89.1rc1-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for quillmark-0.89.1rc1-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a00e0c12888ea73d068da6b9357b989d72c8e2027fdef8f447b1d8bf2b31aee5
MD5 294eebcde52d38cdbd0409689d0e2595
BLAKE2b-256 45316fb6f4fe53a4e49d6a3a64ee3c3512d3ed42fdcc6294555917bbe7e92f44

See more details on using hashes here.

Provenance

The following attestation bundles were made for quillmark-0.89.1rc1-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on quillmark-org/quillmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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