@geajs/vite-plugin 1.0.24 → 1.0.27

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 +136 -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,6 +4718,32 @@ 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) {
4709
4748
  if (t10.isIdentifier(expr) && expr.name === "children") return true;
4710
4749
  if (t10.isMemberExpression(expr) && t10.isIdentifier(expr.property) && expr.property.name === "children" && t10.isIdentifier(expr.object) && expr.object.name === "props")
@@ -4928,13 +4967,16 @@ function replaceJSXInExpression(node, mapJSXNodes, ctx) {
4928
4967
  normalizeDestructuredMapCallback(fn);
4929
4968
  const handlerPropsInMap = [];
4930
4969
  const mapItemVariable = t10.isIdentifier(fn.params[0]) ? fn.params[0].name : "item";
4931
- 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;
4932
4973
  const mapCtx = {
4933
4974
  ...ctx,
4934
4975
  inMapCallback: true,
4935
4976
  handlerPropsInMap,
4936
4977
  mapItemIdProperty,
4937
4978
  mapItemVariable,
4979
+ ...mapKeyExpr ? { mapKeyExpression: mapKeyExpr } : {},
4938
4980
  conditionalSlots: void 0,
4939
4981
  conditionalSlotCursor: void 0,
4940
4982
  conditionalSlotNodeMap: void 0
@@ -5204,7 +5246,7 @@ function processElement(node, parts, ctx, elementPath = []) {
5204
5246
  if (ctx.inMapCallback && elementPath.length === 0 && ctx.mapItemVariable) {
5205
5247
  const itemVar = ctx.mapItemVariable;
5206
5248
  const itemIdProp = ctx.mapItemIdProperty;
5207
- 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)]);
5208
5250
  {
5209
5251
  parts.push({ type: "string", value: html + ' data-gea-item-id="' });
5210
5252
  parts.push({ type: "expression", value: itemIdExpr });
@@ -5569,7 +5611,7 @@ function processChildren(children, parts, ctx, elementPath, dcCursor, directChil
5569
5611
  if (expressionMayBeFalsy(rawExpr)) {
5570
5612
  expr = t10.logicalExpression("||", expr, t10.stringLiteral(""));
5571
5613
  }
5572
- const skipEscape = childCallInfo || isChildrenPropAccess(rawExpr) || expressionContainsJSX(rawExpr) || ctx.inMapCallback;
5614
+ const skipEscape = childCallInfo || isChildrenPropAccess(rawExpr) || expressionContainsJSX(rawExpr) || ctx.inMapCallback || callsJSXReturningProperty(rawExpr, ctx.classBody);
5573
5615
  const safeExpr = skipEscape ? expr : t10.callExpression(t10.identifier("__escapeHtml"), [
5574
5616
  t10.callExpression(t10.identifier("String"), [expr])
5575
5617
  ]);
@@ -5640,6 +5682,19 @@ import { appendToBody, id as id3, js as js2, jsMethod } from "eszter";
5640
5682
  import { createRequire as createRequire6 } from "module";
5641
5683
  var require7 = createRequire6(import.meta.url);
5642
5684
  var traverse6 = require7("@babel/traverse").default;
5685
+ function rewriteItemVarInExpression(expr, fromVar, toVar, renames) {
5686
+ const renameMap = new Map(renames || []);
5687
+ renameMap.set(fromVar, toVar);
5688
+ const cloned = t11.cloneNode(expr, true);
5689
+ traverse6(t11.program([t11.expressionStatement(cloned)]), {
5690
+ noScope: true,
5691
+ Identifier(path) {
5692
+ const replacement = renameMap.get(path.node.name);
5693
+ if (replacement) path.node.name = replacement;
5694
+ }
5695
+ });
5696
+ return cloned;
5697
+ }
5643
5698
  var EVENT_NAMES2 = /* @__PURE__ */ new Set([
5644
5699
  "click",
5645
5700
  "dblclick",
@@ -5946,7 +6001,8 @@ function generatePatchItemMethod(arrayMap, templatePropNames, wholeParamName, te
5946
6001
  }
5947
6002
  }
5948
6003
  }
5949
- const rawItemIdExpr = itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6004
+ const keyRenames = arrayMap.indexVariable ? /* @__PURE__ */ new Map([[arrayMap.indexVariable, "__idx"]]) : void 0;
6005
+ const rawItemIdExpr = arrayMap.keyExpression ? t11.cloneNode(rewriteItemVarInExpression(arrayMap.keyExpression, arrayMap.itemVariable, "item", keyRenames), true) : itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
5950
6006
  const itemIdExpr = t11.callExpression(t11.identifier("String"), [rawItemIdExpr]);
5951
6007
  body.push(
5952
6008
  t11.expressionStatement(t11.assignmentExpression("=", t11.memberExpression(elVar, t11.identifier("__geaKey")), itemIdExpr))
@@ -6601,7 +6657,8 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6601
6657
  }
6602
6658
  }
6603
6659
  }
6604
- const rawPatchItemIdExpr = itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6660
+ const createKeyRenames = arrayMap.indexVariable ? /* @__PURE__ */ new Map([[arrayMap.indexVariable, "__idx"]]) : void 0;
6661
+ const rawPatchItemIdExpr = arrayMap.keyExpression ? t11.cloneNode(rewriteItemVarInExpression(arrayMap.keyExpression, arrayMap.itemVariable, "item", createKeyRenames), true) : itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6605
6662
  const patchItemIdExpr = t11.callExpression(t11.identifier("String"), [rawPatchItemIdExpr]);
6606
6663
  body.push(
6607
6664
  t11.expressionStatement(
@@ -9565,7 +9622,8 @@ function generateRenderItemMethod(arrayMap, imports, eventHandlers, eventIdCount
9565
9622
  handlerPropsInMap,
9566
9623
  mapItemIdProperty: arrayMap.itemIdProperty || "id",
9567
9624
  mapItemVariable: arrayMap.itemVariable,
9568
- mapContainerBindingId: arrayMap.containerBindingId
9625
+ mapContainerBindingId: arrayMap.containerBindingId,
9626
+ ...arrayMap.keyExpression ? { mapKeyExpression: arrayMap.keyExpression } : {}
9569
9627
  };
9570
9628
  if (t18.isJSXFragment(modified)) {
9571
9629
  const err = new Error(
@@ -10233,6 +10291,16 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10233
10291
  traverse12(ast, {
10234
10292
  ClassDeclaration(classPath) {
10235
10293
  if (!t20.isIdentifier(classPath.node.id) || classPath.node.id.name !== className) return;
10294
+ let originalClassBody;
10295
+ traverse12(originalAST, {
10296
+ noScope: true,
10297
+ ClassDeclaration(origClass) {
10298
+ if (t20.isIdentifier(origClass.node.id) && origClass.node.id.name === className) {
10299
+ originalClassBody = origClass.node.body;
10300
+ origClass.stop();
10301
+ }
10302
+ }
10303
+ });
10236
10304
  const templateMethod = classPath.node.body.body.find(
10237
10305
  (n) => t20.isClassMethod(n) && t20.isIdentifier(n.key) && n.key.name === "template"
10238
10306
  );
@@ -10383,7 +10451,8 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10383
10451
  t20.ifStatement(notTextNode, insertNewTextNode, updateExisting)
10384
10452
  ]);
10385
10453
  } else if (pb.type === "text") {
10386
- const targetProp = pb.propName === "children" ? "innerHTML" : "textContent";
10454
+ const isHtmlProducing = pb.propName === "children" || pb.expression && originalClassBody && expressionCallsJSXReturningClassProp(pb.expression, originalClassBody);
10455
+ const targetProp = isHtmlProducing ? "innerHTML" : "textContent";
10387
10456
  const assignStmt = t20.expressionStatement(
10388
10457
  t20.assignmentExpression(
10389
10458
  "=",
@@ -10391,7 +10460,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10391
10460
  t20.cloneNode(valueExpr, true)
10392
10461
  )
10393
10462
  );
10394
- const consequent = pb.propName === "children" ? t20.blockStatement([
10463
+ const consequent = isHtmlProducing ? t20.blockStatement([
10395
10464
  assignStmt,
10396
10465
  // After replacing innerHTML for children, re-initialize child
10397
10466
  // components that were created from the new HTML string.
@@ -11059,6 +11128,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11059
11128
  itemTemplate: um.itemTemplate,
11060
11129
  isImportedState: false,
11061
11130
  itemIdProperty: um.itemIdProperty,
11131
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11062
11132
  ...um.callbackBodyStatements?.length ? { callbackBodyStatements: um.callbackBodyStatements } : {}
11063
11133
  };
11064
11134
  unresolvedBindings.push({ info: um, binding: syntheticBinding });
@@ -11078,6 +11148,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11078
11148
  mapItemAttrInfos.push({
11079
11149
  itemVariable: um.itemVariable,
11080
11150
  itemIdProperty: um.itemIdProperty,
11151
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11081
11152
  containerBindingId: um.containerBindingId,
11082
11153
  eventToken: tokenMatch ? tokenMatch[1] : void 0
11083
11154
  });
@@ -11850,6 +11921,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11850
11921
  itemVariable: arrayMap.itemVariable,
11851
11922
  ...arrayMap.indexVariable ? { indexVariable: arrayMap.indexVariable } : {},
11852
11923
  itemIdProperty: arrayMap.itemIdProperty,
11924
+ ...arrayMap.keyExpression ? { keyExpression: arrayMap.keyExpression } : {},
11853
11925
  containerElementPath: arrayMap.containerElementPath,
11854
11926
  containerBindingId: arrayMap.containerBindingId,
11855
11927
  computationExpr: computationExprSafe ?? computationExpr
@@ -12669,7 +12741,22 @@ function generateMapRegistration(arrayMap, unresolvedMap, templatePropNames, who
12669
12741
  )
12670
12742
  )
12671
12743
  ];
12672
- if (arrayMap.itemIdProperty && arrayMap.itemIdProperty !== ITEM_IS_KEY) {
12744
+ if (unresolvedMap.keyExpression) {
12745
+ const keyExpr = t20.cloneNode(unresolvedMap.keyExpression, true);
12746
+ const itemVar = unresolvedMap.itemVariable;
12747
+ const idxVar = unresolvedMap.indexVariable;
12748
+ traverse12(t20.program([t20.expressionStatement(keyExpr)]), {
12749
+ noScope: true,
12750
+ Identifier(path) {
12751
+ if (path.node.name === itemVar) path.node.name = "__k";
12752
+ else if (idxVar && path.node.name === idxVar) path.node.name = "__ki";
12753
+ }
12754
+ });
12755
+ const keyFnParams = idxVar ? [t20.identifier("__k"), t20.identifier("__ki")] : [t20.identifier("__k")];
12756
+ registerArgs.push(
12757
+ t20.arrowFunctionExpression(keyFnParams, t20.callExpression(t20.identifier("String"), [keyExpr]))
12758
+ );
12759
+ } else if (arrayMap.itemIdProperty && arrayMap.itemIdProperty !== ITEM_IS_KEY) {
12673
12760
  registerArgs.push(t20.stringLiteral(arrayMap.itemIdProperty));
12674
12761
  }
12675
12762
  return t20.expressionStatement(
@@ -13214,6 +13301,44 @@ function getTemplateParamIdentifier(classBody2) {
13214
13301
  const binding = templateMethod ? getTemplateParamBinding(templateMethod.params[0]) : void 0;
13215
13302
  return t20.isIdentifier(binding) ? binding.name : void 0;
13216
13303
  }
13304
+ function expressionCallsJSXReturningClassProp(expr, classBody2) {
13305
+ if (!t20.isCallExpression(expr)) return false;
13306
+ let propName;
13307
+ if (t20.isMemberExpression(expr.callee) && t20.isIdentifier(expr.callee.property) && !expr.callee.computed) {
13308
+ propName = expr.callee.property.name;
13309
+ }
13310
+ if (!propName) return false;
13311
+ const scanValue = (node) => {
13312
+ if (t20.isObjectExpression(node)) {
13313
+ for (const prop of node.properties) {
13314
+ if (t20.isObjectProperty(prop) && t20.isIdentifier(prop.key) && prop.key.name === propName && (t20.isArrowFunctionExpression(prop.value) || t20.isFunctionExpression(prop.value))) {
13315
+ let found = false;
13316
+ const check = (n) => {
13317
+ if (found) return;
13318
+ if (t20.isJSXElement(n) || t20.isJSXFragment(n)) {
13319
+ found = true;
13320
+ return;
13321
+ }
13322
+ for (const key of t20.VISITOR_KEYS[n.type] || []) {
13323
+ const child = n[key];
13324
+ if (Array.isArray(child)) child.forEach((c) => c && typeof c === "object" && "type" in c && check(c));
13325
+ else if (child && typeof child === "object" && "type" in child) check(child);
13326
+ if (found) return;
13327
+ }
13328
+ };
13329
+ check(prop.value);
13330
+ return found;
13331
+ }
13332
+ }
13333
+ }
13334
+ if (t20.isArrayExpression(node)) return node.elements.some((el) => el != null && scanValue(el));
13335
+ return false;
13336
+ };
13337
+ for (const member of classBody2.body) {
13338
+ if (t20.isClassProperty(member) && member.value && scanValue(member.value)) return true;
13339
+ }
13340
+ return false;
13341
+ }
13217
13342
  function collectPropNamesFromItemTemplate(itemTemplate, templatePropNames) {
13218
13343
  if (!itemTemplate) return [];
13219
13344
  const used = /* @__PURE__ */ new Set();
@@ -13298,7 +13423,7 @@ function injectMapItemAttrsIntoTemplate(templateMethod, mapInfos) {
13298
13423
  const tagName = tagPart.slice(1).toLowerCase();
13299
13424
  const isIntrinsicRoot = !tagName.includes("-");
13300
13425
  const eventAttr = info.eventToken && isIntrinsicRoot ? ` data-gea-event="${info.eventToken}"` : "";
13301
- const itemIdExpr = info.itemIdProperty && info.itemIdProperty !== ITEM_IS_KEY ? t20.logicalExpression(
13426
+ const itemIdExpr = info.keyExpression ? t20.callExpression(t20.identifier("String"), [t20.cloneNode(info.keyExpression, true)]) : info.itemIdProperty && info.itemIdProperty !== ITEM_IS_KEY ? t20.logicalExpression(
13302
13427
  "??",
13303
13428
  buildOptionalMemberChain(t20.identifier(info.itemVariable), info.itemIdProperty),
13304
13429
  t20.identifier(info.itemVariable)
@@ -13878,6 +14003,7 @@ function transformComponentFile(ast, imports, storeImports, className, sourceFil
13878
14003
  earlyReturnBarrierIndex: analysis.earlyReturnBarrierIndex
13879
14004
  },
13880
14005
  sourceFile,
14006
+ classBody: classBody2,
13881
14007
  isRoot: true,
13882
14008
  conditionalSlots: conditionalSlotInfos,
13883
14009
  conditionalSlotCursor: { value: 0 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geajs/vite-plugin",
3
- "version": "1.0.24",
3
+ "version": "1.0.27",
4
4
  "description": "Vite plugin for Gea framework - JSX/TSX transform, reactivity, HMR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",