MDX
ironmark compiles MDX, which is Markdown with JSX tags, expressions in braces and import/export, to JSX. It is off by default (enableMdx / enable_mdx) and needs no extra dependencies.
- To import
.mdor.mdxfiles in an app, add one of the build tool plugins. mdxToJsxitself returns a JavaScript module that still contains JSX, for your own JSX transform (esbuild, Babel, SWC, Oxc, TypeScript).
Quick start
import { mdxToJsx } from "ironmark";
const { esm, jsx, module } = mdxToJsx(`import { Chart } from './chart.js'
export const year = 2026
# Report {year}
<Chart data={[1, 2]} />`);use ironmark::{render_jsx, ParseOptions};
let out = render_jsx("import X from './x'\n\n# Hi {props.name}\n\n<X />", &ParseOptions::default()).unwrap();
// out.esm == "import X from './x'"
// out.jsx == "<>\n<h1>Hi {props.name}</h1>\n<X />\n</>"
let module = out.to_module(); // ESM + `export default function MDXContent(props) { … }`render_jsx / mdxToJsx turn on enable_mdx themselves. Every other option (tables, task lists, highlight, …) applies as usual.
Plain Markdown to JSX
To turn a plain .md file into a component, compile it without MDX syntax: braces and import lines stay text, raw HTML is rewritten as JSX (class becomes className, void tags self-close) and HTML comments are dropped.
mdxToJsx("# Price {per month}", { markdown: true }).jsx;
// "<>\n<h1>Price {per month}</h1>\n</>"
ironmark.parse(source).jsx({ markdown: true, components: true });use ironmark::{render_markdown_jsx, JsxOptions, ParseOptions};
let out = render_markdown_jsx("# Price {per month}", &ParseOptions::default(), &JsxOptions::default()).unwrap();Raw HTML must still nest: an unclosed <div> is a compile error, as in MDX.
Output
| Field (JS) | Rust | Contents |
|---|---|---|
esm | esm | Top-level import/export statements, in document order |
jsx | jsx | The document body as one JSX fragment (<>…</>) |
module | to_module() | esm plus export default function MDXContent(props): import this |
| — | elements, references | Markdown tags routed through _components, and components used but not declared |
Markdown becomes plain JSX elements (<h1>, <p>, <pre><code className="language-js">). Code block content becomes a JS string, so braces and whitespace survive. Braces in text are escaped to { / }.
Next
- Syntax: what MDX accepts and how it differs from Markdown.
- Components: replace Markdown tags and pass components through props or a provider.
- Other renderers: what HTML, AST and ANSI output do with MDX.
Examples
examples/mdx:cargo run --example mdxprints the compiled module (--componentsand--providerfor the other modes), and a Vite + React app renders the sameGuide.mdxthroughironmark/vite.- The playground has an MDX option with a multi-file workspace (
.mdx,.jsx,.js), a live React preview and a JSX output tab.