@stacksjs/stx 0.2.344 → 0.2.346
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.
- package/dist/{chunk-krfx5562.js → chunk-1bws4afs.js} +183 -171
- package/dist/{chunk-7kcfbc0j.js → chunk-1caep9rn.js} +1 -1
- package/dist/{chunk-e4yskgtb.js → chunk-1djdz98r.js} +1 -1
- package/dist/{chunk-mvat8js5.js → chunk-1vyz6kr8.js} +2 -2
- package/dist/{chunk-efx05ah0.js → chunk-1xayahc6.js} +1 -1
- package/dist/{chunk-hsbbfp0c.js → chunk-1xts7768.js} +1 -1
- package/dist/{chunk-7t6h8crt.js → chunk-21mmq3aj.js} +1 -1
- package/dist/{chunk-7d2gfyk8.js → chunk-3pggfwbf.js} +1 -1
- package/dist/{chunk-tscr6bs8.js → chunk-5hhng72w.js} +1 -1
- package/dist/{chunk-bpb3xkg4.js → chunk-7hjjckat.js} +1 -1
- package/dist/{chunk-jzfk5ect.js → chunk-7w66sc17.js} +1 -1
- package/dist/{chunk-mz4breg8.js → chunk-864m3xp2.js} +1 -1
- package/dist/{chunk-3n8avn17.js → chunk-8tghv8cf.js} +1 -1
- package/dist/{chunk-tthrw91n.js → chunk-akb6mgrb.js} +1 -1
- package/dist/{chunk-94sxzp5x.js → chunk-b08taxsf.js} +1 -1
- package/dist/{chunk-1bct7pfj.js → chunk-bxwanj4g.js} +1 -1
- package/dist/{chunk-dx2s51rr.js → chunk-byn0ptqt.js} +1 -1
- package/dist/{chunk-nexpxxsa.js → chunk-ddsgfmhv.js} +1 -1
- package/dist/{chunk-a1ghxrb1.js → chunk-dyy74sdv.js} +1 -1
- package/dist/{chunk-39qy76ek.js → chunk-es275g3w.js} +1 -1
- package/dist/{chunk-8tjg4wbr.js → chunk-fvvdq3ev.js} +1 -1
- package/dist/{chunk-csv48xrx.js → chunk-fynb9e02.js} +1 -1
- package/dist/{chunk-zkwk82ss.js → chunk-hfvknn03.js} +1 -1
- package/dist/{chunk-cmccdayf.js → chunk-j8s9akdq.js} +1 -1
- package/dist/{chunk-cdq28mek.js → chunk-jwe0cwff.js} +1 -1
- package/dist/{chunk-020hpw7m.js → chunk-k5hv1qqy.js} +1 -1
- package/dist/{chunk-72x5v5an.js → chunk-k80kr2t2.js} +1 -1
- package/dist/{chunk-cappe4hd.js → chunk-km92eab7.js} +1 -1
- package/dist/{chunk-a29x23g7.js → chunk-maq5jag2.js} +1 -1
- package/dist/{chunk-5yhv1pe5.js → chunk-p04rck27.js} +1 -1
- package/dist/{chunk-gmm82dst.js → chunk-pc8np1bb.js} +1 -1
- package/dist/{chunk-6z9pm31g.js → chunk-q45fva8h.js} +1 -1
- package/dist/{chunk-9yqt0nf2.js → chunk-qp7sk0ex.js} +1 -1
- package/dist/{chunk-ewpbxy5m.js → chunk-rf2cejt3.js} +1 -1
- package/dist/{chunk-mpyjnwje.js → chunk-rwk5hwvk.js} +1 -1
- package/dist/{chunk-5apmxb4e.js → chunk-s11e8aq9.js} +1 -1
- package/dist/{chunk-wfwj4390.js → chunk-s3jyec9k.js} +1 -1
- package/dist/{chunk-fs2t4rs3.js → chunk-skd72bn4.js} +2 -2
- package/dist/{chunk-3xpk99z4.js → chunk-t2py7vc3.js} +1 -1
- package/dist/{chunk-j5qygdy9.js → chunk-t83m2pkm.js} +1 -1
- package/dist/{chunk-4kbaky4w.js → chunk-tnm0nez5.js} +1 -1
- package/dist/{chunk-g28fs4aa.js → chunk-vw83y4we.js} +2 -2
- package/dist/{chunk-zwhnkxgy.js → chunk-vzbcdxd5.js} +1 -1
- package/dist/{chunk-q5gzpn1n.js → chunk-washyj03.js} +1 -1
- package/dist/{chunk-1exk54qt.js → chunk-wbp4vbm0.js} +1 -1
- package/dist/{chunk-xh9paa2g.js → chunk-xytgvfbf.js} +2 -2
- package/dist/{chunk-5atmahe4.js → chunk-zdq7emrd.js} +322 -322
- package/dist/{chunk-9p5gbhwp.js → chunk-zz2yxsf9.js} +1 -1
- package/dist/cli.js +7 -7
- package/dist/component-library.d.ts +0 -31
- package/dist/component-library.js +279 -17
- package/dist/craft-entry.js +1 -1
- package/dist/craft.js +1 -1
- package/dist/process.js +25 -3
- package/dist/pwa.js +1 -1
- package/dist/ssg.js +2 -2
- package/dist/theme-tokens.js +15 -5
- package/dist/variable-extractor.d.ts +31 -0
- package/dist/variable-extractor.js +9 -5
- package/package.json +5 -5
package/dist/process.js
CHANGED
|
@@ -641,23 +641,45 @@ function scriptSourceOf(attrs) {
|
|
|
641
641
|
const match = new RegExp(`${SCRIPT_SOURCE_ATTR}="([^"]*)"`).exec(attrs);
|
|
642
642
|
return match ? decodeURIComponent(match[1]) : void 0;
|
|
643
643
|
}
|
|
644
|
+
function escapeForBoundary(value) {
|
|
645
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
646
|
+
}
|
|
647
|
+
function serverScriptErrorBoundary(sourcePath, kind, message) {
|
|
648
|
+
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 <script server> ${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>`;
|
|
649
|
+
}
|
|
644
650
|
async function extractServerScriptVariables(output, context, filePath) {
|
|
645
651
|
const scriptRegex = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
|
646
652
|
let scriptMatch;
|
|
653
|
+
const boundaries = [], showBoundaries = !isProduction() && !isTest();
|
|
647
654
|
while ((scriptMatch = scriptRegex.exec(output)) !== null) {
|
|
648
655
|
const attrs = scriptMatch[1], scriptContent = scriptMatch[2];
|
|
649
656
|
if (!/\bserver\b/.test(attrs) || !scriptContent.trim())
|
|
650
657
|
continue;
|
|
651
|
-
const sourcePath = scriptSourceOf(attrs) ?? filePath;
|
|
658
|
+
const sourcePath = scriptSourceOf(attrs) ?? filePath, at = { index: scriptMatch.index, length: scriptMatch[0].length };
|
|
652
659
|
try {
|
|
653
660
|
const { extractVariables } = await importOnce("stx/variable-extractor", () => import("./variable-extractor.js"));
|
|
654
|
-
await extractVariables(scriptContent, context, sourcePath, {
|
|
661
|
+
await extractVariables(scriptContent, context, sourcePath, {
|
|
662
|
+
preserveExisting: !0,
|
|
663
|
+
onFailure: (failure) => {
|
|
664
|
+
if (!showBoundaries || failure.kind === "unknown")
|
|
665
|
+
return;
|
|
666
|
+
boundaries.push({ ...at, markup: serverScriptErrorBoundary(sourcePath, failure.kind, failure.message) });
|
|
667
|
+
}
|
|
668
|
+
});
|
|
655
669
|
} catch (e) {
|
|
656
670
|
const err = e instanceof Error ? e : Error(String(e));
|
|
657
671
|
errorLogger.log(err, { filePath: sourcePath, phase: "server-script-extraction" }, "warning");
|
|
658
672
|
console.warn(`[stx] server <script> extraction failed in ${sourcePath}: ${err.message}`);
|
|
673
|
+
if (showBoundaries)
|
|
674
|
+
boundaries.push({ ...at, markup: serverScriptErrorBoundary(sourcePath, "unknown", err.message) });
|
|
659
675
|
}
|
|
660
676
|
}
|
|
677
|
+
if (boundaries.length === 0)
|
|
678
|
+
return output;
|
|
679
|
+
let result = output;
|
|
680
|
+
for (const boundary of boundaries.sort((a, b) => b.index - a.index))
|
|
681
|
+
result = result.slice(0, boundary.index) + boundary.markup + result.slice(boundary.index + boundary.length);
|
|
682
|
+
return result;
|
|
661
683
|
}
|
|
662
684
|
async function interpolateClientScriptExpressions(output, context, filePath) {
|
|
663
685
|
try {
|
|
@@ -673,7 +695,7 @@ async function interpolateClientScriptExpressions(output, context, filePath) {
|
|
|
673
695
|
async function processOtherDirectives(template, context, filePath, options, dependencies) {
|
|
674
696
|
let output = template;
|
|
675
697
|
const opts = options;
|
|
676
|
-
await extractServerScriptVariables(output, context, filePath);
|
|
698
|
+
output = await extractServerScriptVariables(output, context, filePath);
|
|
677
699
|
output = await interpolateClientScriptExpressions(output, context, filePath);
|
|
678
700
|
output = await processJsDirectives(output, context, filePath);
|
|
679
701
|
output = await processTsDirectives(output, context, filePath);
|
package/dist/pwa.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import{Fk as wq,Gk as dq,Hk as Cq,Ik as mq,Jk as gq}from"./chunk-wvc7t11n.js";import{Kk as S,Lk as Tq,Mk as _q,Nk as z,Ok as D,Pk as P,Qk as kq,Rk as vq,Sk as w,Tk as Iq,Uk as d,Vk as Hq,Wk as Oq,Xk as Mq}from"./chunk-c30qnb6z.js";import{Ew as Aq,Fw as bq,Gw as Sq,Hw as zq,Iw as Dq,Jw as Pq}from"./chunk-9nrgjtah.js";import{Nw as N}from"./chunk-ejqpq0wc.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-
|
|
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-t83m2pkm.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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Bk as Fq,wk as Uq,xk as Iq}from"./chunk-v7aa7v85.js";import{Ck as Eq,Dk as Tq,Ek as Dq}from"./chunk-c0n802j1.js";import{Zk as _q,al as zq,bl as Aq}from"./chunk-
|
|
2
|
+
import{Bk as Fq,wk as Uq,xk as Iq}from"./chunk-v7aa7v85.js";import{Ck as Eq,Dk as Tq,Ek as Dq}from"./chunk-c0n802j1.js";import{Zk as _q,al as zq,bl as Aq}from"./chunk-tnm0nez5.js";import"./chunk-hfvknn03.js";import"./chunk-fvsefztj.js";import{Jp as P,Sm as Oq,io as l,lo as Hq,sr as n}from"./chunk-zdq7emrd.js";import"./chunk-8y1ve8tc.js";import"./chunk-njx93b4z.js";import"./chunk-bqdfbwdf.js";import"./chunk-89mqnh67.js";import"./chunk-xvh1k1a4.js";import{it as Xq}from"./chunk-skd72bn4.js";import{nt as d}from"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-21mmq3aj.js";import"./chunk-vhta1be7.js";import{Ut as Bq}from"./chunk-tc4pj651.js";import"./chunk-san1eq0r.js";import"./chunk-avwywzsj.js";import"./chunk-wj21f1e0.js";import"./chunk-d86q27j8.js";import"./chunk-72x62kch.js";import{rw as Yq,sw as Vq,tw as jq,uw as Gq,vw as Lq,ww as Nq}from"./chunk-yg5r7bnm.js";import"./chunk-9nrgjtah.js";import{Nw as y}from"./chunk-ejqpq0wc.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
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(`
|
|
4
4
|
return (async function getStaticPaths() {
|
|
5
5
|
${K[1]}
|
|
@@ -41,7 +41,7 @@ ${q.map((Q)=>{let K=new URL(Q.loc,Z).href,J=` <url>
|
|
|
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-
|
|
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-864m3xp2.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-e631svvs.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-864m3xp2.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",`
|
|
45
45
|
const validate = ${e[1]};
|
|
46
46
|
return validate(route);
|
|
47
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:
|
package/dist/theme-tokens.js
CHANGED
|
@@ -3,16 +3,26 @@ export const SEMANTIC_TOKENS = {
|
|
|
3
3
|
"fg-strong": { light: "neutral-700", dark: "neutral-300", description: "Labels, secondary headings" },
|
|
4
4
|
"fg-muted": { light: "neutral-600", dark: "neutral-400", description: "Supporting text" },
|
|
5
5
|
"fg-soft": { light: "neutral-500", dark: "neutral-400", description: "De-emphasised text" },
|
|
6
|
-
"fg-subtle": { light: "neutral-400", dark: "neutral-500", description: "
|
|
6
|
+
"fg-subtle": { light: "neutral-400", dark: "neutral-500", description: "Recessive, non-essential text" },
|
|
7
7
|
surface: { light: "neutral-50", dark: "neutral-800", description: "Page and panel background" },
|
|
8
8
|
"surface-raised": { light: "neutral-100", dark: "neutral-700", description: "Cards, popovers" },
|
|
9
9
|
"surface-sunken": { light: "neutral-200", dark: "neutral-700", description: "Wells, track backgrounds" },
|
|
10
10
|
panel: { light: "white", dark: "neutral-800", description: "Card, menu, dialog surface" },
|
|
11
11
|
field: { light: "white", dark: "neutral-700", description: "Form control surface" },
|
|
12
|
+
page: { light: "neutral-50", dark: "neutral-900", description: "Page background, behind panels" },
|
|
13
|
+
content: { light: "white", dark: "neutral-900", description: "Content area under a chrome header - a table or list body" },
|
|
14
|
+
"surface-hover": { light: "neutral-100", dark: "neutral-700", description: "Row or item highlight on a page or panel" },
|
|
15
|
+
"surface-raised-hover": { light: "neutral-200", dark: "neutral-600", description: "Raised surface, hovered" },
|
|
16
|
+
"surface-sunken-hover": { light: "neutral-300", dark: "neutral-600", description: "Sunken surface, hovered" },
|
|
17
|
+
"field-hover": { light: "neutral-50", dark: "neutral-600", description: "Form control surface, hovered" },
|
|
18
|
+
link: { light: "blue-500", dark: "blue-400", description: "Hyperlink" },
|
|
19
|
+
"link-hover": { light: "blue-600", dark: "blue-300", description: "Hyperlink, hovered" },
|
|
20
|
+
inverse: { light: "neutral-900", dark: "neutral-700", description: "Tooltip bubble, inverted surface" },
|
|
21
|
+
"inverse-ink": { light: "white", dark: "white", description: "Text on an inverted surface" },
|
|
12
22
|
line: { light: "neutral-200", dark: "neutral-700", description: "Default border, divider" },
|
|
13
23
|
"line-strong": { light: "neutral-300", dark: "neutral-600", description: "Input border, focus ring track" },
|
|
14
24
|
accent: { light: "blue-600", dark: "blue-400", description: "Primary action, selected state" },
|
|
15
|
-
info: { light: "cyan-600", dark: "cyan-400", description: "Informational emphasis
|
|
25
|
+
info: { light: "cyan-600", dark: "cyan-400", description: "Informational emphasis" },
|
|
16
26
|
danger: { light: "red-600", dark: "red-400", description: "Errors, destructive actions" },
|
|
17
27
|
success: { light: "green-600", dark: "green-400", description: "Confirmation" },
|
|
18
28
|
warning: { light: "yellow-600", dark: "yellow-400", description: "Caution" },
|
|
@@ -27,9 +37,9 @@ export const SEMANTIC_TOKENS = {
|
|
|
27
37
|
"success-solid-hover": { light: "green-600", dark: "green-700", description: "Confirmation fill, hovered" },
|
|
28
38
|
"warning-solid-hover": { light: "yellow-600", dark: "yellow-700", description: "Caution fill, hovered" },
|
|
29
39
|
"accent-ink": { light: "white", dark: "white", description: "Text on a primary fill" },
|
|
30
|
-
"info-ink": { light: "
|
|
40
|
+
"info-ink": { light: "neutral-900", dark: "neutral-900", description: "Text on an informational fill" },
|
|
31
41
|
"danger-ink": { light: "white", dark: "white", description: "Text on a destructive fill" },
|
|
32
|
-
"success-ink": { light: "
|
|
42
|
+
"success-ink": { light: "neutral-900", dark: "neutral-900", description: "Text on a confirmation fill" },
|
|
33
43
|
"warning-ink": { light: "neutral-900", dark: "neutral-900", description: "Text on a caution fill" },
|
|
34
44
|
"accent-soft": { light: "blue-100", dark: "blue-900", description: "Tinted primary fill" },
|
|
35
45
|
"accent-soft-ink": { light: "blue-800", dark: "blue-200", description: "Text on a tinted primary fill" },
|
|
@@ -48,7 +58,7 @@ export const SEMANTIC_TOKENS = {
|
|
|
48
58
|
"secondary-soft": { light: "purple-100", dark: "purple-900", description: "Tinted secondary fill" },
|
|
49
59
|
"secondary-soft-ink": { light: "purple-800", dark: "purple-200", description: "Text on a tinted secondary fill" },
|
|
50
60
|
"danger-fg": { light: "red-900", dark: "red-300", description: "Text in a field with an error" },
|
|
51
|
-
"danger-fg-subtle": { light: "red-300", dark: "red-500", description: "
|
|
61
|
+
"danger-fg-subtle": { light: "red-300", dark: "red-500", description: "Recessive text in a field with an error" },
|
|
52
62
|
"danger-line": { light: "red-300", dark: "red-600", description: "Border of a field with an error" },
|
|
53
63
|
"danger-focus": { light: "red-500", dark: "red-400", description: "Focus ring of a field with an error" }
|
|
54
64
|
};
|
|
@@ -33,6 +33,18 @@ export declare function stripTypeScript(scriptContent: string): string;
|
|
|
33
33
|
* Matched on the message because the failure arrives as a plain Error from the
|
|
34
34
|
* runtime's loader rather than a typed one, and the wording differs between
|
|
35
35
|
* Bun and Node.
|
|
36
|
+
*
|
|
37
|
+
* `cannot find package` is the important one and was missing. An ESM import
|
|
38
|
+
* that does not resolve says
|
|
39
|
+
*
|
|
40
|
+
* Cannot find package 'bunfig' imported from /…/dist/index.js
|
|
41
|
+
*
|
|
42
|
+
* and only a `require()` says "module". So the case stacksjs/stx#1991 was
|
|
43
|
+
* filed for - a dependency importing a package it had not declared, which
|
|
44
|
+
* threw wherever that package was unreachable - was classified as an unknown
|
|
45
|
+
* failure and got the generic warning instead of the one naming the cause.
|
|
46
|
+
* That one is also deduplicated per cause, so the clearest failure in the set
|
|
47
|
+
* was getting the quietest treatment.
|
|
36
48
|
*/
|
|
37
49
|
export declare function isModuleResolutionFailure(message: string): boolean;
|
|
38
50
|
/**
|
|
@@ -76,6 +88,25 @@ export interface ExtractVariablesOptions {
|
|
|
76
88
|
* passes this flag on.
|
|
77
89
|
*/
|
|
78
90
|
preserveExisting?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Called when the script failed, so every variable it declared is undefined
|
|
93
|
+
* and anything reading one renders empty (stacksjs/stx#1991).
|
|
94
|
+
*
|
|
95
|
+
* `kind` says how certain that is a bug. The first three always are.
|
|
96
|
+
* `unknown` is not: a server script reaching for `window` or constructing a
|
|
97
|
+
* Chart lands there, which is the case the quiet fallback exists for, so a
|
|
98
|
+
* caller showing the developer something should leave that one alone.
|
|
99
|
+
*
|
|
100
|
+
* Reported rather than thrown, because one failed script must not take the
|
|
101
|
+
* page down with it. Before this a caller could not find out at all: the
|
|
102
|
+
* extractor warned and returned normally, which is why the component became
|
|
103
|
+
* a hole that nothing could put a boundary around.
|
|
104
|
+
*/
|
|
105
|
+
onFailure?: (failure: {
|
|
106
|
+
kind: 'module-resolution' | 'syntax' | 'missing-binding' | 'unknown';
|
|
107
|
+
message: string;
|
|
108
|
+
error: unknown;
|
|
109
|
+
}) => void;
|
|
79
110
|
}
|
|
80
111
|
export declare function extractVariables(scriptContent: string, context: Record<string, unknown>, filePath: string, options?: ExtractVariablesOptions): Promise<void>;
|
|
81
112
|
/**
|
|
@@ -274,7 +274,7 @@ export function stripTypeScript(scriptContent) {
|
|
|
274
274
|
return result;
|
|
275
275
|
}
|
|
276
276
|
export function isModuleResolutionFailure(message) {
|
|
277
|
-
return /cannot find module|could not resolve|module not found|failed to resolve/i.test(message);
|
|
277
|
+
return /cannot find module|cannot find package|could not resolve|module not found|failed to resolve/i.test(message);
|
|
278
278
|
}
|
|
279
279
|
export function isSyntaxFailure(error) {
|
|
280
280
|
if (error instanceof SyntaxError)
|
|
@@ -569,18 +569,22 @@ export async function extractVariables(scriptContent, context, filePath, options
|
|
|
569
569
|
if (context.__stx_strict_hydration)
|
|
570
570
|
throw primaryError;
|
|
571
571
|
const msg = primaryError instanceof Error ? primaryError.message : String(primaryError);
|
|
572
|
-
if (isModuleResolutionFailure(msg))
|
|
572
|
+
if (isModuleResolutionFailure(msg)) {
|
|
573
573
|
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} imports a module that does not resolve, so every variable in that script is undefined. Cause: ${msg}`);
|
|
574
|
-
|
|
574
|
+
options.onFailure?.({ kind: "module-resolution", message: msg, error: primaryError });
|
|
575
|
+
} else if (isSyntaxFailure(primaryError)) {
|
|
575
576
|
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} does not parse, so every variable in that script is undefined. Cause: ${msg}`);
|
|
576
|
-
|
|
577
|
+
options.onFailure?.({ kind: "syntax", message: msg, error: primaryError });
|
|
578
|
+
} else if (isMissingBindingFailure(msg)) {
|
|
577
579
|
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} names something that does not exist, so every variable in that script is undefined. Optional chaining does not help here: an undefined identifier throws before the chain is reached. Cause: ${msg}`);
|
|
578
|
-
|
|
580
|
+
options.onFailure?.({ kind: "missing-binding", message: msg, error: primaryError });
|
|
581
|
+
} else {
|
|
579
582
|
const seenKey = `${filePath ?? "<unknown>"}\x00${msg}`;
|
|
580
583
|
if (process.env.STX_DEBUG || !reportedServerScriptFailures.has(seenKey)) {
|
|
581
584
|
reportedServerScriptFailures.add(seenKey);
|
|
582
585
|
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} threw, so every variable in that script is undefined and anything that reads one renders empty. Cause: ${msg}`);
|
|
583
586
|
}
|
|
587
|
+
options.onFailure?.({ kind: "unknown", message: msg, error: primaryError });
|
|
584
588
|
}
|
|
585
589
|
try {
|
|
586
590
|
await fallbackVariableExtraction(jsContent, context, filePath);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/stx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.346",
|
|
5
5
|
"description": "A performant UI Framework. Powered by Bun.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"@stacksjs/ts-css": "^0.3.2",
|
|
119
119
|
"@stacksjs/clapp": "^0.2.16",
|
|
120
|
-
"@stacksjs/desktop": "0.2.
|
|
121
|
-
"@stacksjs/sanitizer": "0.2.
|
|
120
|
+
"@stacksjs/desktop": "0.2.346",
|
|
121
|
+
"@stacksjs/sanitizer": "0.2.346",
|
|
122
122
|
"@stacksjs/ts-i18n": "^0.1.11",
|
|
123
|
-
"bun-plugin-stx": "0.2.
|
|
123
|
+
"bun-plugin-stx": "0.2.346",
|
|
124
124
|
"bunfig": "^0.15.19",
|
|
125
|
-
"stx-router": "0.2.
|
|
125
|
+
"stx-router": "0.2.346",
|
|
126
126
|
"ts-broadcasting": "^0.0.10",
|
|
127
127
|
"ts-images": "^0.2.22",
|
|
128
128
|
"ts-syntax-highlighter": "^0.2.1"
|