From ce173f28383281b99877d4e8e999c38997d8a49e Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Mon, 16 Oct 2023 13:11:59 +0200 Subject: [PATCH] Refactor to add types for JSX runtimes --- package.json | 5 - .../mdx/lib/util/resolve-evaluate-options.js | 111 ++++++++++++++++-- packages/mdx/test/evaluate.js | 9 +- packages/preact/test/index.jsx | 8 +- packages/react/test/index.jsx | 10 +- 5 files changed, 121 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 64f707087..b4eab86ae 100644 --- a/package.json +++ b/package.json @@ -169,11 +169,6 @@ "atLeast": 100, "detail": true, "ignoreCatch": true, - "#": "needed `any`s; to do: can they be typed, liked `hast-util-to-jsx-runtime`?", - "ignoreFiles": [ - "packages/mdx/lib/util/resolve-evaluate-options.d.ts", - "packages/mdx/lib/util/resolve-evaluate-options.js" - ], "strict": true }, "xo": { diff --git a/packages/mdx/lib/util/resolve-evaluate-options.js b/packages/mdx/lib/util/resolve-evaluate-options.js index 355cf7efd..501d16c4f 100644 --- a/packages/mdx/lib/util/resolve-evaluate-options.js +++ b/packages/mdx/lib/util/resolve-evaluate-options.js @@ -1,24 +1,117 @@ /** + * @typedef {import('mdx/types.js').MDXComponents} Components * @typedef {import('../core.js').ProcessorOptions} ProcessorOptions + */ + +/** + * @typedef {JSX.Element | string | null | undefined} Child + * Child. + * + * @typedef {EvaluateProcessorOptions & RunnerOptions} EvaluateOptions + * Configuration for evaluation. + * + * @typedef {Omit } EvaluateProcessorOptions + * Compile configuration without JSX options for evaluation. + * + * @typedef {unknown} Fragment + * Represent the children, typically a symbol. + * + * @callback Jsx + * Create a production element. + * @param {unknown} type + * Element type: `Fragment` symbol, tag name (`string`), component. + * @param {Props} props + * Element props, `children`, and maybe `node`. + * @param {string | undefined} [key] + * Dynamicly generated key to use. + * @returns {JSX.Element} + * An element from your framework. + * + * @callback JsxDev + * Create a development element. + * @param {unknown} type + * Element type: `Fragment` symbol, tag name (`string`), component. + * @param {Props} props + * Element props, `children`, and maybe `node`. + * @param {string | 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 + * Info about source. + * @param {undefined} self + * Nothing (this is used by frameworks that have components, we don’t). + * @returns {JSX.Element} + * An element from your framework. + * + * @callback MergeComponents + * Custom merge function. + * @param {Components} currentComponents + * Current components from the context. + * @returns {Components} + * Merged components. + * + * @typedef {{children?: Array | Child, node?: Element | undefined, [prop: string]: Array | Child | Element | Value | undefined}} Props + * Properties and children. * * @typedef RunnerOptions * Configuration with JSX runtime. - * @property {any} Fragment + * @property {Fragment} Fragment * Symbol to use for fragments. - * @property {any} [jsx] + * @property {Jsx | null | undefined} [jsx] * Function to generate an element with static children in production mode. - * @property {any} [jsxs] + * @property {Jsx | null | undefined} [jsxs] * Function to generate an element with dynamic children in production mode. - * @property {any} [jsxDEV] + * @property {JsxDev | null | undefined} [jsxDEV] * Function to generate an element in development mode. - * @property {any} [useMDXComponents] + * @property {UseMdxComponents | null | undefined} [useMDXComponents] * Function to get `MDXComponents` from context. * - * @typedef {Omit } EvaluateProcessorOptions - * Compile configuration without JSX options for evaluation. + * @typedef RuntimeDevelopment + * Runtime fields when development is on. + * @property {Fragment} Fragment + * Fragment. + * @property {Jsx | null | undefined} [jsx] + * Dynamic JSX (optional). + * @property {JsxDev} jsxDEV + * Development JSX. + * @property {Jsx | null | undefined} [jsxs] + * Static JSX (optional). * - * @typedef {EvaluateProcessorOptions & RunnerOptions} EvaluateOptions - * Configuration for evaluation. + * @typedef RuntimeProduction + * Runtime fields when development is off. + * @property {Fragment} Fragment + * Fragment. + * @property {Jsx} jsx + * Dynamic JSX. + * @property {JsxDev | null | undefined} [jsxDEV] + * Development JSX (optional). + * @property {Jsx} jsxs + * Static JSX. + * + * @typedef Source + * Info about source. + * @property {number | undefined} columnNumber + * Column where thing starts (0-indexed). + * @property {string | undefined} fileName + * Name of source file. + * @property {number | undefined} lineNumber + * Line where thing starts (1-indexed). + * + * @typedef {Record} Style + * Style map. + * + * @callback UseMdxComponents + * Get current components from the MDX Context. + * @param {Components | MergeComponents | null | undefined} [components] + * Additional components to use or a function that takes the current + * components and filters/merges/changes them. + * @returns {Components} + * Current components. + * + * @typedef {Style | boolean | number | string} Value + * Primitive property value and `Style` map. */ /** diff --git a/packages/mdx/test/evaluate.js b/packages/mdx/test/evaluate.js index c7ecbec86..aa8e36e1a 100644 --- a/packages/mdx/test/evaluate.js +++ b/packages/mdx/test/evaluate.js @@ -1,3 +1,8 @@ +/** + * @typedef {import('../lib/util/resolve-evaluate-options.js').RuntimeDevelopment} RuntimeDevelopment + * @typedef {import('../lib/util/resolve-evaluate-options.js').RuntimeProduction} RuntimeProduction + */ + import assert from 'node:assert/strict' import {test} from 'node:test' import {renderToStaticMarkup} from 'react-dom/server' @@ -7,10 +12,10 @@ import React from 'react' import * as provider from '../../react/index.js' import {evaluate, evaluateSync, compile} from '../index.js' -/** @type {{Fragment: unknown, jsx: unknown, jsxs: unknown}} */ +/** @type {RuntimeProduction} */ // @ts-expect-error: types are wrong. const runtime = runtime_ -/** @type {{Fragment: unknown, jsxDEV: unknown}} */ +/** @type {RuntimeDevelopment} */ // @ts-expect-error: types are wrong. const devRuntime = devRuntime_ diff --git a/packages/preact/test/index.jsx b/packages/preact/test/index.jsx index 4b1f30f55..8596736f7 100644 --- a/packages/preact/test/index.jsx +++ b/packages/preact/test/index.jsx @@ -1,12 +1,18 @@ /* @jsxRuntime automatic @jsxImportSource preact */ +/** + * @typedef {import('@mdx-js/mdx/lib/util/resolve-evaluate-options.js').RuntimeProduction} RuntimeProduction + */ + import assert from 'node:assert/strict' import {test} from 'node:test' -import * as runtime from 'preact/jsx-runtime' +import * as runtime_ from 'preact/jsx-runtime' import {render} from 'preact-render-to-string' import {evaluate} from '@mdx-js/mdx' import {MDXProvider, useMDXComponents, withMDXComponents} from '../index.js' +const runtime = /** @type {RuntimeProduction} */ (runtime_) + test('should support `components` with `MDXProvider`', async () => { const {default: Content} = await evaluate('# hi', { ...runtime, diff --git a/packages/react/test/index.jsx b/packages/react/test/index.jsx index 69b14da7b..b8537588a 100644 --- a/packages/react/test/index.jsx +++ b/packages/react/test/index.jsx @@ -1,18 +1,18 @@ /** - * @typedef {import('react').ReactNode} ReactNode + * @typedef {import('@mdx-js/mdx/lib/util/resolve-evaluate-options.js').RuntimeProduction} RuntimeProduction */ import assert from 'node:assert/strict' import {test} from 'node:test' import {evaluate} from '@mdx-js/mdx' import React from 'react' -import * as runtimeRaw from 'react/jsx-runtime' +import * as runtime_ from 'react/jsx-runtime' import {renderToString} from 'react-dom/server' import {MDXProvider, useMDXComponents, withMDXComponents} from '../index.js' -/** @type {{Fragment: unknown, jsx: unknown, jsxs: unknown}} */ -// @ts-expect-error: React types are wrong. -const runtime = runtimeRaw +const runtime = /** @type {RuntimeProduction} */ ( + /** @type {unknown} */ (runtime_) +) test('should support `components` with `MDXProvider`', async () => { const {default: Content} = await evaluate('# hi', {