unified

Project: syntax-tree/mdast-util-mdxjs-esm

Package: mdast-util-mdxjs-esm@1.3.0

  1. Dependents: 0
  2. mdast extension to parse and serialize MDX.js ESM (import/exports)
  1. util 147
  2. markdown 145
  3. utility 143
  4. unist 133
  5. mdast 90
  6. mdx 36
  7. mdast-util 31
  8. markup 19
  9. extension 9
  10. mdxjs 8
  11. export 4
  12. esm 3
  13. import 2

mdast-util-mdxjs-esm

Build Coverage Downloads Size Sponsors Backers Chat

mdast extensions to parse and serialize MDX ESM import/exports.

Contents

What is this?

This package contains extensions that add support for the ESM syntax enabled by MDX to mdast-util-from-markdown and mdast-util-to-markdown.

When to use this

These tools are all rather low-level. In most cases, you’d want to use remark-mdx with remark instead.

When you are working with syntax trees and want all of MDX, use mdast-util-mdx instead.

When working with mdast-util-from-markdown, you must combine this package with micromark-extension-mdxjs-esm.

Install

This package is ESM only. In Node.js (version 12.20+, 14.14+, or 16.0+), install with npm:

npm install mdast-util-mdxjs-esm

In Deno with esm.sh:

import {mdxjsEsmFromMarkdown, mdxjsEsmToMarkdown} from 'https://esm.sh/mdast-util-mdxjs-esm@1'

In browsers with esm.sh:

<script type="module">
  import {mdxjsEsmFromMarkdown, mdxjsEsmToMarkdown} from 'https://esm.sh/mdast-util-mdxjs-esm@1?bundle'
</script>

Use

Say our document example.mdx contains:

import a from 'b'
export const c = ''

d

…and our module example.js looks as follows:

import fs from 'node:fs/promises'
import * as acorn from 'acorn'
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toMarkdown} from 'mdast-util-to-markdown'
import {mdxjsEsm} from 'micromark-extension-mdxjs-esm'
import {mdxjsEsmFromMarkdown, mdxjsEsmToMarkdown} from 'mdast-util-mdxjs-esm'

const doc = await fs.readFile('example.mdx')

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

console.log(tree)

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

console.log(out)

…now running node example.js yields (positional info removed for brevity):

{
  type: 'root',
  children: [
    {
      type: 'mdxjsEsm',
      value: "import a from 'b'\nexport const c = ''",
      data: {
        estree: {
          type: 'Program',
          body: [
            {
              type: 'ImportDeclaration',
              specifiers: [
                {
                  type: 'ImportDefaultSpecifier',
                  local: {type: 'Identifier', name: 'a'}
                }
              ],
              source: {type: 'Literal', value: 'b', raw: "'b'"}
            },
            {
              type: 'ExportNamedDeclaration',
              declaration: {
                type: 'VariableDeclaration',
                declarations: [
                  {
                    type: 'VariableDeclarator',
                    id: {type: 'Identifier', name: 'c'},
                    init: {type: 'Literal', value: '', raw: "''"}
                  }
                ],
                kind: 'const'
              },
              specifiers: [],
              source: null
            }
          ],
          sourceType: 'module'
        }
      }
    },
    {type: 'paragraph', children: [{type: 'text', value: 'd'}]}
  ]
}
import a from 'b'
export const c = ''

d

API

This package exports the identifiers mdxjsEsmFromMarkdown and mdxjsEsmToMarkdown. There is no default export.

mdxjsEsmFromMarkdown

Extension for mdast-util-from-markdown.

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

mdxjsEsmToMarkdown

Extension for mdast-util-to-markdown.

Syntax tree

The following interfaces are added to mdast by this utility.

Nodes

MDXJSEsm

interface MDXJSEsm <: Literal {
  type: "mdxjsEsm"
}

MDXJSEsm (Literal) represents ESM import/exports embedded in MDX. It can be used where flow content is expected. Its content is represented by its value field.

For example, the following Markdown:

import a from 'b'

Yields:

{
  type: 'mdxjsEsm',
  value: 'import a from \'b\''
}

Content model

FlowContent (MDX.js ESM)

type FlowContentMdxjsEsm = MDXJSEsm | FlowContent

Note that when ESM is present, it can only exist as top-level content: if it has a parent, that parent must be Root.

Types

This package is fully typed with TypeScript. It exports the additional type MdxjsEsm.

It also registers the node types with @types/mdast. If you’re working with the syntax tree, make sure to import this utility somewhere in your types, as that registers the new node types in the tree.

/**
 * @typedef {import('mdast-util-mdxjs-esm')}
 */

import {visit} from 'unist-util-visit'

/** @type {import('mdast').Root} */
const tree = getMdastNodeSomeHow()

visit(tree, (node) => {
  // `node` can now be an ESM node.
})

Compatibility

Projects maintained by the unified collective are compatible with all maintained versions of Node.js. As of now, that is Node.js 12.20+, 14.14+, and 16.0+. Our projects sometimes work with older versions, but this is not guaranteed.

This plugin works with mdast-util-from-markdown version 1+ and mdast-util-to-markdown version 1+.

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