diff --git a/.editorconfig b/.editorconfig index c6c8b36..b368786 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,9 @@ root = true [*] -indent_style = space -indent_size = 2 -end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true +end_of_line = lf insert_final_newline = true +indent_size = 2 +indent_style = space +trim_trailing_whitespace = true diff --git a/.github/workflows/bb.yml b/.github/workflows/bb.yml index 0198fc3..3dbfce5 100644 --- a/.github/workflows/bb.yml +++ b/.github/workflows/bb.yml @@ -1,9 +1,3 @@ -name: bb -on: - issues: - types: [opened, reopened, edited, closed, labeled, unlabeled] - pull_request_target: - types: [opened, reopened, edited, closed, labeled, unlabeled] jobs: main: runs-on: ubuntu-latest @@ -11,3 +5,9 @@ jobs: - uses: unifiedjs/beep-boop-beta@main with: repo-token: ${{secrets.GITHUB_TOKEN}} +name: bb +on: + issues: + types: [closed, edited, labeled, opened, reopened, unlabeled] + pull_request_target: + types: [closed, edited, labeled, opened, reopened, unlabeled] diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fb63387..ade3921 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,21 +1,21 @@ -name: main -on: - - pull_request - - push jobs: main: name: ${{matrix.node}} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{matrix.node}} - run: npm install - run: npm test - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 strategy: matrix: node: - - lts/gallium + - lts/hydrogen - node +name: main +on: + - pull_request + - push diff --git a/.gitignore b/.gitignore index c977c85..388388c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -.DS_Store *.d.ts *.log +*.map +*.tsbuildinfo +.DS_Store coverage/ node_modules/ yarn.lock diff --git a/lib/handlers/comment.js b/lib/handlers/comment.js index c599da7..fe52ad8 100644 --- a/lib/handlers/comment.js +++ b/lib/handlers/comment.js @@ -1,12 +1,11 @@ /** - * @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 + * @import { + * JSXEmptyExpression as JsxEmptyExpression, + * JSXExpressionContainer as JsxExpressionContainer, + * } from 'estree-jsx' + * @import {Comment} from 'estree' + * @import {State} from 'hast-util-to-estree' + * @import {Comment as HastComment} from 'hast' */ // Make VS Code show references to the above types. diff --git a/lib/handlers/element.js b/lib/handlers/element.js index be8c289..babe841 100644 --- a/lib/handlers/element.js +++ b/lib/handlers/element.js @@ -1,17 +1,12 @@ /** - * @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} Style + * @import { + * JSXAttribute as JsxAttribute, + * JSXElement as JsxElement, + * JSXSpreadAttribute as JsxSpreadAttribute, + * } from 'estree-jsx' + * @import {Property} from 'estree' + * @import {State} from 'hast-util-to-estree' + * @import {Element as HastElement} from 'hast' */ import {stringify as commas} from 'comma-separated-tokens' @@ -40,7 +35,7 @@ const tableCellElement = new Set(['td', 'th']) export function element(node, state) { const parentSchema = state.schema let schema = parentSchema - const props = node.properties || {} + const properties = node.properties || {} if (parentSchema.space === 'html' && node.tagName.toLowerCase() === 'svg') { schema = svg @@ -52,16 +47,16 @@ export function element(node, state) { /** @type {Array} */ const attributes = [] /** @type {string} */ - let prop + let property /** @type {string | undefined} */ let alignValue /** @type {Array | undefined} */ let styleProperties - for (prop in props) { - if (own.call(props, prop)) { - let value = props[prop] - const info = find(schema, prop) + for (property in properties) { + if (own.call(properties, property)) { + let value = properties[property] + const info = find(schema, property) /** @type {JsxAttribute['value']} */ let attributeValue @@ -77,18 +72,18 @@ export function element(node, state) { continue } - prop = + property = state.elementAttributeNameCase === 'react' && info.space ? hastToReact[info.property] || info.property : info.attribute if (Array.isArray(value)) { // Accept `array`. - // Most props are space-separated. + // Most properties are space-separated. value = info.commaSeparated ? commas(value) : spaces(value) } - if (prop === 'style') { + if (property === 'style') { let styleObject = typeof value === 'object' ? value @@ -101,20 +96,20 @@ export function element(node, state) { /** @type {Array} */ const cssProperties = [] /** @type {string} */ - let cssProp + let cssProperty - for (cssProp in styleObject) { + for (cssProperty in styleObject) { // eslint-disable-next-line max-depth - if (own.call(styleObject, cssProp)) { + if (own.call(styleObject, cssProperty)) { 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])}, + key: identifierName(cssProperty) + ? {type: 'Identifier', name: cssProperty} + : {type: 'Literal', value: cssProperty}, + value: {type: 'Literal', value: String(styleObject[cssProperty])}, kind: 'init' }) } @@ -130,7 +125,7 @@ export function element(node, state) { } else if ( state.tableCellAlignToStyle && tableCellElement.has(node.tagName) && - prop === 'align' + property === 'align' ) { alignValue = String(value) continue @@ -138,10 +133,10 @@ export function element(node, state) { attributeValue = {type: 'Literal', value: String(value)} } - if (identifierName(prop, {jsx: true})) { + if (identifierName(property, {jsx: true})) { attributes.push({ type: 'JSXAttribute', - name: {type: 'JSXIdentifier', name: prop}, + name: {type: 'JSXIdentifier', name: property}, value: attributeValue }) } else { @@ -155,7 +150,7 @@ export function element(node, state) { method: false, shorthand: false, computed: false, - key: {type: 'Literal', value: String(prop)}, + key: {type: 'Literal', value: String(property)}, // @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}, @@ -181,7 +176,7 @@ export function element(node, state) { }) } - const cssProp = + const cssProperty = state.stylePropertyNameCase === 'css' ? transformStyleToCssCasing('textAlign') : 'textAlign' @@ -191,9 +186,9 @@ export function element(node, state) { method: false, shorthand: false, computed: false, - key: identifierName(cssProp) - ? {type: 'Identifier', name: cssProp} - : {type: 'Literal', value: cssProp}, + key: identifierName(cssProperty) + ? {type: 'Identifier', name: cssProperty} + : {type: 'Literal', value: cssProperty}, value: {type: 'Literal', value: alignValue}, kind: 'init' }) @@ -231,11 +226,11 @@ export function element(node, state) { * CSS text. * @param {string} tagName * Element name. - * @returns {Style} - * Props. + * @returns {Record} + * Properties. */ function parseStyle(value, tagName) { - /** @type {Style} */ + /** @type {Record} */ const result = {} try { @@ -252,7 +247,7 @@ function parseStyle(value, tagName) { return result /** - * Add `name`, as a CSS prop, to `result`. + * Add `name`, as a CSS property, to `result`. * * @param {string} name * Key. @@ -277,11 +272,11 @@ function parseStyle(value, tagName) { /** * Transform a DOM casing style object to a CSS casing style object. * - * @param {Style} domCasing - * @returns {Style} + * @param {Record} domCasing + * @returns {Record} */ function transformStylesToCssCasing(domCasing) { - /** @type {Style} */ + /** @type {Record} */ const cssCasing = {} /** @type {string} */ let from @@ -296,7 +291,7 @@ function transformStylesToCssCasing(domCasing) { } /** - * Transform a DOM casing style prop to a CSS casing style prop. + * Transform a DOM casing style property to a CSS casing style property. * * @param {string} from * @returns {string} diff --git a/lib/handlers/mdx-expression.js b/lib/handlers/mdx-expression.js index b775140..358c661 100644 --- a/lib/handlers/mdx-expression.js +++ b/lib/handlers/mdx-expression.js @@ -1,13 +1,14 @@ /** - * @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 { + * JSXEmptyExpression as JsxEmptyExpression, + * JSXExpressionContainer as JsxExpressionContainer + * } from 'estree-jsx' + * @import {Expression} from 'estree' + * @import { + * MdxFlowExpressionHast as MdxFlowExpression, + * MdxTextExpressionHast as MdxTextExpression + * } from 'mdast-util-mdx-expression' + * @import {State} from 'hast-util-to-estree' */ import {attachComments} from 'estree-util-attach-comments' diff --git a/lib/handlers/mdx-jsx-element.js b/lib/handlers/mdx-jsx-element.js index bf16e58..0a0f136 100644 --- a/lib/handlers/mdx-jsx-element.js +++ b/lib/handlers/mdx-jsx-element.js @@ -1,15 +1,16 @@ /** - * @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 { + * JSXAttribute as JsxAttribute, + * JSXElement as JsxElement, + * JSXFragment as JsxFragment, + * JSXSpreadAttribute as JsxSpreadAttribute + * } from 'estree-jsx' + * @import {Expression} from 'estree' + * @import {State} from 'hast-util-to-estree' + * @import { + * MdxJsxFlowElementHast as MdxJsxFlowElement, + * MdxJsxTextElementHast as MdxJsxTextElement + * } from 'mdast-util-mdx-jsx' */ import {attachComments} from 'estree-util-attach-comments' @@ -29,7 +30,7 @@ import {svg} from 'property-information' export function mdxJsxElement(node, state) { const parentSchema = state.schema let schema = parentSchema - const attrs = node.attributes || [] + const attributes = node.attributes || [] let index = -1 if ( @@ -43,15 +44,15 @@ export function mdxJsxElement(node, state) { const children = state.all(node) /** @type {Array} */ - const attributes = [] + const jsxAttributes = [] - while (++index < attrs.length) { - const attr = attrs[index] - const value = attr.value + while (++index < attributes.length) { + const attribute = attributes[index] + const value = attribute.value /** @type {JsxAttribute['value']} */ let attributeValue - if (attr.type === 'mdxJsxAttribute') { + if (attribute.type === 'mdxJsxAttribute') { if (value === null || value === undefined) { attributeValue = null // Empty. @@ -87,18 +88,18 @@ export function mdxJsxElement(node, state) { } /** @type {JsxAttribute} */ - const attribute = { + const jsxAttribute = { type: 'JSXAttribute', - name: state.createJsxAttributeName(attr.name), + name: state.createJsxAttributeName(attribute.name), value: attributeValue } - state.inherit(attr, attribute) - attributes.push(attribute) + state.inherit(attribute, jsxAttribute) + jsxAttributes.push(jsxAttribute) } // MdxJsxExpressionAttribute. else { - const estree = attr.data && attr.data.estree + const estree = attribute.data && attribute.data.estree const comments = (estree && estree.comments) || [] /** @type {JsxSpreadAttribute['argument'] | undefined} */ let argumentValue @@ -121,12 +122,12 @@ export function mdxJsxElement(node, state) { } /** @type {JsxSpreadAttribute} */ - const attribute = { + const jsxAttribute = { type: 'JSXSpreadAttribute', argument: argumentValue || {type: 'ObjectExpression', properties: []} } - state.inherit(attr, attribute) - attributes.push(attribute) + state.inherit(attribute, jsxAttribute) + jsxAttributes.push(jsxAttribute) } } @@ -139,7 +140,7 @@ export function mdxJsxElement(node, state) { type: 'JSXElement', openingElement: { type: 'JSXOpeningElement', - attributes, + attributes: jsxAttributes, name: state.createJsxElementName(node.name), selfClosing: children.length === 0 }, diff --git a/lib/handlers/mdxjs-esm.js b/lib/handlers/mdxjs-esm.js index 1caa281..fe866d1 100644 --- a/lib/handlers/mdxjs-esm.js +++ b/lib/handlers/mdxjs-esm.js @@ -1,7 +1,6 @@ /** - * @typedef {import('mdast-util-mdxjs-esm').MdxjsEsmHast} MdxjsEsm - * - * @typedef {import('../state.js').State} State + * @import {MdxjsEsmHast as MdxjsEsm} from 'mdast-util-mdxjs-esm' + * @import {State} from 'hast-util-to-estree' */ import {attachComments} from 'estree-util-attach-comments' diff --git a/lib/handlers/root.js b/lib/handlers/root.js index e52e7d1..5c92764 100644 --- a/lib/handlers/root.js +++ b/lib/handlers/root.js @@ -1,13 +1,13 @@ /** - * @typedef {import('estree-jsx').JSXFragment} JsxFragment - * - * @typedef {import('hast').Root} HastRoot - * - * @typedef {import('../state.js').State} State - */ - -/** - * @typedef {JsxFragment['children'][number]} JsxChild + * @import { + * JSXElement as JsxElement, + * JSXExpressionContainer as JsxExpressionContainer, + * JSXFragment as JsxFragment, + * JSXSpreadChild as JsxSpreadChild, + * JSXText as JsxText, + * } from 'estree-jsx' + * @import {State} from 'hast-util-to-estree' + * @import {Root as HastRoot} from 'hast' */ import {whitespace} from 'hast-util-whitespace' @@ -24,10 +24,10 @@ import {whitespace} from 'hast-util-whitespace' */ export function root(node, state) { const children = state.all(node) - /** @type {Array} */ + /** @type {Array} */ const cleanChildren = [] let index = -1 - /** @type {Array | undefined} */ + /** @type {Array | undefined} */ let queue // Remove surrounding whitespace nodes from the fragment. diff --git a/lib/handlers/text.js b/lib/handlers/text.js index eb5daf6..c836492 100644 --- a/lib/handlers/text.js +++ b/lib/handlers/text.js @@ -1,11 +1,8 @@ /** - * @typedef {import('estree').Literal} Literal - * - * @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer - * - * @typedef {import('hast').Text} HastText - * - * @typedef {import('../state.js').State} State + * @import {JSXExpressionContainer as JsxExpressionContainer} from 'estree-jsx' + * @import {Literal} from 'estree' + * @import {State} from 'hast-util-to-estree' + * @import {Text as HastText} from 'hast' */ // Make VS Code show references to the above types. diff --git a/lib/index.js b/lib/index.js index fc0c5b1..a5f8338 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,18 +1,10 @@ /** - * Register MDX nodes in tree: - * - * @typedef {import('mdast-util-mdx-expression')} - * @typedef {import('mdast-util-mdx-jsx')} - * @typedef {import('mdast-util-mdxjs-esm')} - */ - -/** - * @typedef {import('estree').ExpressionStatement} ExpressionStatement - * @typedef {import('estree').Program} Program - * - * @typedef {import('hast').Nodes} HastNodes - * - * @typedef {import('./state.js').Options} Options + * @import {} from 'mdast-util-mdx-expression' + * @import {} from 'mdast-util-mdx-jsx' + * @import {} from 'mdast-util-mdxjs-esm' + * @import {ExpressionStatement, Program} from 'estree' + * @import {Options} from 'hast-util-to-estree' + * @import {Nodes as HastNodes} from 'hast' */ import {createState} from './state.js' @@ -84,7 +76,6 @@ export function toEstree(tree, options) { } /** @type {ExpressionStatement} */ - // @ts-expect-error: `estree` types don’t allow JSX. const statement = {type: 'ExpressionStatement', expression: result} state.patch(tree, statement) body.push(statement) diff --git a/lib/state.js b/lib/state.js index 9d4be69..ef7fc82 100644 --- a/lib/state.js +++ b/lib/state.js @@ -1,30 +1,18 @@ /** - * @typedef {import('estree').Comment} Comment - * @typedef {import('estree').Directive} Directive - * @typedef {import('estree').ModuleDeclaration} ModuleDeclaration - * @typedef {import('estree').Node} EstreeNode - * @typedef {import('estree').Statement} Statement - * - * @typedef {import('estree-jsx').JSXAttribute} JsxAttribute - * @typedef {import('estree-jsx').JSXElement} JsxElement - * @typedef {import('estree-jsx').JSXIdentifier} JsxIdentifier - * @typedef {import('estree-jsx').JSXMemberExpression} JsxMemberExpression - * @typedef {import('estree-jsx').JSXNamespacedName} JsxNamespacedName - * - * @typedef {import('mdast-util-mdx-jsx').MdxJsxAttribute} MdxJsxAttribute - * @typedef {import('mdast-util-mdx-jsx').MdxJsxAttributeValueExpression} MdxJsxAttributeValueExpression - * @typedef {import('mdast-util-mdx-jsx').MdxJsxExpressionAttribute} MdxJsxExpressionAttribute - * - * @typedef {import('hast').Nodes} HastNodes - * @typedef {import('hast').Parents} HastParents - * - * @typedef {import('property-information').Schema} Schema - */ - -/** - * @typedef {JsxElement['openingElement']['name']} JsxElementName - * @typedef {JsxAttribute['name']} JsxAttributeName - * @typedef {JsxElement['children'][number]} JsxChild + * @import { + * JSXElement as JsxElement, + * JSXExpressionContainer as JsxExpressionContainer, + * JSXFragment as JsxFragment, + * JSXIdentifier as JsxIdentifier, + * JSXMemberExpression as JsxMemberExpression, + * JSXNamespacedName as JsxNamespacedName, + * JSXSpreadChild as JsxSpreadChild, + * JSXText as JsxText, + * } from 'estree-jsx' + * @import {Comment, Directive, ModuleDeclaration, Node as EstreeNode, Statement} from 'estree' + * @import {MdxJsxAttribute, MdxJsxAttributeValueExpression, MdxJsxExpressionAttribute} from 'mdast-util-mdx-jsx' + * @import {Nodes as HastNodes, Parents as HastParents} from 'hast' + * @import {Schema} from 'property-information' */ /** @@ -40,7 +28,7 @@ * Expected hast node. * @param {State} state * Info passed around about the current state. - * @returns {JsxChild | null | undefined} + * @returns {JsxElement | JsxExpressionContainer | JsxFragment | JsxSpreadChild | JsxText | null | undefined} * estree node. * * @typedef Options @@ -78,19 +66,19 @@ * * @typedef State * Info passed around about the current state. - * @property {(parent: HastParents) => Array} all + * @property {(parent: HastParents) => Array} all * Transform children of a hast parent to estree. * @property {Array} comments * List of estree comments. - * @property {(name: string) => JsxAttributeName} createJsxAttributeName + * @property {(name: string) => JsxIdentifier | JsxNamespacedName} createJsxAttributeName * Create a JSX attribute name. - * @property {(name: string) => JsxElementName} createJsxElementName + * @property {(name: string) => JsxIdentifier | JsxMemberExpression | JsxNamespacedName} createJsxElementName * Create a JSX element name. * @property {ElementAttributeNameCase} elementAttributeNameCase * Casing to use for attribute names. * @property {Array} esm * List of top-level estree nodes. - * @property {(node: any) => JsxChild | null | undefined} handle + * @property {(node: any) => JsxElement | JsxExpressionContainer | JsxFragment | JsxSpreadChild | JsxText | null | undefined} handle * Transform a hast node to estree. * @property {(from: HastNodes | MdxJsxAttribute | MdxJsxAttributeValueExpression | MdxJsxExpressionAttribute, to: Comment | EstreeNode) => undefined} inherit * Take positional info and data from `from` (use `patch` if you don’t want data). @@ -164,7 +152,7 @@ export function createState(options) { /** * @this {State} * @param {any} node - * @returns {JsxChild | null | undefined} + * @returns {JsxElement | JsxExpressionContainer | JsxFragment | JsxSpreadChild | JsxText | null | undefined} */ function handle(node) { return one(node, this) @@ -202,13 +190,13 @@ function unknown(node) { * Info passed around about the current state. * @param {HastParents} parent * hast node whose children to transform. - * @returns {Array} + * @returns {Array} * estree nodes. */ function all(parent) { const children = parent.children || [] let index = -1 - /** @type {Array} */ + /** @type {Array} */ const results = [] const ignoreLineBreak = this.schema.space === 'html' && @@ -302,7 +290,7 @@ function patch(from, to) { * Create a JSX attribute name. * * @param {string} name - * @returns {JsxAttributeName} + * @returns {JsxIdentifier | JsxNamespacedName} */ function createJsxAttributeName(name) { const node = createJsxNameFromString(name) @@ -320,7 +308,7 @@ function createJsxAttributeName(name) { * Create a JSX element name. * * @param {string} name - * @returns {JsxElementName} + * @returns {JsxIdentifier | JsxMemberExpression | JsxNamespacedName} */ function createJsxElementName(name) { return createJsxNameFromString(name) diff --git a/license b/license index 8d8660d..bc8f165 100644 --- a/license +++ b/license @@ -1,6 +1,6 @@ (The MIT License) -Copyright (c) 2016 Titus Wormer +Copyright (c) Titus Wormer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/package.json b/package.json index 4f4d512..3a98b5f 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,9 @@ { - "name": "hast-util-to-estree", - "version": "3.1.0", - "description": "hast utility to transform to estree (JavaScript AST) JSX", - "license": "MIT", - "keywords": [ - "unist", - "hast", - "hast-util", - "util", - "utility", - "html", - "change", - "transform", - "rehype", - "estree", - "jsx", - "javascript", - "ecmascript", - "mdx" - ], - "repository": "syntax-tree/hast-util-to-estree", - "bugs": "https://github.com/syntax-tree/hast-util-to-estree/issues", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, "author": "Titus Wormer (https://wooorm.com)", + "bugs": "https://github.com/syntax-tree/hast-util-to-estree/issues", "contributors": [ "Titus Wormer (https://wooorm.com)" ], - "sideEffects": false, - "type": "module", - "exports": "./index.js", - "files": [ - "lib/", - "index.d.ts", - "index.js" - ], "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", @@ -51,38 +18,60 @@ "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.4.0", + "style-to-object": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" }, + "description": "hast utility to transform to estree (JavaScript AST) JSX", "devDependencies": { - "@types/node": "^20.0.0", + "@types/node": "^22.0.0", "acorn-jsx": "^5.0.0", - "c8": "^8.0.0", + "c8": "^10.0.0", "esast-util-from-js": "^2.0.0", "estree-util-to-js": "^2.0.0", "estree-walker": "^3.0.0", - "hastscript": "^8.0.0", + "hastscript": "^9.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx": "^3.0.0", "mdast-util-to-hast": "^13.0.0", - "micromark-extension-mdxjs": "^2.0.0", + "micromark-extension-mdxjs": "^3.0.0", "prettier": "^3.0.0", - "remark-cli": "^11.0.0", - "remark-preset-wooorm": "^9.0.0", + "remark-cli": "^12.0.0", + "remark-preset-wooorm": "^10.0.0", "type-coverage": "^2.0.0", "typescript": "^5.0.0", "unist-util-visit": "^5.0.0", - "xo": "^0.56.0" + "xo": "^0.60.0" }, - "scripts": { - "prepack": "npm run build && npm run format", - "build": "tsc --build --clean && tsc --build && type-coverage", - "format": "remark . -qfo && prettier . -w --log-level warn && xo --fix", - "test-api": "node --conditions development test.js", - "test-coverage": "c8 --100 --reporter lcov npm run test-api", - "test": "npm run build && npm run format && npm run test-coverage" + "exports": "./index.js", + "files": [ + "index.d.ts.map", + "index.d.ts", + "index.js", + "lib/" + ], + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, + "keywords": [ + "change", + "ecmascript", + "estree", + "hast-util", + "hast", + "html", + "javascript", + "jsx", + "mdx", + "rehype", + "transform", + "unist", + "utility", + "util" + ], + "license": "MIT", + "name": "hast-util-to-estree", "prettier": { "bracketSpacing": false, "semi": false, @@ -96,20 +85,30 @@ "remark-preset-wooorm" ] }, + "repository": "syntax-tree/hast-util-to-estree", + "scripts": { + "build": "tsc --build --clean && tsc --build && type-coverage", + "format": "remark --frail --output --quiet -- . && prettier --log-level warn --write -- . && xo --fix", + "test-api": "node --conditions development test.js", + "test-coverage": "c8 --100 --reporter lcov -- npm run test-api", + "test": "npm run build && npm run format && npm run test-coverage" + }, + "sideEffects": false, "typeCoverage": { "atLeast": 100, - "detail": true, - "ignoreCatch": true, - "#": "needed any", + "ignoreFiles#": "needed `any`", "ignoreFiles": [ "lib/state.d.ts", "lib/state.js" ], "strict": true }, + "type": "module", + "version": "3.1.1", "xo": { "prettier": true, "rules": { + "logical-assignment-operators": "off", "unicorn/prefer-code-point": "off", "unicorn/prefer-string-replace-all": "off" } diff --git a/readme.md b/readme.md index 03a6a9a..5aaf5b8 100644 --- a/readme.md +++ b/readme.md @@ -12,25 +12,25 @@ ## Contents -* [What is this?](#what-is-this) -* [When should I use this?](#when-should-i-use-this) -* [Install](#install) -* [Use](#use) -* [API](#api) - * [`toEstree(tree[, options])`](#toestreetree-options) - * [`defaultHandlers`](#defaulthandlers) - * [`ElementAttributeNameCase`](#elementattributenamecase) - * [`Handle`](#handle) - * [`Options`](#options) - * [`Space`](#space) - * [`State`](#state) - * [`StylePropertyNameCase`](#stylepropertynamecase) -* [Types](#types) -* [Compatibility](#compatibility) -* [Security](#security) -* [Related](#related) -* [Contribute](#contribute) -* [License](#license) +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`toEstree(tree[, options])`](#toestreetree-options) + * [`defaultHandlers`](#defaulthandlers) + * [`ElementAttributeNameCase`](#elementattributenamecase) + * [`Handle`](#handle) + * [`Options`](#options) + * [`Space`](#space) + * [`State`](#state) + * [`StylePropertyNameCase`](#stylepropertynamecase) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) ## What is this? @@ -185,10 +185,10 @@ options. ###### Parameters -* `tree` ([`HastNode`][hast-node]) - — hast tree -* `options` ([`Options`][api-options], optional) - — configuration +* `tree` ([`HastNode`][hast-node]) + — hast tree +* `options` ([`Options`][api-options], optional) + — configuration ###### Returns @@ -233,10 +233,10 @@ Turn a hast node into an estree node (TypeScript type). ###### Parameters -* `node` ([`HastNode`][hast-node]) - — expected hast node -* `state` ([`State`][api-state]) - — info passed around about the current state +* `node` ([`HastNode`][hast-node]) + — expected hast node +* `state` ([`State`][api-state]) + — info passed around about the current state ###### Returns @@ -250,26 +250,26 @@ Configuration (TypeScript type). ###### Fields -* `elementAttributeNameCase` - ([`ElementAttributeNameCase`][api-element-attribute-name-case], default: - `'react'`) - — specify casing to use for attribute names; this casing is used for hast - elements, not for embedded MDX JSX nodes (components that someone authored - manually) -* `handlers` (`Record`, optional) - — custom handlers -* `space` ([`Space`][api-space], default: `'html'`) - — which space the document is in; when an `` element is found in the - HTML space, this package already automatically switches to and from the SVG - space when entering and exiting it -* `stylePropertyNameCase` - ([`StylePropertyNameCase`][api-style-property-name-case], - default: `'dom'`) - — specify casing to use for property names in `style` objects; this casing - is used for hast elements, not for embedded MDX JSX nodes (components that - someone authored manually) -* `tableCellAlignToStyle` (`boolean`, default: `true`) - — turn obsolete `align` props on `td` and `th` into CSS `style` props +* `elementAttributeNameCase` + ([`ElementAttributeNameCase`][api-element-attribute-name-case], default: + `'react'`) + — specify casing to use for attribute names; this casing is used for hast + elements, not for embedded MDX JSX nodes (components that someone authored + manually) +* `handlers` (`Record`, optional) + — custom handlers +* `space` ([`Space`][api-space], default: `'html'`) + — which space the document is in; when an `` element is found in the + HTML space, this package already automatically switches to and from the SVG + space when entering and exiting it +* `stylePropertyNameCase` + ([`StylePropertyNameCase`][api-style-property-name-case], + default: `'dom'`) + — specify casing to use for property names in `style` objects; this casing + is used for hast elements, not for embedded MDX JSX nodes (components that + someone authored manually) +* `tableCellAlignToStyle` (`boolean`, default: `true`) + — turn obsolete `align` props on `td` and `th` into CSS `style` props ### `Space` @@ -287,33 +287,33 @@ Info passed around about the current state (TypeScript type). ###### Fields -* `all` (`(node: HastParent) => EstreeJsxChild | undefined`) - — transform children of a hast parent to estree -* `comments` (`Array`) - — list of estree comments -* `createJsxAttributeName` (`(name: string) => EstreeJsxAttributeName`) - — create a JSX attribute name -* `createJsxElementName` (`(name: string) => EstreeJsxElementName`) - — create a JSX attribute name -* `elementAttributeNameCase` - ([`ElementAttributeNameCase`][api-element-attribute-name-case]) - — casing to use for attribute names -* `esm` (`Array`) - — list of top-level estree nodes -* `handle` (`(node: HastNode) => EstreeJsxChild | undefined`) - — transform a hast node to estree -* `inherit` (`(from: HastNode, to: EstreeNode) => undefined`) - — take positional info and data from `from` (use `patch` if you don’t want - data) -* `patch` (`(from: HastNode, to: EstreeNode) => undefined`) - — take positional info from `from` (use `inherit` if you also want data) -* `schema` ([`Schema`][schema]) - — current schema -* `stylePropertyNameCase` - ([`StylePropertyNameCase`][api-style-property-name-case]) - — casing for property names in `style` objects -* `tableCellAlignToStyle` (`boolean`) - — turn obsolete `align` props on `td` and `th` into CSS `style` props +* `all` (`(node: HastParent) => EstreeJsxChild | undefined`) + — transform children of a hast parent to estree +* `comments` (`Array`) + — list of estree comments +* `createJsxAttributeName` (`(name: string) => EstreeJsxAttributeName`) + — create a JSX attribute name +* `createJsxElementName` (`(name: string) => EstreeJsxElementName`) + — create a JSX attribute name +* `elementAttributeNameCase` + ([`ElementAttributeNameCase`][api-element-attribute-name-case]) + — casing to use for attribute names +* `esm` (`Array`) + — list of top-level estree nodes +* `handle` (`(node: HastNode) => EstreeJsxChild | undefined`) + — transform a hast node to estree +* `inherit` (`(from: HastNode, to: EstreeNode) => undefined`) + — take positional info and data from `from` (use `patch` if you don’t want + data) +* `patch` (`(from: HastNode, to: EstreeNode) => undefined`) + — take positional info from `from` (use `inherit` if you also want data) +* `schema` ([`Schema`][schema]) + — current schema +* `stylePropertyNameCase` + ([`StylePropertyNameCase`][api-style-property-name-case]) + — casing for property names in `style` objects +* `tableCellAlignToStyle` (`boolean`) + — turn obsolete `align` props on `td` and `th` into CSS `style` props ### `StylePropertyNameCase` @@ -354,12 +354,12 @@ It’s not safe. ## Related -* [`estree-util-build-jsx`][build-jsx] - — transform JSX to function calls -* [`hastscript`][hastscript] - — hyperscript compatible interface for creating nodes -* [`hast-util-from-dom`](https://github.com/syntax-tree/hast-util-from-dom) - — transform a DOM tree to hast +* [`estree-util-build-jsx`][build-jsx] + — transform JSX to function calls +* [`hastscript`][hastscript] + — hyperscript compatible interface for creating nodes +* [`hast-util-from-dom`](https://github.com/syntax-tree/hast-util-from-dom) + — transform a DOM tree to hast ## Contribute diff --git a/test.js b/test.js index 11a5ce1..4b50310 100644 --- a/test.js +++ b/test.js @@ -1,10 +1,7 @@ /** - * @typedef {import('estree').Program} Program - * @typedef {import('estree').Node} Node - * @typedef {import('hast').Nodes} HastNodes - * @typedef {import('mdast-util-mdx-jsx').MdxJsxAttribute} MdxJsxAttribute - * @typedef {import('mdast-util-mdx-jsx').MdxJsxAttributeValueExpression} MdxJsxAttributeValueExpression - * @typedef {import('mdast-util-mdx-jsx').MdxJsxExpressionAttribute} MdxJsxExpressionAttribute + * @import {Node, Program} from 'estree' + * @import {Nodes as HastNodes} from 'hast' + * @import {MdxJsxAttributeValueExpression, MdxJsxAttribute, MdxJsxExpressionAttribute} from 'mdast-util-mdx-jsx' */ import assert from 'node:assert/strict' @@ -136,6 +133,7 @@ test('toEstree', async function (t) { tagName: 'x', properties: {}, children: [], + // @ts-expect-error: untyped data. data: {a: 1, b: null, c: undefined} }), { @@ -1145,13 +1143,13 @@ test('integration (micromark-extension-mdxjs, mdast-util-mdx)', async function ( ) /** - * @param {string} doc + * @param {string} value * MDX. * @param {boolean} [clean=false] * Whether to clean the tree (default: `false`). */ - function transform(doc, clean) { - const mdast = fromMarkdown(doc, { + function transform(value, clean) { + const mdast = fromMarkdown(value, { extensions: [mdxjs()], mdastExtensions: [mdxFromMarkdown()] }) @@ -1195,7 +1193,7 @@ function acornClean(node) { walk(node, {enter}) - return JSON.parse(JSON.stringify(node)) + return structuredClone(node) /** @param {Node} node */ function enter(node) { @@ -1213,14 +1211,11 @@ function acornClean(node) { } /** - * @param {string} doc + * @param {string} value * JavaScript module. * @returns {Program} * ESTree program. */ -function acornParse(doc) { - return fromJs(doc, { - module: true, - plugins: [acornJsx()] - }) +function acornParse(value) { + return fromJs(value, {module: true, plugins: [acornJsx()]}) } diff --git a/tsconfig.json b/tsconfig.json index 82cc749..fc3d1e4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "checkJs": true, "customConditions": ["development"], + "declarationMap": true, "declaration": true, "emitDeclarationOnly": true, "exactOptionalPropertyTypes": true,