Export profiles
Prerequisites: Getting Started.
An export profile configures presentation — page size, fonts, margins, indentation, page numbers — for a specific output. It never changes MDI syntax or meaning; the same source with two different profiles produces two different-looking PDFs of the same document. The package is @illusions-lab/mdi-export-profile; resolveExportProfile validates every field and throws a descriptive Error rather than silently accepting malformed layout data (see below).
The schema
Section titled “The schema”{ "layout": { "system": "word" }, "metadata": { "title": "The Last Station", "author": "A Writer", "publisher": "Example Press", "identifier": "isbn:9780000000000" }, "typesetting": { "writingMode": "horizontal", "fontFamily": "Noto Serif JP", "textIndentEm": 1, "fullwidthSpaceIndent": false }, "pagination": { "pageSize": "A4", "landscape": false, "charactersPerLine": 40, "linesPerPage": 34, "margins": { "top": 25.4, "bottom": 25.4, "left": 25.4, "right": 25.4 }, "pageNumbers": { "enabled": true, "format": "simple", "position": "bottom-center" } }, "epub": { "chapterSplitLevel": "h1", "coverPath": "cover.png" }, "text": { "fullwidthSpaceIndent": true, "indentCount": 1 }}resolveExportProfile({}) is available for internal/default resolution, but every configured CLI or @illusions-lab/mdi export must state layout.system. Choose one contract: "japanese-publisher" for a strict, mirrored Japanese book grid, or "word" for flowing Word-style pages. They are intentionally not mixed.
| Field | Type | Default | Validation |
|---|---|---|---|
layout.system | "japanese-publisher" | "word" | publisher for internal resolution; required at configured-export boundaries | Selects the complete layout contract. |
layout.marginMode / bindingSide / gutter | "single"|"mirror" / "left"|"right" / mm | publisher: mirror, direction-dependent binding, 0 mm | word has no gutter and defaults to single margins. |
metadata.title/author/publisher/identifier/language/date | string | — | Must be a string if present. |
typesetting.writingMode | "horizontal" | "vertical" | "horizontal" | Must be exactly one of the two. |
typesetting.fontFamily | string | Mincho fallback stack | Must be a non-empty string; whitespace-only falls back to default. |
typesetting.textIndentEm | number | 1 | 0–4. |
typesetting.fullwidthSpaceIndent | boolean | false | — |
pagination.pageSize | one of PAGE_SIZES | publisher: "Shirokuban"; word: "A4" | Must be a key of the exported PAGE_DIMENSIONS map. |
pagination.landscape | boolean | false | — |
pagination.charactersPerLine / linesPerPage | number | publisher horizontal: 27×26; vertical: 40×30; word: informational | 10–400. |
pagination.gridMode | "strict" | "typographic" | publisher: strict; word: typographic | word rejects strict; strict rejects explicit line spacing. |
pagination.margins.{top,bottom,left,right} | number (mm) | publisher: 16.5/18/18/15.5; word: 25.4 each | Must leave printable width and height. |
pagination.pageNumbers.enabled | boolean | true | — |
pagination.pageNumbers.format | "simple" | "dash" | "fraction" | "simple" | Must be one of the three. |
pagination.pageNumbers.position | one of the six *-{left,center,right} combinations | "bottom-center" | Must be one of the six. |
epub.chapterSplitLevel | "h1" | "h2" | "h3" | "none" | "h1" | Must be one of the four. |
epub.coverPath | string (path, resolved relative to the --config file) | — | Must be .jpg/.jpeg/.png when used by the CLI. |
text.fullwidthSpaceIndent | boolean | false | — |
text.indentCount | number | 1 | 1–4. |
Any value outside these constraints — an unsupported pageSize, a charactersPerLine of 5, a writingMode of "rtl" — throws a specific Error naming the offending field, both from resolveExportProfile() directly and from parseExportProfileJson() (used by the CLI’s --config), rather than clamping or ignoring it silently.
Using it
Section titled “Using it”mdi build novel.mdi --to pdf --config novel.export.json -o novel.pdfmdi build novel.mdi --to docx --config novel.export.jsonmdi build novel.mdi --to epub --config novel.export.jsonmdi build novel.mdi --to txt-ruby --config novel.export.jsonimport { parseExportProfileJson, resolveExportProfile } from "@illusions-lab/mdi-export-profile";
const profile = parseExportProfileJson(await readFile("novel.export.json", "utf8"));const resolved = resolveExportProfile(profile); // every field filled in, fully validatedresolvePrintProfile(profile, sourceWritingMode) is the PDF/print convenience wrapper: a document’s front matter supplies the writing-mode default, while an explicit profile wins. It does not silently switch paper orientation.
Format support today
Section titled “Format support today”| Setting | TXT / txt-ruby | EPUB / DOCX | |
|---|---|---|---|
| Page geometry, fonts, page numbers | Yes | — | DOCX: Yes; EPUB uses typography but is reflowable |
| Metadata / writing mode | Yes | — | EPUB / DOCX: Yes |
| Full-width-space indent | Yes | Yes (1–4 spaces via text.indentCount) | EPUB / DOCX: Yes |
| Cover image, chapter split level | — | — | EPUB: Yes |
The adapters package Rust-owned parsed IR; layout policy remains outside the MDI parser. EPUB cannot promise fixed physical pages because it is reflowable.
Next steps
Section titled “Next steps”- Bindings: CLI —
--configin context. - Rust Core API status — exactly which renderer functions exist and what they currently accept.