@mdx-js/mdx
Advanced tools
Comparing version 2.1.2 to 2.1.3
@@ -227,6 +227,4 @@ /** | ||
child.type === 'ExpressionStatement' && | ||
// @ts-expect-error types are wrong: `JSXElement`/`JSXFragment` are | ||
// `Expression`s. | ||
// @ts-expect-error types are wrong: `JSXFragment` is an `Expression`. | ||
(child.expression.type === 'JSXFragment' || | ||
// @ts-expect-error " | ||
child.expression.type === 'JSXElement') | ||
@@ -527,3 +525,2 @@ ) { | ||
// @ts-expect-error: JSXElements are expressions. | ||
let result = /** @type {Expression} */ (element) | ||
@@ -547,2 +544,3 @@ | ||
// Unwrap a fragment of a single element. | ||
if ( | ||
@@ -549,0 +547,0 @@ argument && |
@@ -75,2 +75,4 @@ /** | ||
let currentScope | ||
/** @type {Map<string | number, string>} */ | ||
const idToInvalidComponentName = new Map() | ||
@@ -81,3 +83,2 @@ walk(tree, { | ||
const newScope = /** @type {Scope|undefined} */ ( | ||
// @ts-expect-error: periscopic doesn’t support JSX. | ||
scopeInfo.map.get(node) | ||
@@ -199,12 +200,20 @@ ) | ||
node.openingElement.name = toJsxIdOrMemberExpression([ | ||
'_components', | ||
id | ||
]) | ||
/** @type {Array<string | number>} */ | ||
let jsxIdExpression = ['_components', id] | ||
if (isIdentifierName(id) === false) { | ||
let invalidComponentName = idToInvalidComponentName.get(id) | ||
if (invalidComponentName === undefined) { | ||
invalidComponentName = `_component${idToInvalidComponentName.size}` | ||
idToInvalidComponentName.set(id, invalidComponentName) | ||
} | ||
jsxIdExpression = [invalidComponentName] | ||
} | ||
node.openingElement.name = | ||
toJsxIdOrMemberExpression(jsxIdExpression) | ||
if (node.closingElement) { | ||
node.closingElement.name = toJsxIdOrMemberExpression([ | ||
'_components', | ||
id | ||
]) | ||
node.closingElement.name = | ||
toJsxIdOrMemberExpression(jsxIdExpression) | ||
} | ||
@@ -266,3 +275,7 @@ } | ||
if (defaults.length > 0 || actual.length > 0) { | ||
if ( | ||
defaults.length > 0 || | ||
actual.length > 0 || | ||
idToInvalidComponentName.size > 0 | ||
) { | ||
if (providerImportSource) { | ||
@@ -352,2 +365,23 @@ importProvider = true | ||
if (isNamedFunction(scope.node, '_createMdxContent')) { | ||
for (const [id, componentName] of idToInvalidComponentName) { | ||
// For JSX IDs that can’t be represented as JavaScript IDs (as in, | ||
// those with dashes, such as `custom-element`), generate a | ||
// separate variable that is a valid JS ID (such as `_component0`), | ||
// and takes it from components: | ||
// `const _component0 = _components['custom-element']` | ||
declarations.push({ | ||
type: 'VariableDeclarator', | ||
id: {type: 'Identifier', name: componentName}, | ||
init: { | ||
type: 'MemberExpression', | ||
object: {type: 'Identifier', name: '_components'}, | ||
property: {type: 'Literal', value: id}, | ||
computed: true, | ||
optional: false | ||
} | ||
}) | ||
} | ||
} | ||
if (componentsPattern) { | ||
@@ -354,0 +388,0 @@ declarations.push({ |
@@ -8,110 +8,4 @@ /** | ||
export function recmaStringify(options?: RecmaStringifyOptions | undefined): void; | ||
export type Node = import('estree-jsx').Node; | ||
export type Program = import('estree-jsx').Program; | ||
export type JSXAttribute = import('estree-jsx').JSXAttribute; | ||
export type JSXClosingElement = import('estree-jsx').JSXClosingElement; | ||
export type JSXClosingFragment = import('estree-jsx').JSXClosingFragment; | ||
export type JSXElement = import('estree-jsx').JSXElement; | ||
export type JSXEmptyExpression = import('estree-jsx').JSXEmptyExpression; | ||
export type JSXExpressionContainer = import('estree-jsx').JSXExpressionContainer; | ||
export type JSXFragment = import('estree-jsx').JSXFragment; | ||
export type JSXIdentifier = import('estree-jsx').JSXIdentifier; | ||
export type JSXMemberExpression = import('estree-jsx').JSXMemberExpression; | ||
export type JSXNamespacedName = import('estree-jsx').JSXNamespacedName; | ||
export type JSXOpeningElement = import('estree-jsx').JSXOpeningElement; | ||
export type JSXOpeningFragment = import('estree-jsx').JSXOpeningFragment; | ||
export type JSXSpreadAttribute = import('estree-jsx').JSXSpreadAttribute; | ||
export type JSXText = import('estree-jsx').JSXText; | ||
export type VFile = import('vfile').VFile; | ||
export type SourceMapGenerator = typeof import('source-map').SourceMapGenerator; | ||
export type State = Omit<import("astring").State, "write"> & { | ||
write: (code: string, node?: Node) => void; | ||
}; | ||
export type Generator = { | ||
Identifier: (node: Node, state: State) => void; | ||
Literal: (node: Node, state: State) => void; | ||
Program: (node: Node, state: State) => void; | ||
FunctionDeclaration: (node: Node, state: State) => void; | ||
FunctionExpression: (node: Node, state: State) => void; | ||
ArrowFunctionExpression: (node: Node, state: State) => void; | ||
SwitchCase: (node: Node, state: State) => void; | ||
CatchClause: (node: Node, state: State) => void; | ||
VariableDeclarator: (node: Node, state: State) => void; | ||
ExpressionStatement: (node: Node, state: State) => void; | ||
BlockStatement: (node: Node, state: State) => void; | ||
StaticBlock: (node: Node, state: State) => void; | ||
EmptyStatement: (node: Node, state: State) => void; | ||
DebuggerStatement: (node: Node, state: State) => void; | ||
WithStatement: (node: Node, state: State) => void; | ||
ReturnStatement: (node: Node, state: State) => void; | ||
LabeledStatement: (node: Node, state: State) => void; | ||
BreakStatement: (node: Node, state: State) => void; | ||
ContinueStatement: (node: Node, state: State) => void; | ||
IfStatement: (node: Node, state: State) => void; | ||
SwitchStatement: (node: Node, state: State) => void; | ||
ThrowStatement: (node: Node, state: State) => void; | ||
TryStatement: (node: Node, state: State) => void; | ||
WhileStatement: (node: Node, state: State) => void; | ||
DoWhileStatement: (node: Node, state: State) => void; | ||
ForStatement: (node: Node, state: State) => void; | ||
ForInStatement: (node: Node, state: State) => void; | ||
ForOfStatement: (node: Node, state: State) => void; | ||
VariableDeclaration: (node: Node, state: State) => void; | ||
ClassDeclaration: (node: Node, state: State) => void; | ||
ThisExpression: (node: Node, state: State) => void; | ||
ArrayExpression: (node: Node, state: State) => void; | ||
ObjectExpression: (node: Node, state: State) => void; | ||
YieldExpression: (node: Node, state: State) => void; | ||
UnaryExpression: (node: Node, state: State) => void; | ||
UpdateExpression: (node: Node, state: State) => void; | ||
BinaryExpression: (node: Node, state: State) => void; | ||
AssignmentExpression: (node: Node, state: State) => void; | ||
LogicalExpression: (node: Node, state: State) => void; | ||
MemberExpression: (node: Node, state: State) => void; | ||
ConditionalExpression: (node: Node, state: State) => void; | ||
CallExpression: (node: Node, state: State) => void; | ||
NewExpression: (node: Node, state: State) => void; | ||
SequenceExpression: (node: Node, state: State) => void; | ||
TemplateLiteral: (node: Node, state: State) => void; | ||
TaggedTemplateExpression: (node: Node, state: State) => void; | ||
ClassExpression: (node: Node, state: State) => void; | ||
MetaProperty: (node: Node, state: State) => void; | ||
AwaitExpression: (node: Node, state: State) => void; | ||
ImportExpression: (node: Node, state: State) => void; | ||
ChainExpression: (node: Node, state: State) => void; | ||
PrivateIdentifier: (node: Node, state: State) => void; | ||
Property: (node: Node, state: State) => void; | ||
PropertyDefinition: (node: Node, state: State) => void; | ||
Super: (node: Node, state: State) => void; | ||
TemplateElement: (node: Node, state: State) => void; | ||
SpreadElement: (node: Node, state: State) => void; | ||
ObjectPattern: (node: Node, state: State) => void; | ||
ArrayPattern: (node: Node, state: State) => void; | ||
RestElement: (node: Node, state: State) => void; | ||
AssignmentPattern: (node: Node, state: State) => void; | ||
ClassBody: (node: Node, state: State) => void; | ||
MethodDefinition: (node: Node, state: State) => void; | ||
ImportDeclaration: (node: Node, state: State) => void; | ||
ExportNamedDeclaration: (node: Node, state: State) => void; | ||
ExportDefaultDeclaration: (node: Node, state: State) => void; | ||
ExportAllDeclaration: (node: Node, state: State) => void; | ||
ImportSpecifier: (node: Node, state: State) => void; | ||
ImportDefaultSpecifier: (node: Node, state: State) => void; | ||
ImportNamespaceSpecifier: (node: Node, state: State) => void; | ||
ExportSpecifier: (node: Node, state: State) => void; | ||
JSXIdentifier: (node: Node, state: State) => void; | ||
JSXNamespacedName: (node: Node, state: State) => void; | ||
JSXMemberExpression: (node: Node, state: State) => void; | ||
JSXEmptyExpression: (node: Node, state: State) => void; | ||
JSXExpressionContainer: (node: Node, state: State) => void; | ||
JSXSpreadAttribute: (node: Node, state: State) => void; | ||
JSXAttribute: (node: Node, state: State) => void; | ||
JSXOpeningElement: (node: Node, state: State) => void; | ||
JSXOpeningFragment: (node: Node, state: State) => void; | ||
JSXClosingElement: (node: Node, state: State) => void; | ||
JSXClosingFragment: (node: Node, state: State) => void; | ||
JSXElement: (node: Node, state: State) => void; | ||
JSXFragment: (node: Node, state: State) => void; | ||
JSXText: (node: Node, state: State) => void; | ||
}; | ||
export type RecmaStringifyOptions = { | ||
@@ -118,0 +12,0 @@ /** |
/** | ||
* @typedef {import('estree-jsx').Node} Node | ||
* @typedef {import('estree-jsx').Program} Program | ||
* @typedef {import('estree-jsx').JSXAttribute} JSXAttribute | ||
* @typedef {import('estree-jsx').JSXClosingElement} JSXClosingElement | ||
* @typedef {import('estree-jsx').JSXClosingFragment} JSXClosingFragment | ||
* @typedef {import('estree-jsx').JSXElement} JSXElement | ||
* @typedef {import('estree-jsx').JSXEmptyExpression} JSXEmptyExpression | ||
* @typedef {import('estree-jsx').JSXExpressionContainer} JSXExpressionContainer | ||
* @typedef {import('estree-jsx').JSXFragment} JSXFragment | ||
* @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier | ||
* @typedef {import('estree-jsx').JSXMemberExpression} JSXMemberExpression | ||
* @typedef {import('estree-jsx').JSXNamespacedName} JSXNamespacedName | ||
* @typedef {import('estree-jsx').JSXOpeningElement} JSXOpeningElement | ||
* @typedef {import('estree-jsx').JSXOpeningFragment} JSXOpeningFragment | ||
* @typedef {import('estree-jsx').JSXSpreadAttribute} JSXSpreadAttribute | ||
* @typedef {import('estree-jsx').JSXText} JSXText | ||
* @typedef {import('vfile').VFile} VFile | ||
* @typedef {typeof import('source-map').SourceMapGenerator} SourceMapGenerator | ||
* | ||
* @typedef {Omit<import('astring').State, 'write'> & {write: ((code: string, node?: Node) => void)}} State | ||
* | ||
* @typedef {{[K in Node['type']]: (node: Node, state: State) => void}} Generator | ||
* | ||
* @typedef RecmaStringifyOptions | ||
@@ -31,3 +11,3 @@ * @property {SourceMapGenerator} [SourceMapGenerator] | ||
import {GENERATOR, generate} from 'astring' | ||
import {toJs, jsx} from 'estree-util-to-js' | ||
@@ -47,302 +27,14 @@ /** | ||
function compiler(tree, file) { | ||
/** @type {InstanceType<SourceMapGenerator>|undefined} */ | ||
let sourceMap | ||
const result = SourceMapGenerator | ||
? toJs(tree, { | ||
filePath: file.path || 'unknown.mdx', | ||
SourceMapGenerator, | ||
handlers: jsx | ||
}) | ||
: toJs(tree, {handlers: jsx}) | ||
if (SourceMapGenerator) { | ||
sourceMap = new SourceMapGenerator({file: file.path || 'unknown.mdx'}) | ||
} | ||
file.map = result.map | ||
const generator = { | ||
...GENERATOR, | ||
JSXAttribute, | ||
JSXClosingElement, | ||
JSXClosingFragment, | ||
JSXElement, | ||
JSXEmptyExpression, | ||
JSXExpressionContainer, | ||
JSXFragment, | ||
JSXIdentifier, | ||
JSXMemberExpression, | ||
JSXNamespacedName, | ||
JSXOpeningElement, | ||
JSXOpeningFragment, | ||
JSXSpreadAttribute, | ||
JSXText | ||
} | ||
const result = generate(tree, { | ||
generator, | ||
comments: true, | ||
sourceMap | ||
}) | ||
if (sourceMap) { | ||
file.map = sourceMap.toJSON() | ||
} | ||
return result | ||
return result.value | ||
} | ||
} | ||
/** | ||
* `attr` | ||
* `attr="something"` | ||
* `attr={1}` | ||
* | ||
* @this {Generator} | ||
* @param {JSXAttribute} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXAttribute(node, state) { | ||
this[node.name.type](node.name, state) | ||
if (node.value !== undefined && node.value !== null) { | ||
state.write('=') | ||
// Encode double quotes in attribute values. | ||
if (node.value.type === 'Literal') { | ||
state.write( | ||
'"' + encodeJsx(String(node.value.value)).replace(/"/g, '"') + '"', | ||
node | ||
) | ||
} else { | ||
this[node.value.type](node.value, state) | ||
} | ||
} | ||
} | ||
/** | ||
* `</div>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXClosingElement} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXClosingElement(node, state) { | ||
state.write('</') | ||
this[node.name.type](node.name, state) | ||
state.write('>') | ||
} | ||
/** | ||
* `</>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXClosingFragment} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXClosingFragment(node, state) { | ||
state.write('</>', node) | ||
} | ||
/** | ||
* `<div />` | ||
* `<div></div>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXElement} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXElement(node, state) { | ||
let index = -1 | ||
this[node.openingElement.type](node.openingElement, state) | ||
if (node.children) { | ||
while (++index < node.children.length) { | ||
const child = node.children[index] | ||
// Supported in types but not by Acorn. | ||
/* c8 ignore next 3 */ | ||
if (child.type === 'JSXSpreadChild') { | ||
throw new Error('JSX spread children are not supported') | ||
} | ||
this[child.type](child, state) | ||
} | ||
} | ||
if (node.closingElement) { | ||
this[node.closingElement.type](node.closingElement, state) | ||
} | ||
} | ||
/** | ||
* `{}` (always in a `JSXExpressionContainer`, which does the curlies) | ||
* | ||
* @this {Generator} | ||
* @returns {void} | ||
*/ | ||
function JSXEmptyExpression() {} | ||
/** | ||
* `{expression}` | ||
* | ||
* @this {Generator} | ||
* @param {JSXExpressionContainer} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXExpressionContainer(node, state) { | ||
state.write('{') | ||
this[node.expression.type](node.expression, state) | ||
state.write('}') | ||
} | ||
/** | ||
* `<></>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXFragment} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXFragment(node, state) { | ||
let index = -1 | ||
this[node.openingFragment.type](node.openingFragment, state) | ||
if (node.children) { | ||
while (++index < node.children.length) { | ||
const child = node.children[index] | ||
// Supported in types but not by Acorn. | ||
/* c8 ignore next 3 */ | ||
if (child.type === 'JSXSpreadChild') { | ||
throw new Error('JSX spread children are not supported') | ||
} | ||
this[child.type](child, state) | ||
} | ||
} | ||
this[node.closingFragment.type](node.closingFragment, state) | ||
} | ||
/** | ||
* `div` | ||
* | ||
* @this {Generator} | ||
* @param {JSXIdentifier} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXIdentifier(node, state) { | ||
state.write(node.name, node) | ||
} | ||
/** | ||
* `member.expression` | ||
* | ||
* @this {Generator} | ||
* @param {JSXMemberExpression} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXMemberExpression(node, state) { | ||
this[node.object.type](node.object, state) | ||
state.write('.') | ||
this[node.property.type](node.property, state) | ||
} | ||
/** | ||
* `ns:name` | ||
* | ||
* @this {Generator} | ||
* @param {JSXNamespacedName} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXNamespacedName(node, state) { | ||
this[node.namespace.type](node.namespace, state) | ||
state.write(':') | ||
this[node.name.type](node.name, state) | ||
} | ||
/** | ||
* `<div>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXOpeningElement} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXOpeningElement(node, state) { | ||
let index = -1 | ||
state.write('<') | ||
this[node.name.type](node.name, state) | ||
if (node.attributes) { | ||
while (++index < node.attributes.length) { | ||
state.write(' ') | ||
this[node.attributes[index].type](node.attributes[index], state) | ||
} | ||
} | ||
state.write(node.selfClosing ? ' />' : '>') | ||
} | ||
/** | ||
* `<>` | ||
* | ||
* @this {Generator} | ||
* @param {JSXOpeningFragment} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXOpeningFragment(node, state) { | ||
state.write('<>', node) | ||
} | ||
/** | ||
* `{...argument}` | ||
* | ||
* @this {Generator} | ||
* @param {JSXSpreadAttribute} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXSpreadAttribute(node, state) { | ||
state.write('{') | ||
// eslint-disable-next-line new-cap | ||
this.SpreadElement(node, state) | ||
state.write('}') | ||
} | ||
/** | ||
* `!` | ||
* | ||
* @this {Generator} | ||
* @param {JSXText} node | ||
* @param {State} state | ||
* @returns {void} | ||
*/ | ||
function JSXText(node, state) { | ||
state.write( | ||
encodeJsx(node.value).replace(/<|{/g, ($0) => | ||
$0 === '<' ? '<' : '{' | ||
), | ||
node | ||
) | ||
} | ||
/** | ||
* Make sure that character references don’t pop up. | ||
* For example, the text `©` should stay that way, and not turn into `©`. | ||
* We could encode all `&` (easy but verbose) or look for actual valid | ||
* references (complex but cleanest output). | ||
* Looking for the 2nd character gives us a middle ground. | ||
* The `#` is for (decimal and hexadecimal) numeric references, the letters | ||
* are for the named references. | ||
* | ||
* @param {string} value | ||
* @returns {string} | ||
*/ | ||
function encodeJsx(value) { | ||
return value.replace(/&(?=[#a-z])/gi, '&') | ||
} |
@@ -10,3 +10,3 @@ /** | ||
*/ | ||
export function create<N extends import("estree-jsx").Node>(template: Node, node: N): N; | ||
export function create<N extends import("estree").Node>(template: Node, node: N): N; | ||
export type Node = import('estree-jsx').Node; |
{ | ||
"name": "@mdx-js/mdx", | ||
"version": "2.1.2", | ||
"version": "2.1.3", | ||
"description": "MDX compiler", | ||
@@ -49,7 +49,7 @@ "license": "MIT", | ||
"dependencies": { | ||
"@types/estree-jsx": "^0.0.1", | ||
"@types/estree-jsx": "^1.0.0", | ||
"@types/mdx": "^2.0.0", | ||
"astring": "^1.6.0", | ||
"estree-util-build-jsx": "^2.0.0", | ||
"estree-util-is-identifier-name": "^2.0.0", | ||
"estree-util-to-js": "^1.1.0", | ||
"estree-walker": "^3.0.0", | ||
@@ -56,0 +56,0 @@ "hast-util-to-estree": "^2.0.0", |
123602
2440
+ Addedestree-util-to-js@^1.1.0
+ Addedestree-util-to-js@1.2.0(transitive)
+ Addedsource-map@0.7.4(transitive)
- Removedastring@^1.6.0
- Removed@types/estree-jsx@0.0.1(transitive)
Updated@types/estree-jsx@^1.0.0