Socket
Socket
Sign inDemoInstall

mdast-util-mdx-jsx

Package Overview
Dependencies
Maintainers
2
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mdast-util-mdx-jsx - npm Package Compare versions

Comparing version 1.2.0 to 2.0.0

lib/complex-types.d.ts

55

index.d.ts

@@ -1,50 +0,9 @@

/** @type {FromMarkdownExtension} */
export const mdxJsxFromMarkdown: FromMarkdownExtension
/** @type {ToMarkdownExtension} */
export const mdxJsxToMarkdown: ToMarkdownExtension
export type Literal = import('mdast').Literal
export type Parent = import('mdast').Parent
export type FromMarkdownExtension = import('mdast-util-from-markdown').Extension
export type FromMarkdownHandle = import('mdast-util-from-markdown').Handle
export type Token = import('mdast-util-from-markdown').Token
export type ToMarkdownExtension = import('mdast-util-to-markdown').Options
export type ToMarkdownHandle = import('mdast-util-to-markdown').Handle
export type ToMarkdownMap = import('mdast-util-to-markdown').Map
export type OnEnterError = import('mdast-util-from-markdown').OnEnterError
export type OnExitError = import('mdast-util-from-markdown').OnExitError
export type Program = import('estree-jsx').Program
export type MdxJsxAttributeValueExpression =
import('./complex-types').MdxJsxAttributeValueExpression
export type MdxJsxAttribute = import('./complex-types').MdxJsxAttribute
import('./lib/index.js').MdxJsxAttributeValueExpression
export type MdxJsxAttribute = import('./lib/index.js').MdxJsxAttribute
export type MdxJsxExpressionAttribute =
import('./complex-types').MdxJsxExpressionAttribute
export type MdxJsxFlowElement = import('./complex-types').MdxJsxFlowElement
export type MdxJsxTextElement = import('./complex-types').MdxJsxTextElement
export type Tag = {
name: string | null
attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[]
close?: boolean
selfClosing?: boolean
start: Token['start']
end: Token['start']
}
/**
* Legacy names:
*/
export type MDXJsxAttributeValueExpression = MdxJsxAttributeValueExpression
/**
* Legacy names:
*/
export type MDXJsxAttribute = MdxJsxAttribute
/**
* Legacy names:
*/
export type MDXJsxExpressionAttribute = MdxJsxExpressionAttribute
/**
* Legacy names:
*/
export type MDXJsxFlowElement = MdxJsxFlowElement
/**
* Legacy names:
*/
export type MDXJsxTextElement = MdxJsxTextElement
import('./lib/index.js').MdxJsxExpressionAttribute
export type MdxJsxFlowElement = import('./lib/index.js').MdxJsxFlowElement
export type MdxJsxTextElement = import('./lib/index.js').MdxJsxTextElement
export type ToMarkdownOptions = import('./lib/index.js').ToMarkdownOptions
export {mdxJsxFromMarkdown, mdxJsxToMarkdown} from './lib/index.js'
/**
* @typedef {import('mdast').Literal} Literal
* @typedef {import('mdast').Parent} Parent
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
* @typedef {import('mdast-util-from-markdown').Token} Token
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
* @typedef {import('mdast-util-to-markdown').Map} ToMarkdownMap
* @typedef {import('mdast-util-from-markdown').OnEnterError} OnEnterError
* @typedef {import('mdast-util-from-markdown').OnExitError} OnExitError
* @typedef {import('estree-jsx').Program} Program
* @typedef {import('./complex-types').MdxJsxAttributeValueExpression} MdxJsxAttributeValueExpression
* @typedef {import('./complex-types').MdxJsxAttribute} MdxJsxAttribute
* @typedef {import('./complex-types').MdxJsxExpressionAttribute} MdxJsxExpressionAttribute
* @typedef {import('./complex-types').MdxJsxFlowElement} MdxJsxFlowElement
* @typedef {import('./complex-types').MdxJsxTextElement} MdxJsxTextElement
* @typedef {{name: string|null, attributes: (MdxJsxAttribute|MdxJsxExpressionAttribute)[], close?: boolean, selfClosing?: boolean, start: Token['start'], end: Token['start']}} Tag
* @typedef {import('./lib/index.js').MdxJsxAttributeValueExpression} MdxJsxAttributeValueExpression
* @typedef {import('./lib/index.js').MdxJsxAttribute} MdxJsxAttribute
* @typedef {import('./lib/index.js').MdxJsxExpressionAttribute} MdxJsxExpressionAttribute
* @typedef {import('./lib/index.js').MdxJsxFlowElement} MdxJsxFlowElement
* @typedef {import('./lib/index.js').MdxJsxTextElement} MdxJsxTextElement
* @typedef {import('./lib/index.js').ToMarkdownOptions} ToMarkdownOptions
*/
/**
* Legacy names:
*
* @typedef {MdxJsxAttributeValueExpression} MDXJsxAttributeValueExpression
* @typedef {MdxJsxAttribute} MDXJsxAttribute
* @typedef {MdxJsxExpressionAttribute} MDXJsxExpressionAttribute
* @typedef {MdxJsxFlowElement} MDXJsxFlowElement
* @typedef {MdxJsxTextElement} MDXJsxTextElement
*/
import {parseEntities} from 'parse-entities'
import {stringifyPosition} from 'unist-util-stringify-position'
import {VFileMessage} from 'vfile-message'
import {stringifyEntitiesLight} from 'stringify-entities'
import {containerFlow} from 'mdast-util-to-markdown/lib/util/container-flow.js'
import {containerPhrasing} from 'mdast-util-to-markdown/lib/util/container-phrasing.js'
import {checkQuote} from 'mdast-util-to-markdown/lib/util/check-quote.js'
import {indentLines} from 'mdast-util-to-markdown/lib/util/indent-lines.js'
mdxElement.peek = peekElement
/** @type {FromMarkdownExtension} */
export const mdxJsxFromMarkdown = {
canContainEols: ['mdxJsxTextElement'],
enter: {
mdxJsxFlowTag: enterMdxJsxTag,
mdxJsxFlowTagClosingMarker: enterMdxJsxTagClosingMarker,
mdxJsxFlowTagAttribute: enterMdxJsxTagAttribute,
mdxJsxFlowTagExpressionAttribute: enterMdxJsxTagExpressionAttribute,
mdxJsxFlowTagAttributeValueLiteral: buffer,
mdxJsxFlowTagAttributeValueExpression: buffer,
mdxJsxFlowTagSelfClosingMarker: enterMdxJsxTagSelfClosingMarker,
mdxJsxTextTag: enterMdxJsxTag,
mdxJsxTextTagClosingMarker: enterMdxJsxTagClosingMarker,
mdxJsxTextTagAttribute: enterMdxJsxTagAttribute,
mdxJsxTextTagExpressionAttribute: enterMdxJsxTagExpressionAttribute,
mdxJsxTextTagAttributeValueLiteral: buffer,
mdxJsxTextTagAttributeValueExpression: buffer,
mdxJsxTextTagSelfClosingMarker: enterMdxJsxTagSelfClosingMarker
},
exit: {
mdxJsxFlowTagClosingMarker: exitMdxJsxTagClosingMarker,
mdxJsxFlowTagNamePrimary: exitMdxJsxTagNamePrimary,
mdxJsxFlowTagNameMember: exitMdxJsxTagNameMember,
mdxJsxFlowTagNameLocal: exitMdxJsxTagNameLocal,
mdxJsxFlowTagExpressionAttribute: exitMdxJsxTagExpressionAttribute,
mdxJsxFlowTagExpressionAttributeValue: data,
mdxJsxFlowTagAttributeNamePrimary: exitMdxJsxTagAttributeNamePrimary,
mdxJsxFlowTagAttributeNameLocal: exitMdxJsxTagAttributeNameLocal,
mdxJsxFlowTagAttributeValueLiteral: exitMdxJsxTagAttributeValueLiteral,
mdxJsxFlowTagAttributeValueLiteralValue: data,
mdxJsxFlowTagAttributeValueExpression:
exitMdxJsxTagAttributeValueExpression,
mdxJsxFlowTagAttributeValueExpressionValue: data,
mdxJsxFlowTagSelfClosingMarker: exitMdxJsxTagSelfClosingMarker,
mdxJsxFlowTag: exitMdxJsxTag,
mdxJsxTextTagClosingMarker: exitMdxJsxTagClosingMarker,
mdxJsxTextTagNamePrimary: exitMdxJsxTagNamePrimary,
mdxJsxTextTagNameMember: exitMdxJsxTagNameMember,
mdxJsxTextTagNameLocal: exitMdxJsxTagNameLocal,
mdxJsxTextTagExpressionAttribute: exitMdxJsxTagExpressionAttribute,
mdxJsxTextTagExpressionAttributeValue: data,
mdxJsxTextTagAttributeNamePrimary: exitMdxJsxTagAttributeNamePrimary,
mdxJsxTextTagAttributeNameLocal: exitMdxJsxTagAttributeNameLocal,
mdxJsxTextTagAttributeValueLiteral: exitMdxJsxTagAttributeValueLiteral,
mdxJsxTextTagAttributeValueLiteralValue: data,
mdxJsxTextTagAttributeValueExpression:
exitMdxJsxTagAttributeValueExpression,
mdxJsxTextTagAttributeValueExpressionValue: data,
mdxJsxTextTagSelfClosingMarker: exitMdxJsxTagSelfClosingMarker,
mdxJsxTextTag: exitMdxJsxTag
}
}
/** @type {ToMarkdownExtension} */
export const mdxJsxToMarkdown = {
handlers: {
mdxJsxFlowElement: mdxElement,
mdxJsxTextElement: mdxElement
},
unsafe: [
{character: '<', inConstruct: ['phrasing']},
{atBreak: true, character: '<'}
],
fences: true,
resourceLink: true
}
/** @type {FromMarkdownHandle} */
function buffer() {
this.buffer()
}
/** @type {FromMarkdownHandle} */
function data(token) {
this.config.enter.data.call(this, token)
this.config.exit.data.call(this, token)
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTag(token) {
/** @type {Tag} */
const tag = {name: null, attributes: [], start: token.start, end: token.end}
if (!this.getData('mdxJsxTagStack')) this.setData('mdxJsxTagStack', [])
this.setData('mdxJsxTag', tag)
this.buffer()
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTagClosingMarker(token) {
const stack = /** @type {Tag[]} */ (this.getData('mdxJsxTagStack'))
if (stack.length === 0) {
throw new VFileMessage(
'Unexpected closing slash `/` in tag, expected an open tag first',
{start: token.start, end: token.end},
'mdast-util-mdx-jsx:unexpected-closing-slash'
)
}
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTagAnyAttribute(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
if (tag.close) {
throw new VFileMessage(
'Unexpected attribute in closing tag, expected the end of the tag',
{start: token.start, end: token.end},
'mdast-util-mdx-jsx:unexpected-attribute'
)
}
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTagSelfClosingMarker(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
if (tag.close) {
throw new VFileMessage(
'Unexpected self-closing slash `/` in closing tag, expected the end of the tag',
{start: token.start, end: token.end},
'mdast-util-mdx-jsx:unexpected-self-closing-slash'
)
}
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagClosingMarker() {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.close = true
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagNamePrimary(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.name = this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagNameMember(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.name += '.' + this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagNameLocal(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.name += ':' + this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTagAttribute(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
enterMdxJsxTagAnyAttribute.call(this, token)
tag.attributes.push({type: 'mdxJsxAttribute', name: '', value: null})
}
/** @type {FromMarkdownHandle} */
function enterMdxJsxTagExpressionAttribute(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
enterMdxJsxTagAnyAttribute.call(this, token)
tag.attributes.push({type: 'mdxJsxExpressionAttribute', value: ''})
this.buffer()
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagExpressionAttribute(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const tail = /** @type {MdxJsxExpressionAttribute} */ (
tag.attributes[tag.attributes.length - 1]
)
/** @type {Program|undefined} */
// @ts-expect-error: custom.
const estree = token.estree
tail.value = this.resume()
if (estree) {
tail.data = {estree}
}
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagAttributeNamePrimary(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const node = /** @type {MdxJsxAttribute} */ (
tag.attributes[tag.attributes.length - 1]
)
node.name = this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagAttributeNameLocal(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const node = /** @type {MdxJsxAttribute} */ (
tag.attributes[tag.attributes.length - 1]
)
node.name += ':' + this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagAttributeValueLiteral() {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.attributes[tag.attributes.length - 1].value = parseEntities(
this.resume(),
{nonTerminated: false}
)
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagAttributeValueExpression(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const tail = /** @type {MdxJsxAttribute} */ (
tag.attributes[tag.attributes.length - 1]
)
/** @type {MdxJsxAttributeValueExpression} */
const node = {type: 'mdxJsxAttributeValueExpression', value: this.resume()}
/** @type {Program|undefined} */
// @ts-expect-error: custom.
const estree = token.estree
if (estree) {
node.data = {estree}
}
tail.value = node
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTagSelfClosingMarker() {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
tag.selfClosing = true
}
/** @type {FromMarkdownHandle} */
function exitMdxJsxTag(token) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const stack = /** @type {Tag[]} */ (this.getData('mdxJsxTagStack'))
const tail = stack[stack.length - 1]
if (tag.close && tail.name !== tag.name) {
throw new VFileMessage(
'Unexpected closing tag `' +
serializeAbbreviatedTag(tag) +
'`, expected corresponding closing tag for `' +
serializeAbbreviatedTag(tail) +
'` (' +
stringifyPosition(tail) +
')',
{start: token.start, end: token.end},
'mdast-util-mdx-jsx:end-tag-mismatch'
)
}
// End of a tag, so drop the buffer.
this.resume()
if (tag.close) {
stack.pop()
} else {
this.enter(
{
type:
token.type === 'mdxJsxTextTag'
? 'mdxJsxTextElement'
: 'mdxJsxFlowElement',
name: tag.name,
attributes: tag.attributes,
children: []
},
token,
onErrorRightIsTag
)
}
if (tag.selfClosing || tag.close) {
this.exit(token, onErrorLeftIsTag)
} else {
stack.push(tag)
}
}
/** @type {OnEnterError} */
function onErrorRightIsTag(closing, open) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
const place = closing ? ' before the end of `' + closing.type + '`' : ''
const position = closing
? {start: closing.start, end: closing.end}
: undefined
throw new VFileMessage(
'Expected a closing tag for `' +
serializeAbbreviatedTag(tag) +
'` (' +
stringifyPosition({start: open.start, end: open.end}) +
')' +
place,
position,
'mdast-util-mdx-jsx:end-tag-mismatch'
)
}
/** @type {OnExitError} */
function onErrorLeftIsTag(a, b) {
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
throw new VFileMessage(
'Expected the closing tag `' +
serializeAbbreviatedTag(tag) +
'` either after the end of `' +
b.type +
'` (' +
stringifyPosition(b.end) +
') or another opening tag after the start of `' +
b.type +
'` (' +
stringifyPosition(b.start) +
')',
{start: a.start, end: a.end},
'mdast-util-mdx-jsx:end-tag-mismatch'
)
}
/**
* Serialize a tag, excluding attributes.
* `self-closing` is not supported, because we don’t need it yet.
*
* @param {Tag} tag
* @returns {string}
*/
function serializeAbbreviatedTag(tag) {
return '<' + (tag.close ? '/' : '') + (tag.name || '') + '>'
}
/**
* @type {ToMarkdownHandle}
* @param {MdxJsxFlowElement|MdxJsxTextElement} node
*/
// eslint-disable-next-line complexity
function mdxElement(node, _, context) {
const selfClosing =
node.name && (!node.children || node.children.length === 0)
const quote = checkQuote(context)
const exit = context.enter(node.type)
let attributeValue = ''
let index = -1
/** @type {Array<string>} */
const attributes = []
/** @type {string} */
let result
// None.
if (node.attributes && node.attributes.length > 0) {
if (!node.name) {
throw new Error('Cannot serialize fragment w/ attributes')
}
const isMultiFlow =
node.type === 'mdxJsxFlowElement' && node.attributes.length > 1
while (++index < node.attributes.length) {
const attribute = node.attributes[index]
if (attribute.type === 'mdxJsxExpressionAttribute') {
result = '{' + (attribute.value || '') + '}'
} else {
if (!attribute.name) {
throw new Error('Cannot serialize attribute w/o name')
}
result =
attribute.name +
(attribute.value === undefined || attribute.value === null
? ''
: '=' +
(typeof attribute.value === 'object'
? '{' + (attribute.value.value || '') + '}'
: quote +
stringifyEntitiesLight(attribute.value, {subset: [quote]}) +
quote))
}
attributes.push((isMultiFlow ? '\n ' : ' ') + result)
}
attributeValue = attributes.join('') + (isMultiFlow ? '\n' : '')
}
const value =
'<' +
(node.name || '') +
attributeValue +
(selfClosing ? '/' : '') +
'>' +
(node.children && node.children.length > 0
? node.type === 'mdxJsxFlowElement'
? '\n' + indent(containerFlow(node, context)) + '\n'
: containerPhrasing(node, context, {before: '<', after: '>'})
: '') +
(selfClosing ? '' : '</' + (node.name || '') + '>')
exit()
return value
}
/**
* @type {ToMarkdownHandle}
*/
function peekElement() {
return '<'
}
/**
* @param {string} value
* @returns {string}
*/
function indent(value) {
return indentLines(value, map)
/** @type {ToMarkdownMap} */
function map(line, _, blank) {
return (blank ? '' : ' ') + line
}
}
export {mdxJsxFromMarkdown, mdxJsxToMarkdown} from './lib/index.js'
{
"name": "mdast-util-mdx-jsx",
"version": "1.2.0",
"version": "2.0.0",
"description": "mdast extension to parse and serialize MDX or MDX.js JSX",

@@ -34,3 +34,3 @@ "license": "MIT",

"files": [
"complex-types.d.ts",
"lib/",
"index.d.ts",

@@ -41,4 +41,6 @@ "index.js"

"@types/estree-jsx": "^0.0.1",
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"mdast-util-to-markdown": "^1.0.0",
"ccount": "^2.0.0",
"mdast-util-to-markdown": "^1.3.0",
"parse-entities": "^4.0.0",

@@ -63,6 +65,6 @@ "stringify-entities": "^4.0.0",

"typescript": "^4.0.0",
"xo": "^0.46.0"
"xo": "^0.47.0"
},
"scripts": {
"build": "rimraf \"{index,test}.d.ts\" && tsc && type-coverage",
"build": "rimraf \"lib/index.d.ts\" \"*.d.ts\" && tsc && type-coverage",
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",

@@ -69,0 +71,0 @@ "test-api": "node --conditions development test.js",

@@ -11,22 +11,49 @@ # mdast-util-mdx-jsx

Extension for [`mdast-util-from-markdown`][from-markdown] and/or
[`mdast-util-to-markdown`][to-markdown] to support MDX (or MDX.js) JSX.
When parsing (`from-markdown`), must be combined with
[`micromark-extension-mdx-jsx`][extension].
Extensions to parse and serialize JSX between mdast and markdown.
This utility handles parsing and serializing.
See [`micromark-extension-mdx-jsx`][extension] for how the syntax works.
## Contents
* [What is this?](#what-is-this)
* [When to use this](#when-to-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`mdxJsxFromMarkdown()`](#mdxjsxfrommarkdown)
* [`mdxJsxToMarkdown(options?)`](#mdxjsxtomarkdownoptions)
* [Syntax tree](#syntax-tree)
* [Nodes](#nodes)
* [Mixin](#mixin)
* [Content model](#content-model)
* [Types](#types)
* [Compatibility](#compatibility)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package contains extensions that add support for the JSX syntax enabled by
MDX to [`mdast-util-from-markdown`][mdast-util-from-markdown] and
[`mdast-util-to-markdown`][mdast-util-to-markdown].
[JSX][] is an XML-like syntax extension to ECMAScript (JavaScript), which MDX
brings to markdown.
For more info on MDX, see [What is MDX?][what-is-mdx]
## When to use this
Use [`mdast-util-mdx`][mdast-util-mdx] if you want all of MDX / MDX.js.
Use this otherwise.
These tools are all rather low-level.
In most cases, you’d want to use [`remark-mdx`][remark-mdx] with remark instead.
When you are working with syntax trees and want all of MDX, use
[`mdast-util-mdx`][mdast-util-mdx] instead.
When working with `mdast-util-from-markdown`, you’d want to combine this package
with [`micromark-extension-mdx-jsx`][micromark-extension-mdx-jsx].
## Install
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c):
Node 12+ is needed to use it and it must be `import`ed instead of `require`d.
This package is [ESM only][esm].
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]:
[npm][]:
```sh

@@ -36,5 +63,19 @@ npm install mdast-util-mdx-jsx

In Deno with [Skypack][]:
```js
import {mdxJsxFromMarkdown, mdxJsxToMarkdown} from 'https://cdn.skypack.dev/mdast-util-mdx-jsx@1?dts'
```
In browsers with [Skypack][]:
```html
<script type="module">
import {mdxJsxFromMarkdown, mdxJsxToMarkdown} from 'https://cdn.skypack.dev/mdast-util-mdx-jsx@1?min'
</script>
```
## Use
Say we have an MDX.js file, `example.mdx`:
Say our document `example.mdx` contains:

@@ -51,3 +92,3 @@ ```mdx

And our module, `example.js`, looks as follows:
…and our module `example.js` looks as follows:

@@ -66,3 +107,3 @@ ```js

extensions: [mdxJsx({acorn: acorn, addResult: true})],
mdastExtensions: [mdxJsxFromMarkdown]
mdastExtensions: [mdxJsxFromMarkdown()]
})

@@ -72,3 +113,3 @@

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

@@ -78,3 +119,3 @@ console.log(out)

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

@@ -166,3 +207,3 @@ ```js

<MyComponent {...props}/>
<MyComponent {...props} />

@@ -174,20 +215,50 @@ <abbr title="Hypertext Markup Language">HTML</abbr> is a lovely language.

### `mdxJsxFromMarkdown`
This package exports the following identifiers: `mdxJsxFromMarkdown`,
`mdxJsxToMarkdown`.
There is no default export.
### `mdxJsxToMarkdown`
### `mdxJsxFromMarkdown()`
Support MDX (or MDX.js) JSX.
The exports are extensions, respectively for
[`mdast-util-from-markdown`][from-markdown] and
[`mdast-util-to-markdown`][to-markdown].
Function that can be called to get an extension for
[`mdast-util-from-markdown`][mdast-util-from-markdown].
When using the [syntax extension][extension] with `addResult`, nodes will have a
`data.estree` field set to an [ESTree][].
When using [`micromark-extension-mdx-jsx`][micromark-extension-mdx-jsx]
with `options.addResult`, nodes will have a `data.estree` field set to an
[ESTree][].
There are no options, but passing [`options.quote`][quote] to
`mdast-util-to-markdown` is honored for attributes.
### `mdxJsxToMarkdown(options?)`
this extension configures [`mdast-util-to-markdown`][to-markdown] with
`fences: true` and `resourceLink: true` too, do not overwrite them!
Function that can be called to get an extension for
[`mdast-util-to-markdown`][mdast-util-to-markdown].
This extension configures `mdast-util-to-markdown` with
[`options.fences: true`][mdast-util-to-markdown-fences] and
[`options.resourceLink: true`][mdast-util-to-markdown-resourcelink] too, do not
overwrite them!
##### `options`
Configuration (optional).
###### `options.quote`
Preferred quote to use around attribute values (`'"'` or `"'"`, default: `'"'`).
###### `options.quoteSmart`
Use the other quote if that results in less bytes (`boolean`, default: `false`).
###### `options.tightSelfClosing`
Do not use an extra space when closing self-closing elements: `<img/>` instead
of `<img />` (`boolean`, default: `false`).
###### `options.printWidth`
Try and wrap syntax as this width (`number`, default: `Infinity`).
When set to a finite number (say, `80`), the formatter will print attributes on
separate lines when a tag doesn’t fit on one line.
The normal behavior is to print attributes with spaces between them instead of
line endings.
## Syntax tree

@@ -199,15 +270,15 @@

#### `MDXJsxFlowElement`
###### `MdxJsxFlowElement`
```idl
interface MDXJsxFlowElement <: Parent {
interface MdxJsxFlowElement <: Parent {
type: "mdxJsxFlowElement"
}
MDXJsxFlowElement includes MDXJsxElement
MdxJsxFlowElement includes MdxJsxElement
```
**MDXJsxFlowElement** (**[Parent][dfn-parent]**) represents JSX in flow (block).
**MdxJsxFlowElement** (**[Parent][dfn-parent]**) represents JSX in flow (block).
It can be used where **[flow][dfn-content-flow]** content is expected.
It includes the mixin **[MDXJsxElement][dfn-mixin-mdx-jsx-element]**.
It includes the mixin **[MdxJsxElement][dfn-mixin-mdx-jsx-element]**.

@@ -233,17 +304,17 @@ For example, the following markdown:

#### `MDXJsxTextElement`
###### `MdxJsxTextElement`
```idl
interface MDXJsxTextElement <: Parent {
interface MdxJsxTextElement <: Parent {
type: "mdxJsxTextElement"
}
MDXJsxTextElement includes MDXJsxElement
MdxJsxTextElement includes MdxJsxElement
```
**MDXJsxTextElement** (**[Parent][dfn-parent]**) represents JSX in text (span,
**MdxJsxTextElement** (**[Parent][dfn-parent]**) represents JSX in text (span,
inline).
It can be used where **[phrasing][dfn-content-phrasing]** content is
expected.
It includes the mixin **[MDXJsxElement][dfn-mixin-mdx-jsx-element]**.
It includes the mixin **[MdxJsxElement][dfn-mixin-mdx-jsx-element]**.

@@ -269,21 +340,21 @@ For example, the following markdown:

### `MDXJsxElement`
###### `MdxJsxElement`
```idl
interface mixin MDXJsxElement {
interface mixin MdxJsxElement {
name: string?
attributes: [MDXJsxExpressionAttribute | MDXJsxAttribute]
attributes: [MdxJsxExpressionAttribute | MdxJsxAttribute]
}
interface MDXJsxExpressionAttribute <: Literal {
interface MdxJsxExpressionAttribute <: Literal {
type: "mdxJsxExpressionAttribute"
}
interface MDXJsxAttribute <: Node {
interface MdxJsxAttribute <: Node {
type: "mdxJsxAttribute"
name: string
value: MDXJsxAttributeValueExpression | string?
value: MdxJsxAttributeValueExpression | string?
}
interface MDXJsxAttributeValueExpression <: Literal {
interface MdxJsxAttributeValueExpression <: Literal {
type: "mdxJsxAttributeValueExpression"

@@ -293,3 +364,3 @@ }

**MDXJsxElement** represents a JSX element.
**MdxJsxElement** represents a JSX element.

@@ -301,9 +372,9 @@ The `name` field can be present and represents an identifier.

The `attributes` field represents information associated with the node.
The value of the `attributes` field is a list of **MDXJsxExpressionAttribute**
and **MDXJsxAttribute** nodes.
The value of the `attributes` field is a list of **MdxJsxExpressionAttribute**
and **MdxJsxAttribute** nodes.
**MDXJsxExpressionAttribute** represents an expression (typically in a
**MdxJsxExpressionAttribute** represents an expression (typically in a
programming language) that when evaluated results in multiple attributes.
**MDXJsxAttribute** represents a single attribute.
**MdxJsxAttribute** represents a single attribute.
The `name` field must be present.

@@ -316,30 +387,58 @@ The `value` field can be present, in which case it is either a string (a static

#### `FlowContent` (MDX JSX)
###### `FlowContent` (MDX JSX)
```idl
type MDXJsxFlowContent = MDXJsxFlowElement | FlowContent
type MdxJsxFlowContent = MdxJsxFlowElement | FlowContent
```
#### `PhrasingContent` (MDX JSX)
###### `PhrasingContent` (MDX JSX)
```idl
type MDXJsxPhrasingContent = MDXJsxTextElement | PhrasingContent
type MdxJsxPhrasingContent = MdxJsxTextElement | PhrasingContent
```
## Types
This package is fully typed with [TypeScript][].
It exports the `MdxJsxAttributeValueExpression`, `MdxJsxAttribute`,
`MdxJsxExpressionAttribute`, `MdxJsxFlowElement`, and `MdxJsxTextElement` types
that represents the supported nodes.
It also exports `ToMarkdownOptions`, which represents the structure of the
respective options.
It also registers the node types with `@types/mdast`.
If you’re working with the syntax tree, make sure to import this plugin
somewhere in your types, as that registers the new node types in the tree.
```js
/** @typedef {import('mdast-util-mdx-jsx')} */
import {visit} from 'unist-util-visit'
/** @type {import('mdast').Root} */
const tree = getMdastNodeSomeHow()
visit(tree, (node) => {
// `node` can now be one of the JSX nodes.
})
```
## 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+.
## Related
* [`remarkjs/remark`][remark]
— markdown processor powered by plugins
* [`micromark/micromark-extension-mdx-jsx`][micromark-extension-mdx-jsx]
— support MDX JSX in micromark
* [`syntax-tree/mdast-util-mdx`][mdast-util-mdx]
— support MDX in mdast
* [`remarkjs/remark-mdx`][remark-mdx]
— remark plugin to support MDX
* [`syntax-tree/mdast-util-from-markdown`][from-markdown]
— mdast parser using `micromark` to create mdast from markdown
* [`syntax-tree/mdast-util-to-markdown`][to-markdown]
— mdast serializer to create markdown from mdast
* [`syntax-tree/mdast-util-mdx`][mdast-util-mdx]
— mdast utility to support all of MDX
* [`micromark/micromark`][micromark]
— the smallest commonmark-compliant markdown parser that exists
* [`micromark/micromark-extension-mdx-jsx`][extension]
— micromark extension to parse JSX
— support MDX in remark

@@ -388,2 +487,4 @@ ## Contribute

[skypack]: https://www.skypack.dev
[license]: license

@@ -399,18 +500,14 @@

[mdast]: https://github.com/syntax-tree/mdast
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[remark]: https://github.com/remarkjs/remark
[typescript]: https://www.typescriptlang.org
[from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
[mdast]: https://github.com/syntax-tree/mdast
[to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown
[mdast-util-from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
[micromark]: https://github.com/micromark/micromark
[mdast-util-to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown
[extension]: https://github.com/micromark/micromark-extension-mdxjs-esm
[mdast-util-mdx]: https://github.com/syntax-tree/mdast-util-mdx
[quote]: https://github.com/syntax-tree/mdast-util-to-markdown#optionsquote
[estree]: https://github.com/estree/estree

@@ -427,1 +524,11 @@

[remark-mdx]: https://github.com/mdx-js/mdx/tree/main/packages/remark-mdx
[jsx]: https://facebook.github.io/jsx/
[what-is-mdx]: https://mdxjs.com/docs/what-is-mdx/
[micromark-extension-mdx-jsx]: https://github.com/micromark/micromark-extension-mdx-jsx
[mdast-util-to-markdown-fences]: https://github.com/syntax-tree/mdast-util-to-markdown#optionsfences
[mdast-util-to-markdown-resourcelink]: https://github.com/syntax-tree/mdast-util-to-markdown#optionsresourcelink
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc