Skip to content

Commit

Permalink
Add descriptions to types
Browse files Browse the repository at this point in the history
Closes GH-5.
  • Loading branch information
wooorm authored Feb 13, 2021
1 parent f43715f commit e4c2340
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 42 deletions.
25 changes: 16 additions & 9 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@ import {remarkMdx} from './remark-mdx.js'
* @typedef {import("./recma-jsx-rewrite").RecmaJsxRewriteOptions} RecmaJsxRewriteOptions
*
* @typedef BaseProcessorOptions
* @property {boolean} [jsx]
* @property {PluggableList} [recmaPlugins]
* @property {PluggableList} [remarkPlugins]
* @property {PluggableList} [rehypePlugins]
* @property {boolean} [_contain]
* @property {boolean} [jsx=false] Whether to keep JSX
* @property {PluggableList} [recmaPlugins] List of recma (esast, JavaScript) plugins
* @property {PluggableList} [remarkPlugins] List of remark (mdast, markdown) plugins
* @property {PluggableList} [rehypePlugins] List of rehype (hast, HTML) plugins
* @property {boolean} [_contain=false] Semihidden option
*
* @typedef {Omit<RecmaDocumentOptions & RecmaStringifyOptions & RecmaJsxRewriteOptions & BaseProcessorOptions, "contain"> } ProcessorOptions
*/

/**
* Compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]
* @return {Promise<VFile>}
*/
Expand All @@ -39,8 +40,9 @@ export function compile(file, options) {
}

/**
* Synchronously compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]
* @return {VFile}
*/
Expand All @@ -49,6 +51,11 @@ export function compileSync(file, options) {
}

/**
* Pipeline to:
*
* 1. Parse MDX (serialized markdown with embedded JSX, ESM, and expressions)
* 2. Transform through remark (mdast), rehype (hast), and recma (esast)
* 3. Serialize as JavaScript
*
* @param {ProcessorOptions} [options]
* @return {Processor}
Expand Down Expand Up @@ -85,9 +92,9 @@ function createProcessor(options = {}) {
.use(rehypePlugins)
.use(rehypeRecma)
.use(recmaDocument, {...otherOptions, contain})
// @ts-ignore recma transformer uses an estree node rather than a unist node
// @ts-ignore recma transformer uses an esast node rather than a unist node
.use(recmaJsxRewrite, {providerImportSource, contain})
// @ts-ignore recma transformer uses an estree node rather than a unist node
// @ts-ignore recma transformer uses an esast node rather than a unist node
.use(jsx ? undefined : recmaJsxBuild, {contain})
// @ts-ignore recma compiler is seen as a transformer
.use(recmaStringify, {SourceMapGenerator})
Expand Down
26 changes: 14 additions & 12 deletions lib/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {compile, compileSync} from './core.js'
* @typedef {import('./core.js').BaseProcessorOptions} BaseProcessorOptions
*
* @typedef RunnerOptions
* @property {*} [Fragment]
* @property {*} [jsx]
* @property {*} [jsxs]
* @property {*} [useMDXComponents]
* @property {*} Fragment Symbol to use for fragments
* @property {*} jsx Function to generate an element with static children
* @property {*} jsxs Function to generate an element with dynamic children
* @property {*} [useMDXComponents] Function to get `MDXComponents` from context
*
* @typedef {Omit<BaseProcessorOptions, "jsx" | "_contain"> } ProcessorOptions
* @typedef {ProcessorOptions & RunnerOptions} ProcessorAndRunnerOptions
Expand All @@ -19,9 +19,10 @@ import {compile, compileSync} from './core.js'
*/

/**
* Evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {Promise<ExportMap>}
*/
export async function evaluate(file, options) {
Expand All @@ -33,9 +34,10 @@ export async function evaluate(file, options) {
}

/**
* Synchronously evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {ExportMap}
*/
export function evaluateSync(file, options) {
Expand All @@ -44,11 +46,11 @@ export function evaluateSync(file, options) {
}

/**
* Split processor/compiler options from runner options
* Split processor/compiler options from runner options.
*
* @param {ProcessorAndRunnerOptions} [options]
* @param {ProcessorAndRunnerOptions} options
*/
function split(options = {}) {
function split(options) {
var {
Fragment,
jsx,
Expand All @@ -57,7 +59,7 @@ function split(options = {}) {
rehypePlugins,
remarkPlugins,
useMDXComponents
} = options
} = options || {}

if (!Fragment) throw new Error('Expected `Fragment` given to `evaluate`')
if (!jsx) throw new Error('Expected `jsx` given to `evaluate`')
Expand Down
13 changes: 7 additions & 6 deletions lib/recma-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import {create} from './util/estree-util-create.js'

/**
* @typedef RecmaDocumentOptions
* @property {boolean} contain
* @property {string} [pragma]
* @property {string} [pragmaFrag]
* @property {string} [pragmaImportSource]
* @property {string} [jsxImportSource]
* @property {'automatic' | 'classic'} [jsxRuntime]
* @property {boolean} [contain] Semihidden option which here results in failing on imports and adding a top-level return statement instead of an export.
* @property {string} [pragma='React.createElement'] Pragma for JSX (used in classic runtime)
* @property {string} [pragmaFrag='React.Fragment'] Pragma for JSX fragments (used in classic runtime)
* @property {string} [pragmaImportSource='react'] Where to import the identifier of `pragma` from (used in classic runtime)
* @property {string} [jsxImportSource='react'] Place to import automatic JSX runtimes from (used in automatic runtime)
* @property {'automatic' | 'classic'} [jsxRuntime='automatic'] JSX runtime to use
*/

/**
* A plugin to wrap the estree in `MDXContent`.
*
* @param {RecmaDocumentOptions} [options]
*/
export function recmaDocument(options) {
Expand Down
11 changes: 8 additions & 3 deletions lib/recma-jsx-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import u from 'unist-builder'
* @typedef {import("estree").Program} Program
*
* @typedef RecmaJsxBuildOptions
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting the automatic runtime from `arguments[0]` instead of importing it
*/

/**
Expand All @@ -18,15 +18,20 @@ export function recmaJsxBuild({contain}) {
return transform

/**
*
* @param {Program} tree
*/
function transform(tree) {
build(tree)

// In contain mode, replace the import that was just generated, and get
// `jsx`, `jsxs`, and `Fragment` from `arguments[0]` instead.
if (contain && tree.body[0] && tree.body[0].type === 'ImportDeclaration') {
if (
contain &&
tree.body[0] &&
tree.body[0].type === 'ImportDeclaration' &&
typeof tree.body[0].source.value === 'string' &&
/\/jsx-runtime$/.test(tree.body[0].source.value)
) {
// @ts-ignore assume this is not missing properties
tree.body[0] = u('VariableDeclaration', {
kind: 'const',
Expand Down
5 changes: 2 additions & 3 deletions lib/recma-jsx-rewrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import u from 'unist-builder'
* @typedef {import("estree").Program} Program
*
* @typedef RecmaJsxRewriteOptions
* @property {string} [providerImportSource]
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting `useMDXComponents` from `arguments[0]` instead of importing it
* @property {string} [providerImportSource] Place to import a provider from
*/

/**
Expand All @@ -24,7 +24,6 @@ export function recmaJsxRewrite({providerImportSource, contain} = {}) {
return transform

/**
*
* @param {Program} tree
*/
function transform(tree) {
Expand Down
8 changes: 4 additions & 4 deletions lib/recma-stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import stringifyEntities from 'stringify-entities/light.js'
* @typedef {typeof import("source-map").SourceMapGenerator} SourceMapGenerator
*
* @typedef RecmaStringifyOptions
* @property {SourceMapGenerator} [SourceMapGenerator]
* @property {SourceMapGenerator} [SourceMapGenerator] Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/

/**
* A small wrapper around `astring` to add support for serializing JSX.
* A plugin that adds an esast compiler: a small wrapper around `astring` to add
* support for serializing JSX.
*
* @param {RecmaStringifyOptions} [options]
*/
Expand All @@ -22,7 +23,6 @@ export function recmaStringify(options) {
this.Compiler = compiler

/**
*
* @param {Program} tree
* @param {VFile} file
* @return {string}
Expand Down Expand Up @@ -189,7 +189,7 @@ function JSXSpreadAttribute(node, state) {
// But we always compile to expressions instead (`{"1"}`).
/* c8 ignore next 6 */
function JSXText(node, state) {
// `raw` is currently always be set, but could be missing if something injects
// `raw` is currently always set, but could be missing if something injects
// a `JSXText` into the tree.
// Preferring `raw` over `value` means character references are kept as-is.
state.write(node.raw || node.value, node)
Expand Down
1 change: 0 additions & 1 deletion lib/rehype-mark-and-unravel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export function rehypeMarkAndUnravel() {
}

/**
*
* @param {Node} tree
* @return {void}
*/
Expand Down
1 change: 1 addition & 0 deletions lib/webpack-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {compile} from './core.js'
* See `webpack.cjs`, which wraps this, because Webpack loaders must currently
* be CommonJS.
* `file.map` is defined when a `SourceMapGenerator` is passed in options.
*
* @param {string} value
* @param {*} callback
*/
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ compile(file, {jsxRuntime: 'classic'})

###### `options.jsxImportSource`

Place to import automatic JSX runtimes from (`string?`, default: `react`).
Place to import automatic JSX runtimes from (`string?`, default: `'react'`).
When in the `automatic` runtime, this is used to define an import for
`_Fragment`, `_jsx`, and `_jsxs`.

Expand Down
20 changes: 17 additions & 3 deletions test/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {evaluate, evaluateSync} from '../index.js'
test('xdm (evaluate)', async function (t) {
t.throws(
function () {
// @ts-expect-error
evaluateSync('a')
},
/Expected `Fragment` given to `evaluate`/,
Expand All @@ -16,7 +17,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
// @ts-expect-error
evaluateSync('a', {Fragment: runtime.Fragment})
},
/Expected `jsx` given to `evaluate`/,
Expand All @@ -25,7 +26,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
// @ts-expect-error
evaluateSync('a', {Fragment: runtime.Fragment, jsx: runtime.jsx})
},
/Expected `jsxs` given to `evaluate`/,
Expand All @@ -34,6 +35,7 @@ test('xdm (evaluate)', async function (t) {

t.equal(
renderToStaticMarkup(
// @ts-ignore runtime.js does not have a typing
React.createElement((await evaluate('# hi!', runtime)).default)
),
'<h1>hi!</h1>',
Expand All @@ -42,12 +44,14 @@ test('xdm (evaluate)', async function (t) {

t.equal(
renderToStaticMarkup(
// @ts-ignore runtime.js does not have a typing
React.createElement(evaluateSync('# hi!', runtime).default)
),
'<h1>hi!</h1>',
'should evaluate (sync)'
)

// @ts-ignore runtime.js does not have a typing
var mod = await evaluate('export const a = 1\n\n{a}', runtime)

t.equal(
Expand All @@ -58,6 +62,7 @@ test('xdm (evaluate)', async function (t) {

t.equal(mod.a, 1, 'should support an `export` (2)')

// @ts-ignore runtime.js does not have a typing
mod = await evaluate('export function a() { return 1 }\n\n{a()}', runtime)

t.equal(
Expand All @@ -72,6 +77,7 @@ test('xdm (evaluate)', async function (t) {

mod = await evaluate(
'export class A { constructor() { this.b = 1 } }\n\n{new A().b}',
// @ts-ignore runtime.js does not have a typing
runtime
)

Expand All @@ -84,6 +90,7 @@ test('xdm (evaluate)', async function (t) {
// @ts-ignore TODO figure out how to narrow class type in JSDoc typescript
t.equal(new mod.A().b, 1, 'should support an `export class` (2)')

// @ts-ignore runtime.js does not have a typing
mod = await evaluate('export const a = 1\nexport {a as b}\n\n{a}', runtime)

t.equal(
Expand All @@ -101,6 +108,7 @@ test('xdm (evaluate)', async function (t) {
(
await evaluate(
'export default function Layout({components, ...props}) { return <section {...props} /> }\n\na',
// @ts-ignore runtime.js does not have a typing
runtime
)
).default
Expand All @@ -112,6 +120,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
evaluateSync('export {a} from "b"', runtime)
},
/Cannot use `export from` in contained MDX/,
Expand All @@ -120,6 +129,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
evaluateSync('export * from "a"', runtime)
},
/Cannot use `export \* from` in contained MDX/,
Expand All @@ -128,6 +138,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
evaluateSync('import {a} from "b"', runtime)
},
/Cannot use `import` in contained MDX/,
Expand All @@ -136,6 +147,7 @@ test('xdm (evaluate)', async function (t) {

t.throws(
function () {
// @ts-ignore runtime.js does not have a typing
evaluateSync('import a from "b"', runtime)
},
/Cannot use `import` in contained MDX/,
Expand All @@ -144,7 +156,8 @@ test('xdm (evaluate)', async function (t) {

t.equal(
renderToStaticMarkup(
React.createElement((await evaluate('<X/>', {...runtime})).default, {
// @ts-ignore runtime.js does not have a typing
React.createElement((await evaluate('<X/>', runtime)).default, {
components: {
X() {
return React.createElement('span', {}, '!')
Expand All @@ -168,6 +181,7 @@ test('xdm (evaluate)', async function (t) {
}
},
React.createElement(
// @ts-ignore runtime.js does not have a typing
(await evaluate('<X/>', {...runtime, ...provider})).default
)
)
Expand Down

0 comments on commit e4c2340

Please sign in to comment.