@stacksjs/stx 0.2.82 → 0.2.84

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 (62) hide show
  1. package/dist/app-shell.js +21 -11
  2. package/dist/build-assets.js +19 -9
  3. package/dist/build-mode-detector.js +22 -12
  4. package/dist/build-views.js +22 -12
  5. package/dist/build.js +21 -11
  6. package/dist/caching.js +19 -9
  7. package/dist/cli.js +22 -12
  8. package/dist/component-processing.js +21 -11
  9. package/dist/component-renderer.js +21 -11
  10. package/dist/components.js +22 -12
  11. package/dist/conditionals.js +1 -1
  12. package/dist/custom-directives.js +1 -1
  13. package/dist/dev-server/index.js +22 -12
  14. package/dist/dev-server/serve-app.js +21 -11
  15. package/dist/dev-server/serve-file.js +21 -11
  16. package/dist/dev-server/serve-markdown.js +22 -12
  17. package/dist/dev-server/serve-multi.js +21 -11
  18. package/dist/dev-server.js +21 -11
  19. package/dist/docs.js +22 -12
  20. package/dist/dynamic-components.js +21 -11
  21. package/dist/error-handling.js +1 -1
  22. package/dist/errors/formatter.js +1 -1
  23. package/dist/errors/index.js +1 -1
  24. package/dist/i18n.js +1 -1
  25. package/dist/includes.js +21 -11
  26. package/dist/index.js +21 -11
  27. package/dist/interactive.js +22 -12
  28. package/dist/lazy-loader.js +98 -88
  29. package/dist/misc-directives.js +1 -1
  30. package/dist/plugin.js +21 -11
  31. package/dist/process.js +21 -11
  32. package/dist/production-builder.js +21 -11
  33. package/dist/production-server.js +21 -11
  34. package/dist/pwa/index.js +22 -12
  35. package/dist/pwa/offline.js +22 -12
  36. package/dist/pwa.js +21 -11
  37. package/dist/reactive.js +1 -1
  38. package/dist/render.js +22 -12
  39. package/dist/runtime-injection.js +19 -9
  40. package/dist/seo.js +1 -1
  41. package/dist/serve.js +22 -12
  42. package/dist/signal-processing.js +41 -31
  43. package/dist/signals.js +19 -9
  44. package/dist/site-builder/build.js +22 -12
  45. package/dist/site-builder/index.js +22 -12
  46. package/dist/ssg.js +21 -11
  47. package/dist/ssr.js +22 -12
  48. package/dist/store-loader.js +18 -18
  49. package/dist/story/cli.js +22 -12
  50. package/dist/story/commands/dev.js +22 -12
  51. package/dist/story/commands/index.js +22 -12
  52. package/dist/story/index.js +22 -12
  53. package/dist/story/renderer.js +22 -12
  54. package/dist/story/server.js +22 -12
  55. package/dist/story/visual-testing.js +22 -12
  56. package/dist/streaming.js +21 -11
  57. package/dist/template-compiler.js +22 -12
  58. package/dist/template-hydrator.js +22 -12
  59. package/dist/testing.js +147 -137
  60. package/dist/utils.js +21 -11
  61. package/dist/web-components.js +22 -12
  62. package/package.json +5 -5
@@ -2963,6 +2963,13 @@ catch (e2) {
2963
2963
 
2964
2964
  // Known directive names to exclude from generic :attr binding
2965
2965
  var DIRECTIVE_NAMES = {class:1, style:1, text:1, html:1, show:1, model:1, 'if':1, 'for':1, ref:1};
2966
+ // SVG attributes are case-sensitive, but the HTML parser lowercases
2967
+ // prefixed attribute names \u2014 ':viewBox' arrives as ':viewbox' because
2968
+ // the spec's "adjust SVG attributes" step only covers unprefixed names.
2969
+ // Without restoring the canonical casing, setAttribute('viewbox') creates
2970
+ // a dead duplicate attribute and the real viewBox never updates.
2971
+ var SVG_ATTR_CASE = {attributename:'attributeName', attributetype:'attributeType', basefrequency:'baseFrequency', baseprofile:'baseProfile', calcmode:'calcMode', clippathunits:'clipPathUnits', diffuseconstant:'diffuseConstant', edgemode:'edgeMode', filterunits:'filterUnits', glyphref:'glyphRef', gradienttransform:'gradientTransform', gradientunits:'gradientUnits', kernelmatrix:'kernelMatrix', kernelunitlength:'kernelUnitLength', keypoints:'keyPoints', keysplines:'keySplines', keytimes:'keyTimes', lengthadjust:'lengthAdjust', limitingconeangle:'limitingConeAngle', markerheight:'markerHeight', markerunits:'markerUnits', markerwidth:'markerWidth', maskcontentunits:'maskContentUnits', maskunits:'maskUnits', numoctaves:'numOctaves', pathlength:'pathLength', patterncontentunits:'patternContentUnits', patterntransform:'patternTransform', patternunits:'patternUnits', pointsatx:'pointsAtX', pointsaty:'pointsAtY', pointsatz:'pointsAtZ', preservealpha:'preserveAlpha', preserveaspectratio:'preserveAspectRatio', primitiveunits:'primitiveUnits', refx:'refX', refy:'refY', repeatcount:'repeatCount', repeatdur:'repeatDur', requiredextensions:'requiredExtensions', requiredfeatures:'requiredFeatures', specularconstant:'specularConstant', specularexponent:'specularExponent', spreadmethod:'spreadMethod', startoffset:'startOffset', stddeviation:'stdDeviation', stitchtiles:'stitchTiles', surfacescale:'surfaceScale', systemlanguage:'systemLanguage', tablevalues:'tableValues', targetx:'targetX', targety:'targetY', textlength:'textLength', viewbox:'viewBox', viewtarget:'viewTarget', xchannelselector:'xChannelSelector', ychannelselector:'yChannelSelector', zoomandpan:'zoomAndPan'};
2972
+ var SVG_NS = 'http://www.w3.org/2000/svg';
2966
2973
  var EVENT_RE = /^(click|dblclick|mousedown|mouseup|mousemove|mouseenter|mouseleave|keydown|keyup|keypress|input|change|submit|focus|blur|scroll|resize|touchstart|touchend|touchmove|contextmenu|wheel|pointerdown|pointerup|pointermove)/;
2967
2974
  var KEY_MAP = {enter:'Enter', tab:'Tab', escape:'Escape', space:' ', up:'ArrowUp', down:'ArrowDown', left:'ArrowLeft', right:'ArrowRight', 'delete':'Delete', backspace:'Backspace'};
2968
2975
 
@@ -2987,7 +2994,8 @@ catch (e2) {
2987
2994
  if (name.startsWith('@bind:') || name.startsWith('x-bind:')
2988
2995
  || (name.startsWith(':') && !name.startsWith('::') && !DIRECTIVE_NAMES[name.slice(1).split('.')[0]] && !EVENT_RE.test(name.slice(1)))
2989
2996
  || (name.startsWith('x-') && !X_HANDLED[name.split('.')[0]] && !X_HANDLED[name])) {
2990
- const attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
2997
+ let attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
2998
+ if (el.namespaceURI === SVG_NS && SVG_ATTR_CASE[attrName]) attrName = SVG_ATTR_CASE[attrName];
2991
2999
  effect(() => {
2992
3000
  const v = evalAttrExpr(value);
2993
3001
  if (v === false || v === null || v === undefined) {
@@ -3366,10 +3374,12 @@ else {
3366
3374
  });
3367
3375
  }
3368
3376
  else if (Array.isArray(value)) {
3369
- el.className = originalClasses + ' ' + value.filter(Boolean).join(' ');
3377
+ var _clsArr = originalClasses + ' ' + value.filter(Boolean).join(' ');
3378
+ if (typeof el.className === 'string') el.className = _clsArr; else el.setAttribute('class', _clsArr);
3370
3379
  }
3371
3380
  else {
3372
- el.className = originalClasses + (value ? ' ' + value : '');
3381
+ var _clsStr = originalClasses + (value ? ' ' + value : '');
3382
+ if (typeof el.className === 'string') el.className = _clsStr; else el.setAttribute('class', _clsStr);
3373
3383
  }
3374
3384
  });
3375
3385
  }
@@ -5693,10 +5703,10 @@ else {
5693
5703
  var root = scriptEl ? scriptEl.nextElementSibling : null;
5694
5704
  if (!root && scriptEl) root = scriptEl.previousElementSibling || scriptEl.parentElement;
5695
5705
 
5696
- // SPA fallback: during router navigation, script is appended to <body>
5706
+ // SPA fallback: during router navigation, script is appended to body>
5697
5707
  // (not inside the content container), so nextElementSibling won't find the page content.
5698
5708
  // Only use fallback when we genuinely couldn't find a suitable root element.
5699
- // Do NOT fallback just because the script is in <body> \u2014 layout scripts in <body>
5709
+ // Do NOT fallback just because the script is in body> \u2014 layout scripts in body>
5700
5710
  // with valid siblings (e.g. sidebar <aside>) should use those siblings as root.
5701
5711
  var needsFallback = !root || root === document.body
5702
5712
  || (root && root.tagName === 'SCRIPT');
@@ -6015,7 +6025,7 @@ else {
6015
6025
  mountCallbacks.forEach(fn => fn());
6016
6026
  });
6017
6027
 
6018
- // Multi-root fragment fix: a no-<body> setup page tags only the FIRST
6028
+ // Multi-root fragment fix: a no-body> setup page tags only the FIRST
6019
6029
  // top-level element with data-stx (signal-processing.ts marks one element),
6020
6030
  // so sibling root elements were orphaned \u2014 their :if / :for / {{ }} / x-text
6021
6031
  // never hydrated, which read as "{{ }} doesn't work under :if/:for". The
@@ -6112,7 +6122,7 @@ else {
6112
6122
  el.querySelectorAll('[x-cloak]').forEach(function(c) { c.removeAttribute('x-cloak'); });
6113
6123
  });
6114
6124
 
6115
- // Process <head> elements (title, meta) that may contain {{ }} expressions
6125
+ // Process head> elements (title, meta) that may contain {{ }} expressions
6116
6126
  // Use componentScope which now contains variables from processed components
6117
6127
  const headElements = document.querySelectorAll('head title, head meta[content]');
6118
6128
  headElements.forEach(el => {
@@ -6308,7 +6318,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
6308
6318
 
6309
6319
  // Apply new page's SFC setup function. During SPA navigation, re-executed page
6310
6320
  // scripts set window.stx._latestSetup to the new setup function. This takes priority
6311
- // over the stale data-stx attribute on <body> (which has the PREVIOUS page's function name).
6321
+ // over the stale data-stx attribute on body> (which has the PREVIOUS page's function name).
6312
6322
  var usedLatestSetup = false;
6313
6323
  if (window.stx._latestSetup && typeof window.stx._latestSetup === 'function') {
6314
6324
  try {
@@ -6392,7 +6402,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
6392
6402
 
6393
6403
  // Process the container content \u2014 bind {{ }}, :attr, @event directives.
6394
6404
  // Run synchronously (not in setTimeout) so componentScope is captured correctly.
6395
- // The DOMContentLoaded path processes <body> synchronously \u2014 the SPA path must match.
6405
+ // The DOMContentLoaded path processes body> synchronously \u2014 the SPA path must match.
6396
6406
  console.log('[stx:load] container:', container.tagName, '__stx_scope:', !!container.__stx_scope, 'scope keys:', Object.keys(componentScope).slice(0, 10));
6397
6407
  if (!container.__stx_scope) {
6398
6408
  // Dispose previous effects on the container (from prior navigation)
package/dist/seo.js CHANGED
@@ -58,7 +58,7 @@ ${F}`)}if(J.suggestion)V.push(`
58
58
  ${"\x1B[31m"}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${"\x1B[0m"}`),V.join("")}function sJ(J,Q,Z){let $=J.split(`
59
59
  `),q=Math.max(0,Q-Z-1),W=Math.min($.length-1,Q+Z-1),G=[];for(let Y=q;Y<=W;Y++){let X=(Y+1).toString().padStart(4),V=Y===Q-1?">":" ";G.push(`${V}${X} | ${$[Y]}`)}return G.join(`
60
60
  `)}function rJ(J,Q,Z){let $=J.split(`
61
- `),q=Math.max(0,Q-Z-1),W=Math.min($.length-1,Q+Z-1),G="\x1B[90m",Y="\x1B[31m",X="\x1B[0m",V=[];for(let B=q;B<=W;B++){let F=(B+1).toString().padStart(4),O=B===Q-1,M=O?"\x1B[31m>\x1B[0m":" ",K=O?`\x1B[31m${$[B]}\x1B[0m`:`\x1B[90m${$[B]}`;V.push(`${M}${F}\x1B[0m | ${K}`)}return V.join(`
61
+ `),q=Math.max(0,Q-Z-1),W=Math.min($.length-1,Q+Z-1),G="\x1B[90m",Y="\x1B[31m",X="\x1B[0m",V=[];for(let B=q;B<=W;B++){let F=(B+1).toString().padStart(4),O=B===Q-1,M=O?"\x1B[31m>\x1B[0m":" ",K=O?`\x1B[31m${$[B]}\x1B[0m`:`\x1B[90m${$[B]}\x1B[0m`;V.push(`${M}\x1B[90m${F}\x1B[0m | ${K}`)}return V.join(`
62
62
  `)}function BJ(J){return J.replace(/--/g,"- -").replace(/>/g,"&gt;")}function FJ(J,Q){let $=J.substring(0,Q).split(`
63
63
  `);return{line:$.length,column:$[$.length-1].length}}function w(J,Q,Z){return p({type:J,message:Q,code:Z,format:"html"}).formatted}function iJ(J,Q,Z,$,q){return p({type:J,message:Q,code:q,filePath:Z,line:$,format:"console"}).formatted}function nJ(J,Q,Z){let $=Z.template.split(`
64
64
  `),q=FJ(Z.template,Z.offset),W=`[${J} Error at line ${q.line} in ${Z.filePath}]: ${Q}
package/dist/serve.js CHANGED
@@ -1783,7 +1783,7 @@ ${W}`)}if($.suggestion)q.push(`
1783
1783
  ${"\x1B[31m"}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${"\x1B[0m"}`),q.join("")}function cK($,Z,Y){let X=$.split(`
1784
1784
  `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G=[];for(let K=J;K<=Q;K++){let z=(K+1).toString().padStart(4),q=K===Z-1?">":" ";G.push(`${q}${z} | ${X[K]}`)}return G.join(`
1785
1785
  `)}function iK($,Z,Y){let X=$.split(`
1786
- `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G="\x1B[90m",K="\x1B[31m",z="\x1B[0m",q=[];for(let U=J;U<=Q;U++){let W=(U+1).toString().padStart(4),_=U===Z-1,B=_?"\x1B[31m>\x1B[0m":" ",j=_?`\x1B[31m${X[U]}\x1B[0m`:`\x1B[90m${X[U]}`;q.push(`${B}${W}\x1B[0m | ${j}`)}return q.join(`
1786
+ `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G="\x1B[90m",K="\x1B[31m",z="\x1B[0m",q=[];for(let U=J;U<=Q;U++){let W=(U+1).toString().padStart(4),_=U===Z-1,B=_?"\x1B[31m>\x1B[0m":" ",j=_?`\x1B[31m${X[U]}\x1B[0m`:`\x1B[90m${X[U]}\x1B[0m`;q.push(`${B}\x1B[90m${W}\x1B[0m | ${j}`)}return q.join(`
1787
1787
  `)}function qZ($){return $.replace(/--/g,"- -").replace(/>/g,"&gt;")}function UZ($,Z){let X=$.substring(0,Z).split(`
1788
1788
  `);return{line:X.length,column:X[X.length-1].length}}function r($,Z,Y){return X3({type:$,message:Z,code:Y,format:"html"}).formatted}function nK($,Z,Y,X,J){return X3({type:$,message:Z,code:J,filePath:Y,line:X,format:"console"}).formatted}function oK($,Z,Y){let X=Y.template.split(`
1789
1789
  `),J=UZ(Y.template,Y.offset),Q=`[${$} Error at line ${J.line} in ${Y.filePath}]: ${Z}
@@ -3756,7 +3756,7 @@ window.__stx_reactive = (function() {
3756
3756
 
3757
3757
  return { initScope: initScope, reactive: reactive };
3758
3758
  })();
3759
- `}function oZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=h0(J,Z,!0);if(Q===void 0)return X;return String(Q)}catch{return X}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(X,J)=>{try{let Q=h0(J,Z,!0);if(Q===void 0)return X;return JSON.stringify(Q)}catch{return X}}),Y}function Yq($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=oZ(X.stateExpr,Z),G=X.initExpr?oZ(X.initExpr,Z):null,K=JSON.stringify(Q),z=G?JSON.stringify(G):"null";return`
3759
+ `}function oZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=h0(J,Z,!0);if(Q===void 0)return X;return String(Q)}catch{return X}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(X,J)=>{try{let Q=h0(J,Z,!0);if(Q===void 0)return X;if(typeof Q==="string"){let G=Q.trim();if(G.startsWith("{")&&G.endsWith("}")||G.startsWith("[")&&G.endsWith("]"))try{return JSON.parse(G),G}catch{}}return JSON.stringify(Q)}catch{return X}}),Y}function Yq($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=oZ(X.stateExpr,Z),G=X.initExpr?oZ(X.initExpr,Z):null,K=JSON.stringify(Q),z=G?JSON.stringify(G):"null";return`
3760
3760
  (function() {
3761
3761
  var scopeEl = document.querySelector('${X.selector}');
3762
3762
  if (!scopeEl) return;
@@ -5996,6 +5996,13 @@ catch (e2) {
5996
5996
 
5997
5997
  // Known directive names to exclude from generic :attr binding
5998
5998
  var DIRECTIVE_NAMES = {class:1, style:1, text:1, html:1, show:1, model:1, 'if':1, 'for':1, ref:1};
5999
+ // SVG attributes are case-sensitive, but the HTML parser lowercases
6000
+ // prefixed attribute names \u2014 ':viewBox' arrives as ':viewbox' because
6001
+ // the spec's "adjust SVG attributes" step only covers unprefixed names.
6002
+ // Without restoring the canonical casing, setAttribute('viewbox') creates
6003
+ // a dead duplicate attribute and the real viewBox never updates.
6004
+ var SVG_ATTR_CASE = {attributename:'attributeName', attributetype:'attributeType', basefrequency:'baseFrequency', baseprofile:'baseProfile', calcmode:'calcMode', clippathunits:'clipPathUnits', diffuseconstant:'diffuseConstant', edgemode:'edgeMode', filterunits:'filterUnits', glyphref:'glyphRef', gradienttransform:'gradientTransform', gradientunits:'gradientUnits', kernelmatrix:'kernelMatrix', kernelunitlength:'kernelUnitLength', keypoints:'keyPoints', keysplines:'keySplines', keytimes:'keyTimes', lengthadjust:'lengthAdjust', limitingconeangle:'limitingConeAngle', markerheight:'markerHeight', markerunits:'markerUnits', markerwidth:'markerWidth', maskcontentunits:'maskContentUnits', maskunits:'maskUnits', numoctaves:'numOctaves', pathlength:'pathLength', patterncontentunits:'patternContentUnits', patterntransform:'patternTransform', patternunits:'patternUnits', pointsatx:'pointsAtX', pointsaty:'pointsAtY', pointsatz:'pointsAtZ', preservealpha:'preserveAlpha', preserveaspectratio:'preserveAspectRatio', primitiveunits:'primitiveUnits', refx:'refX', refy:'refY', repeatcount:'repeatCount', repeatdur:'repeatDur', requiredextensions:'requiredExtensions', requiredfeatures:'requiredFeatures', specularconstant:'specularConstant', specularexponent:'specularExponent', spreadmethod:'spreadMethod', startoffset:'startOffset', stddeviation:'stdDeviation', stitchtiles:'stitchTiles', surfacescale:'surfaceScale', systemlanguage:'systemLanguage', tablevalues:'tableValues', targetx:'targetX', targety:'targetY', textlength:'textLength', viewbox:'viewBox', viewtarget:'viewTarget', xchannelselector:'xChannelSelector', ychannelselector:'yChannelSelector', zoomandpan:'zoomAndPan'};
6005
+ var SVG_NS = 'http://www.w3.org/2000/svg';
5999
6006
  var EVENT_RE = /^(click|dblclick|mousedown|mouseup|mousemove|mouseenter|mouseleave|keydown|keyup|keypress|input|change|submit|focus|blur|scroll|resize|touchstart|touchend|touchmove|contextmenu|wheel|pointerdown|pointerup|pointermove)/;
6000
6007
  var KEY_MAP = {enter:'Enter', tab:'Tab', escape:'Escape', space:' ', up:'ArrowUp', down:'ArrowDown', left:'ArrowLeft', right:'ArrowRight', 'delete':'Delete', backspace:'Backspace'};
6001
6008
 
@@ -6020,7 +6027,8 @@ catch (e2) {
6020
6027
  if (name.startsWith('@bind:') || name.startsWith('x-bind:')
6021
6028
  || (name.startsWith(':') && !name.startsWith('::') && !DIRECTIVE_NAMES[name.slice(1).split('.')[0]] && !EVENT_RE.test(name.slice(1)))
6022
6029
  || (name.startsWith('x-') && !X_HANDLED[name.split('.')[0]] && !X_HANDLED[name])) {
6023
- const attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
6030
+ let attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
6031
+ if (el.namespaceURI === SVG_NS && SVG_ATTR_CASE[attrName]) attrName = SVG_ATTR_CASE[attrName];
6024
6032
  effect(() => {
6025
6033
  const v = evalAttrExpr(value);
6026
6034
  if (v === false || v === null || v === undefined) {
@@ -6399,10 +6407,12 @@ else {
6399
6407
  });
6400
6408
  }
6401
6409
  else if (Array.isArray(value)) {
6402
- el.className = originalClasses + ' ' + value.filter(Boolean).join(' ');
6410
+ var _clsArr = originalClasses + ' ' + value.filter(Boolean).join(' ');
6411
+ if (typeof el.className === 'string') el.className = _clsArr; else el.setAttribute('class', _clsArr);
6403
6412
  }
6404
6413
  else {
6405
- el.className = originalClasses + (value ? ' ' + value : '');
6414
+ var _clsStr = originalClasses + (value ? ' ' + value : '');
6415
+ if (typeof el.className === 'string') el.className = _clsStr; else el.setAttribute('class', _clsStr);
6406
6416
  }
6407
6417
  });
6408
6418
  }
@@ -8726,10 +8736,10 @@ else {
8726
8736
  var root = scriptEl ? scriptEl.nextElementSibling : null;
8727
8737
  if (!root && scriptEl) root = scriptEl.previousElementSibling || scriptEl.parentElement;
8728
8738
 
8729
- // SPA fallback: during router navigation, script is appended to <body>
8739
+ // SPA fallback: during router navigation, script is appended to body>
8730
8740
  // (not inside the content container), so nextElementSibling won't find the page content.
8731
8741
  // Only use fallback when we genuinely couldn't find a suitable root element.
8732
- // Do NOT fallback just because the script is in <body> \u2014 layout scripts in <body>
8742
+ // Do NOT fallback just because the script is in body> \u2014 layout scripts in body>
8733
8743
  // with valid siblings (e.g. sidebar <aside>) should use those siblings as root.
8734
8744
  var needsFallback = !root || root === document.body
8735
8745
  || (root && root.tagName === 'SCRIPT');
@@ -9048,7 +9058,7 @@ else {
9048
9058
  mountCallbacks.forEach(fn => fn());
9049
9059
  });
9050
9060
 
9051
- // Multi-root fragment fix: a no-<body> setup page tags only the FIRST
9061
+ // Multi-root fragment fix: a no-body> setup page tags only the FIRST
9052
9062
  // top-level element with data-stx (signal-processing.ts marks one element),
9053
9063
  // so sibling root elements were orphaned \u2014 their :if / :for / {{ }} / x-text
9054
9064
  // never hydrated, which read as "{{ }} doesn't work under :if/:for". The
@@ -9145,7 +9155,7 @@ else {
9145
9155
  el.querySelectorAll('[x-cloak]').forEach(function(c) { c.removeAttribute('x-cloak'); });
9146
9156
  });
9147
9157
 
9148
- // Process <head> elements (title, meta) that may contain {{ }} expressions
9158
+ // Process head> elements (title, meta) that may contain {{ }} expressions
9149
9159
  // Use componentScope which now contains variables from processed components
9150
9160
  const headElements = document.querySelectorAll('head title, head meta[content]');
9151
9161
  headElements.forEach(el => {
@@ -9341,7 +9351,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
9341
9351
 
9342
9352
  // Apply new page's SFC setup function. During SPA navigation, re-executed page
9343
9353
  // scripts set window.stx._latestSetup to the new setup function. This takes priority
9344
- // over the stale data-stx attribute on <body> (which has the PREVIOUS page's function name).
9354
+ // over the stale data-stx attribute on body> (which has the PREVIOUS page's function name).
9345
9355
  var usedLatestSetup = false;
9346
9356
  if (window.stx._latestSetup && typeof window.stx._latestSetup === 'function') {
9347
9357
  try {
@@ -9425,7 +9435,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
9425
9435
 
9426
9436
  // Process the container content \u2014 bind {{ }}, :attr, @event directives.
9427
9437
  // Run synchronously (not in setTimeout) so componentScope is captured correctly.
9428
- // The DOMContentLoaded path processes <body> synchronously \u2014 the SPA path must match.
9438
+ // The DOMContentLoaded path processes body> synchronously \u2014 the SPA path must match.
9429
9439
  console.log('[stx:load] container:', container.tagName, '__stx_scope:', !!container.__stx_scope, 'scope keys:', Object.keys(componentScope).slice(0, 10));
9430
9440
  if (!container.__stx_scope) {
9431
9441
  // Dispose previous effects on the container (from prior navigation)
@@ -9535,7 +9545,7 @@ ${_}${U}
9535
9545
  return { ${W} };
9536
9546
  }
9537
9547
  if(window.stx)window.stx._latestSetup=${G};
9538
- </script>`,j=$;for(let H of Q)j=j.split(H.fullMatch).join("");if(j.includes("<body"))j=j.replace(/<body([^>]*)>/,`<body$1 data-stx="${G}">`);else{let H=["script","style","html","head","meta","link","title","!doctype"];j=j.replace(/<([a-zA-Z][a-zA-Z0-9-]*)\b([^>]*)>/i,(L,F,O)=>{if(H.includes(F.toLowerCase()))return L;return`<${F}${O} data-stx="${G}">`})}return{output:j,setupCode:B}}function wX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",z=()=>{Q++;let j=!1;while(Q<G){let H=Z[Q];if(H==="\\"){Q+=2;continue}if(H==="["&&!j){j=!0,Q++;continue}if(H==="]"&&j){j=!1,Q++;continue}if(H==="/"&&!j){Q++;while(Q<G&&/[gimsuyd]/.test(Z[Q]))Q++;return}if(H===`
9548
+ </script>`,j=$;for(let H of Q)j=j.split(H.fullMatch).join("");if(j.includes("<body"))j=j.replace(/<body([^>]*)>/,`<body$1 data-stx="${G}">`);else{let H=["script","style","html","head","meta","link","title","!doctype"],L=!1;j=j.replace(/<([a-zA-Z][a-zA-Z0-9-]*)\b([^>]*)>/gi,(F,O,V)=>{if(L||H.includes(O.toLowerCase()))return F;return L=!0,`<${O}${V} data-stx="${G}">`})}return{output:j,setupCode:B}}function wX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",z=()=>{Q++;let j=!1;while(Q<G){let H=Z[Q];if(H==="\\"){Q+=2;continue}if(H==="["&&!j){j=!0,Q++;continue}if(H==="]"&&j){j=!1,Q++;continue}if(H==="/"&&!j){Q++;while(Q<G&&/[gimsuyd]/.test(Z[Q]))Q++;return}if(H===`
9539
9549
  `)return;Q++}},q=()=>{if(!K)return!0;if(/[\w)\]]/.test(K))return!1;return!0},U=(j)=>{Q++;while(Q<G){if(Z[Q]==="\\"){Q+=2;continue}if(Z[Q]===j){Q++;return}Q++}},W=()=>{Q++;while(Q<G){if(Z[Q]==="\\"){Q+=2;continue}if(Z[Q]==="`"){Q++;return}if(Z[Q]==="$"&&Z[Q+1]==="{"){Q+=2;let j=1;while(Q<G&&j>0)if(Z[Q]==="{")j++,Q++;else if(Z[Q]==="}")j--,Q++;else if(Z[Q]==="'"||Z[Q]==='"')U(Z[Q]);else if(Z[Q]==="`")W();else Q++;continue}Q++}},_=()=>{if(Z[Q]==="/"&&Z[Q+1]==="/"){while(Q<G&&Z[Q]!==`
9540
9550
  `)Q++;return!0}if(Z[Q]==="/"&&Z[Q+1]==="*"){Q+=2;while(Q<G-1&&!(Z[Q]==="*"&&Z[Q+1]==="/"))Q++;return Q+=2,!0}return!1},B=()=>{if(J!==0)return;let j=Z.slice(Q).match(/^(const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/);if(j){let V=j[2];if(!X.has(V))Y.push(V),X.add(V);return}let H=Z.slice(Q).match(/^(?:const|let|var)\s+\{([^}]+)\}\s*=/);if(H){H[1].split(",").forEach((V)=>{let A=V.trim();if(!A)return;let w=A.indexOf(":"),N=(w>=0?A.slice(w+1).trim():A).split(/[\s=]/)[0];if(N&&!X.has(N))Y.push(N),X.add(N)});return}let L=Z.slice(Q).match(/^(?:const|let|var)\s+\[([^\]]+)\]\s*=/);if(L){L[1].split(",").forEach((V)=>{let A=V.trim().replace(/^\.\.\./,"");if(!A)return;let w=A.split(/[\s=]/)[0];if(w&&!X.has(w))Y.push(w),X.add(w)});return}let F=Z.slice(Q).match(/^function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/);if(F){let V=F[1];if(!X.has(V))Y.push(V),X.add(V);return}let O=Z.slice(Q).match(/^async\s+function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/);if(O){let V=O[1];if(!X.has(V))Y.push(V),X.add(V)}};while(Q<G){if(_())continue;if(Z[Q]==="'"||Z[Q]==='"'){U(Z[Q]),K=Z[Q-1];continue}if(Z[Q]==="`"){W(),K="`";continue}if(Z[Q]==="/"&&Z[Q+1]!=="/"&&Z[Q+1]!=="*"&&q()){z(),K="/";continue}if(Z[Q]==="{"){J++,K="{",Q++;continue}if(Z[Q]==="}"){J--,K="}",Q++;continue}if(J===0&&/[a-z]/i.test(Z[Q])&&(Q===0||/\s|[;{}()]/.test(Z[Q-1])))B();if(!/\s/.test(Z[Q]))K=Z[Q];Q++}return Y.join(", ")}async function a6($,Z,Y,X){if(!c4($))return $;let J=$;if(Z.skipSignalsRuntime)return J;let{output:Q,setupCode:G}=await VX(J,Y,X);if(J=Q,J=await WX(J,Z),J=UX(J),G)if(J.includes("</head>"))J=J.replace("</head>",`${G}
9541
9551
  </head>`);else if(J.includes("<body"))J=J.replace(/<body([^>]*)>/,`<body$1>