@mdxld/jsx
v1.9.0
Published
MDX compilation and build tooling - tsup/vite/esbuild plugins for MDX files
Maintainers
Readme
@mdxld/jsx
Universal JSX runtime with pluggable output renderers. Write components once, render to any format.
Installation
pnpm add @mdxld/jsxOverview
@mdxld/jsx provides a unified JSX system that can render to multiple output formats:
| Entry Point | Output | Use Case |
|-------------|--------|----------|
| @mdxld/jsx/html | HTML string | SSR, static sites, email |
| @mdxld/jsx/dom | DOM nodes | Client-side hydration |
| @mdxld/jsx/react | React elements | React applications |
| @mdxld/jsx/preact | Preact VNodes | Preact applications |
| @mdxld/jsx/markdown | Markdown string | Docs, AI editing, content |
| @mdxld/jsx/json | JSON object | APIs, data exchange |
| @mdxld/jsx/jsonld | JSON-LD | SEO, linked data, Schema.org |
Quick Start
import { Entity, Property } from '@mdxld/jsx/primitives'
function Customer({ name, email, tier }) {
return (
<Entity name={name} type="Customer">
<Property name="email">{email}</Property>
<Property name="tier" default="free">{tier}</Property>
</Entity>
)
}
// Render to any format
import { renderToMarkdown } from '@mdxld/jsx/markdown'
import { renderToJSON } from '@mdxld/jsx/json'
import { renderToHTML } from '@mdxld/jsx/html'
renderToMarkdown(<Customer name="Acme" email="[email protected]" tier="pro" />)
// # Acme
// **Email:** [email protected]
// **Tier:** pro
renderToJSON(<Customer name="Acme" email="[email protected]" tier="pro" />)
// { name: "Acme", type: "Customer", email: "[email protected]", tier: "pro" }
renderToHTML(<Customer name="Acme" email="[email protected]" tier="pro" />)
// <article><h1>Acme</h1>...</article>Runtime Configuration
Configure the JSX runtime in tsconfig.json:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@mdxld/jsx/html"
}
}Or import directly:
import { jsx, Fragment } from '@mdxld/jsx/html'
import { jsx, Fragment } from '@mdxld/jsx/markdown'
import { jsx, Fragment } from '@mdxld/jsx/json'Output Runtimes
HTML (SSR)
Wraps hono/jsx for HTML string output:
import { renderToString } from '@mdxld/jsx/html'
const html = renderToString(<Customer {...data} />)
// <article class="customer"><h1>Acme</h1>...</article>DOM (Client)
Wraps hono/jsx/dom for client-side rendering:
import { render } from '@mdxld/jsx/dom'
render(<Customer {...data} />, document.getElementById('root'))React
Standard React JSX runtime:
import { jsx } from '@mdxld/jsx/react'
// Uses react/jsx-runtimePreact
Preact JSX runtime:
import { jsx } from '@mdxld/jsx/preact'
// Uses preactMarkdown
Renders JSX to Markdown strings:
import { renderToMarkdown, extractFromMarkdown } from '@mdxld/jsx/markdown'
// Render
const md = renderToMarkdown(<Customer {...data} />)
// Extract (bi-directional)
const obj = extractFromMarkdown(editedMarkdown, Customer)JSON
Renders JSX to JSON objects:
import { renderToJSON, extractFromJSON } from '@mdxld/jsx/json'
const json = renderToJSON(<Customer {...data} />)
const obj = extractFromJSON(jsonData, Customer)JSON-LD
Renders JSX to JSON-LD with Schema.org context:
import { renderToJSONLD } from '@mdxld/jsx/jsonld'
const jsonld = renderToJSONLD(<Customer {...data} />)
// { "@context": "https://schema.org", "@type": "Person", ... }Semantic Primitives
Core building blocks that know how to render to each format:
import {
// Structural
Document, // Root container
Entity, // Named thing with properties
Section, // Grouped content
Property, // Key-value pair
List, // Array of items
Table, // Tabular data
// Data Types
Text, // Plain text
Code, // Code block with language
Link, // URL reference
// Actions/API
Action, // Function/method definition
Argument, // Parameter
Returns, // Return type
Event, // Event definition
// Metadata
Type, // Type reference
Extends, // Inheritance
} from '@mdxld/jsx/primitives'Entity Example
<Entity name="Customer" plural="Customers" extends="Entity">
<Property name="id" type="string" required>
Unique identifier
</Property>
<Property name="email" type="string" required>
Primary email address
</Property>
<Action name="upgrade" returns="Customer">
<Argument name="tier" type="Tier" required />
</Action>
</Entity>→ Markdown:
# Customer (Customers)
**Extends:** Entity
## Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| id | string | ✓ | Unique identifier |
| email | string | ✓ | Primary email address |
## Actions
### upgrade
**Returns:** `Customer`
| Argument | Type | Required |
|----------|------|----------|
| tier | Tier | ✓ |→ JSON:
{
"name": "Customer",
"plural": "Customers",
"extends": "Entity",
"properties": [
{ "name": "id", "type": "string", "required": true, "description": "Unique identifier" }
],
"actions": [
{ "name": "upgrade", "returns": "Customer", "arguments": [{ "name": "tier", "type": "Tier", "required": true }] }
]
}→ JSON-LD:
{
"@context": "https://schema.org",
"@type": "Class",
"name": "Customer",
"subClassOf": { "@id": "Entity" }
}Composition
Templates compose like React components:
function StoryBrand({ name, hero, problem, guide }) {
return (
<Document name={name}>
<Hero {...hero} />
<Problem {...problem} />
<Guide {...guide} />
</Document>
)
}
function Hero({ persona, occupation, company }) {
return (
<Section name="hero" title="Hero">
<Property name="persona">{persona}</Property>
<Property name="occupation">{occupation}</Property>
<Property name="company">{company}</Property>
</Section>
)
}Bi-directional Extraction
Components define both rendering AND extraction:
import { renderToMarkdown, extractFromMarkdown } from '@mdxld/jsx/markdown'
// 1. Render to markdown
const markdown = renderToMarkdown(<Customer {...data} />)
// 2. User/AI edits the markdown
const edited = markdown.replace('pro', 'enterprise')
// 3. Extract back to object
const updated = extractFromMarkdown(edited, Customer)The component structure serves as the extraction schema.
MDX Compilation
Compile MDX files with JSX runtime support:
import { compileMDX } from '@mdxld/jsx'
const result = await compileMDX(mdxContent, {
jsx: 'html', // or 'react', 'preact', 'markdown', 'json'
})Build Plugins
// esbuild
import { mdxPlugin } from '@mdxld/jsx/esbuild'
// Vite
import { mdxVitePlugin } from '@mdxld/jsx/plugin'
// Rollup
import { mdxRollupPlugin } from '@mdxld/jsx/plugin'
// tsup
import { mdxTsupPlugin } from '@mdxld/jsx/plugin'JSX Presets
import { compileMDX, JSX_PRESETS } from '@mdxld/jsx'
// Use preset name
await compileMDX(content, { jsx: 'html' })
await compileMDX(content, { jsx: 'react' })
await compileMDX(content, { jsx: 'preact' })
await compileMDX(content, { jsx: 'markdown' })
// Or custom config
await compileMDX(content, {
jsx: { importSource: '@mdxld/jsx/html' }
})Exports
| Entry Point | Description |
|-------------|-------------|
| @mdxld/jsx | Core compiler, types, presets |
| @mdxld/jsx/html | HTML string renderer (hono/jsx) |
| @mdxld/jsx/dom | DOM renderer (hono/jsx/dom) |
| @mdxld/jsx/react | React JSX runtime |
| @mdxld/jsx/preact | Preact JSX runtime |
| @mdxld/jsx/markdown | Markdown renderer + extractor |
| @mdxld/jsx/json | JSON renderer + extractor |
| @mdxld/jsx/jsonld | JSON-LD renderer |
| @mdxld/jsx/primitives | Semantic primitive components |
| @mdxld/jsx/plugin | Vite/Rollup/tsup plugins |
| @mdxld/jsx/esbuild | esbuild plugin |
Related Packages
| Package | Description |
|---------|-------------|
| @mdxld/markdown | Standalone toMarkdown/fromMarkdown |
| @mdxld/json | Standalone toJSON/fromJSON/toJSONLD |
| @mdxld/html | Standalone toHTML/fromHTML |
| mdxld | Core MDX + Linked Data parser |
| @mdxld/extract | Template-based extraction |
License
MIT
