Skip to main content

A typed translator that reads MyST and GFM and writes MyST, GFM, rST, and Typst.

Project description

myform

Status: In development — the package has not had its first public release. Expect breaking changes.

Pipeline Status Test Coverage License pre-commit pyrefly ruff

myform is a universal docs-format translator built around one absolute, typed document tree. It reads MyST Markdown and GitHub Flavored Markdown (GFM), then writes idiomatic MyST, GFM, Sphinx reStructuredText, or Typst. Formatting is the identity case: myform.convert(text, format, format) runs through the same reader, typed tree, and writer as a cross-format conversion.

Format Read Write
MyST Markdown Yes Yes
GFM Yes Yes
Sphinx reStructuredText No Yes
Typst No Yes

The two Markdown identity conversions remain the compatibility rail. They produce byte-for-byte the same text as the existing mdformat pipelines, including the MyST opinions developed in this repository.

Develop from source

Until the first myform release, install the checked-out source with uv:

uv sync --all-extras
uv run myform --help

After the first public release, the package installation command will be:

pip install myform

Translate documents

uv run myform convert guide.md --from myst --to rst -o guide.rst
printf '# Hello\n' | uv run myform convert - --from gfm --to typst
uv run myform convert guide.md --from myst --to gfm --report json >guide.gfm

Use - as the input path to read stdin. Output goes to stdout unless -o/--output names a file. Conversion reports always go to stderr, keeping document output safe for pipelines. Choose --report summary (the default), --report json, or --report none.

Format documents

The format verb performs an identity conversion:

uv run myform format README.md
uv run myform format README.md --format myst -o README.formatted.md

The Python API exposes the same contract:

import myform

rst = myform.convert(source, 'myst', 'rst')
formatted = myform.convert(source, 'myst', 'myst')

Configure translation

myform discovers the nearest myform.yaml, .myform.yaml, or [tool.myform] table by walking upward from the target path. Within one directory, that order is also the precedence order. The nearest directory wins rather than merging several files.

degrade:
  mode: annotate
  comments: true
assist:
  enabled: false
typst:
  postformat: off
extensions: []

Every non-native conversion is represented in the conversion report. The default annotate degradation mode also leaves a provenance comment when the target supports comments; silent suppresses comments but not reports, while strict refuses carrying or dropping unsupported constructs.

The optional LM assist is degradation-only and disabled by default, which makes zero network calls. When enabled, it uses the configured local OpenAI-compatible gateway and retains a deterministic fallback.

The committed myform.schema.json and myst-options.schema.json schemas describe the translator and mdformat-facade configuration surfaces. Refresh or verify both with:

uv run myform-write-schema
uv run myform-write-schema --check

Use the MyST mdformat facade

The original plugin remains available through mdformat's myst extension entry point:

uv run mdformat README.md

This repository began as a ground-up rewrite of mdformat-myst, written to make uncompiled MyST documents look closer to the hand-formatted sources maintained by the MyST team. That facade remains useful on its own:

  1. Targets hug the headings or blocks they identify instead of being separated by an extra blank line.

  2. Directive options prefer the readable :key: value prefix form and escalate to a YAML block only when necessary.

  3. Directive contents are formatted as first-class Markdown rather than treated as opaque text.

  4. Parser and renderer rules are explicit, decorator-registered examples of a modern mdformat extension.

  5. YAML values use srsly's maintained ruamel.yaml integration.

  6. The optional sembr mode reflows paragraphs to one sentence per line without changing their rendered output:

    [plugin.myst]
    sembr = true
    

    Enable it per invocation with mdformat --sembr <filename>; --no-sembr overrides the TOML setting.

The facade also preserves established skip-formatting comments:

<!-- myform-ignore -->

This next block is left exactly as written.
<!-- myform-ignore-start -->

Every block in this range is preserved.

<!-- myform-ignore-end -->
<!-- myform-ignore-file -->

The markers act at the document top level. Their strings remain configurable through [plugin.myst].

Documentation

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

myform-0.7.0.tar.gz (107.8 kB view details)

Uploaded Source

Built Distribution

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

myform-0.7.0-py3-none-any.whl (129.7 kB view details)

Uploaded Python 3

File details

Details for the file myform-0.7.0.tar.gz.

File metadata

  • Download URL: myform-0.7.0.tar.gz
  • Upload date:
  • Size: 107.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for myform-0.7.0.tar.gz
Algorithm Hash digest
SHA256 20b58583a496bf40c6d6bd970ac1b298fe716f7822db379328e8cb011772a6a7
MD5 78481754092765aa198be88973dbfc08
BLAKE2b-256 72e74758a2e38fee353069c409c1ff143d7fa6e5ba6132fe98f575f6192010dc

See more details on using hashes here.

File details

Details for the file myform-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: myform-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 129.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for myform-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5d9452f274f7cc0544e020940f83a3fdbe55d87b263b7cab1e641aefbd7c534
MD5 d781de64fad3cc80b7e02d80ace8e8a5
BLAKE2b-256 3f7157399e5644d89497d67af2700408e7a67f9f70c9b21918fa17685ee04564

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