@stacksjs/stx 0.2.373 → 0.2.375

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 (63) hide show
  1. package/dist/build-views.js +21 -2
  2. package/dist/{chunk-q5hyhe0r.js → chunk-2gw7rgbd.js} +1 -1
  3. package/dist/{chunk-pdrtf7ga.js → chunk-2kabn4gx.js} +1 -1
  4. package/dist/{chunk-t5d1q2ps.js → chunk-2tbxmf8q.js} +1 -1
  5. package/dist/{chunk-dhj6zfzc.js → chunk-49k7jgtd.js} +1 -1
  6. package/dist/{chunk-tas7ervy.js → chunk-4a93q5s6.js} +1 -1
  7. package/dist/{chunk-abffw83w.js → chunk-4gpbttfy.js} +1 -1
  8. package/dist/{chunk-p2bbfek9.js → chunk-5bcjbtzv.js} +1 -1
  9. package/dist/{chunk-hk88xttw.js → chunk-5fws3j14.js} +1 -1
  10. package/dist/{chunk-h13564da.js → chunk-60cttsne.js} +165 -165
  11. package/dist/{chunk-f47tm3jw.js → chunk-7d2az9wf.js} +1 -1
  12. package/dist/{chunk-e03m4har.js → chunk-7rwmnwc3.js} +27 -6
  13. package/dist/{chunk-wpzcgwqj.js → chunk-7shj7qhy.js} +1 -1
  14. package/dist/chunk-85hnnapk.js +2 -0
  15. package/dist/{chunk-zm98xr8t.js → chunk-890ykrtx.js} +2 -2
  16. package/dist/chunk-8ee37nzy.js +2 -0
  17. package/dist/{chunk-mv8q9xyt.js → chunk-c7wxj426.js} +2 -2
  18. package/dist/{chunk-h40194h3.js → chunk-cn04s9jy.js} +1 -1
  19. package/dist/{chunk-ew2f2gt0.js → chunk-dn3f4vha.js} +1 -1
  20. package/dist/{chunk-r7ym6zf1.js → chunk-e7eka8f0.js} +1 -1
  21. package/dist/{chunk-e772yfk8.js → chunk-f42xqr15.js} +1 -1
  22. package/dist/{chunk-v3mmcyvx.js → chunk-fq6x61z6.js} +1 -1
  23. package/dist/{chunk-0t2kjykc.js → chunk-fw8jzvjq.js} +1 -1
  24. package/dist/{chunk-100261ad.js → chunk-h2xrx8dp.js} +1 -1
  25. package/dist/{chunk-n44dxh1c.js → chunk-jg47xsh5.js} +1 -1
  26. package/dist/{chunk-fwbsr4kx.js → chunk-kh2v2xqp.js} +2 -2
  27. package/dist/{chunk-5p0bm54m.js → chunk-mze9423y.js} +1 -1
  28. package/dist/{chunk-gjxdxfaz.js → chunk-n1wxgmf5.js} +1 -1
  29. package/dist/{chunk-y336fe2t.js → chunk-nak6z2rd.js} +2 -2
  30. package/dist/{chunk-dhafhyw2.js → chunk-njqp8xdd.js} +1 -1
  31. package/dist/{chunk-dmtvgwmm.js → chunk-p0pp4mx1.js} +1 -1
  32. package/dist/{chunk-fscn8dg3.js → chunk-pz7jrd7e.js} +1 -1
  33. package/dist/{chunk-xgxf107n.js → chunk-qca0yw23.js} +1 -1
  34. package/dist/{chunk-e6hjrrb9.js → chunk-qnh4my5d.js} +1 -1
  35. package/dist/{chunk-mfxesx41.js → chunk-qwbrahwb.js} +1 -1
  36. package/dist/{chunk-2nqj7hnt.js → chunk-ryv2ase3.js} +1 -1
  37. package/dist/{chunk-ej4a59pv.js → chunk-rz8atgv8.js} +1 -1
  38. package/dist/{chunk-t9m81dj8.js → chunk-skqqb8s4.js} +1 -1
  39. package/dist/{chunk-bsvars9r.js → chunk-sxzdtsqe.js} +1 -1
  40. package/dist/{chunk-e26spfv8.js → chunk-tk9acsdg.js} +1 -1
  41. package/dist/{chunk-3nfccw8g.js → chunk-v1k2a5rq.js} +1 -1
  42. package/dist/{chunk-9z2mksp0.js → chunk-vsqz8wre.js} +12 -10
  43. package/dist/{chunk-mfh0zj95.js → chunk-vybqgjxd.js} +1 -1
  44. package/dist/{chunk-gsjkk7re.js → chunk-wkrbkr05.js} +1 -1
  45. package/dist/{chunk-5cjc1w05.js → chunk-xagg1b4c.js} +1 -1
  46. package/dist/{chunk-jq0p5dyc.js → chunk-xkcz6hd9.js} +1 -1
  47. package/dist/{chunk-eja82tav.js → chunk-xq8dj9br.js} +1 -1
  48. package/dist/{chunk-5853mbhm.js → chunk-y062nrhj.js} +1 -1
  49. package/dist/{chunk-8rt0vg06.js → chunk-yhfej8dy.js} +1 -1
  50. package/dist/{chunk-necx4e30.js → chunk-ypm408ak.js} +1 -1
  51. package/dist/{chunk-8rm4znzz.js → chunk-zfysz73j.js} +1 -1
  52. package/dist/{chunk-cpjqmg8e.js → chunk-zmssgked.js} +1 -1
  53. package/dist/cli.js +7 -7
  54. package/dist/craft-entry.js +1 -1
  55. package/dist/craft.js +1 -1
  56. package/dist/process.js +11 -4
  57. package/dist/pwa.js +1 -1
  58. package/dist/ssg.d.ts +21 -0
  59. package/dist/ssg.js +30 -27
  60. package/dist/types/config-types.d.ts +27 -0
  61. package/package.json +6 -6
  62. package/dist/chunk-76jc2bp2.js +0 -2
  63. package/dist/chunk-xman4hcx.js +0 -2
package/dist/process.js CHANGED
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import { injectCss } from "./dev-server/ts-css.js";
4
4
  import { findBodyOpenTag, replaceBodyOpenTag } from "./find-body-tag.js";
5
5
  import { findFirstScriptTag } from "./first-script-tag.js";
6
- import { matchHtmlComment, matchStyleElement, maskAtElementPosition, stashScriptElements } from "./html-masking.js";
6
+ import { matchHtmlComment, matchStyleElement, maskAtElementPosition, restoreStashedScripts, stashScriptElements } from "./html-masking.js";
7
7
  import { processA11yDirectives } from "./a11y.js";
8
8
  import { generateLifecycleRuntime } from "./composables.js";
9
9
  import { processTemplateBindings } from "./reactive-bindings.js";
@@ -470,6 +470,10 @@ ${output.trim()}
470
470
  @endsection`;
471
471
  }
472
472
  }
473
+ if (layoutPath && output.includes("<script")) {
474
+ const stashed = stashScriptElements(output), tagged = stashed.scripts.map((token) => tagServerScriptSource(token, filePath) ?? token);
475
+ output = restoreStashedScripts(stashed.output, tagged);
476
+ }
473
477
  output = output.replace(/@section\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*\)/g, (_, name, value) => {
474
478
  sections[name] = value;
475
479
  return "";
@@ -650,7 +654,7 @@ function escapeForBoundary(value) {
650
654
  function serverScriptErrorBoundary(sourcePath, kind, message) {
651
655
  return `<div data-stx-server-script-error role="alert" style="padding:12px 14px;border:1px solid #f0b4b4;border-left-width:4px;background:#fff5f5;color:#7a1f1f;font:13px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace"><strong style="display:block;margin-bottom:4px">stx: a &lt;script server&gt; ${kind === "module-resolution" ? "imports a module that does not resolve" : kind === "syntax" ? "does not parse" : "names something that does not exist"}, so this component rendered nothing.</strong><span style="display:block;opacity:.85">${escapeForBoundary(sourcePath)}</span><span style="display:block;margin-top:4px">${escapeForBoundary(message)}</span></div>`;
652
656
  }
653
- async function extractServerScriptVariables(output, context, filePath) {
657
+ async function extractServerScriptVariables(output, context, filePath, options) {
654
658
  const { scanScriptTags } = await importOnce("stx/signal-processing", () => import("./signal-processing.js")), boundaries = [], showBoundaries = !isProduction() && !isTest();
655
659
  for (const script of scanScriptTags(output)) {
656
660
  const attrs = script.attrs;
@@ -668,7 +672,10 @@ async function extractServerScriptVariables(output, context, filePath) {
668
672
  await extractVariables(scriptContent, context, sourcePath, {
669
673
  preserveExisting: !0,
670
674
  onFailure: (failure) => {
671
- if (!showBoundaries || failure.kind === "unknown")
675
+ if (failure.kind === "unknown")
676
+ return;
677
+ options?.onServerScriptError?.({ sourcePath, kind: failure.kind, message: failure.message });
678
+ if (!showBoundaries)
672
679
  return;
673
680
  boundaries.push({ ...at, markup: serverScriptErrorBoundary(sourcePath, failure.kind, failure.message) });
674
681
  }
@@ -702,7 +709,7 @@ async function interpolateClientScriptExpressions(output, context, filePath) {
702
709
  async function processOtherDirectives(template, context, filePath, options, dependencies) {
703
710
  let output = template;
704
711
  const opts = options;
705
- output = await extractServerScriptVariables(output, context, filePath);
712
+ output = await extractServerScriptVariables(output, context, filePath, options);
706
713
  output = await interpolateClientScriptExpressions(output, context, filePath);
707
714
  output = await processJsDirectives(output, context, filePath);
708
715
  output = await processTsDirectives(output, context, filePath);
package/dist/pwa.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  import{Gk as wq,Hk as dq,Ik as Cq,Jk as mq,Kk as gq}from"./chunk-kaet6r9w.js";import{Lk as S,Mk as Tq,Nk as _q,Ok as z,Pk as D,Qk as P,Rk as kq,Sk as vq,Tk as w,Uk as Iq,Vk as d,Wk as Hq,Xk as Oq,Yk as Mq}from"./chunk-7wj5je2t.js";import{Jw as Aq,Kw as bq,Lw as Sq,Mw as zq,Nw as Dq,Ow as Pq}from"./chunk-vsqx756d.js";import{Sw as N}from"./chunk-m8kem5ca.js";import p from"fs";import E from"path";import C from"fs";import L from"path";var k=[72,96,128,144,152,192,384,512],v=[120,152,167,180],I=[16,32];async function H(G,B){let q={success:!0,generatedFiles:[],errors:[],warnings:[]},K=G.pwa?.icons;if(!K?.src)return q.errors.push("No source icon specified in pwa.icons.src"),q.success=!1,q;let Y=L.isAbsolute(K.src)?K.src:L.resolve(process.cwd(),K.src);if(!await Bun.file(Y).exists())return q.errors.push(`Source icon not found: ${Y}`),q.success=!1,q;let Q=L.resolve(B,K.outputDir||"pwa-icons");try{C.mkdirSync(Q,{recursive:!0})}catch{return q.errors.push(`Failed to create output directory: ${Q}`),q.success=!1,q}let X=K.sizes||k,j=K.generateWebP??!0,J=K.generateAppleIcons??!0;try{let y;try{y=await import("sharp")}catch{return q.errors.push(`sharp is not installed. Install it with: bun add sharp
3
- Icon generation requires the sharp package for image processing.`),q.success=!1,q}let R=await y.default(Y).metadata();if(R.width&&R.width<512)q.warnings.push(`Source icon is ${R.width}x${R.height}. Recommend using at least 512x512 for best quality.`);for(let $ of X){let x=L.join(Q,`icon-${$}x${$}.png`);if(await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x),j){let F=L.join(Q,`icon-${$}x${$}.webp`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).webp({quality:90}).toFile(F),q.generatedFiles.push(F)}}if(J){for(let x of v){let F=L.join(Q,`apple-touch-icon-${x}x${x}.png`);await y.default(Y).resize(x,x,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile(F),q.generatedFiles.push(F)}let $=L.join(Q,"apple-touch-icon.png");await y.default(Y).resize(180,180,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile($),q.generatedFiles.push($)}for(let $ of I){let x=L.join(Q,`favicon-${$}x${$}.png`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x)}let U=512,T=L.join(Q,`icon-maskable-${U}x${U}.png`),Z=Math.floor(U*0.1),_=U-Z*2;await y.default(Y).resize(_,_,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).extend({top:Z,bottom:Z,left:Z,right:Z,background:{r:255,g:255,b:255,alpha:1}}).png().toFile(T),q.generatedFiles.push(T)}catch(y){let V=y instanceof Error?y.message:String(y);q.errors.push(`Icon generation failed: ${V}`),q.success=!1}return q}function n(G){let B=G.sizes||k,q=G.outputDir?`/${G.outputDir}`:"/pwa-icons",K=G.generateWebP??!0,Y=G.generateAppleIcons??!0,Q=[];for(let X of B)if(Q.push(`${q}/icon-${X}x${X}.png`),K)Q.push(`${q}/icon-${X}x${X}.webp`);if(Y){Q.push(`${q}/apple-touch-icon.png`);for(let X of v)Q.push(`${q}/apple-touch-icon-${X}x${X}.png`)}for(let X of I)Q.push(`${q}/favicon-${X}x${X}.png`);return Q.push(`${q}/icon-maskable-512x512.png`),Q}async function O(){try{return await import("sharp"),!0}catch{return!1}}function m(G,B,q,K){let Y=[],Q=K.join(" ");for(let X of G)if(Y.push({src:`${B}/icon-${X}x${X}.png`,sizes:`${X}x${X}`,type:"image/png",purpose:Q}),q)Y.push({src:`${B}/icon-${X}x${X}.webp`,sizes:`${X}x${X}`,type:"image/webp",purpose:Q});return Y}function g(G){return G.map((B)=>({name:B.name,short_name:B.shortName,description:B.description,url:B.url,icons:B.icons?.map((q)=>({src:q.src,sizes:q.sizes,type:q.type}))}))}function h(G){let B=G.pwa?.shareTarget;if(!B?.enabled)return;let q={action:B.action||"/share",method:B.method||"POST",enctype:B.enctype||"multipart/form-data",params:{title:B.params?.title||"title",text:B.params?.text||"text",url:B.params?.url||"url"}};if(B.acceptFiles&&B.acceptFiles.length>0)q.params.files=B.acceptFiles.map((K)=>({name:K.name,accept:K.accept}));return q}function c(G){let B=G.pwa?.fileHandlers;if(!B?.enabled||!B.accept)return;let q=[{action:B.action||"/",accept:B.accept,launch_type:B.launchType||"single-client"}];if(B.icons)q[0].icons=B.icons.map((K)=>({src:K.src,sizes:K.sizes,type:K.type}));return q}function l(G){let B=G.pwa?.protocolHandlers;if(!B||B.length===0)return;return B.map((q)=>({protocol:q.protocol,url:q.url}))}function u(G){let B=G.pwa;if(!B?.enabled||!B.manifest)return null;let{manifest:q,icons:K}=B,Y=K?.sizes||[72,96,128,144,152,192,384,512],Q=K?.outputDir?`/${K.outputDir}`:"/pwa-icons",X=K?.generateWebP??!0,j=K?.purpose||["any","maskable"],J={name:q.name,short_name:q.shortName||q.name,description:q.description,start_url:q.startUrl||"/",display:q.display||"standalone",display_override:q.displayOverride,orientation:q.orientation,theme_color:q.themeColor,background_color:q.backgroundColor,scope:q.scope||"/",lang:q.lang,dir:q.dir,id:q.id,categories:q.categories,icons:m(Y,Q,X,j)};if(q.shortcuts&&q.shortcuts.length>0)J.shortcuts=g(q.shortcuts);if(q.screenshots&&q.screenshots.length>0)J.screenshots=q.screenshots.map((U)=>({src:U.src,sizes:U.sizes,type:U.type,label:U.label,form_factor:U.platform}));let y=h(G);if(y)J.share_target=y;let V=c(G);if(V)J.file_handlers=V;let R=l(G);if(R)J.protocol_handlers=R;if(q.launchHandler)J.launch_handler={client_mode:q.launchHandler};if(q.handleLinks)J.handle_links=q.handleLinks;if(q.edgeSidePanel?.enabled)J.edge_side_panel={preferred_width:q.edgeSidePanel.preferredWidth};return J}function M(G){let B=u(G);if(!B)return"";let q=JSON.parse(JSON.stringify(B));return JSON.stringify(q,null,2)}function i(G,B){return{...B,...G,shortcuts:G.shortcuts||B.shortcuts,screenshots:G.screenshots||B.screenshots,categories:G.categories||B.categories}}function s(G){let B=[],q=G.pwa;if(!q?.enabled)return B;let K=q.manifest;if(!K)return B.push("PWA manifest configuration is missing"),B;if(!K.name)B.push("Manifest name is required");let Y=["fullscreen","standalone","minimal-ui","browser"];if(K.display&&!Y.includes(K.display))B.push(`Invalid display mode: ${K.display}. Must be one of: ${Y.join(", ")}`);let Q=["any","natural","landscape","landscape-primary","landscape-secondary","portrait","portrait-primary","portrait-secondary"];if(K.orientation&&!Q.includes(K.orientation))B.push(`Invalid orientation: ${K.orientation}`);let X=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;if(K.themeColor&&!X.test(K.themeColor))B.push(`Invalid theme color: ${K.themeColor}. Must be a valid hex color.`);if(K.backgroundColor&&!X.test(K.backgroundColor))B.push(`Invalid background color: ${K.backgroundColor}. Must be a valid hex color.`);if(q.shareTarget?.enabled){if(!q.shareTarget.action)B.push("Share target action URL is required")}if(q.fileHandlers?.enabled){if(!q.fileHandlers.accept||Object.keys(q.fileHandlers.accept).length===0)B.push("File handlers must specify accepted MIME types")}if(q.protocolHandlers)for(let j of q.protocolHandlers){if(!j.protocol)B.push("Protocol handler missing protocol");if(!j.url||!j.url.includes("%s"))B.push(`Protocol handler URL must contain %s placeholder: ${j.protocol}`)}return B}import A from"path";async function b(G){let B=G.pwa?.offline;if(!B?.enabled)return"";if(B.page){let q=A.isAbsolute(B.page)?B.page:A.resolve(process.cwd(),B.page);if(await Bun.file(q).exists())try{let{processDirectives:K}=await import("./chunk-e6hjrrb9.js"),Y=await Bun.file(q).text();return await K(Y,{},q,G,new Set)}catch(K){console.warn(`[PWA] Failed to process custom offline page: ${K}`)}else console.warn(`[PWA] Custom offline page not found: ${q}`)}return f(G)}function f(G){let B=G.pwa?.offline,q=G.pwa?.manifest,K=B?.fallbackTitle||"You are offline",Y=B?.fallbackMessage||"Please check your internet connection and try again.",Q=q?.themeColor||"#4f46e5",X=q?.shortName||q?.name||"App";return`<!DOCTYPE html>
3
+ Icon generation requires the sharp package for image processing.`),q.success=!1,q}let R=await y.default(Y).metadata();if(R.width&&R.width<512)q.warnings.push(`Source icon is ${R.width}x${R.height}. Recommend using at least 512x512 for best quality.`);for(let $ of X){let x=L.join(Q,`icon-${$}x${$}.png`);if(await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x),j){let F=L.join(Q,`icon-${$}x${$}.webp`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).webp({quality:90}).toFile(F),q.generatedFiles.push(F)}}if(J){for(let x of v){let F=L.join(Q,`apple-touch-icon-${x}x${x}.png`);await y.default(Y).resize(x,x,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile(F),q.generatedFiles.push(F)}let $=L.join(Q,"apple-touch-icon.png");await y.default(Y).resize(180,180,{fit:"contain",background:{r:255,g:255,b:255,alpha:1}}).png().toFile($),q.generatedFiles.push($)}for(let $ of I){let x=L.join(Q,`favicon-${$}x${$}.png`);await y.default(Y).resize($,$,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toFile(x),q.generatedFiles.push(x)}let U=512,T=L.join(Q,`icon-maskable-${U}x${U}.png`),Z=Math.floor(U*0.1),_=U-Z*2;await y.default(Y).resize(_,_,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).extend({top:Z,bottom:Z,left:Z,right:Z,background:{r:255,g:255,b:255,alpha:1}}).png().toFile(T),q.generatedFiles.push(T)}catch(y){let V=y instanceof Error?y.message:String(y);q.errors.push(`Icon generation failed: ${V}`),q.success=!1}return q}function n(G){let B=G.sizes||k,q=G.outputDir?`/${G.outputDir}`:"/pwa-icons",K=G.generateWebP??!0,Y=G.generateAppleIcons??!0,Q=[];for(let X of B)if(Q.push(`${q}/icon-${X}x${X}.png`),K)Q.push(`${q}/icon-${X}x${X}.webp`);if(Y){Q.push(`${q}/apple-touch-icon.png`);for(let X of v)Q.push(`${q}/apple-touch-icon-${X}x${X}.png`)}for(let X of I)Q.push(`${q}/favicon-${X}x${X}.png`);return Q.push(`${q}/icon-maskable-512x512.png`),Q}async function O(){try{return await import("sharp"),!0}catch{return!1}}function m(G,B,q,K){let Y=[],Q=K.join(" ");for(let X of G)if(Y.push({src:`${B}/icon-${X}x${X}.png`,sizes:`${X}x${X}`,type:"image/png",purpose:Q}),q)Y.push({src:`${B}/icon-${X}x${X}.webp`,sizes:`${X}x${X}`,type:"image/webp",purpose:Q});return Y}function g(G){return G.map((B)=>({name:B.name,short_name:B.shortName,description:B.description,url:B.url,icons:B.icons?.map((q)=>({src:q.src,sizes:q.sizes,type:q.type}))}))}function h(G){let B=G.pwa?.shareTarget;if(!B?.enabled)return;let q={action:B.action||"/share",method:B.method||"POST",enctype:B.enctype||"multipart/form-data",params:{title:B.params?.title||"title",text:B.params?.text||"text",url:B.params?.url||"url"}};if(B.acceptFiles&&B.acceptFiles.length>0)q.params.files=B.acceptFiles.map((K)=>({name:K.name,accept:K.accept}));return q}function c(G){let B=G.pwa?.fileHandlers;if(!B?.enabled||!B.accept)return;let q=[{action:B.action||"/",accept:B.accept,launch_type:B.launchType||"single-client"}];if(B.icons)q[0].icons=B.icons.map((K)=>({src:K.src,sizes:K.sizes,type:K.type}));return q}function l(G){let B=G.pwa?.protocolHandlers;if(!B||B.length===0)return;return B.map((q)=>({protocol:q.protocol,url:q.url}))}function u(G){let B=G.pwa;if(!B?.enabled||!B.manifest)return null;let{manifest:q,icons:K}=B,Y=K?.sizes||[72,96,128,144,152,192,384,512],Q=K?.outputDir?`/${K.outputDir}`:"/pwa-icons",X=K?.generateWebP??!0,j=K?.purpose||["any","maskable"],J={name:q.name,short_name:q.shortName||q.name,description:q.description,start_url:q.startUrl||"/",display:q.display||"standalone",display_override:q.displayOverride,orientation:q.orientation,theme_color:q.themeColor,background_color:q.backgroundColor,scope:q.scope||"/",lang:q.lang,dir:q.dir,id:q.id,categories:q.categories,icons:m(Y,Q,X,j)};if(q.shortcuts&&q.shortcuts.length>0)J.shortcuts=g(q.shortcuts);if(q.screenshots&&q.screenshots.length>0)J.screenshots=q.screenshots.map((U)=>({src:U.src,sizes:U.sizes,type:U.type,label:U.label,form_factor:U.platform}));let y=h(G);if(y)J.share_target=y;let V=c(G);if(V)J.file_handlers=V;let R=l(G);if(R)J.protocol_handlers=R;if(q.launchHandler)J.launch_handler={client_mode:q.launchHandler};if(q.handleLinks)J.handle_links=q.handleLinks;if(q.edgeSidePanel?.enabled)J.edge_side_panel={preferred_width:q.edgeSidePanel.preferredWidth};return J}function M(G){let B=u(G);if(!B)return"";let q=JSON.parse(JSON.stringify(B));return JSON.stringify(q,null,2)}function i(G,B){return{...B,...G,shortcuts:G.shortcuts||B.shortcuts,screenshots:G.screenshots||B.screenshots,categories:G.categories||B.categories}}function s(G){let B=[],q=G.pwa;if(!q?.enabled)return B;let K=q.manifest;if(!K)return B.push("PWA manifest configuration is missing"),B;if(!K.name)B.push("Manifest name is required");let Y=["fullscreen","standalone","minimal-ui","browser"];if(K.display&&!Y.includes(K.display))B.push(`Invalid display mode: ${K.display}. Must be one of: ${Y.join(", ")}`);let Q=["any","natural","landscape","landscape-primary","landscape-secondary","portrait","portrait-primary","portrait-secondary"];if(K.orientation&&!Q.includes(K.orientation))B.push(`Invalid orientation: ${K.orientation}`);let X=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;if(K.themeColor&&!X.test(K.themeColor))B.push(`Invalid theme color: ${K.themeColor}. Must be a valid hex color.`);if(K.backgroundColor&&!X.test(K.backgroundColor))B.push(`Invalid background color: ${K.backgroundColor}. Must be a valid hex color.`);if(q.shareTarget?.enabled){if(!q.shareTarget.action)B.push("Share target action URL is required")}if(q.fileHandlers?.enabled){if(!q.fileHandlers.accept||Object.keys(q.fileHandlers.accept).length===0)B.push("File handlers must specify accepted MIME types")}if(q.protocolHandlers)for(let j of q.protocolHandlers){if(!j.protocol)B.push("Protocol handler missing protocol");if(!j.url||!j.url.includes("%s"))B.push(`Protocol handler URL must contain %s placeholder: ${j.protocol}`)}return B}import A from"path";async function b(G){let B=G.pwa?.offline;if(!B?.enabled)return"";if(B.page){let q=A.isAbsolute(B.page)?B.page:A.resolve(process.cwd(),B.page);if(await Bun.file(q).exists())try{let{processDirectives:K}=await import("./chunk-qnh4my5d.js"),Y=await Bun.file(q).text();return await K(Y,{},q,G,new Set)}catch(K){console.warn(`[PWA] Failed to process custom offline page: ${K}`)}else console.warn(`[PWA] Custom offline page not found: ${q}`)}return f(G)}function f(G){let B=G.pwa?.offline,q=G.pwa?.manifest,K=B?.fallbackTitle||"You are offline",Y=B?.fallbackMessage||"Please check your internet connection and try again.",Q=q?.themeColor||"#4f46e5",X=q?.shortName||q?.name||"App";return`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
package/dist/ssg.d.ts CHANGED
@@ -79,6 +79,27 @@ export interface SSGConfig {
79
79
  * Set `false` for the old behaviour.
80
80
  */
81
81
  failOnIncludeError?: boolean;
82
+ /**
83
+ * Fail the build when a `<script server>` fails (default: true).
84
+ *
85
+ * The same condition as `failOnIncludeError`, for the other half of the page.
86
+ * A failed server script leaves every variable it declared undefined, so the
87
+ * page is written with its content missing -- empty headings, `{{ name }}` as
88
+ * literal text, or an error banner where a component should be -- while the
89
+ * build reports `Failed: 0` and exits 0.
90
+ *
91
+ * That is not a theoretical ordering: an app shipped 13 of 46 pages as
92
+ * nothing but a banner printing an absolute build-machine path to visitors,
93
+ * and what caught it was an unrelated responsive check noticing the banner
94
+ * overflowed a 390px viewport (stacksjs/stx#2035).
95
+ *
96
+ * Only the failures that are certainly bugs count -- a module that does not
97
+ * resolve, a script that does not parse, a binding that does not exist. A
98
+ * script reaching for `window` is not one of them.
99
+ *
100
+ * Set `false` for the old behaviour.
101
+ */
102
+ failOnServerScriptError?: boolean;
82
103
  /** Output directory for generated files (default: 'dist') */
83
104
  outputDir?: string;
84
105
  /** Base URL for the site (default: '/') */
package/dist/ssg.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- import{Ck as Fq,xk as Uq,yk as Iq}from"./chunk-necx4e30.js";import{Dk as Eq,Ek as Tq,Fk as Dq}from"./chunk-frp9fc7j.js";import{_k as _q,bl as zq,cl as Aq}from"./chunk-5853mbhm.js";import"./chunk-mv8q9xyt.js";import"./chunk-qjvny3wf.js";import{Lp as P,Tm as Oq,jo as l,mo as Hq,xr as n}from"./chunk-h13564da.js";import"./chunk-jc6wrxrh.js";import"./chunk-2xpdcr8c.js";import"./chunk-v90kxg77.js";import"./chunk-4arms0am.js";import"./chunk-135mme4g.js";import{nt as Xq}from"./chunk-bsvars9r.js";import{st as d}from"./chunk-w1asc0zd.js";import"./chunk-kd95t585.js";import"./chunk-gjxdxfaz.js";import"./chunk-xk402w4a.js";import{Zt as Bq}from"./chunk-dnard9gp.js";import"./chunk-vgx5077x.js";import"./chunk-met6wtbk.js";import"./chunk-ta6z7k4p.js";import"./chunk-zxptxz2b.js";import"./chunk-7racewc5.js";import{Aw as Lq,Bw as Nq,ww as Yq,xw as Vq,yw as jq,zw as Gq}from"./chunk-e03m4har.js";import"./chunk-vsqx756d.js";import{Sw as y}from"./chunk-m8kem5ca.js";import O from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,z,A)=>{let G=A.trim();if(!G)return J;if(/\bdata-stx-src=/.test(z))return J;if(Z.minify)G=yq(G);let X=Cq(G);if(!$.has(X))$.set(X,G);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(G).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${X}.js"${B}${z}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let z=q.lastIndexOf("</head>");if(K.size===0||z===-1)return q;let A=Array.from(K).filter((G)=>!q.includes(`rel="prefetch" href="${G}"`)).map((G)=>`<link rel="prefetch" href="${G}" as="script">`).join("");if(!A)return q;return q.slice(0,z)+A+q.slice(z)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
3
- `)}class wq{cacheDir;cache=new Map;loaded=!1;salt;constructor(q,Z=""){this.cacheDir=q,this.salt=Z}async load(){if(this.loaded)return;let q=j.join(this.cacheDir,"build-cache.json");if(await Bun.file(q).exists())try{let Z=JSON.parse(await Bun.file(q).text());for(let[$,Q]of Object.entries(Z))this.cache.set($,Q)}catch{}this.loaded=!0}async save(){await O.promises.mkdir(this.cacheDir,{recursive:!0});let q=j.join(this.cacheDir,"build-cache.json"),Z={};for(let[$,Q]of this.cache)Z[$]=Q;await Bun.write(q,JSON.stringify(Z))}getHash(q,Z){let $=O.statSync(q),Q=`${this.salt}|${q}:${$.mtimeMs}`;for(let J of Z)if(O.existsSync(J)){let W=O.statSync(J);Q+=`:${J}:${W.mtimeMs}`}let K=0;for(let J=0;J<Q.length;J++){let W=Q.charCodeAt(J);K=(K<<5)-K+W,K=K&K}return Math.abs(K).toString(36)}get(q,Z){let $=this.cache.get(q);if(!$)return null;let Q=this.getHash(Z,$.dependencies??[]);if($.hash!==Q)return this.cache.delete(q),null;return $.html}set(q,Z,$,Q){let K=this.getHash(Z,$);this.cache.set(q,{hash:K,html:Q,generatedAt:Date.now(),dependencies:$})}}class Rq{cacheDir;constructor(q){this.cacheDir=q}getFilePath(q){let Z=q.replace(/[^a-zA-Z0-9]/g,"_")+".json";return j.join(this.cacheDir,"isr",Z)}async get(q){let Z=this.getFilePath(q);if(!await Bun.file(Z).exists())return null;try{return JSON.parse(await Bun.file(Z).text())}catch{return null}}async set(q,Z){let $=this.getFilePath(q);await O.promises.mkdir(j.dirname($),{recursive:!0}),await Bun.write($,JSON.stringify(Z))}async invalidate(q){let Z=this.getFilePath(q);if(await Bun.file(Z).exists())await O.promises.unlink(Z)}async invalidatePattern(q){let Z=j.join(this.cacheDir,"isr");if(!O.existsSync(Z))return;let $=await O.promises.readdir(Z);for(let Q of $){let K=Q.replace(/_/g,"/").replace(".json","");if(q.test(K))await O.promises.unlink(j.join(Z,Q))}}async needsRevalidation(q){let Z=await this.get(q);if(!Z)return!0;return Date.now()>Z.revalidateAfter}}async function pq(q){try{let $=(await Bun.file(q).text()).match(/<script\s+server\b[^>]*>([\s\S]*?)<\/script>/i);if(!$)return null;let Q=$[1];if(!Q.includes("getStaticPaths"))return null;let K=Q.match(/(?:export\s+)?(?:async\s+)?function\s+getStaticPaths\s*\([^)]*\)\s*\{([\s\S]*?)\n[\t ]*\}/);if(!K)return null;return await Function(`
2
+ import{Ck as wq,xk as Uq,yk as Iq}from"./chunk-ypm408ak.js";import{Dk as Eq,Ek as Tq,Fk as Dq}from"./chunk-frp9fc7j.js";import{_k as _q,bl as zq,cl as Aq}from"./chunk-y062nrhj.js";import"./chunk-c7wxj426.js";import"./chunk-qjvny3wf.js";import{Lp as C,Tm as Oq,jo as l,mo as Hq,xr as n}from"./chunk-60cttsne.js";import"./chunk-jc6wrxrh.js";import"./chunk-2xpdcr8c.js";import"./chunk-v90kxg77.js";import"./chunk-4arms0am.js";import"./chunk-135mme4g.js";import{nt as Xq}from"./chunk-sxzdtsqe.js";import{st as d}from"./chunk-w1asc0zd.js";import"./chunk-kd95t585.js";import"./chunk-n1wxgmf5.js";import"./chunk-xk402w4a.js";import{Zt as Bq}from"./chunk-dnard9gp.js";import"./chunk-vgx5077x.js";import"./chunk-met6wtbk.js";import"./chunk-ta6z7k4p.js";import"./chunk-zxptxz2b.js";import"./chunk-7racewc5.js";import{Aw as Lq,Bw as Nq,ww as Yq,xw as Vq,yw as jq,zw as Gq}from"./chunk-7rwmnwc3.js";import"./chunk-vsqx756d.js";import{Sw as P}from"./chunk-m8kem5ca.js";import X from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,_,z)=>{let L=z.trim();if(!L)return J;if(/\bdata-stx-src=/.test(_))return J;if(Z.minify)L=yq(L);let A=Cq(L);if(!$.has(A))$.set(A,L);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(L).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${A}.js"${B}${_}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let _=q.lastIndexOf("</head>");if(K.size===0||_===-1)return q;let z=Array.from(K).filter((L)=>!q.includes(`rel="prefetch" href="${L}"`)).map((L)=>`<link rel="prefetch" href="${L}" as="script">`).join("");if(!z)return q;return q.slice(0,_)+z+q.slice(_)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
3
+ `)}class Fq{cacheDir;cache=new Map;loaded=!1;salt;constructor(q,Z=""){this.cacheDir=q,this.salt=Z}async load(){if(this.loaded)return;let q=j.join(this.cacheDir,"build-cache.json");if(await Bun.file(q).exists())try{let Z=JSON.parse(await Bun.file(q).text());for(let[$,Q]of Object.entries(Z))this.cache.set($,Q)}catch{}this.loaded=!0}async save(){await X.promises.mkdir(this.cacheDir,{recursive:!0});let q=j.join(this.cacheDir,"build-cache.json"),Z={};for(let[$,Q]of this.cache)Z[$]=Q;await Bun.write(q,JSON.stringify(Z))}getHash(q,Z){let $=X.statSync(q),Q=`${this.salt}|${q}:${$.mtimeMs}`;for(let J of Z)if(X.existsSync(J)){let W=X.statSync(J);Q+=`:${J}:${W.mtimeMs}`}let K=0;for(let J=0;J<Q.length;J++){let W=Q.charCodeAt(J);K=(K<<5)-K+W,K=K&K}return Math.abs(K).toString(36)}get(q,Z){let $=this.cache.get(q);if(!$)return null;let Q=this.getHash(Z,$.dependencies??[]);if($.hash!==Q)return this.cache.delete(q),null;return $.html}set(q,Z,$,Q){let K=this.getHash(Z,$);this.cache.set(q,{hash:K,html:Q,generatedAt:Date.now(),dependencies:$})}}class Rq{cacheDir;constructor(q){this.cacheDir=q}getFilePath(q){let Z=q.replace(/[^a-zA-Z0-9]/g,"_")+".json";return j.join(this.cacheDir,"isr",Z)}async get(q){let Z=this.getFilePath(q);if(!await Bun.file(Z).exists())return null;try{return JSON.parse(await Bun.file(Z).text())}catch{return null}}async set(q,Z){let $=this.getFilePath(q);await X.promises.mkdir(j.dirname($),{recursive:!0}),await Bun.write($,JSON.stringify(Z))}async invalidate(q){let Z=this.getFilePath(q);if(await Bun.file(Z).exists())await X.promises.unlink(Z)}async invalidatePattern(q){let Z=j.join(this.cacheDir,"isr");if(!X.existsSync(Z))return;let $=await X.promises.readdir(Z);for(let Q of $){let K=Q.replace(/_/g,"/").replace(".json","");if(q.test(K))await X.promises.unlink(j.join(Z,Q))}}async needsRevalidation(q){let Z=await this.get(q);if(!Z)return!0;return Date.now()>Z.revalidateAfter}}async function pq(q){try{let $=(await Bun.file(q).text()).match(/<script\s+server\b[^>]*>([\s\S]*?)<\/script>/i);if(!$)return null;let Q=$[1];if(!Q.includes("getStaticPaths"))return null;let K=Q.match(/(?:export\s+)?(?:async\s+)?function\s+getStaticPaths\s*\([^)]*\)\s*\{([\s\S]*?)\n[\t ]*\}/);if(!K)return null;return await Function(`
4
4
  return (async function getStaticPaths() {
5
5
  ${K[1]}
6
6
  })()
@@ -8,48 +8,51 @@ import{Ck as Fq,xk as Uq,yk as Iq}from"./chunk-necx4e30.js";import{Dk as Eq,Ek a
8
8
  return (async function getStaticProps() {
9
9
  ${J[1]}
10
10
  })()
11
- `)(Z)}catch(J){return console.error(`Error executing getStaticProps in ${$}:`,J),null}}function lq(q){return/(?:^|[^\w$.])(?:export\s+)?(?:async\s+)?function\s+action\s*\(/.test(q)||/(?:^|[^\w$.])(?:export\s+)?(?:const|let|var)\s+action\s*=/.test(q)}async function Mq(q,Z,$={},Q,K){let J=await Bun.file(q.filePath).text(),W=await hq(q.filePath),z=await cq(J,Z,q.filePath),A={...W||{},...z||{},...$,params:Z,$route:{path:q.pattern,params:Z}},G=new Set,X=[],B={...K,...Q.partialsDir?{partialsDir:Q.partialsDir}:{},...Q.componentsDir?{componentsDir:Q.componentsDir}:{},debug:!1,cache:!1,autoShell:!0,onIncludeError:(_)=>{X.push(`${j.relative(process.cwd(),_.templatePath)}: ${_.message}
12
- resolved against partialsDir: ${_.partialsDir}`)}};if(lq(J))console.warn(`Warning: ${q.pattern} exports a page action, which cannot run in a static build. Its form will submit to a file. Serve this route with the production server, or point the form's action at a route handler.`);let L=await P(J,A,q.filePath,B,G);for(let _ of[q.filePath,...G])for(let F of _q(_))G.add(F);if(Object.keys(Z).length>0){let _=`<script>if(window.stx)window.stx._rp=${JSON.stringify(Z)};else window.__stx_rp=${JSON.stringify(Z)};</script>`;if(L.includes("</head>"))L=L.replace("</head>",`${_}
13
- </head>`);else L=`${_}
14
- ${L}`}if(L=await Hq(L,{router:Q.router}),L=await Xq(L),Q.minify!==!1)return{html:nq(L),dependencies:Array.from(G),includeFailures:X};return{html:L,dependencies:Array.from(G),includeFailures:X}}function nq(q){let Z=[],$=0,Q=/(<script[^>]*>)([\s\S]*?)(<\/script>)/gi,K;while((K=Q.exec(q))!==null){let W=q.slice($,K.index);Z.push(W.replace(/<!--(?!\[if)[\s\S]*?-->/g,"").replace(/\s+/g," ").replace(/>\s+</g,"><"));let z=K[1],A=K[2],G=K[3];A=A.replace(/([^:"\\'`])\/\/(?!\/)(?![*!])([^\n]*)/g,"$1"),Z.push(z+A+G),$=K.index+K[0].length}let J=q.slice($);return Z.push(J.replace(/<!--(?!\[if)[\s\S]*?-->/g,"").replace(/\s+/g," ").replace(/>\s+</g,"><")),Z.join("").trim()}function iq(q){let Z=0;for(let $=0;$<q.length;$++){let Q=q.charCodeAt($);Z=(Z<<5)-Z+Q,Z=Z&Z}return`"${Math.abs(Z).toString(36)}"`}function sq(q,Z,$,Q){if($?.sitemap===!1)return!0;if(/<meta[^>]+name=["']robots["'][^>]+content=["'][^"']*noindex/i.test(Z))return!0;return Q.some((K)=>{if(K instanceof RegExp)return K.test(q);return K.endsWith("/")?q===K.slice(0,-1)||q.startsWith(K):q===K})}function oq(q,Z){return`<?xml version="1.0" encoding="UTF-8"?>
11
+ `)(Z)}catch(J){return console.error(`Error executing getStaticProps in ${$}:`,J),null}}function lq(q){return/(?:^|[^\w$.])(?:export\s+)?(?:async\s+)?function\s+action\s*\(/.test(q)||/(?:^|[^\w$.])(?:export\s+)?(?:const|let|var)\s+action\s*=/.test(q)}function nq(q){return q.replace(/\s*imported from \S*(?:[/\\]packages[/\\]stx[/\\]|@stacksjs[/\\]stx[/\\])\S*/g,"")}async function Mq(q,Z,$={},Q,K){let J=await Bun.file(q.filePath).text(),W=await hq(q.filePath),_=await cq(J,Z,q.filePath),z={...W||{},..._||{},...$,params:Z,$route:{path:q.pattern,params:Z}},L=new Set,A=[],B=[],U={...K,...Q.partialsDir?{partialsDir:Q.partialsDir}:{},...Q.componentsDir?{componentsDir:Q.componentsDir}:{},debug:!1,cache:!1,autoShell:!0,onIncludeError:(H)=>{A.push(`${j.relative(process.cwd(),H.templatePath)}: ${H.message}
12
+ resolved against partialsDir: ${H.partialsDir}`)},onServerScriptError:(H)=>{B.push(`${j.relative(process.cwd(),H.sourcePath)} (${H.kind}): ${nq(H.message)}`)}};if(lq(J))console.warn(`Warning: ${q.pattern} exports a page action, which cannot run in a static build. Its form will submit to a file. Serve this route with the production server, or point the form's action at a route handler.`);let G=await C(J,z,q.filePath,U,L);for(let H of[q.filePath,...L])for(let F of _q(H))L.add(F);if(Object.keys(Z).length>0){let H=`<script>if(window.stx)window.stx._rp=${JSON.stringify(Z)};else window.__stx_rp=${JSON.stringify(Z)};</script>`;if(G.includes("</head>"))G=G.replace("</head>",`${H}
13
+ </head>`);else G=`${H}
14
+ ${G}`}if(G=await Hq(G,{router:Q.router}),G=await Xq(G),Q.minify!==!1)return{html:iq(G),dependencies:Array.from(L),includeFailures:A,serverScriptFailures:B};return{html:G,dependencies:Array.from(L),includeFailures:A,serverScriptFailures:B}}function iq(q){let Z=[],$=0,Q=/(<script[^>]*>)([\s\S]*?)(<\/script>)/gi,K;while((K=Q.exec(q))!==null){let W=q.slice($,K.index);Z.push(W.replace(/<!--(?!\[if)[\s\S]*?-->/g,"").replace(/\s+/g," ").replace(/>\s+</g,"><"));let _=K[1],z=K[2],L=K[3];z=z.replace(/([^:"\\'`])\/\/(?!\/)(?![*!])([^\n]*)/g,"$1"),Z.push(_+z+L),$=K.index+K[0].length}let J=q.slice($);return Z.push(J.replace(/<!--(?!\[if)[\s\S]*?-->/g,"").replace(/\s+/g," ").replace(/>\s+</g,"><")),Z.join("").trim()}function oq(q){let Z=0;for(let $=0;$<q.length;$++){let Q=q.charCodeAt($);Z=(Z<<5)-Z+Q,Z=Z&Z}return`"${Math.abs(Z).toString(36)}"`}function sq(q,Z,$,Q){if($?.sitemap===!1)return!0;if(/<meta[^>]+name=["']robots["'][^>]+content=["'][^"']*noindex/i.test(Z))return!0;return Q.some((K)=>{if(K instanceof RegExp)return K.test(q);return K.endsWith("/")?q===K.slice(0,-1)||q.startsWith(K):q===K})}function aq(q,Z){return`<?xml version="1.0" encoding="UTF-8"?>
15
15
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
16
16
  ${q.map((Q)=>{let K=new URL(Q.loc,Z).href,J=` <url>
17
- <loc>${T(K)}</loc>`;if(Q.lastmod)J+=`
17
+ <loc>${w(K)}</loc>`;if(Q.lastmod)J+=`
18
18
  <lastmod>${Q.lastmod}</lastmod>`;if(Q.changefreq)J+=`
19
19
  <changefreq>${Q.changefreq}</changefreq>`;if(Q.priority!==void 0)J+=`
20
20
  <priority>${Q.priority}</priority>`;return J+=`
21
21
  </url>`,J}).join(`
22
22
  `)}
23
- </urlset>`}function T(q){return q.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function rq(q,Z){let $=Z.map((Q)=>{let K=" <item>";if(K+=`
24
- <title>${T(Q.title)}</title>`,K+=`
25
- <link>${T(Q.link)}</link>`,Q.description)K+=`
26
- <description>${T(Q.description)}</description>`;if(Q.pubDate)K+=`
23
+ </urlset>`}function w(q){return q.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function rq(q,Z){let $=Z.map((Q)=>{let K=" <item>";if(K+=`
24
+ <title>${w(Q.title)}</title>`,K+=`
25
+ <link>${w(Q.link)}</link>`,Q.description)K+=`
26
+ <description>${w(Q.description)}</description>`;if(Q.pubDate)K+=`
27
27
  <pubDate>${Q.pubDate.toUTCString()}</pubDate>`;if(Q.author)K+=`
28
- <author>${T(Q.author)}</author>`;if(Q.categories)for(let J of Q.categories)K+=`
29
- <category>${T(J)}</category>`;if(Q.guid)K+=`
30
- <guid>${T(Q.guid)}</guid>`;return K+=`
28
+ <author>${w(Q.author)}</author>`;if(Q.categories)for(let J of Q.categories)K+=`
29
+ <category>${w(J)}</category>`;if(Q.guid)K+=`
30
+ <guid>${w(Q.guid)}</guid>`;return K+=`
31
31
  </item>`,K});return`<?xml version="1.0" encoding="UTF-8"?>
32
32
  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
33
33
  <channel>
34
- <title>${T(q.title)}</title>
35
- <link>${T(q.link)}</link>
36
- <description>${T(q.description)}</description>
34
+ <title>${w(q.title)}</title>
35
+ <link>${w(q.link)}</link>
36
+ <description>${w(q.description)}</description>
37
37
  ${q.language?`<language>${q.language}</language>`:""}
38
- ${q.copyright?`<copyright>${T(q.copyright)}</copyright>`:""}
38
+ ${q.copyright?`<copyright>${w(q.copyright)}</copyright>`:""}
39
39
  <lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
40
40
  <atom:link href="${q.link}/rss.xml" rel="self" type="application/rss+xml"/>
41
41
  ${$.join(`
42
42
  `)}
43
43
  </channel>
44
- </rss>`}async function aq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},z=new Set,A=0,G={},X={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&O.existsSync(J.outputDir))await O.promises.rm(J.outputDir,{recursive:!0});await O.promises.mkdir(J.outputDir,{recursive:!0});let L=J.cacheSalt;if(!L){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-f47tm3jw.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-pf8575bx.js"),F=await _(J.publicDir,J.outputDir);if(F.count>0)console.log(`Optimized ${F.count} image(s) for responsive delivery`),L=[L,F.fingerprint].filter(Boolean).join(":");let C=new wq(J.cacheDir,L);if(J.cache)await C.load();try{let{generateCss:Y}=await import("./chunk-f47tm3jw.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];Fq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let H of N)g.push({route:Y,url:H.url,params:H.params,props:H.props,revalidate:H.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let b=[],s=[];for(let Y=0;Y<g.length;Y+=J.concurrency)s.push(g.slice(Y,Y+J.concurrency));for(let Y of s)await Promise.all(Y.map(async(N)=>{let{route:H,url:V,params:S,props:Sq,revalidate:a}=N;try{await J.hooks.onPageStart?.(V);let w=await Bun.file(H.filePath).text(),R=JJ(w),vq=R?.middleware?Array.isArray(R.middleware)?R.middleware:[R.middleware]:[],t=[...bq,...vq];if(t.length>0){let D=Gq(V,S,R||{}),M=Lq(D,null,void 0,{isServer:!0}),E=await Nq(t,M);if(E.redirect){let U=typeof E.redirect==="string"?E.redirect:E.redirect.path||E.redirect,x=QJ(String(U),V),k=ZJ(V,J);await O.promises.mkdir(j.dirname(k),{recursive:!0}),await Bun.write(k,x),W.successCount++,W.pages.push({route:V,outputPath:k,size:Buffer.byteLength(x),cached:!1}),b.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${U}`);return}if(E.abort){let U=typeof E.abort==="string"?E.abort:E.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${U}`);return}}let e=w.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
44
+ </rss>`}async function tq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,failOnServerScriptError:q.failOnServerScriptError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},_=new Set,z=0,L={},A={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&X.existsSync(J.outputDir))await X.promises.rm(J.outputDir,{recursive:!0});await X.promises.mkdir(J.outputDir,{recursive:!0});let U=J.cacheSalt;if(!U){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-7d2az9wf.js");try{U=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:G}=await import("./chunk-pf8575bx.js"),H=await G(J.publicDir,J.outputDir);if(H.count>0)console.log(`Optimized ${H.count} image(s) for responsive delivery`),U=[U,H.fingerprint].filter(Boolean).join(":");let F=new Fq(J.cacheDir,U);if(J.cache)await F.load();try{let{generateCss:Y}=await import("./chunk-7d2az9wf.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];wq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let O of N)g.push({route:Y,url:O.url,params:O.params,props:O.props,revalidate:O.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let S=[],o=[];for(let Y=0;Y<g.length;Y+=J.concurrency)o.push(g.slice(Y,Y+J.concurrency));for(let Y of o)await Promise.all(Y.map(async(N)=>{let{route:O,url:V,params:v,props:Sq,revalidate:r}=N;try{await J.hooks.onPageStart?.(V);let R=await Bun.file(O.filePath).text(),M=QJ(R),vq=M?.middleware?Array.isArray(M.middleware)?M.middleware:[M.middleware]:[],t=[...bq,...vq];if(t.length>0){let T=Gq(V,v,M||{}),k=Lq(T,null,void 0,{isServer:!0}),D=await Nq(t,k);if(D.redirect){let I=typeof D.redirect==="string"?D.redirect:D.redirect.path||D.redirect,y=ZJ(String(I),V),b=$J(V,J);await X.promises.mkdir(j.dirname(b),{recursive:!0}),await Bun.write(b,y),W.successCount++,W.pages.push({route:V,outputPath:b,size:Buffer.byteLength(y),cached:!1}),S.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${I}`);return}if(D.abort){let I=typeof D.abort==="string"?D.abort:D.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${I}`);return}}let e=R.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
45
45
  const validate = ${e[1]};
46
46
  return validate(route);
47
- `)({params:S})){console.warn(`Validation failed for ${V}, skipping...`);return}}catch{}let I=null,qq=!1;if(J.cache){if(I=C.get(V,H.filePath),I)qq=!0,W.cachedCount++}if(!I){let D=await Mq(H,S,Sq,J,$);if(I=D.html,J.failOnIncludeError&&D.includeFailures.length>0)throw Error(`${D.includeFailures.length} include(s) failed to resolve, so this page would have shipped with an error banner where the markup should be:
48
- ${D.includeFailures.join(`
47
+ `)({params:v})){console.warn(`Validation failed for ${V}, skipping...`);return}}catch{}let E=null,qq=!1;if(J.cache){if(E=F.get(V,O.filePath),E)qq=!0,W.cachedCount++}if(!E){let T=await Mq(O,v,Sq,J,$);if(E=T.html,J.failOnIncludeError&&T.includeFailures.length>0)throw Error(`${T.includeFailures.length} include(s) failed to resolve, so this page would have shipped with an error banner where the markup should be:
48
+ ${T.includeFailures.join(`
49
49
  `)}
50
- Set ssg.failOnIncludeError to false to build anyway.`);if(J.cache)C.set(V,H.filePath,D.dependencies,I)}let v;if(J.trailingSlash)v=j.join(J.outputDir,V,"index.html");else v=V==="/"?j.join(J.outputDir,"index.html"):j.join(J.outputDir,`${V}.html`);if(J.chunkIslands){let{html:D,chunks:M}=Qq(I,{integrity:J.integrityIslands,minify:J.minify});if(M.length>0){let E=j.join(J.outputDir,"_stx","islands");await O.promises.mkdir(E,{recursive:!0});for(let U of M){let x=j.join(E,`${U.hash}.js`);if(!await Bun.file(x).exists())await Bun.write(x,U.code);if(!z.has(U.hash)){z.add(U.hash);let k=Buffer.byteLength(U.code,"utf8");A+=k,G[U.hash]={bytes:k,file:`/_stx/islands/${U.hash}.js`}}}if(X[V]=M.map((U)=>U.hash),I=D,J.prefetchIslands)I=Zq(I)}}if(await O.promises.mkdir(j.dirname(v),{recursive:!0}),await Bun.write(v,I),!sq(V,I,R,J.sitemapExclude))b.push({loc:V,lastmod:new Date().toISOString().split("T")[0],priority:V==="/"?1:0.8});let Jq={route:V,outputPath:v,size:Buffer.byteLength(I,"utf8"),cached:qq};if(a!==!1)Jq.revalidateAt=Date.now()+a*1000;W.pages.push(Jq),W.successCount++,await J.hooks.onPageEnd?.(V,I)}catch(w){W.failedCount++,W.errors.push({route:V,error:w}),await J.hooks.onError?.(w,V),console.error(`Error generating ${V}:`,w)}}));let o=zq();if(o.length>0){let Y=o.map((N)=>`${N.filePath}: ${N.message}`).join(`
50
+ Set ssg.failOnIncludeError to false to build anyway.`);if(J.failOnServerScriptError&&T.serverScriptFailures.length>0)throw Error(`${T.serverScriptFailures.length} <script server> block(s) failed, so this page would have shipped with the content they produce missing:
51
+ ${T.serverScriptFailures.join(`
52
+ `)}
53
+ Set ssg.failOnServerScriptError to false to build anyway.`);if(J.cache)F.set(V,O.filePath,T.dependencies,E)}let x;if(J.trailingSlash)x=j.join(J.outputDir,V,"index.html");else x=V==="/"?j.join(J.outputDir,"index.html"):j.join(J.outputDir,`${V}.html`);if(J.chunkIslands){let{html:T,chunks:k}=Qq(E,{integrity:J.integrityIslands,minify:J.minify});if(k.length>0){let D=j.join(J.outputDir,"_stx","islands");await X.promises.mkdir(D,{recursive:!0});for(let I of k){let y=j.join(D,`${I.hash}.js`);if(!await Bun.file(y).exists())await Bun.write(y,I.code);if(!_.has(I.hash)){_.add(I.hash);let b=Buffer.byteLength(I.code,"utf8");z+=b,L[I.hash]={bytes:b,file:`/_stx/islands/${I.hash}.js`}}}if(A[V]=k.map((I)=>I.hash),E=T,J.prefetchIslands)E=Zq(E)}}if(await X.promises.mkdir(j.dirname(x),{recursive:!0}),await Bun.write(x,E),!sq(V,E,M,J.sitemapExclude))S.push({loc:V,lastmod:new Date().toISOString().split("T")[0],priority:V==="/"?1:0.8});let Jq={route:V,outputPath:x,size:Buffer.byteLength(E,"utf8"),cached:qq};if(r!==!1)Jq.revalidateAt=Date.now()+r*1000;W.pages.push(Jq),W.successCount++,await J.hooks.onPageEnd?.(V,E)}catch(R){W.failedCount++,W.errors.push({route:V,error:R}),await J.hooks.onError?.(R,V),console.error(`Error generating ${V}:`,R)}}));let s=zq();if(s.length>0){let Y=s.map((N)=>`${N.filePath}: ${N.message}`).join(`
51
54
  `);throw Error(`Client script bundling failed:
52
- ${Y}`)}if(J.cache)await C.save();if(J.generate404){let Y=j.join(J.pagesDir,"404.stx");if(await Bun.file(Y).exists()){let N=new Set,H={...$,debug:!1,cache:!1},V=await P(await Bun.file(Y).text(),{},Y,H,N);await Bun.write(j.join(J.outputDir,"404.html"),V)}else await Bun.write(j.join(J.outputDir,"404.html"),`<!DOCTYPE html>
55
+ ${Y}`)}if(J.cache)await F.save();if(J.generate404){let Y=j.join(J.pagesDir,"404.stx");if(await Bun.file(Y).exists()){let N=new Set,O={...$,debug:!1,cache:!1},V=await C(await Bun.file(Y).text(),{},Y,O,N);await Bun.write(j.join(J.outputDir,"404.html"),V)}else await Bun.write(j.join(J.outputDir,"404.html"),`<!DOCTYPE html>
53
56
  <html lang="en">
54
57
  <head>
55
58
  <meta charset="UTF-8">
@@ -70,7 +73,7 @@ ${Y}`)}if(J.cache)await C.save();if(J.generate404){let Y=j.join(J.pagesDir,"404.
70
73
  <a href="/">Go home</a>
71
74
  </div>
72
75
  </body>
73
- </html>`)}for(let Y of[500]){let N=j.join(J.pagesDir,`${Y}.stx`);if(await Bun.file(N).exists()){let H=new Set,V={...$,debug:!1,cache:!1},S=await P(await Bun.file(N).text(),{},N,V,H);await Bun.write(j.join(J.outputDir,`${Y}.html`),S)}}let u=j.join(J.pagesDir,"error.stx");if(await Bun.file(u).exists()){let Y=new Set,N={...$,debug:!1,cache:!1},H=await P(await Bun.file(u).text(),{},u,N,Y);await Bun.write(j.join(J.outputDir,"error.html"),H)}if(J.sitemap&&b.length>0){let Y=oq(b,J.domain),N=j.join(J.outputDir,"sitemap.xml");await Bun.write(N,Y),W.sitemapPath=N,console.log(`Generated sitemap.xml with ${b.length} URLs`)}if(J.robots!==!1){let Y=typeof J.robots==="object"?J.robots:{},N=[...J.sitemapExclude.filter((V)=>typeof V==="string"),...Y.disallow||[]],H=Bq({rules:[{userAgent:Y.userAgent||"*",allow:Y.allow||["/"],...N.length>0?{disallow:N}:{}}],...Y.sitemap!==!1&&W.sitemapPath?{sitemap:new URL("/sitemap.xml",J.domain).href}:{}});await Bun.write(j.join(J.outputDir,"robots.txt"),H),console.log("Generated robots.txt")}if(J.rss){let Y=typeof J.rss==="object"?J.rss:{title:"Site Feed",description:"Latest updates",link:J.domain},N=[];if(Y.getItems)N=await Y.getItems();let H=rq(Y,N),V=j.join(J.outputDir,"rss.xml");await Bun.write(V,H),W.rssPath=V,console.log(`Generated rss.xml with ${N.length} items`)}let f=Uq(J.outputDir);if(f.assets>0)console.log(`Externalized ${f.assets} asset(s) from ${f.pages} page(s) (${(f.bytesInlined/1024).toFixed(1)}KB removed from HTML)`);let m=Iq(J.outputDir);if(m.assets>0)console.log(`Externalized ${m.assets} repeated asset(s) from ${m.pages} page(s) (${(m.bytesInlined/1024).toFixed(1)}KB removed from HTML)`);if(J.publicDir&&O.existsSync(J.publicDir))await c(J.publicDir,J.outputDir),console.log(`Copied public assets from ${J.publicDir}`);let r=Dq();if(r)await c(r,j.join(J.outputDir,Tq)),console.log(`Copied assets from ${Eq}`)}catch(L){throw await J.hooks.onError?.(L),L}if(W.buildTime=Date.now()-Z,z.size>0){W.islandChunks={count:z.size,totalBytes:A};let L={generatedChunks:z.size,totalBytes:A,chunks:G,pages:X};await Bun.write(j.join(J.outputDir,"_stx","islands-manifest.json"),JSON.stringify(L,null,2))}await J.hooks.onBuildEnd?.(W);let B=W.islandChunks?`
76
+ </html>`)}for(let Y of[500]){let N=j.join(J.pagesDir,`${Y}.stx`);if(await Bun.file(N).exists()){let O=new Set,V={...$,debug:!1,cache:!1},v=await C(await Bun.file(N).text(),{},N,V,O);await Bun.write(j.join(J.outputDir,`${Y}.html`),v)}}let u=j.join(J.pagesDir,"error.stx");if(await Bun.file(u).exists()){let Y=new Set,N={...$,debug:!1,cache:!1},O=await C(await Bun.file(u).text(),{},u,N,Y);await Bun.write(j.join(J.outputDir,"error.html"),O)}if(J.sitemap&&S.length>0){let Y=aq(S,J.domain),N=j.join(J.outputDir,"sitemap.xml");await Bun.write(N,Y),W.sitemapPath=N,console.log(`Generated sitemap.xml with ${S.length} URLs`)}if(J.robots!==!1){let Y=typeof J.robots==="object"?J.robots:{},N=[...J.sitemapExclude.filter((V)=>typeof V==="string"),...Y.disallow||[]],O=Bq({rules:[{userAgent:Y.userAgent||"*",allow:Y.allow||["/"],...N.length>0?{disallow:N}:{}}],...Y.sitemap!==!1&&W.sitemapPath?{sitemap:new URL("/sitemap.xml",J.domain).href}:{}});await Bun.write(j.join(J.outputDir,"robots.txt"),O),console.log("Generated robots.txt")}if(J.rss){let Y=typeof J.rss==="object"?J.rss:{title:"Site Feed",description:"Latest updates",link:J.domain},N=[];if(Y.getItems)N=await Y.getItems();let O=rq(Y,N),V=j.join(J.outputDir,"rss.xml");await Bun.write(V,O),W.rssPath=V,console.log(`Generated rss.xml with ${N.length} items`)}let f=Uq(J.outputDir);if(f.assets>0)console.log(`Externalized ${f.assets} asset(s) from ${f.pages} page(s) (${(f.bytesInlined/1024).toFixed(1)}KB removed from HTML)`);let m=Iq(J.outputDir);if(m.assets>0)console.log(`Externalized ${m.assets} repeated asset(s) from ${m.pages} page(s) (${(m.bytesInlined/1024).toFixed(1)}KB removed from HTML)`);if(J.publicDir&&X.existsSync(J.publicDir))await c(J.publicDir,J.outputDir),console.log(`Copied public assets from ${J.publicDir}`);let a=Dq();if(a)await c(a,j.join(J.outputDir,Tq)),console.log(`Copied assets from ${Eq}`)}catch(U){throw await J.hooks.onError?.(U),U}if(W.buildTime=Date.now()-Z,_.size>0){W.islandChunks={count:_.size,totalBytes:z};let U={generatedChunks:_.size,totalBytes:z,chunks:L,pages:A};await Bun.write(j.join(J.outputDir,"_stx","islands-manifest.json"),JSON.stringify(U,null,2))}await J.hooks.onBuildEnd?.(W);let B=W.islandChunks?`
74
77
  Island chunks: ${W.islandChunks.count} (${(W.islandChunks.totalBytes/1024).toFixed(1)} KB lifted out of inline HTML)`:"";return console.log(`
75
78
  Build complete!
76
79
  Total: ${W.totalPages} pages
@@ -78,8 +81,8 @@ Build complete!
78
81
  Cached: ${W.cachedCount}
79
82
  Failed: ${W.failedCount}
80
83
  Time: ${W.buildTime}ms${B}
81
- `),W}async function c(q,Z){await O.promises.mkdir(Z,{recursive:!0});let $=await O.promises.readdir(q,{withFileTypes:!0});for(let Q of $){let K=j.join(q,Q.name),J=j.join(Z,Q.name);if(Q.isDirectory())await O.promises.mkdir(J,{recursive:!0}),await c(K,J);else await O.promises.copyFile(K,J)}}function tq(q={}){let Z=q.cacheDir||d(process.cwd(),"ssg-cache"),$=new Rq(Z),Q=q.revalidate||3600;return{async get(K){let J=await $.get(K);if(!J)return null;if(Date.now()>J.revalidateAfter)this.revalidate(K).catch(console.error);return{html:J.html,headers:{"Cache-Control":`public, max-age=${Q}, stale-while-revalidate=${Q*2}`,ETag:J.etag,"X-ISR-Generated":new Date(J.generatedAt).toISOString(),...J.headers}}},async revalidate(K){let W=l(".",{pagesDir:q.pagesDir||"pages"}).find((B)=>{return K.match(B.regex)!==null});if(!W){console.warn(`Route not found for revalidation: ${K}`);return}let z=K.match(W.regex),A={};if(z)W.params.forEach((B,L)=>{A[B]=z[L+1]});let G=await n(),{html:X}=await Mq(W,A,{},q,G);await $.set(K,{html:X,generatedAt:Date.now(),revalidateAfter:Date.now()+Q*1000,etag:iq(X)}),console.log(`Revalidated: ${K}`)},async invalidate(K){if(typeof K==="string")await $.invalidate(K);else await $.invalidatePattern(K)}}}function eq(q){return async()=>{return{paths:await q(),fallback:!1}}}function qJ(){return{name:"markdown",extensions:[".md",".mdx"],async load(q){let Z=await Bun.file(q).text(),$=Z.match(/^---\n([\s\S]*?)\n---/),Q={},K=Z;if($){let G=$[1];K=Z.slice($[0].length).trim();for(let X of G.split(`
82
- `)){let B=X.indexOf(":");if(B>0){let L=X.slice(0,B).trim(),_=X.slice(B+1).trim();if(_==="true")_=!0;else if(_==="false")_=!1;else if(/^\d+$/.test(_))_=parseInt(_,10);else if(/^\d+\.\d+$/.test(_))_=parseFloat(_);else if(_.startsWith("[")&&_.endsWith("]"))_=_.slice(1,-1).split(",").map((F)=>F.trim().replace(/^['"]|['"]$/g,""));Q[L]=_}}}let J=K.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/`([^`]+)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/\n/gim,"<br>"),W=[],z=/<h([1-6])>([^<]+)<\/h[1-6]>/gi,A;while((A=z.exec(J))!==null){let G=parseInt(A[1],10),X=A[2],B=X.toLowerCase().replace(/[^a-z0-9]+/g,"-");W.push({id:B,text:X,level:G})}return{content:J,data:Q,toc:W}}}}function JJ(q){return Oq(q)}function QJ(q,Z){return`<!DOCTYPE html>
84
+ `),W}async function c(q,Z){await X.promises.mkdir(Z,{recursive:!0});let $=await X.promises.readdir(q,{withFileTypes:!0});for(let Q of $){let K=j.join(q,Q.name),J=j.join(Z,Q.name);if(Q.isDirectory())await X.promises.mkdir(J,{recursive:!0}),await c(K,J);else await X.promises.copyFile(K,J)}}function eq(q={}){let Z=q.cacheDir||d(process.cwd(),"ssg-cache"),$=new Rq(Z),Q=q.revalidate||3600;return{async get(K){let J=await $.get(K);if(!J)return null;if(Date.now()>J.revalidateAfter)this.revalidate(K).catch(console.error);return{html:J.html,headers:{"Cache-Control":`public, max-age=${Q}, stale-while-revalidate=${Q*2}`,ETag:J.etag,"X-ISR-Generated":new Date(J.generatedAt).toISOString(),...J.headers}}},async revalidate(K){let W=l(".",{pagesDir:q.pagesDir||"pages"}).find((B)=>{return K.match(B.regex)!==null});if(!W){console.warn(`Route not found for revalidation: ${K}`);return}let _=K.match(W.regex),z={};if(_)W.params.forEach((B,U)=>{z[B]=_[U+1]});let L=await n(),{html:A}=await Mq(W,z,{},q,L);await $.set(K,{html:A,generatedAt:Date.now(),revalidateAfter:Date.now()+Q*1000,etag:oq(A)}),console.log(`Revalidated: ${K}`)},async invalidate(K){if(typeof K==="string")await $.invalidate(K);else await $.invalidatePattern(K)}}}function qJ(q){return async()=>{return{paths:await q(),fallback:!1}}}function JJ(){return{name:"markdown",extensions:[".md",".mdx"],async load(q){let Z=await Bun.file(q).text(),$=Z.match(/^---\n([\s\S]*?)\n---/),Q={},K=Z;if($){let L=$[1];K=Z.slice($[0].length).trim();for(let A of L.split(`
85
+ `)){let B=A.indexOf(":");if(B>0){let U=A.slice(0,B).trim(),G=A.slice(B+1).trim();if(G==="true")G=!0;else if(G==="false")G=!1;else if(/^\d+$/.test(G))G=parseInt(G,10);else if(/^\d+\.\d+$/.test(G))G=parseFloat(G);else if(G.startsWith("[")&&G.endsWith("]"))G=G.slice(1,-1).split(",").map((H)=>H.trim().replace(/^['"]|['"]$/g,""));Q[U]=G}}}let J=K.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/`([^`]+)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/\n/gim,"<br>"),W=[],_=/<h([1-6])>([^<]+)<\/h[1-6]>/gi,z;while((z=_.exec(J))!==null){let L=parseInt(z[1],10),A=z[2],B=A.toLowerCase().replace(/[^a-z0-9]+/g,"-");W.push({id:B,text:A,level:L})}return{content:J,data:Q,toc:W}}}}function QJ(q){return Oq(q)}function ZJ(q,Z){return`<!DOCTYPE html>
83
86
  <html>
84
87
  <head>
85
88
  <meta charset="utf-8">
@@ -91,4 +94,4 @@ Build complete!
91
94
  <p>Redirecting to <a href="${q}">${q}</a>...</p>
92
95
  <script>window.location.replace('${q}')</script>
93
96
  </body>
94
- </html>`}function ZJ(q,Z){if(q==="/"||q==="")return j.join(Z.outputDir,"index.html");let $=q.replace(/^\/|\/$/g,"");if(Z.trailingSlash)return j.join(Z.outputDir,$,"index.html");return j.join(Z.outputDir,`${$}.html`)}var FJ={generateStaticSite:aq,createISRHandler:tq,defineStaticPaths:eq,createMarkdownLoader:qJ};export{sq as isExcludedFromSitemap,aq as generateStaticSite,eq as defineStaticPaths,FJ as default,lq as declaresPageAction,qJ as createMarkdownLoader,tq as createISRHandler};
97
+ </html>`}function $J(q,Z){if(q==="/"||q==="")return j.join(Z.outputDir,"index.html");let $=q.replace(/^\/|\/$/g,"");if(Z.trailingSlash)return j.join(Z.outputDir,$,"index.html");return j.join(Z.outputDir,`${$}.html`)}var FJ={generateStaticSite:tq,createISRHandler:eq,defineStaticPaths:qJ,createMarkdownLoader:JJ};export{sq as isExcludedFromSitemap,tq as generateStaticSite,qJ as defineStaticPaths,FJ as default,lq as declaresPageAction,JJ as createMarkdownLoader,eq as createISRHandler};
@@ -640,6 +640,33 @@ export interface StxConfig {
640
640
  /** The directory the include was resolved against. */
641
641
  partialsDir: string;
642
642
  }) => void;
643
+ /**
644
+ * Called when a `<script server>` fails, instead of the failure being silent.
645
+ *
646
+ * The same argument as `onIncludeError`, for the other half of the page. A
647
+ * failed server script leaves every variable it declared undefined, so the
648
+ * markup around it renders empty and `{{ name }}` ships as literal text --
649
+ * and in a build that is a file nobody would knowingly deploy, written while
650
+ * the build prints `Failed: 0`. One app shipped 13 of 46 pages as nothing but
651
+ * an error banner that way (stacksjs/stx#2035), found only because the banner
652
+ * happened to overflow a mobile viewport in an unrelated responsive check.
653
+ *
654
+ * Only the kinds that are certainly bugs are reported: a module that does not
655
+ * resolve, a script that does not parse, a binding that does not exist. A
656
+ * script reaching for `window` or building something that only exists in a
657
+ * browser is classified `unknown` by the extractor and is NOT reported here,
658
+ * because that one is legitimate on pages that work.
659
+ *
660
+ * The rendered output is unchanged -- this only carries the fact out, so a
661
+ * caller that writes files can decide to fail.
662
+ */
663
+ onServerScriptError?: (failure: {
664
+ /** The file the script was written in, which is not always the file being rendered. */
665
+ sourcePath: string;
666
+ /** `module-resolution`, `syntax` or `missing-binding`. */
667
+ kind: string;
668
+ message: string;
669
+ }) => void;
643
670
  /** Path to components directory, defaults to 'components' in the same directory as the template */
644
671
  componentsDir: string;
645
672
  /** @internal Configured component root retained while nested components resolve locally. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/stx",
3
3
  "type": "module",
4
- "version": "0.2.373",
4
+ "version": "0.2.375",
5
5
  "description": "A performant UI Framework. Powered by Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -118,13 +118,13 @@
118
118
  "dependencies": {
119
119
  "@stacksjs/ts-css": "^0.3.2",
120
120
  "@stacksjs/clapp": "^0.2.16",
121
- "@stacksjs/desktop": "0.2.373",
122
- "@stacksjs/sanitizer": "0.2.373",
121
+ "@stacksjs/desktop": "0.2.375",
122
+ "@stacksjs/sanitizer": "0.2.375",
123
123
  "@stacksjs/ts-i18n": "^0.1.11",
124
- "bun-plugin-stx": "0.2.373",
124
+ "bun-plugin-stx": "0.2.375",
125
125
  "bunfig": "^0.15.19",
126
- "stx-router": "0.2.373",
127
- "ts-broadcasting": "^0.0.10",
126
+ "stx-router": "0.2.375",
127
+ "ts-broadcasting": "^0.0.11",
128
128
  "ts-images": "^0.2.22",
129
129
  "ts-syntax-highlighter": "^0.2.1"
130
130
  }
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Ze as a}from"./chunk-ej4a59pv.js";import"./chunk-y336fe2t.js";import"./chunk-0knxnyq6.js";import"./chunk-mv8q9xyt.js";import"./chunk-h13564da.js";import"./chunk-jc6wrxrh.js";import"./chunk-2xpdcr8c.js";import"./chunk-v90kxg77.js";import"./chunk-4arms0am.js";import"./chunk-135mme4g.js";import"./chunk-bsvars9r.js";import"./chunk-w1asc0zd.js";import"./chunk-kd95t585.js";import"./chunk-gjxdxfaz.js";import"./chunk-xk402w4a.js";import"./chunk-dnard9gp.js";import"./chunk-vgx5077x.js";import"./chunk-met6wtbk.js";import"./chunk-ta6z7k4p.js";import"./chunk-zxptxz2b.js";import"./chunk-7racewc5.js";import"./chunk-e03m4har.js";import"./chunk-vsqx756d.js";import"./chunk-m8kem5ca.js";export{a as startProductionServer};
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Ve as a}from"./chunk-e772yfk8.js";import"./chunk-0knxnyq6.js";import"./chunk-h13564da.js";import"./chunk-jc6wrxrh.js";import"./chunk-2xpdcr8c.js";import"./chunk-v90kxg77.js";import"./chunk-4arms0am.js";import"./chunk-135mme4g.js";import"./chunk-bsvars9r.js";import"./chunk-w1asc0zd.js";import"./chunk-kd95t585.js";import"./chunk-gjxdxfaz.js";import"./chunk-xk402w4a.js";import"./chunk-dnard9gp.js";import"./chunk-vgx5077x.js";import"./chunk-met6wtbk.js";import"./chunk-ta6z7k4p.js";import"./chunk-zxptxz2b.js";import"./chunk-7racewc5.js";import"./chunk-e03m4har.js";import"./chunk-vsqx756d.js";import"./chunk-m8kem5ca.js";export{a as buildApp};