babel-plugin-essor 0.0.5 → 0.0.6-beta.2
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/LICENSE +1 -1
- package/dist/index.cjs +818 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +17 -3
- package/dist/index.js +816 -4
- package/dist/index.js.map +1 -1
- package/package.json +21 -41
package/dist/index.js
CHANGED
|
@@ -1,8 +1,820 @@
|
|
|
1
|
+
// src/jsx/server.ts
|
|
2
|
+
import { types as t3 } from "@babel/core";
|
|
3
|
+
|
|
4
|
+
// src/program.ts
|
|
5
|
+
import { types as t } from "@babel/core";
|
|
6
|
+
var imports = /* @__PURE__ */ new Set();
|
|
7
|
+
var transformProgram = {
|
|
8
|
+
enter(path, state) {
|
|
9
|
+
path.state = {
|
|
10
|
+
h: path.scope.generateUidIdentifier("h$"),
|
|
11
|
+
ssrtmpl: path.scope.generateUidIdentifier("ssrtmpl$"),
|
|
12
|
+
ssr: path.scope.generateUidIdentifier("ssr$"),
|
|
13
|
+
template: path.scope.generateUidIdentifier("template$"),
|
|
14
|
+
useSignal: path.scope.generateUidIdentifier("signal$"),
|
|
15
|
+
useComputed: path.scope.generateUidIdentifier("computed$"),
|
|
16
|
+
tmplDeclaration: t.variableDeclaration("const", []),
|
|
17
|
+
opts: state.opts
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
exit(path) {
|
|
21
|
+
const state = path.state;
|
|
22
|
+
if (state.tmplDeclaration.declarations.length > 0) {
|
|
23
|
+
const index = path.node.body.findIndex(
|
|
24
|
+
(node) => !t.isImportDeclaration(node) && !t.isExportDeclaration(node)
|
|
25
|
+
);
|
|
26
|
+
path.node.body.splice(index, 0, state.tmplDeclaration);
|
|
27
|
+
}
|
|
28
|
+
if (imports.size > 0) {
|
|
29
|
+
path.node.body.unshift(createImport(state, "essor"));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
function createImport(state, from) {
|
|
34
|
+
const ImportSpecifier = [];
|
|
35
|
+
imports.forEach((name) => {
|
|
36
|
+
const local = t.identifier(state[name].name);
|
|
37
|
+
const imported = t.identifier(name);
|
|
38
|
+
ImportSpecifier.push(t.importSpecifier(local, imported));
|
|
39
|
+
});
|
|
40
|
+
const importSource = t.stringLiteral(from);
|
|
41
|
+
return t.importDeclaration(ImportSpecifier, importSource);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/jsx/constants.ts
|
|
45
|
+
var selfClosingTags = [
|
|
46
|
+
"area",
|
|
47
|
+
"base",
|
|
48
|
+
"br",
|
|
49
|
+
"col",
|
|
50
|
+
"embed",
|
|
51
|
+
"hr",
|
|
52
|
+
"img",
|
|
53
|
+
"input",
|
|
54
|
+
"link",
|
|
55
|
+
"meta",
|
|
56
|
+
"param",
|
|
57
|
+
"source",
|
|
58
|
+
"track",
|
|
59
|
+
"wbr"
|
|
60
|
+
];
|
|
61
|
+
var svgTags = [
|
|
62
|
+
"circle",
|
|
63
|
+
"clipPath",
|
|
64
|
+
"defs",
|
|
65
|
+
"ellipse",
|
|
66
|
+
"filter",
|
|
67
|
+
"g",
|
|
68
|
+
"line",
|
|
69
|
+
"linearGradient",
|
|
70
|
+
"mask",
|
|
71
|
+
"path",
|
|
72
|
+
"pattern",
|
|
73
|
+
"polygon",
|
|
74
|
+
"polyline",
|
|
75
|
+
"radialGradient",
|
|
76
|
+
"rect",
|
|
77
|
+
"stop",
|
|
78
|
+
"symbol",
|
|
79
|
+
"text",
|
|
80
|
+
"use"
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
// src/jsx/client.ts
|
|
84
|
+
import { types as t2 } from "@babel/core";
|
|
85
|
+
function transformJSXClient(path) {
|
|
86
|
+
const result = {
|
|
87
|
+
index: 1,
|
|
88
|
+
isLastChild: false,
|
|
89
|
+
parentIndex: 0,
|
|
90
|
+
props: {},
|
|
91
|
+
template: ""
|
|
92
|
+
};
|
|
93
|
+
transformJSXElement(path, result, true);
|
|
94
|
+
path.replaceWith(createEssorNode(path, result));
|
|
95
|
+
}
|
|
96
|
+
function createEssorNode(path, result) {
|
|
97
|
+
var _a;
|
|
98
|
+
const state = path.state;
|
|
99
|
+
let tmpl;
|
|
100
|
+
if (path.isJSXElement() && isComponent(getTagName(path.node))) {
|
|
101
|
+
tmpl = t2.identifier(getTagName(path.node));
|
|
102
|
+
} else {
|
|
103
|
+
tmpl = path.scope.generateUidIdentifier("_tmpl$");
|
|
104
|
+
const template = t2.callExpression(state.template, [t2.stringLiteral(result.template)]);
|
|
105
|
+
const declarator = t2.variableDeclarator(tmpl, template);
|
|
106
|
+
state.tmplDeclaration.declarations.push(declarator);
|
|
107
|
+
imports.add("template");
|
|
108
|
+
}
|
|
109
|
+
const args = [tmpl, createProps(result.props)];
|
|
110
|
+
const key = result.props.key || ((_a = result.props[0]) == null ? void 0 : _a.key);
|
|
111
|
+
if (key) {
|
|
112
|
+
args.push(key);
|
|
113
|
+
}
|
|
114
|
+
imports.add("h");
|
|
115
|
+
return t2.callExpression(state.h, args);
|
|
116
|
+
}
|
|
117
|
+
function createProps(props) {
|
|
118
|
+
const toAstNode = (value) => {
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
return t2.arrayExpression(value.map(toAstNode));
|
|
121
|
+
}
|
|
122
|
+
if (value && typeof value === "object" && !t2.isNode(value)) {
|
|
123
|
+
return createProps(value);
|
|
124
|
+
}
|
|
125
|
+
switch (typeof value) {
|
|
126
|
+
case "string":
|
|
127
|
+
return t2.stringLiteral(value);
|
|
128
|
+
case "number":
|
|
129
|
+
return t2.numericLiteral(value);
|
|
130
|
+
case "boolean":
|
|
131
|
+
return t2.booleanLiteral(value);
|
|
132
|
+
case "undefined":
|
|
133
|
+
return t2.tsUndefinedKeyword();
|
|
134
|
+
case void 0:
|
|
135
|
+
return t2.tsUndefinedKeyword();
|
|
136
|
+
case null:
|
|
137
|
+
return t2.nullLiteral();
|
|
138
|
+
default:
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const result = Object.keys(props).filter((prop) => prop !== "key").map((prop) => {
|
|
143
|
+
const value = toAstNode(props[prop]);
|
|
144
|
+
return prop === "_$spread$" ? t2.spreadElement(value) : t2.objectProperty(t2.stringLiteral(prop), value);
|
|
145
|
+
});
|
|
146
|
+
return t2.objectExpression(result);
|
|
147
|
+
}
|
|
148
|
+
function transformJSXElement(path, result, isRoot = false) {
|
|
149
|
+
if (path.isJSXElement()) {
|
|
150
|
+
const tagName = getTagName(path.node);
|
|
151
|
+
const tagIsComponent = isComponent(tagName);
|
|
152
|
+
const isSelfClose = !tagIsComponent && selfClosingTags.includes(tagName);
|
|
153
|
+
const isSvg = svgTags.includes(tagName) && result.index === 1;
|
|
154
|
+
const props = getAttrProps(path);
|
|
155
|
+
if (tagIsComponent) {
|
|
156
|
+
if (isRoot) {
|
|
157
|
+
result.props = props;
|
|
158
|
+
const children = getChildren(path);
|
|
159
|
+
if (children.length > 0) {
|
|
160
|
+
const childrenGenerator = children.length === 1 ? children[0] : t2.arrayExpression(children);
|
|
161
|
+
result.props.children = childrenGenerator;
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
transformJSXClient(path);
|
|
165
|
+
replaceChild(path.node, result);
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
if (isSvg) {
|
|
169
|
+
result.template = "<svg _svg_>";
|
|
170
|
+
}
|
|
171
|
+
result.template += `<${tagName}`;
|
|
172
|
+
handleAttributes(props, result);
|
|
173
|
+
result.template += isSelfClose ? "/>" : ">";
|
|
174
|
+
if (!isSelfClose) {
|
|
175
|
+
transformChildren(path, result);
|
|
176
|
+
result.template += `</${tagName}>`;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
result.index--;
|
|
181
|
+
transformChildren(path, result);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function transformChildren(path, result) {
|
|
185
|
+
const parentIndex = result.index;
|
|
186
|
+
path.get("children").reduce((pre, cur) => {
|
|
187
|
+
if (isValidChild(cur)) {
|
|
188
|
+
const lastChild = pre.at(-1);
|
|
189
|
+
if (lastChild && isTextChild(cur) && isTextChild(lastChild)) {
|
|
190
|
+
setNodeText(lastChild, getNodeText(lastChild) + getNodeText(cur));
|
|
191
|
+
} else {
|
|
192
|
+
pre.push(cur);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return pre;
|
|
196
|
+
}, []).forEach((child, i, arr) => {
|
|
197
|
+
result.parentIndex = parentIndex;
|
|
198
|
+
result.isLastChild = i === arr.length - 1;
|
|
199
|
+
transformChild(child, result);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function transformChild(child, result) {
|
|
203
|
+
result.index++;
|
|
204
|
+
if (child.isJSXElement() || child.isJSXFragment()) {
|
|
205
|
+
transformJSXElement(child, result, false);
|
|
206
|
+
} else if (child.isJSXExpressionContainer()) {
|
|
207
|
+
const expression = child.get("expression");
|
|
208
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
209
|
+
result.template += String(expression.node.value);
|
|
210
|
+
} else if (expression.isExpression()) {
|
|
211
|
+
replaceChild(expression.node, result);
|
|
212
|
+
} else {
|
|
213
|
+
throw new Error("Unsupported child type");
|
|
214
|
+
}
|
|
215
|
+
} else if (child.isJSXText()) {
|
|
216
|
+
result.template += String(child.node.value);
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error("Unsupported child type");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function getNodeText(path) {
|
|
222
|
+
if (path.isJSXText()) {
|
|
223
|
+
return path.node.value;
|
|
224
|
+
}
|
|
225
|
+
if (path.isJSXExpressionContainer()) {
|
|
226
|
+
const expression = path.get("expression");
|
|
227
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
228
|
+
return String(expression.node.value);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return "";
|
|
232
|
+
}
|
|
233
|
+
function setNodeText(path, text) {
|
|
234
|
+
if (path.isJSXText()) {
|
|
235
|
+
path.node.value = text;
|
|
236
|
+
}
|
|
237
|
+
if (path.isJSXExpressionContainer()) {
|
|
238
|
+
const expression = path.get("expression");
|
|
239
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
240
|
+
expression.replaceWith(t2.stringLiteral(text));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function isTextChild(path) {
|
|
245
|
+
if (path.isJSXExpressionContainer()) {
|
|
246
|
+
const expression = path.get("expression");
|
|
247
|
+
if (expression.isJSXText() || expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (path.isJSXText() || path.isStringLiteral() || path.isNullLiteral()) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
function handleAttributes(props, result) {
|
|
257
|
+
let klass = "";
|
|
258
|
+
let style = "";
|
|
259
|
+
for (const prop in props) {
|
|
260
|
+
const value = props[prop];
|
|
261
|
+
if (prop === "class" && typeof value === "string") {
|
|
262
|
+
klass += ` ${value}`;
|
|
263
|
+
delete props[prop];
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (prop.indexOf("class:") === 0) {
|
|
267
|
+
if (value === true) {
|
|
268
|
+
const name = prop.replace(/^class:/, "");
|
|
269
|
+
klass += ` ${name}`;
|
|
270
|
+
delete props[prop];
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (value === false) {
|
|
274
|
+
delete props[prop];
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (prop === "style" && typeof value === "string") {
|
|
279
|
+
style += `${value}${value.at(-1) === ";" ? "" : ";"}`;
|
|
280
|
+
delete props[prop];
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (prop.indexOf("style:") === 0 && (typeof value === "string" || typeof value === "number")) {
|
|
284
|
+
const name = prop.replace(/^style:/, "");
|
|
285
|
+
style += `${name}:${value};`;
|
|
286
|
+
delete props[prop];
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (value === true) {
|
|
290
|
+
result.template += ` ${prop}`;
|
|
291
|
+
delete props[prop];
|
|
292
|
+
}
|
|
293
|
+
if (value === false) {
|
|
294
|
+
delete props[prop];
|
|
295
|
+
}
|
|
296
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
297
|
+
result.template += ` ${prop}="${value}"`;
|
|
298
|
+
delete props[prop];
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (Object.keys(props).length > 0) {
|
|
302
|
+
result.props[result.index] = props;
|
|
303
|
+
}
|
|
304
|
+
klass = klass.trim();
|
|
305
|
+
style = style.trim();
|
|
306
|
+
if (klass) {
|
|
307
|
+
result.template += ` class="${klass}"`;
|
|
308
|
+
}
|
|
309
|
+
if (style) {
|
|
310
|
+
result.template += ` style="${style}"`;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function replaceChild(node, result) {
|
|
314
|
+
var _a, _b, _c, _d, _e;
|
|
315
|
+
if (result.isLastChild) {
|
|
316
|
+
result.index--;
|
|
317
|
+
} else {
|
|
318
|
+
result.template += "<!-->";
|
|
319
|
+
}
|
|
320
|
+
(_c = (_a = result.props)[_b = result.parentIndex]) != null ? _c : _a[_b] = {};
|
|
321
|
+
(_e = (_d = result.props[result.parentIndex]).children) != null ? _e : _d.children = [];
|
|
322
|
+
result.props[result.parentIndex].children.push(
|
|
323
|
+
t2.arrayExpression([
|
|
324
|
+
t2.arrowFunctionExpression([], node),
|
|
325
|
+
result.isLastChild ? t2.nullLiteral() : t2.identifier(String(result.index))
|
|
326
|
+
])
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
function getChildren(path) {
|
|
330
|
+
return path.get("children").filter((child) => isValidChild(child)).map((child) => {
|
|
331
|
+
if (child.isJSXElement() || child.isJSXFragment()) {
|
|
332
|
+
transformJSXClient(child);
|
|
333
|
+
} else if (child.isJSXExpressionContainer()) {
|
|
334
|
+
child.replaceWith(child.get("expression"));
|
|
335
|
+
} else if (child.isJSXText()) {
|
|
336
|
+
child.replaceWith(t2.stringLiteral(child.node.value));
|
|
337
|
+
} else {
|
|
338
|
+
throw new Error("Unsupported child type");
|
|
339
|
+
}
|
|
340
|
+
return child.node;
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function isValidChild(path) {
|
|
344
|
+
const regex = /^\s*$/;
|
|
345
|
+
if (path.isStringLiteral() || path.isJSXText()) {
|
|
346
|
+
return !regex.test(path.node.value);
|
|
347
|
+
}
|
|
348
|
+
return Object.keys(path.node).length > 0;
|
|
349
|
+
}
|
|
350
|
+
function getAttrProps(path) {
|
|
351
|
+
const props = {};
|
|
352
|
+
path.get("openingElement").get("attributes").forEach((attribute) => {
|
|
353
|
+
if (attribute.isJSXAttribute()) {
|
|
354
|
+
const name = getAttrName(attribute.node);
|
|
355
|
+
const value = attribute.get("value");
|
|
356
|
+
if (!value.node) {
|
|
357
|
+
props[name] = true;
|
|
358
|
+
} else if (value.isStringLiteral()) {
|
|
359
|
+
props[name] = value.node.value;
|
|
360
|
+
} else {
|
|
361
|
+
if (value.isJSXExpressionContainer()) {
|
|
362
|
+
const expression = value.get("expression");
|
|
363
|
+
if (expression.isStringLiteral()) {
|
|
364
|
+
props[name] = expression.node.value;
|
|
365
|
+
} else if (expression.isNumericLiteral()) {
|
|
366
|
+
props[name] = expression.node.value;
|
|
367
|
+
} else if (expression.isJSXElement() || expression.isJSXFragment()) {
|
|
368
|
+
transformJSXClient(expression);
|
|
369
|
+
props[name] = expression.node;
|
|
370
|
+
} else if (expression.isExpression()) {
|
|
371
|
+
if (/^key|ref|on.+$/.test(name)) {
|
|
372
|
+
props[name] = expression.node;
|
|
373
|
+
} else if (/^bind:.+/.test(name)) {
|
|
374
|
+
props[name] = t2.arrowFunctionExpression([], expression.node);
|
|
375
|
+
} else {
|
|
376
|
+
if (expression.isConditionalExpression()) {
|
|
377
|
+
props[name] = t2.arrowFunctionExpression([], expression.node);
|
|
378
|
+
} else {
|
|
379
|
+
props[name] = expression.node;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
} else if (value.isJSXElement() || value.isJSXFragment()) {
|
|
384
|
+
transformJSXClient(value);
|
|
385
|
+
props[name] = value.node;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
} else if (attribute.isJSXSpreadAttribute()) {
|
|
389
|
+
props._$spread$ = attribute.get("argument").node;
|
|
390
|
+
} else {
|
|
391
|
+
throw new Error("Unsupported attribute type");
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
return props;
|
|
395
|
+
}
|
|
396
|
+
function getAttrName(attribute) {
|
|
397
|
+
if (t2.isJSXIdentifier(attribute.name)) {
|
|
398
|
+
return attribute.name.name;
|
|
399
|
+
}
|
|
400
|
+
if (t2.isJSXNamespacedName(attribute.name)) {
|
|
401
|
+
return `${attribute.name.namespace.name}:${attribute.name.name.name}`;
|
|
402
|
+
}
|
|
403
|
+
throw new Error("Unsupported attribute type");
|
|
404
|
+
}
|
|
405
|
+
function isComponent(tagName) {
|
|
406
|
+
return tagName[0] && tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".") || /[^A-Za-z]/.test(tagName[0]);
|
|
407
|
+
}
|
|
408
|
+
function getTagName(node) {
|
|
409
|
+
const tag = node.openingElement.name;
|
|
410
|
+
return jsxElementNameToString(tag);
|
|
411
|
+
}
|
|
412
|
+
function jsxElementNameToString(node) {
|
|
413
|
+
if (t2.isJSXMemberExpression(node)) {
|
|
414
|
+
return `${jsxElementNameToString(node.object)}.${jsxElementNameToString(node.property)}`;
|
|
415
|
+
}
|
|
416
|
+
if (t2.isJSXIdentifier(node) || t2.isIdentifier(node)) {
|
|
417
|
+
return node.name;
|
|
418
|
+
}
|
|
419
|
+
return `${node.namespace.name}:${node.name.name}`;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/jsx/server.ts
|
|
423
|
+
function transformJSXService(path) {
|
|
424
|
+
const result = {
|
|
425
|
+
index: 0,
|
|
426
|
+
isLastChild: false,
|
|
427
|
+
parentIndex: 0,
|
|
428
|
+
props: {},
|
|
429
|
+
template: []
|
|
430
|
+
// 修改为数组
|
|
431
|
+
};
|
|
432
|
+
transformJSXServiceElement(path, result, true);
|
|
433
|
+
path.replaceWith(createEssorNode2(path, result));
|
|
434
|
+
}
|
|
435
|
+
function createEssorNode2(path, result) {
|
|
436
|
+
var _a;
|
|
437
|
+
const state = path.state;
|
|
438
|
+
let tmpl;
|
|
439
|
+
if (path.isJSXElement() && isComponent(getTagName(path.node))) {
|
|
440
|
+
tmpl = t3.identifier(getTagName(path.node));
|
|
441
|
+
} else {
|
|
442
|
+
tmpl = path.scope.generateUidIdentifier("_tmpl$");
|
|
443
|
+
const template = t3.callExpression(state.ssrtmpl, [
|
|
444
|
+
t3.arrayExpression(result.template.map(t3.stringLiteral))
|
|
445
|
+
]);
|
|
446
|
+
const declarator = t3.variableDeclarator(tmpl, template);
|
|
447
|
+
state.tmplDeclaration.declarations.push(declarator);
|
|
448
|
+
imports.add("ssrtmpl");
|
|
449
|
+
}
|
|
450
|
+
const args = [tmpl, createProps2(result.props)];
|
|
451
|
+
const key = result.props.key || ((_a = result.props[0]) == null ? void 0 : _a.key);
|
|
452
|
+
if (key) {
|
|
453
|
+
args.push(key);
|
|
454
|
+
}
|
|
455
|
+
imports.add("ssr");
|
|
456
|
+
return t3.callExpression(state.ssr, args);
|
|
457
|
+
}
|
|
458
|
+
function createProps2(props) {
|
|
459
|
+
const result = [];
|
|
460
|
+
for (const prop in props) {
|
|
461
|
+
let value = props[prop];
|
|
462
|
+
if (prop === "key") {
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (Array.isArray(value)) {
|
|
466
|
+
value = t3.arrayExpression(value);
|
|
467
|
+
}
|
|
468
|
+
if (typeof value === "object" && value !== null && !t3.isNode(value)) {
|
|
469
|
+
value = createProps2(value);
|
|
470
|
+
}
|
|
471
|
+
if (typeof value === "string") {
|
|
472
|
+
value = t3.stringLiteral(value);
|
|
473
|
+
}
|
|
474
|
+
if (typeof value === "number") {
|
|
475
|
+
value = t3.numericLiteral(value);
|
|
476
|
+
}
|
|
477
|
+
if (typeof value === "boolean") {
|
|
478
|
+
value = t3.booleanLiteral(value);
|
|
479
|
+
}
|
|
480
|
+
if (value === void 0) {
|
|
481
|
+
value = t3.tsUndefinedKeyword();
|
|
482
|
+
}
|
|
483
|
+
if (value === null) {
|
|
484
|
+
value = t3.nullLiteral();
|
|
485
|
+
}
|
|
486
|
+
if (prop === "_$spread$") {
|
|
487
|
+
result.push(t3.spreadElement(value));
|
|
488
|
+
} else {
|
|
489
|
+
result.push(t3.objectProperty(t3.stringLiteral(prop), value));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return t3.objectExpression(result);
|
|
493
|
+
}
|
|
494
|
+
function transformJSXServiceElement(path, result, isRoot = false) {
|
|
495
|
+
if (path.isJSXElement()) {
|
|
496
|
+
const tagName = getTagName(path.node);
|
|
497
|
+
const tagIsComponent = isComponent(tagName);
|
|
498
|
+
const isSelfClose = !tagIsComponent && selfClosingTags.includes(tagName);
|
|
499
|
+
const isSvg = svgTags.includes(tagName) && result.index === 1;
|
|
500
|
+
const { props, hasExpression } = getAttrProps2(path);
|
|
501
|
+
if (tagIsComponent) {
|
|
502
|
+
if (isRoot) {
|
|
503
|
+
result.props = props;
|
|
504
|
+
const children = getChildren2(path);
|
|
505
|
+
if (children.length > 0) {
|
|
506
|
+
const childrenGenerator = children.length === 1 ? children[0] : t3.arrayExpression(children);
|
|
507
|
+
result.props.children = childrenGenerator;
|
|
508
|
+
}
|
|
509
|
+
} else {
|
|
510
|
+
transformJSXService(path);
|
|
511
|
+
replaceChild2(path.node, result);
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
if (isSvg) {
|
|
515
|
+
result.template.push("<svg _svg_>");
|
|
516
|
+
}
|
|
517
|
+
result.template.push(`<${tagName}`);
|
|
518
|
+
handleAttributes2(props, result);
|
|
519
|
+
if (hasExpression) {
|
|
520
|
+
result.template.push(isSelfClose ? "/>" : ">");
|
|
521
|
+
result.props || (result.props = {});
|
|
522
|
+
} else {
|
|
523
|
+
result.template[result.template.length - 1] += isSelfClose ? "/>" : ">";
|
|
524
|
+
}
|
|
525
|
+
transformChildren2(path, result);
|
|
526
|
+
if (!isSelfClose) {
|
|
527
|
+
result.template.push(`</${tagName}>`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
result.index--;
|
|
532
|
+
transformChildren2(path, result);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function transformChildren2(path, result) {
|
|
536
|
+
const parentIndex = result.template.length;
|
|
537
|
+
path.get("children").reduce((pre, cur) => {
|
|
538
|
+
if (isValidChild2(cur)) {
|
|
539
|
+
const lastChild = pre.at(-1);
|
|
540
|
+
if (lastChild && isTextChild(cur) && isTextChild(lastChild)) {
|
|
541
|
+
setNodeText2(lastChild, getNodeText2(lastChild) + getNodeText2(cur));
|
|
542
|
+
} else {
|
|
543
|
+
pre.push(cur);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return pre;
|
|
547
|
+
}, []).forEach((child, i, arr) => {
|
|
548
|
+
result.parentIndex = parentIndex;
|
|
549
|
+
result.isLastChild = i === arr.length - 1;
|
|
550
|
+
transformChild2(child, result);
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
function transformChild2(child, result) {
|
|
554
|
+
if (child.isJSXElement() || child.isJSXFragment()) {
|
|
555
|
+
transformJSXServiceElement(child, result, false);
|
|
556
|
+
} else if (child.isJSXExpressionContainer()) {
|
|
557
|
+
const expression = child.get("expression");
|
|
558
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
559
|
+
result.template[result.template.length - 1] += String(expression.node.value);
|
|
560
|
+
} else if (expression.isExpression()) {
|
|
561
|
+
replaceChild2(expression.node, result);
|
|
562
|
+
} else {
|
|
563
|
+
throw new Error("Unsupported child type");
|
|
564
|
+
}
|
|
565
|
+
} else if (child.isJSXText()) {
|
|
566
|
+
result.template.push(String(child.node.value));
|
|
567
|
+
} else {
|
|
568
|
+
throw new Error("Unsupported child type");
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
function getNodeText2(path) {
|
|
572
|
+
if (path.isJSXText()) {
|
|
573
|
+
return path.node.value;
|
|
574
|
+
}
|
|
575
|
+
if (path.isJSXExpressionContainer()) {
|
|
576
|
+
const expression = path.get("expression");
|
|
577
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
578
|
+
return String(expression.node.value);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return "";
|
|
582
|
+
}
|
|
583
|
+
function setNodeText2(path, text) {
|
|
584
|
+
if (path.isJSXText()) {
|
|
585
|
+
path.node.value = text;
|
|
586
|
+
}
|
|
587
|
+
if (path.isJSXExpressionContainer()) {
|
|
588
|
+
const expression = path.get("expression");
|
|
589
|
+
if (expression.isStringLiteral() || expression.isNumericLiteral()) {
|
|
590
|
+
expression.replaceWith(t3.stringLiteral(text));
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function handleAttributes2(props, result) {
|
|
595
|
+
let klass = "";
|
|
596
|
+
let style = "";
|
|
597
|
+
for (const prop in props) {
|
|
598
|
+
const value = props[prop];
|
|
599
|
+
if (prop === "class" && typeof value === "string") {
|
|
600
|
+
klass += ` ${value}`;
|
|
601
|
+
delete props[prop];
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (prop.indexOf("class:") === 0) {
|
|
605
|
+
if (value === true) {
|
|
606
|
+
const name = prop.replace(/^class:/, "");
|
|
607
|
+
klass += ` ${name}`;
|
|
608
|
+
delete props[prop];
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
if (value === false) {
|
|
612
|
+
delete props[prop];
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
if (prop === "style" && typeof value === "string") {
|
|
617
|
+
style += `${value}${value.at(-1) === ";" ? "" : ";"}`;
|
|
618
|
+
delete props[prop];
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
if (prop.indexOf("style:") === 0 && (typeof value === "string" || typeof value === "number")) {
|
|
622
|
+
const name = prop.replace(/^style:/, "");
|
|
623
|
+
style += `${name}:${value};`;
|
|
624
|
+
delete props[prop];
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (value === true) {
|
|
628
|
+
result.template[result.template.length - 1] += ` ${prop}`;
|
|
629
|
+
delete props[prop];
|
|
630
|
+
}
|
|
631
|
+
if (value === false) {
|
|
632
|
+
delete props[prop];
|
|
633
|
+
}
|
|
634
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
635
|
+
result.template[result.template.length - 1] += ` ${prop}="${value}"`;
|
|
636
|
+
delete props[prop];
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (Object.keys(props).length > 0) {
|
|
640
|
+
result.props[result.index] = props;
|
|
641
|
+
}
|
|
642
|
+
klass = klass.trim();
|
|
643
|
+
style = style.trim();
|
|
644
|
+
if (klass) {
|
|
645
|
+
result.template[result.template.length - 1] += ` class="${klass}"`;
|
|
646
|
+
}
|
|
647
|
+
if (style) {
|
|
648
|
+
result.template[result.template.length - 1] += ` style="${style}"`;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
function replaceChild2(node, result) {
|
|
652
|
+
var _a, _b, _c, _d, _e;
|
|
653
|
+
if (result.isLastChild) {
|
|
654
|
+
result.index--;
|
|
655
|
+
}
|
|
656
|
+
(_c = (_a = result.props)[_b = result.parentIndex]) != null ? _c : _a[_b] = {};
|
|
657
|
+
(_e = (_d = result.props[result.parentIndex]).children) != null ? _e : _d.children = [];
|
|
658
|
+
result.props[result.parentIndex].children.push(
|
|
659
|
+
t3.arrayExpression([
|
|
660
|
+
t3.arrowFunctionExpression([], node),
|
|
661
|
+
t3.identifier(String(result.template.length))
|
|
662
|
+
])
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
function getChildren2(path) {
|
|
666
|
+
return path.get("children").filter((child) => isValidChild2(child)).map((child) => {
|
|
667
|
+
if (child.isJSXElement() || child.isJSXFragment()) {
|
|
668
|
+
transformJSXService(child);
|
|
669
|
+
} else if (child.isJSXExpressionContainer()) {
|
|
670
|
+
child.replaceWith(child.get("expression"));
|
|
671
|
+
} else if (child.isJSXText()) {
|
|
672
|
+
child.replaceWith(t3.stringLiteral(child.node.value));
|
|
673
|
+
} else {
|
|
674
|
+
throw new Error("Unsupported child type");
|
|
675
|
+
}
|
|
676
|
+
return child.node;
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
function isValidChild2(path) {
|
|
680
|
+
const regex = /^\s*$/;
|
|
681
|
+
if (path.isStringLiteral() || path.isJSXText()) {
|
|
682
|
+
return !regex.test(path.node.value);
|
|
683
|
+
}
|
|
684
|
+
return Object.keys(path.node).length > 0;
|
|
685
|
+
}
|
|
686
|
+
function getAttrProps2(path) {
|
|
687
|
+
const props = {};
|
|
688
|
+
let hasExpression = false;
|
|
689
|
+
path.get("openingElement").get("attributes").forEach((attribute) => {
|
|
690
|
+
if (attribute.isJSXAttribute()) {
|
|
691
|
+
const name = getAttrName(attribute.node);
|
|
692
|
+
const value = attribute.get("value");
|
|
693
|
+
if (!value.node) {
|
|
694
|
+
props[name] = true;
|
|
695
|
+
} else if (value.isStringLiteral()) {
|
|
696
|
+
props[name] = value.node.value;
|
|
697
|
+
} else {
|
|
698
|
+
if (value.isJSXExpressionContainer()) {
|
|
699
|
+
const expression = value.get("expression");
|
|
700
|
+
if (expression.isStringLiteral()) {
|
|
701
|
+
props[name] = expression.node.value;
|
|
702
|
+
} else if (expression.isNumericLiteral()) {
|
|
703
|
+
props[name] = expression.node.value;
|
|
704
|
+
} else if (expression.isJSXElement() || expression.isJSXFragment()) {
|
|
705
|
+
transformJSXService(expression);
|
|
706
|
+
props[name] = expression.node;
|
|
707
|
+
} else if (expression.isExpression()) {
|
|
708
|
+
hasExpression = true;
|
|
709
|
+
if (/^key|ref|on.+$/.test(name)) {
|
|
710
|
+
props[name] = expression.node;
|
|
711
|
+
} else if (/^bind:.+/.test(name)) {
|
|
712
|
+
props[name] = t3.arrowFunctionExpression([], expression.node);
|
|
713
|
+
} else {
|
|
714
|
+
if (expression.isConditionalExpression()) {
|
|
715
|
+
props[name] = t3.arrowFunctionExpression([], expression.node);
|
|
716
|
+
} else {
|
|
717
|
+
props[name] = expression.node;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
} else if (value.isJSXElement() || value.isJSXFragment()) {
|
|
722
|
+
transformJSXService(value);
|
|
723
|
+
props[name] = value.node;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
} else if (attribute.isJSXSpreadAttribute()) {
|
|
727
|
+
props._$spread$ = attribute.get("argument").node;
|
|
728
|
+
hasExpression = true;
|
|
729
|
+
} else {
|
|
730
|
+
throw new Error("Unsupported attribute type");
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
return {
|
|
734
|
+
props,
|
|
735
|
+
hasExpression
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// src/jsx/index.ts
|
|
740
|
+
function transformJSX(path) {
|
|
741
|
+
const state = path.state;
|
|
742
|
+
const isSsr = state.opts.ssr;
|
|
743
|
+
return isSsr ? transformJSXService(path) : transformJSXClient(path);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// src/signal/symbol.ts
|
|
747
|
+
import { types as t4 } from "@babel/core";
|
|
748
|
+
import { cloneNode } from "@babel/types";
|
|
749
|
+
function replaceSymbol(path) {
|
|
750
|
+
const init = path.node.init;
|
|
751
|
+
const variableName = path.node.id.name;
|
|
752
|
+
if (t4.isObjectPattern(path.node.id) || t4.isArrayPattern(path.node.id)) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (!variableName.startsWith("$")) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (init && (t4.isFunctionExpression(init) || t4.isArrowFunctionExpression(init)) && path.parent.kind === "const") {
|
|
759
|
+
const newInit = t4.callExpression(t4.identifier(path.state.useComputed.name), init ? [init] : []);
|
|
760
|
+
imports.add("useComputed");
|
|
761
|
+
path.node.init = newInit;
|
|
762
|
+
} else {
|
|
763
|
+
const originalImportDeclarationNodes = cloneNode(path.get("id").node, true);
|
|
764
|
+
const newInit = t4.callExpression(t4.identifier(path.state.useSignal.name), init ? [init] : []);
|
|
765
|
+
imports.add("useSignal");
|
|
766
|
+
path.node.init = newInit;
|
|
767
|
+
path.scope.rename(variableName, `${variableName}.value`);
|
|
768
|
+
path.get("id").replaceWith(originalImportDeclarationNodes);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// src/signal/import.ts
|
|
773
|
+
import { types as t5 } from "@babel/core";
|
|
774
|
+
function isVariableUsedAsObject(path, variableName) {
|
|
775
|
+
const binding = path.scope.getBinding(variableName);
|
|
776
|
+
let isUsedObject = false;
|
|
777
|
+
if (!binding || !binding.referencePaths) {
|
|
778
|
+
return isUsedObject;
|
|
779
|
+
}
|
|
780
|
+
for (const referencePath of binding.referencePaths) {
|
|
781
|
+
if (t5.isMemberExpression(referencePath.parent)) {
|
|
782
|
+
isUsedObject = true;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return isUsedObject;
|
|
786
|
+
}
|
|
787
|
+
function replaceImportDeclaration(path) {
|
|
788
|
+
const imports2 = path.node.specifiers;
|
|
789
|
+
imports2.forEach((specifier) => {
|
|
790
|
+
const variableName = specifier.local.name;
|
|
791
|
+
if (variableName.indexOf("$") === 0 && !isVariableUsedAsObject(path, variableName)) {
|
|
792
|
+
path.scope.rename(variableName, `${variableName}.value`);
|
|
793
|
+
specifier.local.name = `${variableName}`;
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
|
|
1
798
|
// src/index.ts
|
|
2
|
-
|
|
3
|
-
|
|
799
|
+
function src_default() {
|
|
800
|
+
return {
|
|
801
|
+
name: "babel-plugin-essor",
|
|
802
|
+
manipulateOptions({ filename }, parserOpts) {
|
|
803
|
+
if (filename.endsWith(".ts") || filename.endsWith(".tsx")) {
|
|
804
|
+
parserOpts.plugins.push("typescript");
|
|
805
|
+
}
|
|
806
|
+
parserOpts.plugins.push("jsx");
|
|
807
|
+
},
|
|
808
|
+
visitor: {
|
|
809
|
+
Program: transformProgram,
|
|
810
|
+
JSXElement: transformJSX,
|
|
811
|
+
JSXFragment: transformJSX,
|
|
812
|
+
VariableDeclarator: replaceSymbol,
|
|
813
|
+
ImportDeclaration: replaceImportDeclaration
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
4
817
|
export {
|
|
5
|
-
|
|
6
|
-
two
|
|
818
|
+
src_default as default
|
|
7
819
|
};
|
|
8
820
|
//# sourceMappingURL=index.js.map
|