Skip to content

Commit ac09c72

Browse files
committed
Add improved docs
1 parent ead7356 commit ac09c72

File tree

2 files changed

+93
-57
lines changed

2 files changed

+93
-57
lines changed

lib/index.js

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier
1515
*
1616
* @typedef {'automatic' | 'classic'} Runtime
17+
* How to transform JSX.
1718
*
1819
* @typedef Options
1920
* Configuration.
@@ -25,7 +26,7 @@
2526
*
2627
* Comment form: `@jsxRuntime theRuntime`.
2728
* @property {string | null | undefined} [importSource='react']
28-
* Place to import `jsx`, `jsxs`, `jsxDEV`, and/or `Fragment` from, when the
29+
* Place to import `jsx`, `jsxs`, `jsxDEV`, and `Fragment` from, when the
2930
* effective runtime is automatic.
3031
*
3132
* Comment form: `@jsxImportSource theSource`.
@@ -54,16 +55,16 @@
5455
*
5556
* Comment form: `@jsxFrag identifier`.
5657
* @property {boolean | null | undefined} [development=false]
57-
* Import `jsxDEV` from `theSource/jsx-dev-runtime.js` and add location info
58-
* on where a component originated from.
58+
* When in the automatic runtime, whether to import
59+
* `theSource/jsx-dev-runtime.js`, use `jsxDEV`, and pass location info when
60+
* available.
5961
*
6062
* This helps debugging but adds a lot of code that you don’t want in
6163
* production.
62-
* Only used in the automatic runtime.
6364
* @property {string | null | undefined} [filePath]
6465
* File path to the original source file.
6566
*
66-
* Used in the location info when using the automatic runtime with
67+
* Passed in location info to `jsxDEV` when using the automatic runtime with
6768
* `development: true`.
6869
*
6970
* @typedef Annotations
@@ -97,18 +98,32 @@ const regex = /@(jsx|jsxFrag|jsxImportSource|jsxRuntime)\s+(\S+)/g
9798
/**
9899
* Turn JSX in `tree` into function calls: `<x />` -> `h('x')`!
99100
*
101+
* ###### Algorithm
102+
*
103+
* In almost all cases, this utility is the same as the Babel plugin, except that
104+
* they work on slightly different syntax trees.
105+
*
106+
* Some differences:
107+
*
108+
* * no pure annotations things
109+
* * `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
110+
* * namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
111+
* which throws by default in Babel or can be turned on with `throwIfNamespace`
112+
* * no `useSpread`, `useBuiltIns`, or `filter` options
113+
*
100114
* @template {Node} Tree
101115
* Node type.
102116
* @param {Tree} tree
103-
* Tree to transform.
104-
* @param {Options} [options={}]
117+
* Tree to transform (typically `Program`).
118+
* @param {Options | null | undefined} [options={}]
105119
* Configuration (optional).
106120
* @returns {Tree}
107-
* Given, modified, tree.
121+
* Given, modified, `tree`.
108122
*/
109123
// To do next major: do not return the given Node.
110-
export function buildJsx(tree, options = {}) {
111-
let automatic = options.runtime === 'automatic'
124+
export function buildJsx(tree, options) {
125+
const config = options || {}
126+
let automatic = config.runtime === 'automatic'
112127
/** @type {Annotations} */
113128
const annotations = {}
114129
/** @type {Imports} */
@@ -211,9 +226,9 @@ export function buildJsx(tree, options = {}) {
211226
type: 'Literal',
212227
value:
213228
(annotations.jsxImportSource ||
214-
options.importSource ||
229+
config.importSource ||
215230
'react') +
216-
(options.development ? '/jsx-dev-runtime' : '/jsx-runtime')
231+
(config.development ? '/jsx-dev-runtime' : '/jsx-runtime')
217232
}
218233
})
219234
}
@@ -331,7 +346,7 @@ export function buildJsx(tree, options = {}) {
331346
name = {type: 'Identifier', name: '_Fragment'}
332347
} else {
333348
name = toMemberExpression(
334-
annotations.jsxFrag || options.pragmaFrag || 'React.Fragment'
349+
annotations.jsxFrag || config.pragmaFrag || 'React.Fragment'
335350
)
336351
}
337352

@@ -384,13 +399,13 @@ export function buildJsx(tree, options = {}) {
384399

385400
if (key) {
386401
parameters.push(key)
387-
} else if (options.development) {
402+
} else if (config.development) {
388403
parameters.push({type: 'Identifier', name: 'undefined'})
389404
}
390405

391406
const isStaticChildren = children.length > 1
392407

393-
if (options.development) {
408+
if (config.development) {
394409
imports.jsxDEV = true
395410
callee = {
396411
type: 'Identifier',
@@ -411,7 +426,7 @@ export function buildJsx(tree, options = {}) {
411426
key: {type: 'Identifier', name: 'fileName'},
412427
value: {
413428
type: 'Literal',
414-
value: options.filePath || '<source.js>'
429+
value: config.filePath || '<source.js>'
415430
}
416431
}
417432
]
@@ -457,7 +472,7 @@ export function buildJsx(tree, options = {}) {
457472
}
458473

459474
callee = toMemberExpression(
460-
annotations.jsx || options.pragma || 'React.createElement'
475+
annotations.jsx || config.pragma || 'React.createElement'
461476
)
462477
}
463478

readme.md

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
* [Use](#use)
1919
* [API](#api)
2020
* [`buildJsx(tree, options?)`](#buildjsxtree-options)
21+
* [`Options`](#options)
22+
* [`Runtime`](#runtime)
2123
* [Examples](#examples)
2224
* [Example: use with Acorn](#example-use-with-acorn)
23-
* [Algorithm](#algorithm)
2425
* [Types](#types)
2526
* [Compatibility](#compatibility)
2627
* [Related](#related)
@@ -37,12 +38,12 @@ function calls.
3738
## When should I use this?
3839

3940
If you already have a tree and only need to compile JSX away, use this.
40-
If you have code, using something like [SWC][] or [esbuild][] instead.
41+
If you have code, use something like [SWC][] or [esbuild][] instead.
4142

4243
## Install
4344

4445
This package is [ESM only][esm].
45-
In Node.js (version 14.14+, 16.0+), install with [npm][]:
46+
In Node.js (version 14.14+ and 16.0+), install with [npm][]:
4647

4748
```sh
4849
npm install estree-util-build-jsx
@@ -90,27 +91,24 @@ console.log(
9091

9192
```js
9293
import fs from 'node:fs/promises'
93-
import {Parser} from 'acorn'
94-
import jsx from 'acorn-jsx'
95-
import {generate} from 'astring'
94+
import {fromJs} from 'esast-util-from-js'
9695
import {buildJsx} from 'estree-util-build-jsx'
96+
import {toJs} from 'estree-util-to-js'
97+
import jsx from 'acorn-jsx'
9798

9899
const doc = String(await fs.readFile('example.jsx'))
99100

100-
const tree = Parser.extend(jsx()).parse(doc, {
101-
sourceType: 'module',
102-
ecmaVersion: 2022
103-
})
101+
const tree = fromJs(doc, {module: true, plugins: [jsx()]})
104102

105103
buildJsx(tree, {pragma: 'x', pragmaFrag: 'null'})
106104

107-
console.log(generate(tree))
105+
console.log(toJs(tree).value)
108106
```
109107

110108
…now running `node example.js` yields:
111109

112110
```js
113-
import x from 'xastscript';
111+
import x from "xastscript";
114112
console.log(x("album", {
115113
id: 123
116114
}, x("name", null, "Born in the U.S.A."), x("artist", null, "Bruce Springsteen"), x("releasedate", {
@@ -125,31 +123,53 @@ console.log(x(null, null, 1 + 1, x("self-closing"), x("x", Object.assign({
125123

126124
## API
127125

128-
This package exports the identifier `buildJsx`.
126+
This package exports the identifier [`buildJsx`][build-jsx].
129127
There is no default export.
130128

131129
### `buildJsx(tree, options?)`
132130

133-
Turn JSX in `tree` ([`Program`][program]) into function calls:
134-
`<x />` -> `h('x')`!
131+
Turn JSX in `tree` into function calls: `<x />` -> `h('x')`!
132+
133+
###### Algorithm
134+
135+
In almost all cases, this utility is the same as the Babel plugin, except that
136+
they work on slightly different syntax trees.
137+
138+
Some differences:
139+
140+
* no pure annotations things
141+
* `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
142+
* namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
143+
which throws by default in Babel or can be turned on with `throwIfNamespace`
144+
* no `useSpread`, `useBuiltIns`, or `filter` options
135145

136-
##### `options`
146+
###### Parameters
137147

138-
Configuration (optional).
148+
* `tree` ([`Node`][node])
149+
— tree to transform (typically [`Program`][program])
150+
* `options` ([`Options`][options], optional)
151+
— configuration
152+
153+
###### Returns
154+
155+
Given, modified, `tree` ([`Node`][node]).
156+
157+
### `Options`
158+
159+
Configuration (TypeScript type).
139160

140161
> 👉 **Note**: you can also configure `runtime`, `importSource`, `pragma`, and
141162
> `pragmaFrag` from within files through comments.
142163
143164
###### `options.runtime`
144165

145-
Choose the [runtime][]
146-
(`string`, `'automatic'` or `'classic'`, default: `'classic'`).
166+
Choose the [runtime][jsx-runtime] ([`Runtime`][runtime], default: `'classic'`).
147167

148168
Comment form: `@jsxRuntime theRuntime`.
149169

150170
###### `options.importSource`
151171

152-
Place to import `jsx`, `jsxs`, `jsxDEV`, and/or `Fragment` from, when the
172+
Place to import `jsx`, `jsxs`, `jsxDEV`, and `Fragment` from, when the
153173
effective runtime is automatic (`string`, default: `'react'`).
154174

155175
Comment form: `@jsxImportSource theSource`.
@@ -184,20 +204,26 @@ Comment form: `@jsxFrag identifier`.
184204
185205
###### `options.development`
186206
187-
Import `jsxDEV` from `theSource/jsx-dev-runtime.js` and add location info on
188-
where a component originated from (`boolean`, default: `false`).
207+
When in the automatic runtime, whether to import `theSource/jsx-dev-runtime.js`,
208+
use `jsxDEV`, and pass location info when available (`boolean`, default: `false`).
209+
189210
This helps debugging but adds a lot of code that you don’t want in production.
190-
Only used in the automatic runtime.
191211
192212
###### `options.filePath`
193213
194214
File path to the original source file (`string`, example: `'path/to/file.js'`).
195-
Used in the location info when using the automatic runtime with
215+
Passed in location info to `jsxDEV` when using the automatic runtime with
196216
`development: true`.
197217
198-
##### Returns
218+
### `Runtime`
199219
200-
The given `tree` (`Node`).
220+
How to transform JSX (TypeScript type).
221+
222+
###### Type
223+
224+
```ts
225+
type Runtime = 'automatic' | 'classic'
226+
```
201227
202228
## Examples
203229
@@ -218,19 +244,6 @@ const tree = Parser.extend(jsx()).parse(doc, {onComment: comments})
218244
tree.comments = comments
219245
```
220246
221-
## Algorithm
222-
223-
In almost all cases, this utility is the same as the Babel plugin, except that
224-
they work on slightly different syntax trees.
225-
226-
Some differences:
227-
228-
* no pure annotations things
229-
* `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
230-
* namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
231-
which throws by default in Babel or can be turned on with `throwIfNamespace`
232-
* no `useSpread`, `useBuiltIns`, or `filter` options
233-
234247
## Types
235248
236249
This package is fully typed with [TypeScript][].
@@ -321,10 +334,18 @@ abide by its terms.
321334
322335
[espree]: https://github.com/eslint/espree
323336
337+
[node]: https://github.com/estree/estree/blob/master/es5.md#node-objects
338+
324339
[program]: https://github.com/estree/estree/blob/master/es5.md#programs
325340
326-
[runtime]: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
341+
[jsx-runtime]: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
327342
328343
[swc]: https://swc.rs
329344
330345
[esbuild]: https://esbuild.github.io
346+
347+
[build-jsx]: #buildjsxtree-options
348+
349+
[options]: #options
350+
351+
[runtime]: #runtime

0 commit comments

Comments
 (0)