From facc3b4a070170e45d26bb7d14081bc6550cc07a Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Fri, 5 Apr 2024 15:02:28 +0200 Subject: [PATCH] Fix the JSX runtime types in RunOptions `@types/react` now has types for `react/jsx-runtime` and `react/jsx-dev-runtime`. These types are not compatible with the types provided by `hast-util-to-jsx-runtime`, which are used by MDX. To resolve the issue, all runtime related options have been changed to `unknown`. Since the user is supposed to pass in whatever JSX runtime they imported, this should be sufficient. This fixes several type errors. An outdated workaround has been removed from the documentation. Closes #2463 --- docs/_asset/editor.jsx | 2 -- docs/migrating/v3.mdx | 11 ++-------- package-lock.json | 4 +++- packages/mdx/index.js | 6 ++--- .../mdx/lib/util/resolve-evaluate-options.js | 22 ++++++++++++++++++- packages/mdx/package.json | 1 - packages/mdx/test/evaluate.js | 15 ++----------- packages/preact/test/index.jsx | 7 +----- packages/react/test/index.jsx | 7 +----- packages/vue/test/index.js | 7 +----- 10 files changed, 34 insertions(+), 48 deletions(-) diff --git a/docs/_asset/editor.jsx b/docs/_asset/editor.jsx index 8b3af61ef..8f0939d08 100644 --- a/docs/_asset/editor.jsx +++ b/docs/_asset/editor.jsx @@ -204,9 +204,7 @@ function Playground() { /** @type {MDXModule} */ const result = await run(String(file), { Fragment, - // @ts-expect-error: to do: fix in `hast-util-to-jsx-runtime`. jsx, - // @ts-expect-error: to do: fix in `hast-util-to-jsx-runtime`. jsxs, baseUrl: window.location.href }) diff --git a/docs/migrating/v3.mdx b/docs/migrating/v3.mdx index 724d0e66c..3ebbe1a97 100644 --- a/docs/migrating/v3.mdx +++ b/docs/migrating/v3.mdx @@ -52,16 +52,9 @@ You will get a runtime error if these features are used in MDX without If you passed the `useDynamicImport` option before, remove it, the behavior is now the default. -If you use `react/jsx-runtime`, you might get a TypeScript error (such as -`Property 'Fragment' is missing in type`), because it is typed incorrectly. -To remediate this, do: - ```tsx -import {type Fragment, type Jsx, run} from '@mdx-js/mdx' -import * as runtime_ from 'react/jsx-runtime' - -// @ts-expect-error: the automatic react runtime is untyped. -const runtime: {Fragment: Fragment; jsx: Jsx; jsxs: Jsx} = runtime_ +import {run} from '@mdx-js/mdx' +import * as runtime from 'react/jsx-runtime' const result = await run('# hi', {...runtime, baseUrl: import.meta.url}) ``` diff --git a/package-lock.json b/package-lock.json index 3bb3bed0f..22fb5d67f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7776,6 +7776,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -7803,12 +7804,14 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "dev": true, "license": "MIT" }, "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dev": true, "license": "MIT", "dependencies": { "inline-style-parser": "0.2.3" @@ -19881,7 +19884,6 @@ "estree-util-to-js": "^2.0.0", "estree-walker": "^3.0.0", "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "periscopic": "^3.0.0", "remark-mdx": "^3.0.0", diff --git a/packages/mdx/index.js b/packages/mdx/index.js index e70cea125..d4534570d 100644 --- a/packages/mdx/index.js +++ b/packages/mdx/index.js @@ -1,7 +1,7 @@ /** - * @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('./lib/util/resolve-evaluate-options.js').Fragment} Fragment + * @typedef {import('./lib/util/resolve-evaluate-options.js').Jsx} Jsx + * @typedef {import('./lib/util/resolve-evaluate-options.js').JsxDev} JsxDev * @typedef {import('./lib/util/resolve-evaluate-options.js').UseMdxComponents} UseMdxComponents * @typedef {import('./lib/compile.js').CompileOptions} CompileOptions * @typedef {import('./lib/core.js').ProcessorOptions} ProcessorOptions diff --git a/packages/mdx/lib/util/resolve-evaluate-options.js b/packages/mdx/lib/util/resolve-evaluate-options.js index 0b9a05b84..41c58e404 100644 --- a/packages/mdx/lib/util/resolve-evaluate-options.js +++ b/packages/mdx/lib/util/resolve-evaluate-options.js @@ -1,9 +1,29 @@ /** - * @import {Fragment, Jsx, JsxDev} from 'hast-util-to-jsx-runtime' * @import {MDXComponents} from 'mdx/types.js' * @import {CompileOptions} from '../compile.js' */ +/** + * @typedef {unknown} Fragment + */ + +/** + * @callback Jsx + * @param {any} type + * @param {object} props + * @param {any} [key] + */ + +/** + * @callback JsxDev + * @param {any} type + * @param {object} props + * @param {any} key + * @param {boolean} isStatic + * @param {object} [source] + * @param {object} [self] + */ + /** * @typedef {EvaluateProcessorOptions & RunOptions} EvaluateOptions * Configuration for `evaluate`. diff --git a/packages/mdx/package.json b/packages/mdx/package.json index 290fc84a5..2a73acc2f 100644 --- a/packages/mdx/package.json +++ b/packages/mdx/package.json @@ -54,7 +54,6 @@ "estree-util-to-js": "^2.0.0", "estree-walker": "^3.0.0", "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "periscopic": "^3.0.0", "remark-mdx": "^3.0.0", diff --git a/packages/mdx/test/evaluate.js b/packages/mdx/test/evaluate.js index 52b804313..691f1f892 100644 --- a/packages/mdx/test/evaluate.js +++ b/packages/mdx/test/evaluate.js @@ -1,23 +1,12 @@ -/** - * @import {Fragment, Jsx, JsxDev} from '@mdx-js/mdx' - */ - import assert from 'node:assert/strict' import {test} from 'node:test' import {evaluate, evaluateSync, compile} from '@mdx-js/mdx' import * as provider from '@mdx-js/react' import {renderToStaticMarkup} from 'react-dom/server' -import * as runtime_ from 'react/jsx-runtime' -import * as devRuntime_ from 'react/jsx-dev-runtime' +import * as runtime from 'react/jsx-runtime' +import * as developmentRuntime from 'react/jsx-dev-runtime' import React from 'react' -/** @type {{Fragment: Fragment, jsx: Jsx, jsxs: Jsx}} */ -// @ts-expect-error: the automatic react runtime is untyped. -const runtime = runtime_ -/** @type {{Fragment: Fragment, jsxDEV: JsxDev}} */ -// @ts-expect-error: the automatic dev react runtime is untyped. -const developmentRuntime = devRuntime_ - test('@mdx-js/mdx: evaluate', async function (t) { await t.test('should throw on missing `Fragment`', async function () { try { diff --git a/packages/preact/test/index.jsx b/packages/preact/test/index.jsx index c7e7760e4..0de28e625 100644 --- a/packages/preact/test/index.jsx +++ b/packages/preact/test/index.jsx @@ -2,7 +2,6 @@ /* @jsxImportSource preact */ /** - * @import {Fragment, Jsx} from '@mdx-js/mdx' * @import {ComponentProps} from 'preact' */ @@ -10,13 +9,9 @@ import assert from 'node:assert/strict' import {test} from 'node:test' import {evaluate} from '@mdx-js/mdx' import {MDXProvider, useMDXComponents} from '@mdx-js/preact' -import * as runtime_ from 'preact/jsx-runtime' +import * as runtime from 'preact/jsx-runtime' import {render} from 'preact-render-to-string' -const runtime = /** @type {{Fragment: Fragment, jsx: Jsx, jsxs: Jsx}} */ ( - runtime_ -) - test('@mdx-js/preact', async function (t) { await t.test('should expose the public api', async function () { assert.deepEqual(Object.keys(await import('@mdx-js/preact')).sort(), [ diff --git a/packages/react/test/index.jsx b/packages/react/test/index.jsx index fa67f0148..683034a4e 100644 --- a/packages/react/test/index.jsx +++ b/packages/react/test/index.jsx @@ -1,5 +1,4 @@ /** - * @import {Fragment, Jsx} from '@mdx-js/mdx' * @import {ComponentProps} from 'react' */ @@ -8,13 +7,9 @@ import {test} from 'node:test' import {evaluate} from '@mdx-js/mdx' import {MDXProvider, useMDXComponents} from '@mdx-js/react' import React from 'react' -import * as runtime_ from 'react/jsx-runtime' +import * as runtime from 'react/jsx-runtime' import {renderToString} from 'react-dom/server' -const runtime = /** @type {{Fragment: Fragment, jsx: Jsx, jsxs: Jsx}} */ ( - /** @type {unknown} */ (runtime_) -) - test('@mdx-js/react', async function (t) { await t.test('should expose the public api', async function () { assert.deepEqual(Object.keys(await import('@mdx-js/preact')).sort(), [ diff --git a/packages/vue/test/index.js b/packages/vue/test/index.js index 3a6bbdfde..3feea4683 100644 --- a/packages/vue/test/index.js +++ b/packages/vue/test/index.js @@ -1,5 +1,4 @@ /** - * @import {Fragment, Jsx} from '@mdx-js/mdx' * @import {MDXModule} from 'mdx/types.js' * @import {Component} from 'vue' */ @@ -8,13 +7,9 @@ import assert from 'node:assert/strict' import test from 'node:test' import {compile, run} from '@mdx-js/mdx' import {MDXProvider, useMDXComponents} from '@mdx-js/vue' -import * as runtime_ from 'vue/jsx-runtime' +import * as runtime from 'vue/jsx-runtime' import * as vue from 'vue' -const runtime = /** @type {{Fragment: Fragment, jsx: Jsx, jsxs: Jsx}} */ ( - /** @type {unknown} */ (runtime_) -) - // Note: a regular import would be nice but that completely messes up the JSX types. const name = '@vue/server-renderer' /** @type {{default: {renderToString(node: unknown): string}}} */