@geajs/vite-plugin 1.0.27 → 1.0.28

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 +127 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import babelGenerator2 from "@babel/generator";
2
+ import babelGenerator3 from "@babel/generator";
3
3
  import babelTraverse2 from "@babel/traverse";
4
4
 
5
5
  // src/parse.ts
@@ -1559,9 +1559,7 @@ function replaceIdentifierWithClonedExpr(node, name, expr) {
1559
1559
  }
1560
1560
  function optimizeBoundValueAliasesInSequence(stmts) {
1561
1561
  const out = [...stmts];
1562
- let changed = true;
1563
- while (changed) {
1564
- changed = false;
1562
+ while (true) {
1565
1563
  const idx = out.findIndex(
1566
1564
  (s) => t2.isVariableDeclaration(s) && s.declarations.length === 1 && t2.isIdentifier(s.declarations[0].id, { name: "__boundValue" })
1567
1565
  );
@@ -1576,7 +1574,6 @@ function optimizeBoundValueAliasesInSequence(stmts) {
1576
1574
  renameIdentifier(blk2, "__boundValue", aliasedName);
1577
1575
  out.length = 0;
1578
1576
  out.push(...blk2.body);
1579
- changed = true;
1580
1577
  continue;
1581
1578
  }
1582
1579
  if (!t2.isExpression(init) || !isPureExpression(init)) break;
@@ -1587,7 +1584,6 @@ function optimizeBoundValueAliasesInSequence(stmts) {
1587
1584
  replaceIdentifierWithClonedExpr(blk, "__boundValue", init);
1588
1585
  out.length = 0;
1589
1586
  out.push(...blk.body);
1590
- changed = true;
1591
1587
  }
1592
1588
  return out;
1593
1589
  }
@@ -5768,20 +5764,62 @@ function collectItemTemplatePropTree(template, itemVar) {
5768
5764
  });
5769
5765
  return tree;
5770
5766
  }
5771
- function buildDummyFromTree(tree, keyPathParts) {
5767
+ function getCalleeMemberChainFromItem(callee, itemVar) {
5768
+ const chain = [];
5769
+ let node = callee;
5770
+ while (t11.isMemberExpression(node) && !node.computed && t11.isIdentifier(node.property)) {
5771
+ chain.unshift(node.property.name);
5772
+ node = node.object;
5773
+ }
5774
+ if (!t11.isIdentifier(node, { name: itemVar }) || chain.length === 0) return null;
5775
+ return chain;
5776
+ }
5777
+ function collectItemCalleePropertyPaths(template, itemVar) {
5778
+ const paths = /* @__PURE__ */ new Set();
5779
+ const program12 = t11.program([t11.expressionStatement(t11.cloneNode(template, true))]);
5780
+ traverse6(program12, {
5781
+ noScope: true,
5782
+ CallExpression(path) {
5783
+ const chain = getCalleeMemberChainFromItem(path.node.callee, itemVar);
5784
+ if (chain) paths.add(chain.join("."));
5785
+ }
5786
+ });
5787
+ return paths;
5788
+ }
5789
+ function buildDummyFromTree(tree, keyPathParts, calleePaths, pathPrefix = []) {
5772
5790
  const props = [];
5773
5791
  for (const [key, value] of Object.entries(tree)) {
5792
+ const pathHere = [...pathPrefix, key];
5793
+ const pathStr = pathHere.join(".");
5774
5794
  const matchesKeyPath = keyPathParts && keyPathParts.length > 0 && keyPathParts[0] === key;
5775
5795
  if (matchesKeyPath && keyPathParts.length === 1) {
5776
5796
  props.push(t11.objectProperty(t11.identifier(key), t11.numericLiteral(0)));
5777
5797
  } else if (matchesKeyPath) {
5778
5798
  props.push(
5779
- t11.objectProperty(t11.identifier(key), buildDummyFromTree(value === true ? {} : value, keyPathParts.slice(1)))
5799
+ t11.objectProperty(
5800
+ t11.identifier(key),
5801
+ buildDummyFromTree(
5802
+ value === true ? {} : value,
5803
+ keyPathParts.slice(1),
5804
+ calleePaths,
5805
+ pathHere
5806
+ )
5807
+ )
5780
5808
  );
5781
5809
  } else if (value === true) {
5782
- props.push(t11.objectProperty(t11.identifier(key), t11.stringLiteral(" ")));
5810
+ props.push(
5811
+ t11.objectProperty(
5812
+ t11.identifier(key),
5813
+ calleePaths.has(pathStr) ? (
5814
+ // Return empty string so `${item.content()}` in template init does not inject "null" / escaped markup.
5815
+ t11.arrowFunctionExpression([], t11.stringLiteral(""), true)
5816
+ ) : t11.stringLiteral(" ")
5817
+ )
5818
+ );
5783
5819
  } else {
5784
- props.push(t11.objectProperty(t11.identifier(key), buildDummyFromTree(value, null)));
5820
+ props.push(
5821
+ t11.objectProperty(t11.identifier(key), buildDummyFromTree(value, null, calleePaths, pathHere))
5822
+ );
5785
5823
  }
5786
5824
  }
5787
5825
  return t11.objectExpression(props);
@@ -5792,7 +5830,6 @@ function generatePatchItemMethod(arrayMap, templatePropNames, wholeParamName, te
5792
5830
  const arrayName = arrayPath.replace(/\./g, "");
5793
5831
  const capName = arrayName.charAt(0).toUpperCase() + arrayName.slice(1);
5794
5832
  const methodName = `patch${capName}Item`;
5795
- const containerProp = `__${arrayPath.replace(/\./g, "_")}_container`;
5796
5833
  const itemIdProperty = arrayMap.itemIdProperty;
5797
5834
  const itemTemplateRootIsComponent = t11.isJSXElement(arrayMap.itemTemplate) && isComponentTag(getJSXTagName(arrayMap.itemTemplate.openingElement.name));
5798
5835
  if (itemTemplateRootIsComponent) return { method: null, privateFields: [] };
@@ -6039,6 +6076,26 @@ function generatePatchItemMethod(arrayMap, templatePropNames, wholeParamName, te
6039
6076
  privateFields: patchPrivateFields
6040
6077
  };
6041
6078
  }
6079
+ function textPatchHasItemMethodCall(expr, itemVar) {
6080
+ const calleeIsItemMethod = (callee) => t11.isMemberExpression(callee) && !callee.computed && t11.isIdentifier(callee.object, { name: itemVar });
6081
+ const visit = (e) => {
6082
+ let found = false;
6083
+ traverse6(t11.program([t11.expressionStatement(t11.cloneNode(e, true))]), {
6084
+ noScope: true,
6085
+ CallExpression(p) {
6086
+ if (calleeIsItemMethod(p.node.callee)) {
6087
+ found = true;
6088
+ p.stop();
6089
+ }
6090
+ }
6091
+ });
6092
+ return found;
6093
+ };
6094
+ if (t11.isTemplateLiteral(expr)) {
6095
+ return expr.expressions.some((ex) => visit(ex));
6096
+ }
6097
+ return visit(expr);
6098
+ }
6042
6099
  function collectPatchEntries(arrayMap) {
6043
6100
  const cloned = t11.cloneNode(arrayMap.itemTemplate, true);
6044
6101
  const tempFile = t11.file(t11.program([t11.expressionStatement(cloned)]));
@@ -6050,7 +6107,7 @@ function collectPatchEntries(arrayMap) {
6050
6107
  });
6051
6108
  const modified = tempFile.program.body[0].expression;
6052
6109
  const entries = [];
6053
- const requiresRerender = templateRequiresRerender(tempFile);
6110
+ let requiresRerender = templateRequiresRerender(tempFile);
6054
6111
  if (t11.isJSXElement(modified)) {
6055
6112
  const rootTagName = getJSXTagName(modified.openingElement.name);
6056
6113
  const rootIsComponent = isComponentTag(rootTagName);
@@ -6059,6 +6116,14 @@ function collectPatchEntries(arrayMap) {
6059
6116
  for (const ent of entries) {
6060
6117
  ent.expression = optionalizeMemberChainsAfterComputedItemKey(ent.expression, "item");
6061
6118
  }
6119
+ if (!requiresRerender) {
6120
+ for (const ent of entries) {
6121
+ if (ent.type === "text" && textPatchHasItemMethodCall(ent.expression, "item")) {
6122
+ requiresRerender = true;
6123
+ break;
6124
+ }
6125
+ }
6126
+ }
6062
6127
  return { entries, requiresRerender };
6063
6128
  }
6064
6129
  function walkJSXForPatch(node, path, entries, rootIsComponent = false) {
@@ -6347,10 +6412,12 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6347
6412
  }
6348
6413
  const propTree = collectItemTemplatePropTree(arrayMap.itemTemplate, arrayMap.itemVariable);
6349
6414
  const containerRef = t11.memberExpression(t11.thisExpression(), t11.identifier(containerProp));
6350
- const privateDcField = t11.memberExpression(t11.thisExpression(), t11.privateName(t11.identifier("__dc")));
6415
+ const dcFieldSuffix = arrayMap.containerBindingId ?? arrayPath.replace(/\./g, "_");
6416
+ const dcPrivateName = `__dc_${dcFieldSuffix}`;
6417
+ const privateDcField = t11.memberExpression(t11.thisExpression(), t11.privateName(t11.identifier(dcPrivateName)));
6351
6418
  const cVar = t11.identifier("__c");
6352
6419
  const elVar = t11.identifier("el");
6353
- const privateFields = ["__dc"];
6420
+ const privateFields = [dcPrivateName];
6354
6421
  const body = [];
6355
6422
  if (useRawStoreCache) {
6356
6423
  const privateRsField = t11.memberExpression(t11.thisExpression(), t11.privateName(t11.identifier("__rs")));
@@ -6383,10 +6450,11 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6383
6450
  )
6384
6451
  ])
6385
6452
  );
6386
- const isPrimitiveKey = !itemIdProperty || itemIdProperty === ITEM_IS_KEY;
6453
+ const isPrimitiveKey = (itemIdProperty === ITEM_IS_KEY || !itemIdProperty) && !arrayMap.keyExpression && Object.keys(propTree).length === 0;
6454
+ const calleePaths = collectItemCalleePropertyPaths(arrayMap.itemTemplate, arrayMap.itemVariable);
6387
6455
  const dummyItem = isPrimitiveKey ? t11.stringLiteral("__dummy__") : (() => {
6388
6456
  if (itemIdProperty) ensureDummyTreePath(propTree, itemIdProperty);
6389
- return buildDummyFromTree(propTree, itemIdProperty ? normalizePathParts(itemIdProperty) : null);
6457
+ return buildDummyFromTree(propTree, itemIdProperty ? normalizePathParts(itemIdProperty) : null, calleePaths);
6390
6458
  })();
6391
6459
  const hasRootClassNamePatch = patchedEntries.some((e) => e.type === "className" && e.childPath.length === 0);
6392
6460
  const tplInit = [
@@ -6658,7 +6726,10 @@ function generateCreateItemMethod(arrayMap, templatePropNames, wholeParamName, t
6658
6726
  }
6659
6727
  }
6660
6728
  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");
6729
+ const rawPatchItemIdExpr = arrayMap.keyExpression ? t11.cloneNode(
6730
+ rewriteItemVarInExpression(arrayMap.keyExpression, arrayMap.itemVariable, "item", createKeyRenames),
6731
+ true
6732
+ ) : itemIdProperty && itemIdProperty !== ITEM_IS_KEY ? t11.logicalExpression("??", buildOptionalMemberChain(t11.identifier("item"), itemIdProperty), t11.identifier("item")) : t11.identifier("item");
6662
6733
  const patchItemIdExpr = t11.callExpression(t11.identifier("String"), [rawPatchItemIdExpr]);
6663
6734
  body.push(
6664
6735
  t11.expressionStatement(
@@ -6831,7 +6902,7 @@ function buildEventIdExpr(suffix) {
6831
6902
  t12.stringLiteral("-" + suffix)
6832
6903
  );
6833
6904
  }
6834
- function jsxToStaticHtml(node, refCounter, elementPath = [], isRoot = true) {
6905
+ function jsxToStaticHtml(node, refCounter, elementPath = [], _isRoot = true) {
6835
6906
  const tagName = getJSXTagName(node.openingElement.name);
6836
6907
  const isComp = Boolean(tagName && isComponentTag(tagName));
6837
6908
  if (isComp) return null;
@@ -7471,7 +7542,9 @@ function buildCloneTemplateBody(identityPatches, contentPatches, cloneCtx) {
7471
7542
 
7472
7543
  // src/generate-events.ts
7473
7544
  import * as t13 from "@babel/types";
7545
+ import babelGenerator from "@babel/generator";
7474
7546
  import { id as id4, jsBlockBody, jsMethod as jsMethod2 } from "eszter";
7547
+ var generate2 = typeof babelGenerator.default === "function" ? babelGenerator.default : babelGenerator;
7475
7548
  function getTemplateParamContext(classBody2) {
7476
7549
  const templateMethod = classBody2.body.find(
7477
7550
  (m) => t13.isClassMethod(m) && t13.isIdentifier(m.key) && m.key.name === "template"
@@ -7495,12 +7568,26 @@ function getTemplateParamContext(classBody2) {
7495
7568
  function getMapContextKey(ctx) {
7496
7569
  const store = ctx.storeVar || "store";
7497
7570
  const path = ctx.arrayPathParts.join("_");
7498
- return `${store}_${path}_${ctx.itemIdProperty}`;
7571
+ const keyPart = ctx.keyExpression ? `expr:${generate2(ctx.keyExpression).code}` : ctx.itemIdProperty;
7572
+ return `${store}_${path}_${keyPart}`;
7499
7573
  }
7500
7574
  function ensureMapItemHelper(classBody2, ctx, helperName) {
7501
7575
  if (classBody2.body.some((m) => t13.isClassMethod(m) && t13.isIdentifier(m.key) && m.key.name === helperName)) return;
7502
7576
  const itemsExpr = buildArrayItemsExpr(ctx);
7503
- const findPredicate = ctx.itemIdProperty && ctx.itemIdProperty !== ITEM_IS_KEY ? t13.arrowFunctionExpression(
7577
+ const findPredicate = ctx.keyExpression ? t13.arrowFunctionExpression(
7578
+ [t13.identifier("__candidate")],
7579
+ t13.binaryExpression(
7580
+ "===",
7581
+ t13.callExpression(t13.identifier("String"), [
7582
+ rewriteItemVarInExpression(
7583
+ t13.cloneNode(ctx.keyExpression, true),
7584
+ ctx.itemVariable,
7585
+ "__candidate"
7586
+ )
7587
+ ]),
7588
+ t13.identifier("__itemId")
7589
+ )
7590
+ ) : ctx.itemIdProperty && ctx.itemIdProperty !== ITEM_IS_KEY ? t13.arrowFunctionExpression(
7504
7591
  [t13.identifier("__candidate")],
7505
7592
  t13.binaryExpression(
7506
7593
  "===",
@@ -8167,7 +8254,7 @@ function buildPropsBuilderMethod(child) {
8167
8254
  }
8168
8255
 
8169
8256
  // src/apply-reactivity.ts
8170
- import babelGenerator from "@babel/generator";
8257
+ import babelGenerator2 from "@babel/generator";
8171
8258
  import * as t20 from "@babel/types";
8172
8259
  import { appendToBody as appendToBody5, id as id11, js as js6, jsBlockBody as jsBlockBody4, jsExpr as jsExpr4, jsMethod as jsMethod8 } from "eszter";
8173
8260
 
@@ -9266,10 +9353,7 @@ function buildElsLookup(elsRef, containerRef, idExpr, rowVar, containerBindingId
9266
9353
  t17.binaryExpression(
9267
9354
  "<",
9268
9355
  t17.identifier("__i"),
9269
- t17.memberExpression(
9270
- t17.memberExpression(ctrLocal, t17.identifier("children")),
9271
- t17.identifier("length")
9272
- )
9356
+ t17.memberExpression(t17.memberExpression(ctrLocal, t17.identifier("children")), t17.identifier("length"))
9273
9357
  ),
9274
9358
  t17.updateExpression("++", t17.identifier("__i")),
9275
9359
  t17.blockStatement([
@@ -9755,6 +9839,7 @@ function generateRenderItemMethod(arrayMap, imports, eventHandlers, eventIdCount
9755
9839
  h.mapContext = {
9756
9840
  arrayPathParts: arrayMap.arrayPathParts || normalizePathParts(arrayMap.arrayPath || ""),
9757
9841
  itemIdProperty: arrayMap.itemIdProperty || "id",
9842
+ ...arrayMap.keyExpression ? { keyExpression: t18.cloneNode(arrayMap.keyExpression, true) } : {},
9758
9843
  itemVariable: arrayMap.itemVariable,
9759
9844
  indexVariable: arrayMap.indexVariable,
9760
9845
  isImportedState: arrayMap.isImportedState || false,
@@ -9935,7 +10020,7 @@ function generateComponentArrayResult(um, arrayPropName, imports, propNames, _cl
9935
10020
 
9936
10021
  // src/apply-reactivity.ts
9937
10022
  import { createRequire as createRequire12 } from "module";
9938
- var generate2 = "default" in babelGenerator ? babelGenerator.default : babelGenerator;
10023
+ var generate3 = "default" in babelGenerator2 ? babelGenerator2.default : babelGenerator2;
9939
10024
  var URL_ATTRS3 = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "cite", "poster", "background"]);
9940
10025
  var require13 = createRequire12(import.meta.url);
9941
10026
  var traverse12 = require13("@babel/traverse").default;
@@ -12386,7 +12471,7 @@ function applyStaticReactivity(ast, originalAST, className, sourceFile, imports,
12386
12471
  const bodyGroups = /* @__PURE__ */ new Map();
12387
12472
  for (const entry of methodEntries) {
12388
12473
  const { storeVar } = parseObserveKey(entry.observeKey);
12389
- const bodyCode = (storeVar || "") + ":" + generate2(t20.blockStatement(entry.method.body.body)).code;
12474
+ const bodyCode = (storeVar || "") + ":" + generate3(t20.blockStatement(entry.method.body.body)).code;
12390
12475
  if (!bodyGroups.has(bodyCode)) bodyGroups.set(bodyCode, []);
12391
12476
  bodyGroups.get(bodyCode).push(entry);
12392
12477
  }
@@ -12753,9 +12838,7 @@ function generateMapRegistration(arrayMap, unresolvedMap, templatePropNames, who
12753
12838
  }
12754
12839
  });
12755
12840
  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
- );
12841
+ registerArgs.push(t20.arrowFunctionExpression(keyFnParams, t20.callExpression(t20.identifier("String"), [keyExpr])));
12759
12842
  } else if (arrayMap.itemIdProperty && arrayMap.itemIdProperty !== ITEM_IS_KEY) {
12760
12843
  registerArgs.push(t20.stringLiteral(arrayMap.itemIdProperty));
12761
12844
  }
@@ -14526,7 +14609,7 @@ function resolveDefault(mod) {
14526
14609
  throw new Error("resolveDefault: expected a function or module with default export");
14527
14610
  }
14528
14611
  var traverse16 = resolveDefault(babelTraverse2);
14529
- var generate3 = resolveDefault(babelGenerator2);
14612
+ var generate4 = resolveDefault(babelGenerator3);
14530
14613
  function hasSSREnvironment(ctx) {
14531
14614
  if (!("environment" in ctx)) return false;
14532
14615
  const env = ctx.environment;
@@ -14762,6 +14845,13 @@ function isComponentImportSource(source) {
14762
14845
  if (source.startsWith("node:")) return false;
14763
14846
  return true;
14764
14847
  }
14848
+ function looksLikeGeaFunctionalComponentSource(source) {
14849
+ if (!source.includes("<") || !source.includes(">")) return false;
14850
+ if (/export\s+default\s+async\s+function\b/.test(source)) return true;
14851
+ if (/export\s+default\s+function\b/.test(source)) return true;
14852
+ if (/export\s+default\s*\([^)]*\)\s*=>\s*/.test(source)) return true;
14853
+ return false;
14854
+ }
14765
14855
  function geaPlugin() {
14766
14856
  const storeModules = /* @__PURE__ */ new Set();
14767
14857
  const componentModules = /* @__PURE__ */ new Set();
@@ -14821,6 +14911,10 @@ function geaPlugin() {
14821
14911
  componentModules.add(filePath);
14822
14912
  return true;
14823
14913
  }
14914
+ if (looksLikeGeaFunctionalComponentSource(source)) {
14915
+ componentModules.add(filePath);
14916
+ return true;
14917
+ }
14824
14918
  return false;
14825
14919
  } catch {
14826
14920
  return false;
@@ -14903,7 +14997,7 @@ ${entries.join(",\n")}
14903
14997
  convertFunctionalToClass(ast, functionalComponentInfo, imports);
14904
14998
  componentClassName = functionalComponentInfo.name;
14905
14999
  componentClassNames = [functionalComponentInfo.name];
14906
- const freshCode = generate3(ast, { retainLines: true }).code;
15000
+ const freshCode = generate4(ast, { retainLines: true }).code;
14907
15001
  const freshParsed = parseSource(freshCode);
14908
15002
  if (freshParsed) {
14909
15003
  ast = freshParsed.ast;
@@ -15025,7 +15119,7 @@ ${entries.join(",\n")}
15025
15119
  if (!transformed) return null;
15026
15120
  ensureImport(ast, "@geajs/core", "__escapeHtml");
15027
15121
  ensureImport(ast, "@geajs/core", "__sanitizeAttr");
15028
- const output = generate3(ast, { sourceMaps: true, sourceFileName: cleanId }, code);
15122
+ const output = generate4(ast, { sourceMaps: true, sourceFileName: cleanId }, code);
15029
15123
  return { code: output.code, map: output.map };
15030
15124
  } catch (error) {
15031
15125
  if (error?.__geaCompileError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geajs/vite-plugin",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "Vite plugin for Gea framework - JSX/TSX transform, reactivity, HMR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",