Comprehensive MDX Format Guide and Testing Document
Welcome to the complete MDX format testing document. This guide demonstrates every major feature of MDX (Markdown + JSX) including standard Markdown syntax, code blocks, tables, lists, and more. This document serves as both a reference and a visual test for your MDX renderer.
Table of Contents
- Introduction
- Text Formatting
- Headings
- Lists
- Code Examples
- Blockquotes
- Tables
- Links and Images
- Advanced MDX Features
- Best Practices
Introduction
MDX is a powerful format that combines the simplicity of Markdown with the flexibility of JSX. It allows you to seamlessly import and use React components within your Markdown content, making it perfect for technical documentation, blog posts, and interactive content.
What is MDX?
MDX stands for Markdown + JSX. It's an authorable format that lets you write JSX embedded inside Markdown documents. This enables you to:
- Write long-form content with the ease of Markdown
- Import and use React components within your content
- Create interactive examples and demonstrations
- Build reusable content blocks
- Maintain type safety with TypeScript
Why Use MDX?
There are several compelling reasons to use MDX for your content:
- Component Reusability: Write components once, use them everywhere
- Interactivity: Create engaging, interactive documentation
- Type Safety: Leverage TypeScript for better development experience
- Flexibility: Combine the best of both Markdown and React
- Developer Experience: Use familiar tools and syntax
Text Formatting
MDX supports all standard Markdown text formatting options. Let's explore each one in detail.
Basic Text Styles
Here are the fundamental ways to style text in MDX:
- Bold text using double asterisks:
**bold** - Italic text using single asterisks:
*italic* - Bold and italic using triple asterisks:
***bold and italic*** - ~~Strikethrough~~ using double tildes:
~~strikethrough~~ Inline codeusing backticks:`code`
Combining Styles
You can also combine these styles in interesting ways:
- Bold with nested italic text
- Italic with nested bold text
- Bold with
inline codeinside Code with **bold** inside(though this may not work as expected)
Paragraphs and Line Breaks
In Markdown, paragraphs are separated by blank lines. This is a single paragraph that continues on multiple lines without blank lines in between, and it will be rendered as a continuous paragraph.
To create a new paragraph, simply add a blank line.
You can also use two spaces at the end of a line to create a line break without starting a new paragraph.
Headings
MDX supports six levels of headings, from H1 to H6:
Heading Level 1
Heading Level 2
Heading Level 3
Heading Level 4
Heading Level 5
Heading Level 6
Headings can also be created using underlines (for H1 and H2):
Alternative H1 Style
Alternative H2 Style
Best Practices for Headings
- Use only one H1 per document (typically the title)
- Maintain a logical hierarchy (don't skip levels)
- Keep headings concise and descriptive
- Use sentence case or title case consistently
Lists
Lists are essential for organizing information. MDX supports both ordered and unordered lists, with unlimited nesting.
Unordered Lists
You can create unordered lists using -, *, or +:
- First item
- Second item
- Third item
- Nested item 1
- Nested item 2
- Deeply nested item
- Another deeply nested item
- Back to second level
- Fourth item
Ordered Lists
Ordered lists use numbers followed by periods:
- First step
- Second step
- Third step
- Sub-step A
- Sub-step B
- Sub-step C
- Fourth step
Mixed Lists
You can mix ordered and unordered lists:
- First ordered item
- Unordered sub-item
- Another unordered sub-item
- Second ordered item
- Ordered sub-item
- Another ordered sub-item
- Mixed nested item
- Another mixed nested item
Task Lists
Some Markdown processors support task lists (GitHub-style):
- [x] Completed task
- [x] Another completed task
- [ ] Pending task
- [ ] Another pending task
- [x] Completed sub-task
- [ ] Pending sub-task
Definition Lists
Definition lists are great for glossaries:
Term 1 : Definition of term 1
Term 2 : Definition of term 2 : Alternative definition of term 2
Code Examples
Code blocks are crucial for technical documentation. MDX provides excellent syntax highlighting support.
Inline Code
Use single backticks for inline code: const greeting = 'Hello, World!'
You can also reference variables, functions(), or file-names.ts inline.
Basic Code Blocks
Use triple backticks for code blocks:
This is a plain code block without syntax highlighting.
It preserves formatting and indentation.TypeScript Examples
// TypeScript example with types
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user';
}
function getUserById(id: number): User | null {
// Implementation here
return null;
}
const user: User = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
role: 'admin',
};Python Examples
# Python example
from typing import List, Optional
from dataclasses import dataclass
@dataclass
class User:
id: int
name: str
email: str
is_active: bool = True
def get_active_users(users: List[User]) -> List[User]:
"""Filter and return only active users."""
return [user for user in users if user.is_active]
def find_user_by_email(users: List[User], email: str) -> Optional[User]:
"""Find a user by their email address."""
for user in users:
if user.email == email:
return user
return None
# Example usage
users = [
User(1, "Alice", "alice@example.com"),
User(2, "Bob", "bob@example.com", False),
User(3, "Charlie", "charlie@example.com"),
]
active_users = get_active_users(users)
user = find_user_by_email(users, "alice@example.com")Blockquotes
Blockquotes are perfect for highlighting important information, quotes, or callouts.
Basic Blockquote
This is a simple blockquote. It's great for highlighting important information or including quotes from other sources.
Nested Blockquotes
This is the outer blockquote.
This is a nested blockquote.
And this is a deeply nested blockquote.
Blockquotes with Multiple Paragraphs
This is the first paragraph of the blockquote.
This is the second paragraph of the blockquote. You can include multiple paragraphs within a single blockquote by using blank lines with the
>character.This is the third paragraph.
Blockquotes with Other Elements
Heading in Blockquote
You can include formatted text, italics, and even
codewithin blockquotes.
- List item 1
- List item 2
- List item 3
// Even code blocks! console.log('Hello from blockquote');
Different Types of Callouts
Note: This is an informational note that provides additional context.
Warning: This is a warning message that highlights potential issues.
Tip: This is a helpful tip that provides useful advice.
Important: This is critical information that should not be overlooked.
Tables
Tables are excellent for presenting structured data. MDX supports GitHub-flavored Markdown tables.
Basic Table
| Name | Age | Occupation | |---------|-----|-------------| | Alice | 28 | Developer | | Bob | 32 | Designer | | Charlie | 25 | Product Manager |
Table with Alignment
| Left Aligned | Center Aligned | Right Aligned | |:-------------|:--------------:|--------------:| | Left | Center | Right | | Text | Text | Text | | More | Data | Here |
Complex Table
| Feature | Free | Pro | Enterprise | |---------|:----:|:---:|:----------:| | Users | 5 | 25 | Unlimited | | Storage | 10 GB | 100 GB | Unlimited | | Support | Email | Priority | 24/7 Phone | | API Access | ❌ | ✅ | ✅ | | Custom Domain | ❌ | ✅ | ✅ | | Analytics | Basic | Advanced | Custom | | Price | 29/mo | Contact Us |
Table with Code
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /api/users | Retrieve all users |
| GET | /api/users/:id | Retrieve a specific user |
| POST | /api/users | Create a new user |
| PUT | /api/users/:id | Update a user |
| DELETE | /api/users/:id | Delete a user |
Comparison Table
| Feature | React | Vue | Angular | Svelte | |---------|-------|-----|---------|--------| | Learning Curve | Moderate | Easy | Steep | Easy | | Performance | Excellent | Excellent | Good | Excellent | | Bundle Size | Medium | Small | Large | Tiny | | TypeScript | ✅ | ✅ | ✅ (Built-in) | ✅ | | Community | Huge | Large | Large | Growing | | Backed By | Meta | Independent | Google | Independent |
Links and Images
Basic Links
Here's a link to Google.
You can also use reference-style links like this.
Links with Titles
This is a link with a title: MDN Web Docs.
Automatic Links
URLs and email addresses can be automatically turned into links:
- https://www.github.com
- contact@example.com
Internal Links
Image Syntax
Images in Markdown use a similar syntax to links:
![]()
Image with Link
You can make images clickable by wrapping them in a link:
Advanced MDX Features
MDX goes beyond standard Markdown by allowing you to use JSX and React components directly in your content.
Importing Components
In MDX, you can import and use React components:
import { CustomComponent } from '@/components/CustomComponent'
<CustomComponent prop1="value1" prop2="value2" />Inline JSX
You can write JSX directly in your MDX:
<div className="custom-wrapper">
<h3>Custom Heading</h3>
<p>This is JSX content!</p>
</div>Using JavaScript Expressions
MDX supports JavaScript expressions:
The current year is {new Date().getFullYear()}.
Random number: {Math.floor(Math.random() * 100)}Component Props
You can pass props to components, including functions:
<Button
onClick={() => alert('Clicked!')}
variant="primary"
size="large"
>
Click Me
</Button>Conditional Rendering
{true && <p>This will be rendered</p>}
{false && <p>This will not be rendered</p>}
{condition ? <ComponentA /> : <ComponentB />}Mapping Over Arrays
{['React', 'Vue', 'Angular', 'Svelte'].map((framework) => (
<Badge key={framework}>{framework}</Badge>
))}Advanced Patterns
Custom MDX Components
You can replace default Markdown elements with custom components:
// mdx-components.tsx
import type { MDXComponents } from 'mdx/types'
import { Code } from '@/components/Code'
import { Heading } from '@/components/Heading'
import { Image } from '@/components/Image'
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
h1: (props) => <Heading level={1} {...props} />,
h2: (props) => <Heading level={2} {...props} />,
h3: (props) => <Heading level={3} {...props} />,
code: (props) => <Code {...props} />,
img: (props) => <Image {...props} />,
...components,
}
}Syntax Highlighting
For advanced syntax highlighting, you can use libraries like Shiki or Prism:
import { getHighlighter } from 'shiki'
export async function highlightCode(code: string, lang: string) {
const highlighter = await getHighlighter({
themes: ['github-dark', 'github-light'],
langs: ['javascript', 'typescript', 'jsx', 'tsx', 'python', 'rust'],
})
return highlighter.codeToHtml(code, {
lang,
themes: {
light: 'github-light',
dark: 'github-dark',
},
})
}Frontmatter Processing
Process frontmatter metadata in your MDX files:
interface FrontMatter {
title: string
description: string
date: string
author: string
tags: string[]
published: boolean
}
export function processFrontMatter(frontmatter: FrontMatter) {
return {
...frontmatter,
date: new Date(frontmatter.date),
tags: frontmatter.tags.map(tag => tag.toLowerCase()),
}
}Dynamic Content Loading
Load MDX content dynamically:
import fs from 'fs/promises'
import path from 'path'
import matter from 'gray-matter'
export async function getMDXContent(slug: string) {
const filePath = path.join(process.cwd(), 'content', `${slug}.mdx`)
const source = await fs.readFile(filePath, 'utf-8')
const { content, data } = matter(source)
return {
content,
frontmatter: data,
}
}
export async function getAllPosts() {
const contentDir = path.join(process.cwd(), 'content')
const files = await fs.readdir(contentDir)
const posts = await Promise.all(
files
.filter(file => file.endsWith('.mdx'))
.map(async file => {
const slug = file.replace(/\.mdx$/, '')
const content = await getMDXContent(slug)
return { slug, ...content }
})
)
return posts.sort((a, b) => {
return new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime()
})
}Mathematical Expressions
If your MDX setup supports math (via remark-math or KaTeX), you can include mathematical expressions. Here are examples of how to write them:
Inline Math
For inline math, you would typically use single dollar signs or parentheses notation:
Inline math: $E = mc^2$ or \(E = mc^2\)Block Math
For display math blocks, use double dollar signs or bracket notation: