@ssets/babel 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helper/annotate-as-pure.d.ts +4 -0
- package/dist/helper/annotate-as-pure.js +13 -0
- package/dist/helper/validator-option.d.ts +36 -0
- package/dist/helper/validator-option.js +100 -0
- package/dist/plugin/display-name.d.ts +9 -0
- package/dist/plugin/display-name.js +339 -0
- package/dist/plugin/resolve-imports.d.ts +8 -0
- package/dist/plugin/resolve-imports.js +62 -0
- package/dist/plugin/syntax-typescript.d.ts +7 -0
- package/dist/plugin/syntax-typescript.js +15 -0
- package/dist/plugin/transform-react-display-name.d.ts +9 -0
- package/dist/plugin/transform-react-display-name.js +97 -0
- package/dist/plugin/transform-react-pure-annotations.d.ts +8 -0
- package/dist/plugin/transform-react-pure-annotations.js +69 -0
- package/dist/plugin/transform-remove-imports.d.ts +1 -0
- package/dist/plugin/transform-remove-imports.js +1 -0
- package/dist/plugin/transform-runtime.d.ts +1 -0
- package/dist/plugin/transform-runtime.js +1 -0
- package/dist/preset/env.d.ts +2 -0
- package/dist/preset/env.js +2 -0
- package/dist/preset/react/index.d.ts +14 -0
- package/dist/preset/react/index.js +34 -0
- package/dist/preset/react/normalize-options.d.ts +10 -0
- package/dist/preset/react/normalize-options.js +60 -0
- package/package.json +39 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { addComment } from "@babel/types";
|
|
2
|
+
const PURE_ANNOTATION = "#__PURE__";
|
|
3
|
+
const isPureAnnotated = ({ leadingComments }) => !!leadingComments &&
|
|
4
|
+
leadingComments.some((comment) => /[@#]__PURE__/.test(comment.value));
|
|
5
|
+
export default function annotateAsPure(pathOrNode) {
|
|
6
|
+
const node =
|
|
7
|
+
// @ts-expect-error Node will not have `node` property
|
|
8
|
+
(pathOrNode.node || pathOrNode);
|
|
9
|
+
if (isPureAnnotated(node)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
addComment(node, "leading", PURE_ANNOTATION);
|
|
13
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given a string `str` and an array of candidates `arr`,
|
|
3
|
+
* return the first of elements in candidates that has minimal
|
|
4
|
+
* Levenshtein distance with `str`.
|
|
5
|
+
* @export
|
|
6
|
+
* @param {string} str
|
|
7
|
+
* @param {string[]} arr
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
export declare function findSuggestion(str: string, arr: readonly string[]): string;
|
|
11
|
+
export declare class OptionValidator {
|
|
12
|
+
descriptor: string;
|
|
13
|
+
constructor(descriptor: string);
|
|
14
|
+
/**
|
|
15
|
+
* Validate if the given `options` follow the name of keys defined in the `TopLevelOptionShape`
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {Object} TopLevelOptionShape
|
|
19
|
+
* An object with all the valid key names that `options` should be allowed to have
|
|
20
|
+
* The property values of `TopLevelOptionShape` can be arbitrary
|
|
21
|
+
* @memberof OptionValidator
|
|
22
|
+
*/
|
|
23
|
+
validateTopLevelOptions(options: object, TopLevelOptionShape: object): void;
|
|
24
|
+
validateBooleanOption<T extends boolean>(name: string, value?: boolean, defaultValue?: T): boolean | T;
|
|
25
|
+
validateStringOption<T extends string>(name: string, value?: string, defaultValue?: T): string | T;
|
|
26
|
+
/**
|
|
27
|
+
* A helper interface copied from the `invariant` npm package.
|
|
28
|
+
* It throws given `message` when `condition` is not met
|
|
29
|
+
*
|
|
30
|
+
* @param {boolean} condition
|
|
31
|
+
* @param {string} message
|
|
32
|
+
* @memberof OptionValidator
|
|
33
|
+
*/
|
|
34
|
+
invariant(condition: boolean, message: string): void;
|
|
35
|
+
formatMessage(message: string): string;
|
|
36
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const { min } = Math;
|
|
2
|
+
// a minimal leven distance implementation
|
|
3
|
+
// balanced maintainability with code size
|
|
4
|
+
// It is not blazingly fast but should be okay for Babel user case
|
|
5
|
+
// where it will be run for at most tens of time on strings
|
|
6
|
+
// that have less than 20 ASCII characters
|
|
7
|
+
// https://rosettacode.org/wiki/Levenshtein_distance#ES5
|
|
8
|
+
function levenshtein(a, b) {
|
|
9
|
+
let t = [], u = [], i, j;
|
|
10
|
+
const m = a.length, n = b.length;
|
|
11
|
+
if (!m) {
|
|
12
|
+
return n;
|
|
13
|
+
}
|
|
14
|
+
if (!n) {
|
|
15
|
+
return m;
|
|
16
|
+
}
|
|
17
|
+
for (j = 0; j <= n; j++) {
|
|
18
|
+
t[j] = j;
|
|
19
|
+
}
|
|
20
|
+
for (i = 1; i <= m; i++) {
|
|
21
|
+
for (u = [i], j = 1; j <= n; j++) {
|
|
22
|
+
u[j] =
|
|
23
|
+
a[i - 1] === b[j - 1] ? t[j - 1] : min(t[j - 1], t[j], u[j - 1]) + 1;
|
|
24
|
+
}
|
|
25
|
+
t = u;
|
|
26
|
+
}
|
|
27
|
+
return u[n];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Given a string `str` and an array of candidates `arr`,
|
|
31
|
+
* return the first of elements in candidates that has minimal
|
|
32
|
+
* Levenshtein distance with `str`.
|
|
33
|
+
* @export
|
|
34
|
+
* @param {string} str
|
|
35
|
+
* @param {string[]} arr
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export function findSuggestion(str, arr) {
|
|
39
|
+
const distances = arr.map((el) => levenshtein(el, str));
|
|
40
|
+
return arr[distances.indexOf(min(...distances))];
|
|
41
|
+
}
|
|
42
|
+
export class OptionValidator {
|
|
43
|
+
constructor(descriptor) {
|
|
44
|
+
this.descriptor = descriptor;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate if the given `options` follow the name of keys defined in the `TopLevelOptionShape`
|
|
48
|
+
*
|
|
49
|
+
* @param {Object} options
|
|
50
|
+
* @param {Object} TopLevelOptionShape
|
|
51
|
+
* An object with all the valid key names that `options` should be allowed to have
|
|
52
|
+
* The property values of `TopLevelOptionShape` can be arbitrary
|
|
53
|
+
* @memberof OptionValidator
|
|
54
|
+
*/
|
|
55
|
+
validateTopLevelOptions(options, TopLevelOptionShape) {
|
|
56
|
+
const validOptionNames = Object.keys(TopLevelOptionShape);
|
|
57
|
+
for (const option of Object.keys(options)) {
|
|
58
|
+
if (!validOptionNames.includes(option)) {
|
|
59
|
+
throw new Error(this.formatMessage(`'${option}' is not a valid top-level option.
|
|
60
|
+
- Did you mean '${findSuggestion(option, validOptionNames)}'?`));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// note: we do not consider rewrite them to high order functions
|
|
65
|
+
// until we have to support `validateNumberOption`.
|
|
66
|
+
validateBooleanOption(name, value, defaultValue) {
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
return defaultValue;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.invariant(typeof value === "boolean", `'${name}' option must be a boolean.`);
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
validateStringOption(name, value, defaultValue) {
|
|
76
|
+
if (value === undefined) {
|
|
77
|
+
return defaultValue;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.invariant(typeof value === "string", `'${name}' option must be a string.`);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A helper interface copied from the `invariant` npm package.
|
|
86
|
+
* It throws given `message` when `condition` is not met
|
|
87
|
+
*
|
|
88
|
+
* @param {boolean} condition
|
|
89
|
+
* @param {string} message
|
|
90
|
+
* @memberof OptionValidator
|
|
91
|
+
*/
|
|
92
|
+
invariant(condition, message) {
|
|
93
|
+
if (!condition) {
|
|
94
|
+
throw new Error(this.formatMessage(message));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
formatMessage(message) {
|
|
98
|
+
return `${this.descriptor}: ${message}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import babel from "@babel/core";
|
|
2
|
+
interface AllowedCallees {
|
|
3
|
+
[moduleName: string]: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface PluginOptions {
|
|
6
|
+
allowedCallees?: AllowedCallees;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: (api: object, options: PluginOptions | null | undefined, dirname: string) => babel.PluginObj<babel.PluginPass>;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
2
|
+
// remember to set `cacheDirectory` to `false` when modifying this plugin
|
|
3
|
+
const DEFAULT_ALLOWED_CALLEES = {
|
|
4
|
+
react: ["createContext", "forwardRef", "memo"],
|
|
5
|
+
};
|
|
6
|
+
const calleeModuleMapping = new Map(); // Mapping of callee name to module name
|
|
7
|
+
const seenDisplayNames = new Set();
|
|
8
|
+
/**
|
|
9
|
+
* Applies allowed callees mapping to the internal calleeModuleMapping.
|
|
10
|
+
*/
|
|
11
|
+
function applyAllowedCallees(mapping) {
|
|
12
|
+
Object.entries(mapping).forEach(([moduleName, methodNames]) => {
|
|
13
|
+
methodNames.forEach((methodName) => {
|
|
14
|
+
const moduleNames = calleeModuleMapping.get(methodName) ?? [];
|
|
15
|
+
moduleNames.push(moduleName);
|
|
16
|
+
calleeModuleMapping.set(methodName, moduleNames);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export default declare((api, options) => {
|
|
21
|
+
api.assertVersion(7);
|
|
22
|
+
calleeModuleMapping.clear();
|
|
23
|
+
applyAllowedCallees(DEFAULT_ALLOWED_CALLEES);
|
|
24
|
+
if (options.allowedCallees) {
|
|
25
|
+
applyAllowedCallees(options.allowedCallees);
|
|
26
|
+
}
|
|
27
|
+
const t = api.types;
|
|
28
|
+
return {
|
|
29
|
+
name: "@probablyup/babel-plugin-react-displayname",
|
|
30
|
+
visitor: {
|
|
31
|
+
Program() {
|
|
32
|
+
// We allow duplicate names across files,
|
|
33
|
+
// so we clear when we're transforming on a new file
|
|
34
|
+
seenDisplayNames.clear();
|
|
35
|
+
},
|
|
36
|
+
"FunctionExpression|ArrowFunctionExpression|ObjectMethod": (path) => {
|
|
37
|
+
// if the parent is a call expression, make sure it's an allowed one
|
|
38
|
+
if (path.parentPath && path.parentPath.isCallExpression()
|
|
39
|
+
? isAllowedCallExpression(t, path.parentPath)
|
|
40
|
+
: true) {
|
|
41
|
+
if (doesReturnJSX(t, path.node.body)) {
|
|
42
|
+
addDisplayNamesToFunctionComponent(t, path);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
CallExpression(path) {
|
|
47
|
+
if (isAllowedCallExpression(t, path)) {
|
|
48
|
+
addDisplayNamesToFunctionComponent(t, path);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Checks if this function returns JSX nodes.
|
|
56
|
+
* It does not do type-checking, which means calling
|
|
57
|
+
* other functions that return JSX will still return `false`.
|
|
58
|
+
*/
|
|
59
|
+
function doesReturnJSX(t, node) {
|
|
60
|
+
if (!node) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const body = t.toBlock(node).body;
|
|
64
|
+
if (!body) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return body.some((statement) => {
|
|
68
|
+
let currentNode;
|
|
69
|
+
if (t.isReturnStatement(statement)) {
|
|
70
|
+
currentNode = statement.argument;
|
|
71
|
+
}
|
|
72
|
+
else if (t.isExpressionStatement(statement) &&
|
|
73
|
+
!t.isCallExpression(statement.expression)) {
|
|
74
|
+
currentNode = statement.expression;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (t.isCallExpression(currentNode) &&
|
|
80
|
+
// detect *.createElement and count it as returning JSX
|
|
81
|
+
// this could be improved a lot but will work for the 99% case
|
|
82
|
+
t.isMemberExpression(currentNode.callee) &&
|
|
83
|
+
t.isIdentifier(currentNode.callee.property) &&
|
|
84
|
+
currentNode.callee.property.name === "createElement") {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (t.isConditionalExpression(currentNode)) {
|
|
88
|
+
return (isJSX(t, currentNode.consequent) || isJSX(t, currentNode.alternate));
|
|
89
|
+
}
|
|
90
|
+
if (t.isLogicalExpression(currentNode)) {
|
|
91
|
+
return isJSX(t, currentNode.left) || isJSX(t, currentNode.right);
|
|
92
|
+
}
|
|
93
|
+
if (t.isArrayExpression(currentNode)) {
|
|
94
|
+
return currentNode.elements.some((ele) => isJSX(t, ele));
|
|
95
|
+
}
|
|
96
|
+
return isJSX(t, currentNode);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks if this node is JSXElement or JSXFragment,
|
|
101
|
+
* which are the root nodes of react components.
|
|
102
|
+
*/
|
|
103
|
+
function isJSX(t, node) {
|
|
104
|
+
return t.isJSXElement(node) || t.isJSXFragment(node);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Checks if this path is an allowed CallExpression.
|
|
108
|
+
*/
|
|
109
|
+
function isAllowedCallExpression(t, path) {
|
|
110
|
+
const calleePath = path.get("callee");
|
|
111
|
+
const callee = path.node
|
|
112
|
+
.callee;
|
|
113
|
+
const calleeName = callee.name || callee.property?.name;
|
|
114
|
+
const moduleNames = calleeName && calleeModuleMapping.get(calleeName);
|
|
115
|
+
if (!moduleNames) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
// If the callee is an identifier expression, then check if it matches
|
|
119
|
+
// a named import, e.g. `import {createContext} from 'react'`.
|
|
120
|
+
if (calleePath.isIdentifier()) {
|
|
121
|
+
return moduleNames.some((moduleName) => calleePath.referencesImport(moduleName, calleeName));
|
|
122
|
+
}
|
|
123
|
+
// Otherwise, check if the member expression's object matches
|
|
124
|
+
// a default import (e.g. `import React from 'react'`)
|
|
125
|
+
// or namespace import (e.g. `import * as React from 'react')
|
|
126
|
+
if (calleePath.isMemberExpression()) {
|
|
127
|
+
const object = calleePath.get("object");
|
|
128
|
+
return moduleNames.some((moduleName) => object.referencesImport(moduleName, "default") ||
|
|
129
|
+
object.referencesImport(moduleName, "*"));
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Adds displayName to the function component if it is:
|
|
135
|
+
* - assigned to a variable or object path
|
|
136
|
+
* - not within other JSX elements
|
|
137
|
+
* - not called by a react hook or _createClass helper
|
|
138
|
+
*/
|
|
139
|
+
function addDisplayNamesToFunctionComponent(t, path) {
|
|
140
|
+
const componentIdentifiers = [];
|
|
141
|
+
if (path.node.key) {
|
|
142
|
+
componentIdentifiers.push({ id: path.node.key });
|
|
143
|
+
}
|
|
144
|
+
let assignmentPath;
|
|
145
|
+
let hasCallee = false;
|
|
146
|
+
let hasObjectProperty = false;
|
|
147
|
+
const scopePath = path.scope.parent && path.scope.parent.path;
|
|
148
|
+
path.find((parentPath) => {
|
|
149
|
+
// we've hit the scope, stop going further up
|
|
150
|
+
if (parentPath === scopePath) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// Ignore functions within jsx
|
|
154
|
+
if (isJSX(t, parentPath.node)) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
if (parentPath.isCallExpression()) {
|
|
158
|
+
// Ignore immediately invoked function expressions (IIFEs)
|
|
159
|
+
const callee = parentPath.node.callee;
|
|
160
|
+
if (t.isArrowFunctionExpression(callee) ||
|
|
161
|
+
t.isFunctionExpression(callee)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
// Ignore instances where displayNames are disallowed
|
|
165
|
+
// _createClass(() => <Element />)
|
|
166
|
+
// useMemo(() => <Element />)
|
|
167
|
+
const calleeName = t.isIdentifier(callee) ? callee.name : undefined;
|
|
168
|
+
if (calleeName &&
|
|
169
|
+
(calleeName.startsWith("_") || calleeName.startsWith("use"))) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
hasCallee = true;
|
|
173
|
+
}
|
|
174
|
+
// componentIdentifier = <Element />
|
|
175
|
+
if (parentPath.isAssignmentExpression()) {
|
|
176
|
+
assignmentPath = parentPath.parentPath;
|
|
177
|
+
componentIdentifiers.unshift({
|
|
178
|
+
id: parentPath.node.left,
|
|
179
|
+
});
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
// const componentIdentifier = <Element />
|
|
183
|
+
if (parentPath.isVariableDeclarator()) {
|
|
184
|
+
// Ternary expression
|
|
185
|
+
if (t.isConditionalExpression(parentPath.node.init)) {
|
|
186
|
+
const { consequent, alternate } = parentPath.node.init;
|
|
187
|
+
const isConsequentFunction = t.isArrowFunctionExpression(consequent) ||
|
|
188
|
+
t.isFunctionExpression(consequent);
|
|
189
|
+
const isAlternateFunction = t.isArrowFunctionExpression(alternate) ||
|
|
190
|
+
t.isFunctionExpression(alternate);
|
|
191
|
+
// Only add display name if variable is a function
|
|
192
|
+
if (!isConsequentFunction || !isAlternateFunction) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
assignmentPath = parentPath.parentPath;
|
|
197
|
+
componentIdentifiers.unshift({
|
|
198
|
+
id: parentPath.node.id,
|
|
199
|
+
});
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
// if this is not a continuous object key: value pair, stop processing it
|
|
203
|
+
if (hasObjectProperty &&
|
|
204
|
+
!(parentPath.isObjectProperty() || parentPath.isObjectExpression())) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
// { componentIdentifier: <Element /> }
|
|
208
|
+
if (parentPath.isObjectProperty()) {
|
|
209
|
+
hasObjectProperty = true;
|
|
210
|
+
const node = parentPath.node;
|
|
211
|
+
componentIdentifiers.unshift({
|
|
212
|
+
id: node.key,
|
|
213
|
+
computed: node.computed,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
});
|
|
218
|
+
if (!assignmentPath || componentIdentifiers.length === 0) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const name = generateDisplayName(t, componentIdentifiers);
|
|
222
|
+
const pattern = `${name}.displayName`;
|
|
223
|
+
// disallow duplicate names if they were assigned in different scopes
|
|
224
|
+
if (seenDisplayNames.has(name) &&
|
|
225
|
+
!hasBeenAssignedPrev(t, assignmentPath, pattern, name)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// skip unnecessary addition of name if it is reassigned later on
|
|
229
|
+
if (hasBeenAssignedNext(t, assignmentPath, pattern)) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// at this point we're ready to start pushing code
|
|
233
|
+
if (hasCallee) {
|
|
234
|
+
// if we're getting called by some wrapper function,
|
|
235
|
+
// give this function a name
|
|
236
|
+
setInternalFunctionName(t, path, name);
|
|
237
|
+
}
|
|
238
|
+
const displayNameStatement = createDisplayNameStatement(t, componentIdentifiers, name);
|
|
239
|
+
assignmentPath.insertAfter(displayNameStatement);
|
|
240
|
+
seenDisplayNames.add(name);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Generate a displayName string based on the ids collected.
|
|
244
|
+
*/
|
|
245
|
+
function generateDisplayName(t, componentIdentifiers) {
|
|
246
|
+
let displayName = "";
|
|
247
|
+
componentIdentifiers.forEach((componentIdentifier) => {
|
|
248
|
+
const node = componentIdentifier.id;
|
|
249
|
+
if (!node) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const name = generateNodeDisplayName(t, node);
|
|
253
|
+
displayName += componentIdentifier.computed ? `[${name}]` : `.${name}`;
|
|
254
|
+
});
|
|
255
|
+
return displayName.slice(1);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Generate a displayName string based on the node.
|
|
259
|
+
*/
|
|
260
|
+
function generateNodeDisplayName(t, node) {
|
|
261
|
+
if (t.isIdentifier(node)) {
|
|
262
|
+
return node.name;
|
|
263
|
+
}
|
|
264
|
+
if (t.isMemberExpression(node)) {
|
|
265
|
+
const objectDisplayName = generateNodeDisplayName(t, node.object);
|
|
266
|
+
const propertyDisplayName = generateNodeDisplayName(t, node.property);
|
|
267
|
+
const res = node.computed
|
|
268
|
+
? `${objectDisplayName}[${propertyDisplayName}]`
|
|
269
|
+
: `${objectDisplayName}.${propertyDisplayName}`;
|
|
270
|
+
return res;
|
|
271
|
+
}
|
|
272
|
+
return "";
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Checks if this path has been previously assigned to a particular value.
|
|
276
|
+
*/
|
|
277
|
+
function hasBeenAssignedPrev(t, assignmentPath, pattern, value) {
|
|
278
|
+
return assignmentPath.getAllPrevSiblings().some((sibling) => {
|
|
279
|
+
const expression = sibling.get("expression");
|
|
280
|
+
if (!t.isAssignmentExpression(expression.node, { operator: "=" })) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
if (!t.isStringLiteral(expression.node.right, { value })) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
return expression.get("left").matchesPattern(pattern);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Checks if this path will be assigned later in the scope.
|
|
291
|
+
*/
|
|
292
|
+
function hasBeenAssignedNext(t, assignmentPath, pattern) {
|
|
293
|
+
return assignmentPath.getAllNextSiblings().some((sibling) => {
|
|
294
|
+
const expression = sibling.get("expression");
|
|
295
|
+
if (!t.isAssignmentExpression(expression.node, { operator: "=" })) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
return expression.get("left").matchesPattern(pattern);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Generate a displayName ExpressionStatement node based on the ids.
|
|
303
|
+
*/
|
|
304
|
+
function createDisplayNameStatement(t, componentIdentifiers, displayName) {
|
|
305
|
+
const node = createMemberExpression(t, componentIdentifiers);
|
|
306
|
+
const expression = t.assignmentExpression("=", t.memberExpression(node, t.identifier("displayName")), t.stringLiteral(displayName));
|
|
307
|
+
const ifStatement = t.ifStatement(t.binaryExpression("!==", t.memberExpression(t.memberExpression(t.identifier("process"), t.identifier("env")), t.identifier("NODE_ENV")), t.stringLiteral("production")), t.expressionStatement(expression));
|
|
308
|
+
return ifStatement;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Helper that creates a MemberExpression node from the ids.
|
|
312
|
+
*/
|
|
313
|
+
function createMemberExpression(t, componentIdentifiers) {
|
|
314
|
+
let node = componentIdentifiers[0].id;
|
|
315
|
+
if (componentIdentifiers.length > 1) {
|
|
316
|
+
for (let i = 1; i < componentIdentifiers.length; i += 1) {
|
|
317
|
+
const { id, computed } = componentIdentifiers[i];
|
|
318
|
+
node = t.memberExpression(node, id, computed);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return node;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Changes the arrow function to a function expression and gives it a name.
|
|
325
|
+
* `name` will be changed to ensure that it is unique within the scope. e.g. `helper` -> `_helper`
|
|
326
|
+
*/
|
|
327
|
+
function setInternalFunctionName(t, path, name) {
|
|
328
|
+
if (!name ||
|
|
329
|
+
("id" in path.node && path.node.id != null) ||
|
|
330
|
+
("key" in path.node && path.node.key != null)) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const id = path.scope.generateUidIdentifier(name);
|
|
334
|
+
if (path.isArrowFunctionExpression()) {
|
|
335
|
+
path.arrowFunctionToExpression();
|
|
336
|
+
}
|
|
337
|
+
// @ts-expect-error Not really an error
|
|
338
|
+
path.node.id = id;
|
|
339
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import nodePath from "node:path";
|
|
2
|
+
import resolve from "resolve/sync.js";
|
|
3
|
+
function toPosixPath(importPath) {
|
|
4
|
+
return nodePath
|
|
5
|
+
.normalize(importPath)
|
|
6
|
+
.split(nodePath.sep)
|
|
7
|
+
.join(nodePath.posix.sep);
|
|
8
|
+
}
|
|
9
|
+
function pathToNodeImportSpecifier(importPath) {
|
|
10
|
+
const normalized = toPosixPath(importPath);
|
|
11
|
+
return normalized.startsWith("/") || normalized.startsWith(".")
|
|
12
|
+
? normalized
|
|
13
|
+
: `./${normalized}`;
|
|
14
|
+
}
|
|
15
|
+
export default function plugin({ types }, { outExtension } = {}) {
|
|
16
|
+
const cache = new Map();
|
|
17
|
+
const extensions = [".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx"];
|
|
18
|
+
const extensionsSet = new Set(extensions);
|
|
19
|
+
function doResolve(importSource, state) {
|
|
20
|
+
const importedPath = importSource.node.value;
|
|
21
|
+
if (extensionsSet.has(nodePath.extname(importedPath)) ||
|
|
22
|
+
importedPath.endsWith(".css") ||
|
|
23
|
+
!importedPath.startsWith(".")) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const importerDir = nodePath.dirname(state.filename);
|
|
27
|
+
const absoluteImportPath = nodePath.resolve(importerDir, importedPath);
|
|
28
|
+
let resolvedPath = cache.get(absoluteImportPath);
|
|
29
|
+
if (!resolvedPath) {
|
|
30
|
+
try {
|
|
31
|
+
resolvedPath = resolve(absoluteImportPath, { extensions });
|
|
32
|
+
if (outExtension &&
|
|
33
|
+
extensionsSet.has(nodePath.extname(resolvedPath))) {
|
|
34
|
+
const dir = nodePath.dirname(resolvedPath);
|
|
35
|
+
const ext = nodePath.extname(resolvedPath);
|
|
36
|
+
const base = nodePath.basename(resolvedPath, ext);
|
|
37
|
+
resolvedPath = nodePath.resolve(dir, base + outExtension);
|
|
38
|
+
}
|
|
39
|
+
cache.set(absoluteImportPath, resolvedPath);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
throw new Error(`Could not resolve "${importedPath}" from "${state.filename}"`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const relativeResolvedPath = nodePath.relative(importerDir, resolvedPath);
|
|
46
|
+
importSource.replaceWith(types.stringLiteral(pathToNodeImportSpecifier(relativeResolvedPath)));
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
visitor: {
|
|
50
|
+
ImportDeclaration(path, state) {
|
|
51
|
+
doResolve(path.get("source"), state);
|
|
52
|
+
},
|
|
53
|
+
ExportNamedDeclaration(path, state) {
|
|
54
|
+
if (path.get("source").isStringLiteral())
|
|
55
|
+
doResolve(path.get("source"), state);
|
|
56
|
+
},
|
|
57
|
+
ExportAllDeclaration(path, state) {
|
|
58
|
+
doResolve(path.get("source"), state);
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
disallowAmbiguousJSXLike?: boolean;
|
|
3
|
+
dts?: boolean;
|
|
4
|
+
isTSX?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const _default: (api: object, options: Options | null | undefined, dirname: string) => import("@babel/core").PluginObj<import("@babel/core").PluginPass>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
3
|
+
export default declare((api, opts) => {
|
|
4
|
+
api.assertVersion("^7.0.0-0 || ^8.0.0");
|
|
5
|
+
const { disallowAmbiguousJSXLike, dts } = opts;
|
|
6
|
+
return {
|
|
7
|
+
name: "syntax-typescript",
|
|
8
|
+
manipulateOptions(opts, parserOpts) {
|
|
9
|
+
parserOpts.plugins.push([
|
|
10
|
+
"typescript",
|
|
11
|
+
{ disallowAmbiguousJSXLike, dts },
|
|
12
|
+
]);
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { types as t } from "@babel/core";
|
|
2
|
+
declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => {
|
|
3
|
+
name: string;
|
|
4
|
+
visitor: {
|
|
5
|
+
ExportDefaultDeclaration(this: import("@babel/core").PluginPass, { node }: import("@babel/traverse").NodePath<t.ExportDefaultDeclaration>, state: import("@babel/core").PluginPass): void;
|
|
6
|
+
CallExpression(this: import("@babel/core").PluginPass, path: import("@babel/traverse").NodePath<t.CallExpression>): void;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { types as t } from "@babel/core";
|
|
4
|
+
export default declare((api) => {
|
|
5
|
+
api.assertVersion(7);
|
|
6
|
+
function addDisplayName(id, call) {
|
|
7
|
+
const props = call.arguments[0].properties;
|
|
8
|
+
let safe = true;
|
|
9
|
+
for (let i = 0; i < props.length; i++) {
|
|
10
|
+
const prop = props[i];
|
|
11
|
+
if (t.isSpreadElement(prop)) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const key = t.toComputedKey(prop);
|
|
15
|
+
if (t.isStringLiteral(key, { value: "displayName" })) {
|
|
16
|
+
safe = false;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (safe) {
|
|
21
|
+
props.unshift(t.objectProperty(t.identifier("displayName"), t.stringLiteral(id)));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const isCreateClassCallExpression = t.buildMatchMemberExpression("React.createClass");
|
|
25
|
+
const isCreateClassAddon = (callee) => t.isIdentifier(callee, { name: "createReactClass" });
|
|
26
|
+
function isCreateClass(node) {
|
|
27
|
+
if (!node || !t.isCallExpression(node))
|
|
28
|
+
return false;
|
|
29
|
+
// not createReactClass nor React.createClass call member object
|
|
30
|
+
if (!isCreateClassCallExpression(node.callee) &&
|
|
31
|
+
!isCreateClassAddon(node.callee)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// no call arguments
|
|
35
|
+
const args = node.arguments;
|
|
36
|
+
if (args.length !== 1)
|
|
37
|
+
return false;
|
|
38
|
+
// first node arg is not an object
|
|
39
|
+
const first = args[0];
|
|
40
|
+
if (!t.isObjectExpression(first))
|
|
41
|
+
return false;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
name: "transform-react-display-name",
|
|
46
|
+
visitor: {
|
|
47
|
+
ExportDefaultDeclaration({ node }, state) {
|
|
48
|
+
if (isCreateClass(node.declaration)) {
|
|
49
|
+
const filename = state.filename || "unknown";
|
|
50
|
+
let displayName = path.basename(filename, path.extname(filename));
|
|
51
|
+
// ./{module name}/index.js
|
|
52
|
+
if (displayName === "index") {
|
|
53
|
+
displayName = path.basename(path.dirname(filename));
|
|
54
|
+
}
|
|
55
|
+
addDisplayName(displayName, node.declaration);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
CallExpression(path) {
|
|
59
|
+
const { node } = path;
|
|
60
|
+
if (!isCreateClass(node))
|
|
61
|
+
return;
|
|
62
|
+
let id;
|
|
63
|
+
// crawl up the ancestry looking for possible candidates for displayName inference
|
|
64
|
+
path.find(function (path) {
|
|
65
|
+
if (path.isAssignmentExpression()) {
|
|
66
|
+
id = path.node.left;
|
|
67
|
+
}
|
|
68
|
+
else if (path.isObjectProperty()) {
|
|
69
|
+
id = path.node.key;
|
|
70
|
+
}
|
|
71
|
+
else if (path.isVariableDeclarator()) {
|
|
72
|
+
id = path.node.id;
|
|
73
|
+
}
|
|
74
|
+
else if (path.isStatement()) {
|
|
75
|
+
// we've hit a statement, we should stop crawling up
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
// we've got an id! no need to continue
|
|
79
|
+
if (id)
|
|
80
|
+
return true;
|
|
81
|
+
return false;
|
|
82
|
+
});
|
|
83
|
+
// ensure that we have an identifier we can inherit from
|
|
84
|
+
if (!id)
|
|
85
|
+
return;
|
|
86
|
+
// foo.bar -> bar
|
|
87
|
+
if (t.isMemberExpression(id)) {
|
|
88
|
+
id = id.property;
|
|
89
|
+
}
|
|
90
|
+
// identifiers are the only thing we can reliably get a name from
|
|
91
|
+
if (t.isIdentifier(id)) {
|
|
92
|
+
addDisplayName(id.name, node);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { types as t, type NodePath } from "@babel/core";
|
|
2
|
+
declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => {
|
|
3
|
+
name: string;
|
|
4
|
+
visitor: {
|
|
5
|
+
CallExpression(this: import("@babel/core").PluginPass, path: NodePath<t.CallExpression>): void;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
2
|
+
import annotateAsPure from "../helper/annotate-as-pure";
|
|
3
|
+
import { types as t } from "@babel/core";
|
|
4
|
+
// Mapping of React top-level methods that are pure.
|
|
5
|
+
// This plugin adds a /*#__PURE__#/ annotation to calls to these methods,
|
|
6
|
+
// so that terser and other minifiers can safely remove them during dead
|
|
7
|
+
// code elimination.
|
|
8
|
+
// See https://reactjs.org/docs/react-api.html
|
|
9
|
+
const PURE_CALLS = [
|
|
10
|
+
[
|
|
11
|
+
"react",
|
|
12
|
+
new Set([
|
|
13
|
+
"cloneElement",
|
|
14
|
+
"createContext",
|
|
15
|
+
"createElement",
|
|
16
|
+
"createFactory",
|
|
17
|
+
"createRef",
|
|
18
|
+
"forwardRef",
|
|
19
|
+
"isValidElement",
|
|
20
|
+
"memo",
|
|
21
|
+
"lazy",
|
|
22
|
+
]),
|
|
23
|
+
],
|
|
24
|
+
["react-dom", new Set(["createPortal"])],
|
|
25
|
+
];
|
|
26
|
+
export default declare((api) => {
|
|
27
|
+
api.assertVersion(7);
|
|
28
|
+
return {
|
|
29
|
+
name: "transform-react-pure-annotations",
|
|
30
|
+
visitor: {
|
|
31
|
+
CallExpression(path) {
|
|
32
|
+
if (isReactCall(path)) {
|
|
33
|
+
annotateAsPure(path);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
function isReactCall(path) {
|
|
40
|
+
// If the callee is not a member expression, then check if it matches
|
|
41
|
+
// a named import, e.g. `import {forwardRef} from 'react'`.
|
|
42
|
+
const calleePath = path.get("callee");
|
|
43
|
+
if (!calleePath.isMemberExpression()) {
|
|
44
|
+
for (const [module, methods] of PURE_CALLS) {
|
|
45
|
+
for (const method of methods) {
|
|
46
|
+
if (calleePath.referencesImport(module, method)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
// Otherwise, check if the member expression's object matches
|
|
54
|
+
// a default import (`import React from 'react'`) or namespace
|
|
55
|
+
// import (`import * as React from 'react'), and check if the
|
|
56
|
+
// property matches one of the pure methods.
|
|
57
|
+
const object = calleePath.get("object");
|
|
58
|
+
const callee = calleePath.node;
|
|
59
|
+
if (!callee.computed && t.isIdentifier(callee.property)) {
|
|
60
|
+
const propertyName = callee.property.name;
|
|
61
|
+
for (const [module, methods] of PURE_CALLS) {
|
|
62
|
+
if (object.referencesImport(module, "default") ||
|
|
63
|
+
object.referencesImport(module, "*")) {
|
|
64
|
+
return methods.has(propertyName);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "babel-plugin-transform-remove-imports";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "babel-plugin-transform-remove-imports";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "@babel/plugin-transform-runtime";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "@babel/plugin-transform-runtime";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
development?: boolean;
|
|
3
|
+
developmentSourceSelf?: boolean;
|
|
4
|
+
importSource?: string;
|
|
5
|
+
pragma?: string;
|
|
6
|
+
pragmaFrag?: string;
|
|
7
|
+
pure?: string;
|
|
8
|
+
runtime?: "automatic" | "classic";
|
|
9
|
+
throwIfNamespace?: boolean;
|
|
10
|
+
useBuiltIns?: boolean;
|
|
11
|
+
useSpread?: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare const _default: (api: object, options: Options | null | undefined, dirname: string) => import("@babel/core").PluginObj<import("@babel/core").PluginPass>;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
2
|
+
import transformReactJSX from "@babel/plugin-transform-react-jsx";
|
|
3
|
+
import createReactJSXPlugin from "@babel/plugin-transform-react-jsx/lib/create-plugin";
|
|
4
|
+
import transformReactDisplayName from "../../plugin/transform-react-display-name";
|
|
5
|
+
import transformReactPure from "../../plugin/transform-react-pure-annotations";
|
|
6
|
+
import normalizeOptions from "./normalize-options";
|
|
7
|
+
export default declare((api, opts) => {
|
|
8
|
+
api.assertVersion("7");
|
|
9
|
+
const { development = api.env((env) => env === "development"), developmentSourceSelf, importSource, pragma, pragmaFrag, pure, runtime, throwIfNamespace, } = normalizeOptions(opts);
|
|
10
|
+
return {
|
|
11
|
+
visitor: {},
|
|
12
|
+
plugins: [
|
|
13
|
+
[
|
|
14
|
+
development
|
|
15
|
+
? createReactJSXPlugin({
|
|
16
|
+
name: "transform-react-jsx/development",
|
|
17
|
+
development: true,
|
|
18
|
+
developmentSourceSelf,
|
|
19
|
+
})
|
|
20
|
+
: transformReactJSX,
|
|
21
|
+
{
|
|
22
|
+
importSource,
|
|
23
|
+
pragma,
|
|
24
|
+
pragmaFrag,
|
|
25
|
+
runtime,
|
|
26
|
+
throwIfNamespace,
|
|
27
|
+
pure,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
transformReactDisplayName,
|
|
31
|
+
pure !== false && transformReactPure,
|
|
32
|
+
].filter(Boolean),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { OptionValidator, findSuggestion } from "../../helper/validator-option";
|
|
2
|
+
const v = new OptionValidator("@babel/preset-react");
|
|
3
|
+
export default function normalizeOptions(options = {}) {
|
|
4
|
+
if ("useSpread" in options) {
|
|
5
|
+
throw new Error('@babel/preset-react: Since Babel 8, an inline object with spread elements is always used, and the "useSpread" option is no longer available. Please remove it from your config.');
|
|
6
|
+
}
|
|
7
|
+
if ("useBuiltIns" in options) {
|
|
8
|
+
const useBuiltInsFormatted = JSON.stringify(options.useBuiltIns);
|
|
9
|
+
throw new Error(`@babel/preset-react: Since "useBuiltIns" is removed in Babel 8, you can remove it from the config.
|
|
10
|
+
- Babel 8 now transforms JSX spread to object spread. If you need to transpile object spread with
|
|
11
|
+
\`useBuiltIns: ${useBuiltInsFormatted}\`, you can use the following config
|
|
12
|
+
{
|
|
13
|
+
"plugins": [
|
|
14
|
+
["@babel/plugin-transform-object-rest-spread", { "loose": true, "useBuiltIns": ${useBuiltInsFormatted} }]
|
|
15
|
+
],
|
|
16
|
+
"presets": ["@babel/preset-react"]
|
|
17
|
+
}`);
|
|
18
|
+
}
|
|
19
|
+
const TopLevelOptions = {
|
|
20
|
+
development: "development",
|
|
21
|
+
developmentSourceSelf: "developmentSourceSelf",
|
|
22
|
+
importSource: "importSource",
|
|
23
|
+
pragma: "pragma",
|
|
24
|
+
pragmaFrag: "pragmaFrag",
|
|
25
|
+
pure: "pure",
|
|
26
|
+
runtime: "runtime",
|
|
27
|
+
throwIfNamespace: "throwIfNamespace",
|
|
28
|
+
};
|
|
29
|
+
v.validateTopLevelOptions(options, TopLevelOptions);
|
|
30
|
+
const development = v.validateBooleanOption(TopLevelOptions.development, options.development);
|
|
31
|
+
const developmentSourceSelf = v.validateBooleanOption(TopLevelOptions.developmentSourceSelf, options.developmentSourceSelf, false);
|
|
32
|
+
let importSource = v.validateStringOption(TopLevelOptions.importSource, options.importSource);
|
|
33
|
+
let pragma = v.validateStringOption(TopLevelOptions.pragma, options.pragma);
|
|
34
|
+
let pragmaFrag = v.validateStringOption(TopLevelOptions.pragmaFrag, options.pragmaFrag);
|
|
35
|
+
const pure = v.validateBooleanOption(TopLevelOptions.pure, options.pure);
|
|
36
|
+
const runtime = v.validateStringOption(TopLevelOptions.runtime, options.runtime, "automatic");
|
|
37
|
+
const throwIfNamespace = v.validateBooleanOption(TopLevelOptions.throwIfNamespace, options.throwIfNamespace, true);
|
|
38
|
+
const validRuntime = ["classic", "automatic"];
|
|
39
|
+
if (runtime === "classic") {
|
|
40
|
+
pragma = pragma || "React.createElement";
|
|
41
|
+
pragmaFrag = pragmaFrag || "React.Fragment";
|
|
42
|
+
}
|
|
43
|
+
else if (runtime === "automatic") {
|
|
44
|
+
importSource = importSource || "react";
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error(`@babel/preset-react: 'runtime' must be one of ['automatic', 'classic'] but we have '${runtime}'\n` +
|
|
48
|
+
`- Did you mean '${findSuggestion(runtime, validRuntime)}'?`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
development,
|
|
52
|
+
developmentSourceSelf,
|
|
53
|
+
importSource,
|
|
54
|
+
pragma,
|
|
55
|
+
pragmaFrag,
|
|
56
|
+
pure,
|
|
57
|
+
runtime,
|
|
58
|
+
throwIfNamespace,
|
|
59
|
+
};
|
|
60
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ssets/babel",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Babel for SSE SSE UI Builder",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./plugin/*": {
|
|
8
|
+
"import": "./dist/plugin/*.js",
|
|
9
|
+
"types": "./dist/plugin/*.d.ts"
|
|
10
|
+
},
|
|
11
|
+
"./preset/*": {
|
|
12
|
+
"import": "./dist/preset/*.js",
|
|
13
|
+
"types": "./dist/preset/*.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.build.json"
|
|
21
|
+
},
|
|
22
|
+
"author": "SSE Official",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@babel/core": "^7.29.0",
|
|
26
|
+
"@babel/helper-plugin-utils": "^7.28.6",
|
|
27
|
+
"@babel/plugin-transform-react-jsx": "^7.28.6",
|
|
28
|
+
"@babel/plugin-transform-runtime": "^7.29.0",
|
|
29
|
+
"@babel/preset-env": "^7.29.0",
|
|
30
|
+
"@babel/types": "^7.29.0",
|
|
31
|
+
"@types/babel__plugin-transform-runtime": "^7.9.5",
|
|
32
|
+
"@types/babel__preset-env": "^7.10.0",
|
|
33
|
+
"babel-plugin-transform-remove-imports": "^1.8.1",
|
|
34
|
+
"resolve": "^1.22.11"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/babel__helper-plugin-utils": "^7.10.3"
|
|
38
|
+
}
|
|
39
|
+
}
|