Skip to content

Commit

Permalink
Refactor to add types for JSX runtimes
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Oct 16, 2023
1 parent e9a307b commit ce173f2
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 22 deletions.
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
111 changes: 102 additions & 9 deletions packages/mdx/lib/util/resolve-evaluate-options.js
Original file line number Diff line number Diff line change
@@ -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<ProcessorOptions, 'jsx' | 'jsxImportSource' | 'jsxRuntime' | 'pragma' | 'pragmaFrag' | 'pragmaImportSource' | 'providerImportSource' | 'outputFormat'> } 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> | Child, node?: Element | undefined, [prop: string]: Array<Child> | 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<ProcessorOptions, 'jsx' | 'jsxImportSource' | 'jsxRuntime' | 'pragma' | 'pragmaFrag' | 'pragmaImportSource' | 'providerImportSource' | 'outputFormat'> } 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<string, string>} 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.
*/

/**
Expand Down
9 changes: 7 additions & 2 deletions packages/mdx/test/evaluate.js
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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_

Expand Down
8 changes: 7 additions & 1 deletion packages/preact/test/index.jsx
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
10 changes: 5 additions & 5 deletions packages/react/test/index.jsx
Original file line number Diff line number Diff line change
@@ -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', {
Expand Down

0 comments on commit ce173f2

Please sign in to comment.