diff --git a/index.js b/index.js index d619a92..568e5d4 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,56 @@ /** - * @typedef {import('./lib/components.js').Components} Components - * @typedef {import('./lib/components.js').ExtraProps} ExtraProps - * @typedef {import('./lib/index.js').CreateEvaluater} CreateEvaluater + * @typedef {unknown} Components + * @typedef {unknown} ExtraProps * @typedef {import('./lib/index.js').ElementAttributeNameCase} ElementAttributeNameCase - * @typedef {import('./lib/index.js').EvaluateExpression} EvaluateExpression * @typedef {import('./lib/index.js').EvaluateProgram} EvaluateProgram - * @typedef {import('./lib/index.js').Evaluater} Evaluater - * @typedef {import('./lib/index.js').Fragment} Fragment - * @typedef {import('./lib/index.js').Jsx} Jsx - * @typedef {import('./lib/index.js').JsxDev} JsxDev - * @typedef {import('./lib/index.js').Options} Options - * @typedef {import('./lib/index.js').Props} Props + * @typedef {unknown} Fragment * @typedef {import('./lib/index.js').Source} Source * @typedef {import('./lib/index.js').Space} Space * @typedef {import('./lib/index.js').StylePropertyNameCase} StylePropertyNameCase */ +/** + * @template [JsxElementType=any] + * @template [JsxProps=any] + * @template [JsxKey=any] + * @template [JsxElement=any] + * @typedef {import('./lib/index.js').Jsx} Jsx + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').CreateEvaluater} CreateEvaluater + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').EvaluateExpression} EvaluateExpression + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').Evaluater} Evaluater + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').JsxDev} JsxDev + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').Options} Options + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {import('./lib/index.js').Props} Props + */ + export {toJsxRuntime} from './lib/index.js' diff --git a/lib/components.d.ts b/lib/components.d.ts deleted file mode 100644 index d11011a..0000000 --- a/lib/components.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type {Element} from 'hast' - -/** - * Basic functional component: given props, returns an element. - * - * @typeParam ComponentProps - * Props type. - * @param props - * Props. - * @returns - * Result. - */ -export type FunctionComponent = ( - props: ComponentProps -) => JSX.Element | string | null | undefined - -/** - * Class component: given props, returns an instance. - * - * @typeParam ComponentProps - * Props type. - * @param props - * Props. - * @returns - * Instance. - */ -export type ClassComponent = new ( - props: ComponentProps -) => JSX.ElementClass - -/** - * Function or class component. - * - * You can access props at `JSX.IntrinsicElements`. - * For example, to find props for `a`, use `JSX.IntrinsicElements['a']`. - * - * @typeParam ComponentProps - * Props type. - */ -export type Component = - | ClassComponent - | FunctionComponent - -/** - * Extra fields we pass. - */ -export type ExtraProps = {node?: Element | undefined} - -/** - * Possible components to use. - * - * Each key is a tag name typed in `JSX.IntrinsicElements`. - * Each value is either a different tag name, or a component accepting the - * corresponding props (and an optional `node` prop if `passNode` is on). - * - * You can access props at `JSX.IntrinsicElements`. - * For example, to find props for `a`, use `JSX.IntrinsicElements['a']`. - */ -// Note: this type has to be in `.ts` or `.d.ts`, otherwise TSC hardcodes -// react into the `.d.ts` file. -export type Components = { - [TagName in keyof JSX.IntrinsicElements]: - | Component - | keyof JSX.IntrinsicElements -} diff --git a/lib/components.js b/lib/components.js deleted file mode 100644 index 3efcbf7..0000000 --- a/lib/components.js +++ /dev/null @@ -1,2 +0,0 @@ -// TypeScript only. -export {} diff --git a/lib/index.js b/lib/index.js index 2a1b093..ffdae02 100644 --- a/lib/index.js +++ b/lib/index.js @@ -27,45 +27,61 @@ * @typedef {import('property-information').Schema} Schema * * @typedef {import('unist').Position} Position - * - * @typedef {import('./components.js').Components} Components */ /** - * @typedef {JSX.Element | string | null | undefined} Child + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {ReturnType | string | null | undefined} Child * Child. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @callback Create * Create something in development or production. * @param {Nodes} node * hast node. - * @param {unknown} type + * @param {GetType} type * Fragment symbol or tag name. - * @param {Props} props + * @param {GetProps} props * Properties and children. - * @param {string | undefined} key + * @param {GetKey} [key] * Key. - * @returns {JSX.Element} + * @returns {ReturnType} * Result. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @callback CreateEvaluater * Create an evaluator that turns ESTree ASTs from embedded MDX into values. - * @returns {Evaluater} + * @returns {Evaluater} * Evaluater. - * + */ + +/** * @typedef {'html' | 'react'} ElementAttributeNameCase * Casing to use for attribute names. * * HTML casing is for example `class`, `stroke-linecap`, `xml:lang`. * React casing is for example `className`, `strokeLinecap`, `xmlLang`. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @callback EvaluateExpression * Turn an MDX expression into a value. * @param {Expression} expression * ESTree expression. - * @returns {unknown} + * @returns {GetType} * Result of expression. - * + */ + +/** * @callback EvaluateProgram * Turn an MDX program (export/import statements) into a value. * @param {Program} expression @@ -74,57 +90,103 @@ * Result of program; * should likely be `undefined` as ESM changes the scope but doesn’t yield * something. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef Evaluater * Evaluator that turns ESTree ASTs from embedded MDX into values. - * @property {EvaluateExpression} evaluateExpression + * @property {EvaluateExpression} evaluateExpression * Evaluate an expression. * @property {EvaluateProgram} evaluateProgram * Evaluate a program. - * + */ + +/** * @typedef {[string, Value]} Field * Property field. - * - * @typedef {unknown} Fragment - * Represent the children, typically a symbol. - * + */ + +/** + * @template [JsxElementType=any] + * Element type: `Fragment` symbol, tag name (`string`), component. + * @template [JsxProps=any] + * Element props, `children`, and maybe `node`. + * @template [JsxKey=any] + * Dynamicly generated key to use. + * @template [JsxElement=any] + * Analogous to `JSX.Element`. * @callback Jsx * Create a production element. - * @param {unknown} type + * @param {JsxElementType} type * Element type: `Fragment` symbol, tag name (`string`), component. - * @param {Props} props + * @param {JsxProps} props * Element props, `children`, and maybe `node`. - * @param {string | undefined} [key] + * @param {JsxKey} [key] * Dynamicly generated key to use. - * @returns {JSX.Element} + * @returns {JsxElement} * Element from your framework. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {Parameters[0]} GetType + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {Parameters[1]} GetProps + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {Parameters[2]} GetKey + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @callback JsxDev * Create a development element. - * @param {unknown} type + * @param {GetType} type * Element type: `Fragment` symbol, tag name (`string`), component. - * @param {Props} props + * @param {GetProps} props * Element props, `children`, and maybe `node`. - * @param {string | undefined} key + * @param {GetKey | undefined} key * Dynamicly generated key to use. * @param {boolean} isStaticChildren * Whether two or more children are passed (in an array), which is whether * `jsxs` or `jsx` would be used. - * @param {Source} source + * @param {Source} [source] * Info about source. - * @param {undefined} self + * @param {unknown} [self=unknown] * Nothing (this is used by frameworks that have components, we don’t). - * @returns {JSX.Element} + * @returns {ReturnType} * Element from your framework. - * - * @typedef {{children?: Array | Child, node?: Element | MdxJsxFlowElement | MdxJsxTextElement | undefined, [prop: string]: Array | Child | Element | MdxJsxFlowElement | MdxJsxTextElement | Value | undefined}} Props + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {{ + * children?: Array> | Child, node?: Element | MdxJsxFlowElement | MdxJsxTextElement | undefined, + * [prop: string]: Array> | Child | Element | MdxJsxFlowElement | MdxJsxTextElement | Value | undefined + * }} Props * Properties and children. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef RegularFields * Configuration. - * @property {Partial | null | undefined} [components] + * @property {Record>} [components] * Components to use (optional). - * @property {CreateEvaluater | null | undefined} [createEvaluater] + * @property {CreateEvaluater | null | undefined} [createEvaluater] * Create an evaluator that turns ESTree ASTs into values (optional). * @property {ElementAttributeNameCase | null | undefined} [elementAttributeNameCase='react'] * Specify casing to use for attribute names (default: `'react'`). @@ -154,46 +216,59 @@ * @property {boolean | null | undefined} [tableCellAlignToStyle=true] * Turn obsolete `align` props on `td` and `th` into CSS `style` props * (default: `true`). - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef RuntimeDevelopment * Runtime fields when development is on. - * @property {Fragment} Fragment + * @property {GetType} Fragment * Fragment. * @property {true} development * Whether to use `jsxDEV` (when on) or `jsx` and `jsxs` (when off). - * @property {Jsx | null | undefined} [jsx] + * @property {JsxFunction | null | undefined} [jsx] * Dynamic JSX (optional). - * @property {JsxDev} jsxDEV + * @property {JsxDev} jsxDEV * Development JSX. - * @property {Jsx | null | undefined} [jsxs] + * @property {JsxFunction | null | undefined} [jsxs] * Static JSX (optional). - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef RuntimeProduction * Runtime fields when development is off. - * @property {Fragment} Fragment + * @property {GetType} Fragment * Fragment. * @property {false | null | undefined} [development] * Whether to use `jsxDEV` (when on) or `jsx` and `jsxs` (when off) (optional). - * @property {Jsx} jsx + * @property {JsxFunction} jsx * Dynamic JSX. - * @property {JsxDev | null | undefined} [jsxDEV] - * Development JSX (optional). - * @property {Jsx} jsxs + * @property {JsxFunction} jsxs * Static JSX. - * + * @property {Record>} [components] + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef RuntimeUnknown * Runtime fields when development might be on or off. - * @property {Fragment} Fragment + * @property {GetType} Fragment * Fragment. * @property {boolean} development * Whether to use `jsxDEV` (when on) or `jsx` and `jsxs` (when off). - * @property {Jsx | null | undefined} [jsx] + * @property {JsxFunction | null | undefined} [jsx] * Dynamic JSX (optional). - * @property {JsxDev | null | undefined} [jsxDEV] + * @property {JsxDev | null | undefined} [jsxDEV] * Development JSX (optional). - * @property {Jsx | null | undefined} [jsxs] + * @property {JsxFunction | null | undefined} [jsxs] * Static JSX (optional). - * + */ + +/** * @typedef Source * Info about source. * @property {number | undefined} columnNumber @@ -202,7 +277,9 @@ * Name of source file. * @property {number | undefined} lineNumber * Line where thing starts (1-indexed). - * + */ + +/** * @typedef {'html' | 'svg'} Space * Namespace. * @@ -211,20 +288,24 @@ * > It does not support the features available in XML. * > Passing SVG might break but fragments of modern SVG should be fine. * > Use `xast` if you need to support SVG as XML. - * + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @typedef State * Info passed around. - * @property {unknown} Fragment + * @property {GetType} Fragment * Fragment symbol. * @property {Array} ancestors * Stack of parents. - * @property {Partial} components + * @property {Record>} components * Components to swap. - * @property {Create} create + * @property {Create} create * Create something in development or production. * @property {ElementAttributeNameCase} elementAttributeNameCase * Casing to use for attribute names. - * @property {Evaluater | undefined} evaluater + * @property {Evaluater | undefined} evaluater * Evaluator that turns ESTree ASTs into values. * @property {string | undefined} filePath * File path. @@ -240,28 +321,51 @@ * Casing to use for property names in `style` objects. * @property {boolean} tableCellAlignToStyle * Turn obsolete `align` props on `td` and `th` into CSS `style` props. - * + */ + +/** * @typedef {Record} Style * Style map. - * + */ + +/** * @typedef {'css' | 'dom'} StylePropertyNameCase * Casing to use for property names in `style` objects. * * CSS casing is for example `background-color` and `-webkit-line-clamp`. * DOM casing is for example `backgroundColor` and `WebkitLineClamp`. - * + */ + +/** * @typedef {Style | boolean | number | string} Value * Primitive property value and `Style` map. */ /** - * @typedef {RuntimeDevelopment & RegularFields} Development + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {RuntimeDevelopment & RegularFields} Development * Configuration (development). - * @typedef {Development | Production | Unknown} Options + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {Development | Production} Options * Configuration. - * @typedef {RegularFields & RuntimeProduction} Production + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {RegularFields & RuntimeProduction} Production * Configuration (production). - * @typedef {RegularFields & RuntimeUnknown} Unknown + */ + +/** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @typedef {RegularFields & RuntimeUnknown} Unknown * Configuration (production or development). */ @@ -304,11 +408,13 @@ const docs = 'https://github.com/syntax-tree/hast-util-to-jsx-runtime' * Transform a hast tree to preact, react, solid, svelte, vue, etc., * with an automatic JSX runtime. * + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @param {Nodes} tree * Tree to transform. - * @param {Options} options + * @param {Options} options * Configuration (required). - * @returns {JSX.Element} + * @returns {ReturnType} * JSX element. */ @@ -318,7 +424,7 @@ export function toJsxRuntime(tree, options) { } const filePath = options.filePath || undefined - /** @type {Create} */ + /** @type {Create} */ let create if (options.development) { @@ -341,7 +447,7 @@ export function toJsxRuntime(tree, options) { create = productionCreate(filePath, options.jsx, options.jsxs) } - /** @type {State} */ + /** @type {State} */ const state = { Fragment: options.Fragment, ancestors: [], @@ -377,13 +483,15 @@ export function toJsxRuntime(tree, options) { /** * Transform a node. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {Nodes} node * Current node. * @param {string | undefined} key * Key. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function one(state, node, key) { @@ -415,13 +523,15 @@ function one(state, node, key) { /** * Handle element. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {Element} node * Current node. * @param {string | undefined} key * Key. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function element(state, node, key) { @@ -458,11 +568,13 @@ function element(state, node, key) { /** * Handle MDX expression. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {MdxFlowExpression | MdxTextExpression} node * Current node. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function mdxExpression(state, node) { @@ -472,7 +584,7 @@ function mdxExpression(state, node) { assert(expression.type === 'ExpressionStatement') // Assume result is a child. - return /** @type {Child | undefined} */ ( + return /** @type {Child | undefined} */ ( state.evaluater.evaluateExpression(expression.expression) ) } @@ -483,17 +595,19 @@ function mdxExpression(state, node) { /** * Handle MDX ESM. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {MdxjsEsm} node * Current node. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function mdxEsm(state, node) { if (node.data && node.data.estree && state.evaluater) { // Assume result is a child. - return /** @type {Child | undefined} */ ( + return /** @type {Child | undefined} */ ( state.evaluater.evaluateProgram(node.data.estree) ) } @@ -504,13 +618,16 @@ function mdxEsm(state, node) { /** * Handle MDX JSX. * - * @param {State} state + * + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {MdxJsxFlowElement | MdxJsxTextElement} node * Current node. * @param {string | undefined} key * Key. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function mdxJsxElement(state, node, key) { @@ -544,17 +661,19 @@ function mdxJsxElement(state, node, key) { /** * Handle root. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {Root} node * Current node. * @param {string | undefined} key * Key. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function root(state, node, key) { - /** @type {Props} */ + /** @type {Props} */ const props = {} addChildren(props, createChildren(state, node)) @@ -565,11 +684,13 @@ function root(state, node, key) { /** * Handle text. * - * @param {State} _ + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} _ * Info passed around. * @param {Text} node * Current node. - * @returns {Child | undefined} + * @returns {Child | undefined} * Child, optional. */ function text(_, node) { @@ -579,9 +700,11 @@ function text(_, node) { /** * Add `node` to props. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. - * @param {Props} props + * @param {Props} props * Props. * @param {unknown} type * Type. @@ -600,9 +723,11 @@ function addNode(state, props, type, node) { /** * Add children to props. * - * @param {Props} props + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {Props} props * Props. - * @param {Array} children + * @param {Array>} children * Children. * @returns {undefined} * Nothing. @@ -618,40 +743,48 @@ function addChildren(props, children) { } /** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @param {string | undefined} _ * Path to file. - * @param {Jsx} jsx + * @param {JsxFunction} jsx * Dynamic. - * @param {Jsx} jsxs + * @param {JsxFunction} jsxs * Static. - * @returns {Create} + * @returns {Create} * Create a production element. */ function productionCreate(_, jsx, jsxs) { return create - /** @type {Create} */ + /** @type {Create} */ function create(_, type, props, key) { // Only an array when there are 2 or more children. - const isStaticChildren = Array.isArray(props.children) + const isStaticChildren = Array.isArray( + /** @type {Record} */ (props).children + ) const fn = isStaticChildren ? jsxs : jsx return key ? fn(type, props, key) : fn(type, props) } } /** + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. * @param {string | undefined} filePath * Path to file. - * @param {JsxDev} jsxDEV + * @param {JsxDev} jsxDEV * Development. - * @returns {Create} + * @returns {Create} * Create a development element. */ function developmentCreate(filePath, jsxDEV) { return create - /** @type {Create} */ + /** @type {Create} */ function create(node, type, props, key) { // Only an array when there are 2 or more children. - const isStaticChildren = Array.isArray(props.children) + const isStaticChildren = Array.isArray( + /** @type {Record} */ (props).children + ) const point = pointStart(node) return jsxDEV( type, @@ -671,15 +804,17 @@ function developmentCreate(filePath, jsxDEV) { /** * Create props from an element. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {Element} node * Current element. - * @returns {Props} + * @returns {Props} * Props. */ function createElementProps(state, node) { - /** @type {Props} */ + /** @type {Props} */ const props = {} /** @type {string | undefined} */ let alignValue @@ -720,15 +855,17 @@ function createElementProps(state, node) { /** * Create props from a JSX element. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {MdxJsxFlowElement | MdxJsxTextElement} node * Current JSX element. - * @returns {Props} + * @returns {Props} * Props. */ function createJsxElementProps(state, node) { - /** @type {Props} */ + /** @type {Props} */ const props = {} for (const attribute of node.attributes) { @@ -773,7 +910,8 @@ function createJsxElementProps(state, node) { } // Assume a prop. - props[name] = /** @type {Props[keyof Props]} */ (value) + props[name] = + /** @type {Props[keyof Props]} */ (value) } } @@ -783,15 +921,17 @@ function createJsxElementProps(state, node) { /** * Create children. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {Parents} node * Current element. - * @returns {Array} + * @returns {Array>} * Children. */ function createChildren(state, node) { - /** @type {Array} */ + /** @type {Array>} */ const children = [] let index = -1 /** @type {Map} */ @@ -830,7 +970,9 @@ function createChildren(state, node) { /** * Handle a property. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {string} prop * Key. @@ -880,7 +1022,9 @@ function createProperty(state, prop, value) { /** * Parse a CSS declaration to an object. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * Info passed around. * @param {string} value * CSS declarations. @@ -939,13 +1083,15 @@ function parseStyle(state, value) { /** * Create a JSX name from a string. * - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * To do. * @param {string} name * Name. * @param {boolean} allowExpression * Allow member expressions and identifiers. - * @returns {unknown} + * @returns {GetType} * To do. */ function findComponentFromName(state, name, allowExpression) { @@ -988,7 +1134,9 @@ function findComponentFromName(state, name, allowExpression) { // Only literals can be passed in `components` currently. // No identifiers / member expressions. if (result.type === 'Literal') { - const name = /** @type {keyof JSX.IntrinsicElements} */ (result.value) + const name = /** @type {Extract, string>} */ ( + result.value + ) return own.call(state.components, name) ? state.components[name] : name } @@ -1002,7 +1150,9 @@ function findComponentFromName(state, name, allowExpression) { } /** - * @param {State} state + * @template {Jsx} [JsxFunction=Jsx] + * The type of the `jsx` function impoted from `${jsxImportSource}/jsx-runtime`. + * @param {State} state * @param {Position | undefined} [place] * @returns {never} */ diff --git a/package.json b/package.json index 2c2d5e7..9a997e0 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "ignoreFiles": [ "example/**/*.js" ], + "ignoreNested": true, "strict": true }, "xo": { diff --git a/test/index.js b/test/index.js index a1844bd..ecec577 100644 --- a/test/index.js +++ b/test/index.js @@ -1,11 +1,8 @@ /** - * @typedef {import('estree').Expression} Expression * @typedef {import('estree').Program} Program + * @typedef {import('hast').Nodes} Nodes * - * @typedef {import('hast-util-to-jsx-runtime').CreateEvaluater} CreateEvaluater - * @typedef {import('hast-util-to-jsx-runtime').Fragment} Fragment - * @typedef {import('hast-util-to-jsx-runtime').Jsx} Jsx - * @typedef {import('hast-util-to-jsx-runtime').JsxDev} JsxDev + * @typedef {import('hast-util-to-jsx-runtime').CreateEvaluater} CreateEvaluater * * @typedef {import('../lib/index.js').Source} Source */ @@ -17,25 +14,14 @@ import {h, s} from 'hastscript' import {toJsxRuntime} from 'hast-util-to-jsx-runtime' import * as sval from 'sval' import React from 'react' -import * as dev from 'react/jsx-dev-runtime' -import * as prod from 'react/jsx-runtime' +import * as development from 'react/jsx-dev-runtime' +import * as production from 'react/jsx-runtime' import {renderToStaticMarkup} from 'react-dom/server' /** @type {import('sval')['default']} */ // @ts-expect-error: ESM types are wrong. const Sval = sval.default -const production = /** @type {{Fragment: Fragment, jsx: Jsx, jsxs: Jsx}} */ ({ - Fragment: prod.Fragment, - jsx: prod.jsx, - jsxs: prod.jsxs -}) - -const development = /** @type {{Fragment: Fragment, jsxDEV: JsxDev}} */ ({ - Fragment: dev.Fragment, - jsxDEV: dev.jsxDEV -}) - test('core', async function (t) { await t.test('should expose the public api', async function () { assert.deepEqual( @@ -91,6 +77,7 @@ test('core', async function (t) { 'should throw in development w/ `Fragment`, w/o `jsxDEV`', async function () { assert.throws(function () { + // @ts-expect-error: check how the development runtime handles `jsxDEV` missing. toJsxRuntime(h(), {Fragment: production.Fragment, development: true}) }, /Expected `jsxDEV` in options when `development: true`/) } @@ -264,6 +251,10 @@ test('properties', async function (t) { }), { ...production, + /** + * @param {React.ElementType} type + * @param {unknown} props + */ jsx(type, props) { foundProps = props return production.jsx(type, {}) @@ -491,7 +482,7 @@ test('source', async function (t) { }) /** - * @param {JSX.Element} node + * @param {React.ReactElement} node * @returns {Source | undefined} */ function getSource(node) { @@ -508,6 +499,9 @@ test('components', async function (t) { toJsxRuntime(h('b#x'), { ...production, components: { + /** + * @param {{id: string}} props + */ b(props) { // Note: types for this are working. assert(props.id === 'x') @@ -528,7 +522,7 @@ test('components', async function (t) { components: { b: class extends React.Component { /** - * @param {JSX.IntrinsicElements['b']} props + * @param {React.ComponentPropsWithoutRef<'b'>} props */ constructor(props) { super(props) @@ -556,6 +550,9 @@ test('components', async function (t) { ...production, passNode: true, components: { + /** + * @param {{ node: Nodes }} props + */ b(props) { assert.ok(props.node) return 'a' @@ -574,6 +571,9 @@ test('components', async function (t) { toJsxRuntime(h('b'), { ...production, components: { + /** + * @param {{ node: Nodes }} props + */ b(props) { assert.equal(props.node, undefined) return 'a' @@ -678,6 +678,10 @@ test('react specific: `align` to `style`', async function (t) { renderToStaticMarkup( toJsxRuntime(h('td', {align: 'center'}), { ...production, + /** + * @param {React.ElementType} type + * @param {unknown} props + */ jsx(type, props) { foundProps = props return production.jsx(type, {}) @@ -702,6 +706,10 @@ test('react specific: `align` to `style`', async function (t) { renderToStaticMarkup( toJsxRuntime(h('td', {align: 'center'}), { ...production, + /** + * @param {React.ElementType} type + * @param {unknown} props + */ jsx(type, props) { foundProps = props return production.jsx(type, {}) @@ -862,7 +870,6 @@ test('mdx: jsx', async function (t) { { ...production, components: { - // @ts-expect-error: untyped. 'a:b': 'b' } } @@ -1293,7 +1300,7 @@ function createEvaluater() { } interpreter.run(program) - const value = /** @type {unknown} */ ( + const value = /** @type {React.ElementType} */ ( // type-coverage:ignore-next-line interpreter.exports._evaluateExpressionValue ) diff --git a/tsconfig.json b/tsconfig.json index 4617360..29572a6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,5 @@ "strict": true, "target": "es2022" }, - "exclude": ["coverage/", "node_modules/"], - "include": ["**/**.js", "lib/components.d.ts", "types.d.ts"] + "exclude": ["coverage/", "node_modules/"] }