@geajs/vite-plugin 1.0.23 → 1.0.26

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.
Files changed (2) hide show
  1. package/dist/index.js +130 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2347,6 +2347,17 @@ function detectItemIdProperty(template, itemVar) {
2347
2347
  }
2348
2348
  return void 0;
2349
2349
  }
2350
+ function extractKeyExpression(template) {
2351
+ if (!template || !t6.isJSXElement(template)) return void 0;
2352
+ for (const attr of template.openingElement.attributes) {
2353
+ if (!t6.isJSXAttribute(attr) || !t6.isJSXIdentifier(attr.name) || attr.name.name !== "key") continue;
2354
+ if (!t6.isJSXExpressionContainer(attr.value)) continue;
2355
+ const keyExpr = attr.value.expression;
2356
+ if (t6.isJSXEmptyExpression(keyExpr)) continue;
2357
+ return keyExpr;
2358
+ }
2359
+ return void 0;
2360
+ }
2350
2361
  function hasExplicitItemKey(template) {
2351
2362
  if (!template || !t6.isJSXElement(template)) return false;
2352
2363
  return template.openingElement.attributes.some(
@@ -3843,6 +3854,7 @@ function handleArrayMap(expr, tagName, node, elementPath, index, arrayMaps, stat
3843
3854
  itemVariable: itemVar2,
3844
3855
  ...indexVar2 ? { indexVariable: indexVar2 } : {},
3845
3856
  itemIdProperty: itemIdProp,
3857
+ ...!itemIdProp && hasExplicitItemKey(itemTemplate2) ? { keyExpression: t9.cloneNode(extractKeyExpression(itemTemplate2), true) } : {},
3846
3858
  rootHasUserId: hasRootUserIdAttribute(itemTemplate2),
3847
3859
  computationExpr: t9.cloneNode(normalizedArrayExpr, true),
3848
3860
  computationSetupStatements: computationSetupStatements.map((stmt) => t9.cloneNode(stmt, true)),
@@ -3956,6 +3968,7 @@ function handleArrayMap(expr, tagName, node, elementPath, index, arrayMaps, stat
3956
3968
  isImportedState: result.isImportedState || false,
3957
3969
  isKeyed,
3958
3970
  itemIdProperty: itemIdProperty || (isKeyed ? void 0 : "id"),
3971
+ ...!itemIdProperty && isKeyed ? { keyExpression: t9.cloneNode(extractKeyExpression(itemTemplate), true) } : {},
3959
3972
  classToggleName,
3960
3973
  conditionalBindings,
3961
3974
  ...cbBodyStmts.length > 0 ? { callbackBodyStatements: cbBodyStmts } : {}
@@ -4705,7 +4718,34 @@ function expressionContainsJSX(expr) {
4705
4718
  check(expr);
4706
4719
  return found;
4707
4720
  }
4721
+ function callsJSXReturningProperty(expr, classBody2) {
4722
+ if (!classBody2 || !t10.isCallExpression(expr)) return false;
4723
+ let propName;
4724
+ if (t10.isMemberExpression(expr.callee) && t10.isIdentifier(expr.callee.property) && !expr.callee.computed) {
4725
+ propName = expr.callee.property.name;
4726
+ }
4727
+ if (!propName) return false;
4728
+ for (const member of classBody2.body) {
4729
+ if (!t10.isClassProperty(member) || !member.value) continue;
4730
+ const scanValue = (node) => {
4731
+ if (t10.isObjectExpression(node)) {
4732
+ for (const prop of node.properties) {
4733
+ if (t10.isObjectProperty(prop) && t10.isIdentifier(prop.key) && prop.key.name === propName && (t10.isArrowFunctionExpression(prop.value) || t10.isFunctionExpression(prop.value))) {
4734
+ return expressionContainsJSX(prop.value);
4735
+ }
4736
+ }
4737
+ }
4738
+ if (t10.isArrayExpression(node)) {
4739
+ return node.elements.some((el) => el && scanValue(el));
4740
+ }
4741
+ return false;
4742
+ };
4743
+ if (scanValue(member.value)) return true;
4744
+ }
4745
+ return false;
4746
+ }
4708
4747
  function isChildrenPropAccess(expr) {
4748
+ if (t10.isIdentifier(expr) && expr.name === "children") return true;
4709
4749
  if (t10.isMemberExpression(expr) && t10.isIdentifier(expr.property) && expr.property.name === "children" && t10.isIdentifier(expr.object) && expr.object.name === "props")
4710
4750
  return true;
4711
4751
  if (t10.isMemberExpression(expr) && t10.isIdentifier(expr.property) && expr.property.name === "children" && t10.isMemberExpression(expr.object) && t10.isThisExpression(expr.object.object) && t10.isIdentifier(expr.object.property) && expr.object.property.name === "props")
@@ -4927,13 +4967,16 @@ function replaceJSXInExpression(node, mapJSXNodes, ctx) {
4927
4967
  normalizeDestructuredMapCallback(fn);
4928
4968
  const handlerPropsInMap = [];
4929
4969
  const mapItemVariable = t10.isIdentifier(fn.params[0]) ? fn.params[0].name : "item";
4930
- const mapItemIdProperty = detectItemIdProperty(extractItemTemplate(fn), mapItemVariable) || "id";
4970
+ const itemTemplate = extractItemTemplate(fn);
4971
+ const mapItemIdProperty = detectItemIdProperty(itemTemplate, mapItemVariable) || "id";
4972
+ const mapKeyExpr = !detectItemIdProperty(itemTemplate, mapItemVariable) && hasExplicitItemKey(itemTemplate) ? extractKeyExpression(itemTemplate) : void 0;
4931
4973
  const mapCtx = {
4932
4974
  ...ctx,
4933
4975
  inMapCallback: true,
4934
4976
  handlerPropsInMap,
4935
4977
  mapItemIdProperty,
4936
4978
  mapItemVariable,
4979
+ ...mapKeyExpr ? { mapKeyExpression: mapKeyExpr } : {},
4937
4980
  conditionalSlots: void 0,
4938
4981
  conditionalSlotCursor: void 0,
4939
4982
  conditionalSlotNodeMap: void 0
@@ -5203,7 +5246,7 @@ function processElement(node, parts, ctx, elementPath = []) {
5203
5246
  if (ctx.inMapCallback && elementPath.length === 0 && ctx.mapItemVariable) {
5204
5247
  const itemVar = ctx.mapItemVariable;
5205
5248
  const itemIdProp = ctx.mapItemIdProperty;
5206
- const itemIdExpr = itemIdProp && itemIdProp !== ITEM_IS_KEY ? t10.logicalExpression("??", buildOptionalMemberChain(t10.identifier(itemVar), itemIdProp), t10.identifier(itemVar)) : t10.callExpression(t10.identifier("String"), [t10.identifier(itemVar)]);
5249
+ const itemIdExpr = ctx.mapKeyExpression ? t10.callExpression(t10.identifier("String"), [t10.cloneNode(ctx.mapKeyExpression, true)]) : itemIdProp && itemIdProp !== ITEM_IS_KEY ? t10.logicalExpression("??", buildOptionalMemberChain(t10.identifier(itemVar), itemIdProp), t10.identifier(itemVar)) : t10.callExpression(t10.identifier("String"), [t10.identifier(itemVar)]);
5207
5250
  {
5208
5251
  parts.push({ type: "string", value: html + ' data-gea-item-id="' });
5209
5252
  parts.push({ type: "expression", value: itemIdExpr });
@@ -5568,7 +5611,7 @@ function processChildren(children, parts, ctx, elementPath, dcCursor, directChil
5568
5611
  if (expressionMayBeFalsy(rawExpr)) {
5569
5612
  expr = t10.logicalExpression("||", expr, t10.stringLiteral(""));
5570
5613
  }
5571
- const skipEscape = childCallInfo || isChildrenPropAccess(rawExpr) || expressionContainsJSX(rawExpr) || ctx.inMapCallback;
5614
+ const skipEscape = childCallInfo || isChildrenPropAccess(rawExpr) || expressionContainsJSX(rawExpr) || ctx.inMapCallback || callsJSXReturningProperty(rawExpr, ctx.classBody);
5572
5615
  const safeExpr = skipEscape ? expr : t10.callExpression(t10.identifier("__escapeHtml"), [
5573
5616
  t10.callExpression(t10.identifier("String"), [expr])
5574
5617
  ]);
@@ -5639,6 +5682,17 @@ import { appendToBody, id as id3, js as js2, jsMethod } from "eszter";
5639
5682
  import { createRequire as createRequire6 } from "module";
5640
5683
  var require7 = createRequire6(import.meta.url);
5641
5684
  var traverse6 = require7("@babel/traverse").default;
5685
+ function rewriteItemVarInExpression(expr, fromVar, toVar) {
5686
+ if (fromVar === toVar) return expr;
5687
+ const cloned = t11.cloneNode(expr, true);
5688
+ traverse6(t11.program([t11.expressionStatement(cloned)]), {
5689
+ noScope: true,
5690
+ Identifier(path) {
5691
+ if (path.node.name === fromVar) path.node.name = toVar;
5692
+ }
5693
+ });
5694
+ return cloned;
5695
+ }
5642
5696
  var EVENT_NAMES2 = /* @__PURE__ */ new Set([
5643
5697
  "click",
5644
5698
  "dblclick",
@@ -5945,7 +5999,7 @@ function generatePatchItemMethod(arrayMap, templatePropNames, wholeParamName, te
5945
5999
  }
5946
6000
  }
5947
6001
  }
5948
- const rawItemIdExpr = itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6002
+ const rawItemIdExpr = arrayMap.keyExpression ? t11.cloneNode(rewriteItemVarInExpression(arrayMap.keyExpression, arrayMap.itemVariable, "item"), true) : itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
5949
6003
  const itemIdExpr = t11.callExpression(t11.identifier("String"), [rawItemIdExpr]);
5950
6004
  body.push(
5951
6005
  t11.expressionStatement(t11.assignmentExpression("=", t11.memberExpression(elVar, t11.identifier("__geaKey")), itemIdExpr))
@@ -6600,7 +6654,7 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6600
6654
  }
6601
6655
  }
6602
6656
  }
6603
- const rawPatchItemIdExpr = itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6657
+ const rawPatchItemIdExpr = arrayMap.keyExpression ? t11.cloneNode(rewriteItemVarInExpression(arrayMap.keyExpression, arrayMap.itemVariable, "item"), true) : itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6604
6658
  const patchItemIdExpr = t11.callExpression(t11.identifier("String"), [rawPatchItemIdExpr]);
6605
6659
  body.push(
6606
6660
  t11.expressionStatement(
@@ -9564,7 +9618,8 @@ function generateRenderItemMethod(arrayMap, imports, eventHandlers, eventIdCount
9564
9618
  handlerPropsInMap,
9565
9619
  mapItemIdProperty: arrayMap.itemIdProperty || "id",
9566
9620
  mapItemVariable: arrayMap.itemVariable,
9567
- mapContainerBindingId: arrayMap.containerBindingId
9621
+ mapContainerBindingId: arrayMap.containerBindingId,
9622
+ ...arrayMap.keyExpression ? { mapKeyExpression: arrayMap.keyExpression } : {}
9568
9623
  };
9569
9624
  if (t18.isJSXFragment(modified)) {
9570
9625
  const err = new Error(
@@ -10232,6 +10287,16 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10232
10287
  traverse12(ast, {
10233
10288
  ClassDeclaration(classPath) {
10234
10289
  if (!t20.isIdentifier(classPath.node.id) || classPath.node.id.name !== className) return;
10290
+ let originalClassBody;
10291
+ traverse12(originalAST, {
10292
+ noScope: true,
10293
+ ClassDeclaration(origClass) {
10294
+ if (t20.isIdentifier(origClass.node.id) && origClass.node.id.name === className) {
10295
+ originalClassBody = origClass.node.body;
10296
+ origClass.stop();
10297
+ }
10298
+ }
10299
+ });
10235
10300
  const templateMethod = classPath.node.body.body.find(
10236
10301
  (n) => t20.isClassMethod(n) && t20.isIdentifier(n.key) && n.key.name === "template"
10237
10302
  );
@@ -10382,7 +10447,8 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10382
10447
  t20.ifStatement(notTextNode, insertNewTextNode, updateExisting)
10383
10448
  ]);
10384
10449
  } else if (pb.type === "text") {
10385
- const targetProp = pb.propName === "children" ? "innerHTML" : "textContent";
10450
+ const isHtmlProducing = pb.propName === "children" || pb.expression && originalClassBody && expressionCallsJSXReturningClassProp(pb.expression, originalClassBody);
10451
+ const targetProp = isHtmlProducing ? "innerHTML" : "textContent";
10386
10452
  const assignStmt = t20.expressionStatement(
10387
10453
  t20.assignmentExpression(
10388
10454
  "=",
@@ -10390,7 +10456,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10390
10456
  t20.cloneNode(valueExpr, true)
10391
10457
  )
10392
10458
  );
10393
- const consequent = pb.propName === "children" ? t20.blockStatement([
10459
+ const consequent = isHtmlProducing ? t20.blockStatement([
10394
10460
  assignStmt,
10395
10461
  // After replacing innerHTML for children, re-initialize child
10396
10462
  // components that were created from the new HTML string.
@@ -11058,6 +11124,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11058
11124
  itemTemplate: um.itemTemplate,
11059
11125
  isImportedState: false,
11060
11126
  itemIdProperty: um.itemIdProperty,
11127
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11061
11128
  ...um.callbackBodyStatements?.length ? { callbackBodyStatements: um.callbackBodyStatements } : {}
11062
11129
  };
11063
11130
  unresolvedBindings.push({ info: um, binding: syntheticBinding });
@@ -11077,6 +11144,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11077
11144
  mapItemAttrInfos.push({
11078
11145
  itemVariable: um.itemVariable,
11079
11146
  itemIdProperty: um.itemIdProperty,
11147
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11080
11148
  containerBindingId: um.containerBindingId,
11081
11149
  eventToken: tokenMatch ? tokenMatch[1] : void 0
11082
11150
  });
@@ -11849,6 +11917,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11849
11917
  itemVariable: arrayMap.itemVariable,
11850
11918
  ...arrayMap.indexVariable ? { indexVariable: arrayMap.indexVariable } : {},
11851
11919
  itemIdProperty: arrayMap.itemIdProperty,
11920
+ ...arrayMap.keyExpression ? { keyExpression: arrayMap.keyExpression } : {},
11852
11921
  containerElementPath: arrayMap.containerElementPath,
11853
11922
  containerBindingId: arrayMap.containerBindingId,
11854
11923
  computationExpr: computationExprSafe ?? computationExpr
@@ -12668,7 +12737,19 @@ function generateMapRegistration(arrayMap, unresolvedMap, templatePropNames, who
12668
12737
  )
12669
12738
  )
12670
12739
  ];
12671
- if (arrayMap.itemIdProperty && arrayMap.itemIdProperty !== ITEM_IS_KEY) {
12740
+ if (unresolvedMap.keyExpression) {
12741
+ const keyExpr = t20.cloneNode(unresolvedMap.keyExpression, true);
12742
+ const itemVar = unresolvedMap.itemVariable;
12743
+ traverse12(t20.program([t20.expressionStatement(keyExpr)]), {
12744
+ noScope: true,
12745
+ Identifier(path) {
12746
+ if (path.node.name === itemVar) path.node.name = "__k";
12747
+ }
12748
+ });
12749
+ registerArgs.push(
12750
+ t20.arrowFunctionExpression([t20.identifier("__k")], t20.callExpression(t20.identifier("String"), [keyExpr]))
12751
+ );
12752
+ } else if (arrayMap.itemIdProperty && arrayMap.itemIdProperty !== ITEM_IS_KEY) {
12672
12753
  registerArgs.push(t20.stringLiteral(arrayMap.itemIdProperty));
12673
12754
  }
12674
12755
  return t20.expressionStatement(
@@ -13213,6 +13294,44 @@ function getTemplateParamIdentifier(classBody2) {
13213
13294
  const binding = templateMethod ? getTemplateParamBinding(templateMethod.params[0]) : void 0;
13214
13295
  return t20.isIdentifier(binding) ? binding.name : void 0;
13215
13296
  }
13297
+ function expressionCallsJSXReturningClassProp(expr, classBody2) {
13298
+ if (!t20.isCallExpression(expr)) return false;
13299
+ let propName;
13300
+ if (t20.isMemberExpression(expr.callee) && t20.isIdentifier(expr.callee.property) && !expr.callee.computed) {
13301
+ propName = expr.callee.property.name;
13302
+ }
13303
+ if (!propName) return false;
13304
+ const scanValue = (node) => {
13305
+ if (t20.isObjectExpression(node)) {
13306
+ for (const prop of node.properties) {
13307
+ if (t20.isObjectProperty(prop) && t20.isIdentifier(prop.key) && prop.key.name === propName && (t20.isArrowFunctionExpression(prop.value) || t20.isFunctionExpression(prop.value))) {
13308
+ let found = false;
13309
+ const check = (n) => {
13310
+ if (found) return;
13311
+ if (t20.isJSXElement(n) || t20.isJSXFragment(n)) {
13312
+ found = true;
13313
+ return;
13314
+ }
13315
+ for (const key of t20.VISITOR_KEYS[n.type] || []) {
13316
+ const child = n[key];
13317
+ if (Array.isArray(child)) child.forEach((c) => c && typeof c === "object" && "type" in c && check(c));
13318
+ else if (child && typeof child === "object" && "type" in child) check(child);
13319
+ if (found) return;
13320
+ }
13321
+ };
13322
+ check(prop.value);
13323
+ return found;
13324
+ }
13325
+ }
13326
+ }
13327
+ if (t20.isArrayExpression(node)) return node.elements.some((el) => el != null && scanValue(el));
13328
+ return false;
13329
+ };
13330
+ for (const member of classBody2.body) {
13331
+ if (t20.isClassProperty(member) && member.value && scanValue(member.value)) return true;
13332
+ }
13333
+ return false;
13334
+ }
13216
13335
  function collectPropNamesFromItemTemplate(itemTemplate, templatePropNames) {
13217
13336
  if (!itemTemplate) return [];
13218
13337
  const used = /* @__PURE__ */ new Set();
@@ -13297,7 +13416,7 @@ function injectMapItemAttrsIntoTemplate(templateMethod, mapInfos) {
13297
13416
  const tagName = tagPart.slice(1).toLowerCase();
13298
13417
  const isIntrinsicRoot = !tagName.includes("-");
13299
13418
  const eventAttr = info.eventToken && isIntrinsicRoot ? ` data-gea-event="${info.eventToken}"` : "";
13300
- const itemIdExpr = info.itemIdProperty && info.itemIdProperty !== ITEM_IS_KEY ? t20.logicalExpression(
13419
+ const itemIdExpr = info.keyExpression ? t20.callExpression(t20.identifier("String"), [t20.cloneNode(info.keyExpression, true)]) : info.itemIdProperty && info.itemIdProperty !== ITEM_IS_KEY ? t20.logicalExpression(
13301
13420
  "??",
13302
13421
  buildOptionalMemberChain(t20.identifier(info.itemVariable), info.itemIdProperty),
13303
13422
  t20.identifier(info.itemVariable)
@@ -13877,6 +13996,7 @@ function transformComponentFile(ast, imports, storeImports, className, sourceFil
13877
13996
  earlyReturnBarrierIndex: analysis.earlyReturnBarrierIndex
13878
13997
  },
13879
13998
  sourceFile,
13999
+ classBody: classBody2,
13880
14000
  isRoot: true,
13881
14001
  conditionalSlots: conditionalSlotInfos,
13882
14002
  conditionalSlotCursor: { value: 0 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geajs/vite-plugin",
3
- "version": "1.0.23",
3
+ "version": "1.0.26",
4
4
  "description": "Vite plugin for Gea framework - JSX/TSX transform, reactivity, HMR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",