@useavalon/avalon 0.1.76 → 0.1.79

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.
@@ -1,4 +1,4 @@
1
1
  import{existsSync as e,readdirSync as t,readFileSync as n,statSync as r}from"node:fs";import{dirname as i,relative as a,resolve as o}from"node:path";export function islandClientBundlerPlugin(e,t,n){let r=process.cwd(),i=new Map,a=!1,o=c(e,r);for(let e of o)d(e,r,i);let s=`\0avalon-island-entry:`,l=!1,u=[],f={},p=`dist`;return{name:`avalon:island-client-bundler`,enforce:`pre`,configResolved(e){l=e.command===`serve`,a=e.command===`build`,u=e.resolve?.alias??[],f=e.define??{},p=e.build?.outDir??`dist`},resolveId(e){return e.startsWith(s)?e:null},load(e){if(!e.startsWith(s))return null;let t=e.slice(21),n=JSON.stringify(t);if(t.includes(`.qwik.`))return a?[`export * from ${n};`,`export { _hW } from "@builder.io/qwik";`].join(`
2
2
  `):[`export * from ${n};`,`export { _hW } from "@builder.io/qwik";`,`import __C from ${n};`,`export default __C;`,`if(typeof globalThis<"u")globalThis.__avalonIsland=__C;`].join(`
3
3
  `);let r=t.includes(`.lit.`),i=t.includes(`.solid.`),o=t.includes(`.preact.`),c=t.includes(`.react.`),l=t.includes(`.vue.`)||t.endsWith(`.vue`),u=t.includes(`.svelte.`)||t.endsWith(`.svelte`),d=[];if(r&&a&&d.push(`import "@useavalon/lit/client";`),d.push(`import __C from ${n};`,`var Component = __C;`,`export { Component as default, Component };`,`if(typeof globalThis<"u")globalThis.__avalonIsland=Component;`),a){let e={solid:`@useavalon/solid/client`,preact:`@useavalon/preact/client`,react:`@useavalon/react/client`,vue:`@useavalon/vue/client`,svelte:`@useavalon/svelte/client`,lit:`@useavalon/lit/client`},t=i?`solid`:o?`preact`:c?`react`:l?`vue`:u?`svelte`:r?`lit`:null;t&&e[t]?d.push(`export { hydrate as __hydrateIsland } from ${JSON.stringify(e[t])};`):d.push(`export { loadIntegrationModule } from "virtual:avalon/integration-loader";`)}return d.join(`
4
- `)},async buildStart(){if(l)return;let t=this.environment;if(!(t&&t.name!==`client`)&&i.size>0){for(let[,e]of i)this.emitFile({type:`chunk`,id:s+e.filePath,fileName:`islands/${e.bundleKey}.js`,preserveSignature:`exports-only`});e.verbose&&console.log(`🏝️ Emitting ${i.size} island client bundles`)}},async closeBundle(){if(l||!a||i.size===0||globalThis.__avalonIslandsRebuilt)return;globalThis.__avalonIslandsRebuilt=!0;let{buildIsolatedIslands:e}=await import(`../post-build/isolated-island-builder.js`),t=new Map;for(let[e,n]of i){let r=n.filePath.includes(`.solid.`)?`solid`:n.filePath.includes(`.preact.`)?`preact`:n.filePath.includes(`.react.`)?`react`:n.filePath.includes(`.vue.`)||n.filePath.endsWith(`.vue`)?`vue`:n.filePath.includes(`.svelte.`)||n.filePath.endsWith(`.svelte`)?`svelte`:n.filePath.includes(`.lit.`)?`lit`:n.filePath.includes(`.qwik.`)?`qwik`:`preact`;t.set(e,{...n,framework:r})}await e(r,p,t,u,f,n?{treeshake:n}:void 0)}}}function c(n,r){let i=[];if(n.pagesDir){let t=o(r,n.pagesDir);e(t)&&i.push(t)}if(n.layoutsDir){let t=o(r,n.layoutsDir);e(t)&&i.push(t)}if(n.modules){let a=o(r,n.modules.dir);if(e(a))try{for(let n of t(a,{withFileTypes:!0}))if(n.isDirectory())for(let t of[`pages`,`layouts`,`components`]){let r=o(a,n.name,t);e(r)&&i.push(r)}}catch{}}return i}const l=[`.qwik.`];function u(e){return l.some(t=>e.includes(t))}function d(e,r,i){let a;try{a=t(e,{withFileTypes:!0})}catch{return}for(let t of a){let a=o(e,t.name);if(t.isDirectory()){d(a,r,i);continue}if(/\.(tsx?|jsx?|mdx?)$/.test(t.name))try{let e=n(a,`utf-8`),t=e.includes(`island=`)||e.includes(`island `),o=/import\s+\w+\s+from\s+['"][^'"]*\.qwik\.[^'"]*['"]/m.test(e);if(!t&&!o)continue;f(e,a,r,i)}catch{}}}function f(e,t,n,r){let i=/<([A-Z]\w*)\s+[^>]*\bisland\b/g,o=new Set,s=null;for(s=i.exec(e);s!==null;s=i.exec(e))o.add(s[1]);let c=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,l=new Set,d=[];for(s=c.exec(e);s!==null;s=c.exec(e))d.push([s[1],s[2]]),u(s[2])&&RegExp(`<${s[1]}[\\s/>]`).test(e)&&l.add(s[1]);if(!(o.size===0&&l.size===0))for(let[e,i]of d){if(!o.has(e)&&!l.has(e))continue;let s=p(i,t,n);if(!s)continue;let c=a(n,s).replaceAll(`\\`,`/`).replace(/\.(tsx?|jsx?)$/,``);r.has(s)||r.set(s,{filePath:s,bundleKey:c})}}function p(t,n,a){let s;if(t.startsWith(`@shared/`))s=o(a,`app/shared`,t.slice(8));else if(t.startsWith(`@modules/`))s=o(a,`app/modules`,t.slice(9));else if(t.startsWith(`@/`))s=o(a,`app`,t.slice(2));else if(t.startsWith(`.`))s=o(i(n),t);else return null;if(e(s)&&r(s).isFile())return s;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(s+t))return s+t;return null}
4
+ `)},async buildStart(){if(l)return;let t=this.environment;if(!(t&&t.name!==`client`)&&i.size>0){for(let[,e]of i)this.emitFile({type:`chunk`,id:s+e.filePath,fileName:`islands/${e.bundleKey}.js`,preserveSignature:`exports-only`});e.verbose&&console.log(`🏝️ Emitting ${i.size} island client bundles`)}},async closeBundle(){if(l||!a||i.size===0||globalThis.__avalonIslandsRebuilt)return;globalThis.__avalonIslandsRebuilt=!0;let{buildIsolatedIslands:e}=await import(`../post-build/isolated-island-builder.js`),t=new Map;for(let[e,n]of i){let r=n.filePath.includes(`.solid.`)?`solid`:n.filePath.includes(`.preact.`)?`preact`:n.filePath.includes(`.react.`)?`react`:n.filePath.includes(`.vue.`)||n.filePath.endsWith(`.vue`)?`vue`:n.filePath.includes(`.svelte.`)||n.filePath.endsWith(`.svelte`)?`svelte`:n.filePath.includes(`.lit.`)?`lit`:n.filePath.includes(`.qwik.`)?`qwik`:`preact`;t.set(e,{...n,framework:r})}await e(r,p,t,u,f,n?{treeshake:n}:void 0)}}}function c(n,r){let i=[];if(n.pagesDir){let t=o(r,n.pagesDir);e(t)&&i.push(t)}if(n.layoutsDir){let t=o(r,n.layoutsDir);e(t)&&i.push(t)}if(n.modules){let a=o(r,n.modules.dir);if(e(a))try{for(let n of t(a,{withFileTypes:!0}))if(n.isDirectory())for(let t of[`pages`,`layouts`,`components`]){let r=o(a,n.name,t);e(r)&&i.push(r)}}catch{}}return i}const l=[`.qwik.`];function u(e){return l.some(t=>e.includes(t))}function d(e,r,i){let a;try{a=t(e,{withFileTypes:!0})}catch{return}for(let t of a){let a=o(e,t.name);if(t.isDirectory()){d(a,r,i);continue}if(/\.(tsx?|jsx?|mdx?)$/.test(t.name))try{let e=n(a,`utf-8`),t=e.includes(`island=`)||e.includes(`island `),o=/import\s+\w+\s+from\s+['"][^'"]*\.qwik\.[^'"]*['"]/m.test(e);if(!t&&!o)continue;f(e,a,r,i)}catch{}}}function f(e,t,n,r){let i=/<([A-Z]\w*)\s+[^>]*\bisland\b/g,o=new Set,s=null;for(s=i.exec(e);s!==null;s=i.exec(e))o.add(s[1]);let c=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,l=new Set,d=[];for(s=c.exec(e);s!==null;s=c.exec(e))d.push([s[1],s[2]]),u(s[2])&&RegExp(`<${s[1]}[\\s/>]`).test(e)&&l.add(s[1]);if(!(o.size===0&&l.size===0))for(let[e,i]of d){if(!o.has(e)&&!l.has(e))continue;let s=p(i,t,n);if(!s)continue;let c=a(n,s).replaceAll(`\\`,`/`).replace(/\.(tsx?|jsx?)$/,``);r.has(s)||r.set(s,{filePath:s,bundleKey:c})}}function p(t,n,a,s=[]){let c;for(let n of s){let i=n.find;if(typeof i==`string`){if(t===i||t.startsWith(`${i}/`)){let s=t.slice(i.length);if(c=o(a,n.replacement+s),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}else if(i instanceof RegExp&&i.test(t)){if(c=o(a,t.replace(i,n.replacement)),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}if(t.startsWith(`@shared/`))c=o(a,`app/shared`,t.slice(8));else if(t.startsWith(`@modules/`))c=o(a,`app/modules`,t.slice(9));else if(t.startsWith(`@/`))c=o(a,`app`,t.slice(2));else if(t.startsWith(`.`))c=o(i(n),t);else return null;if(e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t;return null}
@@ -15,7 +15,7 @@
15
15
  * with await expressions that call renderIsland() directly. This allows proper
16
16
  * async SSR rendering of islands in MDX files.
17
17
  */
18
- import type { Plugin } from 'vite';
18
+ import type { Plugin } from "vite";
19
19
  export interface MDXIslandTransformOptions {
20
20
  islandPathPatterns?: RegExp[];
21
21
  verbose?: boolean;
@@ -1,2 +1,2 @@
1
- import{dirname as e}from"node:path";const t=[/['"]\.\.\/islands\//,/['"]\.\/islands\//,/['"]\.\.\/\.\.\/islands\//,/['"]\$islands\//,/['"]@\/islands\//,/['"]\/src\/islands\//];function n(e){let t=new Map,n=/import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/g,r;for(;(r=n.exec(e))!==null;){let e=r[1],n=r[2].slice(1,-1);t.set(e,n)}return t}function r(e){let t=new Set,n=/<([A-Z]\w*)\s+[^>]*\bisland\s*[={]/g,r;for(;(r=n.exec(e))!==null;)t.add(r[1]);let i=/(?:_?jsxs?(?:DEV)?)\s*\(\s*([A-Z]\w*)\s*,\s*\{[^}]*\bisland\s*:/g;for(;(r=i.exec(e))!==null;)t.add(r[1]);return t}function i(e,t){let i=[],a=n(e),o=r(e);for(let[e,n]of a){let r=`"${n}"`,a=t.some(e=>e.test(r)),s=o.has(e);(a||s)&&i.push({localName:e,importPath:n,islandPropUsage:s})}return i}function a(t,n){if(t.startsWith(`/src/`)||t.startsWith(`/app/`)||t.startsWith(`/`))return t;if(t.startsWith(`@/`))return`/app/`+t.slice(2);if(t.startsWith(`@shared/`))return`/app/shared/`+t.slice(8);if(t.startsWith(`@modules/`))return`/app/modules/`+t.slice(9);if(t.startsWith(`$components/`))return`/src/components/`+t.slice(12);if(t.startsWith(`$islands/`))return`/src/islands/`+t.slice(9);if(t.startsWith(`~/`))return`/src/`+t.slice(2);if(t.startsWith(`.`)){let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i!==-1){let n=e(r.slice(i)).split(`/`),a=t.split(`/`);for(let e of a)e===`..`?n.pop():e!==`.`&&n.push(e);return n.join(`/`)}}return t.includes(`/islands/`)?`/src/islands/`+t.split(`/`).at(-1):`/src/`+t.split(`/`).pop()}function o(e){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;if(e.includes(`.qwik.`))return`qwik`;if(e.endsWith(`.tsx`)||e.endsWith(`.jsx`))return`preact`}function s(e,t){let n=t+1,r=1;for(;n<e.length&&r>0;){let t=e[n];t===`{`?(r++,n++):t===`}`?(r--,r>0&&n++):t===`'`||t===`"`||t==="`"?n=c(e,n):n++}return n<e.length?n+1:n}function c(e,t){let n=e[t];for(t++;t<e.length&&e[t]!==n;)e[t]===`\\`&&t++,t++;return t<e.length?t+1:t}function l(e,t){let n=t,r=0;for(;n<e.length&&e[n]!==`(`;)n++;if(n>=e.length)return t;for(;n<e.length;){let t=e[n];if(t===`(`)r++,n++;else if(t===`)`){if(r--,n++,r===0)return n}else t===`{`?n=s(e,n):t===`'`||t===`"`||t==="`"?n=c(e,n):n++}return n}function u(e){let t=e.match(/\bisland\s*:\s*/);if(!t)return null;let n=t.index+t[0].length,r;if(e[n]===`{`)r=s(e,n);else{let t=n,i=0;for(;t<e.length;){let n=e[t];if(n===`{`||n===`[`||n===`(`)i++,t++;else if(n===`}`||n===`]`||n===`)`){if(i===0)break;i--,t++}else if(n===`,`&&i===0)break;else t++}r=t}let i=e.slice(n,r).trim(),a=e.slice(0,t.index).trim(),o=e.slice(r).trim(),c=a;return o.startsWith(`,`)?c+=o.slice(1):c+=o,c=c.replace(/,\s*}$/,`}`).replace(/{\s*,/,`{`),{islandValue:i,otherProps:c}}function d(e,t,n,r){let i=RegExp(`(_?jsxs?(?:DEV)?)\\s*\\(\\s*`+t+`\\s*,`,`g`),a=``,o=0,c;for(;(c=i.exec(e))!==null;){let t=c.index;c[1];let i=l(e,t),d=e.slice(t,i);if(!d.includes(`island`)){a+=e.slice(o,i),o=i;continue}let f=d.indexOf(`{`);if(f===-1){a+=e.slice(o,i),o=i;continue}let p=s(d,f),m=u(d.slice(f,p));if(!m){a+=e.slice(o,i),o=i;continue}let{islandValue:h,otherProps:g}=m,_=`(await __AvalonRenderIsland({ src: "${n}", ${r?`framework: "${r}",`:``} ...(${h}), ${g.trim()!==`{}`&&g.trim()!==``?`props: ${g},`:``} ssr: (${h}).ssr !== undefined ? (${h}).ssr : true }))`;a+=e.slice(o,t)+_,o=i}return a+=e.slice(o),a}export function mdxIslandTransform(e={}){let{islandPathPatterns:n=t,verbose:r=!1}=e;return{name:`avalon:mdx-island-transform`,enforce:`post`,transform(e,t){if(!t.endsWith(`.mdx`)&&!t.includes(`.mdx?`))return null;let s=i(e,n);if(s.length===0)return null;if(r){console.log(`[mdx-island-transform] Found `+s.length+` island import(s) in `+t);for(let e of s)console.log(` - `+e.localName+` from `+e.importPath+(e.islandPropUsage?` (island prop)`:` (islands dir)`))}let c=e;if(!(c.includes(`from "@useavalon/avalon"`)||c.includes(`from '@useavalon/avalon'`))){let e=/^(import\s.+?from\s+.+?\n)/m.exec(c);if(e){let t=c.indexOf(e[0])+e[0].length;c=c.slice(0,t)+`import { renderIsland as __AvalonRenderIsland } from "@useavalon/avalon";
2
- `+c.slice(t)}}for(let e of s){let n=a(e.importPath,t),r=o(n);c=d(c,e.localName,n,r)}for(let e of s){let t=RegExp(`import\\s+${e.localName}\\s+from\\s+(['"][^'"]+['"])`,`g`);c=c.replace(t,`import $1; // [mdx-island-transform] kept for CSS: ${e.localName}`)}return c=c.replace(/function\s+_createMdxContent\s*\(/g,`async function _createMdxContent(`),c=c.replace(/export\s+default\s+function\s+MDXContent\s*\(/g,`export default async function MDXContent(`),r&&console.log(`[mdx-island-transform] Transformed `+t),{code:c,map:null}}}}
1
+ import{dirname as e}from"node:path";const t=[/['"]\.\.\/islands\//,/['"]\.\/islands\//,/['"]\.\.\/\.\.\/islands\//,/['"]\$islands\//,/['"]@\/islands\//,/['"]\/src\/islands\//];function n(e){let t=new Map,n=/import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/g,r;for(;(r=n.exec(e))!==null;){let e=r[1],n=r[2].slice(1,-1);t.set(e,n)}return t}function r(e){let t=new Set,n=/<([A-Z]\w*)\s+[^>]*\bisland\s*[={]/g,r;for(;(r=n.exec(e))!==null;)t.add(r[1]);let i=/(?:_?jsxs?(?:DEV)?)\s*\(\s*([A-Z]\w*)\s*,\s*\{[^}]*\bisland\s*:/g;for(;(r=i.exec(e))!==null;)t.add(r[1]);return t}function i(e,t){let i=[],a=n(e),o=r(e);for(let[e,n]of a){let r=`"${n}"`,a=t.some(e=>e.test(r)),s=o.has(e);(a||s)&&i.push({localName:e,importPath:n,islandPropUsage:s})}return i}function a(t,n,r=[]){if(t.startsWith(`/src/`)||t.startsWith(`/app/`)||t.startsWith(`/`))return t;for(let e of r){let n=e.find;if(typeof n==`string`){if(t===n||t.startsWith(`${n}/`)){let r=t.slice(n.length);return`${e.replacement.startsWith(`/`)?e.replacement:`/${e.replacement}`}${r}`}}else if(n instanceof RegExp&&n.test(t)){let r=e.replacement.startsWith(`/`)?e.replacement:`/${e.replacement}`;return t.replace(n,r)}}if(t.startsWith(`@/`))return`/app/${t.slice(2)}`;if(t.startsWith(`@shared/`))return`/app/shared/${t.slice(8)}`;if(t.startsWith(`@modules/`))return`/app/modules/${t.slice(9)}`;if(t.startsWith(`$components/`))return`/src/components/${t.slice(12)}`;if(t.startsWith(`$islands/`))return`/src/islands/${t.slice(9)}`;if(t.startsWith(`~/`))return`/src/${t.slice(2)}`;if(t.startsWith(`.`)){let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i!==-1){let n=e(r.slice(i)).split(`/`),a=t.split(`/`);for(let e of a)e===`..`?n.pop():e!==`.`&&n.push(e);return n.join(`/`)}}return t.includes(`/islands/`)?`/src/islands/${t.split(`/`).at(-1)}`:`/src/${t.split(`/`).pop()}`}function o(e){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;if(e.includes(`.qwik.`))return`qwik`;if(e.endsWith(`.tsx`)||e.endsWith(`.jsx`))return`preact`}function s(e,t){let n=t+1,r=1;for(;n<e.length&&r>0;){let t=e[n];t===`{`?(r++,n++):t===`}`?(r--,r>0&&n++):t===`'`||t===`"`||t==="`"?n=c(e,n):n++}return n<e.length?n+1:n}function c(e,t){let n=e[t];for(t++;t<e.length&&e[t]!==n;)e[t]===`\\`&&t++,t++;return t<e.length?t+1:t}function l(e,t){let n=t,r=0;for(;n<e.length&&e[n]!==`(`;)n++;if(n>=e.length)return t;for(;n<e.length;){let t=e[n];if(t===`(`)r++,n++;else if(t===`)`){if(r--,n++,r===0)return n}else t===`{`?n=s(e,n):t===`'`||t===`"`||t==="`"?n=c(e,n):n++}return n}function u(e){let t=e.match(/\bisland\s*:\s*/);if(!t)return null;let n=t.index+t[0].length,r;if(e[n]===`{`)r=s(e,n);else{let t=n,i=0;for(;t<e.length;){let n=e[t];if(n===`{`||n===`[`||n===`(`)i++,t++;else if(n===`}`||n===`]`||n===`)`){if(i===0)break;i--,t++}else if(n===`,`&&i===0)break;else t++}r=t}let i=e.slice(n,r).trim(),a=e.slice(0,t.index).trim(),o=e.slice(r).trim(),c=a;return o.startsWith(`,`)?c+=o.slice(1):c+=o,c=c.replace(/,\s*}$/,`}`).replace(/{\s*,/,`{`),{islandValue:i,otherProps:c}}function d(e,t,n,r){let i=RegExp(`(_?jsxs?(?:DEV)?)\\s*\\(\\s*${t}\\s*,`,`g`),a=``,o=0,c;for(;(c=i.exec(e))!==null;){let t=c.index;c[1];let i=l(e,t),d=e.slice(t,i);if(!d.includes(`island`)){a+=e.slice(o,i),o=i;continue}let f=d.indexOf(`{`);if(f===-1){a+=e.slice(o,i),o=i;continue}let p=s(d,f),m=u(d.slice(f,p));if(!m){a+=e.slice(o,i),o=i;continue}let{islandValue:h,otherProps:g}=m,_=`(await __AvalonRenderIsland({ src: "${n}", ${r?`framework: "${r}",`:``} ...(${h}), ${g.trim()!==`{}`&&g.trim()!==``?`props: ${g},`:``} ssr: (${h}).ssr !== undefined ? (${h}).ssr : true }))`;a+=e.slice(o,t)+_,o=i}return a+=e.slice(o),a}export function mdxIslandTransform(e={}){let{islandPathPatterns:n=t,verbose:r=!1}=e,s=[];return{name:`avalon:mdx-island-transform`,enforce:`post`,configResolved(e){s=e.resolve?.alias??[]},transform(e,t){if(!t.endsWith(`.mdx`)&&!t.includes(`.mdx?`))return null;let c=i(e,n);if(c.length===0)return null;if(r){console.log(`[mdx-island-transform] Found ${c.length} island import(s) in ${t}`);for(let e of c)console.log(` - ${e.localName} from ${e.importPath}${e.islandPropUsage?` (island prop)`:` (islands dir)`}`)}let l=e;if(!(l.includes(`from "@useavalon/avalon"`)||l.includes(`from '@useavalon/avalon'`))){let e=/^(import\s.+?from\s+.+?\n)/m.exec(l);if(e){let t=l.indexOf(e[0])+e[0].length;l=l.slice(0,t)+`import { renderIsland as __AvalonRenderIsland } from "@useavalon/avalon";
2
+ `+l.slice(t)}}for(let e of c){let n=a(e.importPath,t,s),r=o(n);l=d(l,e.localName,n,r)}for(let e of c){let t=RegExp(`import\\s+${e.localName}\\s+from\\s+(['"][^'"]+['"])`,`g`);l=l.replace(t,`import $1; // [mdx-island-transform] kept for CSS: ${e.localName}`)}return l=l.replace(/function\s+_createMdxContent\s*\(/g,`async function _createMdxContent(`),l=l.replace(/export\s+default\s+function\s+MDXContent\s*\(/g,`export default async function MDXContent(`),r&&console.log(`[mdx-island-transform] Transformed ${t}`),{code:l,map:null}}}}
@@ -1,2 +1,2 @@
1
- import{dirname as e}from"node:path";function t(e){let t=[],n=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,r=null;for(r=n.exec(e);r!==null;r=n.exec(e))t.push({localName:r[1],importPath:r[2].slice(1,-1),fullMatch:r[0].trimStart()});return t}function n(t,n){if(t.startsWith(`/src/`)||t.startsWith(`/app/`)||t.startsWith(`/`))return t;if(t.startsWith(`@/`))return`/app/${t.slice(2)}`;if(t.startsWith(`@shared/`))return`/app/shared/${t.slice(8)}`;if(t.startsWith(`@modules/`))return`/app/modules/${t.slice(9)}`;if(t.startsWith(`$components/`))return`/src/components/${t.slice(12)}`;if(t.startsWith(`$islands/`))return`/src/islands/${t.slice(9)}`;if(t.startsWith(`~/`))return`/src/${t.slice(2)}`;if(t.startsWith(`.`)){let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i!==-1){let n=e(r.slice(i)).split(`/`),a=t.split(`/`);for(let e of a)e===`..`?n.pop():e!==`.`&&n.push(e);return n.join(`/`)}}return`/src/${t.split(`/`).pop()}`}function r(e){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;if(e.includes(`.qwik.`))return`qwik`;if(e.includes(`.react.`))return`react`;if(e.endsWith(`.tsx`)||e.endsWith(`.jsx`))return`preact`}function i(e,t,n){let r=e.replaceAll(`\\`,`/`),i=t.replace(/^\//,``);if(r.includes(`/${i}/`)&&/\.(tsx|jsx)$/.test(r))return!0;if(n){let e=n.dir.replace(/^\//,``);if(RegExp(`/${e}/[^/]+/${n.pagesDirName}/`).test(r)&&/\.(tsx|jsx)$/.test(r))return!0}return!1}function a(e,t,n){let r=e.replaceAll(`\\`,`/`),i=t.replace(/^\//,``);if(r.includes(`/${i}/`)&&/\.(tsx|jsx)$/.test(r))return!0;if(n){let e=n.dir.replace(/^\//,``);if(RegExp(`/${e}/[^/]+/${n.layoutsDirName}/`).test(r)&&/\.(tsx|jsx)$/.test(r))return!0}return!1}const o=new Set([`qwik`]);function s(e){let t=r(e);return t!==void 0&&o.has(t)}function c(e,t){return t.some(t=>RegExp(`<${t}${String.raw`[\s][^>]*island[\s]*[={]`}`).test(e))}function l(e,t){return t.some(t=>s(t.importPath)?RegExp(`<${t.localName}${String.raw`[\s/>]`}`).test(e):!1)}function u(e,t,i){let a=new Map;for(let s of t){let t=n(s.importPath,i),c=r(t);if(RegExp(`<${s.localName}${String.raw`[\s][^>]*island[\s]*[={]`}`).test(e)){a.set(s.localName,{srcPath:t,framework:c,importPath:s.importPath,autoIsland:!1});continue}c&&o.has(c)&&RegExp(`<${s.localName}${String.raw`[\s/>]`}`).test(e)&&a.set(s.localName,{srcPath:t,framework:c,importPath:s.importPath,autoIsland:!0})}return a}function d(e,t){for(;t<e.length&&/\s/.test(e[t]);)t++;return t}function f(e,t){let n=e[t];for(t++;t<e.length&&e[t]!==n;)e[t]===`\\`&&t++,t++;return t<e.length?t+1:t}function p(e,t){for(t++;t<e.length&&e[t]!=="`";){if(e[t]===`\\`){t+=2;continue}if(e[t]===`$`&&e[t+1]===`{`){t=m(t+1,e);continue}t++}return t<e.length?t+1:t}function m(e,t){let n=e+1,r=1;for(;n<t.length&&r>0;){let e=t[n];e===`{`?(r++,n++):e===`}`?(r--,r>0&&n++):e===`'`||e===`"`||e==="`"?n=f(t,n):n++}return n<t.length?n+1:n}function h(e,t){let n=t+1,r=m(t,e);return{value:e.slice(n,r-1),endIdx:r}}function g(e,t){let n=e[t],r=t+1;for(;r<e.length&&e[r]!==n;)e[r]===`\\`&&r++,r++;return{value:`"${e.slice(t+1,r)}"`,endIdx:r+1}}function _(e,t){let n=t,r=t;for(;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;let i=e.slice(n,r);if(!i)return null;if(r=d(e,r),e[r]!==`=`)return{name:i,value:null,endIdx:r};if(r=d(e,r+1),e[r]===`{`){let t=h(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}if(e[r]===`"`||e[r]===`'`){let t=g(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}return null}function v(e,t,n){if(e[t]===`/`&&e[t+1]===`>`)return{endIdx:t+2,selfClosing:!0};if(e[t]===`>`){let r=`</${n}>`,i=e.indexOf(r,t+1);return i===-1?null:{endIdx:i+r.length,selfClosing:!1}}return null}function y(e,t,n){let r=d(e,t+1+n.length),i=null,a=[];for(;r<e.length;){r=d(e,r);let t=v(e,r,n);if(t)return{endIdx:t.endIdx,islandProp:i,otherProps:a};let o=_(e,r);if(!o)return null;if(r=o.endIdx,o.name===`island`)i=o.value??`{}`;else{let e=o.value===null?`${o.name}: true`:`${o.name}: ${o.value}`;a.push(e)}}return null}function b(e,t,n,r,i){let a=n?`, framework: "${n}"`:``,o=e.otherProps.length>0?`, props: { ${e.otherProps.join(`, `)} }`:``,s=`, component: ${i}`;if(r)return`{await __pageRenderIsland({ src: "`+t+`"`+a+s+o+`, ssr: true, ssrOnly: true })}`;let c=e.islandProp??``;return`{await __pageRenderIsland({ src: "`+t+`"`+a+s+`, ...(`+c+`)`+o+`, ssr: (`+c+`).ssr !== undefined ? (`+c+`).ssr : true })}`}function x(e,t,n){if(!e.startsWith(n,t))return!1;let r=t+n.length;return r>=e.length||!/[a-zA-Z0-9_$]/.test(e[r])}function S(e,t,n,r,i){let a=`<${t}`,o=``,s=0;for(;s<e.length;){if(e[s]==="`"){let t=s;s=p(e,s),o+=e.slice(t,s);continue}if(e[s]===`{`&&e[s+1]===`/`&&e[s+2]===`*`){let t=e.indexOf(`*/`,s+3);if(t!==-1){let n=t+2;for(;n<e.length&&/\s/.test(e[n]);)n++;if(n<e.length&&e[n]===`}`){o+=e.slice(s,n+1),s=n+1;continue}}}if(e[s]===`/`&&e[s+1]===`/`){let t=e.indexOf(`
2
- `,s),n=t===-1?e.length:t+1;o+=e.slice(s,n),s=n;continue}if(e[s]===`/`&&e[s+1]===`*`){let t=e.indexOf(`*/`,s+2),n=t===-1?e.length:t+2;o+=e.slice(s,n),s=n;continue}if(!x(e,s,a)){o+=e[s],s++;continue}let c=y(e,s,t);if(!c||!c.islandProp&&!i){let t=c?c.endIdx:s+1;o+=e.slice(s,t),s=t;continue}o+=b(c,n,r,i&&!c.islandProp,t),s=c.endIdx}return o}export function pageIslandTransform(e={}){let{pagesDir:n=`src/pages`,layoutsDir:r=`src/layouts`,modules:o=null}=e;return{name:`avalon:page-island-transform`,enforce:`pre`,transform(e,s){let d=a(s,r,o);if(!i(s,n,o)&&!d)return null;let f=t(e);if(f.length===0||!c(e,f.map(e=>e.localName))&&!l(e,f))return null;let p=u(e,f,s);if(p.size===0)return null;let m=`import { renderIsland as __pageRenderIsland } from '@useavalon/avalon';\n${e}`;for(let[e,t]of p)m=S(m,e,t.srcPath,t.framework,t.autoIsland);return{code:m,map:null}}}}
1
+ import{dirname as e}from"node:path";function t(e){let t=[],n=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,r=null;for(r=n.exec(e);r!==null;r=n.exec(e))t.push({localName:r[1],importPath:r[2].slice(1,-1),fullMatch:r[0].trimStart()});return t}function n(t,n,r=[]){if(t.startsWith(`/src/`)||t.startsWith(`/app/`)||t.startsWith(`/`))return t;for(let e of r){let n=e.find;if(typeof n==`string`){if(t===n||t.startsWith(`${n}/`)){let r=t.slice(n.length);return`${e.replacement.startsWith(`/`)?e.replacement:`/${e.replacement}`}${r}`}}else if(n instanceof RegExp&&n.test(t)){let r=e.replacement.startsWith(`/`)?e.replacement:`/${e.replacement}`;return t.replace(n,r)}}if(t.startsWith(`@/`))return`/app/${t.slice(2)}`;if(t.startsWith(`@shared/`))return`/app/shared/${t.slice(8)}`;if(t.startsWith(`@modules/`))return`/app/modules/${t.slice(9)}`;if(t.startsWith(`$components/`))return`/src/components/${t.slice(12)}`;if(t.startsWith(`$islands/`))return`/src/islands/${t.slice(9)}`;if(t.startsWith(`~/`))return`/src/${t.slice(2)}`;if(t.startsWith(`.`)){let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i!==-1){let n=e(r.slice(i)).split(`/`),a=t.split(`/`);for(let e of a)e===`..`?n.pop():e!==`.`&&n.push(e);return n.join(`/`)}}return`/src/${t.split(`/`).pop()}`}function r(e){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;if(e.includes(`.qwik.`))return`qwik`;if(e.includes(`.react.`))return`react`;if(e.endsWith(`.tsx`)||e.endsWith(`.jsx`))return`preact`}function i(e,t,n){let r=e.replaceAll(`\\`,`/`),i=t.replace(/^\//,``);if(r.includes(`/${i}/`)&&/\.(tsx|jsx)$/.test(r))return!0;if(n){let e=n.dir.replace(/^\//,``);if(RegExp(`/${e}/[^/]+/${n.pagesDirName}/`).test(r)&&/\.(tsx|jsx)$/.test(r))return!0}return!1}function a(e,t,n){let r=e.replaceAll(`\\`,`/`),i=t.replace(/^\//,``);if(r.includes(`/${i}/`)&&/\.(tsx|jsx)$/.test(r))return!0;if(n){let e=n.dir.replace(/^\//,``);if(RegExp(`/${e}/[^/]+/${n.layoutsDirName}/`).test(r)&&/\.(tsx|jsx)$/.test(r))return!0}return!1}const o=new Set([`qwik`]);function s(e){let t=r(e);return t!==void 0&&o.has(t)}function c(e,t){return t.some(t=>RegExp(`<${t}${String.raw`[\s][^>]*island[\s]*[={]`}`).test(e))}function l(e,t){return t.some(t=>s(t.importPath)?RegExp(`<${t.localName}${String.raw`[\s/>]`}`).test(e):!1)}function u(e,t,i,a=[]){let s=new Map;for(let c of t){let t=n(c.importPath,i,a),l=r(t);if(RegExp(`<${c.localName}${String.raw`[\s][^>]*island[\s]*[={]`}`).test(e)){s.set(c.localName,{srcPath:t,framework:l,importPath:c.importPath,autoIsland:!1});continue}l&&o.has(l)&&RegExp(`<${c.localName}${String.raw`[\s/>]`}`).test(e)&&s.set(c.localName,{srcPath:t,framework:l,importPath:c.importPath,autoIsland:!0})}return s}function d(e,t){for(;t<e.length&&/\s/.test(e[t]);)t++;return t}function f(e,t){let n=e[t];for(t++;t<e.length&&e[t]!==n;)e[t]===`\\`&&t++,t++;return t<e.length?t+1:t}function p(e,t){for(t++;t<e.length&&e[t]!=="`";){if(e[t]===`\\`){t+=2;continue}if(e[t]===`$`&&e[t+1]===`{`){t=m(t+1,e);continue}t++}return t<e.length?t+1:t}function m(e,t){let n=e+1,r=1;for(;n<t.length&&r>0;){let e=t[n];e===`{`?(r++,n++):e===`}`?(r--,r>0&&n++):e===`'`||e===`"`||e==="`"?n=f(t,n):n++}return n<t.length?n+1:n}function h(e,t){let n=t+1,r=m(t,e);return{value:e.slice(n,r-1),endIdx:r}}function g(e,t){let n=e[t],r=t+1;for(;r<e.length&&e[r]!==n;)e[r]===`\\`&&r++,r++;return{value:`"${e.slice(t+1,r)}"`,endIdx:r+1}}function _(e,t){let n=t,r=t;for(;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;let i=e.slice(n,r);if(!i)return null;if(r=d(e,r),e[r]!==`=`)return{name:i,value:null,endIdx:r};if(r=d(e,r+1),e[r]===`{`){let t=h(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}if(e[r]===`"`||e[r]===`'`){let t=g(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}return null}function v(e,t,n){if(e[t]===`/`&&e[t+1]===`>`)return{endIdx:t+2,selfClosing:!0};if(e[t]===`>`){let r=`</${n}>`,i=e.indexOf(r,t+1);return i===-1?null:{endIdx:i+r.length,selfClosing:!1}}return null}function y(e,t,n){let r=d(e,t+1+n.length),i=null,a=[];for(;r<e.length;){r=d(e,r);let t=v(e,r,n);if(t)return{endIdx:t.endIdx,islandProp:i,otherProps:a};let o=_(e,r);if(!o)return null;if(r=o.endIdx,o.name===`island`)i=o.value??`{}`;else{let e=o.value===null?`${o.name}: true`:`${o.name}: ${o.value}`;a.push(e)}}return null}function b(e,t,n,r,i){let a=n?`, framework: "${n}"`:``,o=e.otherProps.length>0?`, props: { ${e.otherProps.join(`, `)} }`:``,s=`, component: ${i}`;if(r)return`{await __pageRenderIsland({ src: "`+t+`"`+a+s+o+`, ssr: true, ssrOnly: true })}`;let c=e.islandProp??``;return`{await __pageRenderIsland({ src: "`+t+`"`+a+s+`, ...(`+c+`)`+o+`, ssr: (`+c+`).ssr !== undefined ? (`+c+`).ssr : true })}`}function x(e,t,n){if(!e.startsWith(n,t))return!1;let r=t+n.length;return r>=e.length||!/[a-zA-Z0-9_$]/.test(e[r])}function S(e,t,n,r,i){let a=`<${t}`,o=``,s=0;for(;s<e.length;){if(e[s]==="`"){let t=s;s=p(e,s),o+=e.slice(t,s);continue}if(e[s]===`{`&&e[s+1]===`/`&&e[s+2]===`*`){let t=e.indexOf(`*/`,s+3);if(t!==-1){let n=t+2;for(;n<e.length&&/\s/.test(e[n]);)n++;if(n<e.length&&e[n]===`}`){o+=e.slice(s,n+1),s=n+1;continue}}}if(e[s]===`/`&&e[s+1]===`/`){let t=e.indexOf(`
2
+ `,s),n=t===-1?e.length:t+1;o+=e.slice(s,n),s=n;continue}if(e[s]===`/`&&e[s+1]===`*`){let t=e.indexOf(`*/`,s+2),n=t===-1?e.length:t+2;o+=e.slice(s,n),s=n;continue}if(!x(e,s,a)){o+=e[s],s++;continue}let c=y(e,s,t);if(!c||!c.islandProp&&!i){let t=c?c.endIdx:s+1;o+=e.slice(s,t),s=t;continue}o+=b(c,n,r,i&&!c.islandProp,t),s=c.endIdx}return o}export function pageIslandTransform(e={}){let{pagesDir:n=`src/pages`,layoutsDir:r=`src/layouts`,modules:o=null}=e,s=[];return{name:`avalon:page-island-transform`,enforce:`pre`,configResolved(e){s=e.resolve?.alias??[]},transform(e,d){let f=a(d,r,o);if(!i(d,n,o)&&!f)return null;let p=t(e);if(p.length===0||!c(e,p.map(e=>e.localName))&&!l(e,p))return null;let m=u(e,p,d,s);if(m.size===0)return null;let h=`import { renderIsland as __pageRenderIsland } from '@useavalon/avalon';\n${e}`;for(let[e,t]of m)h=S(h,e,t.srcPath,t.framework,t.autoIsland);return{code:h,map:null}}}}
@@ -21,15 +21,19 @@ export declare function deduplicateCSSRules(css: string): string;
21
21
  */
22
22
  export declare function extractCriticalCSS(clear?: boolean): string;
23
23
  /**
24
- * Convert external third-party <link rel="stylesheet"> tags to use the
25
- * media="print" swap pattern for async/non-blocking loading.
24
+ * Convert external third-party <link rel="stylesheet"> tags and explicitly
25
+ * deferred local stylesheets to use the media="print" swap pattern for
26
+ * async/non-blocking loading.
26
27
  *
27
- * Only defers stylesheets from external origins (https://) — local asset
28
- * stylesheets (e.g., /assets/entry-client-*.css) are never deferred since
29
- * they contain essential layout CSS that would cause FOUC if delayed.
28
+ * Defers:
29
+ * - External stylesheets (https://, http://)
30
+ * - Local stylesheets marked with data-defer attribute
31
+ * - Local stylesheets matching known non-critical patterns (e.g., syntax highlighting)
30
32
  *
31
- * Stylesheets that already have a media attribute or are marked as critical
32
- * (data-critical) are left untouched.
33
+ * Preserves (never deferred):
34
+ * - Local asset stylesheets (/assets/*) essential layout CSS
35
+ * - Stylesheets with an existing media attribute
36
+ * - Stylesheets marked as critical (data-critical)
33
37
  */
34
38
  export declare function deferNonCriticalStylesheets(html: string): string;
35
39
  /**
@@ -38,6 +42,7 @@ export declare function deferNonCriticalStylesheets(html: string): string;
38
42
  * 1. Extracts SSR-collected CSS from the universal collector
39
43
  * 2. Inlines it as a <style> tag in <head>
40
44
  * 3. Converts external stylesheet <link> tags to async loading
45
+ * 4. Adds fetchpriority hints for above-the-fold resources
41
46
  *
42
47
  * @param html - The rendered HTML string
43
48
  * @returns The HTML with critical CSS inlined and external stylesheets deferred
@@ -1,3 +1,4 @@
1
- import{getUniversalCSS as e}from"./universal-css-collector.js";import{minifyCSS as t}from"./css-utils.js";function n(e){let t=0;for(let n of e)n===`{`?t++:n===`}`&&t--;return t}function r(e,t,n){let r=e.replaceAll(/\s+/g,` `).trim();if(r.startsWith(`/*`)&&r.endsWith(`*/`)){n.push(e.trimEnd());return}t.has(r)||(t.add(r),n.push(e.trimEnd()))}export function deduplicateCSSRules(e){if(!e.trim())return``;let t=new Set,i=e.split(`
1
+ import{minifyCSS as e}from"./css-utils.js";import{getUniversalCSS as t}from"./universal-css-collector.js";function n(e){let t=0;for(let n of e)n===`{`?t++:n===`}`&&t--;return t}function r(e,t,n){let r=e.replaceAll(/\s+/g,` `).trim();if(r.startsWith(`/*`)&&r.endsWith(`*/`)){n.push(e.trimEnd());return}t.has(r)||(t.add(r),n.push(e.trimEnd()))}export function deduplicateCSSRules(e){if(!e.trim())return``;let t=new Set,i=e.split(`
2
2
  `),a=[],o=``,s=0;for(let e of i)s+=n(e),o+=`${e}\n`,s<=0&&o.trim()&&(r(o,t,a),o=``,s=0);return o.trim()&&a.push(o.trimEnd()),a.join(`
3
- `)}export function extractCriticalCSS(n=!0){let r=e(n);if(!r.trim())return``;let a=t(deduplicateCSSRules(r));return a.trim()?`<style data-critical-css="true">${a}</style>`:``}export function deferNonCriticalStylesheets(e){return e.replaceAll(/<link\s+([^>]*rel=["']stylesheet["'][^>]*)>/gi,(e,t)=>{if(/\bmedia\s*=/i.test(t)||/data-critical/i.test(t))return e;let n=/href=["']([^"']+)["']/i.exec(t);if(!n)return e;let r=n[1];return!r.startsWith(`https://`)&&!r.startsWith(`http://`)?e:`${`<link ${t} media="print" onload="this.media='all'">`}\n${`<noscript><link rel="stylesheet" href="${r}"></noscript>`}`})}export function inlineCriticalCSS(e){let t=extractCriticalCSS(!0),n=e;return t&&n.includes(`</head>`)&&(n=n.replace(`</head>`,`${t}\n</head>`)),n=deferNonCriticalStylesheets(n),n}
3
+ `)}export function extractCriticalCSS(n=!0){let r=t(n);if(!r.trim())return``;let a=e(deduplicateCSSRules(r));return a.trim()?`<style data-critical-css="true">${a}</style>`:``}export function deferNonCriticalStylesheets(e){let t=/<link\s+([^>]*rel=["']stylesheet["'][^>]*)>/gi,n=[/syntax-highlight/i,/hljs/i,/prism/i,/highlight\.js/i];return e.replaceAll(t,(e,t)=>{if(/\bmedia\s*=/i.test(t)||/data-critical/i.test(t))return e;let r=/href=["']([^"']+)["']/i.exec(t);if(!r)return e;let i=r[1],a=i.startsWith(`https://`)||i.startsWith(`http://`),o=/data-defer/i.test(t),s=!a&&n.some(e=>e.test(i));return!a&&!o&&!s?e:`${`<link ${t.replace(/\s*data-defer(?:=["'][^"']*["'])?\s*/gi,` `).trim()} media="print" onload="this.media='all'">`}\n${`<noscript><link rel="stylesheet" href="${i}"></noscript>`}`})}export function inlineCriticalCSS(e){let t=extractCriticalCSS(!0),n=e;return t&&n.includes(`</head>`)&&(n=n.replace(`</head>`,`${t}\n</head>`)),n=deferNonCriticalStylesheets(n),n=c(n),n}function c(e){let t=/href=["'](https:\/\/fonts\.googleapis\.com\/css2[^"']+)["']/gi,n=new Set,r;for(r=t.exec(e);r!==null;r=t.exec(e))n.add(r[1]);if(n.size===0)return e;let i=[];for(let t of n){let n=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`);new RegExp(String.raw`<link\s+[^>]*rel=["']preload["'][^>]*href=["']${n}["'][^>]*>`,`i`).test(e)||i.push(`<link rel="preload" href="${t}" as="style">`)}if(i.length===0)return e;let a=i.join(`
4
+ `);return e.includes(`</title>`)?e.replace(`</title>`,`</title>\n${a}`):e}
@@ -9,15 +9,12 @@
9
9
  * 4. Adapter Copying: Copies framework adapters to dist/
10
10
  * 5. Netlify Function Copying: Copies server function to all Netlify paths
11
11
  * 6. Prerendering: Boots built server, fetches routes, writes static HTML
12
+ * 7. HTML Optimization: Inlines small CSS, defers non-critical stylesheets,
13
+ * adds font preload hints
12
14
  *
13
15
  * Usage:
14
16
  * import { runPostBuild } from '@useavalon/avalon/post-build';
15
17
  * await runPostBuild();
16
- *
17
- * With custom prerender config:
18
- * await runPostBuild({
19
- * prerender: { routes: ['/'], crawlLinks: true, ignore: ['/admin'] },
20
- * });
21
18
  */
22
19
  export interface PrerenderConfig {
23
20
  /** Routes to prerender (default: ['/']) */
@@ -45,13 +42,4 @@ export interface PostBuildOptions {
45
42
  /** Port for prerender server (default: 13172) */
46
43
  prerenderPort?: number;
47
44
  }
48
- /**
49
- * Run all post-build tasks.
50
- *
51
- * Usage in consumer's post-build.mjs:
52
- * ```js
53
- * import { runPostBuild } from '@useavalon/avalon/post-build';
54
- * await runPostBuild();
55
- * ```
56
- */
57
45
  export declare function runPostBuild(options?: PostBuildOptions): Promise<void>;
@@ -1,32 +1,24 @@
1
- import{copyFileSync as e,cpSync as t,existsSync as n,mkdirSync as r,readdirSync as i,readFileSync as a,unlinkSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,relative as u}from"node:path";function d(e,t,r=[]){if(!n(e))return r;for(let n of i(e,{withFileTypes:!0})){let i=l(e,n.name);n.isDirectory()?d(i,t,r):t(n.name)&&r.push(i)}return r}function f(e){if(!n(e))return!1;let t=a(e,`utf-8`);return t.length<500&&!t.includes(`data-framework`)&&!t.includes(`avalon`)}function p(e){for(let t of[`dist/index.html`,`.netlify/functions-internal/server/public/index.html`,`.output/public/index.html`]){let r=l(e,t);f(r)?(o(r),console.log(`[cleanup] Removed stale Vite template ${t}`)):n(r)&&console.log(`[cleanup] Preserved prerendered ${t}`)}}function m(e,t,r){if(!n(e))return;let i=[l(t,`assets`),l(r,`.netlify`,`functions-internal`,`server`,`public`,`assets`),l(r,`.output`,`public`,`assets`)].find(e=>n(e));if(!i)return;let o=d(i,e=>e.endsWith(`.css`)).filter(e=>{let t=(e.split(`/`).pop()||``).toLowerCase();return t.includes(`_isolated-island-entry`)?!1:!!(t.startsWith(`entry-client`)||t.startsWith(`index-`))}).map(e=>`/assets${e.substring(i.length).replaceAll(`\\`,`/`)}`);if(!o.some(e=>/\/index-[^/]+\.css$/.test(e))){let e=d(i,e=>e.endsWith(`.css`)).filter(e=>(e.split(`/`).pop()||``).toLowerCase().startsWith(`ssr-index`)).map(e=>`/assets${e.substring(i.length).replaceAll(`\\`,`/`)}`);o.push(...e)}console.log(`[patch] Found ${o.length} CSS files in ${i}`);let c=a(e,`utf-8`);for(let{re:t,hrefRe:n,q:r}of[{re:/css:\[(\{href:`[^`]+`\}(?:,\{href:`[^`]+`\})*)\]/,hrefRe:/href:`([^`]+)`/g,q:"`"},{re:/css:\[(\{href:"[^"]+"\}(?:,\{href:"[^"]+"\})*)\]/,hrefRe:/href:"([^"]+)"/g,q:`"`}]){let i=t.exec(c);if(!i)continue;let a=new Set([...i[1].matchAll(n)].map(e=>e[1])),l=o.filter(e=>!a.has(e));if(l.length===0){console.log(`[patch] All CSS already included`);return}let u=l.map(e=>`{href:${r}${e}${r}}`).join(`,`);c=c.replace(i[0],`css:[${i[1]},${u}]`),s(e,c),console.log(`[patch] ✅ Added ${l.length} CSS files to SSR bundle`);return}console.warn(`[patch] Could not find CSS array in SSR bundle`)}function h(e){return e.replaceAll(/\/\*[\s\S]*?\*\//g,``).replaceAll(/\s+/g,` `).replaceAll(/\s*([{}:;,>~+])\s*/g,`$1`).replaceAll(/;}/g,`}`).trim()}function g(e,t){let o=l(t,`assets`);if(n(o)&&i(o).some(e=>e.startsWith(`entry-client`)&&e.endsWith(`.css`))){console.log(`[ssr-css] Skipped — client build already includes entry-client CSS`);return}let c=[l(e,`node_modules`,`.nitro`,`vite`,`services`,`ssr`,`assets`)];for(let o of c){if(!n(o))continue;let c=i(o).filter(e=>e.endsWith(`.css`));if(c.length===0)continue;let u=[l(t,`assets`),l(e,`.output`,`public`,`assets`),l(e,`.netlify`,`functions-internal`,`server`,`public`,`assets`)];for(let e of u){r(e,{recursive:!0});for(let t of c){let n=a(l(o,t),`utf-8`);n=h(n),s(l(e,`ssr-${t}`),n)}}let d=`ssr-${c[0]}`,f=l(u.find(e=>n(e))||u[0],d),p=n(f)?a(f).length:0;console.log(`[ssr-css] Copied SSR CSS → /assets/${d} (${p} bytes, minified)`);let m=[l(e,`.output`,`server`,`index.mjs`),l(e,`.netlify`,`functions-internal`,`server`,`main.mjs`)];for(let e of m){if(!n(e))continue;let t=a(e,`utf-8`),r=`/assets/${d}`;if(t.includes(r))continue;let i=/"\/assets\/[^"]+\.css":\{type:`text\/css[^}]+\}/.exec(t);if(i){let n=new Date().toISOString(),a=`,"${r}":{type:\`text/css; charset=utf-8\`,etag:\`${`"${p.toString(16)}-ssr"`}\`,mtime:\`${n}\`,size:${p},path:\`../public/assets/${d}\`}`;t=t.replace(i[0],i[0]+a),s(e,t),console.log(`[ssr-css] ✅ Patched asset manifest in ${e}`)}}return}console.log(`[ssr-css] No SSR CSS files found`)}async function _(e,t){let r=l(t,`islands`);if(!n(r))return;let i=d(r,e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));if(i.length===0)return;let o=[];for(let t of i){let i=a(t,`utf-8`);if(!/from\s*["']\.\.\//.test(i))continue;let s=t.substring(r.length+1).replace(/\.js$/,``),c=`preact`;if(t.includes(`.solid.`)?c=`solid`:t.includes(`.vue.`)||t.endsWith(`.vue.js`)?c=`vue`:t.includes(`.svelte.`)?c=`svelte`:t.includes(`.react.`)?c=`react`:t.includes(`.lit.`)?c=`lit`:t.includes(`.qwik.`)&&(c=`qwik`),c===`qwik`||c===`lit`)continue;let u=l(e,`${s}.tsx`),d=l(e,`${s}.ts`),f=l(e,`${s}`).replace(/\.vue$/,`.vue`),p=l(e,`${s}`).replace(/\.svelte$/,`.svelte`),m=null;for(let e of[u,d,f,p])if(n(e)){m=e;break}if(!m){console.warn(`[islands] ⚠ Cannot find source for stale island: ${s}`);continue}o.push({filePath:m,bundleKey:s,framework:c})}if(o.length!==0){console.log(`[islands] Found ${o.length} island(s) still code-split, rebuilding...`);try{let{buildIsolatedIslands:t}=await import(`./isolated-island-builder.js`),n=new Map;for(let e of o)n.set(e.filePath,e);await t(e,`dist`,n,[],{})}catch(e){console.error(`[islands] Failed to rebuild stale islands: ${e instanceof Error?e.message:e}`)}}}function v(t,i){let a=l(i,`islands`);if(!n(a))return;let s=[l(t,`.output`,`public`),l(t,`.netlify`,`functions-internal`,`server`,`public`)],u=0,f=d(a,e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));for(let t of s){if(!n(t))continue;let i=l(t,`islands`);for(let t of f){let s=l(i,t.substring(a.length));r(c(s),{recursive:!0}),e(t,s),u++;for(let e of[`.br`,`.gz`,`.zst`]){let t=s+e;n(t)&&o(t)}}}u>0&&console.log(`[islands] Synced ${u} isolated island build(s) to output`)}function y(t){let i=[l(t,`assets`,`islands`),l(t,`islands`)].find(e=>n(e));if(!i)return;let o=d(i,e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));if(o.length===0)return;let f=o.filter(e=>/-[A-Za-z0-9_-]{6,12}\.js$/.test(e));if(f.length===0){console.log(`[redirects] ${o.length} island(s) found with clean paths — no redirects needed`);return}let p=[];for(let n of f){let i=`/${u(t,n).replaceAll(`\\`,`/`)}`,a=i.replace(`/assets/`,`/`).replace(/-[A-Za-z0-9_-]{6,12}\.js$/,`.js`);p.push(`${a} ${i} 200`);let o=l(t,a.slice(1));r(c(o),{recursive:!0}),e(n,o)}let m=l(t,`_redirects`),h=n(m)?a(m,`utf-8`):``;h=h.replaceAll(/# Island JS path rewrites[^\n]*\n(?:\/islands\/[^\n]*\n)*/g,``).trim();let g=`# Island JS path rewrites (generated by Avalon post-build)
2
- `;s(m,h?`${h}\n\n${g}${p.join(`
3
- `)}\n`:`${g+p.join(`
4
- `)}\n`),console.log(`[redirects] ✅ Wrote ${p.length} island redirects + local copies`)}function b(t,a){let o=[l(t,`.output`,`public`,`_adapters`),l(a,`_adapters`)];for(let t of o){if(!n(t))continue;let o=i(t).filter(e=>e.endsWith(`.js`));if(o.length===0)continue;let s=l(a,`_adapters`);r(s,{recursive:!0});for(let n of o){let r=l(t,n),i=l(s,n);r!==i&&e(r,i)}console.log(`[adapters] ✅ Copied ${o.length} framework adapters`);return}console.log(`[adapters] No _adapters/ directory found`)}function x(e){let r=l(e,`.netlify`,`functions-internal`,`server`);if(!n(r))return;let i=[l(e,`.netlify`,`v1`,`functions`,`server`)];for(let n of i){t(r,n,{recursive:!0,force:!0});let i=n.substring(e.length).replaceAll(`\\`,`/`);console.log(`[netlify-fn] ✅ Copied server function to ${i}/`)}}function S(e){let t=a(e,`utf-8`);return t.includes(`path: "/*"`)||t.includes("path:`/*`")}function C(e,t,r){let i=l(c(e),`_prerender-server.mjs`),a=``,o=[l(r,`node_modules`,`urlpattern-polyfill`,`index.js`),l(r,`node_modules`,`urlpattern-polyfill`,`dist`,`urlpattern.js`)].find(e=>n(e));return o&&(a=`import '${o.replaceAll(`\\`,`/`)}';`),s(i,`
5
- ${a}
1
+ import{copyFileSync as e,cpSync as t,existsSync as n,mkdirSync as r,readdirSync as i,readFileSync as a,unlinkSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,relative as u}from"node:path";function d(e,t,r=[]){if(!n(e))return r;for(let n of i(e,{withFileTypes:!0})){let i=l(e,n.name);n.isDirectory()?d(i,t,r):t(n.name)&&r.push(i)}return r}function f(e){if(!n(e))return!1;let t=a(e,`utf-8`);return t.length<500&&!t.includes(`data-framework`)&&!t.includes(`avalon`)}function p(e){for(let t of[`dist/index.html`,`.netlify/functions-internal/server/public/index.html`,`.output/public/index.html`]){let r=l(e,t);f(r)?(o(r),console.log(`[cleanup] Removed stale Vite template ${t}`)):n(r)&&console.log(`[cleanup] Kept ${t} (not a Vite template)`)}}function m(e){return e.replaceAll(/\/\*[\s\S]*?\*\//g,``).replaceAll(/\s+/g,` `).replaceAll(/\s*([{}:;,])\s*/g,`$1`).trim()}function h(e,t,r){if(!n(e))return;let i=[l(t,`assets`),l(r,`.netlify`,`functions-internal`,`server`,`public`,`assets`),l(r,`.output`,`public`,`assets`)].find(e=>n(e));if(!i)return;let o=d(i,e=>e.endsWith(`.css`)).filter(e=>{let t=(e.split(`/`).pop()||``).toLowerCase();return t.includes(`_isolated-island-entry`)?!1:!!(t.startsWith(`entry-client`)||t.startsWith(`index-`))}).map(e=>`/assets${e.substring(i.length).replaceAll(`\\`,`/`)}`);if(!o.some(e=>/\/index-[^/]+\.css$/.test(e))){let e=d(i,e=>e.endsWith(`.css`)).filter(e=>(e.split(`/`).pop()||``).toLowerCase().startsWith(`ssr-index`)).map(e=>`/assets${e.substring(i.length).replaceAll(`\\`,`/`)}`);o.push(...e)}console.log(`[patch] Found ${o.length} CSS files in ${i}`);let c=a(e,`utf-8`);for(let{re:t,hrefRe:n,q:r}of[{re:/css:\[(\{href:`[^`]+`\}(?:,\{href:`[^`]+`\})*)\]/,hrefRe:/href:`([^`]+)`/g,q:"`"},{re:/css:\[(\{href:"[^"]+"\}(?:,\{href:"[^"]+"\})*)\]/,hrefRe:/href:"([^"]+)"/g,q:`"`}]){let i=t.exec(c);if(!i)continue;let a=new Set([...i[1].matchAll(n)].map(e=>e[1])),l=o.filter(e=>!a.has(e));if(l.length===0){console.log(`[patch] All CSS already included`);return}let u=l.map(e=>`{href:${r}${e}${r}}`).join(`,`);c=c.replace(i[0],`css:[${i[1]},${u}]`),s(e,c),console.log(`[patch] ✅ Added ${l.length} CSS files to SSR bundle`);return}console.warn(`[patch] Could not find CSS array in SSR bundle`)}function g(e,t){let o=l(t,`assets`);if(n(o)&&i(o).some(e=>e.startsWith(`entry-client`)&&e.endsWith(`.css`))){console.log(`[ssr-css] Skipped — client build already includes entry-client CSS`);return}let c=[l(e,`node_modules`,`.nitro`,`vite`,`services`,`ssr`,`assets`)];for(let o of c){if(!n(o))continue;let c=i(o).filter(e=>e.endsWith(`.css`));if(c.length===0)continue;let u=[l(t,`assets`),l(e,`.output`,`public`,`assets`),l(e,`.netlify`,`functions-internal`,`server`,`public`,`assets`)];for(let e of u){r(e,{recursive:!0});for(let t of c){let n=a(l(o,t),`utf-8`);n=m(n),s(l(e,`ssr-${t}`),n)}}let d=`ssr-${c[0]}`,f=l(u.find(e=>n(e))||u[0],d),p=n(f)?a(f).length:0;console.log(`[ssr-css] Copied SSR CSS → /assets/${d} (${p} bytes, minified)`);let h=[l(e,`.output`,`server`,`index.mjs`),l(e,`.netlify`,`functions-internal`,`server`,`main.mjs`)];for(let e of h){if(!n(e))continue;let t=a(e,`utf-8`),r=`/assets/${d}`;if(t.includes(r))continue;let i=/"\/assets\/[^"]+\.css":\{type:`text\/css[^}]+\}/.exec(t);if(i){let n=new Date().toISOString(),a=`,"${r}":{type:\`text/css; charset=utf-8\`,etag:\`${`"${p.toString(16)}-ssr"`}\`,mtime:\`${n}\`,size:${p},path:\`../public/assets/${d}\`}`;t=t.replace(i[0],i[0]+a),s(e,t),console.log(`[ssr-css] ✅ Patched asset manifest in ${e}`)}}return}console.log(`[ssr-css] No SSR CSS files found`)}async function _(e,t){let r=l(t,`islands`);if(!n(r)){console.log(`[islands] No islands directory found, skipping isolation`);return}let i=d(r,e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));if(!i.some(e=>{let t=a(e,`utf-8`);return t.includes(`from"../`)||t.includes(`from'../`)})){console.log(`[islands] All islands are self-contained`);return}try{let{buildIsolatedIslands:n}=await import(`./isolated-island-builder.js`),r=new Map;for(let e of i){let n=u(t,e).replaceAll(`\\`,`/`).replace(/^islands\//,``).replace(/\.js$/,``),i=a(e,`utf-8`),o=`preact`;i.includes(`solid`)||i.includes(`createSignal`)?o=`solid`:i.includes(`vue`)||i.includes(`createApp`)?o=`vue`:i.includes(`svelte`)&&(o=`svelte`);let s=/from["']([^"']+\.(tsx|jsx|vue|svelte))["']/i.exec(i),c=s?s[1]:`src/islands/${n}.tsx`;r.set(n,{filePath:c,bundleKey:n,framework:o})}await n(e,t,r,[],{})}catch{console.warn(`[islands] Isolated rebuild failed, falling back to inline-islands`);try{let{inlineIslandChunks:e}=await import(`./inline-islands.js`);await e(t,{verbose:!0})}catch(e){console.error(`[islands] Inline fallback also failed:`,e)}}}function v(e,r){let i=l(r,`islands`);if(!n(i))return;let a=[l(e,`.output`,`public`),l(e,`.netlify`,`functions-internal`,`server`,`public`)];for(let e of a)n(e)&&t(i,l(e,`islands`),{recursive:!0,force:!0});console.log(`[islands] Synced isolated islands to output directories`)}function y(e){let t=l(e,`islands`);if(!n(t))return;let r=d(t,e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));if(r.length===0)return;let i=[];for(let t of r){let n=t.substring(e.length).replaceAll(`\\`,`/`);i.push(`${n} ${n} 200`)}let o=l(e,`_redirects`),c=n(o)?a(o,`utf-8`):``;s(o,c?`${c}\n${i.join(`
2
+ `)}`:i.join(`
3
+ `)),console.log(`[redirects] Generated ${i.length} island redirect(s)`)}function b(e,a){let o=l(e,`node_modules`,`@useavalon`);if(!n(o))return;let s=[l(a,`adapters`),l(e,`.output`,`public`,`adapters`),l(e,`.netlify`,`functions-internal`,`server`,`public`,`adapters`)];for(let e of s){if(!n(c(e)))continue;let a=i(o).map(e=>l(o,e,`client`)).filter(e=>n(e));for(let n of a){let i=l(e,n.split(`/`).at(-2)||``);r(i,{recursive:!0}),t(n,i,{recursive:!0,force:!0})}}console.log(`[adapters] Copied framework adapters to output directories`)}function x(e){let i=l(e,`.netlify`,`functions-internal`),a=l(e,`.netlify`,`v1`,`functions`);n(i)&&(r(a,{recursive:!0}),t(i,a,{recursive:!0,force:!0}),console.log(`[netlify] Copied server function to v1 API paths`))}function S(e){if(!n(e))return!1;let t=a(e,`utf-8`);return t.includes(`netlify`)||t.includes(`lambda`)}function C(e,t,n){let r=l(c(e),`_prerender-server.mjs`);return s(r,`
6
4
  import { createServer } from 'node:http';
7
- import handler from './main.mjs';
8
- const PORT = ${t};
5
+ import { handler } from './main.mjs';
6
+
9
7
  const server = createServer(async (req, res) => {
8
+ const url = new URL(req.url, 'http://localhost:${t}');
9
+ const event = { rawUrl: url.href, path: url.pathname, httpMethod: req.method, headers: Object.fromEntries(Object.entries(req.headers)), body: null, isBase64Encoded: false };
10
10
  try {
11
- const url = new URL(req.url, 'http://localhost:' + PORT);
12
- const headers = new Headers();
13
- for (const [key, value] of Object.entries(req.headers)) {
14
- if (value) headers.set(key, Array.isArray(value) ? value.join(', ') : value);
15
- }
16
- const request = new Request(url.toString(), { method: req.method, headers });
17
- const response = await handler(request);
18
- res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
19
- const body = await response.text();
20
- res.end(body);
11
+ const result = await handler(event, {});
12
+ res.writeHead(result.statusCode || 200, result.headers || {});
13
+ res.end(result.body || '');
21
14
  } catch (err) {
22
- console.error('[prerender-wrapper] Error:', err);
23
15
  res.writeHead(500);
24
16
  res.end('Internal Server Error');
25
17
  }
26
18
  });
27
- server.listen(PORT, '127.0.0.1', () => {
28
- console.log('[prerender-wrapper] Listening on http://127.0.0.1:' + PORT);
29
- });
30
- `),i}function w(e){let t=[],n=/<a\s[^>]*href=["']([^"'#?]+)/gi,r=null;for(r=n.exec(e);r!==null;r=n.exec(e)){let e=r[1];e.startsWith(`/`)&&!e.startsWith(`//`)&&!e.startsWith(`/assets/`)&&!e.startsWith(`/islands/`)&&!e.startsWith(`/chunks/`)&&!e.startsWith(`/_`)&&!e.match(/\.\w{2,5}$/)&&t.push(e)}return[...new Set(t)]}async function T(t,i,d,f){let p=[l(t,`.netlify`,`functions-internal`,`server`,`server.mjs`),l(t,`.netlify`,`v1`,`functions`,`server`,`server.mjs`),l(t,`.output`,`server`,`index.mjs`)].find(e=>n(e));if(!p){console.log(`[prerender] No server entry found, skipping prerender`);return}let m=[l(t,`.output`,`public`),i].find(e=>n(e));if(!m){console.log(`[prerender] No output directory found, skipping prerender`);return}let h={routes:d.routes??[`/`],crawlLinks:d.crawlLinks??!0,ignore:d.ignore??[],failOnError:d.failOnError??!1,concurrency:d.concurrency??4,autoSubfolderIndex:d.autoSubfolderIndex??!0,retry:d.retry??3,retryDelay:d.retryDelay??500},g=`http://localhost:${f}`,_=S(p),v=p;if(_){let e=l(c(p),`main.mjs`);if(!n(e)){console.error(`[prerender] Netlify handler detected but main.mjs not found`);return}v=C(e,f,t),console.log(`[prerender] Netlify handler detected — using wrapper`)}{let e=[p,l(c(p),`main.mjs`)].filter(e=>n(e));for(let n of e){let e=a(n,`utf-8`),r=/"\/[^"]*\.html":\{[^}]+\},?/g,i=e.length;e=e.replaceAll(r,``),i!==e.length&&(s(n,e),console.log(`[prerender] Patched ${u(t,n)}: removed HTML asset entries`))}}console.log(`[prerender] Starting prerender with server: ${u(t,v)}`);let{spawn:y}=await import(`node:child_process`),b;try{b=y(`node`,[v],{env:{...process.env,PORT:String(f),NITRO_PORT:String(f),HOST:`127.0.0.1`,NITRO_HOST:`127.0.0.1`,NODE_ENV:`production`},stdio:[`ignore`,`pipe`,`pipe`]}),b.stdout?.on(`data`,e=>{let t=e.toString().trim();t&&console.log(`[prerender:server] ${t}`)}),b.stderr?.on(`data`,e=>{let t=e.toString().trim();t&&console.error(`[prerender:server:err] ${t}`)});let e=Date.now(),t=!1;for(;Date.now()-e<15e3;){try{let e=await fetch(`${g}/`);if(e.ok||e.status<500){t=!0;break}}catch{}await new Promise(e=>setTimeout(e,200))}if(!t)throw Error(`Server did not become ready within 15s`);console.log(`[prerender] Server ready at ${g}`)}catch(e){b?.kill(`SIGKILL`),console.error(`[prerender] Failed to start server:`,e.message);return}let x=new Set,T=[...h.routes],E=[],D=[];function O(e){for(let t of h.ignore)if(typeof t==`string`&&e===t||typeof t==`string`&&t.endsWith(`/**`)&&e.startsWith(t.slice(0,-2)))return!0;return!1}try{for(;T.length>0;){let e=T.splice(0,h.concurrency);await Promise.all(e.map(async e=>{let t=e.endsWith(`/`)&&e!==`/`?e.slice(0,-1):e;if(x.has(t)||(x.add(t),O(t)))return;let n=null;for(let e=1;e<=h.retry;e++)try{let e=await fetch(`${g}${t}`);n={html:await e.text(),status:e.status};break}catch{e<h.retry&&await new Promise(e=>setTimeout(e,h.retryDelay))}if(!n){D.push({route:t,error:`Failed after ${h.retry} attempts`});return}if(n.status>=400){D.push({route:t,error:`Returned ${n.status}`});return}let i=h.autoSubfolderIndex?l(t,`index.html`):`${t}.html`,a=l(m,i);r(c(a),{recursive:!0});let o=n.html.replace(`<!DOCTYPE html>`,`<!DOCTYPE html>
19
+ server.listen(${t}, '127.0.0.1', () => console.log('Listening on http://127.0.0.1:${t}'));
20
+ `),r}function w(e){let t=/<a\s+[^>]*href=["']([^"']+)["'][^>]*>/gi,n=[],r;for(r=t.exec(e);r!==null;r=t.exec(e)){let e=r[1];e.startsWith(`/`)&&!e.startsWith(`//`)&&!e.includes(`.`)&&n.push(e)}return n}async function T(t,i,d,f){let p=[l(t,`.netlify`,`functions-internal`,`server`,`server.mjs`),l(t,`.netlify`,`v1`,`functions`,`server`,`server.mjs`),l(t,`.output`,`server`,`index.mjs`)].find(e=>n(e));if(!p){console.log(`[prerender] No server entry found, skipping prerender`);return}let m=[l(t,`.output`,`public`),i].find(e=>n(e));if(!m){console.log(`[prerender] No output directory found, skipping prerender`);return}let h={routes:d.routes??[`/`],crawlLinks:d.crawlLinks??!0,ignore:d.ignore??[],failOnError:d.failOnError??!1,concurrency:d.concurrency??4,autoSubfolderIndex:d.autoSubfolderIndex??!0,retry:d.retry??3,retryDelay:d.retryDelay??500},g=`http://localhost:${f}`,_=S(p),v=p;if(_){let e=l(c(p),`main.mjs`);if(!n(e)){console.error(`[prerender] Netlify handler detected but main.mjs not found`);return}v=C(e,f,t),console.log(`[prerender] Netlify handler detected — using wrapper`)}{let e=[p,l(c(p),`main.mjs`)].filter(e=>n(e));for(let n of e){let e=a(n,`utf-8`),r=/"\/[^"]*\.html":\{[^}]+\},?/g,i=e.length;e=e.replaceAll(r,``),i!==e.length&&(s(n,e),console.log(`[prerender] Patched ${u(t,n)}: removed HTML asset entries`))}}console.log(`[prerender] Starting prerender with server: ${u(t,v)}`);let{spawn:y}=await import(`node:child_process`),b;try{b=y(`node`,[v],{env:{...process.env,PORT:String(f),NITRO_PORT:String(f),HOST:`127.0.0.1`,NITRO_HOST:`127.0.0.1`,NODE_ENV:`production`},stdio:[`ignore`,`pipe`,`pipe`]}),b.stdout?.on(`data`,e=>{let t=e.toString().trim();t&&console.log(`[prerender:server] ${t}`)}),b.stderr?.on(`data`,e=>{let t=e.toString().trim();t&&console.error(`[prerender:server:err] ${t}`)});let e=Date.now(),t=!1;for(;Date.now()-e<15e3;){try{let e=await fetch(`${g}/`);if(e.ok||e.status<500){t=!0;break}}catch{}await new Promise(e=>setTimeout(e,200))}if(!t)throw Error(`Server did not become ready within 15s`);console.log(`[prerender] Server ready at ${g}`)}catch(e){b?.kill(`SIGKILL`),console.error(`[prerender] Failed to start server:`,e.message);return}let x=new Set,T=[...h.routes],E=[],D=[];function O(e){for(let t of h.ignore)if(typeof t==`string`&&e===t||typeof t==`string`&&t.endsWith(`/**`)&&e.startsWith(t.slice(0,-2)))return!0;return!1}try{for(;T.length>0;){let e=T.splice(0,h.concurrency);await Promise.all(e.map(async e=>{let t=e.endsWith(`/`)&&e!==`/`?e.slice(0,-1):e;if(x.has(t)||(x.add(t),O(t)))return;let n=null;for(let e=1;e<=h.retry;e++)try{let e=await fetch(`${g}${t}`);n={html:await e.text(),status:e.status};break}catch{e<h.retry&&await new Promise(e=>setTimeout(e,h.retryDelay))}if(!n){D.push({route:t,error:`Failed after ${h.retry} attempts`});return}if(n.status>=400){D.push({route:t,error:`Returned ${n.status}`});return}let i=h.autoSubfolderIndex?l(t,`index.html`):`${t}.html`,a=l(m,i);r(c(a),{recursive:!0});let o=n.html.replace(`<!DOCTYPE html>`,`<!DOCTYPE html>
31
21
  <!-- SSG: prerendered at build time -->`).replaceAll(/<link rel="stylesheet" href="\/assets\/[^"]*\.css">\n?/g,e=>e.includes(`_isolated-island-entry`)?``:e);if(o=o.replaceAll(/<script type="module" src="\/assets\/entry-client[^"]*\.js"><\/script>\n?/g,``),o=o.replaceAll(/<link rel="stylesheet" href="\/assets\/entry-client[^"]*\.css">\n?/g,``),o=o.replaceAll(/<link rel="modulepreload" href="\/assets\/entry-client[^"]*\.js">\n?/g,``),s(a,o),E.push(t),console.log(`[prerender] ✅ ${t} → ${i}`),h.crawlLinks)for(let e of w(n.html)){let t=e.endsWith(`/`)&&e!==`/`?e.slice(0,-1):e;!x.has(t)&&!O(t)&&T.push(t)}}))}}finally{console.log(`[prerender] Shutting down server...`),b?.kill(`SIGKILL`)}if(console.log(`[prerender] Done: ${E.length} page(s) prerendered`+(D.length>0?`, ${D.length} error(s)`:``)),_){let e=l(c(p),`_prerender-server.mjs`);n(e)&&(o(e),console.log(`[prerender] Cleaned up wrapper script`))}if(E.length>0){let a=[i,l(t,`.netlify`,`functions-internal`,`server`,`public`),l(t,`.netlify`,`v1`,`functions`,`server`,`public`)].filter(e=>e!==m&&n(c(e)));for(let t of a)for(let i of E){let a=l(i,`index.html`),o=l(m,a),s=l(t,a);n(o)&&(r(c(s),{recursive:!0}),e(o,s))}a.length>0&&console.log(`[prerender] Copied prerendered HTML to ${a.length} additional output dir(s)`)}}function E(e,t){let r={},i=l(t,`island-deps.json`);if(n(i))try{r=JSON.parse(a(i,`utf-8`))}catch{}let o=l(e,`.output`,`public`);if(Object.keys(r).length===0&&n(o)){let e=d(l(o,`islands`),e=>e.endsWith(`.js`)&&!e.endsWith(`.js.map`));for(let t of e){let e=`/${t.substring(o.length+1).replaceAll(`\\`,`/`)}`,n=a(t,`utf-8`),i=/\bfrom\s*["']([^"']+)["']|import\s*["']([^"']+)["']/g,s=[],u;for(u=i.exec(n);u!==null;u=i.exec(n)){let t=u[1]||u[2];if(t&&(t.includes(`/assets/`)||t.startsWith(`.`))){let n=(t.startsWith(`.`)?`/${l(c(e.slice(1)),t).replaceAll(`\\`,`/`).replace(/^\/+/,``)}`:t).split(`/`).filter(Boolean),r=[];for(let e of n)e===`..`?r.pop():e!==`.`&&r.push(e);s.push(`/${r.join(`/`)}`)}}s.length>0&&(r[e]=s)}}if(Object.keys(r).length===0)return;let u=[l(e,`.output`,`public`),t],f=0;for(let e of u){if(!n(e))continue;let t=d(e,e=>e===`index.html`);for(let e of t){let t=a(e,`utf-8`),n=new Set;for(let[e,i]of Object.entries(r))if(t.includes(e))for(let e of i)t.includes(`href="${e}"`)||n.add(e);if(n.size===0)continue;let i=Array.from(n).map(e=>`<link rel="modulepreload" href="${e}">`).join(`
32
- `);t.includes(`</head>`)&&(t=t.replace(`</head>`,`${i}\n</head>`),s(e,t),f++)}}f>0&&console.log(`[modulepreload] ✅ Injected dependency preloads into ${f} HTML file(s)`)}async function D(e){let{promisify:t}=await import(`node:util`),r=await import(`node:zlib`),i=t(r.brotliCompress),o=t(r.gzip),c=[l(e,`.output`,`public`),l(e,`.netlify`,`functions-internal`,`server`,`public`)],u=e=>e.endsWith(`.js`)||e.endsWith(`.css`)||e.endsWith(`.html`)||e.endsWith(`.svg`)||e.endsWith(`.txt`)||e.endsWith(`.xml`)||e.endsWith(`.json`),f=0;for(let e of c){if(!n(e))continue;let t=d(e,e=>u(e)&&!e.endsWith(`.map`));for(let e of t){let t=a(e);if(!(t.length<256))try{let[n,a]=await Promise.all([i(t,{params:{[r.constants.BROTLI_PARAM_QUALITY]:11}}),o(t,{level:9})]);s(`${e}.br`,n),s(`${e}.gz`,a),f++}catch{}}}f>0&&console.log(`[compress] Compressed ${f} public asset(s) (brotli + gzip)`)}export async function runPostBuild(e={}){let t=e.cwd??process.cwd(),r=l(t,`dist`),i=e.prerenderPort??13172;p(t),g(t,r);for(let e of[l(t,`.netlify`,`functions-internal`,`server`,`_ssr`,`ssr.mjs`),l(t,`.netlify`,`v1`,`functions`,`server`,`_ssr`,`ssr.mjs`),l(t,`.output`,`server`,`_ssr`,`ssr.mjs`)])n(e)&&(console.log(`[patch] Patching ${e}`),m(e,r,t));await _(t,r),v(t,r),y(r),b(t,r),x(t),e.prerender!==!1&&await T(t,r,e.prerender??{},i),E(t,r),await D(t),console.log(`[post-build] ✅ Complete`)}
22
+ `);t.includes(`</head>`)&&(t=t.replace(`</head>`,`${i}\n</head>`),s(e,t),f++)}}f>0&&console.log(`[modulepreload] ✅ Injected dependency preloads into ${f} HTML file(s)`)}const D=[/syntax-highlight/i,/hljs/i,/prism/i,/highlight\.js/i];function O(e,t){let r=[l(e,`.output`,`public`),t],i=A(r),o=0;for(let e of r){if(!n(e))continue;let t=d(e,e=>e===`index.html`);for(let e of t){let t=a(e,`utf-8`),n=t;t=j(t,i),t=k(t),t=M(t),t=N(t),t!==n&&(s(e,t),o++)}}o>0&&console.log(`[post-build] Optimized ${o} HTML file(s) deferred non-critical CSS, added font preload hints`)}function k(e){if(!e.includes(`</head>`)||!e.includes(`<body`))return e;let t=e.indexOf(`</head>`),n=e.indexOf(`<body`);if(t===-1||n===-1||n<t)return e;let r=e.substring(n),i=new Set,a=[],o=``,s=0,c=0;for(;c<r.length;){if(r[c]===`<`){if(r.startsWith(`<template`,c)){s++;let e=r.indexOf(`>`,c);if(e===-1)break;o+=r.substring(c,e+1),c=e+1;continue}if(r.startsWith(`</template>`,c)){s=Math.max(0,s-1),o+=`</template>`,c+=11;continue}if(s===0&&r.startsWith(`<style`,c)){let e=r.indexOf(`</style>`,c);if(e===-1)break;let t=r.substring(c,e+8),n=/<style[^>]*>([\s\S]*?)<\/style>/.exec(t);if(n){let e=n[1].replaceAll(/\s+/g,` `).trim();e&&!i.has(e)&&(i.add(e),a.push(`<style>${e}</style>`))}c=e+8;continue}}o+=r[c],c++}return a.length===0?e:`${e.substring(0,t)}\n${a.join(`
23
+ `)}\n</head>${o}`}function A(e){let t=new Map;for(let r of e){let e=l(r,`assets`);if(n(e))for(let n of i(e))n.endsWith(`.css`)&&t.set(`/assets/${n}`,a(l(e,n),`utf-8`))}return t}function j(e,t){let n=/<link\s+rel="stylesheet"\s+href="(\/assets\/(?:ssr-)?index-[^"]+\.css)">/i.exec(e);if(!n)return e;let r=n[1],i=t.get(r);if(!i)return e;if(Buffer.byteLength(i,`utf-8`)<=14336){let t=`<style data-inlined-from="${r}">${i}</style>`;return e.replace(n[0],t)}let a=`<link rel="preload" href="${r}" as="style">`;return e.includes(`</title>`)&&!e.includes(`preload" href="${r}"`)&&(e=e.replace(`</title>`,`</title>\n${a}`)),e}function M(e){return e.replaceAll(/<link\s+([^>]*rel=["']stylesheet["'][^>]*)>/gi,(e,t)=>{if(/\bmedia\s*=/i.test(t)||/data-critical/i.test(t))return e;let n=/href=["']([^"']+)["']/i.exec(t);if(!n)return e;let r=n[1],i=r.startsWith(`https://`)||r.startsWith(`http://`),a=!i&&D.some(e=>e.test(r));return!i&&!a?e:`<link ${t} media="print" onload="this.media='all'">\n<noscript><link ${t}></noscript>`})}function N(e){let t=/href=["'](https:\/\/fonts\.googleapis\.com\/css2[^"']+)["']/gi,n=new Set,r;for(r=t.exec(e);r!==null;r=t.exec(e))n.add(r[1]);if(n.size===0)return e;let i=[];for(let t of n){let n=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`);new RegExp(String.raw`<link\s+[^>]*rel=["']preload["'][^>]*href=["']${n}["'][^>]*>`,`i`).test(e)||i.push(`<link rel="preload" href="${t}" as="style">`)}if(i.length===0)return e;let a=i.join(`
24
+ `);return e.includes(`</title>`)?e.replace(`</title>`,`</title>\n${a}`):e}async function P(e){let{promisify:t}=await import(`node:util`),r=await import(`node:zlib`),i=t(r.brotliCompress),o=t(r.gzip),c=[l(e,`.output`,`public`),l(e,`.netlify`,`functions-internal`,`server`,`public`)],u=e=>e.endsWith(`.js`)||e.endsWith(`.css`)||e.endsWith(`.html`)||e.endsWith(`.svg`)||e.endsWith(`.txt`)||e.endsWith(`.xml`)||e.endsWith(`.json`),f=0;for(let e of c){if(!n(e))continue;let t=d(e,e=>u(e)&&!e.endsWith(`.map`));for(let e of t){let t=a(e);if(!(t.length<256))try{let[n,a]=await Promise.all([i(t,{params:{[r.constants.BROTLI_PARAM_QUALITY]:11}}),o(t,{level:9})]);s(`${e}.br`,n),s(`${e}.gz`,a),f++}catch{}}}f>0&&console.log(`[compress] ✅ Compressed ${f} public asset(s) (brotli + gzip)`)}function F(e){let t=[l(e,`.output`,`server`,`index.mjs`),l(e,`.netlify`,`functions-internal`,`server`,`index.mjs`)],r=l(e,`.output`,`public`);if(!n(r))return;let i=I(r);if(i.length===0)return;let a=0;for(let e of t)L(e,i,r)&&a++;a>0&&console.log(`[manifest] ✅ Registered ${i.length} prerendered HTML file(s) in Nitro asset manifest`)}function I(e){let t=d(e,e=>e===`index.html`||e===`index.html.br`||e===`index.html.gz`||e===`index.html.zst`),n=[],r=new Date().toISOString();for(let i of t){let t=`/${i.substring(e.length+1).replaceAll(`\\`,`/`)}`,o=a(i).length,s=`"${o.toString(16)}-prerender"`,c=``;t.endsWith(`.br`)?c=`br`:t.endsWith(`.gz`)?c=`gzip`:t.endsWith(`.zst`)&&(c=`zstd`);let l=`"${t}":{type:\`text/html; charset=utf-8\``;c&&(l+=`,encoding:\`${c}\``),l+=`,etag:\`${s}\`,mtime:\`${r}\`,size:${o},path:\`../public${t}\`}`,n.push(l)}return n}function L(e,t,r){if(!n(e))return!1;let i=a(e,`utf-8`),o=/("\/favicon\.ico":\{[^}]+\})/.exec(i);if(!o)return!1;let c=t.filter(e=>{let t=/^"([^"]+)"/.exec(e);return t&&!i.includes(`"${t[1]}":{`)});c.length>0&&(i=i.replace(o[0],`${o[0]},${c.join(`,`)}`));let l=R(r),u="u===`/favicon.ico`&&d.unshift({data:e})";for(let e of l){if(i.includes(`route:\`${e}\``))continue;let t=`[{name:\`headers\`,route:\`${e}\`,handler:x,options:{"Cache-Control":\`public, max-age=0, must-revalidate\`}}]`;i=i.replace(u,`${u};u===\`${e}\`&&d.unshift({data:${t}})`)}return s(e,i),c.length>0||l.length>0}function R(e){let t=[];if(!n(e))return t;for(let r of i(e,{withFileTypes:!0}))!r.isDirectory()&&r.name===`index.html`?t.push(`/`):r.isDirectory()&&n(l(e,r.name,`index.html`))&&t.push(`/${r.name}`);return t}export async function runPostBuild(e={}){let t=e.cwd??process.cwd(),r=l(t,`dist`),i=e.prerenderPort??13172;p(t),g(t,r);for(let e of[l(t,`.netlify`,`functions-internal`,`server`,`_ssr`,`ssr.mjs`),l(t,`.netlify`,`v1`,`functions`,`server`,`_ssr`,`ssr.mjs`),l(t,`.output`,`server`,`_ssr`,`ssr.mjs`)])n(e)&&(console.log(`[patch] Patching ${e}`),h(e,r,t));await _(t,r),v(t,r),y(r),b(t,r),x(t),e.prerender!==!1&&await T(t,r,e.prerender??{},i),E(t,r),O(t,r),await P(t),F(t),console.log(`[post-build] ✅ Complete`)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useavalon/avalon",
3
- "version": "0.1.76",
3
+ "version": "0.1.79",
4
4
  "description": "Multi-framework islands architecture for the modern web",
5
5
  "license": "MIT",
6
6
  "type": "module",