8
8
[ ![ Backers] [ backers-badge ]] [ collective ]
9
9
[ ![ Chat] [ chat-badge ]] [ chat ]
10
10
11
- Transform JSX to function calls: ` <x /> ` -> ` h('x') ` !
11
+ [ estree ] [ ] utility to turn JSX into function calls: ` <x /> ` -> ` h('x') ` !
12
12
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
19
14
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?
21
31
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.
24
35
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] [ ] :
26
45
27
46
``` sh
28
47
npm install estree-util-build-jsx
29
48
```
30
49
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
+
31
64
## Use
32
65
33
- Say we have the following file, ` example.jsx ` :
66
+ Say we have the following ` example.jsx ` :
34
67
35
68
``` js
36
69
import x from ' xastscript'
@@ -52,28 +85,28 @@ console.log(
52
85
)
53
86
```
54
87
55
- And our script, ` example.js ` , looks as follows :
88
+ …and next to it a module ` example.js ` :
56
89
57
90
``` js
58
- import fs from ' node:fs'
91
+ import fs from ' node:fs/promises '
59
92
import {Parser } from ' acorn'
60
93
import jsx from ' acorn-jsx'
61
94
import {generate } from ' astring'
62
95
import {buildJsx } from ' estree-util-build-jsx'
63
96
64
- const doc = fs .readFileSync (' example.jsx' )
97
+ const doc = String ( await fs .readFile (' example.jsx' ) )
65
98
66
99
const tree = Parser .extend (jsx ()).parse (doc, {
67
100
sourceType: ' module' ,
68
- ecmaVersion: 2020
101
+ ecmaVersion: 2022
69
102
})
70
103
71
104
buildJsx (tree, {pragma: ' x' , pragmaFrag: ' null' })
72
105
73
106
console .log (generate (tree))
74
107
```
75
108
76
- Now, running ` node example ` yields:
109
+ …now running ` node example.js ` yields:
77
110
78
111
``` js
79
112
import x from ' xastscript' ;
@@ -91,32 +124,67 @@ console.log(x(null, null, 1 + 1, x("self-closing"), x("x", Object.assign({
91
124
92
125
## API
93
126
94
- This package exports the following identifiers: ` buildJsx ` .
127
+ This package exports the identifier ` buildJsx ` .
95
128
There is no default export.
96
129
97
130
### ` buildJsx(tree, options?) `
98
131
99
- Turn JSX in ` tree ` ([ ` Program ` ] [ program ] ) into hyperscript calls.
132
+ Turn JSX in ` tree ` ([ ` Program ` ] [ program ] ) into function calls:
133
+ ` <x /> ` -> ` h('x') ` !
100
134
101
135
##### ` options `
102
136
137
+ Configuration (optional).
138
+
139
+ > 👉 ** Note** : you can also configure ` runtime ` , ` importSource ` , ` pragma ` , and
140
+ > ` pragmaFrag ` from within files through comments.
141
+
103
142
###### ` options.runtime `
104
143
105
- Choose the [ runtime] [ ] .
144
+ Choose the [ runtime] [ ]
106
145
(` string ` , ` 'automatic' ` or ` 'classic' ` , default: ` 'classic' ` ).
146
+
107
147
Comment form: ` @jsxRuntime theRuntime ` .
108
148
109
149
###### ` options.importSource `
110
150
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` .
115
183
116
- ##### ` options.development `
184
+ ###### ` options .development `
117
185
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 ` ).
120
188
This helps debugging but adds a lot of code that you don’t want in production.
121
189
Only used in the automatic runtime.
122
190
@@ -126,58 +194,71 @@ File path to the original source file (`string`, example: `'path/to/file.js'`).
126
194
Used in the location info when using the automatic runtime with
127
195
` development: true ` .
128
196
129
- ###### ` options.pragma `
197
+ ##### Returns
130
198
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 ` ).
134
200
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
140
202
141
- ###### Returns
203
+ ### Example: use with Acorn
142
204
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]:
151
208
152
209
` ` ` js
153
210
import {Parser } from ' acorn'
154
211
import jsx from ' acorn-jsx'
155
212
156
- var doc = ' '
213
+ const doc = ' ' // To do: get `doc` somehow.
157
214
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})
160
217
tree .comments = comments
161
218
` ` `
162
219
220
+ ## Algorithm
221
+
163
222
In almost all cases, this utility is the same as the Babel plugin, except that
164
223
they work on slightly different syntax trees.
165
224
166
225
Some differences:
167
226
168
- * No pure annotations or dev things
227
+ * No pure annotations things
169
228
* ` this ` is not a component: ` < this > ` -> ` h (' this' )` , not ` h (this )`
170
229
* Namespaces are supported: ` < a: b c: d> ` -> ` h (' a:b' , {' c:d' : true })` ,
171
230
which throws by default in Babel or can be turned on with ` throwIfNamespace`
172
231
* No ` useSpread` , ` useBuiltIns` , or ` filter` options
173
232
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
+
174
245
## Related
175
246
176
247
* [` 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][]
178
249
JSX
179
250
* [` 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.
181
262
182
263
## License
183
264
@@ -211,12 +292,24 @@ Some differences:
211
292
212
293
[chat]: https://github.com/syntax-tree/unist/discussions
213
294
295
+ [esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
296
+
214
297
[npm]: https://docs.npmjs.com/cli/install
215
298
299
+ [esmsh]: https://esm.sh
300
+
216
301
[license]: license
217
302
218
303
[author]: https://wooorm.com
219
304
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
+
220
313
[acorn]: https://github.com/acornjs/acorn
221
314
222
315
[estree]: https://github.com/estree/estree
@@ -225,6 +318,8 @@ Some differences:
225
318
226
319
[program]: https://github.com/estree/estree/blob/master/es5.md#programs
227
320
228
- [ pr ] : https://github.com/mdx-js/mdx/pull/1399
229
-
230
321
[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