Avatar

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

  1. Introduction
  2. Text Formatting
  3. Headings
  4. Lists
  5. Code Examples
  6. Blockquotes
  7. Tables
  8. Links and Images
  9. Advanced MDX Features
  10. 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:

  1. Component Reusability: Write components once, use them everywhere
  2. Interactivity: Create engaging, interactive documentation
  3. Type Safety: Leverage TypeScript for better development experience
  4. Flexibility: Combine the best of both Markdown and React
  5. 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 code using 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 code inside
  • 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:

  1. First step
  2. Second step
  3. Third step
    1. Sub-step A
    2. Sub-step B
    3. Sub-step C
  4. Fourth step

Mixed Lists

You can mix ordered and unordered lists:

  1. First ordered item
    • Unordered sub-item
    • Another unordered sub-item
  2. Second ordered item
    1. Ordered sub-item
    2. 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 code within 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 | 0/mo0/mo | 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:

Alt text Alt text with title

Image with Link

You can make images clickable by wrapping them in a link:

Alt text


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:

b±b24ac2a\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

Complex Expressions

ex2dx=π\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}

Common Mathematical Notation Examples

Fractions

numeratordenominator\frac{numerator}{denominator}

Square roots

xorxn\sqrt{x} or \sqrt[n]{x}

Summation

i=1nxi\sum_{i=1}^{n} x_i

Integration

abf(x)dx\int_{a}^{b} f(x) dx

Greek letters

α,β,γ,Δ,Ω\alpha, \beta, \gamma, \Delta, \Omega

Matrices

abcd\begin{matrix} a & b \\ c & d \end{matrix}

Additional Resources