@open-press/core/mdx
MDX sources
MDX source registration is passed as a prop to <Press>. The engine reads sources to discover content files, compile blocks, and feed them into MdxArea slots — feeding the manuscript helpers, search/replace, and the comment-marker writer.
<Press sources={[...]}>
prop — an array, not the named-export record from v0.x. The codemod in v0.10 rewrites the old
shape. See <Press> for the prop reference.
Array of source registrations passed as a prop on <Press>. Each entry has an explicit id which becomes the MdxArea chainId, the Sections / Toc source key, and the search/replace scope label.
<Press sources={[
mdxSource({ id: "story", preset: "section-folders", root: "chapters" }),
]}> Multiple sources are allowed — each gets its own id. A document with a main body and a separate appendix typically declares two sources:
<Press
title="Paper"
page="a4"
sources={[
mdxSource({ id: "story", preset: "section-folders", root: "chapters" }),
mdxSource({ id: "appendix", preset: "section-folders", root: "appendix" }),
]}
>
<Sections source="story" />
<Sections source="appendix" />
</Press> The v0.x named-export shape. Removed in v1.0; the codemod migrates to the new array prop. Keys in the record become the source ids (now explicit via the id field).
// document/index.tsx (removed in v1.0)
export const sources = {
story: mdxSource({ preset: "section-folders", root: "chapters" }),
}; Register an MDX source tree. Returns the value you store in the sources object — the engine inspects the return value, not the function call itself.
import { mdxSource } from "@open-press/core/mdx"; mdxSource(options: MdxSourceOptions): SourceRegistration Options
| Name | Type | Default | Description |
|---|---|---|---|
id required | string | Stable identifier referenced by <MdxArea chainId>, <Sections source>, <Toc source>, and the search/replace CLI. In v0.x this was the key in the sources object; now it's an explicit field. | |
preset required | "section-folders" | "file-list" | section-folders walks <root>/<NN-slug>/content/*.mdx relative to the document file and produces one section per folder. file-list takes an explicit files array — useful when sections aren't folder-shaped. | |
root | string | Folder relative to the document file (where <Press> lives). Default "chapters" for section-folders. Ignored by file-list. | |
files | string[] | Required when preset: "file-list". Paths relative to the document file. |
press/
chapters/
01-intro/
content/
01-overview.mdx
02-context.mdx
02-methods/
content/
01-design.mdx
03-results/
content/
01-figures.mdx
02-tables.mdx
Each NN-slug folder maps to one section. Files inside content/ are read in
name order and concatenated into the section's MDX. The NN- prefix sets section order.
mdxSource({
preset: "file-list",
files: [
"intro.mdx",
"results.mdx",
"conclusion.mdx",
],
}); MDX content rules
Source MDX files must be block-only — JSX components live on their own line, not
inside paragraphs. The MDX compiler rejects mdxJsxTextElement nodes and reports the file
+ line, because measurement and pagination can only address block-level elements.
Some prose.
<TableCaption>Daily ridership</TableCaption>
| Day | Riders |
| --- | --- |
| Mon | 1,204 |
| Tue | 1,317 | Some prose with <Highlight>inline JSX</Highlight> inside a paragraph.
// ^^^^^^^ MDX compile error: block-only What sources unlock
- MdxArea —
chainId="story"pulls from the source registered asstory. - Manuscript helpers —
<Sections source="story" page={...} />iterates the section folders and emits one frame per section. - Search & replace — the
search/replaceCLI commands walk the registered files; unregistered files aren't reachable. - Inline editing — the workbench's source-edit endpoint resolves block ids back to source files via the same registration.
- Comment markers —
@openpress-commentmarkers are written into the source file the block came from.
What lives outside sources
- React components —
press/components/**/*.tsxis imported normally frompress/index.tsxand used inside MDX. The components folder is not part ofsourcesbecause nothing's paginated. - Media —
press/media/**is synced intopublic/openpress/media/at export. Reference media in MDX viamedia/<file>.png(relative) or/openpress/media/<file>.png(absolute). - Theme CSS —
press/theme/**is concatenated into the document stylesheet bundle by the build, not registered as a source.