🎉 initiate project *astro_rewrite*
This commit is contained in:
parent
ffd4d5e86c
commit
2ba37bfbe3
8658 changed files with 2268794 additions and 2538 deletions
153
node_modules/estree-util-build-jsx/lib/index.d.ts
generated
vendored
Normal file
153
node_modules/estree-util-build-jsx/lib/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* Turn JSX in `tree` into function calls: `<x />` -> `h('x')`!
|
||||
*
|
||||
* ###### Algorithm
|
||||
*
|
||||
* In almost all cases, this utility is the same as the Babel plugin, except that
|
||||
* they work on slightly different syntax trees.
|
||||
*
|
||||
* Some differences:
|
||||
*
|
||||
* * no pure annotations things
|
||||
* * `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
|
||||
* * namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
|
||||
* which throws by default in Babel or can be turned on with `throwIfNamespace`
|
||||
* * no `useSpread`, `useBuiltIns`, or `filter` options
|
||||
*
|
||||
* @template {Node} Tree
|
||||
* Node type.
|
||||
* @param {Tree} tree
|
||||
* Tree to transform (typically `Program`).
|
||||
* @param {Options | null | undefined} [options={}]
|
||||
* Configuration (optional).
|
||||
* @returns {Tree}
|
||||
* Given, modified, `tree`.
|
||||
*/
|
||||
export function buildJsx<Tree extends import('estree').Node>(
|
||||
tree: Tree,
|
||||
options?: Options | null | undefined
|
||||
): Tree
|
||||
export type Node = import('estree-jsx').Node
|
||||
export type Expression = import('estree-jsx').Expression
|
||||
export type ObjectExpression = import('estree-jsx').ObjectExpression
|
||||
export type Property = import('estree-jsx').Property
|
||||
export type ImportSpecifier = import('estree-jsx').ImportSpecifier
|
||||
export type SpreadElement = import('estree-jsx').SpreadElement
|
||||
export type MemberExpression = import('estree-jsx').MemberExpression
|
||||
export type Literal = import('estree-jsx').Literal
|
||||
export type Identifier = import('estree-jsx').Identifier
|
||||
export type JSXAttribute = import('estree-jsx').JSXAttribute
|
||||
export type JSXMemberExpression = import('estree-jsx').JSXMemberExpression
|
||||
export type JSXNamespacedName = import('estree-jsx').JSXNamespacedName
|
||||
export type JSXIdentifier = import('estree-jsx').JSXIdentifier
|
||||
/**
|
||||
* How to transform JSX.
|
||||
*/
|
||||
export type Runtime = 'automatic' | 'classic'
|
||||
/**
|
||||
* Configuration.
|
||||
*
|
||||
* > 👉 **Note**: you can also configure `runtime`, `importSource`, `pragma`,
|
||||
* > and `pragmaFrag` from within files through comments.
|
||||
*/
|
||||
export type Options = {
|
||||
/**
|
||||
* Choose the runtime.
|
||||
*
|
||||
* Comment form: `@jsxRuntime theRuntime`.
|
||||
*/
|
||||
runtime?: Runtime | null | undefined
|
||||
/**
|
||||
* Place to import `jsx`, `jsxs`, `jsxDEV`, and `Fragment` from, when the
|
||||
* effective runtime is automatic.
|
||||
*
|
||||
* Comment form: `@jsxImportSource theSource`.
|
||||
*
|
||||
* > 👉 **Note**: `/jsx-runtime` or `/jsx-dev-runtime` is appended to this
|
||||
* > provided source.
|
||||
* > In CJS, that can resolve to a file (as in `theSource/jsx-runtime.js`),
|
||||
* > but for ESM an export map needs to be set up to point to files:
|
||||
* >
|
||||
* > ```js
|
||||
* > // …
|
||||
* > "exports": {
|
||||
* > // …
|
||||
* > "./jsx-runtime": "./path/to/jsx-runtime.js",
|
||||
* > "./jsx-dev-runtime": "./path/to/jsx-runtime.js"
|
||||
* > // …
|
||||
* > ```
|
||||
*/
|
||||
importSource?: string | null | undefined
|
||||
/**
|
||||
* Identifier or member expression to call when the effective runtime is
|
||||
* classic.
|
||||
*
|
||||
* Comment form: `@jsx identifier`.
|
||||
*/
|
||||
pragma?: string | null | undefined
|
||||
/**
|
||||
* Identifier or member expression to use as a symbol for fragments when the
|
||||
* effective runtime is classic.
|
||||
*
|
||||
* Comment form: `@jsxFrag identifier`.
|
||||
*/
|
||||
pragmaFrag?: string | null | undefined
|
||||
/**
|
||||
* When in the automatic runtime, whether to import
|
||||
* `theSource/jsx-dev-runtime.js`, use `jsxDEV`, and pass location info when
|
||||
* available.
|
||||
*
|
||||
* This helps debugging but adds a lot of code that you don’t want in
|
||||
* production.
|
||||
*/
|
||||
development?: boolean | null | undefined
|
||||
/**
|
||||
* File path to the original source file.
|
||||
*
|
||||
* Passed in location info to `jsxDEV` when using the automatic runtime with
|
||||
* `development: true`.
|
||||
*/
|
||||
filePath?: string | null | undefined
|
||||
}
|
||||
/**
|
||||
* State where info from comments is gathered.
|
||||
*/
|
||||
export type Annotations = {
|
||||
/**
|
||||
* Runtime.
|
||||
*/
|
||||
jsxRuntime?: Runtime | undefined
|
||||
/**
|
||||
* JSX identifier (`pragma`).
|
||||
*/
|
||||
jsx?: string | undefined
|
||||
/**
|
||||
* JSX identifier of fragment (`pragmaFrag`).
|
||||
*/
|
||||
jsxFrag?: string | undefined
|
||||
/**
|
||||
* Where to import an automatic JSX runtime from.
|
||||
*/
|
||||
jsxImportSource?: string | undefined
|
||||
}
|
||||
/**
|
||||
* State of used identifiers from the automatic runtime.
|
||||
*/
|
||||
export type Imports = {
|
||||
/**
|
||||
* Symbol of `Fragment`.
|
||||
*/
|
||||
fragment?: boolean | undefined
|
||||
/**
|
||||
* Symbol of `jsx`.
|
||||
*/
|
||||
jsx?: boolean | undefined
|
||||
/**
|
||||
* Symbol of `jsxs`.
|
||||
*/
|
||||
jsxs?: boolean | undefined
|
||||
/**
|
||||
* Symbol of `jsxDEV`.
|
||||
*/
|
||||
jsxDEV?: boolean | undefined
|
||||
}
|
||||
619
node_modules/estree-util-build-jsx/lib/index.js
generated
vendored
Normal file
619
node_modules/estree-util-build-jsx/lib/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,619 @@
|
|||
/**
|
||||
* @typedef {import('estree-jsx').Node} Node
|
||||
* @typedef {import('estree-jsx').Expression} Expression
|
||||
* @typedef {import('estree-jsx').ObjectExpression} ObjectExpression
|
||||
* @typedef {import('estree-jsx').Property} Property
|
||||
* @typedef {import('estree-jsx').ImportSpecifier} ImportSpecifier
|
||||
* @typedef {import('estree-jsx').SpreadElement} SpreadElement
|
||||
* @typedef {import('estree-jsx').MemberExpression} MemberExpression
|
||||
* @typedef {import('estree-jsx').Literal} Literal
|
||||
* @typedef {import('estree-jsx').Identifier} Identifier
|
||||
* @typedef {import('estree-jsx').JSXAttribute} JSXAttribute
|
||||
* @typedef {import('estree-jsx').JSXMemberExpression} JSXMemberExpression
|
||||
* @typedef {import('estree-jsx').JSXNamespacedName} JSXNamespacedName
|
||||
* @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier
|
||||
*
|
||||
* @typedef {'automatic' | 'classic'} Runtime
|
||||
* How to transform JSX.
|
||||
*
|
||||
* @typedef Options
|
||||
* Configuration.
|
||||
*
|
||||
* > 👉 **Note**: you can also configure `runtime`, `importSource`, `pragma`,
|
||||
* > and `pragmaFrag` from within files through comments.
|
||||
* @property {Runtime | null | undefined} [runtime='classic']
|
||||
* Choose the runtime.
|
||||
*
|
||||
* Comment form: `@jsxRuntime theRuntime`.
|
||||
* @property {string | null | undefined} [importSource='react']
|
||||
* Place to import `jsx`, `jsxs`, `jsxDEV`, and `Fragment` from, when the
|
||||
* effective runtime is automatic.
|
||||
*
|
||||
* Comment form: `@jsxImportSource theSource`.
|
||||
*
|
||||
* > 👉 **Note**: `/jsx-runtime` or `/jsx-dev-runtime` is appended to this
|
||||
* > provided source.
|
||||
* > In CJS, that can resolve to a file (as in `theSource/jsx-runtime.js`),
|
||||
* > but for ESM an export map needs to be set up to point to files:
|
||||
* >
|
||||
* > ```js
|
||||
* > // …
|
||||
* > "exports": {
|
||||
* > // …
|
||||
* > "./jsx-runtime": "./path/to/jsx-runtime.js",
|
||||
* > "./jsx-dev-runtime": "./path/to/jsx-runtime.js"
|
||||
* > // …
|
||||
* > ```
|
||||
* @property {string | null | undefined} [pragma='React.createElement']
|
||||
* Identifier or member expression to call when the effective runtime is
|
||||
* classic.
|
||||
*
|
||||
* Comment form: `@jsx identifier`.
|
||||
* @property {string | null | undefined} [pragmaFrag='React.Fragment']
|
||||
* Identifier or member expression to use as a symbol for fragments when the
|
||||
* effective runtime is classic.
|
||||
*
|
||||
* Comment form: `@jsxFrag identifier`.
|
||||
* @property {boolean | null | undefined} [development=false]
|
||||
* When in the automatic runtime, whether to import
|
||||
* `theSource/jsx-dev-runtime.js`, use `jsxDEV`, and pass location info when
|
||||
* available.
|
||||
*
|
||||
* This helps debugging but adds a lot of code that you don’t want in
|
||||
* production.
|
||||
* @property {string | null | undefined} [filePath]
|
||||
* File path to the original source file.
|
||||
*
|
||||
* Passed in location info to `jsxDEV` when using the automatic runtime with
|
||||
* `development: true`.
|
||||
*
|
||||
* @typedef Annotations
|
||||
* State where info from comments is gathered.
|
||||
* @property {Runtime | undefined} [jsxRuntime]
|
||||
* Runtime.
|
||||
* @property {string | undefined} [jsx]
|
||||
* JSX identifier (`pragma`).
|
||||
* @property {string | undefined} [jsxFrag]
|
||||
* JSX identifier of fragment (`pragmaFrag`).
|
||||
* @property {string | undefined} [jsxImportSource]
|
||||
* Where to import an automatic JSX runtime from.
|
||||
*
|
||||
* @typedef Imports
|
||||
* State of used identifiers from the automatic runtime.
|
||||
* @property {boolean | undefined} [fragment]
|
||||
* Symbol of `Fragment`.
|
||||
* @property {boolean | undefined} [jsx]
|
||||
* Symbol of `jsx`.
|
||||
* @property {boolean | undefined} [jsxs]
|
||||
* Symbol of `jsxs`.
|
||||
* @property {boolean | undefined} [jsxDEV]
|
||||
* Symbol of `jsxDEV`.
|
||||
*/
|
||||
|
||||
import {walk} from 'estree-walker'
|
||||
import {name as isIdentifierName} from 'estree-util-is-identifier-name'
|
||||
|
||||
const regex = /@(jsx|jsxFrag|jsxImportSource|jsxRuntime)\s+(\S+)/g
|
||||
|
||||
/**
|
||||
* Turn JSX in `tree` into function calls: `<x />` -> `h('x')`!
|
||||
*
|
||||
* ###### Algorithm
|
||||
*
|
||||
* In almost all cases, this utility is the same as the Babel plugin, except that
|
||||
* they work on slightly different syntax trees.
|
||||
*
|
||||
* Some differences:
|
||||
*
|
||||
* * no pure annotations things
|
||||
* * `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
|
||||
* * namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
|
||||
* which throws by default in Babel or can be turned on with `throwIfNamespace`
|
||||
* * no `useSpread`, `useBuiltIns`, or `filter` options
|
||||
*
|
||||
* @template {Node} Tree
|
||||
* Node type.
|
||||
* @param {Tree} tree
|
||||
* Tree to transform (typically `Program`).
|
||||
* @param {Options | null | undefined} [options={}]
|
||||
* Configuration (optional).
|
||||
* @returns {Tree}
|
||||
* Given, modified, `tree`.
|
||||
*/
|
||||
// To do next major: do not return the given Node.
|
||||
export function buildJsx(tree, options) {
|
||||
const config = options || {}
|
||||
let automatic = config.runtime === 'automatic'
|
||||
/** @type {Annotations} */
|
||||
const annotations = {}
|
||||
/** @type {Imports} */
|
||||
const imports = {}
|
||||
|
||||
walk(tree, {
|
||||
// @ts-expect-error: hush, `estree-walker` is broken.
|
||||
enter(/** @type {Node} */ node) {
|
||||
if (node.type === 'Program') {
|
||||
const comments = node.comments || []
|
||||
let index = -1
|
||||
|
||||
while (++index < comments.length) {
|
||||
regex.lastIndex = 0
|
||||
|
||||
let match = regex.exec(comments[index].value)
|
||||
|
||||
while (match) {
|
||||
// @ts-expect-error: indexable.
|
||||
annotations[match[1]] = match[2]
|
||||
match = regex.exec(comments[index].value)
|
||||
}
|
||||
}
|
||||
|
||||
if (annotations.jsxRuntime) {
|
||||
if (annotations.jsxRuntime === 'automatic') {
|
||||
automatic = true
|
||||
|
||||
if (annotations.jsx) {
|
||||
throw new Error('Unexpected `@jsx` pragma w/ automatic runtime')
|
||||
}
|
||||
|
||||
if (annotations.jsxFrag) {
|
||||
throw new Error(
|
||||
'Unexpected `@jsxFrag` pragma w/ automatic runtime'
|
||||
)
|
||||
}
|
||||
} else if (annotations.jsxRuntime === 'classic') {
|
||||
automatic = false
|
||||
|
||||
if (annotations.jsxImportSource) {
|
||||
throw new Error(
|
||||
'Unexpected `@jsxImportSource` w/ classic runtime'
|
||||
)
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
'Unexpected `jsxRuntime` `' +
|
||||
annotations.jsxRuntime +
|
||||
'`, expected `automatic` or `classic`'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-expect-error: hush, `estree-walker` is broken.
|
||||
// eslint-disable-next-line complexity
|
||||
leave(/** @type {Node} */ node) {
|
||||
if (node.type === 'Program') {
|
||||
/** @type {Array<ImportSpecifier>} */
|
||||
const specifiers = []
|
||||
|
||||
if (imports.fragment) {
|
||||
specifiers.push({
|
||||
type: 'ImportSpecifier',
|
||||
imported: {type: 'Identifier', name: 'Fragment'},
|
||||
local: {type: 'Identifier', name: '_Fragment'}
|
||||
})
|
||||
}
|
||||
|
||||
if (imports.jsx) {
|
||||
specifiers.push({
|
||||
type: 'ImportSpecifier',
|
||||
imported: {type: 'Identifier', name: 'jsx'},
|
||||
local: {type: 'Identifier', name: '_jsx'}
|
||||
})
|
||||
}
|
||||
|
||||
if (imports.jsxs) {
|
||||
specifiers.push({
|
||||
type: 'ImportSpecifier',
|
||||
imported: {type: 'Identifier', name: 'jsxs'},
|
||||
local: {type: 'Identifier', name: '_jsxs'}
|
||||
})
|
||||
}
|
||||
|
||||
if (imports.jsxDEV) {
|
||||
specifiers.push({
|
||||
type: 'ImportSpecifier',
|
||||
imported: {type: 'Identifier', name: 'jsxDEV'},
|
||||
local: {type: 'Identifier', name: '_jsxDEV'}
|
||||
})
|
||||
}
|
||||
|
||||
if (specifiers.length > 0) {
|
||||
node.body.unshift({
|
||||
type: 'ImportDeclaration',
|
||||
specifiers,
|
||||
source: {
|
||||
type: 'Literal',
|
||||
value:
|
||||
(annotations.jsxImportSource ||
|
||||
config.importSource ||
|
||||
'react') +
|
||||
(config.development ? '/jsx-dev-runtime' : '/jsx-runtime')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type !== 'JSXElement' && node.type !== 'JSXFragment') {
|
||||
return
|
||||
}
|
||||
|
||||
/** @type {Array<Expression>} */
|
||||
const children = []
|
||||
let index = -1
|
||||
|
||||
// Figure out `children`.
|
||||
while (++index < node.children.length) {
|
||||
const child = node.children[index]
|
||||
|
||||
if (child.type === 'JSXExpressionContainer') {
|
||||
// Ignore empty expressions.
|
||||
if (child.expression.type !== 'JSXEmptyExpression') {
|
||||
children.push(child.expression)
|
||||
}
|
||||
} else if (child.type === 'JSXText') {
|
||||
const value = child.value
|
||||
// Replace tabs w/ spaces.
|
||||
.replace(/\t/g, ' ')
|
||||
// Use line feeds, drop spaces around them.
|
||||
.replace(/ *(\r?\n|\r) */g, '\n')
|
||||
// Collapse multiple line feeds.
|
||||
.replace(/\n+/g, '\n')
|
||||
// Drop final line feeds.
|
||||
.replace(/\n+$/, '')
|
||||
// Drop first line feeds.
|
||||
.replace(/^\n+/, '')
|
||||
// Replace line feeds with spaces.
|
||||
.replace(/\n/g, ' ')
|
||||
|
||||
// Ignore collapsible text.
|
||||
if (value) {
|
||||
children.push(create(child, {type: 'Literal', value}))
|
||||
}
|
||||
} else {
|
||||
// @ts-expect-error JSX{Element,Fragment} have already been compiled,
|
||||
// and `JSXSpreadChild` is not supported in Babel either, so ignore
|
||||
// it.
|
||||
children.push(child)
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {MemberExpression | Literal | Identifier} */
|
||||
let name
|
||||
/** @type {Array<Property>} */
|
||||
let fields = []
|
||||
/** @type {Array<Expression>} */
|
||||
const objects = []
|
||||
/** @type {Array<Expression | SpreadElement>} */
|
||||
let parameters = []
|
||||
/** @type {Expression | undefined} */
|
||||
let key
|
||||
|
||||
// Do the stuff needed for elements.
|
||||
if (node.type === 'JSXElement') {
|
||||
name = toIdentifier(node.openingElement.name)
|
||||
|
||||
// If the name could be an identifier, but start with a lowercase letter,
|
||||
// it’s not a component.
|
||||
if (name.type === 'Identifier' && /^[a-z]/.test(name.name)) {
|
||||
name = create(name, {type: 'Literal', value: name.name})
|
||||
}
|
||||
|
||||
/** @type {boolean | undefined} */
|
||||
let spread
|
||||
const attributes = node.openingElement.attributes
|
||||
let index = -1
|
||||
|
||||
// Place props in the right order, because we might have duplicates
|
||||
// in them and what’s spread in.
|
||||
while (++index < attributes.length) {
|
||||
const attribute = attributes[index]
|
||||
|
||||
if (attribute.type === 'JSXSpreadAttribute') {
|
||||
if (fields.length > 0) {
|
||||
objects.push({type: 'ObjectExpression', properties: fields})
|
||||
fields = []
|
||||
}
|
||||
|
||||
objects.push(attribute.argument)
|
||||
spread = true
|
||||
} else {
|
||||
const prop = toProperty(attribute)
|
||||
|
||||
if (
|
||||
automatic &&
|
||||
prop.key.type === 'Identifier' &&
|
||||
prop.key.name === 'key'
|
||||
) {
|
||||
if (spread) {
|
||||
throw new Error(
|
||||
'Expected `key` to come before any spread expressions'
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error I can’t see object patterns being used as
|
||||
// attribute values? 🤷♂️
|
||||
key = prop.value
|
||||
} else {
|
||||
fields.push(prop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// …and fragments.
|
||||
else if (automatic) {
|
||||
imports.fragment = true
|
||||
name = {type: 'Identifier', name: '_Fragment'}
|
||||
} else {
|
||||
name = toMemberExpression(
|
||||
annotations.jsxFrag || config.pragmaFrag || 'React.Fragment'
|
||||
)
|
||||
}
|
||||
|
||||
if (automatic) {
|
||||
if (children.length > 0) {
|
||||
fields.push({
|
||||
type: 'Property',
|
||||
key: {type: 'Identifier', name: 'children'},
|
||||
value:
|
||||
children.length > 1
|
||||
? {type: 'ArrayExpression', elements: children}
|
||||
: children[0],
|
||||
kind: 'init',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
parameters = children
|
||||
}
|
||||
|
||||
if (fields.length > 0) {
|
||||
objects.push({type: 'ObjectExpression', properties: fields})
|
||||
}
|
||||
|
||||
/** @type {Expression | undefined} */
|
||||
let props
|
||||
/** @type {MemberExpression | Literal | Identifier} */
|
||||
let callee
|
||||
|
||||
if (objects.length > 1) {
|
||||
// Don’t mutate the first object, shallow clone instead.
|
||||
if (objects[0].type !== 'ObjectExpression') {
|
||||
objects.unshift({type: 'ObjectExpression', properties: []})
|
||||
}
|
||||
|
||||
props = {
|
||||
type: 'CallExpression',
|
||||
callee: toMemberExpression('Object.assign'),
|
||||
arguments: objects,
|
||||
optional: false
|
||||
}
|
||||
} else if (objects.length > 0) {
|
||||
props = objects[0]
|
||||
}
|
||||
|
||||
if (automatic) {
|
||||
parameters.push(props || {type: 'ObjectExpression', properties: []})
|
||||
|
||||
if (key) {
|
||||
parameters.push(key)
|
||||
} else if (config.development) {
|
||||
parameters.push({type: 'Identifier', name: 'undefined'})
|
||||
}
|
||||
|
||||
const isStaticChildren = children.length > 1
|
||||
|
||||
if (config.development) {
|
||||
imports.jsxDEV = true
|
||||
callee = {
|
||||
type: 'Identifier',
|
||||
name: '_jsxDEV'
|
||||
}
|
||||
parameters.push({type: 'Literal', value: isStaticChildren})
|
||||
|
||||
/** @type {ObjectExpression} */
|
||||
const source = {
|
||||
type: 'ObjectExpression',
|
||||
properties: [
|
||||
{
|
||||
type: 'Property',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false,
|
||||
kind: 'init',
|
||||
key: {type: 'Identifier', name: 'fileName'},
|
||||
value: {
|
||||
type: 'Literal',
|
||||
value: config.filePath || '<source.js>'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (node.loc) {
|
||||
source.properties.push(
|
||||
{
|
||||
type: 'Property',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false,
|
||||
kind: 'init',
|
||||
key: {type: 'Identifier', name: 'lineNumber'},
|
||||
value: {type: 'Literal', value: node.loc.start.line}
|
||||
},
|
||||
{
|
||||
type: 'Property',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false,
|
||||
kind: 'init',
|
||||
key: {type: 'Identifier', name: 'columnNumber'},
|
||||
value: {type: 'Literal', value: node.loc.start.column + 1}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
parameters.push(source, {type: 'ThisExpression'})
|
||||
} else if (isStaticChildren) {
|
||||
imports.jsxs = true
|
||||
callee = {type: 'Identifier', name: '_jsxs'}
|
||||
} else {
|
||||
imports.jsx = true
|
||||
callee = {type: 'Identifier', name: '_jsx'}
|
||||
}
|
||||
}
|
||||
// Classic.
|
||||
else {
|
||||
// There are props or children.
|
||||
if (props || parameters.length > 0) {
|
||||
parameters.unshift(props || {type: 'Literal', value: null})
|
||||
}
|
||||
|
||||
callee = toMemberExpression(
|
||||
annotations.jsx || config.pragma || 'React.createElement'
|
||||
)
|
||||
}
|
||||
|
||||
parameters.unshift(name)
|
||||
|
||||
// Types of `estree-walker` are wrong
|
||||
this.replace(
|
||||
create(node, {
|
||||
type: 'CallExpression',
|
||||
callee,
|
||||
arguments: parameters,
|
||||
optional: false
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSXAttribute} node
|
||||
* @returns {Property}
|
||||
*/
|
||||
function toProperty(node) {
|
||||
/** @type {Expression} */
|
||||
let value
|
||||
|
||||
if (node.value) {
|
||||
if (node.value.type === 'JSXExpressionContainer') {
|
||||
// @ts-expect-error `JSXEmptyExpression` is not allowed in props.
|
||||
value = node.value.expression
|
||||
}
|
||||
// Literal or call expression.
|
||||
else {
|
||||
// @ts-expect-error: JSX{Element,Fragment} are already compiled to
|
||||
// `CallExpression`.
|
||||
value = node.value
|
||||
// @ts-expect-error Remove `raw` so we don’t get character references in
|
||||
// strings.
|
||||
delete value.raw
|
||||
}
|
||||
}
|
||||
// Boolean prop.
|
||||
else {
|
||||
value = {type: 'Literal', value: true}
|
||||
}
|
||||
|
||||
return create(node, {
|
||||
type: 'Property',
|
||||
key: toIdentifier(node.name),
|
||||
value,
|
||||
kind: 'init',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSXMemberExpression | JSXNamespacedName | JSXIdentifier} node
|
||||
* @returns {MemberExpression | Identifier | Literal}
|
||||
*/
|
||||
function toIdentifier(node) {
|
||||
/** @type {MemberExpression | Identifier | Literal} */
|
||||
let replace
|
||||
|
||||
if (node.type === 'JSXMemberExpression') {
|
||||
// `property` is always a `JSXIdentifier`, but it could be something that
|
||||
// isn’t an ES identifier name.
|
||||
const id = toIdentifier(node.property)
|
||||
replace = {
|
||||
type: 'MemberExpression',
|
||||
object: toIdentifier(node.object),
|
||||
property: id,
|
||||
computed: id.type === 'Literal',
|
||||
optional: false
|
||||
}
|
||||
} else if (node.type === 'JSXNamespacedName') {
|
||||
replace = {
|
||||
type: 'Literal',
|
||||
value: node.namespace.name + ':' + node.name.name
|
||||
}
|
||||
}
|
||||
// Must be `JSXIdentifier`.
|
||||
else {
|
||||
replace = isIdentifierName(node.name)
|
||||
? {type: 'Identifier', name: node.name}
|
||||
: {type: 'Literal', value: node.name}
|
||||
}
|
||||
|
||||
return create(node, replace)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {Identifier | Literal | MemberExpression}
|
||||
*/
|
||||
function toMemberExpression(id) {
|
||||
const identifiers = id.split('.')
|
||||
let index = -1
|
||||
/** @type {Identifier | Literal | MemberExpression | undefined} */
|
||||
let result
|
||||
|
||||
while (++index < identifiers.length) {
|
||||
/** @type {Identifier | Literal} */
|
||||
const prop = isIdentifierName(identifiers[index])
|
||||
? {type: 'Identifier', name: identifiers[index]}
|
||||
: {type: 'Literal', value: identifiers[index]}
|
||||
result = result
|
||||
? {
|
||||
type: 'MemberExpression',
|
||||
object: result,
|
||||
property: prop,
|
||||
computed: Boolean(index && prop.type === 'Literal'),
|
||||
optional: false
|
||||
}
|
||||
: prop
|
||||
}
|
||||
|
||||
// @ts-expect-error: always a result.
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {Node} T
|
||||
* @param {Node} from
|
||||
* @param {T} node
|
||||
* @returns {T}
|
||||
*/
|
||||
function create(from, node) {
|
||||
const fields = ['start', 'end', 'loc', 'range', 'comments']
|
||||
let index = -1
|
||||
|
||||
while (++index < fields.length) {
|
||||
const field = fields[index]
|
||||
if (field in from) {
|
||||
// @ts-expect-error: indexable.
|
||||
node[field] = from[field]
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue