Python
前提: Getting Started、Document IR。
illusion-markdown は PyO3/maturin native extension として同じ mdi-core を呼びます。Python 側に独自 grammar はありません。
この binding で解決すること
Section titled “この binding で解決すること”Django/Flask の publishing backend、Jupyter を使う manuscript pipeline、Python の static-site generator から、CLI を起動せずに .mdi を解析・描画できます。Python 側の wrapper は約 60 行で、全関数が他の binding と同じ Rust code を直接呼びます。
Install
Section titled “Install”pip install illusion-markdownPyPI distribution 名は illusion-markdown、import 名は mdi です。Python 3.10+。macOS、Linux x64、Windows x64 の wheel があり、その他では Rust toolchain を必要とする source distribution に fallback します。
import mdisource = "# {東京|とうきょう}の夜\n\n第^12^話\n"result = mdi.parse(source)print(result["document"]["children"][0]["type"])open("book.html", "w", encoding="utf-8").write(mdi.render_html(source))Export される全 API
Section titled “Export される全 API”mdi.MDI_SPEC_VERSION; mdi.MDI_IR_VERSION; mdi.TextFormat; mdi.MdiRenderErrormdi.parse(source: str) -> dictmdi.render_html(source: str) -> strmdi.render_text(source: str) -> strmdi.render_text_format(source: str, format, indent_prefix: str = "") -> strmdi.render_epub(source: str) -> bytesmdi.render_docx(source: str) -> bytesmdi.serialize_mdi(source: str) -> strmdi.parse_mdi_syntax # deprecated aliasparse は typed class や dataclass ではなく、JSON wire format をそのまま decode した dict[str, Any] を返します。key は正確に camelCase です。たとえば result["document"]["children"][0]["type"]、span は startByte/endByte であり start_byte/end_byte ではありません。Document IR の node 一覧をそのまま dict に適用できます。render_epub と render_docx は bytes を返すため、"wb" で開いた file に書き込んでください。
Diagnostic と error handling
Section titled “Diagnostic と error handling”不正な MDI 記法は例外ではなく literal fallback と diagnostics で扱います。warning の全一覧は Diagnostics を参照してください。non-string input は PyO3 により TypeError、未知の text format は ValueError、EPUB/DOCX archive writer の実際の失敗だけは mdi.MdiRenderError です。mdi.parse() を diagnostics の代わりに try/except で包まないでください。
mdi.parse(None) # TypeErrormdi.render_text_format("text", "invalid") # ValueErrorIR version と UTF-8 byte span
Section titled “IR version と UTF-8 byte span”mdi.parse() は decoded irVersion を mdi.MDI_IR_VERSION と照合し、違えば RuntimeError を送出します。返るすべての span は UTF-8 byte offset です。Python の str は code point の列なので、文字 index にするには明示的な変換が必要です。
def byte_span_to_str_index(source: str, byte_offset: int) -> int: return len(source.encode("utf-8")[:byte_offset].decode("utf-8", errors="ignore"))現在の実装状況
Section titled “現在の実装状況”Python binding は 実装済み・公開済み・テスト済み です。test suite は IR shape、diagnostic、byte span、六つの text format、EPUB/DOCX archive、ここにある error path を検証し、branch coverage 95% を要求します。
この binding がしないこと
Section titled “この binding がしないこと”- PDF function はまだありません。 Python には WASM のような原理的制限はありませんが、現在
mdi.render_pdfは export されていません。Python 隣接 workflow の PDF は CLI を使ってください。 - 独自 grammar はありません。 CLI/Rust と差があれば短い wrapper か core のバグです。
- export profile の引数はまだありません。
render_epub/render_docxは現在 source だけを受け取ります。設定付き EPUB/DOCX の実装は既に Rust にあり、Python wrapper が profile と cover の引数をまだ公開していない状態です。
割注の自動組版
Section titled “割注の自動組版”分割規則は Rust が一元管理します。本文の50%の字級、固定2行、行間なしで表示します。先頭の断片には本文行の残り幅、後続には行全体の幅を指定できます。幅の単位は割注字級の半角emです。文字幅の推定であり、比例フォントの厳密な均衡は保証しません。
from mdi import layout_warichufragments = layout_warichu([{"type": "text", "value": "一二三四五六"}], 4, first_capacity=2)戻り値は lines、html、widths、overflow、hardBreakAfter、sources を含みます。path は入力配列からの子インデックス列、startUtf8 / endUtf8 は可視文字列内の半開UTF-8バイト範囲です。同一の group は書式境界をまたぐ書記素も分割しません。ルビ、縦中横、改行禁止は一体として扱います。明示改行を保ち、自動分割は正規MDIや平文に書き戻しません。静的HTML/EPUBは閲覧ソフトにより再配置が異なります。DOCXはネイティブの双行グループを使います。XMLやインポーターの検証をWordの描画実測とは記載しません。
Editorial comments in MDI 2.1
Section titled “Editorial comments in MDI 2.1”mdi.parse(source, include_comments=True)MDI 2.1 recognizes <!-- note --> in all documents, including declared 2.0 and unversioned source. Comments can be empty, multiline or Unicode; the nearest --> closes them and their contents are not interpreted. Code, front matter, link destinations and plain-text MDI parameters remain literal. Escape an opener as \<!--.
Source saving retains comments. Default parse/prepare/mdast APIs omit them with IR 1.0; { includeComments: true } returns positional comment nodes and IR 1.1. Both report syntax 2.1. Existing front-matter declarations are retained. Public body projections and layout exclude comments even with an inclusive tree, and their source-map runs preserve the gaps.
Every publication format always omits valid comments. This intentionally changes old 2.0 output that displayed them as HTML text. Unterminated comments remain literal and return mdi.comment.unterminated: export is allowed, so intended private text may be visible.
Use source serialization or an inclusive IR for lossless comment retention. A filtered external IR cannot restore omitted comments.
MIT License© 2026 Iktahana