babel-plugin-essor 0.0.6-beta.8 → 0.0.6

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,9 +1,18 @@
1
1
  // ../shared/dist/essor-shared.js
2
2
  var isArray = Array.isArray;
3
+ function isString(val) {
4
+ return typeof val === "string";
5
+ }
3
6
  var noop = Function.prototype;
4
7
  function startsWith(str, searchString) {
8
+ if (!isString(str)) {
9
+ return false;
10
+ }
5
11
  return str.indexOf(searchString) === 0;
6
12
  }
13
+ var capitalizeFirstLetter = (inputString) => {
14
+ return inputString.charAt(0).toUpperCase() + inputString.slice(1);
15
+ };
7
16
 
8
17
  // src/jsx/server.ts
9
18
  import { types as t3 } from "@babel/core";
@@ -13,13 +22,14 @@ import { types as t } from "@babel/core";
13
22
  var imports = /* @__PURE__ */ new Set();
14
23
  var transformProgram = {
15
24
  enter(path, state) {
25
+ imports.clear();
16
26
  path.state = {
17
27
  h: path.scope.generateUidIdentifier("h$"),
18
- ssrtmpl: path.scope.generateUidIdentifier("ssrtmpl$"),
19
- ssr: path.scope.generateUidIdentifier("ssr$"),
28
+ renderTemplate: path.scope.generateUidIdentifier("renderTemplate$"),
20
29
  template: path.scope.generateUidIdentifier("template$"),
21
30
  useSignal: path.scope.generateUidIdentifier("signal$"),
22
31
  useComputed: path.scope.generateUidIdentifier("computed$"),
32
+ useReactive: path.scope.generateUidIdentifier("reactive$"),
23
33
  tmplDeclaration: t.variableDeclaration("const", []),
24
34
  opts: state.opts
25
35
  };
@@ -87,17 +97,73 @@ var svgTags = [
87
97
  "use"
88
98
  ];
89
99
 
90
- // src/jsx/client.ts
100
+ // src/jsx/shared.ts
91
101
  import { types as t2 } from "@babel/core";
92
- function transformJSXClient(path) {
102
+ function hasSiblingElement(path) {
103
+ const siblings = path.getAllPrevSiblings().concat(path.getAllNextSiblings());
104
+ const hasSibling = siblings.some((siblingPath) => siblingPath.isJSXElement());
105
+ return hasSibling;
106
+ }
107
+ function getAttrName(attribute) {
108
+ if (t2.isJSXIdentifier(attribute.name)) {
109
+ return attribute.name.name;
110
+ }
111
+ if (t2.isJSXNamespacedName(attribute.name)) {
112
+ return `${attribute.name.namespace.name}:${attribute.name.name.name}`;
113
+ }
114
+ throw new Error("Unsupported attribute type");
115
+ }
116
+ function getTagName(node) {
117
+ const tag = node.openingElement.name;
118
+ return jsxElementNameToString(tag);
119
+ }
120
+ function jsxElementNameToString(node) {
121
+ if (t2.isJSXMemberExpression(node)) {
122
+ return `${jsxElementNameToString(node.object)}.${jsxElementNameToString(node.property)}`;
123
+ }
124
+ if (t2.isJSXIdentifier(node) || t2.isIdentifier(node)) {
125
+ return node.name;
126
+ }
127
+ return `${node.namespace.name}:${node.name.name}`;
128
+ }
129
+ function isComponent(tagName) {
130
+ return tagName[0] && tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".") || /[^A-Za-z]/.test(tagName[0]);
131
+ }
132
+ function isTextChild(path) {
133
+ if (path.isJSXExpressionContainer()) {
134
+ const expression = path.get("expression");
135
+ if (expression.isJSXText() || expression.isStringLiteral() || expression.isNumericLiteral()) {
136
+ return true;
137
+ }
138
+ }
139
+ if (path.isJSXText() || path.isStringLiteral() || path.isNullLiteral()) {
140
+ return true;
141
+ }
142
+ return false;
143
+ }
144
+ function setNodeText(path, text) {
145
+ if (path.isJSXText()) {
146
+ path.node.value = text;
147
+ }
148
+ if (path.isJSXExpressionContainer()) {
149
+ const expression = path.get("expression");
150
+ if (expression.isStringLiteral() || expression.isNumericLiteral()) {
151
+ expression.replaceWith(t2.stringLiteral(text));
152
+ }
153
+ }
154
+ }
155
+
156
+ // src/jsx/server.ts
157
+ function transformJSXService(path) {
93
158
  const result = {
94
- index: 1,
159
+ index: 0,
95
160
  isLastChild: false,
96
161
  parentIndex: 0,
97
162
  props: {},
98
- template: ""
163
+ template: []
164
+ // 修改为数组
99
165
  };
100
- transformJSXElement(path, result, true);
166
+ transformJSXServiceElement(path, result, true);
101
167
  path.replaceWith(createEssorNode(path, result));
102
168
  }
103
169
  function createEssorNode(path, result) {
@@ -105,82 +171,91 @@ function createEssorNode(path, result) {
105
171
  const state = path.state;
106
172
  let tmpl;
107
173
  if (path.isJSXElement() && isComponent(getTagName(path.node))) {
108
- tmpl = t2.identifier(getTagName(path.node));
174
+ tmpl = t3.identifier(getTagName(path.node));
109
175
  } else {
110
176
  tmpl = path.scope.generateUidIdentifier("_tmpl$");
111
- const template = t2.callExpression(state.template, [t2.stringLiteral(result.template)]);
112
- const declarator = t2.variableDeclarator(tmpl, template);
177
+ const template = t3.arrayExpression(result.template.map(t3.stringLiteral));
178
+ const declarator = t3.variableDeclarator(tmpl, template);
113
179
  state.tmplDeclaration.declarations.push(declarator);
114
- imports.add("template");
115
180
  }
116
181
  const args = [tmpl, createProps(result.props)];
117
182
  const key = result.props.key || ((_a = result.props[0]) == null ? void 0 : _a.key);
118
183
  if (key) {
119
184
  args.push(key);
120
185
  }
121
- imports.add("h");
122
- return t2.callExpression(state.h, args);
186
+ imports.add("renderTemplate");
187
+ return t3.callExpression(state.renderTemplate, args);
123
188
  }
124
189
  function createProps(props) {
125
- const toAstNode = (value) => {
190
+ const result = [];
191
+ for (const prop in props) {
192
+ let value = props[prop];
193
+ if (prop === "key") {
194
+ continue;
195
+ }
126
196
  if (Array.isArray(value)) {
127
- return t2.arrayExpression(value.map(toAstNode));
197
+ value = t3.arrayExpression(value);
128
198
  }
129
- if (value && typeof value === "object" && !t2.isNode(value)) {
130
- return createProps(value);
199
+ if (typeof value === "object" && value !== null && !t3.isNode(value)) {
200
+ value = createProps(value);
131
201
  }
132
- switch (typeof value) {
133
- case "string":
134
- return t2.stringLiteral(value);
135
- case "number":
136
- return t2.numericLiteral(value);
137
- case "boolean":
138
- return t2.booleanLiteral(value);
139
- case "undefined":
140
- return t2.tsUndefinedKeyword();
141
- case void 0:
142
- return t2.tsUndefinedKeyword();
143
- case null:
144
- return t2.nullLiteral();
145
- default:
146
- return value;
202
+ if (typeof value === "string") {
203
+ value = t3.stringLiteral(value);
147
204
  }
148
- };
149
- const result = Object.keys(props).filter((prop) => prop !== "key").map((prop) => {
150
- const value = toAstNode(props[prop]);
151
- return prop === "_$spread$" ? t2.spreadElement(value) : t2.objectProperty(t2.stringLiteral(prop), value);
152
- });
153
- return t2.objectExpression(result);
205
+ if (typeof value === "number") {
206
+ value = t3.numericLiteral(value);
207
+ }
208
+ if (typeof value === "boolean") {
209
+ value = t3.booleanLiteral(value);
210
+ }
211
+ if (value === void 0) {
212
+ value = t3.tsUndefinedKeyword();
213
+ }
214
+ if (value === null) {
215
+ value = t3.nullLiteral();
216
+ }
217
+ if (prop === "_$spread$") {
218
+ result.push(t3.spreadElement(value));
219
+ } else {
220
+ result.push(t3.objectProperty(t3.stringLiteral(prop), value));
221
+ }
222
+ }
223
+ return t3.objectExpression(result);
154
224
  }
155
- function transformJSXElement(path, result, isRoot = false) {
225
+ function transformJSXServiceElement(path, result, isRoot = false) {
156
226
  if (path.isJSXElement()) {
157
227
  const tagName = getTagName(path.node);
158
228
  const tagIsComponent = isComponent(tagName);
159
229
  const isSelfClose = !tagIsComponent && selfClosingTags.includes(tagName);
160
230
  const isSvg = svgTags.includes(tagName) && result.index === 1;
161
- const props = getAttrProps(path);
231
+ const { props, hasExpression } = getAttrProps(path);
162
232
  if (tagIsComponent) {
163
233
  if (isRoot) {
164
234
  result.props = props;
165
235
  const children = getChildren(path);
166
236
  if (children.length > 0) {
167
- const childrenGenerator = children.length === 1 ? children[0] : t2.arrayExpression(children);
237
+ const childrenGenerator = children.length === 1 ? children[0] : t3.arrayExpression(children);
168
238
  result.props.children = childrenGenerator;
169
239
  }
170
240
  } else {
171
- transformJSXClient(path);
241
+ transformJSXService(path);
172
242
  replaceChild(path.node, result);
173
243
  }
174
244
  } else {
175
245
  if (isSvg) {
176
- result.template = "<svg _svg_>";
246
+ result.template.push("<svg _svg_>");
177
247
  }
178
- result.template += `<${tagName}`;
248
+ result.template.push(`<${tagName}`);
179
249
  handleAttributes(props, result);
180
- result.template += isSelfClose ? "/>" : ">";
250
+ if (hasExpression) {
251
+ result.template.push(isSelfClose ? "/>" : ">");
252
+ result.props || (result.props = {});
253
+ } else {
254
+ result.template[result.template.length - 1] += isSelfClose ? "/>" : ">";
255
+ }
256
+ transformChildren(path, result);
181
257
  if (!isSelfClose) {
182
- transformChildren(path, result);
183
- result.template += `</${tagName}>`;
258
+ result.template.push(`</${tagName}>`);
184
259
  }
185
260
  }
186
261
  } else {
@@ -189,7 +264,7 @@ function transformJSXElement(path, result, isRoot = false) {
189
264
  }
190
265
  }
191
266
  function transformChildren(path, result) {
192
- const parentIndex = result.index;
267
+ const parentIndex = result.template.length;
193
268
  path.get("children").reduce((pre, cur) => {
194
269
  if (isValidChild(cur)) {
195
270
  const lastChild = pre.at(-1);
@@ -207,20 +282,20 @@ function transformChildren(path, result) {
207
282
  });
208
283
  }
209
284
  function transformChild(child, result) {
210
- result.index++;
211
285
  if (child.isJSXElement() || child.isJSXFragment()) {
212
- transformJSXElement(child, result, false);
286
+ transformJSXServiceElement(child, result, false);
213
287
  } else if (child.isJSXExpressionContainer()) {
214
288
  const expression = child.get("expression");
215
289
  if (expression.isStringLiteral() || expression.isNumericLiteral()) {
216
- result.template += String(expression.node.value);
290
+ result.template[result.template.length - 1] += String(expression.node.value);
217
291
  } else if (expression.isExpression()) {
218
292
  replaceChild(expression.node, result);
293
+ } else if (t3.isJSXEmptyExpression(expression.node)) {
219
294
  } else {
220
295
  throw new Error("Unsupported child type");
221
296
  }
222
297
  } else if (child.isJSXText()) {
223
- result.template += String(child.node.value);
298
+ result.template.push(String(child.node.value));
224
299
  } else {
225
300
  throw new Error("Unsupported child type");
226
301
  }
@@ -237,29 +312,6 @@ function getNodeText(path) {
237
312
  }
238
313
  return "";
239
314
  }
240
- function setNodeText(path, text) {
241
- if (path.isJSXText()) {
242
- path.node.value = text;
243
- }
244
- if (path.isJSXExpressionContainer()) {
245
- const expression = path.get("expression");
246
- if (expression.isStringLiteral() || expression.isNumericLiteral()) {
247
- expression.replaceWith(t2.stringLiteral(text));
248
- }
249
- }
250
- }
251
- function isTextChild(path) {
252
- if (path.isJSXExpressionContainer()) {
253
- const expression = path.get("expression");
254
- if (expression.isJSXText() || expression.isStringLiteral() || expression.isNumericLiteral()) {
255
- return true;
256
- }
257
- }
258
- if (path.isJSXText() || path.isStringLiteral() || path.isNullLiteral()) {
259
- return true;
260
- }
261
- return false;
262
- }
263
315
  function handleAttributes(props, result) {
264
316
  let klass = "";
265
317
  let style = "";
@@ -270,38 +322,20 @@ function handleAttributes(props, result) {
270
322
  delete props[prop];
271
323
  continue;
272
324
  }
273
- if (startsWith(prop, "class:")) {
274
- if (value === true) {
275
- const name = prop.replace(/^class:/, "");
276
- klass += ` ${name}`;
277
- delete props[prop];
278
- continue;
279
- }
280
- if (value === false) {
281
- delete props[prop];
282
- continue;
283
- }
284
- }
285
325
  if (prop === "style" && typeof value === "string") {
286
326
  style += `${value}${value.at(-1) === ";" ? "" : ";"}`;
287
327
  delete props[prop];
288
328
  continue;
289
329
  }
290
- if (startsWith(prop, "style:") && (typeof value === "string" || typeof value === "number")) {
291
- const name = prop.replace(/^style:/, "");
292
- style += `${name}:${value};`;
293
- delete props[prop];
294
- continue;
295
- }
296
330
  if (value === true) {
297
- result.template += ` ${prop}`;
331
+ result.template[result.template.length - 1] += ` ${prop}`;
298
332
  delete props[prop];
299
333
  }
300
334
  if (value === false) {
301
335
  delete props[prop];
302
336
  }
303
337
  if (typeof value === "string" || typeof value === "number") {
304
- result.template += ` ${prop}="${value}"`;
338
+ result.template[result.template.length - 1] += ` ${prop}="${value}"`;
305
339
  delete props[prop];
306
340
  }
307
341
  }
@@ -311,36 +345,34 @@ function handleAttributes(props, result) {
311
345
  klass = klass.trim();
312
346
  style = style.trim();
313
347
  if (klass) {
314
- result.template += ` class="${klass}"`;
348
+ result.template[result.template.length - 1] += ` class="${klass}"`;
315
349
  }
316
350
  if (style) {
317
- result.template += ` style="${style}"`;
351
+ result.template[result.template.length - 1] += ` style="${style}"`;
318
352
  }
319
353
  }
320
354
  function replaceChild(node, result) {
321
355
  var _a, _b, _c, _d, _e;
322
356
  if (result.isLastChild) {
323
357
  result.index--;
324
- } else {
325
- result.template += "<!-->";
326
358
  }
327
359
  (_c = (_a = result.props)[_b = result.parentIndex]) != null ? _c : _a[_b] = {};
328
360
  (_e = (_d = result.props[result.parentIndex]).children) != null ? _e : _d.children = [];
329
361
  result.props[result.parentIndex].children.push(
330
- t2.arrayExpression([
331
- t2.arrowFunctionExpression([], node),
332
- result.isLastChild ? t2.nullLiteral() : t2.identifier(String(result.index))
362
+ t3.arrayExpression([
363
+ t3.arrowFunctionExpression([], node),
364
+ t3.identifier(String(result.template.length))
333
365
  ])
334
366
  );
335
367
  }
336
368
  function getChildren(path) {
337
369
  return path.get("children").filter((child) => isValidChild(child)).map((child) => {
338
370
  if (child.isJSXElement() || child.isJSXFragment()) {
339
- transformJSXClient(child);
371
+ transformJSXService(child);
340
372
  } else if (child.isJSXExpressionContainer()) {
341
373
  child.replaceWith(child.get("expression"));
342
374
  } else if (child.isJSXText()) {
343
- child.replaceWith(t2.stringLiteral(child.node.value));
375
+ child.replaceWith(t3.stringLiteral(child.node.value));
344
376
  } else {
345
377
  throw new Error("Unsupported child type");
346
378
  }
@@ -356,6 +388,7 @@ function isValidChild(path) {
356
388
  }
357
389
  function getAttrProps(path) {
358
390
  const props = {};
391
+ let hasExpression = false;
359
392
  path.get("openingElement").get("attributes").forEach((attribute) => {
360
393
  if (attribute.isJSXAttribute()) {
361
394
  const name = getAttrName(attribute.node);
@@ -372,77 +405,57 @@ function getAttrProps(path) {
372
405
  } else if (expression.isNumericLiteral()) {
373
406
  props[name] = expression.node.value;
374
407
  } else if (expression.isJSXElement() || expression.isJSXFragment()) {
375
- transformJSXClient(expression);
408
+ transformJSXService(expression);
376
409
  props[name] = expression.node;
377
410
  } else if (expression.isExpression()) {
411
+ hasExpression = true;
378
412
  if (/^key|ref|on.+$/.test(name)) {
379
413
  props[name] = expression.node;
380
414
  } else if (/^bind:.+/.test(name)) {
381
415
  const value2 = path.scope.generateUidIdentifier("value");
382
416
  const bindName = name.slice(5).toLocaleLowerCase();
383
417
  props[bindName] = expression.node;
384
- props[`update:${bindName}`] = t2.arrowFunctionExpression(
418
+ props[`update${capitalizeFirstLetter(bindName)}`] = t3.arrowFunctionExpression(
385
419
  [value2],
386
- t2.assignmentExpression("=", expression.node, value2)
420
+ t3.assignmentExpression("=", expression.node, value2)
387
421
  );
388
422
  } else {
389
423
  if (expression.isConditionalExpression()) {
390
- props[name] = t2.arrowFunctionExpression([], expression.node);
424
+ props[name] = t3.arrowFunctionExpression([], expression.node);
391
425
  } else {
392
426
  props[name] = expression.node;
393
427
  }
394
428
  }
395
429
  }
396
430
  } else if (value.isJSXElement() || value.isJSXFragment()) {
397
- transformJSXClient(value);
431
+ transformJSXService(value);
398
432
  props[name] = value.node;
399
433
  }
400
434
  }
401
435
  } else if (attribute.isJSXSpreadAttribute()) {
402
436
  props._$spread$ = attribute.get("argument").node;
437
+ hasExpression = true;
403
438
  } else {
404
439
  throw new Error("Unsupported attribute type");
405
440
  }
406
441
  });
407
- return props;
408
- }
409
- function getAttrName(attribute) {
410
- if (t2.isJSXIdentifier(attribute.name)) {
411
- return attribute.name.name;
412
- }
413
- if (t2.isJSXNamespacedName(attribute.name)) {
414
- return `${attribute.name.namespace.name}:${attribute.name.name.name}`;
415
- }
416
- throw new Error("Unsupported attribute type");
417
- }
418
- function isComponent(tagName) {
419
- return tagName[0] && tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".") || /[^A-Za-z]/.test(tagName[0]);
420
- }
421
- function getTagName(node) {
422
- const tag = node.openingElement.name;
423
- return jsxElementNameToString(tag);
424
- }
425
- function jsxElementNameToString(node) {
426
- if (t2.isJSXMemberExpression(node)) {
427
- return `${jsxElementNameToString(node.object)}.${jsxElementNameToString(node.property)}`;
428
- }
429
- if (t2.isJSXIdentifier(node) || t2.isIdentifier(node)) {
430
- return node.name;
431
- }
432
- return `${node.namespace.name}:${node.name.name}`;
442
+ return {
443
+ props,
444
+ hasExpression
445
+ };
433
446
  }
434
447
 
435
- // src/jsx/server.ts
436
- function transformJSXService(path) {
448
+ // src/jsx/client.ts
449
+ import { types as t4 } from "@babel/core";
450
+ function transformJSXClient(path) {
437
451
  const result = {
438
- index: 0,
452
+ index: 1,
439
453
  isLastChild: false,
440
454
  parentIndex: 0,
441
455
  props: {},
442
- template: []
443
- // 修改为数组
456
+ template: ""
444
457
  };
445
- transformJSXServiceElement(path, result, true);
458
+ transformJSXElement(path, result, true);
446
459
  path.replaceWith(createEssorNode2(path, result));
447
460
  }
448
461
  function createEssorNode2(path, result) {
@@ -450,94 +463,84 @@ function createEssorNode2(path, result) {
450
463
  const state = path.state;
451
464
  let tmpl;
452
465
  if (path.isJSXElement() && isComponent(getTagName(path.node))) {
453
- tmpl = t3.identifier(getTagName(path.node));
466
+ tmpl = t4.identifier(getTagName(path.node));
454
467
  } else {
455
468
  tmpl = path.scope.generateUidIdentifier("_tmpl$");
456
- const template = t3.callExpression(state.ssrtmpl, [
457
- t3.arrayExpression(result.template.map(t3.stringLiteral))
458
- ]);
459
- const declarator = t3.variableDeclarator(tmpl, template);
469
+ const template = t4.callExpression(state.template, [t4.stringLiteral(result.template)]);
470
+ const declarator = t4.variableDeclarator(tmpl, template);
460
471
  state.tmplDeclaration.declarations.push(declarator);
461
- imports.add("ssrtmpl");
472
+ imports.add("template");
462
473
  }
463
474
  const args = [tmpl, createProps2(result.props)];
464
475
  const key = result.props.key || ((_a = result.props[0]) == null ? void 0 : _a.key);
465
476
  if (key) {
466
477
  args.push(key);
467
478
  }
468
- imports.add("ssr");
469
- return t3.callExpression(state.ssr, args);
479
+ imports.add("h");
480
+ return t4.callExpression(state.h, args);
470
481
  }
471
482
  function createProps2(props) {
472
- const result = [];
473
- for (const prop in props) {
474
- let value = props[prop];
475
- if (prop === "key") {
476
- continue;
477
- }
483
+ const toAstNode = (value) => {
478
484
  if (Array.isArray(value)) {
479
- value = t3.arrayExpression(value);
480
- }
481
- if (typeof value === "object" && value !== null && !t3.isNode(value)) {
482
- value = createProps2(value);
483
- }
484
- if (typeof value === "string") {
485
- value = t3.stringLiteral(value);
486
- }
487
- if (typeof value === "number") {
488
- value = t3.numericLiteral(value);
489
- }
490
- if (typeof value === "boolean") {
491
- value = t3.booleanLiteral(value);
492
- }
493
- if (value === void 0) {
494
- value = t3.tsUndefinedKeyword();
485
+ return t4.arrayExpression(value.map(toAstNode));
495
486
  }
496
- if (value === null) {
497
- value = t3.nullLiteral();
487
+ if (value && typeof value === "object" && !t4.isNode(value)) {
488
+ return createProps2(value);
498
489
  }
499
- if (prop === "_$spread$") {
500
- result.push(t3.spreadElement(value));
501
- } else {
502
- result.push(t3.objectProperty(t3.stringLiteral(prop), value));
490
+ switch (typeof value) {
491
+ case "string":
492
+ return t4.stringLiteral(value);
493
+ case "number":
494
+ return t4.numericLiteral(value);
495
+ case "boolean":
496
+ return t4.booleanLiteral(value);
497
+ case "undefined":
498
+ return t4.tsUndefinedKeyword();
499
+ case void 0:
500
+ return t4.tsUndefinedKeyword();
501
+ case null:
502
+ return t4.nullLiteral();
503
+ default:
504
+ return value;
503
505
  }
504
- }
505
- return t3.objectExpression(result);
506
+ };
507
+ const result = Object.keys(props).filter((prop) => prop !== "key").map((prop) => {
508
+ const value = toAstNode(props[prop]);
509
+ return prop === "_$spread$" ? t4.spreadElement(value) : t4.objectProperty(t4.stringLiteral(prop), value);
510
+ });
511
+ return t4.objectExpression(result);
506
512
  }
507
- function transformJSXServiceElement(path, result, isRoot = false) {
513
+ function transformJSXElement(path, result, isRoot = false) {
508
514
  if (path.isJSXElement()) {
509
515
  const tagName = getTagName(path.node);
510
516
  const tagIsComponent = isComponent(tagName);
511
517
  const isSelfClose = !tagIsComponent && selfClosingTags.includes(tagName);
512
518
  const isSvg = svgTags.includes(tagName) && result.index === 1;
513
- const { props, hasExpression } = getAttrProps2(path);
519
+ const props = getAttrProps2(path);
514
520
  if (tagIsComponent) {
515
521
  if (isRoot) {
516
522
  result.props = props;
517
523
  const children = getChildren2(path);
518
524
  if (children.length > 0) {
519
- const childrenGenerator = children.length === 1 ? children[0] : t3.arrayExpression(children);
525
+ const childrenGenerator = children.length === 1 ? children[0] : t4.arrayExpression(children);
520
526
  result.props.children = childrenGenerator;
521
527
  }
522
528
  } else {
523
- transformJSXService(path);
529
+ transformJSXClient(path);
524
530
  replaceChild2(path.node, result);
525
531
  }
526
532
  } else {
527
533
  if (isSvg) {
528
- result.template.push("<svg _svg_>");
534
+ result.template = "<svg _svg_>";
529
535
  }
530
- result.template.push(`<${tagName}`);
536
+ result.template += `<${tagName}`;
531
537
  handleAttributes2(props, result);
532
- if (hasExpression) {
533
- result.template.push(isSelfClose ? "/>" : ">");
534
- result.props || (result.props = {});
535
- } else {
536
- result.template[result.template.length - 1] += isSelfClose ? "/>" : ">";
537
- }
538
- transformChildren2(path, result);
538
+ result.template += isSelfClose ? "/>" : ">";
539
539
  if (!isSelfClose) {
540
- result.template.push(`</${tagName}>`);
540
+ transformChildren2(path, result);
541
+ if (hasSiblingElement(path)) {
542
+ result.template += `</${tagName}>`;
543
+ }
541
544
  }
542
545
  }
543
546
  } else {
@@ -546,12 +549,12 @@ function transformJSXServiceElement(path, result, isRoot = false) {
546
549
  }
547
550
  }
548
551
  function transformChildren2(path, result) {
549
- const parentIndex = result.template.length;
552
+ const parentIndex = result.index;
550
553
  path.get("children").reduce((pre, cur) => {
551
554
  if (isValidChild2(cur)) {
552
555
  const lastChild = pre.at(-1);
553
556
  if (lastChild && isTextChild(cur) && isTextChild(lastChild)) {
554
- setNodeText2(lastChild, getNodeText2(lastChild) + getNodeText2(cur));
557
+ setNodeText(lastChild, getNodeText2(lastChild) + getNodeText2(cur));
555
558
  } else {
556
559
  pre.push(cur);
557
560
  }
@@ -564,19 +567,21 @@ function transformChildren2(path, result) {
564
567
  });
565
568
  }
566
569
  function transformChild2(child, result) {
570
+ result.index++;
567
571
  if (child.isJSXElement() || child.isJSXFragment()) {
568
- transformJSXServiceElement(child, result, false);
572
+ transformJSXElement(child, result, false);
569
573
  } else if (child.isJSXExpressionContainer()) {
570
574
  const expression = child.get("expression");
571
575
  if (expression.isStringLiteral() || expression.isNumericLiteral()) {
572
- result.template[result.template.length - 1] += String(expression.node.value);
576
+ result.template += String(expression.node.value);
573
577
  } else if (expression.isExpression()) {
574
578
  replaceChild2(expression.node, result);
579
+ } else if (t4.isJSXEmptyExpression(expression.node)) {
575
580
  } else {
576
581
  throw new Error("Unsupported child type");
577
582
  }
578
583
  } else if (child.isJSXText()) {
579
- result.template.push(String(child.node.value));
584
+ result.template += String(child.node.value);
580
585
  } else {
581
586
  throw new Error("Unsupported child type");
582
587
  }
@@ -593,17 +598,6 @@ function getNodeText2(path) {
593
598
  }
594
599
  return "";
595
600
  }
596
- function setNodeText2(path, text) {
597
- if (path.isJSXText()) {
598
- path.node.value = text;
599
- }
600
- if (path.isJSXExpressionContainer()) {
601
- const expression = path.get("expression");
602
- if (expression.isStringLiteral() || expression.isNumericLiteral()) {
603
- expression.replaceWith(t3.stringLiteral(text));
604
- }
605
- }
606
- }
607
601
  function handleAttributes2(props, result) {
608
602
  let klass = "";
609
603
  let style = "";
@@ -614,38 +608,20 @@ function handleAttributes2(props, result) {
614
608
  delete props[prop];
615
609
  continue;
616
610
  }
617
- if (startsWith(prop, "class:")) {
618
- if (value === true) {
619
- const name = prop.replace(/^class:/, "");
620
- klass += ` ${name}`;
621
- delete props[prop];
622
- continue;
623
- }
624
- if (value === false) {
625
- delete props[prop];
626
- continue;
627
- }
628
- }
629
611
  if (prop === "style" && typeof value === "string") {
630
612
  style += `${value}${value.at(-1) === ";" ? "" : ";"}`;
631
613
  delete props[prop];
632
614
  continue;
633
615
  }
634
- if (startsWith(prop, "style:") && (typeof value === "string" || typeof value === "number")) {
635
- const name = prop.replace(/^style:/, "");
636
- style += `${name}:${value};`;
637
- delete props[prop];
638
- continue;
639
- }
640
616
  if (value === true) {
641
- result.template[result.template.length - 1] += ` ${prop}`;
617
+ result.template += ` ${prop}`;
642
618
  delete props[prop];
643
619
  }
644
620
  if (value === false) {
645
621
  delete props[prop];
646
622
  }
647
623
  if (typeof value === "string" || typeof value === "number") {
648
- result.template[result.template.length - 1] += ` ${prop}="${value}"`;
624
+ result.template += ` ${prop}="${value}"`;
649
625
  delete props[prop];
650
626
  }
651
627
  }
@@ -655,34 +631,36 @@ function handleAttributes2(props, result) {
655
631
  klass = klass.trim();
656
632
  style = style.trim();
657
633
  if (klass) {
658
- result.template[result.template.length - 1] += ` class="${klass}"`;
634
+ result.template += ` class="${klass}"`;
659
635
  }
660
636
  if (style) {
661
- result.template[result.template.length - 1] += ` style="${style}"`;
637
+ result.template += ` style="${style}"`;
662
638
  }
663
639
  }
664
640
  function replaceChild2(node, result) {
665
641
  var _a, _b, _c, _d, _e;
666
642
  if (result.isLastChild) {
667
643
  result.index--;
644
+ } else {
645
+ result.template += "<!>";
668
646
  }
669
647
  (_c = (_a = result.props)[_b = result.parentIndex]) != null ? _c : _a[_b] = {};
670
648
  (_e = (_d = result.props[result.parentIndex]).children) != null ? _e : _d.children = [];
671
649
  result.props[result.parentIndex].children.push(
672
- t3.arrayExpression([
673
- t3.arrowFunctionExpression([], node),
674
- t3.identifier(String(result.template.length))
650
+ t4.arrayExpression([
651
+ t4.arrowFunctionExpression([], node),
652
+ result.isLastChild ? t4.nullLiteral() : t4.identifier(String(result.index))
675
653
  ])
676
654
  );
677
655
  }
678
656
  function getChildren2(path) {
679
657
  return path.get("children").filter((child) => isValidChild2(child)).map((child) => {
680
658
  if (child.isJSXElement() || child.isJSXFragment()) {
681
- transformJSXService(child);
659
+ transformJSXClient(child);
682
660
  } else if (child.isJSXExpressionContainer()) {
683
661
  child.replaceWith(child.get("expression"));
684
662
  } else if (child.isJSXText()) {
685
- child.replaceWith(t3.stringLiteral(child.node.value));
663
+ child.replaceWith(t4.stringLiteral(child.node.value));
686
664
  } else {
687
665
  throw new Error("Unsupported child type");
688
666
  }
@@ -698,7 +676,6 @@ function isValidChild2(path) {
698
676
  }
699
677
  function getAttrProps2(path) {
700
678
  const props = {};
701
- let hasExpression = false;
702
679
  path.get("openingElement").get("attributes").forEach((attribute) => {
703
680
  if (attribute.isJSXAttribute()) {
704
681
  const name = getAttrName(attribute.node);
@@ -715,81 +692,113 @@ function getAttrProps2(path) {
715
692
  } else if (expression.isNumericLiteral()) {
716
693
  props[name] = expression.node.value;
717
694
  } else if (expression.isJSXElement() || expression.isJSXFragment()) {
718
- transformJSXService(expression);
695
+ transformJSXClient(expression);
719
696
  props[name] = expression.node;
720
697
  } else if (expression.isExpression()) {
721
- hasExpression = true;
722
698
  if (/^key|ref|on.+$/.test(name)) {
723
699
  props[name] = expression.node;
724
700
  } else if (/^bind:.+/.test(name)) {
725
701
  const value2 = path.scope.generateUidIdentifier("value");
726
702
  const bindName = name.slice(5).toLocaleLowerCase();
727
703
  props[bindName] = expression.node;
728
- props[`update:${bindName}`] = t3.arrowFunctionExpression(
704
+ props[`update${capitalizeFirstLetter(bindName)}`] = t4.arrowFunctionExpression(
729
705
  [value2],
730
- t3.assignmentExpression("=", expression.node, value2)
706
+ t4.assignmentExpression("=", expression.node, value2)
731
707
  );
732
708
  } else {
733
709
  if (expression.isConditionalExpression()) {
734
- props[name] = t3.arrowFunctionExpression([], expression.node);
710
+ props[name] = t4.arrowFunctionExpression([], expression.node);
735
711
  } else {
736
712
  props[name] = expression.node;
737
713
  }
738
714
  }
739
715
  }
740
716
  } else if (value.isJSXElement() || value.isJSXFragment()) {
741
- transformJSXService(value);
717
+ transformJSXClient(value);
742
718
  props[name] = value.node;
743
719
  }
744
720
  }
745
721
  } else if (attribute.isJSXSpreadAttribute()) {
746
722
  props._$spread$ = attribute.get("argument").node;
747
- hasExpression = true;
748
723
  } else {
749
724
  throw new Error("Unsupported attribute type");
750
725
  }
751
726
  });
752
- return {
753
- props,
754
- hasExpression
755
- };
727
+ return props;
756
728
  }
757
729
 
758
730
  // src/jsx/index.ts
759
731
  function transformJSX(path) {
760
732
  const state = path.state;
761
- const isSsr = state.opts.ssr;
762
- return isSsr ? transformJSXService(path) : transformJSXClient(path);
733
+ const isSsg = state.opts.ssg;
734
+ return isSsg ? transformJSXService(path) : transformJSXClient(path);
763
735
  }
764
736
 
765
737
  // src/signal/symbol.ts
766
- import { types as t4 } from "@babel/core";
767
- import { cloneNode } from "@babel/types";
738
+ import { types as t5 } from "@babel/core";
768
739
  function replaceSymbol(path) {
769
740
  const init = path.node.init;
770
741
  const variableName = path.node.id.name;
771
- if (t4.isObjectPattern(path.node.id) || t4.isArrayPattern(path.node.id)) {
742
+ if (t5.isObjectPattern(path.node.id) || t5.isArrayPattern(path.node.id)) {
772
743
  return;
773
744
  }
774
745
  if (!startsWith(variableName, "$")) {
775
746
  return;
776
747
  }
777
- if (init && (t4.isFunctionExpression(init) || t4.isArrowFunctionExpression(init)) && path.parent.kind === "const") {
778
- const newInit = t4.callExpression(t4.identifier(path.state.useComputed.name), init ? [init] : []);
748
+ if (init && (t5.isFunctionExpression(init) || t5.isArrowFunctionExpression(init)) && path.parent.kind === "const") {
749
+ const newInit = t5.callExpression(t5.identifier(path.state.useComputed.name), init ? [init] : []);
779
750
  imports.add("useComputed");
780
751
  path.node.init = newInit;
781
752
  } else {
782
- const originalImportDeclarationNodes = cloneNode(path.get("id").node, true);
783
- const newInit = t4.callExpression(t4.identifier(path.state.useSignal.name), init ? [init] : []);
753
+ const newInit = t5.callExpression(t5.identifier(path.state.useSignal.name), init ? [init] : []);
784
754
  imports.add("useSignal");
785
755
  path.node.init = newInit;
786
- path.scope.rename(variableName, `${variableName}.value`);
787
- path.get("id").replaceWith(originalImportDeclarationNodes);
788
756
  }
789
757
  }
758
+ function symbolIdentifier(path) {
759
+ const parentPath = path.parentPath;
760
+ if (!parentPath || t5.isVariableDeclarator(parentPath) || t5.isImportSpecifier(parentPath) || t5.isObjectProperty(parentPath) || t5.isArrayPattern(parentPath) || t5.isObjectPattern(parentPath)) {
761
+ return;
762
+ }
763
+ const { node } = path;
764
+ if (node.name.startsWith("$")) {
765
+ let currentPath = path;
766
+ while (currentPath.parentPath && !currentPath.parentPath.isProgram()) {
767
+ if (currentPath.parentPath.isMemberExpression() && currentPath.parentPath.node.property.name === "value") {
768
+ return;
769
+ }
770
+ currentPath = currentPath.parentPath;
771
+ }
772
+ const newNode = t5.memberExpression(t5.identifier(node.name), t5.identifier("value"));
773
+ path.replaceWith(newNode);
774
+ }
775
+ }
776
+ function symbolObjectPattern(path) {
777
+ path.node.properties.forEach((property) => {
778
+ if (t5.isObjectProperty(property) && t5.isIdentifier(property.key) && property.key.name.startsWith("$")) {
779
+ const newKey = t5.identifier(property.key.name);
780
+ property.key = newKey;
781
+ }
782
+ });
783
+ }
784
+ function symbolArrayPattern(path) {
785
+ path.node.elements.forEach((element) => {
786
+ if (t5.isIdentifier(element) && element.name.startsWith("$")) {
787
+ const newElement = t5.identifier(element.name);
788
+ element.name = newElement.name;
789
+ } else if (t5.isObjectPattern(element)) {
790
+ element.properties.forEach((property) => {
791
+ if (t5.isObjectProperty(property) && t5.isIdentifier(property.key) && property.key.name.startsWith("$")) {
792
+ const newKey = t5.identifier(property.key.name);
793
+ property.key = newKey;
794
+ }
795
+ });
796
+ }
797
+ });
798
+ }
790
799
 
791
800
  // src/signal/import.ts
792
- import { types as t5 } from "@babel/core";
801
+ import { types as t6 } from "@babel/core";
793
802
  function isVariableUsedAsObject(path, variableName) {
794
803
  const binding = path.scope.getBinding(variableName);
795
804
  let isUsedObject = false;
@@ -797,7 +806,7 @@ function isVariableUsedAsObject(path, variableName) {
797
806
  return isUsedObject;
798
807
  }
799
808
  for (const referencePath of binding.referencePaths) {
800
- if (t5.isMemberExpression(referencePath.parent)) {
809
+ if (t6.isMemberExpression(referencePath.parent)) {
801
810
  isUsedObject = true;
802
811
  }
803
812
  }
@@ -814,6 +823,72 @@ function replaceImportDeclaration(path) {
814
823
  });
815
824
  }
816
825
 
826
+ // src/signal/props.ts
827
+ import { types as t7 } from "@babel/core";
828
+ function replaceProps(path) {
829
+ var _a;
830
+ const state = path.state;
831
+ const firstParam = path.node.params[0];
832
+ if (!firstParam || !t7.isObjectPattern(firstParam)) {
833
+ return;
834
+ }
835
+ const returnStatement = path.get("body").get("body").find((statement) => statement.isReturnStatement());
836
+ if (!returnStatement) {
837
+ return;
838
+ }
839
+ const returnValue = (_a = returnStatement.node) == null ? void 0 : _a.argument;
840
+ if (!t7.isJSXElement(returnValue)) {
841
+ return;
842
+ }
843
+ function replaceProperties(properties2, parentPath) {
844
+ properties2.forEach((property) => {
845
+ if (t7.isObjectProperty(property)) {
846
+ const keyName = property.key.name;
847
+ if (t7.isIdentifier(property.value)) {
848
+ const propertyName = property.value.name;
849
+ const newName = `${parentPath}${keyName}`;
850
+ path.scope.rename(propertyName, newName);
851
+ } else if (t7.isObjectPattern(property.value)) {
852
+ replaceProperties(property.value.properties, `${parentPath}${keyName}.`);
853
+ }
854
+ }
855
+ });
856
+ }
857
+ const properties = firstParam.properties;
858
+ replaceProperties(
859
+ properties.filter((property) => !t7.isRestElement(property)),
860
+ "__props."
861
+ );
862
+ const notRestProperties = properties.filter((property) => !t7.isRestElement(property));
863
+ const notRestNames = notRestProperties.map(
864
+ (property) => property.key.name
865
+ );
866
+ if (notRestNames.some((name) => startsWith(name, "$"))) {
867
+ console.warn("props name can not start with $");
868
+ return;
869
+ }
870
+ const restElement = properties.find((property) => t7.isRestElement(property));
871
+ path.node.params[0] = t7.identifier("__props");
872
+ if (restElement) {
873
+ const restName = restElement.argument.name;
874
+ if (notRestProperties.length === 0) {
875
+ path.node.params[0] = t7.identifier(restName);
876
+ } else {
877
+ const restVariableDeclaration = t7.variableDeclaration("const", [
878
+ t7.variableDeclarator(
879
+ t7.identifier(restName),
880
+ t7.callExpression(state.useReactive, [
881
+ t7.identifier("__props"),
882
+ t7.arrayExpression(notRestNames.map((name) => t7.stringLiteral(name)))
883
+ ])
884
+ )
885
+ ]);
886
+ imports.add("useReactive");
887
+ path.node.body.body.unshift(restVariableDeclaration);
888
+ }
889
+ }
890
+ }
891
+
817
892
  // src/index.ts
818
893
  function src_default() {
819
894
  return {
@@ -828,8 +903,13 @@ function src_default() {
828
903
  Program: transformProgram,
829
904
  JSXElement: transformJSX,
830
905
  JSXFragment: transformJSX,
906
+ FunctionDeclaration: replaceProps,
907
+ ArrowFunctionExpression: replaceProps,
831
908
  VariableDeclarator: replaceSymbol,
832
- ImportDeclaration: replaceImportDeclaration
909
+ ImportDeclaration: replaceImportDeclaration,
910
+ Identifier: symbolIdentifier,
911
+ ObjectPattern: symbolObjectPattern,
912
+ ArrayPattern: symbolArrayPattern
833
913
  }
834
914
  };
835
915
  }