@stacksjs/stx 0.2.343 → 0.2.345
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/binding-manifest.d.ts +32 -0
- package/dist/binding-manifest.js +64 -0
- package/dist/{chunk-zr1x54bt.js → chunk-05zfez2g.js} +1 -1
- package/dist/{chunk-jagf7h9y.js → chunk-0k1mtwby.js} +1 -1
- package/dist/{chunk-jh6f1a9y.js → chunk-1c9453w0.js} +1 -1
- package/dist/chunk-1qyg1q6d.js +2 -0
- package/dist/chunk-1t4ece3v.js +2 -0
- package/dist/{chunk-7zxv2631.js → chunk-1vt1h19d.js} +1 -1
- package/dist/chunk-1vtdege3.js +2 -0
- package/dist/{chunk-stqm4brp.js → chunk-1vv9g6cj.js} +1 -1
- package/dist/{chunk-p3awq80d.js → chunk-1yh6pq6b.js} +1 -1
- package/dist/{chunk-57dxdvjh.js → chunk-223makqc.js} +1 -1
- package/dist/chunk-2fhk4e68.js +2 -0
- package/dist/{chunk-wyhb3nb0.js → chunk-34f8c48f.js} +1 -1
- package/dist/chunk-3zm4hgcf.js +2 -0
- package/dist/{chunk-xgw269cf.js → chunk-4spaszfn.js} +286 -286
- package/dist/chunk-57t402mn.js +2 -0
- package/dist/{chunk-wdaf98ya.js → chunk-59906baj.js} +1 -1
- package/dist/{chunk-z9hb80mk.js → chunk-64n10kpa.js} +1 -1
- package/dist/chunk-66tgkvqw.js +2 -0
- package/dist/{chunk-daxr6p6q.js → chunk-6fwp7gee.js} +1 -1
- package/dist/{chunk-1bfvdjpy.js → chunk-6h3r8v55.js} +1 -1
- package/dist/{chunk-safmgrq5.js → chunk-6wmjwbq9.js} +1 -1
- package/dist/{chunk-53sjbp3z.js → chunk-72x62kch.js} +2 -2
- package/dist/{chunk-amfq5rnz.js → chunk-72yrrggn.js} +2 -2
- package/dist/{chunk-2853ye06.js → chunk-77p1kjg2.js} +2 -2
- package/dist/chunk-7g5vk4c3.js +2 -0
- package/dist/{chunk-7mc1k1tq.js → chunk-7h9fajgs.js} +1 -1
- package/dist/{chunk-gvfgrve8.js → chunk-7m9qk7da.js} +1 -1
- package/dist/{chunk-3d3x7dwy.js → chunk-7qp3zphs.js} +1 -1
- package/dist/{chunk-grnmr3y1.js → chunk-86c461ca.js} +1 -1
- package/dist/chunk-86q2h34b.js +2 -0
- package/dist/{chunk-7r79j1hs.js → chunk-89mqnh67.js} +1 -1
- package/dist/{chunk-5hq25yky.js → chunk-8cc4vdkh.js} +1 -1
- package/dist/chunk-8rhjt6fh.js +2 -0
- package/dist/{chunk-45ydb29q.js → chunk-8v2k21n4.js} +1 -1
- package/dist/{chunk-aqxwwq6w.js → chunk-8y1ve8tc.js} +2 -2
- package/dist/{chunk-ag8gdk51.js → chunk-99b5tfxc.js} +1 -1
- package/dist/{chunk-4vd0rqfs.js → chunk-9jbssgem.js} +197 -88
- package/dist/{chunk-s60eccqk.js → chunk-9nrgjtah.js} +1 -1
- package/dist/{chunk-y5sxa2sq.js → chunk-9qtf2b1p.js} +1 -1
- package/dist/chunk-aapqf6bj.js +2 -0
- package/dist/{chunk-k8skvm0d.js → chunk-at622hg0.js} +1 -1
- package/dist/{chunk-1qtd4ex2.js → chunk-avwywzsj.js} +2 -2
- package/dist/{chunk-a0ajg9z5.js → chunk-b5hank5e.js} +1 -1
- package/dist/chunk-b5mnam29.js +2 -0
- package/dist/{chunk-4fafxr8d.js → chunk-bk1zb1xp.js} +1 -1
- package/dist/{chunk-hrdd26r4.js → chunk-bqdfbwdf.js} +1 -1
- package/dist/{chunk-c7qdnc5d.js → chunk-c30qnb6z.js} +1 -1
- package/dist/chunk-c4tf1vpy.js +2 -0
- package/dist/{chunk-g0dbtyk7.js → chunk-c8e2deyp.js} +1 -1
- package/dist/chunk-cypg8qwn.js +2 -0
- package/dist/{chunk-fbmjw0bh.js → chunk-d86q27j8.js} +1 -1
- package/dist/{chunk-dj5mqnp1.js → chunk-dgv43ccd.js} +1 -1
- package/dist/{chunk-em8cr7wy.js → chunk-dsztk2kp.js} +1 -1
- package/dist/{chunk-mwvxhv0r.js → chunk-dxkjvajv.js} +1 -1
- package/dist/{chunk-4pg6wbt6.js → chunk-e631svvs.js} +1 -1
- package/dist/chunk-e7gs18rc.js +2 -0
- package/dist/{chunk-h6y99nak.js → chunk-e7np0h2q.js} +1 -1
- package/dist/{chunk-0s3ry262.js → chunk-ejqpq0wc.js} +1 -1
- package/dist/chunk-ek2m0kkw.js +2 -0
- package/dist/chunk-eqzc88et.js +2 -0
- package/dist/chunk-erb294sv.js +2 -0
- package/dist/{chunk-36j9qset.js → chunk-esjcyxa9.js} +2 -2
- package/dist/{chunk-5azeswj2.js → chunk-evfr2zgg.js} +1 -1
- package/dist/{chunk-e53pwshq.js → chunk-fp868yhg.js} +1 -1
- package/dist/{chunk-5zemhhwe.js → chunk-gsc2vds7.js} +1 -1
- package/dist/{chunk-q6825wwz.js → chunk-gvemapw4.js} +1 -1
- package/dist/chunk-h1vax4wg.js +2 -0
- package/dist/chunk-hke0k33t.js +2 -0
- package/dist/{chunk-zcytk5w9.js → chunk-jekrtm2j.js} +1 -1
- package/dist/{chunk-pwhf5kte.js → chunk-jnbg3e4r.js} +1 -1
- package/dist/{chunk-brjfzbq9.js → chunk-kfkf9v2d.js} +1 -1
- package/dist/chunk-kq30wqp6.js +2 -0
- package/dist/{chunk-s7qbba8r.js → chunk-kqzpmwx2.js} +10 -10
- package/dist/{chunk-0dpgh7a6.js → chunk-kw9cgyfc.js} +1 -1
- package/dist/{chunk-0fp16c1x.js → chunk-m2j5skez.js} +1 -1
- package/dist/{chunk-vj3nx26v.js → chunk-mph46gkj.js} +1 -1
- package/dist/chunk-mr8ccsnm.js +2 -0
- package/dist/{chunk-1h1c2048.js → chunk-msywnv5n.js} +1 -1
- package/dist/{chunk-649dfqqz.js → chunk-n5657hm3.js} +1 -1
- package/dist/{chunk-t00ga194.js → chunk-njx93b4z.js} +1 -1
- package/dist/{chunk-m0xaw0qw.js → chunk-nm60wh6r.js} +1 -1
- package/dist/{chunk-8ah5mhst.js → chunk-nqz501eq.js} +2 -2
- package/dist/{chunk-hq3phk1a.js → chunk-nrt99ptw.js} +1 -1
- package/dist/{chunk-62vng8g8.js → chunk-pajk5680.js} +2 -2
- package/dist/{chunk-ey1tsk22.js → chunk-ppzz953j.js} +1 -1
- package/dist/{chunk-7yfk9393.js → chunk-qkdcbeaw.js} +1 -1
- package/dist/chunk-qr3zcm87.js +2 -0
- package/dist/chunk-r38xq7fp.js +33 -0
- package/dist/{chunk-tqw1yean.js → chunk-rwwfzkz4.js} +1 -1
- package/dist/{chunk-rns7wjy9.js → chunk-rzda6bd6.js} +1 -1
- package/dist/{chunk-rzg9pars.js → chunk-san1eq0r.js} +2 -2
- package/dist/{chunk-eh3meyd3.js → chunk-tc4pj651.js} +2 -2
- package/dist/{chunk-6g8rvnhc.js → chunk-v6e35j4g.js} +1 -1
- package/dist/{chunk-wnmegbw0.js → chunk-v7aa7v85.js} +1 -1
- package/dist/{chunk-e6rxvz3p.js → chunk-vhg91hnw.js} +1 -1
- package/dist/{chunk-k3dtvay1.js → chunk-vhta1be7.js} +1 -1
- package/dist/{chunk-tz68qv47.js → chunk-w5j9tbsk.js} +1 -1
- package/dist/{chunk-ec18ftcg.js → chunk-wj21f1e0.js} +1 -1
- package/dist/{chunk-12qteqk8.js → chunk-ws0282jr.js} +1 -1
- package/dist/chunk-x054qzma.js +2 -0
- package/dist/{chunk-q9ckfwhh.js → chunk-xj6bcwqa.js} +1 -1
- package/dist/chunk-xq0e2y4x.js +2 -0
- package/dist/chunk-xrjx7b2v.js +2 -0
- package/dist/{chunk-ay336sqb.js → chunk-xvh1k1a4.js} +1 -1
- package/dist/{chunk-vaggjvsm.js → chunk-y2f41kaq.js} +1 -1
- package/dist/{chunk-1zav2sf1.js → chunk-y6xzr30x.js} +1 -1
- package/dist/chunk-ybx8n794.js +2 -0
- package/dist/{chunk-yefnrr5z.js → chunk-yca761bm.js} +1 -1
- package/dist/{chunk-kgbz86sa.js → chunk-yg5r7bnm.js} +2 -2
- package/dist/{chunk-kbah2k8e.js → chunk-z8wb7kbj.js} +2 -2
- package/dist/chunk-zkxnarrh.js +2 -0
- package/dist/{chunk-hzbty7hz.js → chunk-zmazqcb8.js} +1 -1
- package/dist/chunk-zp14ksx1.js +2 -0
- package/dist/chunk-zwr4bn6a.js +2 -0
- package/dist/cli.js +14 -14
- package/dist/craft-entry.js +1 -1
- package/dist/craft.js +1 -1
- package/dist/database.js +1 -1
- package/dist/expressions.d.ts +1 -1
- package/dist/expressions.js +15 -3
- package/dist/includes.js +2 -2
- package/dist/pwa.js +2 -2
- package/dist/runtime-globals.d.ts +22 -0
- package/dist/runtime-globals.js +46 -0
- package/dist/signals.js +193 -84
- package/dist/slots.js +3 -3
- package/dist/ssg.js +2 -2
- package/dist/theme-tokens.d.ts +59 -0
- package/dist/theme-tokens.js +83 -17
- package/dist/ts-css-config.js +4 -2
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +77 -12
- package/dist/variable-extractor.d.ts +1 -1
- package/dist/variable-extractor.js +23 -3
- package/dist/visual-testing.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-160g7ynw.js +0 -2
- package/dist/chunk-16hr5y08.js +0 -2
- package/dist/chunk-3h97y3n3.js +0 -2
- package/dist/chunk-3j915h2d.js +0 -2
- package/dist/chunk-4hkg6kx4.js +0 -2
- package/dist/chunk-57494khk.js +0 -2
- package/dist/chunk-5xavmr4t.js +0 -2
- package/dist/chunk-6rsfkms1.js +0 -2
- package/dist/chunk-6xs80tka.js +0 -32
- package/dist/chunk-905j49fe.js +0 -2
- package/dist/chunk-9czj483k.js +0 -2
- package/dist/chunk-9kv0qavn.js +0 -2
- package/dist/chunk-bcz8yp2g.js +0 -2
- package/dist/chunk-bxefsc7k.js +0 -2
- package/dist/chunk-c4kv3r8t.js +0 -2
- package/dist/chunk-fytemc96.js +0 -2
- package/dist/chunk-g7gc0ten.js +0 -2
- package/dist/chunk-gqsxxd81.js +0 -2
- package/dist/chunk-gx9z0wmm.js +0 -2
- package/dist/chunk-jnxzzzm4.js +0 -2
- package/dist/chunk-jy6jwxhs.js +0 -2
- package/dist/chunk-khqn40gv.js +0 -2
- package/dist/chunk-mhbzrh5y.js +0 -2
- package/dist/chunk-p8anntjb.js +0 -2
- package/dist/chunk-pwe51myj.js +0 -2
- package/dist/chunk-rqqdvnp5.js +0 -2
- package/dist/chunk-w1mbrq1g.js +0 -2
- package/dist/chunk-w84qe2m6.js +0 -2
- package/dist/chunk-wjm7hv5e.js +0 -2
- package/dist/chunk-yr7s02f7.js +0 -2
- package/dist/chunk-zq3tm2c2.js +0 -2
package/dist/slots.js
CHANGED
|
@@ -320,9 +320,9 @@ export async function processSlots(template, parsedSlots, context) {
|
|
|
320
320
|
}
|
|
321
321
|
return await renderSlot(slotDef, props, defaultFallback, context);
|
|
322
322
|
});
|
|
323
|
-
const defaultSlotRegex = /<slot\s*(?:\/>|>([\s\S]*?)<\/slot>)/gi;
|
|
324
|
-
result = result.replace(defaultSlotRegex, (match, defaultContent) => {
|
|
325
|
-
if (
|
|
323
|
+
const defaultSlotRegex = /<slot\b((?:"[^"]*"|'[^']*'|[^>"'])*?)\s*(?:\/>|>([\s\S]*?)<\/slot>)/gi;
|
|
324
|
+
result = result.replace(defaultSlotRegex, (match, attrs, defaultContent) => {
|
|
325
|
+
if (/\bname\s*=/.test(attrs || ""))
|
|
326
326
|
return match;
|
|
327
327
|
const fallback = defaultContent?.trim() || "";
|
|
328
328
|
return parsedSlots.default || fallback;
|
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-
|
|
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-223makqc.js";import"./chunk-77p1kjg2.js";import"./chunk-fvsefztj.js";import{Jp as P,Sm as Oq,io as l,lo as Hq,sr as n}from"./chunk-4spaszfn.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-r38xq7fp.js";import{nt as d}from"./chunk-y2f41kaq.js";import"./chunk-xj6bcwqa.js";import"./chunk-z8wb7kbj.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-jnbg3e4r.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-jnbg3e4r.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.d.ts
CHANGED
|
@@ -29,6 +29,23 @@
|
|
|
29
29
|
* pairing was the dominant one, and the defaults stay in step with the palette
|
|
30
30
|
* because they are resolved from it rather than copied.
|
|
31
31
|
*
|
|
32
|
+
* ## Why `neutral` and not `gray`
|
|
33
|
+
*
|
|
34
|
+
* The STEP each neutral role names was measured from the library; the FAMILY
|
|
35
|
+
* is a house decision. `neutral` is achromatic (chroma 0 at every step) while
|
|
36
|
+
* `gray` carries a blue tint (chroma 0.027–0.034 through the mid range), and
|
|
37
|
+
* the two agree on lightness to within about 1% at every step. So the choice
|
|
38
|
+
* is a pure saturation one and changes no contrast ratio.
|
|
39
|
+
*
|
|
40
|
+
* These were gray-backed, which left the library mixing both: 103 `neutral-*`
|
|
41
|
+
* uses in components against gray-backed roles. Everything is `neutral` now -
|
|
42
|
+
* the roles, and the 35 literal shades that could not move onto a role - so
|
|
43
|
+
* there is one neutral in the library rather than two that differ only by a
|
|
44
|
+
* tint nobody chose (stacksjs/stx#1993).
|
|
45
|
+
*
|
|
46
|
+
* Flipping this back is a one-line edit per role, and the rest of the
|
|
47
|
+
* vocabulary is unaffected: the status hues are their own families.
|
|
48
|
+
*
|
|
32
49
|
* ## How dark mode works
|
|
33
50
|
*
|
|
34
51
|
* Each token resolves to `var(--stx-<name>, <light value>)`, and
|
|
@@ -85,4 +102,46 @@ export declare function semanticColors(palette: Palette): Record<string, string>
|
|
|
85
102
|
export declare function semanticTokenCSS(palette: Palette): string;
|
|
86
103
|
/** Every variable a role token reads, for documentation and tooling. */
|
|
87
104
|
export declare function semanticTokenNames(): string[];
|
|
105
|
+
/**
|
|
106
|
+
* Shape roles — the radius a thing has because of what it IS.
|
|
107
|
+
*
|
|
108
|
+
* Colour was only half of what made the library unadoptable. An app whose
|
|
109
|
+
* buttons are pills got `rounded-md`, and `className` is no escape hatch for a
|
|
110
|
+
* radius for exactly the reason it was not one for a colour: `rounded-md` and
|
|
111
|
+
* `rounded-full` are single-class selectors of equal specificity, so the winner
|
|
112
|
+
* is whichever lands later in the generated stylesheet, which a call site
|
|
113
|
+
* cannot control (stacksjs/stx#1993).
|
|
114
|
+
*
|
|
115
|
+
* Three roles, from what the library actually uses: `rounded-md` on controls
|
|
116
|
+
* (54 uses), `rounded-lg` on panels (24), and `rounded-full` where something is
|
|
117
|
+
* genuinely a pill (34, of which the circular ones - avatars, dots, spinners -
|
|
118
|
+
* keep `rounded-full`, because a circle is not a theming decision).
|
|
119
|
+
*
|
|
120
|
+
* So `--stx-radius-control: 9999px` turns every button, input and select in the
|
|
121
|
+
* library into a pill, and nothing else moves.
|
|
122
|
+
*/
|
|
123
|
+
export declare const SHAPE_TOKENS: Record<string, {
|
|
124
|
+
value: string;
|
|
125
|
+
description: string;
|
|
126
|
+
}>;
|
|
127
|
+
/** The CSS custom property that backs a shape role. */
|
|
128
|
+
export declare function shapeVariable(name: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* The `theme.borderRadius` entries to merge in.
|
|
131
|
+
*
|
|
132
|
+
* Same shape as {@link semanticColors}: each is `var(--stx-radius-<name>,
|
|
133
|
+
* <stock value>)`, so `rounded-control` is an ordinary utility - directional
|
|
134
|
+
* variants like `rounded-t-control` included - and an app moves it by setting
|
|
135
|
+
* the variable.
|
|
136
|
+
*/
|
|
137
|
+
export declare function shapeRadii(): Record<string, string>;
|
|
138
|
+
/**
|
|
139
|
+
* The `:root` block for the shape roles.
|
|
140
|
+
*
|
|
141
|
+
* No `.dark` counterpart: a radius does not change with the colour scheme, and
|
|
142
|
+
* emitting an empty dark block would invite someone to fill it in.
|
|
143
|
+
*/
|
|
144
|
+
export declare function shapeTokenCSS(): string;
|
|
145
|
+
/** Every variable a shape role reads, for documentation and tooling. */
|
|
146
|
+
export declare function shapeTokenNames(): string[];
|
|
88
147
|
export {};
|
package/dist/theme-tokens.js
CHANGED
|
@@ -1,23 +1,62 @@
|
|
|
1
1
|
export const SEMANTIC_TOKENS = {
|
|
2
|
-
fg: { light: "
|
|
3
|
-
"fg-strong": { light: "
|
|
4
|
-
"fg-muted": { light: "
|
|
5
|
-
"fg-soft": { light: "
|
|
6
|
-
"fg-subtle": { light: "
|
|
7
|
-
surface: { light: "
|
|
8
|
-
"surface-raised": { light: "
|
|
9
|
-
"surface-sunken": { light: "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
fg: { light: "neutral-900", dark: "neutral-100", description: "Primary text" },
|
|
3
|
+
"fg-strong": { light: "neutral-700", dark: "neutral-300", description: "Labels, secondary headings" },
|
|
4
|
+
"fg-muted": { light: "neutral-600", dark: "neutral-400", description: "Supporting text" },
|
|
5
|
+
"fg-soft": { light: "neutral-500", dark: "neutral-400", description: "De-emphasised text" },
|
|
6
|
+
"fg-subtle": { light: "neutral-400", dark: "neutral-500", description: "Placeholders, disabled text" },
|
|
7
|
+
surface: { light: "neutral-50", dark: "neutral-800", description: "Page and panel background" },
|
|
8
|
+
"surface-raised": { light: "neutral-100", dark: "neutral-700", description: "Cards, popovers" },
|
|
9
|
+
"surface-sunken": { light: "neutral-200", dark: "neutral-700", description: "Wells, track backgrounds" },
|
|
10
|
+
panel: { light: "white", dark: "neutral-800", description: "Card, menu, dialog surface" },
|
|
11
|
+
field: { light: "white", dark: "neutral-700", description: "Form control surface" },
|
|
12
|
+
"surface-hover": { light: "neutral-100", dark: "neutral-700", description: "Row or item highlight on a page or panel" },
|
|
13
|
+
"surface-raised-hover": { light: "neutral-200", dark: "neutral-600", description: "Raised surface, hovered" },
|
|
14
|
+
"surface-sunken-hover": { light: "neutral-300", dark: "neutral-600", description: "Sunken surface, hovered" },
|
|
15
|
+
"field-hover": { light: "neutral-50", dark: "neutral-600", description: "Form control surface, hovered" },
|
|
16
|
+
inverse: { light: "neutral-900", dark: "neutral-700", description: "Tooltip bubble, inverted surface" },
|
|
17
|
+
"inverse-ink": { light: "white", dark: "white", description: "Text on an inverted surface" },
|
|
18
|
+
line: { light: "neutral-200", dark: "neutral-700", description: "Default border, divider" },
|
|
19
|
+
"line-strong": { light: "neutral-300", dark: "neutral-600", description: "Input border, focus ring track" },
|
|
20
|
+
accent: { light: "blue-600", dark: "blue-400", description: "Primary action, selected state" },
|
|
21
|
+
info: { light: "cyan-600", dark: "cyan-400", description: "Informational emphasis, links" },
|
|
14
22
|
danger: { light: "red-600", dark: "red-400", description: "Errors, destructive actions" },
|
|
15
23
|
success: { light: "green-600", dark: "green-400", description: "Confirmation" },
|
|
16
|
-
warning: { light: "yellow-
|
|
17
|
-
"accent-solid": { light: "
|
|
18
|
-
"info-solid": { light: "
|
|
19
|
-
"danger-solid": { light: "red-
|
|
20
|
-
"success-solid": { light: "green-
|
|
24
|
+
warning: { light: "yellow-600", dark: "yellow-400", description: "Caution" },
|
|
25
|
+
"accent-solid": { light: "blue-500", dark: "blue-600", description: "Primary button fill" },
|
|
26
|
+
"info-solid": { light: "cyan-500", dark: "cyan-600", description: "Informational fill" },
|
|
27
|
+
"danger-solid": { light: "red-500", dark: "red-600", description: "Destructive button fill" },
|
|
28
|
+
"success-solid": { light: "green-500", dark: "green-600", description: "Confirmation fill" },
|
|
29
|
+
"warning-solid": { light: "yellow-500", dark: "yellow-600", description: "Caution fill" },
|
|
30
|
+
"accent-solid-hover": { light: "blue-600", dark: "blue-700", description: "Primary button fill, hovered" },
|
|
31
|
+
"info-solid-hover": { light: "cyan-600", dark: "cyan-700", description: "Informational fill, hovered" },
|
|
32
|
+
"danger-solid-hover": { light: "red-600", dark: "red-700", description: "Destructive fill, hovered" },
|
|
33
|
+
"success-solid-hover": { light: "green-600", dark: "green-700", description: "Confirmation fill, hovered" },
|
|
34
|
+
"warning-solid-hover": { light: "yellow-600", dark: "yellow-700", description: "Caution fill, hovered" },
|
|
35
|
+
"accent-ink": { light: "white", dark: "white", description: "Text on a primary fill" },
|
|
36
|
+
"info-ink": { light: "white", dark: "white", description: "Text on an informational fill" },
|
|
37
|
+
"danger-ink": { light: "white", dark: "white", description: "Text on a destructive fill" },
|
|
38
|
+
"success-ink": { light: "white", dark: "white", description: "Text on a confirmation fill" },
|
|
39
|
+
"warning-ink": { light: "neutral-900", dark: "neutral-900", description: "Text on a caution fill" },
|
|
40
|
+
"accent-soft": { light: "blue-100", dark: "blue-900", description: "Tinted primary fill" },
|
|
41
|
+
"accent-soft-ink": { light: "blue-800", dark: "blue-200", description: "Text on a tinted primary fill" },
|
|
42
|
+
"info-soft": { light: "cyan-100", dark: "cyan-900", description: "Tinted informational fill" },
|
|
43
|
+
"info-soft-ink": { light: "cyan-800", dark: "cyan-200", description: "Text on a tinted informational fill" },
|
|
44
|
+
"danger-soft": { light: "red-100", dark: "red-900", description: "Tinted destructive fill" },
|
|
45
|
+
"danger-soft-ink": { light: "red-800", dark: "red-200", description: "Text on a tinted destructive fill" },
|
|
46
|
+
"success-soft": { light: "green-100", dark: "green-900", description: "Tinted confirmation fill" },
|
|
47
|
+
"success-soft-ink": { light: "green-800", dark: "green-200", description: "Text on a tinted confirmation fill" },
|
|
48
|
+
"warning-soft": { light: "yellow-100", dark: "yellow-900", description: "Tinted caution fill" },
|
|
49
|
+
"warning-soft-ink": { light: "yellow-800", dark: "yellow-200", description: "Text on a tinted caution fill" },
|
|
50
|
+
secondary: { light: "purple-600", dark: "purple-400", description: "Secondary emphasis" },
|
|
51
|
+
"secondary-solid": { light: "purple-500", dark: "purple-600", description: "Secondary fill" },
|
|
52
|
+
"secondary-solid-hover": { light: "purple-600", dark: "purple-700", description: "Secondary fill, hovered" },
|
|
53
|
+
"secondary-ink": { light: "white", dark: "white", description: "Text on a secondary fill" },
|
|
54
|
+
"secondary-soft": { light: "purple-100", dark: "purple-900", description: "Tinted secondary fill" },
|
|
55
|
+
"secondary-soft-ink": { light: "purple-800", dark: "purple-200", description: "Text on a tinted secondary fill" },
|
|
56
|
+
"danger-fg": { light: "red-900", dark: "red-300", description: "Text in a field with an error" },
|
|
57
|
+
"danger-fg-subtle": { light: "red-300", dark: "red-500", description: "Placeholder in a field with an error" },
|
|
58
|
+
"danger-line": { light: "red-300", dark: "red-600", description: "Border of a field with an error" },
|
|
59
|
+
"danger-focus": { light: "red-500", dark: "red-400", description: "Focus ring of a field with an error" }
|
|
21
60
|
};
|
|
22
61
|
export function tokenVariable(name) {
|
|
23
62
|
return `--stx-${name}`;
|
|
@@ -69,3 +108,30 @@ export function semanticTokenCSS(palette) {
|
|
|
69
108
|
export function semanticTokenNames() {
|
|
70
109
|
return Object.keys(SEMANTIC_TOKENS).map(tokenVariable);
|
|
71
110
|
}
|
|
111
|
+
export const SHAPE_TOKENS = {
|
|
112
|
+
control: { value: "0.375rem", description: "Buttons, inputs, selects \u2014 rounded-md" },
|
|
113
|
+
panel: { value: "0.5rem", description: "Cards, dialogs, menus \u2014 rounded-lg" },
|
|
114
|
+
pill: { value: "9999px", description: "Chips and badges, which are pill-shaped by intent" }
|
|
115
|
+
};
|
|
116
|
+
export function shapeVariable(name) {
|
|
117
|
+
return `--stx-radius-${name}`;
|
|
118
|
+
}
|
|
119
|
+
export function shapeRadii() {
|
|
120
|
+
const radii = {};
|
|
121
|
+
for (const [name, token] of Object.entries(SHAPE_TOKENS))
|
|
122
|
+
radii[name] = `var(${shapeVariable(name)}, ${token.value})`;
|
|
123
|
+
return radii;
|
|
124
|
+
}
|
|
125
|
+
export function shapeTokenCSS() {
|
|
126
|
+
return [
|
|
127
|
+
"/* stx shape tokens \u2014 a radius by what the thing is. */",
|
|
128
|
+
":root {",
|
|
129
|
+
...Object.entries(SHAPE_TOKENS).map(([name, token]) => ` ${shapeVariable(name)}: ${token.value};`),
|
|
130
|
+
"}",
|
|
131
|
+
""
|
|
132
|
+
].join(`
|
|
133
|
+
`);
|
|
134
|
+
}
|
|
135
|
+
export function shapeTokenNames() {
|
|
136
|
+
return Object.keys(SHAPE_TOKENS).map(shapeVariable);
|
|
137
|
+
}
|
package/dist/ts-css-config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { semanticColors, semanticTokenCSS } from "./theme-tokens.js";
|
|
1
|
+
import { semanticColors, semanticTokenCSS, shapeRadii, shapeTokenCSS } from "./theme-tokens.js";
|
|
2
2
|
function isPlainObject(value) {
|
|
3
3
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
4
|
}
|
|
@@ -11,6 +11,8 @@ export function deepMergeThemes(target, source) {
|
|
|
11
11
|
export function mergeCssConfig(base = {}, user = {}) {
|
|
12
12
|
const baseTheme = base.theme || {}, userTheme = user.theme || {}, { extend: userExtend, ...userThemeKeys } = userTheme, { extend: baseExtend, ...baseThemeKeys } = baseTheme, basePalette = baseThemeKeys.colors || {};
|
|
13
13
|
baseThemeKeys.colors = { ...basePalette, ...semanticColors(basePalette) };
|
|
14
|
+
const baseRadii = baseThemeKeys.borderRadius || {};
|
|
15
|
+
baseThemeKeys.borderRadius = { ...baseRadii, ...shapeRadii() };
|
|
14
16
|
const theme = deepMergeThemes(baseThemeKeys, userThemeKeys), extend = deepMergeThemes(baseExtend || {}, userExtend || {});
|
|
15
17
|
if (Object.keys(extend).length > 0)
|
|
16
18
|
theme.extend = extend;
|
|
@@ -39,6 +41,6 @@ export function mergeCssConfig(base = {}, user = {}) {
|
|
|
39
41
|
shortcuts,
|
|
40
42
|
includePreflight: user.preflight !== !1,
|
|
41
43
|
minify: user.minify === !0,
|
|
42
|
-
tokenCSS: semanticTokenCSS(basePalette)
|
|
44
|
+
tokenCSS: semanticTokenCSS(basePalette) + shapeTokenCSS()
|
|
43
45
|
};
|
|
44
46
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -28,6 +28,16 @@ export declare function getSharedTranspiler(options: ConstructorParameters<typeo
|
|
|
28
28
|
* Transpile TypeScript code to JavaScript using Bun (sync version)
|
|
29
29
|
*/
|
|
30
30
|
export declare function transpileTypeScript(code: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Put `attrs` on the markup's own root element, or return null to say a
|
|
33
|
+
* wrapper is fine.
|
|
34
|
+
*
|
|
35
|
+
* Returns null unless the markup is a single element of a kind whose parent
|
|
36
|
+
* would reject a wrapper: leading comments and whitespace are skipped, the tag
|
|
37
|
+
* name is checked against the set above, and the element has to be the only one
|
|
38
|
+
* of its kind at the top level, closing at the end.
|
|
39
|
+
*/
|
|
40
|
+
export declare function scopeOnRootElement(html: string, attrs: string): string | null;
|
|
31
41
|
/**
|
|
32
42
|
* Does a project-authored component file exist for `componentPath`?
|
|
33
43
|
*
|
package/dist/utils.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
replayComponentClientFactories,
|
|
9
9
|
snapshotComponentClientFactoryCounts
|
|
10
10
|
} from "./component-client-factories.js";
|
|
11
|
-
import { interpolateScriptExpressions, processExpressions, usesSignalsInScript } from "./expressions.js";
|
|
11
|
+
import { evaluateExpression, interpolateScriptExpressions, processExpressions, usesSignalsInScript } from "./expressions.js";
|
|
12
12
|
import { COMPONENT_SCOPE_LOCAL_GLOBALS, buildRuntimeGlobalsDestructure } from "./runtime-globals.js";
|
|
13
13
|
import { contentKey, depsUnchanged, renderMemo, snapshotDeps } from "./render-memo.js";
|
|
14
14
|
import { transformStoreImports } from "./store-imports.js";
|
|
@@ -400,6 +400,36 @@ function applyDestructuredPropDefaults(componentContent, ctx) {
|
|
|
400
400
|
}
|
|
401
401
|
} catch {}
|
|
402
402
|
}
|
|
403
|
+
const WRAPPER_HOISTED_OUT_BY_PARSER = new Set([
|
|
404
|
+
"tr",
|
|
405
|
+
"td",
|
|
406
|
+
"th",
|
|
407
|
+
"thead",
|
|
408
|
+
"tbody",
|
|
409
|
+
"tfoot",
|
|
410
|
+
"caption",
|
|
411
|
+
"colgroup",
|
|
412
|
+
"col",
|
|
413
|
+
"option",
|
|
414
|
+
"optgroup",
|
|
415
|
+
"li",
|
|
416
|
+
"dt",
|
|
417
|
+
"dd"
|
|
418
|
+
]);
|
|
419
|
+
export function scopeOnRootElement(html, attrs) {
|
|
420
|
+
const opening = html.match(/^(\s*(?:(?:<!--[\s\S]*?-->|\x00STX_HTML_COMMENT_\d+\x00)\s*)*)<([a-zA-Z][a-zA-Z0-9-]*)/s);
|
|
421
|
+
if (!opening)
|
|
422
|
+
return null;
|
|
423
|
+
const tag = opening[2].toLowerCase();
|
|
424
|
+
if (!WRAPPER_HOISTED_OUT_BY_PARSER.has(tag))
|
|
425
|
+
return null;
|
|
426
|
+
if ((html.match(new RegExp(`<${tag}(?=[\\s/>])`, "gi")) ?? []).length !== 1)
|
|
427
|
+
return null;
|
|
428
|
+
if (!new RegExp(`</${tag}>\\s*$`, "i").test(html))
|
|
429
|
+
return null;
|
|
430
|
+
const insertAt = opening[0].length;
|
|
431
|
+
return html.slice(0, insertAt) + attrs + html.slice(insertAt);
|
|
432
|
+
}
|
|
403
433
|
export async function userComponentFileExists(componentPath, componentsDir, parentContext, parentFilePath, options) {
|
|
404
434
|
const baseName = componentPath.endsWith(".stx") ? componentPath.slice(0, -4) : componentPath, kebabToPascal = (str) => str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(""), pascalToKebab = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), importedComponents = parentContext.__importedComponents;
|
|
405
435
|
if (importedComponents) {
|
|
@@ -459,6 +489,42 @@ export function slotContentHasExpressions(slotContent) {
|
|
|
459
489
|
const withoutScripts = slotContent.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<style[\s\S]*?<\/style>/gi, "");
|
|
460
490
|
return /\{\{[\s\S]*?\}\}|\{!![\s\S]*?!!\}/.test(withoutScripts);
|
|
461
491
|
}
|
|
492
|
+
function interpolateStyleExpressions(css, context, filePath) {
|
|
493
|
+
if (!css.includes("{{") && !css.includes("{!!"))
|
|
494
|
+
return css;
|
|
495
|
+
const insert = (expression, raw) => {
|
|
496
|
+
let value;
|
|
497
|
+
try {
|
|
498
|
+
value = evaluateExpression(expression, context);
|
|
499
|
+
} catch {
|
|
500
|
+
return raw;
|
|
501
|
+
}
|
|
502
|
+
if (value === void 0 || value === null)
|
|
503
|
+
return "";
|
|
504
|
+
const text = String(value);
|
|
505
|
+
if (/<\/style/i.test(text)) {
|
|
506
|
+
console.warn(`[stx] a <style> expression in ${filePath ?? "<unknown>"} evaluated to CSS containing a closing style tag, which would end the element early, so it was dropped rather than emitted.`);
|
|
507
|
+
return "";
|
|
508
|
+
}
|
|
509
|
+
return text;
|
|
510
|
+
};
|
|
511
|
+
return css.replace(/\{!!([\s\S]*?)!!\}/g, (raw, expression) => insert(expression, raw)).replace(/\{\{([\s\S]*?)\}\}/g, (raw, expression) => insert(expression, raw));
|
|
512
|
+
}
|
|
513
|
+
const reportedUnresolvedComponents = new Set;
|
|
514
|
+
function reportUnresolvedComponent(componentPath, parentFilePath, triedPaths, cause) {
|
|
515
|
+
const key = `${componentPath}\x00${parentFilePath}\x00${cause ?? ""}`;
|
|
516
|
+
if (!process.env.STX_DEBUG && reportedUnresolvedComponents.has(key))
|
|
517
|
+
return;
|
|
518
|
+
reportedUnresolvedComponents.add(key);
|
|
519
|
+
const where = parentFilePath ? ` used in ${parentFilePath}` : "", why = cause ? ` Cause: ${cause}.` : "", searched = triedPaths.length > 0 ? `
|
|
520
|
+
searched:
|
|
521
|
+
${triedPaths.map((tried) => ` - ${tried}`).join(`
|
|
522
|
+
`)}` : "";
|
|
523
|
+
console.error(`[stx] component <${componentPath}> could not be resolved${where}, so it rendered as nothing.${why}${searched}`);
|
|
524
|
+
}
|
|
525
|
+
function unresolvedComponentMarkup(componentPath) {
|
|
526
|
+
return `<!-- stx: component "${componentPath.replace(/--+/g, "-")}" could not be resolved; see the server log -->`;
|
|
527
|
+
}
|
|
462
528
|
export function componentClientSignalNames(scripts) {
|
|
463
529
|
const names = new Set, declaration = /\b(?:const|let|var)\s+([a-zA-Z_$][\w$]*)\s*=\s*(?:state|derived|computed|ref|reactive|signal|useModel|useReactiveProp|useLocalStorage|useSessionStorage|useCookie|useDebouncedValue)\s*(?:<[^>]*>)?\s*\(/g;
|
|
464
530
|
for (const script of scripts) {
|
|
@@ -610,11 +676,8 @@ export async function renderComponentWithSlot(componentPath, props, slotContent,
|
|
|
610
676
|
componentResolutionCache.set(resolutionCacheKey, componentFilePath);
|
|
611
677
|
}
|
|
612
678
|
if (!componentFilePath || !await fileExists(componentFilePath)) {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
${triedPaths.map((p) => ` - ${p}`).join(`
|
|
616
|
-
`)}` : "";
|
|
617
|
-
return `[Error loading component: ENOENT: no such file or directory, open '${componentPath}']${searchInfo}`;
|
|
679
|
+
reportUnresolvedComponent(componentPath, parentFilePath, triedPaths);
|
|
680
|
+
return unresolvedComponentMarkup(componentPath);
|
|
618
681
|
}
|
|
619
682
|
dependencies.add(componentFilePath);
|
|
620
683
|
let componentContent;
|
|
@@ -625,7 +688,9 @@ ${triedPaths.map((p) => ` - ${p}`).join(`
|
|
|
625
688
|
componentContent = await Bun.file(componentFilePath).text();
|
|
626
689
|
componentsCache.set(componentFilePath, componentContent);
|
|
627
690
|
} catch (error) {
|
|
628
|
-
|
|
691
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
692
|
+
reportUnresolvedComponent(componentPath, parentFilePath, [componentFilePath], message);
|
|
693
|
+
return unresolvedComponentMarkup(componentPath);
|
|
629
694
|
}
|
|
630
695
|
const internalKeysToPreserve = new Set([
|
|
631
696
|
"__originalFilePath",
|
|
@@ -727,16 +792,16 @@ ${triedPaths.map((p) => ` - ${p}`).join(`
|
|
|
727
792
|
let cleanContent = content.replace(/^\s*const\s*\{[^}]+\}\s*=\s*window\.stx\s*;?\s*\n?/gm, "");
|
|
728
793
|
const hasMustache = cleanContent.includes("{{") && cleanContent.includes("}}"), hasRawMarker = cleanContent.includes("{!!") && cleanContent.includes("!!}");
|
|
729
794
|
if (hasMustache || hasRawMarker)
|
|
730
|
-
cleanContent = interpolateScriptExpressions(cleanContent, componentContext);
|
|
795
|
+
cleanContent = interpolateScriptExpressions(cleanContent, componentContext, componentFilePath);
|
|
731
796
|
const cleanAttrs = attrs.replace(/\s*\bts\b/g, "").replace(/\s*\blang\s*=\s*["']?(ts|typescript)["']?/gi, "");
|
|
732
797
|
clientScripts.push(`<script${cleanAttrs}>${cleanContent}</script>`);
|
|
733
798
|
}
|
|
734
799
|
}
|
|
735
|
-
const styleMatch = componentContent.match(/<style\b([^>]*)>([\s\S]*?)<\/style>/i), styleAttrs = styleMatch ? styleMatch[1] : "", styleContent = styleMatch ? styleMatch[2] : "";
|
|
800
|
+
const styleMatch = stashScriptElements(componentContent).output.match(/<style\b([^>]*)>([\s\S]*?)<\/style>/i), styleAttrs = styleMatch ? styleMatch[1] : "", styleContent = styleMatch ? styleMatch[2] : "";
|
|
736
801
|
let preservedStyle = "";
|
|
737
802
|
const hasScopedStyle = styleAttrs && /\bscoped\b/i.test(styleAttrs);
|
|
738
803
|
if (styleMatch)
|
|
739
|
-
preservedStyle = `<style${styleAttrs}>${styleContent}</style>`;
|
|
804
|
+
preservedStyle = `<style${styleAttrs}>${interpolateStyleExpressions(styleContent, componentContext, componentFilePath)}</style>`;
|
|
740
805
|
let templateContent = workingContent;
|
|
741
806
|
templateContent = templateContent.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
742
807
|
if (styleMatch)
|
|
@@ -788,8 +853,8 @@ ${triedPaths.map((p) => ` - ${p}`).join(`
|
|
|
788
853
|
try {
|
|
789
854
|
propsJson = ` data-stx-props="${escapeAttr(JSON.stringify(props))}"`;
|
|
790
855
|
} catch {}
|
|
791
|
-
const hydrateJson = hydrateTrigger ? ` stx-hydrate="${escapeAttr(hydrateTrigger)}"` : ""
|
|
792
|
-
output = `<div
|
|
856
|
+
const hydrateJson = hydrateTrigger ? ` stx-hydrate="${escapeAttr(hydrateTrigger)}"` : "", scopeAttrs = ` data-stx-scope="${scopeId}"${propsJson}${hydrateJson}`;
|
|
857
|
+
output = scopeOnRootElement(result, scopeAttrs) ?? `<div${scopeAttrs}>${result}</div>`;
|
|
793
858
|
const scopedScripts = await Promise.all(clientScripts.map(async (script) => {
|
|
794
859
|
const scriptMatch = script.match(/<script([^>]*)>([\s\S]*)<\/script>/i);
|
|
795
860
|
if (!scriptMatch)
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* generated `await import('stx')` rejected and the shadowing binding was never
|
|
20
20
|
* created. The failure needed a real install to appear.
|
|
21
21
|
*/
|
|
22
|
-
export declare const STX_ENGINE_BINDING_NAMES: readonly ['module', 'exports', 'require', 'props', '$props', 'defineProps', 'withDefaults', 'defineClientPayload', 'useServerData', 'useRuntimeConfig', 'useServerRuntimeConfig', 'state', 'derived', 'effect', 'batch', 'onMount', 'onDestroy', 'definePageMeta', 'useRoute', 'useRouter', 'useHead', 'useSeoMeta', 'setResponseStatus', 'setResponseHeader', 'notFound', 'ref', 'reactive', 'computed', 'watch', 'onMounted', 'onUnmounted', 'nextTick', 'defineEmits', 'defineExpose', 'defineSlots', 'provide', 'inject', 'useColorMode', 'useDark', 'useMediaQuery', 'useScrollLock', 'usePreferredDark', 'usePreferredLight', 'usePreferredReducedMotion', 'usePreferredContrast', 'window', 'document', 'console', 'confirm', 'alert', 'fetch', 'params'];
|
|
22
|
+
export declare const STX_ENGINE_BINDING_NAMES: readonly ['module', 'exports', 'require', 'props', '$props', '$bool', 'defineProps', 'withDefaults', 'defineClientPayload', 'useServerData', 'useRuntimeConfig', 'useServerRuntimeConfig', 'state', 'derived', 'effect', 'batch', 'onMount', 'onDestroy', 'definePageMeta', 'useRoute', 'useRouter', 'useHead', 'useSeoMeta', 'setResponseStatus', 'setResponseHeader', 'notFound', 'ref', 'reactive', 'computed', 'watch', 'onMounted', 'onUnmounted', 'nextTick', 'defineEmits', 'defineExpose', 'defineSlots', 'provide', 'inject', 'useColorMode', 'useDark', 'useMediaQuery', 'useScrollLock', 'usePreferredDark', 'usePreferredLight', 'usePreferredReducedMotion', 'usePreferredContrast', 'window', 'document', 'console', 'confirm', 'alert', 'fetch', 'params'];
|
|
23
23
|
/**
|
|
24
24
|
* Strip TypeScript-specific syntax to make it executable as JavaScript
|
|
25
25
|
*
|
|
@@ -10,6 +10,7 @@ export const STX_ENGINE_BINDING_NAMES = [
|
|
|
10
10
|
"require",
|
|
11
11
|
"props",
|
|
12
12
|
"$props",
|
|
13
|
+
"$bool",
|
|
13
14
|
"defineProps",
|
|
14
15
|
"withDefaults",
|
|
15
16
|
"defineClientPayload",
|
|
@@ -286,6 +287,7 @@ export function isMissingBindingFailure(message) {
|
|
|
286
287
|
return !1;
|
|
287
288
|
return !/\b(document|window|navigator|localStorage|sessionStorage|self)\b/.test(message);
|
|
288
289
|
}
|
|
290
|
+
const reportedServerScriptFailures = new Set;
|
|
289
291
|
export async function extractVariables(scriptContent, context, filePath, options = {}) {
|
|
290
292
|
if (!scriptContent.trim())
|
|
291
293
|
return;
|
|
@@ -351,6 +353,19 @@ export async function extractVariables(scriptContent, context, filePath, options
|
|
|
351
353
|
};
|
|
352
354
|
for (const [key, value] of Object.entries(propsObj))
|
|
353
355
|
Object.defineProperty($props, key, { value, enumerable: !0, configurable: !0, writable: !0 });
|
|
356
|
+
const $bool = (value, fallback = !1) => {
|
|
357
|
+
if (value === void 0 || value === null)
|
|
358
|
+
return fallback;
|
|
359
|
+
if (typeof value === "string") {
|
|
360
|
+
const text = value.trim().toLowerCase();
|
|
361
|
+
if (text === "" || text === "true" || text === "1" || text === "on" || text === "yes")
|
|
362
|
+
return !0;
|
|
363
|
+
if (text === "false" || text === "0" || text === "off" || text === "no")
|
|
364
|
+
return !1;
|
|
365
|
+
return !0;
|
|
366
|
+
}
|
|
367
|
+
return Boolean(value);
|
|
368
|
+
};
|
|
354
369
|
for (const shadowed of ["name", "length", "caller", "arguments"]) {
|
|
355
370
|
if (Object.prototype.hasOwnProperty.call(propsObj, shadowed))
|
|
356
371
|
continue;
|
|
@@ -540,7 +555,7 @@ export async function extractVariables(scriptContent, context, filePath, options
|
|
|
540
555
|
const hostRuntimeConfig = context.__stx_options?.runtimeConfig;
|
|
541
556
|
if (hostRuntimeConfig || /\buse(?:Server)?RuntimeConfig\b/.test(jsContent))
|
|
542
557
|
await prepareRuntimeConfig(context, filePath, hostRuntimeConfig);
|
|
543
|
-
const result = await withRuntimeConfig(context.__stx_runtime_config ?? currentRuntimeConfig() ?? resolveRuntimeConfig(), () => withServerData(context, () => scriptFn(module, exports, requireFn, propsObj, $props, defineProps, withDefaults, defineClientPayload, useServerData, useRuntimeConfig, useServerRuntimeConfig, state, derived, effect, batch, onMount, onDestroy, definePageMeta, useRoute, useRouter, useHead, useSeoMeta, responseApi.setResponseStatus, responseApi.setResponseHeader, responseApi.notFound, ref, reactive, computed, watch, onMounted, onUnmounted, nextTick, defineEmits, defineExpose, defineSlots, provide, inject, useColorMode, useDark, useMediaQuery, useScrollLock, usePreferredDark, usePreferredLight, usePreferredReducedMotion, usePreferredContrast, windowProxy, mockDocument, mockConsole, mockWindow.confirm, mockWindow.alert, mockWindow.fetch, paramsObj, ...propArgValues, ...scriptContextValues)));
|
|
558
|
+
const result = await withRuntimeConfig(context.__stx_runtime_config ?? currentRuntimeConfig() ?? resolveRuntimeConfig(), () => withServerData(context, () => scriptFn(module, exports, requireFn, propsObj, $props, $bool, defineProps, withDefaults, defineClientPayload, useServerData, useRuntimeConfig, useServerRuntimeConfig, state, derived, effect, batch, onMount, onDestroy, definePageMeta, useRoute, useRouter, useHead, useSeoMeta, responseApi.setResponseStatus, responseApi.setResponseHeader, responseApi.notFound, ref, reactive, computed, watch, onMounted, onUnmounted, nextTick, defineEmits, defineExpose, defineSlots, provide, inject, useColorMode, useDark, useMediaQuery, useScrollLock, usePreferredDark, usePreferredLight, usePreferredReducedMotion, usePreferredContrast, windowProxy, mockDocument, mockConsole, mockWindow.confirm, mockWindow.alert, mockWindow.fetch, paramsObj, ...propArgValues, ...scriptContextValues)));
|
|
544
559
|
if (options.preserveExisting) {
|
|
545
560
|
for (const [key, value] of Object.entries(result))
|
|
546
561
|
if (!(key in context) || context[key] === void 0)
|
|
@@ -560,8 +575,13 @@ export async function extractVariables(scriptContent, context, filePath, options
|
|
|
560
575
|
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} does not parse, so every variable in that script is undefined. Cause: ${msg}`);
|
|
561
576
|
else if (isMissingBindingFailure(msg))
|
|
562
577
|
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}`);
|
|
563
|
-
else
|
|
564
|
-
|
|
578
|
+
else {
|
|
579
|
+
const seenKey = `${filePath ?? "<unknown>"}\x00${msg}`;
|
|
580
|
+
if (process.env.STX_DEBUG || !reportedServerScriptFailures.has(seenKey)) {
|
|
581
|
+
reportedServerScriptFailures.add(seenKey);
|
|
582
|
+
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
|
+
}
|
|
584
|
+
}
|
|
565
585
|
try {
|
|
566
586
|
await fallbackVariableExtraction(jsContent, context, filePath);
|
|
567
587
|
} catch (fallbackError) {
|
package/dist/visual-testing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"./chunk-
|
|
2
|
+
import"./chunk-ejqpq0wc.js";import B from"fs";import $ from"path";import k from"crypto";var V=[{name:"mobile",width:375,height:667,isMobile:!0,hasTouch:!0},{name:"tablet",width:768,height:1024,isMobile:!0,hasTouch:!0},{name:"desktop",width:1280,height:800,isMobile:!1,hasTouch:!1},{name:"wide",width:1920,height:1080,isMobile:!1,hasTouch:!1}];function J(N={}){let Y={snapshotDir:N.snapshotDir||"__snapshots__",screenshotDir:N.screenshotDir||"__screenshots__",updateSnapshots:N.updateSnapshots||process.env.UPDATE_SNAPSHOTS==="true",threshold:N.threshold??0.01,viewports:N.viewports||V,generateDiff:N.generateDiff??!0,diffDir:N.diffDir||"__diffs__",compare:N.compare||b,ci:N.ci??process.env.CI==="true",retries:N.retries??(N.ci?3:1)};return{async snapshot(M,X){let q=$.join(Y.snapshotDir,`${X}.html`),G=C(M),Q=K(G);if(await Bun.file(q).exists()){let W=await Bun.file(q).text(),Z=K(C(W));if(Q===Z)return{passed:!0,snapshotPath:q,message:"Snapshot matches"};if(Y.updateSnapshots)return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};let F=$.join(Y.diffDir,`${X}.actual.html`),U=$.join(Y.diffDir,`${X}.diff.html`);return await B.promises.mkdir(Y.diffDir,{recursive:!0}),await Bun.write(F,G),await Bun.write(U,I(W,G)),{passed:!1,snapshotPath:q,actualPath:F,diffPath:U,message:"Snapshot does not match"}}return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"New snapshot created"}},async snapshotJson(M,X){let q=$.join(Y.snapshotDir,`${X}.json`),G=JSON.stringify(M,null,2);if(await Bun.file(q).exists()){let Q=await Bun.file(q).text();if(G===Q)return{passed:!0,snapshotPath:q};if(Y.updateSnapshots)return await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};return{passed:!1,snapshotPath:q,message:`JSON snapshot mismatch:
|
|
3
3
|
${z(Q,G)}`}}return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"New snapshot created"}},matchInlineSnapshot(M,X){let q=C(M);if(X===void 0)return{passed:!0,expected:q};let G=C(X);return{passed:q===G,expected:q}},getConfig(){return Y}}}function D(N={}){let Y=J(N),M=Y.getConfig();return{async compareScreenshots(X,q,G="desktop"){let Q=$.join(M.screenshotDir,G,`${X}.png`),W=$.join(M.diffDir,G,`${X}.actual.png`),Z=$.join(M.diffDir,G,`${X}.diff.png`);if(await Bun.file(Q).exists()){let F=await Bun.file(Q).arrayBuffer(),U=Buffer.from(F),_=await M.compare(q,U);if(_.match||_.diffPercentage<=M.threshold)return{viewport:G,passed:!0,baselinePath:Q};if(M.updateSnapshots)return await B.promises.mkdir($.dirname(Q),{recursive:!0}),await Bun.write(Q,q),{viewport:G,passed:!0,baselinePath:Q};if(await B.promises.mkdir($.dirname(W),{recursive:!0}),await Bun.write(W,q),_.diffImage&&M.generateDiff)await Bun.write(Z,_.diffImage);return{viewport:G,passed:!1,baselinePath:Q,actualPath:W,diffPath:M.generateDiff?Z:void 0,diffPercentage:_.diffPercentage}}return await B.promises.mkdir($.dirname(Q),{recursive:!0}),await Bun.write(Q,q),{viewport:G,passed:!0,baselinePath:Q}},async testViewports(X,q,G=M.viewports){let Q=[];for(let W of G){let Z=null;for(let F=0;F<M.retries;F++)try{let U=await q(W),_=await this.compareScreenshots(X,U,W.name);Q.push(_),Z=null;break}catch(U){if(Z=U,F<M.retries-1)await new Promise((_)=>setTimeout(_,100*(F+1)))}if(Z)Q.push({viewport:W.name,passed:!1,baselinePath:"",diffPercentage:100})}return Q},getSnapshotTester(){return Y}}}function L(N={}){let M=D(N).getSnapshotTester(),X=new Map;return{addStory(q){X.set(`${q.component}/${q.name}`,q)},addStories(q){for(let G of q)this.addStory(G)},getStories(){return Array.from(X.values())},getStoriesForComponent(q){return Array.from(X.values()).filter((G)=>G.component===q)},async testStory(q){let G=X.get(q);if(!G)return{name:q,passed:!1,duration:0,snapshots:[],screenshots:[],errors:[Error(`Story not found: ${q}`)]};let Q=Date.now(),W={name:q,passed:!0,duration:0,snapshots:[],screenshots:[],errors:[]};try{let Z=await G.render(),F=await M.snapshot(Z,q.replace(/\//g,"-"));if(W.snapshots.push(F),!F.passed)W.passed=!1}catch(Z){W.passed=!1,W.errors.push(Z)}return W.duration=Date.now()-Q,W},async testAllStories(){let q=[];for(let G of X.keys()){let Q=await this.testStory(G);q.push(Q)}return q},async generateStoryIndex(){let q={};for(let G of X.values()){if(!q[G.component])q[G.component]=[];q[G.component].push({name:G.name,args:G.args})}return JSON.stringify(q,null,2)}}}async function S(N,Y={}){let M={outputDir:Y.outputDir||"visual-test-report",format:Y.format||"html",title:Y.title||"Visual Test Report",includeScreenshots:Y.includeScreenshots??!0};await B.promises.mkdir(M.outputDir,{recursive:!0});let X=N.length,q=N.filter((F)=>F.passed).length,G=X-q,Q=N.reduce((F,U)=>F+U.duration,0);if(M.format==="json"){let F={title:M.title,summary:{total:X,passed:q,failed:G,duration:Q},results:N,generatedAt:new Date().toISOString()},U=$.join(M.outputDir,"report.json");return await Bun.write(U,JSON.stringify(F,null,2)),U}if(M.format==="markdown"){let F=`# ${M.title}
|
|
4
4
|
|
|
5
5
|
`;F+=`## Summary
|
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.345",
|
|
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.345",
|
|
121
|
+
"@stacksjs/sanitizer": "0.2.345",
|
|
122
122
|
"@stacksjs/ts-i18n": "^0.1.11",
|
|
123
|
-
"bun-plugin-stx": "0.2.
|
|
123
|
+
"bun-plugin-stx": "0.2.345",
|
|
124
124
|
"bunfig": "^0.15.19",
|
|
125
|
-
"stx-router": "0.2.
|
|
125
|
+
"stx-router": "0.2.345",
|
|
126
126
|
"ts-broadcasting": "^0.0.10",
|
|
127
127
|
"ts-images": "^0.2.22",
|
|
128
128
|
"ts-syntax-highlighter": "^0.2.1"
|
package/dist/chunk-160g7ynw.js
DELETED
package/dist/chunk-16hr5y08.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{$l as c,cm as d,dm as e,em as f,fm as g,gm as h,hm as i,im as j,jm as k,km as l,lm as m,mm as n}from"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import{js as a,ks as b}from"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{h as transformAutoImports,b as stripCommentsAndLiterals,e as renderVendorStyleTags,i as referencesName,n as processClientScript,g as injectBrowserCoreAutoImports,m as generateServerDataBridge,k as generateBrowserAutoImportDestructuring,j as generateAutoImportDestructuring,a as findInterpolationEnd,l as extractBridgeData,d as extractAndStripCssImports,f as STX_AUTO_IMPORTS,c as BROWSER_CORE_IMPORTS};
|
package/dist/chunk-3h97y3n3.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{$p as k,Ho as a,Jo as b,Lo as c,Mo as d,Vp as e,Wp as f,Xp as g,Yp as h,Zp as i,_p as j,aq as l,bq as m,cq as n,dq as o,eq as p,fq as q,gq as r,hq as s,iq as t,jq as u,kq as v,lq as w,mq as x}from"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{e as validateTemplate,g as validateDirective,n as userComponentFileExists,m as transpileTypeScript,p as slotContentHasExpressions,k as shouldTranspileTypeScript,t as resolveTemplatePath,r as renderComponentWithSlot,j as isJavaScriptScript,o as isHydrateTrigger,d as hasVariables,h as hasDirectives,u as getSourceLineInfo,l as getSharedTranspiler,f as getPositionInfo,x as getComponentCacheStats,s as fileExists,a as extractVariables,c as extractScriptFromTemplate,i as extractDirectiveNames,v as createDetailedErrorMessage,b as convertToCommonJS,q as componentClientSignalNames,w as clearComponentCache};
|
package/dist/chunk-3j915h2d.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Ue as a}from"./chunk-e6rxvz3p.js";import"./chunk-57atgbyq.js";import"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{a as buildApp};
|
package/dist/chunk-4hkg6kx4.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{mo as a,no as b,oo as c,po as d,qo as e,ro as f,so as g,to as h,uo as i,vo as j,wo as k,xo as l,yo as m}from"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{m as stripStxRuntimeImports,b as scanScriptTags,l as rewriteStxImportSpecifiers,j as processSignals,h as processScriptSetup,f as preEvalLiteralReactiveIfs,c as parseLoopExpression,d as hasSignalsSyntax,k as findMarkupIndexOutsideScripts,i as extractExports,g as convertSignalLoopsToAttributes,e as convertSignalDirectivesToAttributes,a as clearScriptScanCache};
|
package/dist/chunk-57494khk.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Qo as a,Ro as b,So as c,To as d,Uo as e,Vo as f,Wo as g}from"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{a as resetUnscopedSignalWarnings,g as processStackReplacements,f as processStackPushDirectives,e as processIncludes,b as partialsCache,c as onceStore,d as clearOnceStore};
|
package/dist/chunk-5xavmr4t.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{$k as c,Zk as a,_k as b,al as d,bl as e,cl as f,dl as g,el as h,fl as i,gl as j,hl as k,il as l,jl as m,kl as n,ll as o}from"./chunk-57dxdvjh.js";import"./chunk-2853ye06.js";import"./chunk-fvsefztj.js";import"./chunk-xgw269cf.js";import"./chunk-aqxwwq6w.js";import"./chunk-t00ga194.js";import"./chunk-hrdd26r4.js";import"./chunk-7r79j1hs.js";import"./chunk-ay336sqb.js";import"./chunk-6xs80tka.js";import"./chunk-vaggjvsm.js";import"./chunk-q9ckfwhh.js";import"./chunk-kbah2k8e.js";import"./chunk-k3dtvay1.js";import"./chunk-eh3meyd3.js";import"./chunk-rzg9pars.js";import"./chunk-1qtd4ex2.js";import"./chunk-ec18ftcg.js";import"./chunk-fbmjw0bh.js";import"./chunk-53sjbp3z.js";import"./chunk-kgbz86sa.js";import"./chunk-s60eccqk.js";import"./chunk-0s3ry262.js";export{o as tempBuildName,b as shouldLogBundlerDiagnostics,f as setBundlerFallbackMode,l as rewriteRegistryImports,g as resolveBundlerFallback,j as registryIdForPath,c as recordBundleFailure,m as queueClientBundleBuild,k as normalizeRegistrySpecifiers,h as hasUserImports,d as getBundleFailures,a as clientBundleDependencies,e as clearBundleFailures,n as bundleClientScript,i as MODULE_SPECIFIER_PREFIX};
|