Skip to content

Commit 8e0b87e

Browse files
committed
Add improved docs
1 parent 76a366d commit 8e0b87e

File tree

1 file changed

+148
-53
lines changed

1 file changed

+148
-53
lines changed

readme.md

Lines changed: 148 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,62 @@
88
[![Backers][backers-badge]][collective]
99
[![Chat][chat-badge]][chat]
1010

11-
Transform JSX to function calls: `<x />` -> `h('x')`!
11+
[estree][] utility to turn JSX into function calls: `<x />` -> `h('x')`!
1212

13-
There is currently one project actively maintained that can transform JSX to
14-
function calls: Babel.
15-
Babel is amazing but ginormous (±300kb) and slow.
16-
Switching from it to [estree][] in a project where Babel was only a small part
17-
made the whole project [**68% smaller and 63% faster**][pr].
18-
So let’s make that two implementations.
13+
## Contents
1914

20-
## Install
15+
* [What is this?](#what-is-this)
16+
* [When should I use this?](#when-should-i-use-this)
17+
* [Install](#install)
18+
* [Use](#use)
19+
* [API](#api)
20+
* [`buildJsx(tree, options?)`](#buildjsxtree-options)
21+
* [Examples](#examples)
22+
* [Example: use with Acorn](#example-use-with-acorn)
23+
* [Algorithm](#algorithm)
24+
* [Types](#types)
25+
* [Compatibility](#compatibility)
26+
* [Related](#related)
27+
* [Contribute](#contribute)
28+
* [License](#license)
29+
30+
## What is this?
2131

22-
This package is ESM only: Node 12+ is needed to use it and it must be `import`ed
23-
instead of `require`d.
32+
This package is a utility that takes an [estree][] (JavaScript) syntax tree as
33+
input that contains embedded JSX nodes (elements, fragments) and turns them into
34+
function calls.
2435

25-
[npm][]:
36+
## When should I use this?
37+
38+
If you already have a tree and only need to compile JSX away, use this.
39+
If you have code, using something like [SWC][] or [esbuild][] instead.
40+
41+
## Install
42+
43+
This package is [ESM only][esm].
44+
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]:
2645

2746
```sh
2847
npm install estree-util-build-jsx
2948
```
3049

50+
In Deno with [`esm.sh`][esmsh]:
51+
52+
```js
53+
import {buildJsx} from 'https://esm.sh/estree-util-build-jsx@2'
54+
```
55+
56+
In browsers with [`esm.sh`][esmsh]:
57+
58+
```html
59+
<script type="module">
60+
import {buildJsx} from 'https://esm.sh/estree-util-build-jsx@2?bundle'
61+
</script>
62+
```
63+
3164
## Use
3265

33-
Say we have the following file, `example.jsx`:
66+
Say we have the following `example.jsx`:
3467

3568
```js
3669
import x from 'xastscript'
@@ -52,28 +85,28 @@ console.log(
5285
)
5386
```
5487

55-
And our script, `example.js`, looks as follows:
88+
…and next to it a module `example.js`:
5689

5790
```js
58-
import fs from 'node:fs'
91+
import fs from 'node:fs/promises'
5992
import {Parser} from 'acorn'
6093
import jsx from 'acorn-jsx'
6194
import {generate} from 'astring'
6295
import {buildJsx} from 'estree-util-build-jsx'
6396

64-
const doc = fs.readFileSync('example.jsx')
97+
const doc = String(await fs.readFile('example.jsx'))
6598

6699
const tree = Parser.extend(jsx()).parse(doc, {
67100
sourceType: 'module',
68-
ecmaVersion: 2020
101+
ecmaVersion: 2022
69102
})
70103

71104
buildJsx(tree, {pragma: 'x', pragmaFrag: 'null'})
72105

73106
console.log(generate(tree))
74107
```
75108

76-
Now, running `node example` yields:
109+
…now running `node example.js` yields:
77110

78111
```js
79112
import x from 'xastscript';
@@ -91,32 +124,67 @@ console.log(x(null, null, 1 + 1, x("self-closing"), x("x", Object.assign({
91124

92125
## API
93126

94-
This package exports the following identifiers: `buildJsx`.
127+
This package exports the identifier `buildJsx`.
95128
There is no default export.
96129

97130
### `buildJsx(tree, options?)`
98131

99-
Turn JSX in `tree` ([`Program`][program]) into hyperscript calls.
132+
Turn JSX in `tree` ([`Program`][program]) into function calls:
133+
`<x />` -> `h('x')`!
100134

101135
##### `options`
102136

137+
Configuration (optional).
138+
139+
> 👉 **Note**: you can also configure `runtime`, `importSource`, `pragma`, and
140+
> `pragmaFrag` from within files through comments.
141+
103142
###### `options.runtime`
104143

105-
Choose the [runtime][].
144+
Choose the [runtime][]
106145
(`string`, `'automatic'` or `'classic'`, default: `'classic'`).
146+
107147
Comment form: `@jsxRuntime theRuntime`.
108148

109149
###### `options.importSource`
110150

111-
Place to import `jsx`, `jsxs`, and/or `Fragment` from, when the effective
112-
runtime is automatic (`string`, default: `'react'`).
113-
Comment: `@jsxImportSource theSource`.
114-
Note that `/jsx-runtime` is appended to this provided source.
151+
Place to import `jsx`, `jsxs`, `jsxDEV`, and/or `Fragment` from, when the
152+
effective runtime is automatic (`string`, default: `'react'`).
153+
154+
Comment form: `@jsxImportSource theSource`.
155+
156+
> 👉 **Note**: `/jsx-runtime` or `/jsx-dev-runtime` is appended to this provided
157+
> source.
158+
> In CJS, that can resolve to a file, as in `theSource/jsx-runtime.js`, but for
159+
> ESM an export map needs to be set up to point to files:
160+
>
161+
> ```js
162+
> //
163+
> "exports": {
164+
> //
165+
> "./jsx-runtime": "./path/to/jsx-runtime.js",
166+
> "./jsx-dev-runtime": "./path/to/jsx-runtime.js"
167+
> //
168+
> ```
169+
170+
###### `options.pragma`
171+
172+
Identifier or member expression to call when the effective runtime is classic
173+
(`string`, default: `'React.createElement'`).
174+
175+
Comment form: `@jsx identifier`.
176+
177+
###### `options.pragmaFrag`
178+
179+
Identifier or member expression to use as a symbol for fragments when the
180+
effective runtime is classic (`string`, default: `'React.Fragment'`).
181+
182+
Comment form: `@jsxFrag identifier`.
115183
116-
##### `options.development`
184+
###### `options.development`
117185
118-
Add location info on where a component originated from (`boolean`, default:
119-
`false`).
186+
Import `jsxDEV` from `theSource/jsx-dev-runtime.js` and add location info on
187+
where a component originated from (`boolean`, default: `false`).
120188
This helps debugging but adds a lot of code that you don’t want in production.
121189
Only used in the automatic runtime.
122190
@@ -126,58 +194,71 @@ File path to the original source file (`string`, example: `'path/to/file.js'`).
126194
Used in the location info when using the automatic runtime with
127195
`development: true`.
128196
129-
###### `options.pragma`
197+
##### Returns
130198
131-
Identifier or member expression to call when the effective runtime is classic
132-
(`string`, default: `'React.createElement'`).
133-
Comment: `@jsx identifier`.
199+
The given `tree` (`Node`).
134200
135-
###### `options.pragmaFrag`
136-
137-
Identifier or member expression to use as a sumbol for fragments when the
138-
effective runtime is classic (`string`, default: `'React.Fragment'`).
139-
Comment: `@jsxFrag identifier`.
201+
## Examples
140202
141-
###### Returns
203+
### Example: use with Acorn
142204
143-
`Node` — The given `tree`.
144-
145-
###### Notes
146-
147-
To support configuration from comments, those comments have to be in the
148-
program.
149-
This is done automatically by [`espree`][espree].
150-
For [`acorn`][acorn], it can be done like so:
205+
To support configuration from comments in Acorn, those comments have to be in
206+
the program.
207+
This is done by [`espree`][espree] but not automatically by [`acorn`][acorn]:
151208
152209
```js
153210
import {Parser} from 'acorn'
154211
import jsx from 'acorn-jsx'
155212
156-
var doc = ''
213+
const doc = '' // To do: get `doc` somehow.
157214
158-
var comments = []
159-
var tree = Parser.extend(jsx()).parse(doc, {onComment: comments})
215+
const comments = []
216+
const tree = Parser.extend(jsx()).parse(doc, {onComment: comments})
160217
tree.comments = comments
161218
```
162219
220+
## Algorithm
221+
163222
In almost all cases, this utility is the same as the Babel plugin, except that
164223
they work on slightly different syntax trees.
165224
166225
Some differences:
167226
168-
* No pure annotations or dev things
227+
* No pure annotations things
169228
* `this` is not a component: `<this>` -> `h('this')`, not `h(this)`
170229
* Namespaces are supported: `<a:b c:d>` -> `h('a:b', {'c:d': true})`,
171230
which throws by default in Babel or can be turned on with `throwIfNamespace`
172231
* No `useSpread`, `useBuiltIns`, or `filter` options
173232
233+
## Types
234+
235+
This package is fully typed with [TypeScript][].
236+
It exports the types `Options` and `Node`.
237+
238+
## Compatibility
239+
240+
Projects maintained by the unified collective are compatible with all maintained
241+
versions of Node.js.
242+
As of now, that is Node.js 12.20+, 14.14+, and 16.0+.
243+
Our projects sometimes work with older versions, but this is not guaranteed.
244+
174245
## Related
175246
176247
* [`syntax-tree/hast-util-to-estree`](https://github.com/syntax-tree/hast-util-to-estree)
177-
Transform [hast](https://github.com/syntax-tree/hast) (HTML) to [estree][]
248+
turn [hast](https://github.com/syntax-tree/hast) (HTML) to [estree][]
178249
JSX
179250
* [`coderaiser/estree-to-babel`](https://github.com/coderaiser/estree-to-babel)
180-
— Transform [estree][] to Babel trees
251+
— turn [estree][] to Babel trees
252+
253+
## Contribute
254+
255+
See [`contributing.md` in `syntax-tree/.github`][contributing] for ways to get
256+
started.
257+
See [`support.md`][support] for ways to get help.
258+
259+
This project has a [code of conduct][coc].
260+
By interacting with this repository, organization, or community you agree to
261+
abide by its terms.
181262
182263
## License
183264
@@ -211,12 +292,24 @@ Some differences:
211292
212293
[chat]: https://github.com/syntax-tree/unist/discussions
213294
295+
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
296+
214297
[npm]: https://docs.npmjs.com/cli/install
215298
299+
[esmsh]: https://esm.sh
300+
216301
[license]: license
217302
218303
[author]: https://wooorm.com
219304
305+
[typescript]: https://www.typescriptlang.org
306+
307+
[contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md
308+
309+
[support]: https://github.com/syntax-tree/.github/blob/main/support.md
310+
311+
[coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md
312+
220313
[acorn]: https://github.com/acornjs/acorn
221314
222315
[estree]: https://github.com/estree/estree
@@ -225,6 +318,8 @@ Some differences:
225318
226319
[program]: https://github.com/estree/estree/blob/master/es5.md#programs
227320
228-
[pr]: https://github.com/mdx-js/mdx/pull/1399
229-
230321
[runtime]: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
322+
323+
[swc]: https://swc.rs
324+
325+
[esbuild]: https://esbuild.github.io

0 commit comments

Comments
 (0)