@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
package/dist/pwa/index.js CHANGED
@@ -1783,7 +1783,7 @@ ${z}`)}if($.suggestion)U.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"}`),U.join("")}function Gq($,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 q=(K+1).toString().padStart(4),U=K===Z-1?">":" ";G.push(`${U}${q} | ${X[K]}`)}return G.join(`
1785
1785
  `)}function Kq($,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",q="\x1B[0m",U=[];for(let W=J;W<=Q;W++){let z=(W+1).toString().padStart(4),B=W===Z-1,_=B?"\x1B[31m>\x1B[0m":" ",j=B?`\x1B[31m${X[W]}\x1B[0m`:`\x1B[90m${X[W]}`;U.push(`${_}${z}\x1B[0m | ${j}`)}return U.join(`
1786
+ `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G="\x1B[90m",K="\x1B[31m",q="\x1B[0m",U=[];for(let W=J;W<=Q;W++){let z=(W+1).toString().padStart(4),B=W===Z-1,_=B?"\x1B[31m>\x1B[0m":" ",j=B?`\x1B[31m${X[W]}\x1B[0m`:`\x1B[90m${X[W]}\x1B[0m`;U.push(`${_}\x1B[90m${z}\x1B[0m | ${j}`)}return U.join(`
1787
1787
  `)}function VZ($){return $.replace(/--/g,"- -").replace(/>/g,"&gt;")}function wZ($,Z){let X=$.substring(0,Z).split(`
1788
1788
  `);return{line:X.length,column:X[X.length-1].length}}function r($,Z,Y){return K3({type:$,message:Z,code:Y,format:"html"}).formatted}function qq($,Z,Y,X,J){return K3({type:$,message:Z,code:J,filePath:Y,line:X,format:"console"}).formatted}function Uq($,Z,Y){let X=Y.template.split(`
1789
1789
  `),J=wZ(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 J2($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(J,Z,!0);if(Q===void 0)return X;return JSON.stringify(Q)}catch{return X}}),Y}function LU($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=J2(X.stateExpr,Z),G=X.initExpr?J2(X.initExpr,Z):null,K=JSON.stringify(Q),q=G?JSON.stringify(G):"null";return`
3759
+ `}function J2($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(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 LU($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=J2(X.stateExpr,Z),G=X.initExpr?J2(X.initExpr,Z):null,K=JSON.stringify(Q),q=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 @@ ${B}${W}
9535
9545
  return { ${z} };
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:_}}function bX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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:_}}function bX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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++}},U=()=>{if(!K)return!0;if(/[\w)\]]/.test(K))return!1;return!0},W=(j)=>{Q++;while(Q<G){if(Z[Q]==="\\"){Q+=2;continue}if(Z[Q]===j){Q++;return}Q++}},z=()=>{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]==='"')W(Z[Q]);else if(Z[Q]==="`")z();else Q++;continue}Q++}},B=()=>{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},_=()=>{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 R=V.trim();if(!R)return;let w=R.indexOf(":"),N=(w>=0?R.slice(w+1).trim():R).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 R=V.trim().replace(/^\.\.\./,"");if(!R)return;let w=R.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(B())continue;if(Z[Q]==="'"||Z[Q]==='"'){W(Z[Q]),K=Z[Q-1];continue}if(Z[Q]==="`"){z(),K="`";continue}if(Z[Q]==="/"&&Z[Q+1]!=="/"&&Z[Q+1]!=="*"&&U()){q(),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])))_();if(!/\s/.test(Z[Q]))K=Z[Q];Q++}return Y.join(", ")}async function $9($,Z,Y,X){if(!n4($))return $;let J=$;if(Z.skipSignalsRuntime)return J;let{output:Q,setupCode:G}=await SX(J,Y,X);if(J=Q,J=await AX(J,Z),J=RX(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>
@@ -1783,7 +1783,7 @@ ${W}`)}if($.suggestion)z.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"}`),z.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 q=(K+1).toString().padStart(4),z=K===Z-1?">":" ";G.push(`${z}${q} | ${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",q="\x1B[0m",z=[];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]}`;z.push(`${B}${W}\x1B[0m | ${j}`)}return z.join(`
1786
+ `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G="\x1B[90m",K="\x1B[31m",q="\x1B[0m",z=[];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`;z.push(`${B}\x1B[90m${W}\x1B[0m | ${j}`)}return z.join(`
1787
1787
  `)}function GZ($){return $.replace(/--/g,"- -").replace(/>/g,"&gt;")}function KZ($,Z){let X=$.substring(0,Z).split(`
1788
1788
  `);return{line:X.length,column:X[X.length-1].length}}function r($,Z,Y){return $3({type:$,message:Z,code:Y,format:"html"}).formatted}function nK($,Z,Y,X,J){return $3({type:$,message:Z,code:J,filePath:Y,line:X,format:"console"}).formatted}function oK($,Z,Y){let X=Y.template.split(`
1789
1789
  `),J=KZ(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 cZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(J,Z,!0);if(Q===void 0)return X;return JSON.stringify(Q)}catch{return X}}),Y}function Yz($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=cZ(X.stateExpr,Z),G=X.initExpr?cZ(X.initExpr,Z):null,K=JSON.stringify(Q),q=G?JSON.stringify(G):"null";return`
3759
+ `}function cZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(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 Yz($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=cZ(X.stateExpr,Z),G=X.initExpr?cZ(X.initExpr,Z):null,K=JSON.stringify(Q),q=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 FX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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 FX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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++}},z=()=>{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]!=="*"&&z()){q(),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 n6($,Z,Y,X){if(!u4($))return $;let J=$;if(Z.skipSignalsRuntime)return J;let{output:Q,setupCode:G}=await LX(J,Y,X);if(J=Q,J=await zX(J,Z),J=qX(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>
package/dist/pwa.js CHANGED
@@ -3689,7 +3689,7 @@ window.__stx_reactive = (function() {
3689
3689
 
3690
3690
  return { initScope: initScope, reactive: reactive };
3691
3691
  })();
3692
- `}function AZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,Q)=>{try{let J=x0(Q,Z,!0);if(J===void 0)return X;return String(J)}catch{return X}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(X,Q)=>{try{let J=x0(Q,Z,!0);if(J===void 0)return X;return JSON.stringify(J)}catch{return X}}),Y}function wq($,Z){if($.length===0)return"";let Y=$.map((X)=>{let Q=JSON.stringify(Object.fromEntries(X.refs)),J=AZ(X.stateExpr,Z),G=X.initExpr?AZ(X.initExpr,Z):null,K=JSON.stringify(J),q=G?JSON.stringify(G):"null";return`
3692
+ `}function AZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,Q)=>{try{let J=x0(Q,Z,!0);if(J===void 0)return X;return String(J)}catch{return X}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(X,Q)=>{try{let J=x0(Q,Z,!0);if(J===void 0)return X;if(typeof J==="string"){let G=J.trim();if(G.startsWith("{")&&G.endsWith("}")||G.startsWith("[")&&G.endsWith("]"))try{return JSON.parse(G),G}catch{}}return JSON.stringify(J)}catch{return X}}),Y}function wq($,Z){if($.length===0)return"";let Y=$.map((X)=>{let Q=JSON.stringify(Object.fromEntries(X.refs)),J=AZ(X.stateExpr,Z),G=X.initExpr?AZ(X.initExpr,Z):null,K=JSON.stringify(J),q=G?JSON.stringify(G):"null";return`
3693
3693
  (function() {
3694
3694
  var scopeEl = document.querySelector('${X.selector}');
3695
3695
  if (!scopeEl) return;
@@ -5734,6 +5734,13 @@ catch (e2) {
5734
5734
 
5735
5735
  // Known directive names to exclude from generic :attr binding
5736
5736
  var DIRECTIVE_NAMES = {class:1, style:1, text:1, html:1, show:1, model:1, 'if':1, 'for':1, ref:1};
5737
+ // SVG attributes are case-sensitive, but the HTML parser lowercases
5738
+ // prefixed attribute names \u2014 ':viewBox' arrives as ':viewbox' because
5739
+ // the spec's "adjust SVG attributes" step only covers unprefixed names.
5740
+ // Without restoring the canonical casing, setAttribute('viewbox') creates
5741
+ // a dead duplicate attribute and the real viewBox never updates.
5742
+ 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'};
5743
+ var SVG_NS = 'http://www.w3.org/2000/svg';
5737
5744
  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)/;
5738
5745
  var KEY_MAP = {enter:'Enter', tab:'Tab', escape:'Escape', space:' ', up:'ArrowUp', down:'ArrowDown', left:'ArrowLeft', right:'ArrowRight', 'delete':'Delete', backspace:'Backspace'};
5739
5746
 
@@ -5758,7 +5765,8 @@ catch (e2) {
5758
5765
  if (name.startsWith('@bind:') || name.startsWith('x-bind:')
5759
5766
  || (name.startsWith(':') && !name.startsWith('::') && !DIRECTIVE_NAMES[name.slice(1).split('.')[0]] && !EVENT_RE.test(name.slice(1)))
5760
5767
  || (name.startsWith('x-') && !X_HANDLED[name.split('.')[0]] && !X_HANDLED[name])) {
5761
- const attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
5768
+ let attrName = name.startsWith('@bind:') ? name.slice(6) : name.startsWith('x-bind:') ? name.slice(7) : name.startsWith('x-') ? name.slice(2) : name.slice(1);
5769
+ if (el.namespaceURI === SVG_NS && SVG_ATTR_CASE[attrName]) attrName = SVG_ATTR_CASE[attrName];
5762
5770
  effect(() => {
5763
5771
  const v = evalAttrExpr(value);
5764
5772
  if (v === false || v === null || v === undefined) {
@@ -6137,10 +6145,12 @@ else {
6137
6145
  });
6138
6146
  }
6139
6147
  else if (Array.isArray(value)) {
6140
- el.className = originalClasses + ' ' + value.filter(Boolean).join(' ');
6148
+ var _clsArr = originalClasses + ' ' + value.filter(Boolean).join(' ');
6149
+ if (typeof el.className === 'string') el.className = _clsArr; else el.setAttribute('class', _clsArr);
6141
6150
  }
6142
6151
  else {
6143
- el.className = originalClasses + (value ? ' ' + value : '');
6152
+ var _clsStr = originalClasses + (value ? ' ' + value : '');
6153
+ if (typeof el.className === 'string') el.className = _clsStr; else el.setAttribute('class', _clsStr);
6144
6154
  }
6145
6155
  });
6146
6156
  }
@@ -8464,10 +8474,10 @@ else {
8464
8474
  var root = scriptEl ? scriptEl.nextElementSibling : null;
8465
8475
  if (!root && scriptEl) root = scriptEl.previousElementSibling || scriptEl.parentElement;
8466
8476
 
8467
- // SPA fallback: during router navigation, script is appended to <body>
8477
+ // SPA fallback: during router navigation, script is appended to body>
8468
8478
  // (not inside the content container), so nextElementSibling won't find the page content.
8469
8479
  // Only use fallback when we genuinely couldn't find a suitable root element.
8470
- // Do NOT fallback just because the script is in <body> \u2014 layout scripts in <body>
8480
+ // Do NOT fallback just because the script is in body> \u2014 layout scripts in body>
8471
8481
  // with valid siblings (e.g. sidebar <aside>) should use those siblings as root.
8472
8482
  var needsFallback = !root || root === document.body
8473
8483
  || (root && root.tagName === 'SCRIPT');
@@ -8786,7 +8796,7 @@ else {
8786
8796
  mountCallbacks.forEach(fn => fn());
8787
8797
  });
8788
8798
 
8789
- // Multi-root fragment fix: a no-<body> setup page tags only the FIRST
8799
+ // Multi-root fragment fix: a no-body> setup page tags only the FIRST
8790
8800
  // top-level element with data-stx (signal-processing.ts marks one element),
8791
8801
  // so sibling root elements were orphaned \u2014 their :if / :for / {{ }} / x-text
8792
8802
  // never hydrated, which read as "{{ }} doesn't work under :if/:for". The
@@ -8883,7 +8893,7 @@ else {
8883
8893
  el.querySelectorAll('[x-cloak]').forEach(function(c) { c.removeAttribute('x-cloak'); });
8884
8894
  });
8885
8895
 
8886
- // Process <head> elements (title, meta) that may contain {{ }} expressions
8896
+ // Process head> elements (title, meta) that may contain {{ }} expressions
8887
8897
  // Use componentScope which now contains variables from processed components
8888
8898
  const headElements = document.querySelectorAll('head title, head meta[content]');
8889
8899
  headElements.forEach(el => {
@@ -9079,7 +9089,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
9079
9089
 
9080
9090
  // Apply new page's SFC setup function. During SPA navigation, re-executed page
9081
9091
  // scripts set window.stx._latestSetup to the new setup function. This takes priority
9082
- // over the stale data-stx attribute on <body> (which has the PREVIOUS page's function name).
9092
+ // over the stale data-stx attribute on body> (which has the PREVIOUS page's function name).
9083
9093
  var usedLatestSetup = false;
9084
9094
  if (window.stx._latestSetup && typeof window.stx._latestSetup === 'function') {
9085
9095
  try {
@@ -9163,7 +9173,7 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
9163
9173
 
9164
9174
  // Process the container content \u2014 bind {{ }}, :attr, @event directives.
9165
9175
  // Run synchronously (not in setTimeout) so componentScope is captured correctly.
9166
- // The DOMContentLoaded path processes <body> synchronously \u2014 the SPA path must match.
9176
+ // The DOMContentLoaded path processes body> synchronously \u2014 the SPA path must match.
9167
9177
  console.log('[stx:load] container:', container.tagName, '__stx_scope:', !!container.__stx_scope, 'scope keys:', Object.keys(componentScope).slice(0, 10));
9168
9178
  if (!container.__stx_scope) {
9169
9179
  // Dispose previous effects on the container (from prior navigation)
@@ -9273,7 +9283,7 @@ ${B}${U}
9273
9283
  return { ${z} };
9274
9284
  }
9275
9285
  if(window.stx)window.stx._latestSetup=${G};
9276
- </script>`,j=$;for(let H of J)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:_}}function IY($){let Z=$,Y=[],X=new Set,Q=0,J=0,G=Z.length,K="",q=()=>{J++;let j=!1;while(J<G){let H=Z[J];if(H==="\\"){J+=2;continue}if(H==="["&&!j){j=!0,J++;continue}if(H==="]"&&j){j=!1,J++;continue}if(H==="/"&&!j){J++;while(J<G&&/[gimsuyd]/.test(Z[J]))J++;return}if(H===`
9286
+ </script>`,j=$;for(let H of J)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:_}}function IY($){let Z=$,Y=[],X=new Set,Q=0,J=0,G=Z.length,K="",q=()=>{J++;let j=!1;while(J<G){let H=Z[J];if(H==="\\"){J+=2;continue}if(H==="["&&!j){j=!0,J++;continue}if(H==="]"&&j){j=!1,J++;continue}if(H==="/"&&!j){J++;while(J<G&&/[gimsuyd]/.test(Z[J]))J++;return}if(H===`
9277
9287
  `)return;J++}},W=()=>{if(!K)return!0;if(/[\w)\]]/.test(K))return!1;return!0},U=(j)=>{J++;while(J<G){if(Z[J]==="\\"){J+=2;continue}if(Z[J]===j){J++;return}J++}},z=()=>{J++;while(J<G){if(Z[J]==="\\"){J+=2;continue}if(Z[J]==="`"){J++;return}if(Z[J]==="$"&&Z[J+1]==="{"){J+=2;let j=1;while(J<G&&j>0)if(Z[J]==="{")j++,J++;else if(Z[J]==="}")j--,J++;else if(Z[J]==="'"||Z[J]==='"')U(Z[J]);else if(Z[J]==="`")z();else J++;continue}J++}},B=()=>{if(Z[J]==="/"&&Z[J+1]==="/"){while(J<G&&Z[J]!==`
9278
9288
  `)J++;return!0}if(Z[J]==="/"&&Z[J+1]==="*"){J+=2;while(J<G-1&&!(Z[J]==="*"&&Z[J+1]==="/"))J++;return J+=2,!0}return!1},_=()=>{if(Q!==0)return;let j=Z.slice(J).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(J).match(/^(?:const|let|var)\s+\{([^}]+)\}\s*=/);if(H){H[1].split(",").forEach((V)=>{let w=V.trim();if(!w)return;let R=w.indexOf(":"),N=(R>=0?w.slice(R+1).trim():w).split(/[\s=]/)[0];if(N&&!X.has(N))Y.push(N),X.add(N)});return}let L=Z.slice(J).match(/^(?:const|let|var)\s+\[([^\]]+)\]\s*=/);if(L){L[1].split(",").forEach((V)=>{let w=V.trim().replace(/^\.\.\./,"");if(!w)return;let R=w.split(/[\s=]/)[0];if(R&&!X.has(R))Y.push(R),X.add(R)});return}let F=Z.slice(J).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(J).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(J<G){if(B())continue;if(Z[J]==="'"||Z[J]==='"'){U(Z[J]),K=Z[J-1];continue}if(Z[J]==="`"){z(),K="`";continue}if(Z[J]==="/"&&Z[J+1]!=="/"&&Z[J+1]!=="*"&&W()){q(),K="/";continue}if(Z[J]==="{"){Q++,K="{",J++;continue}if(Z[J]==="}"){Q--,K="}",J++;continue}if(Q===0&&/[a-z]/i.test(Z[J])&&(J===0||/\s|[;{}()]/.test(Z[J-1])))_();if(!/\s/.test(Z[J]))K=Z[J];J++}return Y.join(", ")}async function e3($,Z,Y,X){if(!L4($))return $;let Q=$;if(Z.skipSignalsRuntime)return Q;let{output:J,setupCode:G}=await MY(Q,Y,X);if(Q=J,Q=await LY(Q,Z),Q=OY(Q),G)if(Q.includes("</head>"))Q=Q.replace("</head>",`${G}
9279
9289
  </head>`);else if(Q.includes("<body"))Q=Q.replace(/<body([^>]*)>/,`<body$1>
package/dist/reactive.js CHANGED
@@ -1477,7 +1477,7 @@ window.__stx_reactive = (function() {
1477
1477
 
1478
1478
  return { initScope: initScope, reactive: reactive };
1479
1479
  })();
1480
- `}function n4($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(J,X)=>{try{let G=q0(X,Z,!0);if(G===void 0)return J;return String(G)}catch{return J}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(J,X)=>{try{let G=q0(X,Z,!0);if(G===void 0)return J;return JSON.stringify(G)}catch{return J}}),Y}function n6($,Z){if($.length===0)return"";let Y=$.map((J)=>{let X=JSON.stringify(Object.fromEntries(J.refs)),G=n4(J.stateExpr,Z),Q=J.initExpr?n4(J.initExpr,Z):null,K=JSON.stringify(G),U=Q?JSON.stringify(Q):"null";return`
1480
+ `}function n4($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(J,X)=>{try{let G=q0(X,Z,!0);if(G===void 0)return J;return String(G)}catch{return J}});return Y=Y.replace(/\{\{([\s\S]*?)\}\}/g,(J,X)=>{try{let G=q0(X,Z,!0);if(G===void 0)return J;if(typeof G==="string"){let Q=G.trim();if(Q.startsWith("{")&&Q.endsWith("}")||Q.startsWith("[")&&Q.endsWith("]"))try{return JSON.parse(Q),Q}catch{}}return JSON.stringify(G)}catch{return J}}),Y}function n6($,Z){if($.length===0)return"";let Y=$.map((J)=>{let X=JSON.stringify(Object.fromEntries(J.refs)),G=n4(J.stateExpr,Z),Q=J.initExpr?n4(J.initExpr,Z):null,K=JSON.stringify(G),U=Q?JSON.stringify(Q):"null";return`
1481
1481
  (function() {
1482
1482
  var scopeEl = document.querySelector('${J.selector}');
1483
1483
  if (!scopeEl) return;
package/dist/render.js CHANGED
@@ -1783,7 +1783,7 @@ ${W}`)}if($.suggestion)z.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"}`),z.join("")}function pK($,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 q=(K+1).toString().padStart(4),z=K===Z-1?">":" ";G.push(`${z}${q} | ${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",q="\x1B[0m",z=[];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]}`;z.push(`${B}${W}\x1B[0m | ${j}`)}return z.join(`
1786
+ `),J=Math.max(0,Z-Y-1),Q=Math.min(X.length-1,Z+Y-1),G="\x1B[90m",K="\x1B[31m",q="\x1B[0m",z=[];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`;z.push(`${B}\x1B[90m${W}\x1B[0m | ${j}`)}return z.join(`
1787
1787
  `)}function qZ($){return $.replace(/--/g,"- -").replace(/>/g,"&gt;")}function zZ($,Z){let X=$.substring(0,Z).split(`
1788
1788
  `);return{line:X.length,column:X[X.length-1].length}}function r($,Z,Y){return Z3({type:$,message:Z,code:Y,format:"html"}).formatted}function nK($,Z,Y,X,J){return Z3({type:$,message:Z,code:J,filePath:Y,line:X,format:"console"}).formatted}function oK($,Z,Y){let X=Y.template.split(`
1789
1789
  `),J=zZ(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 nZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(J,Z,!0);if(Q===void 0)return X;return JSON.stringify(Q)}catch{return X}}),Y}function Zz($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=nZ(X.stateExpr,Z),G=X.initExpr?nZ(X.initExpr,Z):null,K=JSON.stringify(Q),q=G?JSON.stringify(G):"null";return`
3759
+ `}function nZ($,Z){let Y=$.replace(/\{!!([\s\S]*?)!!\}/g,(X,J)=>{try{let Q=g0(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=g0(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 Zz($,Z){if($.length===0)return"";let Y=$.map((X)=>{let J=JSON.stringify(Object.fromEntries(X.refs)),Q=nZ(X.stateExpr,Z),G=X.initExpr?nZ(X.initExpr,Z):null,K=JSON.stringify(Q),q=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 VX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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 VX($){let Z=$,Y=[],X=new Set,J=0,Q=0,G=Z.length,K="",q=()=>{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++}},z=()=>{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]!=="*"&&z()){q(),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 s6($,Z,Y,X){if(!l4($))return $;let J=$;if(Z.skipSignalsRuntime)return J;let{output:Q,setupCode:G}=await FX(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>