🎉 initiate project *astro_rewrite*
This commit is contained in:
parent
ffd4d5e86c
commit
2ba37bfbe3
8658 changed files with 2268794 additions and 2538 deletions
308
node_modules/hast-util-to-estree/lib/handlers/element.js
generated
vendored
Normal file
308
node_modules/hast-util-to-estree/lib/handlers/element.js
generated
vendored
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/**
|
||||
* @typedef {import('hast').Element} Element
|
||||
* @typedef {import('estree').Property} Property
|
||||
* @typedef {import('estree-jsx').JSXElement} JsxElement
|
||||
* @typedef {import('estree-jsx').JSXSpreadAttribute} JsxSpreadAttribute
|
||||
* @typedef {import('estree-jsx').JSXAttribute} JsxAttribute
|
||||
* @typedef {import('../state.js').State} State
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Record<string, string>} Style
|
||||
*/
|
||||
|
||||
import {stringify as commas} from 'comma-separated-tokens'
|
||||
import {svg, find, hastToReact} from 'property-information'
|
||||
import {stringify as spaces} from 'space-separated-tokens'
|
||||
import {
|
||||
start as identifierStart,
|
||||
cont as identifierCont,
|
||||
name as identifierName
|
||||
} from 'estree-util-is-identifier-name'
|
||||
import styleToObject from 'style-to-object'
|
||||
|
||||
const own = {}.hasOwnProperty
|
||||
const cap = /[A-Z]/g
|
||||
const dashSomething = /-([a-z])/g
|
||||
|
||||
/**
|
||||
* Turn a hast element into an estree node.
|
||||
*
|
||||
* @param {Element} 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
|
||||
|
||||
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 === undefined ||
|
||||
value === null ||
|
||||
(typeof value === 'number' && Number.isNaN(value)) ||
|
||||
value === false ||
|
||||
(!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 = transformStyleToCssCasing(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'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
attributeValue = {
|
||||
type: 'JSXExpressionContainer',
|
||||
expression: {type: 'ObjectExpression', properties: cssProperties}
|
||||
}
|
||||
} else if (value === true) {
|
||||
attributeValue = null
|
||||
} else {
|
||||
attributeValue = {type: 'Literal', value: String(value)}
|
||||
}
|
||||
|
||||
if (jsxIdentifierName(prop)) {
|
||||
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 that’s a valid identifier.
|
||||
value: attributeValue || {type: 'Literal', value: true},
|
||||
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 exception = /** @type {Error} */ (error)
|
||||
exception.message =
|
||||
tagName + '[style]' + exception.message.slice('undefined'.length)
|
||||
throw error
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
/**
|
||||
* Add `name`, as a CSS prop, to `result`.
|
||||
*
|
||||
* @param {string} name
|
||||
* Key.
|
||||
* @param {string} value
|
||||
* Value.
|
||||
* @returns {void}
|
||||
* 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 transformStyleToCssCasing(domCasing) {
|
||||
/** @type {Style} */
|
||||
const cssCasing = {}
|
||||
/** @type {string} */
|
||||
let from
|
||||
|
||||
for (from in domCasing) {
|
||||
if (own.call(domCasing, from)) {
|
||||
let to = from.replace(cap, toDash)
|
||||
// Handle `ms-xxx` -> `-ms-xxx`.
|
||||
if (to.slice(0, 3) === 'ms-') to = '-' + to
|
||||
cssCasing[to] = domCasing[from]
|
||||
}
|
||||
}
|
||||
|
||||
return cssCasing
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given string is a valid identifier name.
|
||||
*
|
||||
* Allows dashes, so it’s actually JSX identifier names.
|
||||
*
|
||||
* @param {string} name
|
||||
* Whatever.
|
||||
* @returns {boolean}
|
||||
* Whether `name` is a valid JSX identifier.
|
||||
*/
|
||||
function jsxIdentifierName(name) {
|
||||
let index = -1
|
||||
|
||||
while (++index < name.length) {
|
||||
if (!(index ? cont : identifierStart)(name.charCodeAt(index))) return false
|
||||
}
|
||||
|
||||
// `false` if `name` is empty.
|
||||
return index > 0
|
||||
|
||||
/**
|
||||
* @param {number} code
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function cont(code) {
|
||||
return identifierCont(code) || code === 45 /* `-` */
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue