@mdxui/html
Render MDX to HTML
@mdxui/html
Render MDX documents to static HTML.
Installation
npm install @mdxui/htmlUsage
import { renderToHTML } from '@mdxui/html'
const mdx = `
# Hello World
This is **bold** text.
`
const html = await renderToHTML(mdx)
// <h1>Hello World</h1>
// <p>This is <strong>bold</strong> text.</p>Configuration
interface HTMLRenderOptions {
/** Custom components */
components?: Record<string, HTMLComponent>
/** CSS class names */
classNames?: Record<string, string>
/** Inline styles */
styles?: Record<string, CSSProperties>
/** ID prefix for headings */
idPrefix?: string
/** Generate wrapper element */
wrapper?: string | false
/** Plugins */
plugins?: Plugin[]
}Features
Custom Components
import { renderToHTML, registerComponent } from '@mdxui/html'
registerComponent('Callout', ({ type, title, children }) => `
<aside class="callout callout-${type}">
${title ? `<h4>${title}</h4>` : ''}
<div>${children}</div>
</aside>
`)
const html = await renderToHTML(`
<Callout type="warning" title="Caution">
Be careful with this operation.
</Callout>
`)CSS Classes
const html = await renderToHTML(mdx, {
classNames: {
h1: 'text-4xl font-bold tracking-tight',
h2: 'text-3xl font-semibold mt-8 mb-4',
p: 'text-gray-700 leading-relaxed mb-4',
a: 'text-blue-600 hover:underline',
ul: 'list-disc list-inside space-y-2',
ol: 'list-decimal list-inside space-y-2',
blockquote: 'border-l-4 border-gray-300 pl-4 italic',
code: 'bg-gray-100 px-1 py-0.5 rounded text-sm',
pre: 'bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto',
},
})Syntax Highlighting
import { renderToHTML, highlightPlugin } from '@mdxui/html'
const html = await renderToHTML(mdx, {
plugins: [
highlightPlugin({
theme: 'github-dark',
languages: ['javascript', 'typescript', 'bash'],
}),
],
})Heading IDs
const html = await renderToHTML(mdx, {
idPrefix: 'content-',
})
// # Getting Started
// becomes:
// <h1 id="content-getting-started">Getting Started</h1>Wrapper Element
const html = await renderToHTML(mdx, {
wrapper: 'article',
classNames: {
wrapper: 'prose prose-lg max-w-none',
},
})
// <article class="prose prose-lg max-w-none">...</article>Examples
Email Template
import { renderToHTML } from '@mdxui/html'
const emailHTML = await renderToHTML(newsletter, {
styles: {
h1: { fontSize: '24px', color: '#333', marginBottom: '16px' },
p: { fontSize: '16px', lineHeight: '1.6', color: '#555' },
a: { color: '#0066cc' },
},
wrapper: 'div',
classNames: {
wrapper: 'email-body',
},
})Blog Post
import { renderToHTML, highlightPlugin, tocPlugin } from '@mdxui/html'
const { html, toc } = await renderToHTML(post, {
plugins: [
highlightPlugin({ theme: 'github-light' }),
tocPlugin({ maxDepth: 3 }),
],
classNames: {
h1: 'text-4xl font-bold mb-6',
h2: 'text-2xl font-semibold mt-8 mb-4',
p: 'mb-4 leading-7',
},
})Documentation Page
const html = await renderToHTML(docs, {
components: {
Tabs: renderTabs,
Tab: renderTab,
Callout: renderCallout,
CodeBlock: renderCodeBlock,
},
classNames: {
h1: 'scroll-m-20 text-4xl font-extrabold tracking-tight',
h2: 'scroll-m-20 border-b pb-2 text-3xl font-semibold',
},
})Server Integration
Express
import express from 'express'
import { renderToHTML } from '@mdxui/html'
const app = express()
app.get('/docs/:slug', async (req, res) => {
const mdx = await loadContent(req.params.slug)
const html = await renderToHTML(mdx)
res.type('html').send(`
<!DOCTYPE html>
<html>
<head><title>Docs</title></head>
<body>${html}</body>
</html>
`)
})Static Generation
import { renderToHTML } from '@mdxui/html'
import { glob } from 'glob'
const files = await glob('content/**/*.mdx')
for (const file of files) {
const mdx = await readFile(file, 'utf-8')
const html = await renderToHTML(mdx)
const outPath = file
.replace('content/', 'dist/')
.replace('.mdx', '.html')
await writeFile(outPath, wrapInLayout(html))
}Streaming
import { renderToHTMLStream } from '@mdxui/html'
app.get('/stream/:slug', async (req, res) => {
const mdx = await loadContent(req.params.slug)
const stream = await renderToHTMLStream(mdx)
res.type('html')
stream.pipe(res)
})