micromark-extension-mdx-jsx
Advanced tools
Comparing version 0.3.3 to 1.0.0
@@ -1,2 +0,4 @@ | ||
'use strict' | ||
module.exports = require('./lib') | ||
/** | ||
* @typedef {import('./lib/syntax.js').Options} Options | ||
*/ | ||
export {mdxJsx} from './lib/syntax.js' |
@@ -1,15 +0,61 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext | ||
* @typedef {import('micromark-util-types').Tokenizer} Tokenizer | ||
* @typedef {import('micromark-util-types').Effects} Effects | ||
* @typedef {import('micromark-util-types').State} State | ||
* @typedef {import('micromark-util-types').Code} Code | ||
* @typedef {import('micromark-factory-mdx-expression').Acorn} Acorn | ||
* @typedef {import('micromark-factory-mdx-expression').AcornOptions} AcornOptions | ||
*/ | ||
import {start as idStart, cont as idCont} from 'estree-util-is-identifier-name' | ||
import {factoryMdxExpression} from 'micromark-factory-mdx-expression' | ||
import { | ||
markdownLineEnding, | ||
markdownLineEndingOrSpace, | ||
markdownSpace, | ||
unicodeWhitespace | ||
} from 'micromark-util-character' | ||
import {VFileMessage} from 'vfile-message' | ||
const lazyLineEnd = { | ||
tokenize: tokenizeLazyLineEnd, | ||
partial: true | ||
} | ||
/** | ||
* @this {TokenizeContext} | ||
* @param {Effects} effects | ||
* @param {State} ok | ||
* @param {State} nok | ||
* @param {Acorn|undefined} acorn | ||
* @param {AcornOptions|undefined} acornOptions | ||
* @param {boolean|undefined} addResult | ||
* @param {boolean|undefined} allowLazy | ||
* @param {string} tagType | ||
* @param {string} tagMarkerType | ||
* @param {string} tagClosingMarkerType | ||
* @param {string} tagSelfClosingMarker | ||
* @param {string} tagNameType | ||
* @param {string} tagNamePrimaryType | ||
* @param {string} tagNameMemberMarkerType | ||
* @param {string} tagNameMemberType | ||
* @param {string} tagNamePrefixMarkerType | ||
* @param {string} tagNameLocalType | ||
* @param {string} tagExpressionAttributeType | ||
* @param {string} tagExpressionAttributeMarkerType | ||
* @param {string} tagExpressionAttributeValueType | ||
* @param {string} tagAttributeType | ||
* @param {string} tagAttributeNameType | ||
* @param {string} tagAttributeNamePrimaryType | ||
* @param {string} tagAttributeNamePrefixMarkerType | ||
* @param {string} tagAttributeNameLocalType | ||
* @param {string} tagAttributeInitializerMarkerType | ||
* @param {string} tagAttributeValueLiteralType | ||
* @param {string} tagAttributeValueLiteralMarkerType | ||
* @param {string} tagAttributeValueLiteralValueType | ||
* @param {string} tagAttributeValueExpressionType | ||
* @param {string} tagAttributeValueExpressionMarkerType | ||
* @param {string} tagAttributeValueExpressionMarkerValue | ||
*/ | ||
// eslint-disable-next-line max-params | ||
module.exports = factoryTag | ||
var id = require('estree-util-is-identifier-name') | ||
var markdownLineEnding = require('micromark/dist/character/markdown-line-ending') | ||
var markdownLineEndingOrSpace = require('micromark/dist/character/markdown-line-ending-or-space') | ||
var markdownSpace = require('micromark/dist/character/markdown-space') | ||
var esWhitespace = require('micromark/dist/character/unicode-whitespace') | ||
var fromCharCode = require('micromark/dist/constant/from-char-code') | ||
var factoryExpression = require('micromark-extension-mdx-expression/lib/factory-expression') | ||
var VMessage = require('vfile-message') | ||
function factoryTag( | ||
export function factoryTag( | ||
effects, | ||
@@ -21,2 +67,3 @@ ok, | ||
addResult, | ||
allowLazy, | ||
tagType, | ||
@@ -48,10 +95,13 @@ tagMarkerType, | ||
) { | ||
var self = this | ||
var returnState | ||
var marker | ||
const self = this | ||
/** @type {State} */ | ||
let returnState | ||
/** @type {NonNullable<Code>|undefined} */ | ||
let marker | ||
return start | ||
/** @type {State} */ | ||
function start(code) { | ||
// Always `<` | ||
effects.enter(tagType) | ||
@@ -63,2 +113,3 @@ effects.enter(tagMarkerType) | ||
} | ||
/** @type {State} */ | ||
@@ -70,13 +121,13 @@ function afterStart(code) { | ||
return nok(code) | ||
} | ||
} // Any other ES whitespace does not get this treatment. | ||
// Any other ES whitespace does not get this treatment. | ||
returnState = beforeName | ||
return optionalEsWhitespace(code) | ||
} | ||
} // Right after `<`, before an optional name. | ||
// Right after `<`, before an optional name. | ||
/** @type {State} */ | ||
function beforeName(code) { | ||
// Closing tag. | ||
if (code === 47 /* `/` */) { | ||
if (code === 47) { | ||
effects.enter(tagClosingMarkerType) | ||
@@ -87,11 +138,9 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // Fragment opening tag. | ||
// Fragment opening tag. | ||
if (code === 62 /* `>` */) { | ||
if (code === 62) { | ||
return tagEnd(code) | ||
} | ||
} // Start of a name. | ||
// Start of a name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagNameType) | ||
@@ -107,17 +156,17 @@ effects.enter(tagNamePrimaryType) | ||
'a character that can start a name, such as a letter, `$`, or `_`' + | ||
(code === 33 /* `!` */ | ||
(code === 33 | ||
? ' (note: to create a comment in MDX, use `{/* text */}`)' | ||
: '') | ||
) | ||
} | ||
} // At the start of a closing tag, right after `</`. | ||
// At the start of a closing tag, right after `</`. | ||
/** @type {State} */ | ||
function beforeClosingTagName(code) { | ||
// Fragment closing tag. | ||
if (code === 62 /* `>` */) { | ||
if (code === 62) { | ||
return tagEnd(code) | ||
} | ||
} // Start of a closing tag name. | ||
// Start of a closing tag name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagNameType) | ||
@@ -133,25 +182,25 @@ effects.enter(tagNamePrimaryType) | ||
'a character that can start a name, such as a letter, `$`, or `_`' + | ||
(code === 42 /* `*` */ || code === 47 /* `/` */ | ||
(code === 42 || code === 47 | ||
? ' (note: JS comments in JSX tags are not supported in MDX)' | ||
: '') | ||
) | ||
} | ||
} // Inside the primary name. | ||
// Inside the primary name. | ||
/** @type {State} */ | ||
function primaryName(code) { | ||
// Continuation of name: remain. | ||
if (code === 45 /* `-` */ || id.cont(code)) { | ||
if (code === 45 || (code !== null && idCont(code))) { | ||
effects.consume(code) | ||
return primaryName | ||
} | ||
} // End of name. | ||
// End of name. | ||
if ( | ||
code === 46 /* `.` */ || | ||
code === 47 /* `/` */ || | ||
code === 58 /* `:` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 46 || | ||
code === 47 || | ||
code === 58 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) | ||
unicodeWhitespace(code) | ||
) { | ||
@@ -167,12 +216,13 @@ effects.exit(tagNamePrimaryType) | ||
'a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag' + | ||
(code === 64 /* `@` */ | ||
(code === 64 | ||
? ' (note: to create a link in MDX, use `[text](url)`)' | ||
: '') | ||
) | ||
} | ||
} // After a name. | ||
// After a name. | ||
/** @type {State} */ | ||
function afterPrimaryName(code) { | ||
// Start of a member name. | ||
if (code === 46 /* `.` */) { | ||
if (code === 46) { | ||
effects.enter(tagNameMemberMarkerType) | ||
@@ -183,6 +233,5 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // Start of a local name. | ||
// Start of a local name. | ||
if (code === 58 /* `:` */) { | ||
if (code === 58) { | ||
effects.enter(tagNamePrefixMarkerType) | ||
@@ -193,10 +242,9 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // End of name. | ||
// End of name. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
id.start(code) | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
(code !== null && idStart(code)) | ||
) { | ||
@@ -212,8 +260,9 @@ effects.exit(tagNameType) | ||
) | ||
} | ||
} // We’ve seen a `.` and are expecting a member name. | ||
// We’ve seen a `.` and are expecting a member name. | ||
/** @type {State} */ | ||
function beforeMemberName(code) { | ||
// Start of a member name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagNameMemberType) | ||
@@ -229,20 +278,20 @@ effects.consume(code) | ||
) | ||
} | ||
} // Inside the member name. | ||
// Inside the member name. | ||
/** @type {State} */ | ||
function memberName(code) { | ||
// Continuation of member name: stay in state | ||
if (code === 45 /* `-` */ || id.cont(code)) { | ||
if (code === 45 || (code !== null && idCont(code))) { | ||
effects.consume(code) | ||
return memberName | ||
} | ||
} // End of member name (note that namespaces and members can’t be combined). | ||
// End of member name (note that namespaces and members can’t be combined). | ||
if ( | ||
code === 46 /* `.` */ || | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 46 || | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) | ||
unicodeWhitespace(code) | ||
) { | ||
@@ -258,13 +307,14 @@ effects.exit(tagNameMemberType) | ||
'a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag' + | ||
(code === 64 /* `@` */ | ||
(code === 64 | ||
? ' (note: to create a link in MDX, use `[text](url)`)' | ||
: '') | ||
) | ||
} | ||
} // After a member name: this is the same as `afterPrimaryName` but we don’t | ||
// expect colons. | ||
// After a member name: this is the same as `afterPrimaryName` but we don’t | ||
// expect colons. | ||
/** @type {State} */ | ||
function afterMemberName(code) { | ||
// Start another member name. | ||
if (code === 46 /* `.` */) { | ||
if (code === 46) { | ||
effects.enter(tagNameMemberMarkerType) | ||
@@ -275,10 +325,9 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // End of name. | ||
// End of name. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
id.start(code) | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
(code !== null && idStart(code)) | ||
) { | ||
@@ -294,8 +343,9 @@ effects.exit(tagNameType) | ||
) | ||
} | ||
} // We’ve seen a `:`, and are expecting a local name. | ||
// We’ve seen a `:`, and are expecting a local name. | ||
/** @type {State} */ | ||
function beforeLocalName(code) { | ||
// Start of a local name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagNameLocalType) | ||
@@ -310,23 +360,24 @@ effects.consume(code) | ||
'a character that can start a name, such as a letter, `$`, or `_`' + | ||
(code === 43 /* `+` */ || (code > 46 && code < 58) /* `/` - `9` */ | ||
? ' (note: to create a link in MDX, use `[text](url)`)' | ||
(code === 43 || (code !== null && code > 46 && code < 58) | ||
? /* `/` - `9` */ | ||
' (note: to create a link in MDX, use `[text](url)`)' | ||
: '') | ||
) | ||
} | ||
} // Inside the local name. | ||
// Inside the local name. | ||
/** @type {State} */ | ||
function localName(code) { | ||
// Continuation of local name: stay in state | ||
if (code === 45 /* `-` */ || id.cont(code)) { | ||
if (code === 45 || (code !== null && idCont(code))) { | ||
effects.consume(code) | ||
return localName | ||
} | ||
} // End of local name (note that we don’t expect another colon, or a member). | ||
// End of local name (note that we don’t expect another colon, or a member). | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) | ||
unicodeWhitespace(code) | ||
) { | ||
@@ -343,13 +394,14 @@ effects.exit(tagNameLocalType) | ||
) | ||
} | ||
} // After a local name: this is the same as `afterPrimaryName` but we don’t | ||
// expect colons or periods. | ||
// After a local name: this is the same as `afterPrimaryName` but we don’t | ||
// expect colons or periods. | ||
/** @type {State} */ | ||
function afterLocalName(code) { | ||
// End of name. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
id.start(code) | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
(code !== null && idStart(code)) | ||
) { | ||
@@ -366,6 +418,7 @@ effects.exit(tagNameType) | ||
} | ||
/** @type {State} */ | ||
function beforeAttribute(code) { | ||
// Mark as self-closing. | ||
if (code === 47 /* `/` */) { | ||
if (code === 47) { | ||
effects.enter(tagSelfClosingMarker) | ||
@@ -376,28 +429,26 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // End of tag. | ||
// End of tag. | ||
if (code === 62 /* `>` */) { | ||
if (code === 62) { | ||
return tagEnd(code) | ||
} | ||
} // Attribute expression. | ||
// Attribute expression. | ||
if (code === 123 /* `{` */) { | ||
return factoryExpression.call( | ||
if (code === 123) { | ||
return factoryMdxExpression.call( | ||
self, | ||
effects, | ||
afterAttributeExpression, | ||
nok, | ||
tagExpressionAttributeType, | ||
tagExpressionAttributeMarkerType, | ||
tagExpressionAttributeValueType, | ||
acorn, | ||
acornOptions, | ||
addResult, | ||
tagExpressionAttributeType, | ||
tagExpressionAttributeMarkerType, | ||
tagExpressionAttributeValueType, | ||
true | ||
true, | ||
false, | ||
allowLazy | ||
)(code) | ||
} | ||
} // Start of an attribute name. | ||
// Start of an attribute name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagAttributeType) | ||
@@ -415,27 +466,28 @@ effects.enter(tagAttributeNameType) | ||
) | ||
} | ||
} // At the start of an attribute expression. | ||
// At the start of an attribute expression. | ||
/** @type {State} */ | ||
function afterAttributeExpression(code) { | ||
returnState = beforeAttribute | ||
return optionalEsWhitespace(code) | ||
} | ||
} // In the attribute name. | ||
// In the attribute name. | ||
/** @type {State} */ | ||
function attributePrimaryName(code) { | ||
// Continuation of the attribute name. | ||
if (code === 45 /* `-` */ || id.cont(code)) { | ||
if (code === 45 || (code !== null && idCont(code))) { | ||
effects.consume(code) | ||
return attributePrimaryName | ||
} | ||
} // End of attribute name or tag. | ||
// End of attribute name or tag. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 58 /* `:` */ || | ||
code === 61 /* `=` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 47 || | ||
code === 58 || | ||
code === 61 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) | ||
unicodeWhitespace(code) | ||
) { | ||
@@ -452,8 +504,9 @@ effects.exit(tagAttributeNamePrimaryType) | ||
) | ||
} | ||
} // After an attribute name, probably finding an equals. | ||
// After an attribute name, probably finding an equals. | ||
/** @type {State} */ | ||
function afterAttributePrimaryName(code) { | ||
// Start of a local name. | ||
if (code === 58 /* `:` */) { | ||
if (code === 58) { | ||
effects.enter(tagAttributeNamePrefixMarkerType) | ||
@@ -464,6 +517,5 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // Start of an attribute value. | ||
// Start of an attribute value. | ||
if (code === 61 /* `=` */) { | ||
if (code === 61) { | ||
effects.exit(tagAttributeNameType) | ||
@@ -475,12 +527,11 @@ effects.enter(tagAttributeInitializerMarkerType) | ||
return optionalEsWhitespace | ||
} | ||
} // End of tag / new attribute. | ||
// End of tag / new attribute. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) || | ||
id.start(code) | ||
unicodeWhitespace(code) || | ||
(code !== null && idStart(code)) | ||
) { | ||
@@ -498,8 +549,9 @@ effects.exit(tagAttributeNameType) | ||
) | ||
} | ||
} // We’ve seen a `:`, and are expecting a local name. | ||
// We’ve seen a `:`, and are expecting a local name. | ||
/** @type {State} */ | ||
function beforeAttributeLocalName(code) { | ||
// Start of a local name. | ||
if (id.start(code)) { | ||
if (code !== null && idStart(code)) { | ||
effects.enter(tagAttributeNameLocalType) | ||
@@ -515,20 +567,20 @@ effects.consume(code) | ||
) | ||
} | ||
} // In the local attribute name. | ||
// In the local attribute name. | ||
/** @type {State} */ | ||
function attributeLocalName(code) { | ||
// Continuation of the local attribute name. | ||
if (code === 45 /* `-` */ || id.cont(code)) { | ||
if (code === 45 || (code !== null && idCont(code))) { | ||
effects.consume(code) | ||
return attributeLocalName | ||
} | ||
} // End of tag / attribute name. | ||
// End of tag / attribute name. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 61 /* `=` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
code === 47 || | ||
code === 61 || | ||
code === 62 || | ||
code === 123 || | ||
markdownLineEndingOrSpace(code) || | ||
esWhitespace(code) | ||
unicodeWhitespace(code) | ||
) { | ||
@@ -546,8 +598,9 @@ effects.exit(tagAttributeNameLocalType) | ||
) | ||
} | ||
} // After a local attribute name, expecting an equals. | ||
// After a local attribute name, expecting an equals. | ||
/** @type {State} */ | ||
function afterAttributeLocalName(code) { | ||
// Start of an attribute value. | ||
if (code === 61 /* `=` */) { | ||
if (code === 61) { | ||
effects.enter(tagAttributeInitializerMarkerType) | ||
@@ -558,10 +611,9 @@ effects.consume(code) | ||
return optionalEsWhitespace | ||
} | ||
} // End of tag / new attribute. | ||
// End of tag / new attribute. | ||
if ( | ||
code === 47 /* `/` */ || | ||
code === 62 /* `>` */ || | ||
code === 123 /* `{` */ || | ||
id.start(code) | ||
code === 47 || | ||
code === 62 || | ||
code === 123 || | ||
(code !== null && idStart(code)) | ||
) { | ||
@@ -577,8 +629,9 @@ effects.exit(tagAttributeType) | ||
) | ||
} | ||
} // After an attribute value initializer, expecting quotes and such. | ||
// After an attribute value initializer, expecting quotes and such. | ||
/** @type {State} */ | ||
function beforeAttributeValue(code) { | ||
// Start of double- or single quoted value. | ||
if (code === 34 /* `"` */ || code === 39 /* `'` */) { | ||
if (code === 34 || code === 39) { | ||
effects.enter(tagAttributeValueLiteralType) | ||
@@ -590,19 +643,18 @@ effects.enter(tagAttributeValueLiteralMarkerType) | ||
return attributeValueQuotedStart | ||
} | ||
} // Start of an assignment expression. | ||
// Start of an assignment expression. | ||
if (code === 123 /* `{` */) { | ||
return factoryExpression.call( | ||
if (code === 123) { | ||
return factoryMdxExpression.call( | ||
self, | ||
effects, | ||
afterAttributeValueExpression, | ||
nok, | ||
tagAttributeValueExpressionType, | ||
tagAttributeValueExpressionMarkerType, | ||
tagAttributeValueExpressionMarkerValue, | ||
acorn, | ||
acornOptions, | ||
addResult, | ||
tagAttributeValueExpressionType, | ||
tagAttributeValueExpressionMarkerType, | ||
tagAttributeValueExpressionMarkerValue, | ||
false, | ||
true | ||
false, | ||
allowLazy | ||
)(code) | ||
@@ -615,3 +667,3 @@ } | ||
'a character that can start an attribute value, such as `"`, `\'`, or `{`' + | ||
(code === 60 /* `<` */ | ||
(code === 60 | ||
? ' (note: to use an element or fragment as a prop value in MDX, use `{<element />}`)' | ||
@@ -621,2 +673,3 @@ : '') | ||
} | ||
/** @type {State} */ | ||
@@ -627,11 +680,12 @@ function afterAttributeValueExpression(code) { | ||
return optionalEsWhitespace(code) | ||
} | ||
} // At the start of a quoted attribute value. | ||
// At the start of a quoted attribute value. | ||
/** @type {State} */ | ||
function attributeValueQuotedStart(code) { | ||
if (code === null /* EOF */) { | ||
if (code === null) { | ||
crash( | ||
code, | ||
'in attribute value', | ||
'a corresponding closing quote `' + fromCharCode(marker) + '`' | ||
'a corresponding closing quote `' + String.fromCharCode(marker) + '`' | ||
) | ||
@@ -658,5 +712,6 @@ } | ||
return attributeValueQuoted(code) | ||
} | ||
} // In a quoted attribute value. | ||
// In a quoted attribute value. | ||
/** @type {State} */ | ||
function attributeValueQuoted(code) { | ||
@@ -666,13 +721,13 @@ if (code === null || code === marker || markdownLineEnding(code)) { | ||
return attributeValueQuotedStart(code) | ||
} | ||
} // Continuation. | ||
// Continuation. | ||
effects.consume(code) | ||
return attributeValueQuoted | ||
} | ||
} // Right after the slash on a tag, e.g., `<asd /`. | ||
// Right after the slash on a tag, e.g., `<asd /`. | ||
/** @type {State} */ | ||
function selfClosing(code) { | ||
// End of tag. | ||
if (code === 62 /* `>` */) { | ||
if (code === 62) { | ||
return tagEnd(code) | ||
@@ -685,12 +740,11 @@ } | ||
'`>` to end the tag' + | ||
(code === 42 /* `*` */ || code === 47 /* `/` */ | ||
(code === 42 || code === 47 | ||
? ' (note: JS comments in JSX tags are not supported in MDX)' | ||
: '') | ||
) | ||
} | ||
} // At a `>`. | ||
// At a `>`. | ||
/** @type {State} */ | ||
function tagEnd(code) { | ||
/* istanbul ignore if - never passed */ | ||
if (code !== 62 /* `>` */) throw new Error('expected `>`') | ||
effects.enter(tagMarkerType) | ||
@@ -701,14 +755,19 @@ effects.consume(code) | ||
return ok | ||
} | ||
} // Optionally start whitespace. | ||
// Optionally start whitespace. | ||
/** @type {State} */ | ||
function optionalEsWhitespace(code) { | ||
if (markdownLineEnding(code)) { | ||
effects.enter('lineEnding') | ||
effects.consume(code) | ||
effects.exit('lineEnding') | ||
return optionalEsWhitespace | ||
if (allowLazy) { | ||
effects.enter('lineEnding') | ||
effects.consume(code) | ||
effects.exit('lineEnding') | ||
return optionalEsWhitespace | ||
} | ||
return effects.attempt(lazyLineEnd, optionalEsWhitespace, crashEol)(code) | ||
} | ||
if (markdownSpace(code) || esWhitespace(code)) { | ||
if (markdownSpace(code) || unicodeWhitespace(code)) { | ||
effects.enter('esWhitespace') | ||
@@ -719,9 +778,10 @@ return optionalEsWhitespaceContinue(code) | ||
return returnState(code) | ||
} | ||
} // Continue optional whitespace. | ||
// Continue optional whitespace. | ||
/** @type {State} */ | ||
function optionalEsWhitespaceContinue(code) { | ||
if ( | ||
markdownLineEnding(code) || | ||
!(markdownSpace(code) || esWhitespace(code)) | ||
!(markdownSpace(code) || unicodeWhitespace(code)) | ||
) { | ||
@@ -735,6 +795,20 @@ effects.exit('esWhitespace') | ||
} | ||
/** @type {State} */ | ||
// Crash at a nonconforming character. | ||
function crashEol() { | ||
throw new VFileMessage( | ||
'Unexpected lazy line in container, expected line to be prefixed with `>` when in a block quote, whitespace when in a list, etc', | ||
self.now(), | ||
'micromark-extension-mdx-jsx:unexpected-eof' | ||
) | ||
} // Crash at a nonconforming character. | ||
/** | ||
* @param {Code} code | ||
* @param {string} at | ||
* @param {string} expect | ||
*/ | ||
function crash(code, at, expect) { | ||
throw new VMessage( | ||
throw new VFileMessage( | ||
'Unexpected ' + | ||
@@ -744,3 +818,3 @@ (code === null | ||
: 'character `' + | ||
(code === 96 /* `` ` `` */ ? '` ` `' : fromCharCode(code)) + | ||
(code === 96 ? '` ` `' : String.fromCharCode(code)) + | ||
'` (' + | ||
@@ -759,7 +833,28 @@ serializeCharCode(code) + | ||
} | ||
/** @type {Tokenizer} */ | ||
function tokenizeLazyLineEnd(effects, ok, nok) { | ||
const self = this | ||
return start | ||
/** @type {State} */ | ||
function start(code) { | ||
effects.enter('lineEnding') | ||
effects.consume(code) | ||
effects.exit('lineEnding') | ||
return lineStart | ||
} | ||
/** @type {State} */ | ||
function lineStart(code) { | ||
return self.parser.lazy[self.now().line] ? nok(code) : ok(code) | ||
} | ||
} | ||
/** | ||
* @param {NonNullable<Code>} code | ||
* @returns {string} | ||
*/ | ||
function serializeCharCode(code) { | ||
var value = code.toString(16).toUpperCase() | ||
while (value.length < 4) value = '0' + value | ||
return 'U+' + value | ||
return 'U+' + code.toString(16).toUpperCase().padStart(4, '0') | ||
} |
@@ -1,16 +0,29 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('micromark-util-types').Construct} Construct | ||
* @typedef {import('micromark-util-types').Tokenizer} Tokenizer | ||
* @typedef {import('micromark-util-types').State} State | ||
* @typedef {import('micromark-factory-mdx-expression').Acorn} Acorn | ||
* @typedef {import('micromark-factory-mdx-expression').AcornOptions} AcornOptions | ||
*/ | ||
import {factorySpace} from 'micromark-factory-space' | ||
import {markdownLineEnding} from 'micromark-util-character' | ||
import {factoryTag} from './factory-tag.js' | ||
/** | ||
* @param {Acorn|undefined} acorn | ||
* @param {AcornOptions|undefined} acornOptions | ||
* @param {boolean|undefined} addResult | ||
* @returns {Construct} | ||
*/ | ||
module.exports = createJsxFlow | ||
export function jsxFlow(acorn, acornOptions, addResult) { | ||
return { | ||
tokenize: tokenizeJsxFlow, | ||
concrete: true | ||
} | ||
/** @type {Tokenizer} */ | ||
var markdownLineEnding = require('micromark/dist/character/markdown-line-ending') | ||
var factorySpace = require('micromark/dist/tokenize/factory-space') | ||
var factoryTag = require('./factory-tag') | ||
function createJsxFlow(acorn, acornOptions, addResult) { | ||
return {tokenize: tokenizeJsxFlow, concrete: true} | ||
function tokenizeJsxFlow(effects, ok, nok) { | ||
var self = this | ||
const self = this | ||
return start | ||
/** @type {State} */ | ||
@@ -26,2 +39,3 @@ function start(code) { | ||
addResult, | ||
false, | ||
'mdxJsxFlowTag', | ||
@@ -54,12 +68,13 @@ 'mdxJsxFlowTagMarker', | ||
} | ||
/** @type {State} */ | ||
function after(code) { | ||
// Another tag. | ||
if (code === 60 /* `<` */) { | ||
return start(code) | ||
} | ||
return code === null || markdownLineEnding(code) ? ok(code) : nok(code) | ||
return code === 60 | ||
? start(code) | ||
: code === null || markdownLineEnding(code) | ||
? ok(code) | ||
: nok(code) | ||
} | ||
} | ||
} |
@@ -1,10 +0,21 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('micromark-util-types').Construct} Construct | ||
* @typedef {import('micromark-util-types').Tokenizer} Tokenizer | ||
* @typedef {import('micromark-factory-mdx-expression').Acorn} Acorn | ||
* @typedef {import('micromark-factory-mdx-expression').AcornOptions} AcornOptions | ||
*/ | ||
import {factoryTag} from './factory-tag.js' | ||
/** | ||
* @param {Acorn|undefined} acorn | ||
* @param {AcornOptions|undefined} acornOptions | ||
* @param {boolean|undefined} addResult | ||
* @returns {Construct} | ||
*/ | ||
module.exports = createJsxText | ||
export function jsxText(acorn, acornOptions, addResult) { | ||
return { | ||
tokenize: tokenizeJsxText | ||
} | ||
/** @type {Tokenizer} */ | ||
var factoryTag = require('./factory-tag') | ||
function createJsxText(acorn, acornOptions, addResult) { | ||
return {tokenize: tokenizeJsxText} | ||
function tokenizeJsxText(effects, ok, nok) { | ||
@@ -19,2 +30,3 @@ return factoryTag.call( | ||
addResult, | ||
true, | ||
'mdxJsxTextTag', | ||
@@ -21,0 +33,0 @@ 'mdxJsxTextTagMarker', |
{ | ||
"name": "micromark-extension-mdx-jsx", | ||
"version": "0.3.3", | ||
"version": "1.0.0", | ||
"description": "micromark extension to support MDX or MDX.js JSX", | ||
@@ -29,35 +29,51 @@ "license": "MIT", | ||
], | ||
"sideEffects": false, | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"dev/", | ||
"lib/", | ||
"index.d.ts", | ||
"index.js" | ||
], | ||
"exports": { | ||
"development": "./dev/index.js", | ||
"default": "./index.js" | ||
}, | ||
"dependencies": { | ||
"estree-util-is-identifier-name": "^1.0.0", | ||
"micromark": "~2.11.0", | ||
"micromark-extension-mdx-expression": "^0.3.2", | ||
"vfile-message": "^2.0.0" | ||
"@types/acorn": "^4.0.0", | ||
"estree-util-is-identifier-name": "^2.0.0", | ||
"micromark-factory-mdx-expression": "^1.0.0", | ||
"micromark-factory-space": "^1.0.0", | ||
"micromark-util-character": "^1.0.0", | ||
"micromark-util-symbol": "^1.0.0", | ||
"micromark-util-types": "^1.0.0", | ||
"vfile-message": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/mdast": "^3.0.0", | ||
"@types/tape": "^4.0.0", | ||
"acorn": "^8.0.0", | ||
"acorn-jsx": "^5.0.0", | ||
"mdast-zone": "^4.0.0", | ||
"nyc": "^15.0.0", | ||
"c8": "^7.0.0", | ||
"mdast-zone": "^5.0.0", | ||
"micromark": "^3.0.0", | ||
"micromark-build": "^1.0.0", | ||
"prettier": "^2.0.0", | ||
"remark-cli": "^9.0.0", | ||
"remark-preset-wooorm": "^8.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"xo": "^0.38.0" | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"xo": "^0.39.0" | ||
}, | ||
"scripts": { | ||
"build": "rimraf \"dev/**/*.d.ts\" \"script/**/*.d.ts\" \"test/**/*.d.ts\" && tsc && type-coverage && micromark-build", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test.js", | ||
"test": "npm run format && npm run test-coverage" | ||
"test-api": "node --conditions development test/index.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test/index.js", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"prettier": { | ||
@@ -73,5 +89,3 @@ "tabWidth": 2, | ||
"prettier": true, | ||
"esnext": false, | ||
"rules": { | ||
"max-params": "off", | ||
"unicorn/no-this-assignment": "off" | ||
@@ -85,3 +99,9 @@ } | ||
] | ||
}, | ||
"typeCoverage": { | ||
"atLeast": 100, | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true | ||
} | ||
} |
@@ -16,10 +16,18 @@ # micromark-extension-mdx-jsx | ||
You should use this with [`mdast-util-mdx-jsx`][util] (**[mdast][]**). | ||
Alternatively, use either [`micromark-extension-mdx`][mdx] or | ||
[`micromark-extension-mdxjs`][mdxjs] with [`mdast-util-mdx`][mdast-util-mdx] to | ||
support all of MDX (or MDX.js). | ||
Or, use it through [`remark-mdx`][remark-mdx] (**[remark][]**). | ||
## When to use this | ||
This package is already included in [xdm][] and [`mdx-js/mdx` (next)][mdx-js]. | ||
You should probably use [`micromark-extension-mdx`][mdx] or | ||
[`micromark-extension-mdxjs`][mdxjs] instead, which combine this package with | ||
other MDX features. | ||
Alternatively, if you’re using [`micromark`][micromark] or | ||
[`mdast-util-from-markdown`][from-markdown] and you don’t want all of MDX, use | ||
this package. | ||
## 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. | ||
[npm][]: | ||
@@ -33,14 +41,36 @@ | ||
See [`mdast-util-mdx-jsx`][util] for an example. | ||
```js | ||
import {micromark} from 'micromark' | ||
import {mdxJsx} from 'micromark-extension-mdx-jsx' | ||
const output = micromark('a <b c d="e" /> f', {extensions: [mdxJsx()]}) | ||
console.log(output) | ||
``` | ||
Yields: | ||
```html | ||
<p>a f</p> | ||
``` | ||
…which is rather useless: go to a syntax tree with | ||
[`mdast-util-from-markdown`][from-markdown] and | ||
[`mdast-util-mdx-expression`][util] instead. | ||
## API | ||
### `syntax(options?)` | ||
This package exports the following identifiers: `mdxJsx`. | ||
There is no default export. | ||
Support [MDX][mdx-js] (or MDX.js) JSX. | ||
The export map supports the endorsed | ||
[`development` condition](https://nodejs.org/api/packages.html#packages_resolving_user_conditions). | ||
Run `node --conditions development module.js` to get instrumented dev code. | ||
Without this condition, production code is loaded. | ||
The export of `syntax` is a function that can be called with options and returns | ||
an extension for the micromark parser (to tokenize JSX; can be passed in | ||
`extensions`). | ||
### `mdxJsx(options?)` | ||
A function that can be called with options that returns an extension for | ||
micromark to parse JSX (can be passed in `extensions`). | ||
##### `options` | ||
@@ -357,6 +387,4 @@ | ||
[remark]: https://github.com/remarkjs/remark | ||
[xdm]: https://github.com/wooorm/xdm | ||
[mdast]: https://github.com/syntax-tree/mdast | ||
[mdx-js]: https://github.com/mdx-js/mdx | ||
@@ -382,2 +410,2 @@ | ||
[remark-mdx]: https://github.com/mdx-js/mdx/tree/next/packages/remark-mdx | ||
[from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
89107
23
2100
1
408
Yes
8
16
1
+ Added@types/acorn@^4.0.0
+ Addedmicromark-util-symbol@^1.0.0
+ Addedmicromark-util-types@^1.0.0
+ Added@types/acorn@4.0.6(transitive)
+ Added@types/estree@1.0.5(transitive)
+ Added@types/estree-jsx@1.0.5(transitive)
+ Addeddequal@2.0.3(transitive)
+ Addeddiff@5.2.0(transitive)
+ Addedestree-util-is-identifier-name@2.1.0(transitive)
+ Addedestree-util-visit@1.2.1(transitive)
+ Addedkleur@4.1.5(transitive)
+ Addedmicromark-factory-mdx-expression@1.0.9(transitive)
+ Addedmicromark-factory-space@1.1.0(transitive)
+ Addedmicromark-util-character@1.2.0(transitive)
+ Addedmicromark-util-events-to-acorn@1.2.3(transitive)
+ Addedmicromark-util-symbol@1.1.0(transitive)
+ Addedmicromark-util-types@1.1.0(transitive)
+ Addedmri@1.2.0(transitive)
+ Addedsade@1.8.1(transitive)
+ Addedunist-util-position-from-estree@1.1.2(transitive)
+ Addedunist-util-stringify-position@3.0.3(transitive)
+ Addeduvu@0.5.6(transitive)
+ Addedvfile-message@3.1.4(transitive)
- Removedmicromark@~2.11.0
- Removedcharacter-entities@1.2.4(transitive)
- Removedcharacter-entities-legacy@1.1.4(transitive)
- Removedcharacter-reference-invalid@1.1.4(transitive)
- Removeddebug@4.3.7(transitive)
- Removedestree-util-is-identifier-name@1.1.0(transitive)
- Removedis-alphabetical@1.0.4(transitive)
- Removedis-alphanumerical@1.0.4(transitive)
- Removedis-decimal@1.0.4(transitive)
- Removedis-hexadecimal@1.0.4(transitive)
- Removedmicromark@2.11.4(transitive)
- Removedmicromark-extension-mdx-expression@0.3.2(transitive)
- Removedms@2.1.3(transitive)
- Removedparse-entities@2.0.0(transitive)
- Removedunist-util-stringify-position@2.0.3(transitive)
- Removedvfile-message@2.0.4(transitive)
Updatedvfile-message@^3.0.0