@barefootjs/vite 0.31.8 → 0.31.10

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 +226 -66
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -3113,8 +3113,8 @@ function templateAttrExpr(attrName, valExpr, presenceOrUndefined) {
3113
3113
  function escapeAttrValueExpr(valExpr) {
3114
3114
  return `escapeAttr(${valExpr})`;
3115
3115
  }
3116
- function escapeTextSlotExpr(innerExpr) {
3117
- return `escapeText(${innerExpr})`;
3116
+ function escapeTextSlotExpr(innerExpr, isMarkup = false) {
3117
+ return `${isMarkup ? "escapeTextOrMarkup" : "escapeText"}(${innerExpr})`;
3118
3118
  }
3119
3119
  function dangerouslyHtmlChildren(attrs, toExpr) {
3120
3120
  const attr = attrs.find((a) => a.name === "dangerouslySetInnerHTML");
@@ -3391,7 +3391,7 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
3391
3391
  case "jsx-children": {
3392
3392
  const hoistedRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, true);
3393
3393
  const childHtml = p.value.children.map((c) => hoistedRecurse(c)).join("");
3394
- return `${quotePropName(p.name)}: \`${childHtml}\``;
3394
+ return p.name === "children" ? `${quotePropName(p.name)}: \`${childHtml}\`` : `${quotePropName(p.name)}: bfMarkup(\`${childHtml}\`)`;
3395
3395
  }
3396
3396
  case "literal":
3397
3397
  return `${quotePropName(p.name)}: ${JSON.stringify(p.value.value)}`;
@@ -3750,6 +3750,9 @@ function irChildrenToJsExpr(children) {
3750
3750
  return exprs[0];
3751
3751
  return `[${exprs.join(", ")}]`;
3752
3752
  }
3753
+ function isSingleElementJsxChildren(nodes) {
3754
+ return nodes.length === 1 && nodes[0].type === "element";
3755
+ }
3753
3756
  function irNodeToJsExprs(node) {
3754
3757
  switch (node.type) {
3755
3758
  case "component": {
@@ -3758,8 +3761,11 @@ function irNodeToJsExprs(node) {
3758
3761
  return `${quotePropName(p.name)}: ${attrValueToString(p.value) ?? "undefined"}`;
3759
3762
  }
3760
3763
  switch (p.value.kind) {
3761
- case "jsx-children":
3762
- return `get ${quotePropName(p.name)}() { return ${irChildrenToJsExpr(p.value.children)} }`;
3764
+ case "jsx-children": {
3765
+ const jsxExpr = irChildrenToJsExpr(p.value.children);
3766
+ const wrapped = p.name !== "children" && isSingleElementJsxChildren(p.value.children) ? `bfMarkup(${jsxExpr})` : jsxExpr;
3767
+ return `get ${quotePropName(p.name)}() { return ${wrapped} }`;
3768
+ }
3763
3769
  case "literal":
3764
3770
  return `get ${quotePropName(p.name)}() { return ${JSON.stringify(p.value.value)} }`;
3765
3771
  case "boolean-shorthand":
@@ -3818,8 +3824,8 @@ function isSingleRootElement(html) {
3818
3824
  const closingPattern = new RegExp(`</${tag}>\\s*$`);
3819
3825
  return closingPattern.test(html.trim());
3820
3826
  }
3821
- function irToComponentTemplate(node, inlinableConstants, restSpreadNames, propsObjectName) {
3822
- return irToComponentTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, loopDepth: -1 });
3827
+ function irToComponentTemplate(node, inlinableConstants, restSpreadNames, propsObjectName, markupSlotIds) {
3828
+ return irToComponentTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, loopDepth: -1, markupSlotIds });
3823
3829
  }
3824
3830
  function irToComponentTemplateWithOpts(node, opts) {
3825
3831
  const { inlinableConstants, restSpreadNames, propsObjectName, loopDepth = 0 } = opts;
@@ -3924,7 +3930,8 @@ function irToComponentTemplateWithOpts(node, opts) {
3924
3930
  const wrapped = transformExpr(node.expr, node.templateExpr);
3925
3931
  const value = node.joinArrayChild ? `Array.isArray(${wrapped}) ? ${wrapped}.join('') : (${wrapped} ?? '')` : wrapped;
3926
3932
  if (node.slotId) {
3927
- return `<!--bf:${node.slotId}-->\${${node.joinArrayChild ? value : escapeTextSlotExpr(wrapped)}}<!--/-->`;
3933
+ const isMarkup = opts.markupSlotIds?.has(node.slotId) ?? false;
3934
+ return `<!--bf:${node.slotId}-->\${${node.joinArrayChild ? value : escapeTextSlotExpr(wrapped, isMarkup)}}<!--/-->`;
3928
3935
  }
3929
3936
  return `\${${value}}`;
3930
3937
  }
@@ -3951,7 +3958,7 @@ function irToComponentTemplateWithOpts(node, opts) {
3951
3958
  case "jsx-children": {
3952
3959
  const hoistedRecurse = (n) => irToComponentTemplateWithOpts(n, { ...opts, inHoistedChildren: true });
3953
3960
  const childHtml = p.value.children.map((c) => hoistedRecurse(c)).join("");
3954
- return `${quotePropName(p.name)}: \`${childHtml}\``;
3961
+ return p.name === "children" ? `${quotePropName(p.name)}: \`${childHtml}\`` : `${quotePropName(p.name)}: bfMarkup(\`${childHtml}\`)`;
3955
3962
  }
3956
3963
  case "literal":
3957
3964
  return `${quotePropName(p.name)}: ${JSON.stringify(p.value.value)}`;
@@ -4072,7 +4079,8 @@ function generateCsrTemplate(node, inlinableConstants, ctx, restSpreadNames, pro
4072
4079
  }
4073
4080
  }
4074
4081
  const effectiveUnsafeLocalNames = mergeCsrNullUnsafe(ctx, unsafeLocalNames);
4075
- return generateCsrTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, csrEnv, unsafeLocalNames: effectiveUnsafeLocalNames, deferredChildSlots, loopDepth: -1 });
4082
+ const markupSlotIds = new Set(ctx.dynamicElements.map((e) => e.slotId));
4083
+ return generateCsrTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, csrEnv, unsafeLocalNames: effectiveUnsafeLocalNames, deferredChildSlots, loopDepth: -1, markupSlotIds });
4076
4084
  }
4077
4085
  function mergeCsrNullUnsafe(ctx, unsafeLocalNames) {
4078
4086
  let merged = null;
@@ -4253,7 +4261,8 @@ function generateCsrTemplateWithOpts(node, opts) {
4253
4261
  const expr = transformed === UNSAFE_TEMPLATE_EXPR ? "''" : transformed;
4254
4262
  const value = node.joinArrayChild ? `Array.isArray(${expr}) ? ${expr}.join('') : (${expr} ?? '')` : expr;
4255
4263
  if (node.slotId) {
4256
- return `<!--bf:${node.slotId}-->\${${node.joinArrayChild ? value : escapeTextSlotExpr(expr)}}<!--/-->`;
4264
+ const isMarkup = opts.markupSlotIds?.has(node.slotId) ?? false;
4265
+ return `<!--bf:${node.slotId}-->\${${node.joinArrayChild ? value : escapeTextSlotExpr(expr, isMarkup)}}<!--/-->`;
4257
4266
  }
4258
4267
  return `\${${value}}`;
4259
4268
  }
@@ -4283,7 +4292,7 @@ function generateCsrTemplateWithOpts(node, opts) {
4283
4292
  case "jsx-children": {
4284
4293
  const hoistedRecurse = (n) => generateCsrTemplateWithOpts(n, { ...opts, inHoistedChildren: true });
4285
4294
  const childHtml = p.value.children.map((c) => hoistedRecurse(c)).join("");
4286
- return `${quotePropName(p.name)}: \`${childHtml}\``;
4295
+ return p.name === "children" ? `${quotePropName(p.name)}: \`${childHtml}\`` : `${quotePropName(p.name)}: bfMarkup(\`${childHtml}\`)`;
4287
4296
  }
4288
4297
  case "literal":
4289
4298
  return `${quotePropName(p.name)}: ${JSON.stringify(p.value.value)}`;
@@ -7271,15 +7280,28 @@ function collectKeysFromMembers(members, ctx) {
7271
7280
  }
7272
7281
  return keys;
7273
7282
  }
7283
+ function isResolvableMemberType(info) {
7284
+ switch (info.kind) {
7285
+ case "primitive":
7286
+ return info.primitive === "string" || info.primitive === "number" || info.primitive === "boolean";
7287
+ case "interface":
7288
+ return CATALOGUED_RICH_TYPE_NAMES.has(baseTypeName(info.raw));
7289
+ case "array":
7290
+ return !!info.elementType && isResolvableMemberType(info.elementType);
7291
+ case "object":
7292
+ return info.properties !== undefined && info.properties.every((prop) => isResolvableMemberType(prop.type));
7293
+ default:
7294
+ return false;
7295
+ }
7296
+ }
7274
7297
  function collectMemberTypes(typeNode, ctx) {
7275
- const isResolvablePrimitive = (info) => info.kind === "primitive" && (info.primitive === "string" || info.primitive === "number" || info.primitive === "boolean") || info.kind === "interface" && CATALOGUED_RICH_TYPE_NAMES.has(baseTypeName(info.raw));
7276
7298
  const fromMembers = (members) => {
7277
7299
  const map = new Map;
7278
7300
  for (const member of members) {
7279
7301
  if (ts9.isPropertySignature(member) && member.name) {
7280
7302
  const info = member.type ? typeNodeToTypeInfo(member.type, ctx.sourceFile) : null;
7281
7303
  map.set(member.name.getText(ctx.sourceFile), {
7282
- type: info && isResolvablePrimitive(info) ? info : null,
7304
+ type: info && isResolvableMemberType(info) ? info : null,
7283
7305
  optional: !!member.questionToken
7284
7306
  });
7285
7307
  }
@@ -13988,25 +14010,85 @@ var SVG_ROOT_TAGS = new Set([
13988
14010
  "animateTransform",
13989
14011
  "animateMotion"
13990
14012
  ]);
13991
- function templateRootIsSvg(template) {
14013
+ var MATHML_ROOT_TAGS = new Set([
14014
+ "math",
14015
+ "mrow",
14016
+ "mfrac",
14017
+ "msup",
14018
+ "msub",
14019
+ "msubsup",
14020
+ "mn",
14021
+ "mi",
14022
+ "mo",
14023
+ "mtext",
14024
+ "munder",
14025
+ "mover",
14026
+ "munderover",
14027
+ "mtable",
14028
+ "mtr",
14029
+ "mtd",
14030
+ "msqrt",
14031
+ "mroot",
14032
+ "mstyle",
14033
+ "merror",
14034
+ "mpadded",
14035
+ "mphantom",
14036
+ "menclose",
14037
+ "semantics",
14038
+ "annotation",
14039
+ "annotation-xml"
14040
+ ]);
14041
+ function namespaceForTag(tag) {
14042
+ if (SVG_ROOT_TAGS.has(tag) || SVG_ROOT_TAGS.has(tag.toLowerCase()))
14043
+ return "svg";
14044
+ if (MATHML_ROOT_TAGS.has(tag) || MATHML_ROOT_TAGS.has(tag.toLowerCase()))
14045
+ return "math";
14046
+ return null;
14047
+ }
14048
+ function detectRootNamespaceWrapTag(template) {
13992
14049
  const stripped = stripLeadingNonContent(template);
13993
14050
  const m = stripped.match(/^<\s*([A-Za-z][A-Za-z0-9-]*)/);
13994
- if (m) {
13995
- const tag = m[1];
13996
- if (SVG_ROOT_TAGS.has(tag))
13997
- return true;
13998
- return SVG_ROOT_TAGS.has(tag.toLowerCase());
13999
- }
14051
+ if (m)
14052
+ return namespaceForTag(m[1]);
14000
14053
  const branches = extractConditionalBranchTemplates(stripped);
14001
14054
  if (branches === null || branches.length === 0)
14002
- return false;
14003
- return branches.every(templateRootIsSvg);
14055
+ return null;
14056
+ let result;
14057
+ for (const branch of branches) {
14058
+ const branchNs = detectRootNamespaceWrapTag(branch);
14059
+ if (result === undefined) {
14060
+ result = branchNs;
14061
+ } else if (result !== branchNs) {
14062
+ return null;
14063
+ }
14064
+ }
14065
+ return result ?? null;
14004
14066
  }
14005
- function multiRootTemplateNeedsSvgWrap(template) {
14067
+ function multiRootTemplateNeedsNamespaceWrap(template) {
14006
14068
  const m = stripLeadingNonContent(template).match(/^<\s*([A-Za-z][A-Za-z0-9-]*)/);
14007
- if (m && m[1].toLowerCase() === "svg")
14008
- return false;
14009
- return templateRootIsSvg(template);
14069
+ if (m) {
14070
+ const tagLower = m[1].toLowerCase();
14071
+ if (tagLower === "svg" || tagLower === "math")
14072
+ return null;
14073
+ }
14074
+ return detectRootNamespaceWrapTag(template);
14075
+ }
14076
+ function namespaceWrapForTemplate(template) {
14077
+ const wrapTag = detectRootNamespaceWrapTag(template);
14078
+ return {
14079
+ wrapTag,
14080
+ childPath: wrapTag ? ".firstElementChild.firstElementChild" : ".firstElementChild"
14081
+ };
14082
+ }
14083
+ function multiRootNamespaceWrapForTemplate(template) {
14084
+ const wrapTag = multiRootTemplateNeedsNamespaceWrap(template);
14085
+ return {
14086
+ wrapTag,
14087
+ childPath: wrapTag ? ".firstElementChild" : ""
14088
+ };
14089
+ }
14090
+ function wrapHtmlForNamespace(html, wrapTag) {
14091
+ return wrapTag ? `<${wrapTag}>${html}</${wrapTag}>` : html;
14010
14092
  }
14011
14093
  function stripLeadingNonContent(template) {
14012
14094
  let s = template.trimStart();
@@ -14031,32 +14113,26 @@ function extractConditionalBranchTemplates(template) {
14031
14113
  return findTopLevelTemplateLiterals(expr);
14032
14114
  }
14033
14115
  function emitTemplateCloneInline(template) {
14034
- if (templateRootIsSvg(template)) {
14035
- return `const __tpl = document.createElement('template'); __tpl.innerHTML = \`<svg>${template}</svg>\`; return __tpl.content.firstElementChild.firstElementChild.cloneNode(true)`;
14036
- }
14037
- return `const __tpl = document.createElement('template'); __tpl.innerHTML = \`${template}\`; return __tpl.content.firstElementChild.cloneNode(true)`;
14116
+ const { wrapTag, childPath } = namespaceWrapForTemplate(template);
14117
+ const html = wrapHtmlForNamespace(template, wrapTag);
14118
+ return `const __tpl = document.createElement('template'); __tpl.innerHTML = \`${html}\`; return __tpl.content${childPath}.cloneNode(true)`;
14038
14119
  }
14039
14120
  function emitHoistedTemplateDecl(lines, indent, tplVar, skeletonTemplate) {
14040
- const isSvg = templateRootIsSvg(skeletonTemplate);
14041
- const html = isSvg ? `<svg>${skeletonTemplate}</svg>` : skeletonTemplate;
14121
+ const { wrapTag } = namespaceWrapForTemplate(skeletonTemplate);
14122
+ const html = wrapHtmlForNamespace(skeletonTemplate, wrapTag);
14042
14123
  lines.push(`${indent}const ${tplVar} = document.createElement('template')`);
14043
14124
  lines.push(`${indent}${tplVar}.innerHTML = \`${html}\``);
14044
14125
  }
14045
14126
  function hoistedCloneExpr(tplVar, skeletonTemplate) {
14046
- return templateRootIsSvg(skeletonTemplate) ? `${tplVar}.content.firstElementChild.firstElementChild.cloneNode(true)` : `${tplVar}.content.firstElementChild.cloneNode(true)`;
14127
+ return `${tplVar}.content${namespaceWrapForTemplate(skeletonTemplate).childPath}.cloneNode(true)`;
14047
14128
  }
14048
14129
  function emitTemplateCloneLines(template, indent) {
14049
- if (templateRootIsSvg(template)) {
14050
- return [
14051
- `${indent}const __tpl = document.createElement('template')`,
14052
- `${indent}__tpl.innerHTML = \`<svg>${template}</svg>\``,
14053
- `${indent}return __tpl.content.firstElementChild.firstElementChild.cloneNode(true)`
14054
- ];
14055
- }
14130
+ const { wrapTag, childPath } = namespaceWrapForTemplate(template);
14131
+ const html = wrapHtmlForNamespace(template, wrapTag);
14056
14132
  return [
14057
14133
  `${indent}const __tpl = document.createElement('template')`,
14058
- `${indent}__tpl.innerHTML = \`${template}\``,
14059
- `${indent}return __tpl.content.firstElementChild.cloneNode(true)`
14134
+ `${indent}__tpl.innerHTML = \`${html}\``,
14135
+ `${indent}return __tpl.content${childPath}.cloneNode(true)`
14060
14136
  ];
14061
14137
  }
14062
14138
  function emitLoopItemElementSetup(lines, opts) {
@@ -14088,9 +14164,9 @@ function emitLoopItemElementSetup(lines, opts) {
14088
14164
  lines.push(`${indent}})()${mountRow ? ")" : ""}`);
14089
14165
  }
14090
14166
  function emitMultiRootTemplateCloneLines(template, indent, varEl, varExtras) {
14091
- const isSvg = multiRootTemplateNeedsSvgWrap(template);
14092
- const innerHtmlExpr = isSvg ? `\`<svg>${template}</svg>\`` : `\`${template}\``;
14093
- const parentExpr = isSvg ? `__tpl.content.firstElementChild` : `__tpl.content`;
14167
+ const { wrapTag, childPath } = multiRootNamespaceWrapForTemplate(template);
14168
+ const innerHtmlExpr = `\`${wrapHtmlForNamespace(template, wrapTag)}\``;
14169
+ const parentExpr = `__tpl.content${childPath}`;
14094
14170
  return [
14095
14171
  `${indent}const __tpl = document.createElement('template')`,
14096
14172
  `${indent}__tpl.innerHTML = ${innerHtmlExpr}`,
@@ -14321,6 +14397,9 @@ function jsxChildrenContainComponent(nodes) {
14321
14397
  }
14322
14398
  return false;
14323
14399
  }
14400
+ function isSingleElementJsxChildren2(nodes) {
14401
+ return nodes.length === 1 && nodes[0].type === "element";
14402
+ }
14324
14403
  function buildRestSpreadNames(ctx) {
14325
14404
  const names = new Set;
14326
14405
  if (ctx.restPropsName)
@@ -14357,6 +14436,8 @@ function buildComponentPropsExpr(props, ctx) {
14357
14436
  const jsxExpr = irChildrenToJsExpr(prop.value.children);
14358
14437
  if (jsxChildrenContainComponent(prop.value.children)) {
14359
14438
  propsForInit.push(`get ${quotePropName(prop.name)}() { return __slot(() => ${jsxExpr}) }`);
14439
+ } else if (prop.name !== "children" && isSingleElementJsxChildren2(prop.value.children)) {
14440
+ propsForInit.push(`get ${quotePropName(prop.name)}() { return bfMarkup(${jsxExpr}) }`);
14360
14441
  } else {
14361
14442
  propsForInit.push(`get ${quotePropName(prop.name)}() { return ${jsxExpr} }`);
14362
14443
  }
@@ -14497,7 +14578,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
14497
14578
  reactiveTextSlotIds: new Set(bindings.reactiveTexts.map((t) => t.slotId))
14498
14579
  };
14499
14580
  skeletonTemplate = buildLoopSkeletonTemplate(l.children[0], skeletonSafeSlots) ?? undefined;
14500
- if (skeletonTemplate && !templateRootIsSvg(skeletonTemplate)) {
14581
+ if (skeletonTemplate && !detectRootNamespaceWrapTag(skeletonTemplate)) {
14501
14582
  skeletonPaths = computeSkeletonSlotPaths(l.children[0], skeletonSafeSlots) ?? undefined;
14502
14583
  }
14503
14584
  }
@@ -15416,6 +15497,8 @@ var RUNTIME_IMPORT_CANDIDATES = [
15416
15497
  "escapeAttr",
15417
15498
  "escapeText",
15418
15499
  "escapeTextOrNode",
15500
+ "bfMarkup",
15501
+ "escapeTextOrMarkup",
15419
15502
  "qsa",
15420
15503
  "qsaItem",
15421
15504
  "qsaChildScope",
@@ -16412,7 +16495,8 @@ function emitRegistrationAndHydration(lines, ctx, _ir, graph, inlinability) {
16412
16495
  const isCommentScope = _ir.root.type === "fragment" && _ir.root.needsScopeComment || _ir.root.type === "component";
16413
16496
  const defParts = [`init: init${name}`];
16414
16497
  if (canGenerateStaticTemplate(_ir.root, propNamesForStaticCheck, inlinableConstants, unsafeLocalNames)) {
16415
- const templateHtml = irToComponentTemplate(_ir.root, inlinableConstants, restSpreadNames, ctx.propsObjectName);
16498
+ const markupSlotIds = new Set(ctx.dynamicElements.map((e) => e.slotId));
16499
+ const templateHtml = irToComponentTemplate(_ir.root, inlinableConstants, restSpreadNames, ctx.propsObjectName, markupSlotIds);
16416
16500
  if (templateHtml) {
16417
16501
  defParts.push(buildTemplateDefPart(ctx, templateHtml));
16418
16502
  }
@@ -19638,9 +19722,8 @@ function stringifyBranchInnerLoops(lines, plan, indent, pc) {
19638
19722
  lines.push(`${indent} ${inner.paramUnwrap}`);
19639
19723
  }
19640
19724
  {
19641
- const isSvg = templateRootIsSvg(inner.wrappedTemplate);
19642
- const innerHtml = isSvg ? `<svg>${inner.wrappedTemplate}</svg>` : inner.wrappedTemplate;
19643
- const childPath = isSvg ? ".firstElementChild.firstElementChild" : ".firstElementChild";
19725
+ const { wrapTag, childPath } = namespaceWrapForTemplate(inner.wrappedTemplate);
19726
+ const innerHtml = wrapTag ? `<${wrapTag}>${inner.wrappedTemplate}</${wrapTag}>` : inner.wrappedTemplate;
19644
19727
  lines.push(`${indent} let __bel${uid} = __existing ?? (() => { const __t = document.createElement('template'); __t.innerHTML = \`${innerHtml}\`; return __t.content${childPath}.cloneNode(true) })()`);
19645
19728
  }
19646
19729
  if (inner.wrappedKey) {
@@ -20381,14 +20464,14 @@ function stringifyStaticLoop(lines, plan) {
20381
20464
  lines.push(` let __iterEl = ${containerVar}.children[${childIndexExpr}]`);
20382
20465
  if (csrMaterialize) {
20383
20466
  lines.push(` if (!__iterEl) {`);
20384
- const isSvg = csrMaterialize.bodyIsMultiRoot ? multiRootTemplateNeedsSvgWrap(csrMaterialize.itemTemplate) : templateRootIsSvg(csrMaterialize.itemTemplate);
20385
- const itemHtml = isSvg ? `<svg>${csrMaterialize.itemTemplate}</svg>` : csrMaterialize.itemTemplate;
20467
+ const { wrapTag, childPath } = csrMaterialize.bodyIsMultiRoot ? multiRootNamespaceWrapForTemplate(csrMaterialize.itemTemplate) : namespaceWrapForTemplate(csrMaterialize.itemTemplate);
20468
+ const itemHtml = wrapHtmlForNamespace(csrMaterialize.itemTemplate, wrapTag);
20386
20469
  if (csrMaterialize.bodyIsMultiRoot) {
20387
20470
  lines.push(` const __mtpl = document.createElement('template')`);
20388
20471
  lines.push(` __mtpl.innerHTML = \`${itemHtml}\``);
20389
20472
  lines.push(` const __anchor = ${containerVar}.children[${childIndexExpr}] ?? null`);
20390
20473
  lines.push(` let __first = null`);
20391
- lines.push(` let __sib = __mtpl.content${isSvg ? ".firstElementChild" : ""}.firstElementChild`);
20474
+ lines.push(` let __sib = __mtpl.content${childPath}.firstElementChild`);
20392
20475
  lines.push(` while (__sib) {`);
20393
20476
  lines.push(` const __next = __sib.nextElementSibling`);
20394
20477
  lines.push(` const __cloned = __sib.cloneNode(true)`);
@@ -20400,7 +20483,7 @@ function stringifyStaticLoop(lines, plan) {
20400
20483
  } else {
20401
20484
  lines.push(` const __tpl = document.createElement('template')`);
20402
20485
  lines.push(` __tpl.innerHTML = \`${itemHtml}\``);
20403
- lines.push(` const __cloned = __tpl.content${isSvg ? ".firstElementChild" : ""}.firstElementChild`);
20486
+ lines.push(` const __cloned = __tpl.content${childPath}`);
20404
20487
  lines.push(` if (__cloned) {`);
20405
20488
  lines.push(` const __anchor = ${containerVar}.children[${childIndexExpr}] ?? null`);
20406
20489
  lines.push(` ${containerVar}.insertBefore(__cloned, __anchor)`);
@@ -20470,9 +20553,8 @@ function emitReactive(lines, inner, indent, pc) {
20470
20553
  lines.push(`${innerIndent} __innerEl${uid}.__bfExtras = __innerExtras${uid}`);
20471
20554
  lines.push(`${indent} }`);
20472
20555
  } else {
20473
- const isSvg = templateRootIsSvg(emit.wrappedTemplate);
20474
- const innerHtml = isSvg ? `<svg>${emit.wrappedTemplate}</svg>` : emit.wrappedTemplate;
20475
- const childPath = isSvg ? ".firstElementChild.firstElementChild" : ".firstElementChild";
20556
+ const { wrapTag, childPath } = namespaceWrapForTemplate(emit.wrappedTemplate);
20557
+ const innerHtml = wrapTag ? `<${wrapTag}>${emit.wrappedTemplate}</${wrapTag}>` : emit.wrappedTemplate;
20476
20558
  lines.push(`${indent} let __innerEl${uid} = __existing ?? (() => { const __t = document.createElement('template'); __t.innerHTML = \`${innerHtml}\`; return __t.content${childPath}.cloneNode(true) })()`);
20477
20559
  }
20478
20560
  if (emit.wrappedKey) {
@@ -21798,7 +21880,8 @@ function generateTemplateOnlyMount(ir, ctx) {
21798
21880
  restSpreadNames.add(ctx.propsObjectName);
21799
21881
  let templateHtml;
21800
21882
  if (canGenerateStaticTemplate(ir.root, propNamesForStaticCheck, inlinableConstants, unsafeLocalNames)) {
21801
- templateHtml = irToComponentTemplate(ir.root, inlinableConstants, restSpreadNames, ctx.propsObjectName);
21883
+ const markupSlotIds = new Set(ctx.dynamicElements.map((e) => e.slotId));
21884
+ templateHtml = irToComponentTemplate(ir.root, inlinableConstants, restSpreadNames, ctx.propsObjectName, markupSlotIds);
21802
21885
  }
21803
21886
  if (!templateHtml) {
21804
21887
  const csrInlinableConstants = csrInlinableConstantsFromCtx(ctx);
@@ -22477,6 +22560,7 @@ function extractSsrDefaults(metadata) {
22477
22560
  out[metadata.restPropsName] = { isRestProps: true, value: {} };
22478
22561
  }
22479
22562
  const bindings = {};
22563
+ const localConsts = localConstValuesByName(metadata);
22480
22564
  for (const c of metadata.localConstants ?? []) {
22481
22565
  if (!c.isModule || c.value === undefined)
22482
22566
  continue;
@@ -22492,14 +22576,26 @@ function extractSsrDefaults(metadata) {
22492
22576
  if (sig.envReader)
22493
22577
  continue;
22494
22578
  const value = tryStaticEval(sig.initialValue, { bindings, propsLike });
22495
- out[sig.getter] = { value: resultToJsonable(value) };
22579
+ if (metadata.propsObjectName !== null && referencesOwnProp(sig.initialValue, metadata.propsObjectName, sig.getter, localConsts)) {
22580
+ if (!(sig.getter in out)) {
22581
+ out[sig.getter] = { propName: sig.getter, value: null };
22582
+ }
22583
+ } else {
22584
+ out[sig.getter] = { value: resultToJsonable(value) };
22585
+ }
22496
22586
  bindings[sig.getter] = value;
22497
22587
  }
22498
22588
  for (const memo of metadata.memos) {
22499
22589
  if (memo.isModule)
22500
22590
  continue;
22501
22591
  const value = tryStaticEval(memo.computation, { bindings, propsLike });
22502
- out[memo.name] = { value: resultToJsonable(value) };
22592
+ if (metadata.propsObjectName !== null && referencesOwnProp(memo.computation, metadata.propsObjectName, memo.name, localConsts)) {
22593
+ if (!(memo.name in out)) {
22594
+ out[memo.name] = { propName: memo.name, value: null };
22595
+ }
22596
+ } else {
22597
+ out[memo.name] = { value: resultToJsonable(value) };
22598
+ }
22503
22599
  bindings[memo.name] = value;
22504
22600
  }
22505
22601
  if (metadata.propsObjectName !== null) {
@@ -22507,12 +22603,12 @@ function extractSsrDefaults(metadata) {
22507
22603
  for (const sig of metadata.signals) {
22508
22604
  if (!sig.getter || sig.isModule || sig.envReader)
22509
22605
  continue;
22510
- collectPropRefs(sig.initialValue, metadata.propsObjectName, referenced);
22606
+ collectPropRefsTransitive(sig.initialValue, metadata.propsObjectName, localConsts, referenced);
22511
22607
  }
22512
22608
  for (const memo of metadata.memos) {
22513
22609
  if (memo.isModule)
22514
22610
  continue;
22515
- collectPropRefs(memo.computation, metadata.propsObjectName, referenced);
22611
+ collectPropRefsTransitive(memo.computation, metadata.propsObjectName, localConsts, referenced);
22516
22612
  }
22517
22613
  for (const name of referenced) {
22518
22614
  if (name in out)
@@ -22522,6 +22618,20 @@ function extractSsrDefaults(metadata) {
22522
22618
  }
22523
22619
  return Object.keys(out).length === 0 ? undefined : out;
22524
22620
  }
22621
+ function localConstValuesByName(metadata) {
22622
+ const out = new Map;
22623
+ for (const c of metadata.localConstants ?? []) {
22624
+ if (c.isModule || c.value === undefined)
22625
+ continue;
22626
+ out.set(c.name, c.value);
22627
+ }
22628
+ return out;
22629
+ }
22630
+ function referencesOwnProp(expr, propsObjectName, name, localConsts) {
22631
+ const referenced = new Set;
22632
+ collectPropRefsTransitive(expr, propsObjectName, localConsts, referenced);
22633
+ return referenced.has(name);
22634
+ }
22525
22635
  function collectPropRefs(expr, propsObjectName, out) {
22526
22636
  if (!expr || !expr.trim())
22527
22637
  return;
@@ -22537,6 +22647,23 @@ function collectPropRefs(expr, propsObjectName, out) {
22537
22647
  };
22538
22648
  visit3(node);
22539
22649
  }
22650
+ function collectPropRefsTransitive(expr, propsObjectName, localConsts, out, visited = new Set) {
22651
+ if (!expr || !expr.trim())
22652
+ return;
22653
+ collectPropRefs(expr, propsObjectName, out);
22654
+ const node = parseExpression2(expr);
22655
+ if (!node)
22656
+ return;
22657
+ for (const id of extractFreeIdentifiersFromNode(node)) {
22658
+ if (visited.has(id))
22659
+ continue;
22660
+ const constValue = localConsts.get(id);
22661
+ if (constValue === undefined)
22662
+ continue;
22663
+ visited.add(id);
22664
+ collectPropRefsTransitive(constValue, propsObjectName, localConsts, out, visited);
22665
+ }
22666
+ }
22540
22667
  function resultToJsonable(v) {
22541
22668
  if (v === UNRESOLVED)
22542
22669
  return null;
@@ -22581,7 +22708,7 @@ function evalStatementsForReturn(statements, ctx) {
22581
22708
  return NO_RETURN;
22582
22709
  }
22583
22710
  function parseExpression2(expr) {
22584
- const sf = ts22.createSourceFile("__ssr_default__.ts", `(${expr})`, ts22.ScriptTarget.Latest, false, ts22.ScriptKind.TS);
22711
+ const sf = ts22.createSourceFile("__ssr_default__.ts", `(${expr})`, ts22.ScriptTarget.Latest, true, ts22.ScriptKind.TS);
22585
22712
  const stmt = sf.statements[0];
22586
22713
  if (!stmt || !ts22.isExpressionStatement(stmt))
22587
22714
  return null;
@@ -22895,6 +23022,38 @@ function classify2(name, origin, expr, parsed, available) {
22895
23022
  }
22896
23023
  return { kind: "derived", name, origin, expr, parsed, frees: [...frees] };
22897
23024
  }
23025
+ function localConstExprsByName(metadata) {
23026
+ const out = new Map;
23027
+ for (const c of metadata.localConstants ?? []) {
23028
+ if (c.isModule || c.declarationKind !== "const" || c.value === undefined)
23029
+ continue;
23030
+ out.set(c.name, c.parsed ?? parseExpression(c.value.trim()));
23031
+ }
23032
+ return out;
23033
+ }
23034
+ function resolveThroughLocalConsts(parsed, localConsts) {
23035
+ let current = parsed;
23036
+ const maxIter = localConsts.size + 1;
23037
+ for (let i = 0;i < maxIter; i++) {
23038
+ const frees = freeIdentifiers(current);
23039
+ if (frees === null)
23040
+ break;
23041
+ let changed = false;
23042
+ for (const name of frees) {
23043
+ const value = localConsts.get(name);
23044
+ if (!value)
23045
+ continue;
23046
+ const inlined = inlineBinding(current, name, value);
23047
+ if (inlined === null)
23048
+ continue;
23049
+ current = inlined;
23050
+ changed = true;
23051
+ }
23052
+ if (!changed)
23053
+ break;
23054
+ }
23055
+ return current;
23056
+ }
22898
23057
  function computeSsrSeedPlan(metadata) {
22899
23058
  const baseScope = metadata.propsParams.map((p) => p.name);
22900
23059
  if (metadata.propsObjectName)
@@ -22903,6 +23062,7 @@ function computeSsrSeedPlan(metadata) {
22903
23062
  baseScope.push(name);
22904
23063
  }
22905
23064
  const available = new Set(baseScope);
23065
+ const localConsts = localConstExprsByName(metadata);
22906
23066
  const steps = [];
22907
23067
  for (const signal of metadata.signals) {
22908
23068
  if (signal.envReader) {
@@ -22914,13 +23074,13 @@ function computeSsrSeedPlan(metadata) {
22914
23074
  }
22915
23075
  }
22916
23076
  const expr = signal.initialValue.trim();
22917
- steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify2(signal.getter, "signal", expr, parseExpression(expr), available));
23077
+ steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify2(signal.getter, "signal", expr, resolveThroughLocalConsts(parseExpression(expr), localConsts), available));
22918
23078
  available.add(signal.getter);
22919
23079
  }
22920
23080
  for (const memo of metadata.memos) {
22921
23081
  const body = extractArrowBodyExpression(memo.computation);
22922
23082
  const expr = body?.trim() ?? "";
22923
- steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify2(memo.name, "memo", expr, memo.parsed ?? parseExpression(expr), available));
23083
+ steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify2(memo.name, "memo", expr, resolveThroughLocalConsts(memo.parsed ?? parseExpression(expr), localConsts), available));
22924
23084
  available.add(memo.name);
22925
23085
  }
22926
23086
  return { baseScope, steps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/vite",
3
- "version": "0.31.8",
3
+ "version": "0.31.10",
4
4
  "description": "Vite plugin for BarefootJS: Vite/Rollup owns bundling, hashing, chunking, tree-shaking and minification of client assets, BarefootJS keeps only the JSX to (template, client JS) compile",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,17 +38,17 @@
38
38
  "directory": "packages/vite"
39
39
  },
40
40
  "dependencies": {
41
- "@barefootjs/shared": "0.31.8"
41
+ "@barefootjs/shared": "0.31.10"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@barefootjs/jsx": ">=0.2.0",
45
45
  "vite": "^6.0.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@barefootjs/client": "0.31.8",
49
- "@barefootjs/go-template": "0.31.8",
50
- "@barefootjs/hono": "0.31.8",
51
- "@barefootjs/jsx": "0.31.8",
48
+ "@barefootjs/client": "0.31.10",
49
+ "@barefootjs/go-template": "0.31.10",
50
+ "@barefootjs/hono": "0.31.10",
51
+ "@barefootjs/jsx": "0.31.10",
52
52
  "typescript": "^5.0.0",
53
53
  "vite": "^6.0.0"
54
54
  }