MDX

repository·main·Indexed 12 days ago

https://github.com/mdx-js/mdx

A tool that allows the use of JSX components within Markdown. It includes the core @mdx-js/mdx compiler for transforming MDX syntax into executable JavaScript, as well as dedicated integrations such as @mdx-js/esbuild for esbuild, @mdx-js/loader for webpack, and @mdx-js/node-loader for Node.js environments.

Tokens
36.7K
Snippets
128
Records
206
Agent score
97%

What's inside MDX

  1. What is @mdx-js/mdx?

    main

    The @mdx-js/mdx package is the core MDX compiler. Its primary responsibilities are:

    1. Turning MDX content into JavaScript.
    2. Evaluating MDX code.

    When to use this package directly: Use this package when you need maximum control over the compilation process.

    When to use an integration instead: If you are using a bundler (Rollup, esbuild, webpack), a site builder (Next.js), or a build system (Vite), use the specific integration designed for that tool rather than calling this API directly.

  2. Overview of MDX packages

    main

    The MDX monorepo consists of the core compiler, a remark plugin for syntax support, and various integrations for bundlers and frontend frameworks. The primary packages include:

    • @mdx-js/mdx: The core MDX compiler.
    • remark-mdx: The remark plugin that enables support for MDX syntax.
    • Bundler/Framework Integrations: Various packages to integrate MDX into build tools and UI libraries, such as @mdx-js/esbuild, @mdx-js/rollup, @mdx-js/react, @mdx-js/preact, and @mdx-js/vue.
  3. What is MDX?

    main

    MDX is a format that allows you to use JSX in your markdown content. It enables you to import and embed interactive components (like charts, alerts, or custom UI elements) directly within markdown files.

    Key characteristics:

    • Blends Markdown and JSX: Use standard markdown for text and JSX for components.
    • Everything is a component: You can use existing components in MDX and even import other MDX files as components.
    • Customizable: You can map specific markdown constructs to custom components (e.g., replacing standard h1 with a custom MyHeading component).
    • No runtime: MDX is compiled to JavaScript during the build stage, meaning there is no heavy runtime overhead.
    • Framework agnostic: It compiles to JavaScript that can be used in any framework supporting JSX (React, Preact, Vue, etc.).
  4. How MDX works

    main

    MDX works by compiling MDX syntax into serialized JavaScript. An integration (like @mdx-js/rollup or @mdx-js/esbuild) transforms the MDX file into a JavaScript module that exports a default component (the content) and any other values defined via export statements.

    Key characteristics of the compiled output:

    • The content is exported as a default function (e.g., MDXContent).
    • JSX is compiled away into function calls (e.g., _jsx).
    • It is a complete module with imports and exports.
    • It is not coupled to React; it can be used with Preact, Vue, and other frameworks.
    export function Thing() {
      return <>World</>
    }
    
    # Hello <Thing />

    // Roughly becomes:

    export function Thing() {
      return <>World</>
    }
    
    export default function MDXContent(props) {
      return <h1>Hello <Thing /></h1>
    }
  5. Use adjacent block JSX and expressions in MDX

    main

    MDX 3 now supports placing block expressions immediately adjacent to block JSX tags without requiring a newline between the angle brackets and the braces. This resolves previous syntax errors.

    <style>{`
    
      h1 {
        color: blue;
      }
    
    `}</style>
  6. Use JSX and Markdown together in MDX v2

    main

    MDX v2 allows for more flexible JSX integration:

    • No blank lines required: You no longer need blank lines between JSX tags and markdown content.
    • Indentation: You can now indent both JSX and markdown content within parent tags.
    • Inlines vs Blocks:
      • If text and tags are on the same line, markdown is treated as "inlines" (e.g., <div># heading</div> is not a heading, but <div>*emphasis*</div> works).
      • If text and tags are on separate lines, markdown is treated as "blocks" and will produce elements like <p> tags.
    • Warning: MDX determines block status based on line breaks, not HTML semantics. Avoid nesting blocks incorrectly (e.g., putting a <p> inside an <h1>).
    <article>
      <hgroup>
        # This is a heading now, not code or plain text
      </hgroup>
      <section>
        ```js
        // if you do want code blocks, use fenced code
        ```
      </section>
    </article>
    <div>
      This is a `p`.
    </div>
  7. Use ESM exports as an alternative to frontmatter

    main

    MDX does not support YAML frontmatter by default because it follows standard CommonMark syntax. Instead, MDX provides a native way to define metadata using ESM export statements. These exports are available as named exports when you import the compiled MDX module in JavaScript.

    This approach is dynamic and allows you to use JavaScript logic (like string concatenation) within your metadata definitions.

    export const name = 'World'
    export const title = 'Hi, ' + name + '!'
    
    # {title}
    import * as Post from './example.mdx'
    
    console.log(Post.title) // Prints 'Hi, World!'
  8. MDX Syntax: JSX

    main

    MDX supports JSX, allowing you to use components directly within your content. Components can be imported via ESM, defined locally, or passed in via a provider.

    Usage Patterns:

    • Standard Components: <MyComponent id="123" />
    • Object Properties: <myComponents.thisOne />
    • Passing JSX as Props: <Component icon={<Icon />} />

    Note that the specific syntax for attributes (like className vs class) depends on the target framework (React, Vue, Preact, etc.) you are using with MDX.

    <MyComponent id="123" />
    
    <myComponents.thisOne />
    
    <Component
      open
      x={1}
      label={'this is a string, *not* markdown!'}
      icon={<Icon />}
    />
  9. Security considerations for MDX

    main

    MDX is a programming language. Because it allows executing code, it is unsafe if you do not trust the authors of the MDX files.

    Mitigation strategies:

    • Use <iframe sandbox> for web environments (though not 100% foolproof).
    • For Node.js, consider using vm2.
    • Sandbox the entire OS using Docker.
    • Implement rate limiting and process timeouts to prevent resource exhaustion.
  10. Understand MDX 2 syntax improvements

    main

    MDX 2 shifts the format closer to how JSX works to make it more intuitive. Key improvements include:

    • Improved Markdown in JSX: Markdown inlines (like emphasis) can now form between tags on the same line. Markdown blocks (like headings) can form if they are on their own line. Indentation is now allowed within JSX tags instead of automatically forming code blocks.
    • JavaScript Expressions: You can use JavaScript expressions directly within the MDX content, such as {2 * Math.PI} or complex logic like {new Intl.ListFormat('en').format(authors.map(d => d.name))}.
    • File Extension Handling: When using bundler integrations like @mdx-js/loader, @mdx-js/rollup, @mdx-js/esbuild, or @mdx-js/node-loader, the system distinguishes between formats based on extensions: .mdx files are treated as MDX, while .md files are treated as standard Markdown.
    export const authors = [
      {name: 'Jane', email: 'hi@jane.com'},
      {name: 'John', github: '@johno'}
    ]
    
    Written by: {new Intl.ListFormat('en').format(authors.map(d => d.name))}.
  11. MDX Syntax: Expressions

    main

    You can embed JavaScript expressions inside curly braces {}. These expressions can contain any JavaScript code that evaluates to something renderable. This includes complex logic using Immediately Invoked Function Expressions (IIFE).

    Two 🍰 is: {Math.PI * 2}
    
    {(function () {
      const guess = Math.random()
      if (guess > 0.66) {
        return <span style={{color: 'tomato'}}>Look at us.</span>
      }
      return <span>Not so much.</span>
    })()}
  12. Use JavaScript expressions in MDX

    main

    MDX v2 supports JavaScript expressions using curly braces {}. This can be used to embed logic or as an escape hatch to render raw strings or JSX without markdown interference.

    {
      <h1>
        This just JSX, these *asterisks* have no meaning.
      </h1>
    }
    
    This is just {'`text`'}, not code.