babel-plugin-essor 0.0.5-beta.7 → 0.0.6-beta.1

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/index.js CHANGED
@@ -1,7 +1,47 @@
1
- // src/transform.ts
1
+ // src/jsx/server.ts
2
+ import { types as t3 } from "@babel/core";
3
+
4
+ // src/program.ts
2
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
+ }
3
43
 
4
- // src/constants.ts
44
+ // src/jsx/constants.ts
5
45
  var selfClosingTags = [
6
46
  "area",
7
47
  "base",
@@ -39,48 +79,10 @@ var svgTags = [
39
79
  "text",
40
80
  "use"
41
81
  ];
42
- var imports = /* @__PURE__ */ new Set();
43
-
44
- // src/transform.ts
45
- var transformProgram = {
46
- enter(path) {
47
- path.state = {
48
- h: path.scope.generateUidIdentifier("h$"),
49
- useSignal: path.scope.generateUidIdentifier("useSignal$"),
50
- useComputed: path.scope.generateUidIdentifier("useComputed$"),
51
- template: path.scope.generateUidIdentifier("template$"),
52
- signalObject: path.scope.generateUidIdentifier("signalObject&"),
53
- tmplDeclaration: t.variableDeclaration("const", [])
54
- };
55
- imports.clear();
56
- },
57
- exit(path) {
58
- const state = path.state;
59
- if (state.tmplDeclaration.declarations.length > 0) {
60
- const index = path.node.body.findIndex(
61
- (node) => !t.isImportDeclaration(node) && !t.isExportDeclaration(node)
62
- );
63
- path.node.body.splice(index, 0, state.tmplDeclaration);
64
- }
65
- if (imports.size > 0) {
66
- path.node.body.unshift(createImport(state, "essor"));
67
- }
68
- }
69
- };
70
- function createImport(state, from) {
71
- const ImportSpecifier = [];
72
- imports.forEach((name) => {
73
- const local = t.identifier(state[name].name);
74
- const imported = t.identifier(name);
75
- ImportSpecifier.push(t.importSpecifier(local, imported));
76
- });
77
- const importSource = t.stringLiteral(from);
78
- return t.importDeclaration(ImportSpecifier, importSource);
79
- }
80
82
 
81
- // src/jsx-transform.ts
83
+ // src/jsx/client.ts
82
84
  import { types as t2 } from "@babel/core";
83
- function transformJSX(path) {
85
+ function transformJSXClient(path) {
84
86
  const result = {
85
87
  index: 1,
86
88
  isLastChild: false,
@@ -88,11 +90,11 @@ function transformJSX(path) {
88
90
  props: {},
89
91
  template: ""
90
92
  };
91
- transformElement(path, result, true);
93
+ transformJSXElement(path, result, true);
92
94
  path.replaceWith(createEssorNode(path, result));
93
95
  }
94
96
  function createEssorNode(path, result) {
95
- var _a, _b;
97
+ var _a;
96
98
  const state = path.state;
97
99
  let tmpl;
98
100
  if (path.isJSXElement() && isComponent(getTagName(path.node))) {
@@ -105,7 +107,7 @@ function createEssorNode(path, result) {
105
107
  imports.add("template");
106
108
  }
107
109
  const args = [tmpl, createProps(result.props)];
108
- const key = (_b = result.props.key) != null ? _b : (_a = result.props[0]) == null ? void 0 : _a.key;
110
+ const key = result.props.key || ((_a = result.props[0]) == null ? void 0 : _a.key);
109
111
  if (key) {
110
112
  args.push(key);
111
113
  }
@@ -113,119 +115,63 @@ function createEssorNode(path, result) {
113
115
  return t2.callExpression(state.h, args);
114
116
  }
115
117
  function createProps(props) {
116
- const result = [];
117
- for (const prop in props) {
118
- let value = props[prop];
119
- if (prop === "key") {
120
- continue;
121
- }
118
+ const toAstNode = (value) => {
122
119
  if (Array.isArray(value)) {
123
- value = t2.arrayExpression(value);
124
- }
125
- if (typeof value === "object" && value !== null && !t2.isNode(value)) {
126
- value = createProps(value);
127
- }
128
- if (typeof value === "string") {
129
- value = t2.stringLiteral(value);
130
- }
131
- if (typeof value === "number") {
132
- value = t2.numericLiteral(value);
133
- }
134
- if (typeof value === "boolean") {
135
- value = t2.booleanLiteral(value);
136
- }
137
- if (value === void 0) {
138
- value = t2.tsUndefinedKeyword();
139
- }
140
- if (value === null) {
141
- value = t2.nullLiteral();
120
+ return t2.arrayExpression(value.map(toAstNode));
142
121
  }
143
- if (prop === "_$spread$") {
144
- result.push(t2.spreadElement(value));
145
- } else {
146
- result.push(t2.objectProperty(t2.stringLiteral(prop), value));
122
+ if (value && typeof value === "object" && !t2.isNode(value)) {
123
+ return createProps(value);
147
124
  }
148
- }
149
- return t2.objectExpression(result);
150
- }
151
- function getAttrProps(path) {
152
- const props = {};
153
- path.get("openingElement").get("attributes").forEach((attribute) => {
154
- if (attribute.isJSXAttribute()) {
155
- const name = getAttrName(attribute.node);
156
- const value = attribute.get("value");
157
- if (!value.node) {
158
- props[name] = true;
159
- } else if (value.isStringLiteral()) {
160
- props[name] = value.node.value;
161
- } else {
162
- if (value.isJSXExpressionContainer()) {
163
- const expression = value.get("expression");
164
- if (expression.isStringLiteral()) {
165
- props[name] = expression.node.value;
166
- } else if (expression.isNumericLiteral()) {
167
- props[name] = expression.node.value;
168
- } else if (expression.isJSXElement() || expression.isJSXFragment()) {
169
- transformJSX(expression);
170
- props[name] = expression.node;
171
- } else if (expression.isExpression()) {
172
- if (/^key|ref|on.+$/.test(name)) {
173
- props[name] = expression.node;
174
- } else if (/^bind:.+/.test(name)) {
175
- props[name] = t2.arrowFunctionExpression([], expression.node);
176
- const value2 = path.scope.generateUidIdentifier("value");
177
- props[`update:${name.slice(5).toLocaleLowerCase()}`] = t2.arrowFunctionExpression(
178
- [value2],
179
- t2.assignmentExpression("=", expression.node, value2)
180
- );
181
- } else {
182
- if (expression.isConditionalExpression()) {
183
- props[name] = t2.arrowFunctionExpression([], expression.node);
184
- } else {
185
- props[name] = expression.node;
186
- }
187
- }
188
- }
189
- } else if (value.isJSXElement() || value.isJSXFragment()) {
190
- transformJSX(value);
191
- props[name] = value.node;
192
- }
193
- }
194
- } else if (attribute.isJSXSpreadAttribute()) {
195
- props._$spread$ = attribute.get("argument").node;
196
- } else {
197
- throw new Error("Unsupported attribute type");
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;
198
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);
199
145
  });
200
- return props;
146
+ return t2.objectExpression(result);
201
147
  }
202
- function transformElement(path, result, isRoot) {
148
+ function transformJSXElement(path, result, isRoot = false) {
203
149
  if (path.isJSXElement()) {
204
150
  const tagName = getTagName(path.node);
205
151
  const tagIsComponent = isComponent(tagName);
206
- const isSelfClosing = !tagIsComponent && selfClosingTags.includes(tagName);
207
- const isSvgTemplate = svgTags.includes(tagName) && result.index === 1;
152
+ const isSelfClose = !tagIsComponent && selfClosingTags.includes(tagName);
153
+ const isSvg = svgTags.includes(tagName) && result.index === 1;
208
154
  const props = getAttrProps(path);
209
155
  if (tagIsComponent) {
210
156
  if (isRoot) {
211
157
  result.props = props;
212
158
  const children = getChildren(path);
213
159
  if (children.length > 0) {
214
- const childrenGetter = children.length === 1 ? children[0] : t2.arrayExpression(children);
215
- result.props.children = childrenGetter;
160
+ const childrenGenerator = children.length === 1 ? children[0] : t2.arrayExpression(children);
161
+ result.props.children = childrenGenerator;
216
162
  }
217
163
  } else {
218
- transformJSX(path);
164
+ transformJSXClient(path);
219
165
  replaceChild(path.node, result);
220
166
  }
221
167
  } else {
222
- if (isSvgTemplate) {
223
- result.template += `<svg _svg_>`;
168
+ if (isSvg) {
169
+ result.template = "<svg _svg_>";
224
170
  }
225
171
  result.template += `<${tagName}`;
226
172
  handleAttributes(props, result);
227
- result.template += isSelfClosing ? "/>" : ">";
228
- if (!isSelfClosing) {
173
+ result.template += isSelfClose ? "/>" : ">";
174
+ if (!isSelfClose) {
229
175
  transformChildren(path, result);
230
176
  result.template += `</${tagName}>`;
231
177
  }
@@ -235,20 +181,78 @@ function transformElement(path, result, isRoot) {
235
181
  transformChildren(path, result);
236
182
  }
237
183
  }
238
- function getChildren(path) {
239
- return path.get("children").filter(isValidChild).map((child) => {
240
- if (child.isJSXElement() || child.isJSXFragment()) {
241
- transformJSX(child);
242
- } else if (child.isJSXExpressionContainer()) {
243
- child.replaceWith(child.get("expression"));
244
- } else if (child.isJSXText()) {
245
- child.replaceWith(t2.stringLiteral(child.node.value));
246
- } else {
247
- throw new Error("Unsupported JSX child");
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
+ }
248
194
  }
249
- return child.node;
195
+ return pre;
196
+ }, []).forEach((child, i, arr) => {
197
+ result.parentIndex = parentIndex;
198
+ result.isLastChild = i === arr.length - 1;
199
+ transformChild(child, result);
250
200
  });
251
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
+ }
252
256
  function handleAttributes(props, result) {
253
257
  let klass = "";
254
258
  let style = "";
@@ -306,49 +310,12 @@ function handleAttributes(props, result) {
306
310
  result.template += ` style="${style}"`;
307
311
  }
308
312
  }
309
- function transformChildren(path, result) {
310
- const parentIndex = result.index;
311
- path.get("children").reduce((acc, child) => {
312
- if (isValidChild(child)) {
313
- const lastChild = acc.at(-1);
314
- if (lastChild && isTextChild(child) && isTextChild(lastChild)) {
315
- setNodeText(lastChild, getNodeText(lastChild) + getNodeText(child));
316
- } else {
317
- acc.push(child);
318
- }
319
- }
320
- return acc;
321
- }, []).forEach((child, i, arr) => {
322
- result.parentIndex = parentIndex;
323
- result.isLastChild = i === arr.length - 1;
324
- transformChild(child, result);
325
- });
326
- }
327
- function transformChild(child, result) {
328
- result.index++;
329
- if (child.isJSXElement() || child.isJSXFragment()) {
330
- transformElement(child, result);
331
- } else if (child.isJSXExpressionContainer()) {
332
- const expression = child.get("expression");
333
- if (expression.isStringLiteral() || expression.isNumericLiteral()) {
334
- result.template += expression.node.value;
335
- } else if (expression.isExpression()) {
336
- replaceChild(expression.node, result);
337
- } else {
338
- throw new Error("Unsupported JSX child");
339
- }
340
- } else if (child.isJSXText()) {
341
- result.template += child.node.value;
342
- } else {
343
- throw new Error("Unsupported JSX child");
344
- }
345
- }
346
313
  function replaceChild(node, result) {
347
314
  var _a, _b, _c, _d, _e;
348
315
  if (result.isLastChild) {
349
316
  result.index--;
350
317
  } else {
351
- result.template += "<!>";
318
+ result.template += "<!-->";
352
319
  }
353
320
  (_c = (_a = result.props)[_b = result.parentIndex]) != null ? _c : _a[_b] = {};
354
321
  (_e = (_d = result.props[result.parentIndex]).children) != null ? _e : _d.children = [];
@@ -359,116 +326,469 @@ function replaceChild(node, result) {
359
326
  ])
360
327
  );
361
328
  }
362
- function getAttrName(attribute) {
363
- if (t2.isJSXIdentifier(attribute.name)) {
364
- return attribute.name.name;
365
- }
366
- if (t2.isJSXNamespacedName(attribute.name)) {
367
- return `${attribute.name.namespace.name}:${attribute.name.name.name}`;
368
- }
369
- throw new Error("Unsupported attribute type");
370
- }
371
- function getNodeText(path) {
372
- if (path.isJSXText()) {
373
- return path.node.value;
374
- }
375
- if (path.isJSXExpressionContainer()) {
376
- const expression = path.get("expression");
377
- if (expression.isStringLiteral() || expression.isNumericLiteral()) {
378
- return String(expression.node.value);
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");
379
339
  }
380
- }
381
- return "";
340
+ return child.node;
341
+ });
382
342
  }
383
- function setNodeText(path, text) {
384
- if (path.isJSXText()) {
385
- path.node.value = text;
343
+ function isValidChild(path) {
344
+ const regex = /^\s*$/;
345
+ if (path.isStringLiteral() || path.isJSXText()) {
346
+ return !regex.test(path.node.value);
386
347
  }
387
- if (path.isJSXExpressionContainer()) {
388
- const expression = path.get("expression");
389
- if (expression.isStringLiteral() || expression.isNumericLiteral()) {
390
- expression.replaceWith(t2.stringLiteral(text));
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");
391
392
  }
392
- }
393
+ });
394
+ return props;
393
395
  }
394
- function getTagName(node) {
395
- const jsxName = node.openingElement.name;
396
- return jsxElementNameToString(jsxName);
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");
397
404
  }
398
405
  function isComponent(tagName) {
399
406
  return tagName[0] && tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".") || /[^A-Za-z]/.test(tagName[0]);
400
407
  }
401
- function isTextChild(path) {
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
+ }
402
575
  if (path.isJSXExpressionContainer()) {
403
576
  const expression = path.get("expression");
404
- if (expression.isJSXText() || expression.isStringLiteral() || expression.isNumericLiteral()) {
405
- return true;
577
+ if (expression.isStringLiteral() || expression.isNumericLiteral()) {
578
+ return String(expression.node.value);
406
579
  }
407
580
  }
408
- if (path.isJSXText() || path.isStringLiteral() || path.isNullLiteral()) {
409
- return true;
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
+ }
410
592
  }
411
- return false;
412
593
  }
413
- function isValidChild(path) {
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) {
414
680
  const regex = /^\s*$/;
415
681
  if (path.isStringLiteral() || path.isJSXText()) {
416
682
  return !regex.test(path.node.value);
417
683
  }
418
684
  return Object.keys(path.node).length > 0;
419
685
  }
420
- function jsxElementNameToString(node) {
421
- if (t2.isJSXMemberExpression(node)) {
422
- return `${jsxElementNameToString(node.object)}.${node.property.name}`;
423
- }
424
- if (t2.isJSXIdentifier(node) || t2.isIdentifier(node)) {
425
- return node.name;
426
- }
427
- return `${node.namespace.name}:${node.name.name}`;
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
+ };
428
737
  }
429
738
 
430
- // src/symbol-replace.ts
431
- import { types as t3 } from "@babel/core";
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";
432
748
  import { cloneNode } from "@babel/types";
433
749
  function replaceSymbol(path) {
434
750
  const init = path.node.init;
435
751
  const variableName = path.node.id.name;
436
- if (t3.isObjectPattern(path.node.id) || t3.isArrayPattern(path.node.id)) {
752
+ if (t4.isObjectPattern(path.node.id) || t4.isArrayPattern(path.node.id)) {
437
753
  return;
438
754
  }
439
755
  if (!variableName.startsWith("$")) {
440
756
  return;
441
757
  }
442
- if (init && (t3.isFunctionExpression(init) || t3.isArrowFunctionExpression(init)) && path.parent.kind === "const") {
443
- const newInit = t3.callExpression(t3.identifier(path.state.computed.name), init ? [init] : []);
444
- imports.add("computed");
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");
445
761
  path.node.init = newInit;
446
762
  } else {
447
763
  const originalImportDeclarationNodes = cloneNode(path.get("id").node, true);
448
- const newInit = t3.callExpression(t3.identifier(path.state.signal.name), init ? [init] : []);
449
- imports.add("signal");
764
+ const newInit = t4.callExpression(t4.identifier(path.state.useSignal.name), init ? [init] : []);
765
+ imports.add("useSignal");
450
766
  path.node.init = newInit;
451
767
  path.scope.rename(variableName, `${variableName}.value`);
452
768
  path.get("id").replaceWith(originalImportDeclarationNodes);
453
- path.scope.traverse(path.scope.block, {
454
- Identifier(innerPath) {
455
- if (t3.isExportSpecifier(innerPath.parent)) {
456
- const { name } = innerPath.node;
457
- if (name.endsWith(".value")) {
458
- innerPath.node.name = name.slice(0, -6);
459
- }
460
- }
461
- }
462
- });
463
769
  }
464
770
  }
465
771
 
466
- // src/import-replace.ts
467
- function replaceImport(path) {
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) {
468
788
  const imports2 = path.node.specifiers;
469
789
  imports2.forEach((specifier) => {
470
790
  const variableName = specifier.local.name;
471
- if (variableName.indexOf("$") === 0) {
791
+ if (variableName.indexOf("$") === 0 && !isVariableUsedAsObject(path, variableName)) {
472
792
  path.scope.rename(variableName, `${variableName}.value`);
473
793
  specifier.local.name = `${variableName}`;
474
794
  }
@@ -480,7 +800,7 @@ function src_default() {
480
800
  return {
481
801
  name: "babel-plugin-essor",
482
802
  manipulateOptions({ filename }, parserOpts) {
483
- if (filename.endsWith("ts") || filename.endsWith("tsx")) {
803
+ if (filename.endsWith(".ts") || filename.endsWith(".tsx")) {
484
804
  parserOpts.plugins.push("typescript");
485
805
  }
486
806
  parserOpts.plugins.push("jsx");
@@ -490,7 +810,7 @@ function src_default() {
490
810
  JSXElement: transformJSX,
491
811
  JSXFragment: transformJSX,
492
812
  VariableDeclarator: replaceSymbol,
493
- ImportDeclaration: replaceImport
813
+ ImportDeclaration: replaceImportDeclaration
494
814
  }
495
815
  };
496
816
  }