@useavalon/avalon 0.1.88 → 0.1.90
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/src/build/integration-bundler-plugin.d.ts +1 -1
- package/dist/src/build/integration-detection-plugin.d.ts +1 -1
- package/dist/src/build/integration-detection-plugin.js +1 -1
- package/dist/src/build/integration-resolver-plugin.d.ts +1 -1
- package/dist/src/build/island-code-splitting.d.ts +1 -1
- package/dist/src/build/island-manifest.d.ts +2 -2
- package/dist/src/build/island-manifest.js +1 -1
- package/dist/src/build/island-types-generator.js +4 -4
- package/dist/src/build/mdx-island-transform.js +1 -1
- package/dist/src/build/mdx-plugin.d.ts +2 -2
- package/dist/src/build/prop-extractors/index.d.ts +3 -3
- package/dist/src/build/prop-extractors/index.js +1 -1
- package/dist/src/build/prop-extractors/lit.js +1 -1
- package/dist/src/build/prop-extractors/svelte.js +1 -1
- package/dist/src/build/sidecar-file-manager.js +1 -1
- package/dist/src/client/adapters/index.d.ts +1 -1
- package/dist/src/client/adapters/index.js +1 -1
- package/dist/src/client/css-hmr-handler.d.ts +2 -2
- package/dist/src/client/framework-adapter.d.ts +2 -2
- package/dist/src/client/hmr-coordinator.d.ts +6 -6
- package/dist/src/client/main.js +1 -1
- package/dist/src/client/types/framework-runtime.d.ts +54 -55
- package/dist/src/client/types/vite-hmr.d.ts +35 -35
- package/dist/src/client/types/vite-virtual-modules.d.ts +56 -28
- package/dist/src/core/components/component-analyzer.d.ts +3 -3
- package/dist/src/core/components/component-analyzer.js +1 -1
- package/dist/src/core/components/component-detection.d.ts +8 -8
- package/dist/src/core/components/component-detection.js +1 -1
- package/dist/src/core/components/enhanced-framework-detector.d.ts +2 -2
- package/dist/src/core/components/enhanced-framework-detector.js +1 -1
- package/dist/src/core/components/framework-registry.d.ts +1 -1
- package/dist/src/core/integrations/index.d.ts +1 -1
- package/dist/src/core/integrations/index.js +1 -1
- package/dist/src/core/integrations/registry.js +1 -1
- package/dist/src/core/layout/enhanced-layout-resolver.d.ts +8 -8
- package/dist/src/core/layout/enhanced-layout-resolver.js +1 -1
- package/dist/src/core/layout/layout-cache-manager.d.ts +1 -1
- package/dist/src/core/layout/layout-composer.d.ts +2 -2
- package/dist/src/core/layout/layout-composer.js +1 -1
- package/dist/src/core/layout/layout-data-loader.d.ts +2 -2
- package/dist/src/core/layout/layout-discovery.d.ts +2 -2
- package/dist/src/core/layout/layout-discovery.js +1 -1
- package/dist/src/core/layout/layout-matcher.d.ts +1 -1
- package/dist/src/core/layout/layout-matcher.js +1 -1
- package/dist/src/core/layout/layout-types.d.ts +3 -3
- package/dist/src/islands/component-analysis.d.ts +4 -4
- package/dist/src/islands/component-analysis.js +1 -1
- package/dist/src/islands/critical-css.js +3 -3
- package/dist/src/islands/css-utils.js +1 -1
- package/dist/src/islands/discovery/index.d.ts +9 -9
- package/dist/src/islands/discovery/index.js +1 -1
- package/dist/src/islands/discovery/registry.d.ts +1 -1
- package/dist/src/islands/discovery/resolver.d.ts +1 -1
- package/dist/src/islands/discovery/resolver.js +2 -2
- package/dist/src/islands/discovery/scanner.d.ts +1 -1
- package/dist/src/islands/discovery/scanner.js +1 -1
- package/dist/src/islands/discovery/validator.d.ts +1 -1
- package/dist/src/islands/discovery/validator.js +9 -9
- package/dist/src/islands/discovery/watcher.d.ts +1 -1
- package/dist/src/islands/discovery/watcher.js +1 -1
- package/dist/src/islands/framework-base-css.d.ts +36 -0
- package/dist/src/islands/framework-base-css.js +1 -0
- package/dist/src/islands/framework-detection.d.ts +3 -3
- package/dist/src/islands/framework-detection.js +1 -1
- package/dist/src/islands/island.js +1 -1
- package/dist/src/islands/per-island-script.js +1 -1
- package/dist/src/islands/universal-head-collector.d.ts +2 -2
- package/dist/src/middleware/discovery.d.ts +1 -1
- package/dist/src/middleware/discovery.js +1 -1
- package/dist/src/middleware/executor.d.ts +2 -2
- package/dist/src/middleware/index.d.ts +3 -3
- package/dist/src/middleware/index.js +1 -1
- package/dist/src/middleware/types.d.ts +2 -2
- package/dist/src/nitro/error-handler.d.ts +2 -2
- package/dist/src/nitro/error-handler.js +2 -2
- package/dist/src/nitro/index.d.ts +8 -8
- package/dist/src/nitro/index.js +1 -1
- package/dist/src/nitro/island-manifest.d.ts +1 -1
- package/dist/src/nitro/island-manifest.js +1 -1
- package/dist/src/nitro/middleware-adapter.d.ts +2 -2
- package/dist/src/nitro/types.d.ts +4 -4
- package/dist/src/render/isolated-ssr-renderer.d.ts +2 -2
- package/dist/src/render/isolated-ssr-renderer.js +1 -1
- package/dist/src/render/ssr.d.ts +5 -5
- package/dist/src/render/ssr.js +4 -4
- package/dist/src/schemas/api.d.ts +1 -1
- package/dist/src/schemas/core.d.ts +1 -1
- package/dist/src/schemas/index.d.ts +8 -8
- package/dist/src/schemas/index.js +1 -1
- package/dist/src/schemas/routing/index.d.ts +1 -1
- package/dist/src/schemas/routing/index.js +1 -1
- package/dist/src/schemas/routing.d.ts +4 -4
- package/dist/src/schemas/routing.js +1 -1
- package/dist/src/types/image.d.ts +38 -38
- package/dist/src/types/island-jsx.d.ts +16 -16
- package/dist/src/types/mdx.d.ts +2 -2
- package/dist/src/types/routing.d.ts +7 -7
- package/dist/src/types/routing.js +1 -1
- package/dist/src/types/virtual-modules.d.ts +1 -1
- package/dist/src/types/vite-env.d.ts +1 -1
- package/dist/src/vite-plugin/auto-discover.js +1 -1
- package/dist/src/vite-plugin/config.d.ts +1 -1
- package/dist/src/vite-plugin/image-optimization.d.ts +2 -2
- package/dist/src/vite-plugin/image-optimization.js +1 -1
- package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -1
- package/dist/src/vite-plugin/module-discovery.js +1 -1
- package/dist/src/vite-plugin/nitro-integration.js +1 -1
- package/dist/src/vite-plugin/plugin.d.ts +2 -2
- package/dist/src/vite-plugin/plugin.js +1 -1
- package/dist/src/vite-plugin/types.d.ts +1 -2
- package/package.json +3 -2
- package/dist/src/client/main-slim.js +0 -1
- package/dist/src/client/strategies.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{closeSync as e,openSync as t,readSync as n}from"node:fs";import{stat as r,readdir as i,readFile as a}from"node:fs/promises";import{resolve as o}from"node:path";const s={".vue":`vue`,".svelte":`svelte`},c=[{pattern:/\.solid\.(tsx|jsx)$/,integration:`solid`},{pattern:/\.react\.(tsx|jsx)$/,integration:`react`},{pattern:/\.lit\.(ts|js)$/,integration:`lit`},{pattern:/\.preact\.(tsx|jsx)$/,integration:`preact`},{pattern:/\.qwik\.(tsx|jsx)$/,integration:`qwik`}],l=[{pattern:/from\s+['"]react['"]/,integration:`react`},{pattern:/@jsxImportSource\s+react/,integration:`react`},{pattern:/from\s+['"]solid-js['"]/,integration:`solid`},{pattern:/@jsxImportSource\s+solid-js/,integration:`solid`},{pattern:/from\s+['"]preact['"]/,integration:`preact`},{pattern:/@jsxImportSource\s+preact/,integration:`preact`},{pattern:/from\s+['"]@builder\.io\/qwik['"]/,integration:`qwik`},{pattern:/@jsxImportSource\s+@builder\.io\/qwik/,integration:`qwik`}],u=`preact`,d=[`.tsx`,`.jsx`,`.ts`,`.js`,`.vue`,`.svelte`];export async function discoverIntegrationsFromFiles(e,t){let n=t?o(t,e):o(e);try{if(!(await r(n)).isDirectory())return new Set}catch{return new Set}let i=new Set;return await f(n,i),i}async function f(e,t){try{let n=await i(e,{withFileTypes:!0});for(let r of n){let n=o(e,r.name);if(r.isDirectory())await f(n,t);else if(r.isFile()){let e=await m(n,r.name);e&&t.add(e)}}}catch(t){(!(t instanceof Error)||t.code!==`EACCES`)&&console.warn(`Warning: Could not scan directory ${e}:`,t)}}function p(r){try{let i=t(r,`r`),a=Buffer.alloc(500);n(i,a,0,500,0),e(i);let o=a.toString(`utf-8`);for(let{pattern:e,integration:t}of l)if(e.test(o))return t}catch{}return u}async function m(e,t){let n=t.toLowerCase();for(let{pattern:e,integration:t}of c)if(e.test(n))return t;for(let[e,t]of Object.entries(s))if(n.endsWith(e))return t;return n.endsWith(`.tsx`)||n.endsWith(`.jsx`)?p(e):(n.endsWith(`.ts`)||n.endsWith(`.js`))&&!n.endsWith(`.d.ts`)&&/^[A-Z]/.test(t)?`lit`:null}export function detectIntegrationFromFileName(e){let t=e.toLowerCase();for(let{pattern:e,integration:n}of c)if(e.test(t))return n;for(let[e,n]of Object.entries(s))if(t.endsWith(e))return n;return t.endsWith(`.tsx`)||t.endsWith(`.jsx`)?u:(t.endsWith(`.ts`)||t.endsWith(`.js`))&&!t.endsWith(`.d.ts`)&&/^[A-Z]/.test(e)?`lit`:null}export function isSupportedExtension(e){return d.includes(e.toLowerCase())}export function getSupportedExtensions(){return d}export async function discoverIntegrationsFromIslandUsage(e,t,n,i){let a=new Set,s=n??process.cwd(),c=[o(s,e),o(s,t)];i&&c.push(o(s,i));for(let e of c)try{(await r(e)).isDirectory()&&await h(e,s,a)}catch{}return a}async function h(e,t,n){try{let r=await i(e,{withFileTypes:!0});for(let i of r){let r=o(e,i.name);i.isDirectory()?await h(r,t,n):i.isFile()&&g(i.name)&&await v(r,t,n)}}catch(e){!(e instanceof Error)||e.code}}function g(e){let t=e.toLowerCase();return t.endsWith(`.tsx`)||t.endsWith(`.jsx`)||t.endsWith(`.mdx`)}const _=[{pattern:/\.qwik\./,integration:`qwik`}];async function v(e,t,n){try{let r=await a(e,`utf-8`),i=y(r),o=b(r);for(let r of o){let a=i.get(r);if(!a)continue;let o=x(a,e,t);if(!o)continue;let s=await S(o);s&&n.add(s)}for(let[,e]of i)for(let{pattern:t,integration:r}of _)t.test(e)&&n.add(r)}catch{}}function y(e){let t=new Map,n=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,r;for(r=n.exec(e);r!==null;r=n.exec(e))t.set(r[1],r[2]);let i=/import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g;for(r=i.exec(e);r!==null;r=i.exec(e)){let e=r[1].split(`,`).map(e=>e.trim()),n=r[2];for(let r of e){let e=r.match(/(\w+)\s+as\s+(\w+)/);e?t.set(e[2],n):r&&t.set(r,n)}}return t}function b(e){let t=new Set,n=/<([A-Z]\w*)\s+[^>]*\bisland\b/g;for(let r=n.exec(e);r!==null;r=n.exec(e))t.add(r[1]);return t}function x(e,t,n){if(e.startsWith(`.`))return o(o(t,`..`),e);for(let{prefix:t,replacement:r}of[{prefix:`@/`,replacement:`src/`},{prefix:`$components/`,replacement:`src/components/`},{prefix:`$islands/`,replacement:`src/islands/`},{prefix:`~/`,replacement:`src/`}])if(e.startsWith(t))return o(n,r,e.slice(t.length));return e.startsWith(`/src/`)?o(n,e.slice(1)):null}async function S(e){for(let t of[``,`.tsx`,`.jsx`,`.ts`,`.js`,`.vue`,`.svelte`]){let n=e+t;try{if((await r(n)).isFile())return m(n,n.split(`/`).pop()||``)}catch{}}return null}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module provides default configuration values and the resolution
|
|
5
5
|
* function that merges user configuration with defaults.
|
|
6
6
|
*/
|
|
7
|
-
import type { AvalonPluginConfig, ResolvedAvalonConfig,
|
|
7
|
+
import type { AvalonPluginConfig, ResolvedAvalonConfig, ResolvedImageConfig, ResolvedMDXConfig } from "./types.ts";
|
|
8
8
|
/**
|
|
9
9
|
* Default MDX configuration values
|
|
10
10
|
*/
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
* <HeroImage alt="Hero" />
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
import type { Plugin } from
|
|
27
|
-
import type { ResolvedImageConfig } from
|
|
26
|
+
import type { Plugin } from "vite";
|
|
27
|
+
import type { ResolvedImageConfig } from "./types.ts";
|
|
28
28
|
/**
|
|
29
29
|
* Creates the vite-imagetools plugin with Avalon's configuration
|
|
30
30
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{join as t}from"node:path";export async function createImagePlugin(
|
|
1
|
+
import{createRequire as e}from"node:module";import{join as t}from"node:path";import{pathToFileURL as n}from"node:url";async function r(){try{return await import(n(e(t(process.cwd(),`package.json`)).resolve(`vite-imagetools`)).href)}catch{return await import(`vite-imagetools`)}}export async function createImagePlugin(e,t){if(!e.enabled)return t&&console.log(` ⏭️ Image optimization disabled`),[];try{let{imagetools:n}=await r();return t&&(console.log(` 🖼️ Image optimization enabled`),console.log(` Format: ${e.defaultFormat}`),console.log(` Quality: ${e.quality}`),console.log(` Widths: ${e.widths.join(`, `)}`)),[n({include:e.include,exclude:e.exclude,removeMetadata:e.removeMetadata,defaultDirectives:t=>{let n=new URLSearchParams;return t.searchParams.has(`format`)||n.set(`format`,e.defaultFormat),t.searchParams.has(`quality`)||n.set(`quality`,String(e.quality)),t.searchParams.has(`jsx`)&&(!t.searchParams.has(`w`)&&!t.searchParams.has(`width`)&&n.set(`w`,e.widths.join(`;`)),n.set(`as`,`picture`)),n}})]}catch(e){let t=e instanceof Error?e.message:String(e);if(t.includes(`Cannot find package`)||t.includes(`MODULE_NOT_FOUND`))return console.warn(`⚠️ Avalon: Image optimization is enabled but vite-imagetools is not installed.
|
|
2
2
|
Install it with: bun add -d vite-imagetools
|
|
3
3
|
Or disable image optimization: image: false`),[];throw e}}export const IMAGE_TYPES_DECLARATION=`
|
|
4
4
|
declare module '*.jpg' {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{access as e,readFile as t}from"node:fs/promises";import n from"node:path";import{EXTRACTOR_MAP as r}from"../build/prop-extractors/index.js";import{deleteSidecar as i,getSidecarPath as a,isSidecarFresh as o,writeSidecarIfChanged as s}from"../build/sidecar-file-manager.js";import{renderSidecarContent as c}from"../build/sidecar-renderer.js";import{detectFrameworkFromPath as l}from"../islands/integration-loader.js";const u=new Set([`react`,`preact`]),d=[`.vue`,`.svelte`,`.lit.ts`,`.solid.tsx`,`.qwik.tsx`];export async function checkTsConfigForArbitraryExtensions(e){let r=n.join(e,`tsconfig.json`);try{let e=await t(r,`utf-8`);JSON.parse(e)?.compilerOptions?.allowArbitraryExtensions!==!0&&console.warn(`[avalon] tsconfig.json is missing "allowArbitraryExtensions: true" — sidecar .d.[ext].ts files require this setting`)}catch{}}function f(e){let t=n.basename(e);return/\.d\.(vue|svelte|lit|solid\.tsx)/.test(t)}function p(e){return f(e)?!1:d.some(t=>e.endsWith(t))}async function m(e,n){try{let n=l(e);if(u.has(n))return!1;let i=r[n];if(!i)return!1;let o=c(i(await t(e,`utf-8`)).propsType);return await s(a(e),o)}catch(t){return n&&console.warn(`[avalon] Failed to generate sidecar for ${e}:`,t instanceof Error?t.message:t),!1}}export function islandSidecarPlugin(t={}){let n,r=new Set;return{name:`avalon:island-sidecar`,configResolved(e){n=e.root},async buildStart(){await checkTsConfigForArbitraryExtensions(n),r.clear()},async load(e){return!p(e)||r.has(e)||(r.add(e),await o(e,a(e)))||await m(e,t.verbose)&&t.verbose&&console.log(`[avalon] Generated sidecar for: ${e}`),null},async handleHotUpdate(n){let o=n.file;if(!p(o))return;let s=!0;try{await e(o)}catch{s=!1}if(!s){await i(a(o))&&t.verbose&&console.log(`[avalon] Deleted sidecar for removed file: ${o}`),r.delete(o);return}r.delete(o),await m(o,t.verbose)&&t.verbose&&console.log(`[avalon] Updated sidecar for: ${o}`)}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readdir as e,stat as t}from"node:fs/promises";import{
|
|
1
|
+
import{readdir as e,stat as t}from"node:fs/promises";import{join as n,resolve as r}from"node:path";export async function discoverModules(t,i){let s=r(i,t.dir),c=[],l=[],u=[];try{let r=await e(s,{withFileTypes:!0});for(let e of r){if(!e.isDirectory()||e.name.startsWith(`.`)||e.name===`node_modules`)continue;let r=n(s,e.name),i=n(r,t.pagesDirName),d=n(r,t.layoutsDirName),[f,p]=await Promise.all([o(i),o(d)]),m=a(e.name),h={name:e.name,path:r,pagesDir:f?i:null,layoutsDir:p?d:null,routePrefix:m};c.push(h),f&&l.push({dir:i,prefix:m}),p&&u.push({dir:d,prefix:m})}}catch{}return c.sort((e,t)=>e.routePrefix===`/`?-1:t.routePrefix===`/`?1:e.name.localeCompare(t.name)),{modules:c,pageDirs:l,layoutDirs:u}}function a(e){return[`home`,`root`,`main`,`index`].includes(e.toLowerCase())?`/`:`/`+e}async function o(e){try{return(await t(e)).isDirectory()}catch{return!1}}export async function getAllPageDirs(e,t,n){let a=[],s=r(n,e);if(await o(s)&&a.push({dir:s,prefix:`/`}),t){let{pageDirs:e}=await discoverModules(t,n);a.push(...e)}return a}export async function getAllLayoutDirs(e,t,n){let a=[],s=r(n,e);if(await o(s)&&a.push({dir:s,prefix:`/`}),t){let{layoutDirs:e}=await discoverModules(t,n);a.push(...e)}return a}
|
|
@@ -7,7 +7,7 @@ export default { loadPage, routes: [] };
|
|
|
7
7
|
`}}function R(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
|
|
8
8
|
export default islandManifest;
|
|
9
9
|
`}function z(e,t){let n={avalon:{streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev},...t.runtimeConfig};return`export const runtimeConfig = ${JSON.stringify(n,null,2)};\nexport function useRuntimeConfig() { return runtimeConfig; }\nexport default runtimeConfig;\n`}export function generateConfigModule(e,t){let n=globalThis.__avalonConfig?.isDev??e.isDev,r={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:n,...t.runtimeConfig};return`globalThis.__avalonHydrationMode = "${n?`entry-client`:`per-island`}";\nconst config = ${JSON.stringify(r,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function B(e,t,n){let{getAllLayoutDirs:r}=await import(`./module-discovery.js`),{relative:i,resolve:a}=await import(`node:path`),{stat:s,readFile:c}=await import(`node:fs/promises`),l=process.cwd(),u=await r(e.layoutsDir,e.modules,l),d=[],f=0,p=a(l,e.layoutsDir);for(let{dir:t,prefix:n}of u){let r=o(t,`_layout.tsx`);try{if(!(await s(r)).isFile())continue}catch{continue}let a=i(l,r).replaceAll(`\\`,`/`),c=a.startsWith(`/`)?a:`/${a}`,u=t.startsWith(p),m=u&&!e.modules?`RootLayout`:`Layout_${f}`;d.push({prefix:n,importPath:c,varName:m,isShared:u,filePath:r}),f++}let m=d.filter(e=>e.isShared),h=d.filter(e=>!e.isShared),g=new Map;for(let e of h)try{let t=(await c(e.filePath,`utf8`)).match(/layoutConfig\s*=\s*{[\s\S]*?skipLayouts\s*:\s*\[([^\]]*)\]/)?.[1]??``,n=/['"`]_layout['"`]/.test(t);g.set(e.importPath,n)}catch{g.set(e.importPath,!1)}let _=d.map(e=>`import ${e.varName} from '${e.importPath}';`),v=h.toSorted((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`,n=g.get(e.importPath)??!1,r=t||n;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${r} }`}),y=m.length>0?m[0].varName:`null`,b=JSON.stringify(n);return[`// Auto-generated by Avalon — do not edit`,`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`,`import { getUniversalCSSForHead } from '@useavalon/avalon/islands/universal-css-collector';`,`import { getUniversalHeadForInjection, injectSolidHydrationScriptIfNeeded } from '@useavalon/avalon/islands/universal-head-collector';`,..._,``,`const RootLayoutComponent = ${y};`,`const _cssLinks = ${b};`,``,`const moduleLayouts = [`,v.join(`,
|
|
10
|
-
`),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` // In dev, inject <link> tags for all discovered CSS files.`,` // The ?direct suffix makes Vite return raw CSS (text/css) instead`,` // of a JS module wrapper, so <link rel="stylesheet"> works.`,` if (process.env.NODE_ENV !== 'production' && _cssLinks.length > 0) {`,` var links = _cssLinks.map(function(href) {`,` return '<link rel="stylesheet" href="' + href + '?direct">';`,` }).join('\\n');`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', links + '\\n</head>');`,` }`,` }`,` const universalCSS = getUniversalCSSForHead(true);`,` if (universalCSS && html.includes('</head>')) {`,` html = html.replace('</head>', universalCSS + '\\n</head>');`,` }`,` const universalHead = getUniversalHeadForInjection(true);`,` if (universalHead && html.includes('</head>')) {`,` html = html.replace('</head>', universalHead + '\\n</head>');`,` }`,` html = injectSolidHydrationScriptIfNeeded(html);`,` return html;`,`}`,``,`export async function wrapWithLayouts(pageHtml, pageModule, context, injectAssets) {`,` const pathname = context.url.pathname;`,` const frontmatter = {`,` ...(pageModule.frontmatter || {}),`,` ...(pageModule.metadata || {}),`,` currentPath: pathname,`,` };`,` const pageLayoutConfig = pageModule.layoutConfig;`,` const skipAll = pageLayoutConfig?.skipLayouts?.includes('_layout');`,``,` const layoutEntry = getLayoutsForPath(pathname);`,` const routeInfo = { path: pathname, params: context.params, query: context.url.searchParams };`,` let html;`,``,` if (!layoutEntry || skipAll) {`,` if (RootLayoutComponent && !skipAll) {`,` const rootProps = {`,` children: h('avalon-page', { id: 'app', dangerouslySetInnerHTML: { __html: pageHtml }
|
|
10
|
+
`),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` // In dev, inject <link> tags for all discovered CSS files.`,` // The ?direct suffix makes Vite return raw CSS (text/css) instead`,` // of a JS module wrapper, so <link rel="stylesheet"> works.`,` if (process.env.NODE_ENV !== 'production' && _cssLinks.length > 0) {`,` var links = _cssLinks.map(function(href) {`,` return '<link rel="stylesheet" href="' + href + '?direct">';`,` }).join('\\n');`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', links + '\\n</head>');`,` }`,` }`,` const universalCSS = getUniversalCSSForHead(true);`,` if (universalCSS && html.includes('</head>')) {`,` html = html.replace('</head>', universalCSS + '\\n</head>');`,` }`,` const universalHead = getUniversalHeadForInjection(true);`,` if (universalHead && html.includes('</head>')) {`,` html = html.replace('</head>', universalHead + '\\n</head>');`,` }`,` html = injectSolidHydrationScriptIfNeeded(html);`,` return html;`,`}`,``,`export async function wrapWithLayouts(pageHtml, pageModule, context, injectAssets) {`,` const pathname = context.url.pathname;`,` const frontmatter = {`,` ...(pageModule.frontmatter || {}),`,` ...(pageModule.metadata || {}),`,` currentPath: pathname,`,` };`,` const pageLayoutConfig = pageModule.layoutConfig;`,` const skipAll = pageLayoutConfig?.skipLayouts?.includes('_layout');`,``,` const layoutEntry = getLayoutsForPath(pathname);`,` const routeInfo = { path: pathname, params: context.params, query: context.url.searchParams };`,` let html;`,``,` if (!layoutEntry || skipAll) {`,` if (RootLayoutComponent && !skipAll) {`,` const rootProps = {`,` children: h('avalon-page', { id: 'app', dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` html = '<!DOCTYPE html>\\n' + preactRenderToString(resolvedRoot);`,` } else {`,` // skipAll is true — page provides its own HTML shell or needs a minimal one`,` if (pageHtml.trimStart().startsWith('<html')) {`,` html = '<!DOCTYPE html>\\n' + pageHtml;`,` } else {`,` const title = String(frontmatter.title || 'Avalon');`,` html = [`,` '<!DOCTYPE html>',`,` '<html lang="en">',`,` '<head>',`,` '<meta charset="utf-8">',`,` '<meta name="viewport" content="width=device-width, initial-scale=1">',`,` '<title>' + title + '</title>',`,` '</head>',`,` '<body>',`,` '<div id="app">' + pageHtml + '</div>',`,` '</body>',`,` '</html>',`,` ].join('\\n');`,` }`,` }`,` } else {`,` const layoutProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const layoutResult = layoutEntry.Layout(layoutProps);`,` const resolvedLayout = layoutResult instanceof Promise ? await layoutResult : layoutResult;`,` let wrappedHtml = preactRenderToString(resolvedLayout);`,``,` // If the layout provides its own HTML shell (starts with <html),`,` // skip root wrapping regardless of skipRoot flag — the layout IS the document.`,` const layoutProvidesShell = wrappedHtml.trimStart().startsWith('<html');`,``,` if (!layoutProvidesShell && !layoutEntry.skipRoot && RootLayoutComponent) {`,` const rootProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: wrappedHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` wrappedHtml = preactRenderToString(resolvedRoot);`,` }`,``,` html = '<!DOCTYPE html>\\n' + wrappedHtml;`,` }`,``,` if (injectAssets) {`,` html = injectAssets(html);`,` }`,` return injectUniversalAssets(html);`,`}`,``,`export default { wrapWithLayouts };`,``].join(`
|
|
11
11
|
`)}function V(e){let t=e.clientEntry??`app/entry-client`;return[`// Auto-generated by Avalon — do not edit`,`// @ts-ignore — virtual import resolved by Nitro's Vite assets plugin at build time`,`import clientAssets from '${t.startsWith(`/`)?t:`/${t}`}?assets=client';`,``,`function buildAssetTags() {`,` const cssLinks = (clientAssets?.css ?? [])`,` .filter(attr => {`,` const href = attr.href || '';`,` // The SSR build produces ssr-index-*.css containing all global, reset,`,` // token, and layout CSS module styles. The client build may also emit`,` // entry-client-*.css (a subset) and index-*.css. To avoid duplicates,`,` // prefer ssr-index when it exists; otherwise fall back to the others.`,` var hasSsrIndex = (clientAssets?.css ?? []).some(function(a) { return (a.href || '').includes('ssr-index'); });`,` if (hasSsrIndex) return href.includes('ssr-index');`,` if (href.includes('entry-client') && href.endsWith('.css')) return true;`,` if (/\\/index-[^/]+\\.css$/.test(href)) return true;`,` return false;`,` })`,` .map(attr => '<link rel="stylesheet" href="' + attr.href + '">')`,` .join('\\n');`,` const jsPreloads = (clientAssets?.js ?? [])`,` .map(attr => '<link rel="modulepreload" href="' + attr.href + '">')`,` .join('\\n');`,` const entryScript = clientAssets?.entry`,` ? '<script type="module" src="' + clientAssets.entry + '"><\/script>'`,` : '';`,` return { cssLinks, jsPreloads, entryScript };`,`}`,``,`export function injectAssets(html) {`,` const { cssLinks, jsPreloads, entryScript } = buildAssetTags();`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', cssLinks + '\\n' + jsPreloads + '\\n</head>');`,` }`,` if (html.includes('</body>')) {`,` html = html.replace('</body>', entryScript + '\\n</body>');`,` }`,` return html;`,`}`,``,`export { clientAssets };`,`export default { injectAssets, clientAssets };`,``].join(`
|
|
12
12
|
`)}function H(e){let t=Array.isArray(e.integrations)?e.integrations:[],n=[],r=[];for(let e of t){let t=`${e}Integration`;n.push(`import { ${t} } from '@useavalon/${e}';`),r.push(`registry.register(${t});`)}return[`// Auto-generated by Avalon — do not edit`,`import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,`import { registerBuiltinDirectives } from '@useavalon/avalon';`,`import { registry } from '@useavalon/avalon/islands/integration-registry';`,`import avalonConfig from 'virtual:avalon/config';`,`import { loadPage } from 'virtual:avalon/page-loader';`,`import { wrapWithLayouts } from 'virtual:avalon/layouts';`,`import { injectAssets } from 'virtual:avalon/assets';`,...n,``,`// Pre-register framework integrations for SSR`,...r,``,`// Register built-in custom hydration directives (on:delay, on:scroll, etc.)`,`registerBuiltinDirectives();`,``,`// Set hydration mode flag — intentionally duplicated from virtual:avalon/config`,`// for module-load-order resilience (config import may be tree-shaken or deferred).`,`globalThis.__avalonHydrationMode = avalonConfig.isDev ? "entry-client" : "per-island";`,``,`export default createNitroRenderer({`,` avalonConfig,`,` isDev: avalonConfig.isDev,`,` resolvePageRoute: async (pathname) => {`,` const mod = loadPage(pathname);`,` if (!mod || !('default' in mod)) return null;`,` return { filePath: '[virtual:' + pathname + ']', pattern: pathname, params: {} };`,` },`,` loadPageModule: async (filePath) => {`,` const match = filePath.match(/^\\[virtual:(.+)\\]$/);`,` const pathname = match ? match[1] : filePath;`,` const mod = loadPage(pathname);`,` if (mod) return mod;`,` return { default: () => null, metadata: { title: 'Avalon' } };`,` },`,` wrapWithLayouts: (pageHtml, pageModule, context) =>`,` wrapWithLayouts(pageHtml, pageModule, context, injectAssets),`,`});`,``].join(`
|
|
13
13
|
`)}async function U(e,t){let{getAllLayoutDirs:n}=await import(`./module-discovery.js`),{readdir:r}=await import(`node:fs/promises`),{relative:i,join:a}=await import(`node:path`),o=process.cwd(),s=await n(e.layoutsDir,e.modules,o),c=[];for(let{dir:e}of s)try{let t=await r(e,{withFileTypes:!0});for(let n of t){if(!n.isFile()||!n.name.endsWith(`.css`))continue;let t=i(o,a(e,n.name)).replaceAll(`\\`,`/`),r=t.startsWith(`/`)?t:`/${t}`;c.push(r)}}catch{}let l=globalThis.__avalonConfig?.isDev??e.isDev?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`,u=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`];(globalThis.__avalonHydrationMode??`entry-client`)===`entry-client`?u.push(`import '${l}';`):u.push(`// Per-island hydration mode — no shared runtime needed`),u.push(``);let d=t.globalCSS??[];for(let e of d){let t=e.startsWith(`/`)?e:`/${e}`;u.push(`// Global CSS`),u.push(`import '${t}';`)}if(d.length>0&&u.push(``),c.length>0){u.push(`// Layout CSS (auto-discovered)`);let e=0;for(let t of c)t.includes(`.module.`)?(u.push(`import _lcss${e} from '${t}';`),e++):u.push(`import '${t}';`)}return u.push(``),u.join(`
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* or layouts is automatically treated as an island. No fixed islands directory required.
|
|
11
11
|
*/
|
|
12
12
|
import type { Plugin, PluginOption, ViteDevServer } from "vite";
|
|
13
|
-
import type { AvalonPluginConfig, IntegrationName, ResolvedAvalonConfig } from "./types.ts";
|
|
14
13
|
import type { NitroConfigOutput } from "../nitro/config.ts";
|
|
14
|
+
import type { AvalonPluginConfig, IntegrationName, ResolvedAvalonConfig } from "./types.ts";
|
|
15
15
|
declare global {
|
|
16
16
|
var __avalonConfig: ResolvedAvalonConfig | undefined;
|
|
17
17
|
var __viteDevServer: ViteDevServer | undefined;
|
|
@@ -49,5 +49,5 @@ export declare function getPagesDir(): string;
|
|
|
49
49
|
export declare function getLayoutsDir(): string;
|
|
50
50
|
export declare function getNitroConfig(): NitroConfigOutput | undefined;
|
|
51
51
|
export declare function isNitroEnabled(): boolean;
|
|
52
|
-
export type { AvalonPluginConfig, IntegrationName, ResolvedAvalonConfig, ImageConfig, ResolvedImageConfig, } from "./types.ts";
|
|
53
52
|
export type { AvalonNitroConfig, NitroConfigOutput } from "../nitro/config.ts";
|
|
53
|
+
export type { AvalonPluginConfig, ImageConfig, IntegrationName, ResolvedAvalonConfig, ResolvedImageConfig, } from "./types.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{dirname as t,join as n}from"node:path";import{
|
|
1
|
+
import{createRequire as e}from"node:module";import{dirname as t,join as n}from"node:path";import{islandClientBundlerPlugin as r}from"../build/island-client-bundler.js";import{islandCodeSplittingPlugin as i}from"../build/island-code-splitting.js";import{mdxIslandTransform as a}from"../build/mdx-island-transform.js";import{createMDXPlugin as o}from"../build/mdx-plugin.js";import{pageIslandTransform as s}from"../build/page-island-transform.js";import{registry as c}from"../core/integrations/registry.js";import{discoverIntegrationsFromIslandUsage as l}from"./auto-discover.js";import{checkDirectoriesExist as u,resolveConfig as d}from"./config.js";import{createImagePlugin as f}from"./image-optimization.js";import{activateIntegrations as p,activateSingleIntegration as m}from"./integration-activator.js";import{islandSidecarPlugin as h}from"./island-sidecar-plugin.js";import{createNitroIntegration as g}from"./nitro-integration.js";import{formatValidationResults as _,validateActiveIntegrations as v}from"./validation.js";export async function collectIntegrationPlugins(e,t=!1){let n=[],r=[];for(let i of e){let e=await y(i,t);i===`lit`?r.push(...e):n.push(...e)}return[...r,...n]}async function y(e,t){let n=c.get(e);if(!n||typeof n.vitePlugin!=`function`)return[];try{let e=await n.vitePlugin();return(Array.isArray(e)?e:[e]).filter(e=>e!=null)}catch(t){return console.warn(`[avalon] Failed to load vite plugin for ${e}:`,t instanceof Error?t.message:t),[]}}async function b(e,t){let n=new Set;try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)e.integrations.includes(t)&&n.add(t)}catch{for(let t of e.integrations)n.add(t)}return n}async function x(e){if(!e.lazyIntegrations||e.integrations.length===0)return[...e.integrations];let t=await b(e);return t.size===0?[...e.integrations]:Array.from(t)}async function S(e){try{let t=await o({jsxImportSource:e.mdx.jsxImportSource,syntaxHighlighting:e.mdx.syntaxHighlighting,remarkPlugins:e.mdx.remarkPlugins,rehypePlugins:e.mdx.rehypePlugins,development:!0});return t.push(a({verbose:e.verbose})),t}catch(t){return e.showWarnings&&console.warn(`⚠️ Could not configure MDX plugin:`,t),[]}}function C(e,t,n){let{plugins:r,nitroOptions:i}=g(e,t);return globalThis.__nitroConfig=i,{plugins:r,options:i}}async function w(e,t,n){if(e.autoDiscoverIntegrations)try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)if(!n.has(t))try{await m(t,n,e.verbose)}catch(n){e.showWarnings&&console.warn(` ⚠️ Could not auto-load integration: ${t}`,n)}}catch(t){e.showWarnings&&console.warn(` ⚠️ Auto-discovery failed:`,t)}}function T(e,t){if(!e.validateIntegrations||t.size===0)return;let n=v(t,e.showWarnings);n.allValid||(console.error(_(n)),e.showWarnings&&console.warn(` ⚠️ Some integrations have validation issues.`))}export async function avalon(a){let o,c,l=new Set,m=d(a,!0),g=await x(m);g.length>0&&await p({...m,integrations:g},l);let _=await S(m),v=await f(m.image,m.verbose),y=[];l.size>0&&(y=await collectIntegrationPlugins(l,m.verbose));let b=[];if(a?.nitro){let{plugins:e}=C(m,a.nitro,m.verbose);b=e}let E=h({verbose:m.verbose}),D=e(import.meta.url),O=null;try{O=n(t(D.resolve(`@useavalon/avalon/client`)),`main.js`)}catch{}let k=new Set([`preact`,`react`,`vue`,`svelte`,`solid`,`lit`,`qwik`].flatMap(e=>[`/@useavalon/${e}/client`,`/@useavalon/${e}/client/hmr`,`@useavalon/${e}/client`,`@useavalon/${e}/client/hmr`])),A={name:`avalon`,enforce:`pre`,config(e,{command:t}){let n={preact:[`preact`,`preact/hooks`],react:[`react`,`react-dom`,`react-dom/client`],vue:[`vue`],svelte:[`svelte`,`svelte/internal`],solid:[`solid-js`,`solid-js/web`],lit:[`lit`,`@lit-labs/ssr-client`],qwik:[`@builder.io/qwik`]},r=g.flatMap(e=>n[e]??[]);return{define:{__AVALON_PER_ISLAND__:JSON.stringify(t===`build`)},oxc:{exclude:[/node_modules\/@useavalon\/.*\.tsx?$/]},ssr:{noExternal:[/^@useavalon\//]},optimizeDeps:{exclude:[`@useavalon/avalon`,...g.map(e=>`@useavalon/${e}`)],include:r}}},configResolved(e){c=e,o=d(a,e.command===`serve`),globalThis.__avalonConfig=o,u(o,e.root)},async resolveId(e){if(e===`/src/client/main.js`&&O)return O;if(k.has(e)){let t=e.startsWith(`/`)?e.slice(1):e;return(await this.resolve(t))?.id??null}return null},async transform(e,t){if(t.includes(`@useavalon/`)&&/\.tsx?$/.test(t)){let{transform:n}=await import(`oxc-transform`),r=await n(t,e,{sourcemap:!0,typescript:{onlyRemoveTypeImports:!1}});return{code:r.code,map:r.map,moduleType:`js`}}},async buildStart(){await w(o,c?.root,l),T(o,l)},configureServer(e){globalThis.__viteDevServer=e}},j=y.filter(e=>e.name?.includes(`lit`)),M=y.filter(e=>!e.name?.includes(`lit`));return[s({pagesDir:m.pagesDir,layoutsDir:m.layoutsDir,modules:m.modules,verbose:m.verbose}),r(m,a?.nitro),i(m,a?.nitro),...v,...j,..._,A,E,...b,...M]}export function getResolvedConfig(){return globalThis.__avalonConfig}export function getPagesDir(){return globalThis.__avalonConfig?.pagesDir??`src/pages`}export function getLayoutsDir(){return globalThis.__avalonConfig?.layoutsDir??`src/layouts`}export function getNitroConfig(){return globalThis.__nitroConfig}export function isNitroEnabled(){return globalThis.__nitroConfig!==void 0}
|
|
@@ -277,5 +277,4 @@ export interface ResolvedAvalonConfig {
|
|
|
277
277
|
/**
|
|
278
278
|
* Re-export Nitro configuration types for convenience
|
|
279
279
|
*/
|
|
280
|
-
export type { AvalonNitroConfig } from "../nitro/config.ts";
|
|
281
|
-
export type { CacheOptions, RouteRule, NitroConfigOutput, AvalonRuntimeConfig, StaticAssetsConfig, } from "../nitro/config.ts";
|
|
280
|
+
export type { AvalonNitroConfig, AvalonRuntimeConfig, CacheOptions, NitroConfigOutput, RouteRule, StaticAssetsConfig, } from "../nitro/config.ts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useavalon/avalon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.90",
|
|
4
4
|
"description": "Multi-framework islands architecture for the modern web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
146
|
"dependencies": {
|
|
147
|
-
"@useavalon/core": "^0.1.
|
|
147
|
+
"@useavalon/core": "^0.1.8",
|
|
148
148
|
"@mdx-js/rollup": "^3.0.0",
|
|
149
149
|
"h3": "^2.0.1-rc.16",
|
|
150
150
|
"marked": "^17.0.4",
|
|
@@ -155,6 +155,7 @@
|
|
|
155
155
|
"remark-gfm": "^4.0.0",
|
|
156
156
|
"remark-mdx-frontmatter": "^5.0.0",
|
|
157
157
|
"unified": "^11.0.0",
|
|
158
|
+
"urlpattern-polyfill": "^10.1.0",
|
|
158
159
|
"zod": "^4.3.6"
|
|
159
160
|
}
|
|
160
161
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(()=>{var e=document.querySelectorAll(`[data-framework]`);if(!e.length)return;var t=!1;e.forEach(e=>{var r=e.dataset.framework,i=e.dataset.condition||`on:client`;e.dataset.renderStrategy!==`ssr-only`&&(i===`on:client`?(window.requestIdleCallback||requestAnimationFrame)(()=>{n(e,r)}):t=!0)}),t&&import(`./strategies.js`).then(t=>{e.forEach(e=>{var r=e.dataset.condition||`on:client`;r!==`on:client`&&e.dataset.renderStrategy!==`ssr-only`&&!e.dataset.hydrated&&t.setup(e,e.dataset.framework,r,n)})});async function n(e,t){if(!e.dataset.hydrated){var n=e.dataset.src;if(n)try{var r=e.dataset.props?JSON.parse(e.dataset.props):{},i=await import(`virtual:avalon/integration-loader`);t===`lit`&&await i.preLitHydration();var a=await import(n),o=a.default||Object.values(a).find(e=>typeof e==`function`&&e.prototype)||a,s=await i.loadIntegrationModule(t);s.hydrate&&await s.hydrate(e,o,r),e.dataset.hydrated=`true`}catch(e){console.error(`Hydration error for `+t+` island `+n+`:`,e)}}}})();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function setup(e,t,n,r){if(n===`on:visible`)try{var i=new IntersectionObserver(n=>{n[0].isIntersecting&&(r(e,t),i.disconnect())},{rootMargin:`50px`,threshold:0});i.observe(e)}catch{r(e,t)}else if(n===`on:interaction`){var a=[`click`,`touchstart`,`mouseenter`,`focusin`],o=!1,s=()=>{o||(o=!0,a.forEach(t=>{e.removeEventListener(t,s)}),r(e,t))};a.forEach(t=>{e.addEventListener(t,s,{once:!0,passive:!0})})}else if(n===`on:idle`){var c=()=>{r(e,t)};`requestIdleCallback`in globalThis?globalThis.requestIdleCallback(c,{timeout:5e3}):document.readyState===`complete`?setTimeout(c,200):globalThis.addEventListener(`load`,()=>{setTimeout(c,200)},{once:!0})}else if(n.startsWith(`media:`)){var l=n.slice(6);try{var u=globalThis.matchMedia(l);u.matches?r(e,t):u.addEventListener(`change`,function n(i){i.matches&&(r(e,t),u.removeEventListener(`change`,n))})}catch{r(e,t)}}else e.dataset.customDirective?import(`./custom-directives.js`).then(i=>{i.hasClientDirective&&i.hasClientDirective(n)?i.executeCustomDirective(e,n,()=>{r(e,t)}):r(e,t)}).catch(()=>{r(e,t)}):r(e,t)}
|