@geajs/vite-plugin 1.0.24 → 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 +129 -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,17 @@ 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) {
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
+ }
5643
5696
  var EVENT_NAMES2 = /* @__PURE__ */ new Set([
5644
5697
  "click",
5645
5698
  "dblclick",
@@ -5946,7 +5999,7 @@ function generatePatchItemMethod(arrayMap, templatePropNames, wholeParamName, te
5946
5999
  }
5947
6000
  }
5948
6001
  }
5949
- 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");
5950
6003
  const itemIdExpr = t11.callExpression(t11.identifier("String"), [rawItemIdExpr]);
5951
6004
  body.push(
5952
6005
  t11.expressionStatement(t11.assignmentExpression("=", t11.memberExpression(elVar, t11.identifier("__geaKey")), itemIdExpr))
@@ -6601,7 +6654,7 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6601
6654
  }
6602
6655
  }
6603
6656
  }
6604
- 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");
6605
6658
  const patchItemIdExpr = t11.callExpression(t11.identifier("String"), [rawPatchItemIdExpr]);
6606
6659
  body.push(
6607
6660
  t11.expressionStatement(
@@ -9565,7 +9618,8 @@ function generateRenderItemMethod(arrayMap, imports, eventHandlers, eventIdCount
9565
9618
  handlerPropsInMap,
9566
9619
  mapItemIdProperty: arrayMap.itemIdProperty || "id",
9567
9620
  mapItemVariable: arrayMap.itemVariable,
9568
- mapContainerBindingId: arrayMap.containerBindingId
9621
+ mapContainerBindingId: arrayMap.containerBindingId,
9622
+ ...arrayMap.keyExpression ? { mapKeyExpression: arrayMap.keyExpression } : {}
9569
9623
  };
9570
9624
  if (t18.isJSXFragment(modified)) {
9571
9625
  const err = new Error(
@@ -10233,6 +10287,16 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10233
10287
  traverse12(ast, {
10234
10288
  ClassDeclaration(classPath) {
10235
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
+ });
10236
10300
  const templateMethod = classPath.node.body.body.find(
10237
10301
  (n) => t20.isClassMethod(n) && t20.isIdentifier(n.key) && n.key.name === "template"
10238
10302
  );
@@ -10383,7 +10447,8 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10383
10447
  t20.ifStatement(notTextNode, insertNewTextNode, updateExisting)
10384
10448
  ]);
10385
10449
  } else if (pb.type === "text") {
10386
- 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";
10387
10452
  const assignStmt = t20.expressionStatement(
10388
10453
  t20.assignmentExpression(
10389
10454
  "=",
@@ -10391,7 +10456,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
10391
10456
  t20.cloneNode(valueExpr, true)
10392
10457
  )
10393
10458
  );
10394
- const consequent = pb.propName === "children" ? t20.blockStatement([
10459
+ const consequent = isHtmlProducing ? t20.blockStatement([
10395
10460
  assignStmt,
10396
10461
  // After replacing innerHTML for children, re-initialize child
10397
10462
  // components that were created from the new HTML string.
@@ -11059,6 +11124,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11059
11124
  itemTemplate: um.itemTemplate,
11060
11125
  isImportedState: false,
11061
11126
  itemIdProperty: um.itemIdProperty,
11127
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11062
11128
  ...um.callbackBodyStatements?.length ? { callbackBodyStatements: um.callbackBodyStatements } : {}
11063
11129
  };
11064
11130
  unresolvedBindings.push({ info: um, binding: syntheticBinding });
@@ -11078,6 +11144,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11078
11144
  mapItemAttrInfos.push({
11079
11145
  itemVariable: um.itemVariable,
11080
11146
  itemIdProperty: um.itemIdProperty,
11147
+ ...um.keyExpression ? { keyExpression: um.keyExpression } : {},
11081
11148
  containerBindingId: um.containerBindingId,
11082
11149
  eventToken: tokenMatch ? tokenMatch[1] : void 0
11083
11150
  });
@@ -11850,6 +11917,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
11850
11917
  itemVariable: arrayMap.itemVariable,
11851
11918
  ...arrayMap.indexVariable ? { indexVariable: arrayMap.indexVariable } : {},
11852
11919
  itemIdProperty: arrayMap.itemIdProperty,
11920
+ ...arrayMap.keyExpression ? { keyExpression: arrayMap.keyExpression } : {},
11853
11921
  containerElementPath: arrayMap.containerElementPath,
11854
11922
  containerBindingId: arrayMap.containerBindingId,
11855
11923
  computationExpr: computationExprSafe ?? computationExpr
@@ -12669,7 +12737,19 @@ function generateMapRegistration(arrayMap, unresolvedMap, templatePropNames, who
12669
12737
  )
12670
12738
  )
12671
12739
  ];
12672
- 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) {
12673
12753
  registerArgs.push(t20.stringLiteral(arrayMap.itemIdProperty));
12674
12754
  }
12675
12755
  return t20.expressionStatement(
@@ -13214,6 +13294,44 @@ function getTemplateParamIdentifier(classBody2) {
13214
13294
  const binding = templateMethod ? getTemplateParamBinding(templateMethod.params[0]) : void 0;
13215
13295
  return t20.isIdentifier(binding) ? binding.name : void 0;
13216
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
+ }
13217
13335
  function collectPropNamesFromItemTemplate(itemTemplate, templatePropNames) {
13218
13336
  if (!itemTemplate) return [];
13219
13337
  const used = /* @__PURE__ */ new Set();
@@ -13298,7 +13416,7 @@ function injectMapItemAttrsIntoTemplate(templateMethod, mapInfos) {
13298
13416
  const tagName = tagPart.slice(1).toLowerCase();
13299
13417
  const isIntrinsicRoot = !tagName.includes("-");
13300
13418
  const eventAttr = info.eventToken && isIntrinsicRoot ? ` data-gea-event="${info.eventToken}"` : "";
13301
- 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(
13302
13420
  "??",
13303
13421
  buildOptionalMemberChain(t20.identifier(info.itemVariable), info.itemIdProperty),
13304
13422
  t20.identifier(info.itemVariable)
@@ -13878,6 +13996,7 @@ function transformComponentFile(ast, imports, storeImports, className, sourceFil
13878
13996
  earlyReturnBarrierIndex: analysis.earlyReturnBarrierIndex
13879
13997
  },
13880
13998
  sourceFile,
13999
+ classBody: classBody2,
13881
14000
  isRoot: true,
13882
14001
  conditionalSlots: conditionalSlotInfos,
13883
14002
  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.26",
4
4
  "description": "Vite plugin for Gea framework - JSX/TSX transform, reactivity, HMR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",