This commit is contained in:
2024-03-22 03:47:51 +05:30
parent 8bcf3d211e
commit 89819f6fe2
28440 changed files with 3211033 additions and 2 deletions

View File

@@ -0,0 +1,16 @@
/**
* Turn a hast comment into an estree node.
*
* @param {HastComment} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer}
* estree expression.
*/
export function comment(node: HastComment, state: State): JsxExpressionContainer;
export type Comment = import('estree').Comment;
export type JsxEmptyExpression = import('estree-jsx').JSXEmptyExpression;
export type JsxExpressionContainer = import('estree-jsx').JSXExpressionContainer;
export type HastComment = import('hast').Comment;
export type State = import('../state.js').State;

View File

@@ -0,0 +1,43 @@
/**
* @typedef {import('estree').Comment} Comment
*
* @typedef {import('estree-jsx').JSXEmptyExpression} JsxEmptyExpression
* @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer
*
* @typedef {import('hast').Comment} HastComment
*
* @typedef {import('../state.js').State} State
*/
// Make VS Code show references to the above types.
''
/**
* Turn a hast comment into an estree node.
*
* @param {HastComment} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer}
* estree expression.
*/
export function comment(node, state) {
/** @type {Comment} */
const result = {type: 'Block', value: node.value}
state.inherit(node, result)
state.comments.push(result)
/** @type {JsxEmptyExpression} */
const expression = {
type: 'JSXEmptyExpression',
// @ts-expect-error: `comments` is custom.
comments: [Object.assign({}, result, {leading: false, trailing: true})]
}
state.patch(node, expression)
/** @type {JsxExpressionContainer} */
const container = {type: 'JSXExpressionContainer', expression}
state.patch(node, container)
return container
}

View File

@@ -0,0 +1,18 @@
/**
* Turn a hast element into an estree node.
*
* @param {HastElement} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxElement}
* estree expression.
*/
export function element(node: HastElement, state: State): JsxElement;
export type Property = import('estree').Property;
export type JsxAttribute = import('estree-jsx').JSXAttribute;
export type JsxElement = import('estree-jsx').JSXElement;
export type JsxSpreadAttribute = import('estree-jsx').JSXSpreadAttribute;
export type HastElement = import('hast').Element;
export type State = import('../state.js').State;
export type Style = Record<string, string>;

View File

@@ -0,0 +1,335 @@
/**
* @typedef {import('estree').Property} Property
*
* @typedef {import('estree-jsx').JSXAttribute} JsxAttribute
* @typedef {import('estree-jsx').JSXElement} JsxElement
* @typedef {import('estree-jsx').JSXSpreadAttribute} JsxSpreadAttribute
*
* @typedef {import('hast').Element} HastElement
*
* @typedef {import('../state.js').State} State
*/
/**
* @typedef {Record<string, string>} Style
*/
import {stringify as commas} from 'comma-separated-tokens'
import {name as identifierName} from 'estree-util-is-identifier-name'
import {find, hastToReact, svg} from 'property-information'
import {stringify as spaces} from 'space-separated-tokens'
import styleToObject from 'style-to-object'
const own = {}.hasOwnProperty
const cap = /[A-Z]/g
const dashSomething = /-([a-z])/g
const tableCellElement = new Set(['td', 'th'])
/**
* Turn a hast element into an estree node.
*
* @param {HastElement} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxElement}
* estree expression.
*/
// eslint-disable-next-line complexity
export function element(node, state) {
const parentSchema = state.schema
let schema = parentSchema
const props = node.properties || {}
if (parentSchema.space === 'html' && node.tagName.toLowerCase() === 'svg') {
schema = svg
state.schema = schema
}
const children = state.all(node)
/** @type {Array<JsxAttribute | JsxSpreadAttribute>} */
const attributes = []
/** @type {string} */
let prop
/** @type {string | undefined} */
let alignValue
/** @type {Array<Property> | undefined} */
let styleProperties
for (prop in props) {
if (own.call(props, prop)) {
let value = props[prop]
const info = find(schema, prop)
/** @type {JsxAttribute['value']} */
let attributeValue
// Ignore nullish and `NaN` values.
// Ignore `false` and falsey known booleans.
if (
value === null ||
value === undefined ||
value === false ||
(typeof value === 'number' && Number.isNaN(value)) ||
(!value && info.boolean)
) {
continue
}
prop =
state.elementAttributeNameCase === 'react' && info.space
? hastToReact[info.property] || info.property
: info.attribute
if (Array.isArray(value)) {
// Accept `array`.
// Most props are space-separated.
value = info.commaSeparated ? commas(value) : spaces(value)
}
if (prop === 'style') {
let styleObject =
typeof value === 'object'
? value
: parseStyle(String(value), node.tagName)
if (state.stylePropertyNameCase === 'css') {
styleObject = transformStylesToCssCasing(styleObject)
}
/** @type {Array<Property>} */
const cssProperties = []
/** @type {string} */
let cssProp
for (cssProp in styleObject) {
// eslint-disable-next-line max-depth
if (own.call(styleObject, cssProp)) {
cssProperties.push({
type: 'Property',
method: false,
shorthand: false,
computed: false,
key: identifierName(cssProp)
? {type: 'Identifier', name: cssProp}
: {type: 'Literal', value: cssProp},
value: {type: 'Literal', value: String(styleObject[cssProp])},
kind: 'init'
})
}
}
styleProperties = cssProperties
attributeValue = {
type: 'JSXExpressionContainer',
expression: {type: 'ObjectExpression', properties: cssProperties}
}
} else if (value === true) {
attributeValue = null
} else if (
state.tableCellAlignToStyle &&
tableCellElement.has(node.tagName) &&
prop === 'align'
) {
alignValue = String(value)
continue
} else {
attributeValue = {type: 'Literal', value: String(value)}
}
if (identifierName(prop, {jsx: true})) {
attributes.push({
type: 'JSXAttribute',
name: {type: 'JSXIdentifier', name: prop},
value: attributeValue
})
} else {
attributes.push({
type: 'JSXSpreadAttribute',
argument: {
type: 'ObjectExpression',
properties: [
{
type: 'Property',
method: false,
shorthand: false,
computed: false,
key: {type: 'Literal', value: String(prop)},
// @ts-expect-error No need to worry about `style` (which has a
// `JSXExpressionContainer` value) because thats a valid identifier.
value: attributeValue || {type: 'Literal', value: true},
kind: 'init'
}
]
}
})
}
}
}
if (alignValue !== undefined) {
if (!styleProperties) {
styleProperties = []
attributes.push({
type: 'JSXAttribute',
name: {type: 'JSXIdentifier', name: 'style'},
value: {
type: 'JSXExpressionContainer',
expression: {type: 'ObjectExpression', properties: styleProperties}
}
})
}
const cssProp =
state.stylePropertyNameCase === 'css'
? transformStyleToCssCasing('textAlign')
: 'textAlign'
styleProperties.push({
type: 'Property',
method: false,
shorthand: false,
computed: false,
key: identifierName(cssProp)
? {type: 'Identifier', name: cssProp}
: {type: 'Literal', value: cssProp},
value: {type: 'Literal', value: alignValue},
kind: 'init'
})
}
// Restore parent schema.
state.schema = parentSchema
/** @type {JsxElement} */
const result = {
type: 'JSXElement',
openingElement: {
type: 'JSXOpeningElement',
attributes,
name: state.createJsxElementName(node.tagName),
selfClosing: children.length === 0
},
closingElement:
children.length > 0
? {
type: 'JSXClosingElement',
name: state.createJsxElementName(node.tagName)
}
: null,
children
}
state.inherit(node, result)
return result
}
/**
* Parse CSS rules as a declaration.
*
* @param {string} value
* CSS text.
* @param {string} tagName
* Element name.
* @returns {Style}
* Props.
*/
function parseStyle(value, tagName) {
/** @type {Style} */
const result = {}
try {
styleToObject(value, iterator)
} catch (error) {
const cause = /** @type {Error} */ (error)
const exception = new Error(
'Could not parse `style` attribute on `' + tagName + '`',
{cause}
)
throw exception
}
return result
/**
* Add `name`, as a CSS prop, to `result`.
*
* @param {string} name
* Key.
* @param {string} value
* Value.
* @returns {undefined}
* Nothing.
*/
function iterator(name, value) {
let key = name
if (key.slice(0, 2) !== '--') {
// See: <https://alanhogan.com/code/vendor-prefixed-css-property-names-in-javascript>
if (key.slice(0, 4) === '-ms-') key = 'ms-' + key.slice(4)
key = key.replace(dashSomething, toCamel)
}
result[key] = value
}
}
/**
* Transform a DOM casing style object to a CSS casing style object.
*
* @param {Style} domCasing
* @returns {Style}
*/
function transformStylesToCssCasing(domCasing) {
/** @type {Style} */
const cssCasing = {}
/** @type {string} */
let from
for (from in domCasing) {
if (own.call(domCasing, from)) {
cssCasing[transformStyleToCssCasing(from)] = domCasing[from]
}
}
return cssCasing
}
/**
* Transform a DOM casing style prop to a CSS casing style prop.
*
* @param {string} from
* @returns {string}
*/
function transformStyleToCssCasing(from) {
let to = from.replace(cap, toDash)
// Handle `ms-xxx` -> `-ms-xxx`.
if (to.slice(0, 3) === 'ms-') to = '-' + to
return to
}
/**
* Make `$1` capitalized.
*
* @param {string} _
* Whatever.
* @param {string} $1
* Single ASCII alphabetical.
* @returns {string}
* Capitalized `$1`.
*/
function toCamel(_, $1) {
return $1.toUpperCase()
}
/**
* Make `$0` dash cased.
*
* @param {string} $0
* Capitalized ASCII leter.
* @returns {string}
* Dash and lower letter.
*/
function toDash($0) {
return '-' + $0.toLowerCase()
}

View File

@@ -0,0 +1,27 @@
export namespace handlers {
export { comment };
export { ignore as doctype };
export { element };
export { mdxExpression as mdxFlowExpression };
export { mdxJsxElement as mdxJsxFlowElement };
export { mdxJsxElement as mdxJsxTextElement };
export { mdxExpression as mdxTextExpression };
export { mdxjsEsm };
export { root };
export { text };
}
import { comment } from './comment.js';
/**
* Handle a node that is ignored.
*
* @returns {undefined}
* Nothing.
*/
declare function ignore(): undefined;
import { element } from './element.js';
import { mdxExpression } from './mdx-expression.js';
import { mdxJsxElement } from './mdx-jsx-element.js';
import { mdxjsEsm } from './mdxjs-esm.js';
import { root } from './root.js';
import { text } from './text.js';
export {};

28
node_modules/hast-util-to-estree/lib/handlers/index.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import {comment} from './comment.js'
import {element} from './element.js'
import {mdxExpression} from './mdx-expression.js'
import {mdxJsxElement} from './mdx-jsx-element.js'
import {mdxjsEsm} from './mdxjs-esm.js'
import {root} from './root.js'
import {text} from './text.js'
export const handlers = {
comment,
doctype: ignore,
element,
mdxFlowExpression: mdxExpression,
mdxJsxFlowElement: mdxJsxElement,
mdxJsxTextElement: mdxJsxElement,
mdxTextExpression: mdxExpression,
mdxjsEsm,
root,
text
}
/**
* Handle a node that is ignored.
*
* @returns {undefined}
* Nothing.
*/
function ignore() {}

View File

@@ -0,0 +1,17 @@
/**
* Turn an MDX expression node into an estree node.
*
* @param {MdxFlowExpression | MdxTextExpression} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer}
* estree expression.
*/
export function mdxExpression(node: MdxFlowExpression | MdxTextExpression, state: State): JsxExpressionContainer;
export type Expression = import('estree').Expression;
export type JsxEmptyExpression = import('estree-jsx').JSXEmptyExpression;
export type JsxExpressionContainer = import('estree-jsx').JSXExpressionContainer;
export type MdxFlowExpression = import('mdast-util-mdx-expression').MdxFlowExpressionHast;
export type MdxTextExpression = import('mdast-util-mdx-expression').MdxTextExpressionHast;
export type State = import('../state.js').State;

View File

@@ -0,0 +1,50 @@
/**
* @typedef {import('estree').Expression} Expression
*
* @typedef {import('estree-jsx').JSXEmptyExpression} JsxEmptyExpression
* @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer
*
* @typedef {import('mdast-util-mdx-expression').MdxFlowExpressionHast} MdxFlowExpression
* @typedef {import('mdast-util-mdx-expression').MdxTextExpressionHast} MdxTextExpression
*
* @typedef {import('../state.js').State} State
*/
import {attachComments} from 'estree-util-attach-comments'
/**
* Turn an MDX expression node into an estree node.
*
* @param {MdxFlowExpression | MdxTextExpression} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer}
* estree expression.
*/
export function mdxExpression(node, state) {
const estree = node.data && node.data.estree
const comments = (estree && estree.comments) || []
/** @type {Expression | JsxEmptyExpression | undefined} */
let expression
if (estree) {
state.comments.push(...comments)
attachComments(estree, estree.comments)
expression =
(estree.body[0] &&
estree.body[0].type === 'ExpressionStatement' &&
estree.body[0].expression) ||
undefined
}
if (!expression) {
expression = {type: 'JSXEmptyExpression'}
state.patch(node, expression)
}
/** @type {JsxExpressionContainer} */
const result = {type: 'JSXExpressionContainer', expression}
state.inherit(node, result)
return result
}

View File

@@ -0,0 +1,19 @@
/**
* Turn an MDX JSX element node into an estree node.
*
* @param {MdxJsxFlowElement | MdxJsxTextElement} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxElement | JsxFragment}
* JSX element or fragment.
*/
export function mdxJsxElement(node: MdxJsxFlowElement | MdxJsxTextElement, state: State): JsxElement | JsxFragment;
export type Expression = import('estree').Expression;
export type JsxAttribute = import('estree-jsx').JSXAttribute;
export type JsxElement = import('estree-jsx').JSXElement;
export type JsxFragment = import('estree-jsx').JSXFragment;
export type JsxSpreadAttribute = import('estree-jsx').JSXSpreadAttribute;
export type MdxJsxFlowElement = import('mdast-util-mdx-jsx').MdxJsxFlowElementHast;
export type MdxJsxTextElement = import('mdast-util-mdx-jsx').MdxJsxTextElementHast;
export type State = import('../state.js').State;

View File

@@ -0,0 +1,164 @@
/**
* @typedef {import('estree').Expression} Expression
*
* @typedef {import('estree-jsx').JSXAttribute} JsxAttribute
* @typedef {import('estree-jsx').JSXElement} JsxElement
* @typedef {import('estree-jsx').JSXFragment} JsxFragment
* @typedef {import('estree-jsx').JSXSpreadAttribute} JsxSpreadAttribute
*
* @typedef {import('mdast-util-mdx-jsx').MdxJsxFlowElementHast} MdxJsxFlowElement
* @typedef {import('mdast-util-mdx-jsx').MdxJsxTextElementHast} MdxJsxTextElement
*
* @typedef {import('../state.js').State} State
*/
import {attachComments} from 'estree-util-attach-comments'
import {svg} from 'property-information'
/**
* Turn an MDX JSX element node into an estree node.
*
* @param {MdxJsxFlowElement | MdxJsxTextElement} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxElement | JsxFragment}
* JSX element or fragment.
*/
// eslint-disable-next-line complexity
export function mdxJsxElement(node, state) {
const parentSchema = state.schema
let schema = parentSchema
const attrs = node.attributes || []
let index = -1
if (
node.name &&
parentSchema.space === 'html' &&
node.name.toLowerCase() === 'svg'
) {
schema = svg
state.schema = schema
}
const children = state.all(node)
/** @type {Array<JsxAttribute | JsxSpreadAttribute>} */
const attributes = []
while (++index < attrs.length) {
const attr = attrs[index]
const value = attr.value
/** @type {JsxAttribute['value']} */
let attributeValue
if (attr.type === 'mdxJsxAttribute') {
if (value === null || value === undefined) {
attributeValue = null
// Empty.
}
// `MdxJsxAttributeValueExpression`.
else if (typeof value === 'object') {
const estree = value.data && value.data.estree
const comments = (estree && estree.comments) || []
/** @type {Expression | undefined} */
let expression
if (estree) {
state.comments.push(...comments)
attachComments(estree, estree.comments)
// Should exist.
/* c8 ignore next 5 */
expression =
(estree.body[0] &&
estree.body[0].type === 'ExpressionStatement' &&
estree.body[0].expression) ||
undefined
}
attributeValue = {
type: 'JSXExpressionContainer',
expression: expression || {type: 'JSXEmptyExpression'}
}
state.inherit(value, attributeValue)
}
// Anything else.
else {
attributeValue = {type: 'Literal', value: String(value)}
}
/** @type {JsxAttribute} */
const attribute = {
type: 'JSXAttribute',
name: state.createJsxAttributeName(attr.name),
value: attributeValue
}
state.inherit(attr, attribute)
attributes.push(attribute)
}
// MdxJsxExpressionAttribute.
else {
const estree = attr.data && attr.data.estree
const comments = (estree && estree.comments) || []
/** @type {JsxSpreadAttribute['argument'] | undefined} */
let argumentValue
if (estree) {
state.comments.push(...comments)
attachComments(estree, estree.comments)
// Should exist.
/* c8 ignore next 10 */
argumentValue =
(estree.body[0] &&
estree.body[0].type === 'ExpressionStatement' &&
estree.body[0].expression &&
estree.body[0].expression.type === 'ObjectExpression' &&
estree.body[0].expression.properties &&
estree.body[0].expression.properties[0] &&
estree.body[0].expression.properties[0].type === 'SpreadElement' &&
estree.body[0].expression.properties[0].argument) ||
undefined
}
/** @type {JsxSpreadAttribute} */
const attribute = {
type: 'JSXSpreadAttribute',
argument: argumentValue || {type: 'ObjectExpression', properties: []}
}
state.inherit(attr, attribute)
attributes.push(attribute)
}
}
// Restore parent schema.
state.schema = parentSchema
/** @type {JsxElement | JsxFragment} */
const result = node.name
? {
type: 'JSXElement',
openingElement: {
type: 'JSXOpeningElement',
attributes,
name: state.createJsxElementName(node.name),
selfClosing: children.length === 0
},
closingElement:
children.length > 0
? {
type: 'JSXClosingElement',
name: state.createJsxElementName(node.name)
}
: null,
children
}
: {
type: 'JSXFragment',
openingFragment: {type: 'JSXOpeningFragment'},
closingFragment: {type: 'JSXClosingFragment'},
children
}
state.inherit(node, result)
return result
}

View File

@@ -0,0 +1,13 @@
/**
* Handle an MDX ESM node.
*
* @param {MdxjsEsm} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {undefined}
* Nothing.
*/
export function mdxjsEsm(node: MdxjsEsm, state: State): undefined;
export type MdxjsEsm = import('mdast-util-mdxjs-esm').MdxjsEsmHast;
export type State = import('../state.js').State;

View File

@@ -0,0 +1,28 @@
/**
* @typedef {import('mdast-util-mdxjs-esm').MdxjsEsmHast} MdxjsEsm
*
* @typedef {import('../state.js').State} State
*/
import {attachComments} from 'estree-util-attach-comments'
/**
* Handle an MDX ESM node.
*
* @param {MdxjsEsm} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {undefined}
* Nothing.
*/
export function mdxjsEsm(node, state) {
const estree = node.data && node.data.estree
const comments = (estree && estree.comments) || []
if (estree) {
state.comments.push(...comments)
attachComments(estree, comments)
state.esm.push(...estree.body)
}
}

View File

@@ -0,0 +1,15 @@
/**
* Turn a hast root node into an estree node.
*
* @param {HastRoot} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxFragment}
* estree JSX fragment.
*/
export function root(node: HastRoot, state: State): JsxFragment;
export type JsxFragment = import('estree-jsx').JSXFragment;
export type HastRoot = import('hast').Root;
export type State = import('../state.js').State;
export type JsxChild = JsxFragment['children'][number];

59
node_modules/hast-util-to-estree/lib/handlers/root.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
/**
* @typedef {import('estree-jsx').JSXFragment} JsxFragment
*
* @typedef {import('hast').Root} HastRoot
*
* @typedef {import('../state.js').State} State
*/
/**
* @typedef {JsxFragment['children'][number]} JsxChild
*/
import {whitespace} from 'hast-util-whitespace'
/**
* Turn a hast root node into an estree node.
*
* @param {HastRoot} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxFragment}
* estree JSX fragment.
*/
export function root(node, state) {
const children = state.all(node)
/** @type {Array<JsxChild>} */
const cleanChildren = []
let index = -1
/** @type {Array<JsxChild> | undefined} */
let queue
// Remove surrounding whitespace nodes from the fragment.
while (++index < children.length) {
const child = children[index]
if (
child.type === 'JSXExpressionContainer' &&
child.expression.type === 'Literal' &&
whitespace(String(child.expression.value))
) {
if (queue) queue.push(child)
} else {
if (queue) cleanChildren.push(...queue)
cleanChildren.push(child)
queue = []
}
}
/** @type {JsxFragment} */
const result = {
type: 'JSXFragment',
openingFragment: {type: 'JSXOpeningFragment'},
closingFragment: {type: 'JSXClosingFragment'},
children: cleanChildren
}
state.inherit(node, result)
return result
}

View File

@@ -0,0 +1,15 @@
/**
* Turn a hast text node into an estree node.
*
* @param {HastText} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer | undefined}
* JSX expression.
*/
export function text(node: HastText, state: State): JsxExpressionContainer | undefined;
export type Literal = import('estree').Literal;
export type JsxExpressionContainer = import('estree-jsx').JSXExpressionContainer;
export type HastText = import('hast').Text;
export type State = import('../state.js').State;

36
node_modules/hast-util-to-estree/lib/handlers/text.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
/**
* @typedef {import('estree').Literal} Literal
*
* @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer
*
* @typedef {import('hast').Text} HastText
*
* @typedef {import('../state.js').State} State
*/
// Make VS Code show references to the above types.
''
/**
* Turn a hast text node into an estree node.
*
* @param {HastText} node
* hast node to transform.
* @param {State} state
* Info passed around about the current state.
* @returns {JsxExpressionContainer | undefined}
* JSX expression.
*/
export function text(node, state) {
const value = String(node.value || '')
if (value) {
/** @type {Literal} */
const result = {type: 'Literal', value}
state.inherit(node, result)
/** @type {JsxExpressionContainer} */
const container = {type: 'JSXExpressionContainer', expression: result}
state.patch(node, container)
return container
}
}