Skip to content

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).

{
"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.

FieldTypeDefaultValidation
layout.system"japanese-publisher" | "word"publisher for internal resolution; required at configured-export boundariesSelects the complete layout contract.
layout.marginMode / bindingSide / gutter"single"|"mirror" / "left"|"right" / mmpublisher: mirror, direction-dependent binding, 0 mmword has no gutter and defaults to single margins.
metadata.title/author/publisher/identifier/language/datestringMust be a string if present.
typesetting.writingMode"horizontal" | "vertical""horizontal"Must be exactly one of the two.
typesetting.fontFamilystringMincho fallback stackMust be a non-empty string; whitespace-only falls back to default.
typesetting.textIndentEmnumber104.
typesetting.fullwidthSpaceIndentbooleanfalse
pagination.pageSizeone of PAGE_SIZESpublisher: "Shirokuban"; word: "A4"Must be a key of the exported PAGE_DIMENSIONS map.
pagination.landscapebooleanfalse
pagination.charactersPerLine / linesPerPagenumberpublisher horizontal: 27×26; vertical: 40×30; word: informational10400.
pagination.gridMode"strict" | "typographic"publisher: strict; word: typographicword 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 eachMust leave printable width and height.
pagination.pageNumbers.enabledbooleantrue
pagination.pageNumbers.format"simple" | "dash" | "fraction""simple"Must be one of the three.
pagination.pageNumbers.positionone 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.coverPathstring (path, resolved relative to the --config file)Must be .jpg/.jpeg/.png when used by the CLI.
text.fullwidthSpaceIndentbooleanfalse
text.indentCountnumber114.

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.

Terminal window
mdi build novel.mdi --to pdf --config novel.export.json -o novel.pdf
mdi build novel.mdi --to docx --config novel.export.json
mdi build novel.mdi --to epub --config novel.export.json
mdi build novel.mdi --to txt-ruby --config novel.export.json
import { 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 validated

resolvePrintProfile(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.

SettingPDFTXT / txt-rubyEPUB / DOCX
Page geometry, fonts, page numbersYesDOCX: Yes; EPUB uses typography but is reflowable
Metadata / writing modeYesEPUB / DOCX: Yes
Full-width-space indentYesYes (1–4 spaces via text.indentCount)EPUB / DOCX: Yes
Cover image, chapter split levelEPUB: 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.