/
recma-jsx-build.js
47 lines (43 loc) · 1.57 KB
/
recma-jsx-build.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* @typedef {import('estree-jsx').Program} Program
* @typedef {import('estree-util-build-jsx').BuildJsxOptions} BuildJsxOptions
*
* @typedef RecmaJsxBuildOptions
* @property {'program'|'function-body'} [outputFormat='program']
* Whether to keep the import of the automatic runtime or get it from
* `arguments[0]` instead.
*/
import {buildJsx} from 'estree-util-build-jsx'
import {specifiersToDeclarations} from '../util/estree-util-specifiers-to-declarations.js'
import {toIdOrMemberExpression} from '../util/estree-util-to-id-or-member-expression.js'
/**
* A plugin to build JSX into function calls.
* `estree-util-build-jsx` does all the work for us!
*
* @type {import('unified').Plugin<[BuildJsxOptions & RecmaJsxBuildOptions?], Program>}
*/
export function recmaJsxBuild(options = {}) {
const {development, outputFormat} = options
return (tree, file) => {
buildJsx(tree, {development, filePath: file.history[0]})
// When compiling to a function body, replace the import that was just
// generated, and get `jsx`, `jsxs`, and `Fragment` from `arguments[0]`
// instead.
if (
outputFormat === 'function-body' &&
tree.body[0] &&
tree.body[0].type === 'ImportDeclaration' &&
typeof tree.body[0].source.value === 'string' &&
/\/jsx-(dev-)?runtime$/.test(tree.body[0].source.value)
) {
tree.body[0] = {
type: 'VariableDeclaration',
kind: 'const',
declarations: specifiersToDeclarations(
tree.body[0].specifiers,
toIdOrMemberExpression(['arguments', 0])
)
}
}
}
}