367 lines
9.8 KiB
Markdown
367 lines
9.8 KiB
Markdown
![]() |
# micromark-extension-mdxjs-esm
|
|||
|
|
|||
|
[![Build][build-badge]][build]
|
|||
|
[![Coverage][coverage-badge]][coverage]
|
|||
|
[![Downloads][downloads-badge]][downloads]
|
|||
|
[![Size][size-badge]][size]
|
|||
|
[![Sponsors][sponsors-badge]][collective]
|
|||
|
[![Backers][backers-badge]][collective]
|
|||
|
[![Chat][chat-badge]][chat]
|
|||
|
|
|||
|
[micromark][] extension to support [MDX][mdxjs] ESM (`import x from 'y'`).
|
|||
|
|
|||
|
## Contents
|
|||
|
|
|||
|
* [What is this?](#what-is-this)
|
|||
|
* [When to use this](#when-to-use-this)
|
|||
|
* [Install](#install)
|
|||
|
* [Use](#use)
|
|||
|
* [API](#api)
|
|||
|
* [`mdxjsEsm(options)`](#mdxjsesmoptions)
|
|||
|
* [`Options`](#options)
|
|||
|
* [Authoring](#authoring)
|
|||
|
* [Syntax](#syntax)
|
|||
|
* [Errors](#errors)
|
|||
|
* [Could not parse import/exports with acorn: $error](#could-not-parse-importexports-with-acorn-error)
|
|||
|
* [Unexpected `$type` in code: only import/exports are supported](#unexpected-type-in-code-only-importexports-are-supported)
|
|||
|
* [Tokens](#tokens)
|
|||
|
* [Types](#types)
|
|||
|
* [Compatibility](#compatibility)
|
|||
|
* [Security](#security)
|
|||
|
* [Related](#related)
|
|||
|
* [Contribute](#contribute)
|
|||
|
* [License](#license)
|
|||
|
|
|||
|
## What is this?
|
|||
|
|
|||
|
This package contains an extension that adds support for the ESM syntax enabled
|
|||
|
by [MDX][mdxjs] to [`micromark`][micromark].
|
|||
|
These extensions are used inside MDX.
|
|||
|
It matches how imports and exports work in JavaScript through acorn.
|
|||
|
|
|||
|
This package is aware of JavaScript syntax.
|
|||
|
|
|||
|
## When to use this
|
|||
|
|
|||
|
This project is useful when you want to support ESM in markdown.
|
|||
|
|
|||
|
You can use this extension when you are working with [`micromark`][micromark].
|
|||
|
To support all MDX features, use
|
|||
|
[`micromark-extension-mdxjs`][micromark-extension-mdxjs] instead.
|
|||
|
|
|||
|
When you need a syntax tree, combine this package with
|
|||
|
[`mdast-util-mdxjs-esm`][mdast-util-mdxjs-esm].
|
|||
|
|
|||
|
All these packages are used in [`remark-mdx`][remark-mdx], which focusses on
|
|||
|
making it easier to transform content by abstracting these internals away.
|
|||
|
|
|||
|
When you are using [`mdx-js/mdx`][mdxjs], all of this is already included.
|
|||
|
|
|||
|
## Install
|
|||
|
|
|||
|
This package is [ESM only][esm].
|
|||
|
In Node.js (version 16+), install with [npm][]:
|
|||
|
|
|||
|
```sh
|
|||
|
npm install micromark-extension-mdxjs-esm
|
|||
|
```
|
|||
|
|
|||
|
In Deno with [`esm.sh`][esmsh]:
|
|||
|
|
|||
|
```js
|
|||
|
import {mdxjsEsm} from 'https://esm.sh/micromark-extension-mdxjs-esm@1'
|
|||
|
```
|
|||
|
|
|||
|
In browsers with [`esm.sh`][esmsh]:
|
|||
|
|
|||
|
```html
|
|||
|
<script type="module">
|
|||
|
import {mdxjsEsm} from 'https://esm.sh/micromark-extension-mdxjs-esm@1?bundle'
|
|||
|
</script>
|
|||
|
```
|
|||
|
|
|||
|
## Use
|
|||
|
|
|||
|
```js
|
|||
|
import {Parser} from 'acorn'
|
|||
|
import acornJsx from 'acorn-jsx'
|
|||
|
import {micromark} from 'micromark'
|
|||
|
import {mdxjsEsm} from 'micromark-extension-mdxjs-esm'
|
|||
|
|
|||
|
const acorn = Parser.extend(acornJsx())
|
|||
|
|
|||
|
const output = micromark('import a from "b"\n\n# c', {
|
|||
|
extensions: [mdxjsEsm({acorn})]
|
|||
|
})
|
|||
|
|
|||
|
console.log(output)
|
|||
|
```
|
|||
|
|
|||
|
Yields:
|
|||
|
|
|||
|
```html
|
|||
|
<h1>c</h1>
|
|||
|
```
|
|||
|
|
|||
|
…which is useless: go to a syntax tree with
|
|||
|
[`mdast-util-from-markdown`][mdast-util-from-markdown] and
|
|||
|
[`mdast-util-mdxjs-esm`][mdast-util-mdxjs-esm] instead.
|
|||
|
|
|||
|
## API
|
|||
|
|
|||
|
This package exports the identifier [`mdxjsEsm`][api-mdxjs-esm].
|
|||
|
There is no default export.
|
|||
|
|
|||
|
The export map supports the [`development` condition][development].
|
|||
|
Run `node --conditions development module.js` to get instrumented dev code.
|
|||
|
Without this condition, production code is loaded.
|
|||
|
|
|||
|
### `mdxjsEsm(options)`
|
|||
|
|
|||
|
Create an extension for `micromark` to enable MDX ESM syntax.
|
|||
|
|
|||
|
###### Parameters
|
|||
|
|
|||
|
* `options` ([`Options`][api-options], required)
|
|||
|
— configuration
|
|||
|
|
|||
|
###### Returns
|
|||
|
|
|||
|
Extension for `micromark` that can be passed in `extensions` to enable MDX
|
|||
|
ESM syntax ([`Extension`][micromark-extension]).
|
|||
|
|
|||
|
### `Options`
|
|||
|
|
|||
|
Configuration (TypeScript type).
|
|||
|
|
|||
|
###### Fields
|
|||
|
|
|||
|
* `acorn` ([`Acorn`][acorn], required)
|
|||
|
— acorn parser to use
|
|||
|
* `acornOptions` ([`AcornOptions`][acorn-options], default:
|
|||
|
`{ecmaVersion: 2020, locations: true, sourceType: 'module'}`)
|
|||
|
— configuration for acorn; all fields except `locations` can be set
|
|||
|
* `addResult` (`boolean`, default: `false`)
|
|||
|
— whether to add `estree` fields to tokens with results from acorn
|
|||
|
|
|||
|
## Authoring
|
|||
|
|
|||
|
When authoring markdown with ESM, make sure to follow export and import
|
|||
|
statements with blank lines before more markdown.
|
|||
|
|
|||
|
All valid imports and exports are supported, depending on what the given acorn
|
|||
|
instance and configuration supports.
|
|||
|
|
|||
|
When the lowercase strings `export` or `import` are found, followed by a space,
|
|||
|
we expect JavaScript.
|
|||
|
Otherwise, like normal in markdown, we exit and it’ll end up as a paragraph.
|
|||
|
We continue parsing until we find a blank line.
|
|||
|
At that point, we parse with acorn: it if parses, we found our block.
|
|||
|
Otherwise, if parsing failed at the last character, we assume it’s a blank line
|
|||
|
in code: we continue on until the next blank line and try again.
|
|||
|
Otherwise, the acorn error is thrown.
|
|||
|
|
|||
|
Some examples of valid export and import statements:
|
|||
|
|
|||
|
```js
|
|||
|
import a from 'b'
|
|||
|
import * as a from 'b'
|
|||
|
import {a} from 'b'
|
|||
|
import {a as b} from 'c'
|
|||
|
import a, {b as c} from 'd'
|
|||
|
import a, * as b from 'c'
|
|||
|
import 'a'
|
|||
|
|
|||
|
export var a = ''
|
|||
|
export const a = ''
|
|||
|
export let a = ''
|
|||
|
export var a, b
|
|||
|
export var a = 'a', b = 'b'
|
|||
|
export function a() {}
|
|||
|
export class a {}
|
|||
|
export var {a} = {}
|
|||
|
export var {a: b} = {}
|
|||
|
export var [a] = []
|
|||
|
export default a = 1
|
|||
|
export default function a() {}
|
|||
|
export default class a {}
|
|||
|
export * from 'a'
|
|||
|
export * as a from 'b'
|
|||
|
export {a} from 'b'
|
|||
|
export {a as b} from 'c'
|
|||
|
export {default} from 'b'
|
|||
|
export {default as a, b} from 'c'
|
|||
|
|
|||
|
{/* Blank lines are supported in expressions: */}
|
|||
|
|
|||
|
export function a() {
|
|||
|
|
|||
|
return 'b'
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
{/* A blank line must be used after import/exports: this is incorrect! */}
|
|||
|
|
|||
|
import a from 'b'
|
|||
|
## Hello, world!
|
|||
|
```
|
|||
|
|
|||
|
## Syntax
|
|||
|
|
|||
|
ESM forms with the following BNF:
|
|||
|
|
|||
|
```bnf
|
|||
|
; Restriction: the entire construct must be valid JavaScript.
|
|||
|
mdx_esm ::= word ' ' *line *(eol *line)
|
|||
|
|
|||
|
word ::= 'e' 'x' 'p' 'o' 'r' 't' | 'i' 'm' 'p' 'o' 'r' 't'
|
|||
|
```
|
|||
|
|
|||
|
This construct must be followed by a blank line or eof (end of file).
|
|||
|
|
|||
|
## Errors
|
|||
|
|
|||
|
### Could not parse import/exports with acorn: $error
|
|||
|
|
|||
|
This error occurs if acorn crashes (source: `micromark-extension-mdxjs-esm`,
|
|||
|
rule id: `acorn`).
|
|||
|
For example:
|
|||
|
|
|||
|
```js
|
|||
|
import 1/1
|
|||
|
```
|
|||
|
|
|||
|
### Unexpected `$type` in code: only import/exports are supported
|
|||
|
|
|||
|
This error occurs when a non-ESM construct is found (source:
|
|||
|
`micromark-extension-mdxjs-esm`, rule id: `non-esm`).
|
|||
|
For example:
|
|||
|
|
|||
|
```js
|
|||
|
export var a = 1
|
|||
|
var b
|
|||
|
```
|
|||
|
|
|||
|
## Tokens
|
|||
|
|
|||
|
An `mdxjsEsm` token is used to reflect the block of import/exports in markdown.
|
|||
|
|
|||
|
It includes:
|
|||
|
|
|||
|
* `lineEnding` for the `\r`, `\n`, and `\r\n`
|
|||
|
* `lineEndingBlank` for the same characters but when after potential
|
|||
|
whitespace and another line ending
|
|||
|
* `whitespace` for markdown spaces and tabs in blank lines
|
|||
|
* `mdxjsEsmData` for any character in a line of `mdxjsEsm`
|
|||
|
|
|||
|
## Types
|
|||
|
|
|||
|
This package is fully typed with [TypeScript][].
|
|||
|
It exports the additional type [`Options`][api-options].
|
|||
|
|
|||
|
## Compatibility
|
|||
|
|
|||
|
Projects maintained by the unified collective are compatible with all maintained
|
|||
|
versions of Node.js.
|
|||
|
As of now, that is Node.js 16+.
|
|||
|
Our projects sometimes work with older versions, but this is not guaranteed.
|
|||
|
|
|||
|
These extensions work with `micromark` version 3+.
|
|||
|
|
|||
|
## Security
|
|||
|
|
|||
|
This package is safe.
|
|||
|
|
|||
|
## Related
|
|||
|
|
|||
|
* [`micromark-extension-mdxjs`][micromark-extension-mdxjs]
|
|||
|
— support all MDX syntax
|
|||
|
* [`mdast-util-mdxjs-esm`][mdast-util-mdxjs-esm]
|
|||
|
— support MDX ESM in mdast
|
|||
|
* [`remark-mdx`][remark-mdx]
|
|||
|
— support all MDX syntax in remark
|
|||
|
|
|||
|
## Contribute
|
|||
|
|
|||
|
See [`contributing.md` in `micromark/.github`][contributing] for ways to get
|
|||
|
started.
|
|||
|
See [`support.md`][support] for ways to get help.
|
|||
|
|
|||
|
This project has a [code of conduct][coc].
|
|||
|
By interacting with this repository, organization, or community you agree to
|
|||
|
abide by its terms.
|
|||
|
|
|||
|
## License
|
|||
|
|
|||
|
[MIT][license] © [Titus Wormer][author]
|
|||
|
|
|||
|
<!-- Definitions -->
|
|||
|
|
|||
|
[build-badge]: https://github.com/micromark/micromark-extension-mdxjs-esm/workflows/main/badge.svg
|
|||
|
|
|||
|
[build]: https://github.com/micromark/micromark-extension-mdxjs-esm/actions
|
|||
|
|
|||
|
[coverage-badge]: https://img.shields.io/codecov/c/github/micromark/micromark-extension-mdxjs-esm.svg
|
|||
|
|
|||
|
[coverage]: https://codecov.io/github/micromark/micromark-extension-mdxjs-esm
|
|||
|
|
|||
|
[downloads-badge]: https://img.shields.io/npm/dm/micromark-extension-mdxjs-esm.svg
|
|||
|
|
|||
|
[downloads]: https://www.npmjs.com/package/micromark-extension-mdxjs-esm
|
|||
|
|
|||
|
[size-badge]: https://img.shields.io/bundlephobia/minzip/micromark-extension-mdxjs-esm.svg
|
|||
|
|
|||
|
[size]: https://bundlephobia.com/result?p=micromark-extension-mdxjs-esm
|
|||
|
|
|||
|
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
|
|||
|
|
|||
|
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
|
|||
|
|
|||
|
[collective]: https://opencollective.com/unified
|
|||
|
|
|||
|
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
|
|||
|
|
|||
|
[chat]: https://github.com/micromark/micromark/discussions
|
|||
|
|
|||
|
[npm]: https://docs.npmjs.com/cli/install
|
|||
|
|
|||
|
[esmsh]: https://esm.sh
|
|||
|
|
|||
|
[license]: license
|
|||
|
|
|||
|
[author]: https://wooorm.com
|
|||
|
|
|||
|
[contributing]: https://github.com/micromark/.github/blob/HEAD/contributing.md
|
|||
|
|
|||
|
[support]: https://github.com/micromark/.github/blob/HEAD/support.md
|
|||
|
|
|||
|
[coc]: https://github.com/micromark/.github/blob/HEAD/code-of-conduct.md
|
|||
|
|
|||
|
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
|||
|
|
|||
|
[typescript]: https://www.typescriptlang.org
|
|||
|
|
|||
|
[development]: https://nodejs.org/api/packages.html#packages_resolving_user_conditions
|
|||
|
|
|||
|
[micromark]: https://github.com/micromark/micromark
|
|||
|
|
|||
|
[micromark-extension]: https://github.com/micromark/micromark#syntaxextension
|
|||
|
|
|||
|
[micromark-extension-mdxjs]: https://github.com/micromark/micromark-extension-mdxjs
|
|||
|
|
|||
|
[mdast-util-mdxjs-esm]: https://github.com/syntax-tree/mdast-util-mdxjs-esm
|
|||
|
|
|||
|
[mdast-util-from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
|
|||
|
|
|||
|
[remark-mdx]: https://mdxjs.com/packages/remark-mdx/
|
|||
|
|
|||
|
[mdxjs]: https://mdxjs.com
|
|||
|
|
|||
|
[acorn]: https://github.com/acornjs/acorn
|
|||
|
|
|||
|
[acorn-options]: https://github.com/acornjs/acorn/blob/96c721dbf89d0ccc3a8c7f39e69ef2a6a3c04dfa/acorn/dist/acorn.d.ts#L16
|
|||
|
|
|||
|
[api-mdxjs-esm]: #mdxjsesmoptions
|
|||
|
|
|||
|
[api-options]: #options
|