unified

Project: syntax-tree/mdast-util-mdx-jsx

Package: mdast-util-mdx-jsx@1.1.0

  1. Dependents: 1
  2. mdast extension to parse and serialize MDX or MDX.js JSX
  1. util 137
  2. markdown 137
  3. utility 133
  4. unist 120
  5. mdast 89
  6. mdast-util 30
  7. mdx 30
  8. markup 18
  9. jsx 17
  10. extension 9
  11. mdxjs 8

mdast-util-mdx-jsx

Build Coverage Downloads Size Sponsors Backers Chat

Extension for mdast-util-from-markdown and/or mdast-util-to-markdown to support MDX (or MDX.js) JSX. When parsing (from-markdown), must be combined with micromark-extension-mdx-jsx.

This utility handles parsing and serializing. See micromark-extension-mdx-jsx for how the syntax works.

When to use this

Use mdast-util-mdx if you want all of MDX / MDX.js. Use this otherwise.

Install

This package is ESM only: Node 12+ is needed to use it and it must be imported instead of required.

npm:

npm install mdast-util-mdx-jsx

Use

Say we have an MDX.js file, example.mdx:

<Box>
  - a list
</Box>

<MyComponent {...props} />

<abbr title="Hypertext Markup Language">HTML</abbr> is a lovely language.

And our module, example.js, looks as follows:

import fs from 'node:fs'
import * as acorn from 'acorn'
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toMarkdown} from 'mdast-util-to-markdown'
import {mdxJsx} from 'micromark-extension-mdx-jsx'
import {mdxJsxFromMarkdown, mdxJsxToMarkdown} from 'mdast-util-mdx-jsx'

const doc = fs.readFileSync('example.mdx')

const tree = fromMarkdown(doc, {
  extensions: [mdxJsx({acorn: acorn, addResult: true})],
  mdastExtensions: [mdxJsxFromMarkdown]
})

console.log(tree)

const out = toMarkdown(tree, {extensions: [mdxJsxToMarkdown]})

console.log(out)

Now, running node example yields (positional info removed for brevity):

{
  type: 'root',
  children: [
    {
      type: 'mdxJsxFlowElement',
      name: 'Box',
      attributes: [],
      children: [
        {
          type: 'list',
          ordered: false,
          start: null,
          spread: false,
          children: [
            {
              type: 'listItem',
              spread: false,
              checked: null,
              children: [
                {type: 'paragraph', children: [{type: 'text', value: 'a list'}]}
              ]
            }
          ]
        }
      ]
    },
    {
      type: 'mdxJsxFlowElement',
      name: 'MyComponent',
      attributes: [
        {
          type: 'mdxJsxExpressionAttribute',
          value: '...props',
          data: {
            estree: {
              type: 'Program',
              body: [
                {
                  type: 'ExpressionStatement',
                  expression: {
                    type: 'ObjectExpression',
                    properties: [
                      {
                        type: 'SpreadElement',
                        argument: {type: 'Identifier', name: 'props'}
                      }
                    ]
                  }
                }
              ],
              sourceType: 'module'
            }
          }
        }
      ],
      children: []
    },
    {
      type: 'paragraph',
      children: [
        {
          type: 'mdxJsxTextElement',
          name: 'abbr',
          attributes: [
            {
              type: 'mdxJsxAttribute',
              name: 'title',
              value: 'Hypertext Markup Language'
            }
          ],
          children: [{type: 'text', value: 'HTML'}]
        },
        {type: 'text', value: ' is a lovely language.'}
      ]
    }
  ]
}
<Box>
  *   a list
</Box>

<MyComponent {...props}/>

<abbr title="Hypertext Markup Language">HTML</abbr> is a lovely language.

API

mdxJsxFromMarkdown

mdxJsxToMarkdown

Support MDX (or MDX.js) JSX. The exports are extensions, respectively for mdast-util-from-markdown and mdast-util-to-markdown.

When using the syntax extension with addResult, nodes will have a data.estree field set to an ESTree.

There are no options, but passing options.quote to mdast-util-to-markdown is honored for attributes.

this extension configures mdast-util-to-markdown with fences: true and resourceLink: true too, do not overwrite them!

Syntax tree

The following interfaces are added to mdast by this utility.

Nodes

MDXJsxFlowElement

interface MDXJsxFlowElement <: Parent {
  type: "mdxJsxFlowElement"
}

MDXJsxFlowElement includes MDXJsxElement

MDXJsxFlowElement (Parent) represents JSX in flow (block). It can be used where flow content is expected. It includes the mixin MDXJsxElement.

For example, the following markdown:

<w x="y">
  z
</w>

Yields:

{
  type: 'mdxJsxFlowElement',
  name: 'w',
  attributes: [{type: 'mdxJsxAttribute', name: 'x', value: 'y'}],
  children: [{type: 'paragraph', children: [{type: 'text', value: 'z'}]}]
}

MDXJsxTextElement

interface MDXJsxTextElement <: Parent {
  type: "mdxJsxTextElement"
}

MDXJsxTextElement includes MDXJsxElement

MDXJsxTextElement (Parent) represents JSX in text (span, inline). It can be used where phrasing content is expected. It includes the mixin MDXJsxElement.

For example, the following markdown:

a <b c>d</b> e.

Yields:

{
  type: 'mdxJsxTextElement',
  name: 'b',
  attributes: [{type: 'mdxJsxAttribute', name: 'c', value: null}],
  children: [{type: 'text', value: 'd'}]
}

Mixin

MDXJsxElement

interface mixin MDXJsxElement {
  name: string?
  attributes: [MDXJsxExpressionAttribute | MDXJsxAttribute]
}

interface MDXJsxExpressionAttribute <: Literal {
  type: "mdxJsxExpressionAttribute"
}

interface MDXJsxAttribute <: Node {
  type: "mdxJsxAttribute"
  name: string
  value: MDXJsxAttributeValueExpression | string?
}

interface MDXJsxAttributeValueExpression <: Literal {
  type: "mdxJsxAttributeValueExpression"
}

MDXJsxElement represents a JSX element.

The name field can be present and represents an identifier. Without name, the element represents a fragment, in which case no attributes must be present.

The attributes field represents information associated with the node. The value of the attributes field is a list of MDXJsxExpressionAttribute and MDXJsxAttribute nodes.

MDXJsxExpressionAttribute represents an expression (typically in a programming language) that when evaluated results in multiple attributes.

MDXJsxAttribute represents a single attribute. The name field must be present. The value field can be present, in which case it is either a string (a static value) or an expression (typically in a programming language) that when evaluated results in an attribute value.

Content model

FlowContent (MDX JSX)

type MDXJsxFlowContent = MDXJsxFlowElement | FlowContent

PhrasingContent (MDX JSX)

type MDXJsxPhrasingContent = MDXJsxTextElement | PhrasingContent

Contribute

See contributing.md in syntax-tree/.github for ways to get started. See support.md for ways to get help.

This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

License

MIT © Titus Wormer