@useavalon/avalon 0.3.2-canary.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/mod.d.ts +1 -1
  2. package/dist/mod.js +1 -1
  3. package/dist/src/build/integration-config.js +1 -1
  4. package/dist/src/build/island-client-bundler.js +1 -1
  5. package/dist/src/build/island-manifest.d.ts +3 -0
  6. package/dist/src/build/island-manifest.js +1 -1
  7. package/dist/src/build/island-ssr-flag.d.ts +14 -0
  8. package/dist/src/build/island-ssr-flag.js +1 -0
  9. package/dist/src/build/mdx-island-transform.js +2 -2
  10. package/dist/src/build/mdx-plugin.js +1 -1
  11. package/dist/src/build/page-island-await.d.ts +18 -0
  12. package/dist/src/build/page-island-await.js +2 -0
  13. package/dist/src/build/page-island-transform.d.ts +3 -1
  14. package/dist/src/build/page-island-transform.js +2 -2
  15. package/dist/src/client/css-hmr-handler.d.ts +7 -90
  16. package/dist/src/client/css-hmr-handler.js +1 -1
  17. package/dist/src/client/custom-directives.js +1 -1
  18. package/dist/src/client/hmr-coordinator.d.ts +0 -1
  19. package/dist/src/client/hmr-coordinator.js +1 -1
  20. package/dist/src/client/hmr-error-overlay.d.ts +18 -0
  21. package/dist/src/client/hydrate-runtime.d.ts +33 -0
  22. package/dist/src/client/hydrate-runtime.js +1 -0
  23. package/dist/src/client/hydration-mode.d.ts +11 -0
  24. package/dist/src/client/hydration-mode.js +1 -0
  25. package/dist/src/client/main-slim.js +1 -0
  26. package/dist/src/client/main.js +2 -15
  27. package/dist/src/client/router/a11y.d.ts +9 -0
  28. package/dist/src/client/router/a11y.js +1 -0
  29. package/dist/src/client/router/eligibility.d.ts +32 -0
  30. package/dist/src/client/router/eligibility.js +1 -0
  31. package/dist/src/client/router/events.d.ts +33 -0
  32. package/dist/src/client/router/events.js +1 -0
  33. package/dist/src/client/router/forms.d.ts +25 -0
  34. package/dist/src/client/router/forms.js +1 -0
  35. package/dist/src/client/router/index.d.ts +20 -0
  36. package/dist/src/client/router/index.js +1 -0
  37. package/dist/src/client/router/opt-out.d.ts +30 -0
  38. package/dist/src/client/router/opt-out.js +1 -0
  39. package/dist/src/client/router/persist.d.ts +24 -0
  40. package/dist/src/client/router/persist.js +1 -0
  41. package/dist/src/client/router/prefetch.d.ts +25 -0
  42. package/dist/src/client/router/prefetch.js +1 -0
  43. package/dist/src/client/router/swap.d.ts +31 -0
  44. package/dist/src/client/router/swap.js +1 -0
  45. package/dist/src/client/router/transitions.d.ts +22 -0
  46. package/dist/src/client/router/transitions.js +1 -0
  47. package/dist/src/client/server-islands-boot.d.ts +12 -0
  48. package/dist/src/client/server-islands-boot.js +1 -0
  49. package/dist/src/client/types/vite-virtual-modules.d.ts +7 -0
  50. package/dist/src/islands/builtin-directives.d.ts +1 -0
  51. package/dist/src/islands/builtin-directives.js +1 -1
  52. package/dist/src/islands/critical-css.js +1 -1
  53. package/dist/src/islands/framework-base-css.d.ts +5 -1
  54. package/dist/src/islands/framework-base-css.js +1 -1
  55. package/dist/src/islands/hydration-directives.js +1 -1
  56. package/dist/src/islands/island.d.ts +24 -3
  57. package/dist/src/islands/island.js +1 -1
  58. package/dist/src/islands/per-island-script.js +1 -1
  59. package/dist/src/islands/types.d.ts +6 -0
  60. package/dist/src/nitro/renderer.d.ts +2 -1
  61. package/dist/src/nitro/renderer.js +20 -20
  62. package/dist/src/nitro/types.d.ts +5 -0
  63. package/dist/src/post-build/cloudflare-worker-patch.d.ts +32 -0
  64. package/dist/src/post-build/cloudflare-worker-patch.js +1 -0
  65. package/dist/src/post-build/fetch-handler-wrapper.d.ts +1 -0
  66. package/dist/src/post-build/fetch-handler-wrapper.js +56 -0
  67. package/dist/src/post-build/index.d.ts +16 -0
  68. package/dist/src/post-build/index.js +6 -51
  69. package/dist/src/post-build/isolated-island-builder.js +2 -2
  70. package/dist/src/render/collect-css.d.ts +29 -0
  71. package/dist/src/render/collect-css.js +3 -3
  72. package/dist/src/render/dev-css-select.d.ts +40 -0
  73. package/dist/src/render/dev-css-select.js +5 -0
  74. package/dist/src/schemas/routing/index.d.ts +2 -0
  75. package/dist/src/schemas/routing.d.ts +1 -0
  76. package/dist/src/schemas/routing.js +1 -1
  77. package/dist/src/server-islands/encryption.js +1 -1
  78. package/dist/src/server-islands/endpoint.js +3 -3
  79. package/dist/src/server-islands/renderer.js +6 -5
  80. package/dist/src/server-islands/route.d.ts +3 -1
  81. package/dist/src/server-islands/route.js +1 -1
  82. package/dist/src/types/island-prop.d.ts +28 -9
  83. package/dist/src/types/virtual-modules.d.ts +26 -6
  84. package/dist/src/types/vite-env.d.ts +4 -0
  85. package/dist/src/vite-plugin/config.js +1 -1
  86. package/dist/src/vite-plugin/dev-css-graph.d.ts +41 -0
  87. package/dist/src/vite-plugin/dev-css-graph.js +1 -0
  88. package/dist/src/vite-plugin/dev-css-hmr.d.ts +42 -0
  89. package/dist/src/vite-plugin/dev-css-hmr.js +2 -0
  90. package/dist/src/vite-plugin/dev-css-modules.d.ts +8 -0
  91. package/dist/src/vite-plugin/dev-css-modules.js +1 -0
  92. package/dist/src/vite-plugin/framework-vite-defaults.d.ts +29 -0
  93. package/dist/src/vite-plugin/framework-vite-defaults.js +1 -0
  94. package/dist/src/vite-plugin/nitro-integration.d.ts +4 -0
  95. package/dist/src/vite-plugin/nitro-integration.js +20 -20
  96. package/dist/src/vite-plugin/plugin.d.ts +2 -0
  97. package/dist/src/vite-plugin/plugin.js +1 -1
  98. package/dist/src/vite-plugin/server-islands-plugin.js +1 -1
  99. package/dist/src/vite-plugin/ssr-dom-shim-module.d.ts +27 -0
  100. package/dist/src/vite-plugin/ssr-dom-shim-module.js +121 -0
  101. package/dist/src/vite-plugin/stub-build-time-packages.d.ts +16 -0
  102. package/dist/src/vite-plugin/stub-build-time-packages.js +2 -0
  103. package/dist/src/vite-plugin/types.d.ts +12 -0
  104. package/package.json +13 -7
package/dist/mod.d.ts CHANGED
@@ -22,7 +22,7 @@ export type { HydrationDirectiveDefinition, HydrationDirectiveFn, } from "./src/
22
22
  export { getDirective, getRegisteredDirectives, isCustomDirective, registerHydrationDirective, unregisterHydrationDirective, } from "./src/islands/hydration-directives.ts";
23
23
  export type { PreloadIntegrationsOptions } from "./src/islands/integration-loader.ts";
24
24
  export { DEFAULT_PRELOAD_FRAMEWORKS, detectAndLoadIntegration, detectFrameworksFromPageContent, loadIntegration, preloadIntegrations, } from "./src/islands/integration-loader.ts";
25
- export { default as Island, type IslandProps, renderIsland } from "./src/islands/island.tsx";
25
+ export { default as Island, type IslandProps, renderIsland, withListKey, } from "./src/islands/island.tsx";
26
26
  export type { CacheConfig as IslandCacheConfig, CacheStats as IslandCacheStats, } from "./src/islands/render-cache.ts";
27
27
  export { clearCache, clearIslandCache, configureCache, getCacheConfig, getCacheStats, invalidateCacheForFile, invalidateCacheForPath, logCacheStats, } from "./src/islands/render-cache.ts";
28
28
  export type { Framework, RenderParams, SvelteSSRCSSEntry } from "./src/islands/types.ts";
package/dist/mod.js CHANGED
@@ -1 +1 @@
1
- export{ACTION_ERROR_STATUS,ActionError,createActionClient,defineAction,isAction,isActionError}from"./src/actions/define.js";export{findActionsEntryInfo,generateActionTypes,getActionsWatchDir}from"./src/build/actions-types-generator.js";export{generateIslandManifest,getIslandBundlePath,loadIslandManifest}from"./src/build/island-manifest.js";export{generateIslandTypes,watchAndGenerateTypes}from"./src/build/island-types-generator.js";export{mdxIslandTransform}from"./src/build/mdx-island-transform.js";export{pageIslandTransform}from"./src/build/page-island-transform.js";export{registry as integrationRegistry}from"./src/core/integrations/registry.js";export{registerBuiltinDirectives}from"./src/islands/builtin-directives.js";export{analyzeComponentFile,renderComponentSSROnly}from"./src/islands/component-analysis.js";export{addSvelteSSRCSS,clearSvelteComponentCSS,generateComponentScopeId,getSvelteComponentCSS,getSvelteSSRCSS,getSvelteSSRCSSForHead,getSvelteSSRCSSStats}from"./src/islands/css-utils.js";export{createIslandRegistry,createIslandResolver,createIslandValidator,createIslandWatcher,DEFAULT_DISCOVERY_CONFIG,discoverAllIslands,discoverIslandDirectories,discoverIslandsInDirectory,formatCircularDependency,formatValidationError,formatValidationResult,formatValidationWarning,getDefaultIslandsPath,getQualifiedIslandName,hasDefaultIslandsDirectory,ISLAND_FILE_EXTENSIONS,IslandRegistry,IslandResolver,IslandValidator,IslandWatcher,isIslandsDirectory,isSupportedIslandExtension,parseQualifiedIslandName,validateAllIslands}from"./src/islands/discovery/index.js";export{detectFramework,detectFrameworkFromSrc,resolveIslandPath}from"./src/islands/framework-detection.js";export{getDirective,getRegisteredDirectives,isCustomDirective,registerHydrationDirective,unregisterHydrationDirective}from"./src/islands/hydration-directives.js";export{DEFAULT_PRELOAD_FRAMEWORKS,detectAndLoadIntegration,detectFrameworksFromPageContent,loadIntegration,preloadIntegrations}from"./src/islands/integration-loader.js";export{default as Island,renderIsland}from"./src/islands/island.js";export{clearCache,clearIslandCache,configureCache,getCacheConfig,getCacheStats,invalidateCacheForFile,invalidateCacheForPath,logCacheStats}from"./src/islands/render-cache.js";export{renderToHtml}from"./src/render/ssr.js";export{createNitroCoordinationPlugin,createNitroIntegration,createVirtualModulesPlugin,getAvalonConfig,getViteDevServer,isDevelopmentMode,RESOLVED_VIRTUAL_IDS,VIRTUAL_MODULE_IDS}from"./src/vite-plugin/nitro-integration.js";export{avalon,getLayoutsDir,getNitroConfig,getPagesDir,getResolvedConfig,isNitroEnabled}from"./src/vite-plugin/plugin.js";export async function build(e){throw Error("avalon build() is not available in the published package. Use `vite build` or the Avalon CLI instead.")}export{IslandErrorBoundary,withIslandErrorBoundary}from"./src/components/IslandErrorBoundary.js";export{LayoutErrorBoundary}from"./src/components/LayoutErrorBoundary.js";export*from"./src/layout-system.js";export{clearDiscoveryCache,clearMiddlewareCache,discoverScopedMiddleware,executeScopedMiddleware,getContextValue,getMatchingMiddleware,getMiddlewareCacheSize,hasContextValue,invalidateMiddleware,setContextValue}from"./src/middleware/index.js";export{usePersistentState}from"./src/persistence/use-persistent-state.js";export{CRON_ALIASES,CronConfigSchema,CronJobSchema,CronScheduleSchema,isValidCronExpression}from"./src/schemas/cron.js";
1
+ export{ACTION_ERROR_STATUS,ActionError,createActionClient,defineAction,isAction,isActionError}from"./src/actions/define.js";export{findActionsEntryInfo,generateActionTypes,getActionsWatchDir}from"./src/build/actions-types-generator.js";export{generateIslandManifest,getIslandBundlePath,loadIslandManifest}from"./src/build/island-manifest.js";export{generateIslandTypes,watchAndGenerateTypes}from"./src/build/island-types-generator.js";export{mdxIslandTransform}from"./src/build/mdx-island-transform.js";export{pageIslandTransform}from"./src/build/page-island-transform.js";export{registry as integrationRegistry}from"./src/core/integrations/registry.js";export{registerBuiltinDirectives}from"./src/islands/builtin-directives.js";export{analyzeComponentFile,renderComponentSSROnly}from"./src/islands/component-analysis.js";export{addSvelteSSRCSS,clearSvelteComponentCSS,generateComponentScopeId,getSvelteComponentCSS,getSvelteSSRCSS,getSvelteSSRCSSForHead,getSvelteSSRCSSStats}from"./src/islands/css-utils.js";export{createIslandRegistry,createIslandResolver,createIslandValidator,createIslandWatcher,DEFAULT_DISCOVERY_CONFIG,discoverAllIslands,discoverIslandDirectories,discoverIslandsInDirectory,formatCircularDependency,formatValidationError,formatValidationResult,formatValidationWarning,getDefaultIslandsPath,getQualifiedIslandName,hasDefaultIslandsDirectory,ISLAND_FILE_EXTENSIONS,IslandRegistry,IslandResolver,IslandValidator,IslandWatcher,isIslandsDirectory,isSupportedIslandExtension,parseQualifiedIslandName,validateAllIslands}from"./src/islands/discovery/index.js";export{detectFramework,detectFrameworkFromSrc,resolveIslandPath}from"./src/islands/framework-detection.js";export{getDirective,getRegisteredDirectives,isCustomDirective,registerHydrationDirective,unregisterHydrationDirective}from"./src/islands/hydration-directives.js";export{DEFAULT_PRELOAD_FRAMEWORKS,detectAndLoadIntegration,detectFrameworksFromPageContent,loadIntegration,preloadIntegrations}from"./src/islands/integration-loader.js";export{default as Island,renderIsland,withListKey}from"./src/islands/island.js";export{clearCache,clearIslandCache,configureCache,getCacheConfig,getCacheStats,invalidateCacheForFile,invalidateCacheForPath,logCacheStats}from"./src/islands/render-cache.js";export{renderToHtml}from"./src/render/ssr.js";export{createNitroCoordinationPlugin,createNitroIntegration,createVirtualModulesPlugin,getAvalonConfig,getViteDevServer,isDevelopmentMode,RESOLVED_VIRTUAL_IDS,VIRTUAL_MODULE_IDS}from"./src/vite-plugin/nitro-integration.js";export{avalon,getLayoutsDir,getNitroConfig,getPagesDir,getResolvedConfig,isNitroEnabled}from"./src/vite-plugin/plugin.js";export async function build(e){throw Error("avalon build() is not available in the published package. Use `vite build` or the Avalon CLI instead.")}export{IslandErrorBoundary,withIslandErrorBoundary}from"./src/components/IslandErrorBoundary.js";export{LayoutErrorBoundary}from"./src/components/LayoutErrorBoundary.js";export*from"./src/layout-system.js";export{clearDiscoveryCache,clearMiddlewareCache,discoverScopedMiddleware,executeScopedMiddleware,getContextValue,getMatchingMiddleware,getMiddlewareCacheSize,hasContextValue,invalidateMiddleware,setContextValue}from"./src/middleware/index.js";export{usePersistentState}from"./src/persistence/use-persistent-state.js";export{CRON_ALIASES,CronConfigSchema,CronJobSchema,CronScheduleSchema,isValidCronExpression}from"./src/schemas/cron.js";
@@ -1 +1 @@
1
- export const INTEGRATION_BUILD_CONFIGS={preact:{name:`preact`,extensions:[`.tsx`,`.jsx`],optimizeDeps:[`preact`,`preact/hooks`,`preact/jsx-runtime`,`preact/jsx-dev-runtime`],ssrExternal:[],ssrNoExternal:[`preact`,`preact-render-to-string`],requiresPlugin:!1},vue:{name:`vue`,extensions:[`.vue`],optimizeDeps:[`vue`],ssrExternal:[],ssrNoExternal:[`vue`,`@vue/server-renderer`,`@vue/shared`],requiresPlugin:!0,pluginPackage:`@vitejs/plugin-vue`},solid:{name:`solid`,extensions:[`.tsx`,`.jsx`],optimizeDeps:[`solid-js`,`solid-js/web`,`solid-js/store`],ssrExternal:[],ssrNoExternal:[`solid-js`,`solid-js/web`,`solid-js/store`],requiresPlugin:!0,pluginPackage:`vite-plugin-solid`},svelte:{name:`svelte`,extensions:[`.svelte`],optimizeDeps:[`svelte`,`svelte/internal`,`svelte/store`,`svelte/animate`,`svelte/easing`,`svelte/motion`,`svelte/transition`],ssrExternal:[],ssrNoExternal:[`svelte`,`svelte/server`,`svelte/internal`,`svelte/store`],requiresPlugin:!0,pluginPackage:`@sveltejs/vite-plugin-svelte`},react:{name:`react`,extensions:[`.jsx`,`.tsx`],optimizeDeps:[`react`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom`,`react-dom/client`],ssrExternal:[],ssrNoExternal:[`react`,`react-dom`,`react-dom/server`],requiresPlugin:!0,pluginPackage:`@vitejs/plugin-react`},lit:{name:`lit`,extensions:[`.ts`,`.js`],optimizeDeps:[`lit`,`lit/decorators.js`,`lit/directives/class-map.js`,`lit/directives/style-map.js`,`@lit/reactive-element`],ssrExternal:[],ssrNoExternal:[`lit`,`@lit-labs/ssr`,`@lit/reactive-element`,`lit-html`],requiresPlugin:!1}};export function getIntegrationBuildConfig(t){return INTEGRATION_BUILD_CONFIGS[t]}export function getOptimizeDepsForIntegrations(t){let n=new Set;for(let r of t){let t=INTEGRATION_BUILD_CONFIGS[r];t&&t.optimizeDeps.forEach(e=>n.add(e))}return Array.from(n)}export function getSSRNoExternalForIntegrations(t){let n=new Set;for(let r of t){let t=INTEGRATION_BUILD_CONFIGS[r];t&&t.ssrNoExternal.forEach(e=>n.add(e))}return Array.from(n)}export function integrationRequiresPlugin(t){return INTEGRATION_BUILD_CONFIGS[t]?.requiresPlugin??!1}export function getIntegrationPluginPackage(t){return INTEGRATION_BUILD_CONFIGS[t]?.pluginPackage}
1
+ export const INTEGRATION_BUILD_CONFIGS={preact:{name:`preact`,extensions:[`.tsx`,`.jsx`],optimizeDeps:[`preact`,`preact/hooks`,`preact/jsx-runtime`,`preact/jsx-dev-runtime`],ssrExternal:[],ssrNoExternal:[`preact`,`preact/hooks`,`preact/compat`,`preact/compat/server`,`preact-render-to-string`],requiresPlugin:!1},vue:{name:`vue`,extensions:[`.vue`],optimizeDeps:[`vue`],ssrExternal:[],ssrNoExternal:[`vue`,`@vue/server-renderer`,`@vue/shared`],requiresPlugin:!0,pluginPackage:`@vitejs/plugin-vue`},solid:{name:`solid`,extensions:[`.tsx`,`.jsx`],optimizeDeps:[`solid-js`,`solid-js/web`,`solid-js/store`],ssrExternal:[],ssrNoExternal:[`solid-js`,`solid-js/web`,`solid-js/store`],requiresPlugin:!0,pluginPackage:`vite-plugin-solid`},svelte:{name:`svelte`,extensions:[`.svelte`],optimizeDeps:[`svelte`,`svelte/internal`,`svelte/store`,`svelte/animate`,`svelte/easing`,`svelte/motion`,`svelte/transition`],ssrExternal:[],ssrNoExternal:[`svelte`,`svelte/server`,`svelte/internal`,`svelte/store`],requiresPlugin:!0,pluginPackage:`@sveltejs/vite-plugin-svelte`},react:{name:`react`,extensions:[`.jsx`,`.tsx`],optimizeDeps:[`react`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom`,`react-dom/client`],ssrExternal:[],ssrNoExternal:[`react`,`react-dom`,`react-dom/client`,`react-dom/server`],requiresPlugin:!0,pluginPackage:`@vitejs/plugin-react`},lit:{name:`lit`,extensions:[`.ts`,`.js`],optimizeDeps:[`lit`,`lit/decorators.js`,`lit/directives/class-map.js`,`lit/directives/style-map.js`,`@lit/reactive-element`,`@lit-labs/ssr-client`,`@lit-labs/ssr-client/lit-element-hydrate-support.js`],ssrExternal:[],ssrNoExternal:[`lit`,`@lit-labs/ssr`,`@lit/reactive-element`,`lit-html`],requiresPlugin:!1},qwik:{name:`qwik`,extensions:[`.tsx`,`.jsx`],optimizeDeps:[],ssrExternal:[],ssrNoExternal:[`@builder.io/qwik`,`@builder.io/qwik/server`],requiresPlugin:!1}};export function getIntegrationBuildConfig(t){return INTEGRATION_BUILD_CONFIGS[t]}export function getOptimizeDepsForIntegrations(t){let n=new Set;for(let r of t){let t=INTEGRATION_BUILD_CONFIGS[r];t&&t.optimizeDeps.forEach(e=>n.add(e))}return Array.from(n)}export function getSSRNoExternalForIntegrations(t){let n=new Set;for(let r of t){let t=INTEGRATION_BUILD_CONFIGS[r];t&&t.ssrNoExternal.forEach(e=>n.add(e))}return Array.from(n)}export function integrationRequiresPlugin(t){return INTEGRATION_BUILD_CONFIGS[t]?.requiresPlugin??!1}export function getIntegrationPluginPackage(t){return INTEGRATION_BUILD_CONFIGS[t]?.pluginPackage}
@@ -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
- `);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(`
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, mount as __mountIsland, unmount as __unmountIsland } from ${JSON.stringify(e[t])};`):d.push(`export { loadIntegrationModule } from "virtual:avalon/integration-loader";`)}return d.join(`
4
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\s*[={]/g,o=/<([A-Z]\w*)\s[\s\S]{0,2000}?\bisland\s*[={]/g,s=new Set,c=null;for(c=i.exec(e);c!==null;c=i.exec(e))s.add(c[1]);for(c=o.exec(e);c!==null;c=o.exec(e))s.add(c[1]);let l=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,d=new Set,f=[];for(c=l.exec(e);c!==null;c=l.exec(e))f.push([c[1],c[2]]),u(c[2])&&RegExp(`<${c[1]}[\\s/>]`).test(e)&&d.add(c[1]);if(!(s.size===0&&d.size===0))for(let[e,i]of f){if(!s.has(e)&&!d.has(e))continue;let o=p(i,t,n);if(!o)continue;let c=a(n,o).replaceAll(`\\`,`/`).replace(/\.(tsx?|jsx?)$/,``);r.has(o)||r.set(o,{filePath:o,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}
@@ -1,4 +1,7 @@
1
1
  import { type IslandCollision, type IslandDirectory } from "../islands/discovery/index.ts";
2
+ declare global {
3
+ var __avalonIsDev: boolean | undefined;
4
+ }
2
5
  export interface IslandManifest {
3
6
  islands: Record<string, IslandEntry>;
4
7
  version: string;
@@ -1 +1 @@
1
- import{readFile as e}from"node:fs/promises";import{createIslandRegistry as t,getQualifiedIslandName as n}from"../islands/discovery/index.js";export async function generateIslandManifest(){let r={},s=process.cwd();try{let c=await t(s),l=c.getAllIslands(),u=c.directories,d=c.collisions;for(let t of l){let s=n(t),c=`/${t.relativePath}`,l=await e(t.filePath,`utf-8`),u=i(t.framework),d=a(l),f=await o(l);r[s]={src:c,bundle:t.namespace===``?`/islands/${t.name}.${f}.js`:`/islands/${s}.${f}.js`,hash:f,framework:u,deps:d,namespace:t.namespace,qualifiedName:s,sourceDirectory:t.directory.relativePath}}return{islands:r,directories:u,collisions:d,version:`1.0.0`,buildTime:Date.now()}}catch(e){return console.warn(`Failed to generate island manifest:`,e),{islands:{},directories:[],collisions:[],version:`1.0.0`,buildTime:Date.now()}}}function i(e){switch(e){case`preact`:return`preact`;case`react`:return`react`;case`solid`:return`solid`;case`vue`:return`vue`;case`svelte`:return`svelte`;case`lit`:return`lit`;case`qwik`:return`qwik`;default:return`unknown`}}function a(e){let t=[],n=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;for(let r=n.exec(e);r!==null;r=n.exec(e)){let e=r[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}return[...new Set(t)]}async function o(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,8)}export async function loadIslandManifest(){try{let t=await e(`dist/island-manifest.json`,`utf-8`);return JSON.parse(t)}catch(e){return console.warn(`Failed to load island manifest:`,e),null}}export function getIslandBundlePath(e,t){let n=globalThis.__avalonHydrationMode===void 0?process.env.NODE_ENV!==`production`:globalThis.__avalonHydrationMode===`entry-client`,r=process.cwd();if(r&&e.startsWith(r+`/`)&&(e=e.slice(r.length)),t){let n=l(e),r=t;if(r.islands[n])return r.islands[n].bundle;let i=e.replace(/^\/islands\//,``).replace(/\.(tsx?|jsx?)$/,``),a=t.islands[i];if(a)return a.bundle}return n?e.startsWith(`/islands/`)?e.replaceAll(`/islands/`,`/src/islands/`):e.startsWith(`/src/`)||e.startsWith(`/app/`)||e.startsWith(`/`)?e:`/src/${e}`:`/islands/${l(e)}.js`}function l(e){let t=e.replace(/^\//,``);t=t.replace(/\.(tsx?|jsx?)$/,``);let n=new RegExp(/^src\/(.+)\/islands\/([^/]+)$/).exec(t);if(n){let[,e,t]=n;return`${e}/${t}`}let r=new RegExp(/^(?:src\/)?islands\/([^/]+)$/).exec(t);return r?r[1]:t}export function getIslandEntry(e,t){if(t.islands[e])return t.islands[e];if(t.directories){for(let[n,r]of Object.entries(t.islands))if(n.split(`/`).pop()===e)return r}return null}
1
+ import{readFile as e}from"node:fs/promises";import{createIslandRegistry as t,getQualifiedIslandName as n}from"../islands/discovery/index.js";export async function generateIslandManifest(){let r={},s=process.cwd();try{let c=await t(s),l=c.getAllIslands(),u=c.directories,d=c.collisions;for(let t of l){let s=n(t),c=`/${t.relativePath}`,l=await e(t.filePath,`utf-8`),u=i(t.framework),d=a(l),f=await o(l);r[s]={src:c,bundle:t.namespace===``?`/islands/${t.name}.${f}.js`:`/islands/${s}.${f}.js`,hash:f,framework:u,deps:d,namespace:t.namespace,qualifiedName:s,sourceDirectory:t.directory.relativePath}}return{islands:r,directories:u,collisions:d,version:`1.0.0`,buildTime:Date.now()}}catch(e){return console.warn(`Failed to generate island manifest:`,e),{islands:{},directories:[],collisions:[],version:`1.0.0`,buildTime:Date.now()}}}function i(e){switch(e){case`preact`:return`preact`;case`react`:return`react`;case`solid`:return`solid`;case`vue`:return`vue`;case`svelte`:return`svelte`;case`lit`:return`lit`;case`qwik`:return`qwik`;default:return`unknown`}}function a(e){let t=[],n=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;for(let r=n.exec(e);r!==null;r=n.exec(e)){let e=r[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}return[...new Set(t)]}async function o(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,8)}export async function loadIslandManifest(){try{let t=await e(`dist/island-manifest.json`,`utf-8`);return JSON.parse(t)}catch(e){return console.warn(`Failed to load island manifest:`,e),null}}export function getIslandBundlePath(e,t){let n=typeof globalThis.__avalonIsDev==`boolean`?globalThis.__avalonIsDev:process.env.NODE_ENV!==`production`,r=process.cwd();if(r&&e.startsWith(r+`/`)&&(e=e.slice(r.length)),t){let n=l(e),r=t;if(r.islands[n])return r.islands[n].bundle;let i=e.replace(/^\/islands\//,``).replace(/\.(tsx?|jsx?)$/,``),a=t.islands[i];if(a)return a.bundle}return n?e.startsWith(`/islands/`)?e.replaceAll(`/islands/`,`/src/islands/`):e.startsWith(`/src/`)||e.startsWith(`/app/`)||e.startsWith(`/`)?e:`/src/${e}`:`/islands/${l(e)}.js`}function l(e){let t=e.replace(/^\//,``);t=t.replace(/\.(tsx?|jsx?)$/,``);let n=new RegExp(/^src\/(.+)\/islands\/([^/]+)$/).exec(t);if(n){let[,e,t]=n;return`${e}/${t}`}let r=new RegExp(/^(?:src\/)?islands\/([^/]+)$/).exec(t);return r?r[1]:t}export function getIslandEntry(e,t){if(t.islands[e])return t.islands[e];if(t.directories){for(let[n,r]of Object.entries(t.islands))if(n.split(`/`).pop()===e)return r}return null}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared helpers for computing the `ssr` flag from an `island` prop object.
3
+ * Used by the page and MDX transforms so the expression stays in one place.
4
+ */
5
+ /**
6
+ * Runtime expression evaluated against the island directive object.
7
+ * `clientOnly: true` wins, then an explicit `ssr`, otherwise page usage SSRs.
8
+ */
9
+ export declare function islandSsrExpression(islandValue: string): string;
10
+ /**
11
+ * True when the island prop is an object literal that statically opts out of SSR.
12
+ * Runtime-computed values (`island={opts}`) cannot be proven client-only.
13
+ */
14
+ export declare function isStaticallyClientOnly(islandProp: string | null | undefined): boolean;
@@ -0,0 +1 @@
1
+ export function islandSsrExpression(e){return`((__i) => __i.clientOnly === true ? false : (__i.ssr !== undefined ? __i.ssr : true))(${e})`}export function isStaticallyClientOnly(e){if(!e)return!1;let t=e.trim();return t.startsWith(`{`)?/\bclientOnly\s*:\s*true\b/.test(t)||/\bssr\s*:\s*false\b/.test(t):!1}
@@ -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;for(let r=n.exec(e);r!==null;r=n.exec(e)){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;for(let r=n.exec(e);r!==null;r=n.exec(e))t.add(r[1]);let r=/(?:_?jsxs?(?:DEV)?)\s*\(\s*([A-Z]\w*)\s*,\s*\{[^}]*\bisland\s*:/g;for(let n=r.exec(e);n!==null;n=r.exec(e))t.add(n[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;for(let t=i.exec(e);t!==null;t=i.exec(e)){let i=t.index;t[1];let c=l(e,i),d=e.slice(i,c);if(!d.includes(`island`)){a+=e.slice(o,c),o=c;continue}let f=d.indexOf(`{`);if(f===-1){a+=e.slice(o,c),o=c;continue}let p=s(d,f),m=u(d.slice(f,p));if(!m){a+=e.slice(o,c),o=c;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,i)+_,o=c}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
+ import{dirname as e}from"node:path";import{islandSsrExpression as t}from"./island-ssr-flag.js";const n=[/['"]\.\.\/islands\//,/['"]\.\/islands\//,/['"]\.\.\/\.\.\/islands\//,/['"]\$islands\//,/['"]@\/islands\//,/['"]\/src\/islands\//];function r(e){let t=new Map,n=/import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/g;for(let r=n.exec(e);r!==null;r=n.exec(e)){let e=r[1],n=r[2].slice(1,-1);t.set(e,n)}return t}function i(e,t){let n=1,r=1;for(;n<e.length&&r>0;){let i=e[n];if(r===1){let r=e.slice(n);if(r.startsWith(t)&&/^\s*:/.test(r.slice(t.length))){let t=e[n-1];if(n===1||!/\w/.test(t))return!0}}i===`{`||i===`(`||i===`[`?(r++,n++):i===`}`||i===`)`||i===`]`?(r--,n++):i===`'`||i===`"`||i==="`"?n=u(e,n):n++}return!1}function a(e){let t=new Set,n=/<([A-Z]\w*)\s+[^>]*\bisland\s*[={]/g;for(let r=n.exec(e);r!==null;r=n.exec(e))t.add(r[1]);let r=/(?:_?jsxs?(?:DEV)?)\s*\(\s*([A-Z]\w*)\s*,/g;for(let n=r.exec(e);n!==null;n=r.exec(e)){let r=n.index+n[0].length;for(;r<e.length&&/\s/.test(e[r]);)r++;if(e[r]!==`{`)continue;let a=l(e,r);i(e.slice(r,a),`island`)&&t.add(n[1])}return t}function o(e,t){let n=[],i=r(e),o=a(e);for(let[e,r]of i){let i=`"${r}"`,a=t.some(e=>e.test(i)),s=o.has(e);(a||s)&&n.push({localName:e,importPath:r,islandPropUsage:s})}return n}function s(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 c(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 l(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=u(e,n):n++}return n<e.length?n+1:n}function u(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 d(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=l(e,n):t===`'`||t===`"`||t==="`"?n=u(e,n):n++}return n}function f(e){let t=e.match(/\bisland\s*:\s*/);if(!t)return null;let n=t.index+t[0].length,r;if(e[n]===`{`)r=l(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(),s=a;return o.startsWith(`,`)?s+=o.slice(1):s+=o,s=s.replace(/,\s*}$/,`}`).replace(/{\s*,/,`{`),{islandValue:i,otherProps:s}}function p(e,n,r,i){let a=RegExp(`(_?jsxs?(?:DEV)?)\\s*\\(\\s*${n}\\s*,`,`g`),o=``,s=0;for(let c=a.exec(e);c!==null;c=a.exec(e)){let a=c.index;c[1];let u=d(e,a),p=e.slice(a,u);if(!p.includes(`island`)){o+=e.slice(s,u),s=u;continue}let m=p.indexOf(`{`);if(m===-1){o+=e.slice(s,u),s=u;continue}let h=l(p,m),g=f(p.slice(m,h));if(!g){o+=e.slice(s,u),s=u;continue}let{islandValue:_,otherProps:v}=g,y=i?`framework: "${i}",`:``,b=v.trim()!==`{}`&&v.trim()!==``?`props: ${v},`:``,x=`(await __AvalonRenderIsland({ src: "${r}", ${y} ${/\bclientOnly\s*:\s*true\b/.test(_)?``:`component: ${n},`} ...(${_}), ${b} ssr: ${t(_)} }))`;o+=e.slice(s,a)+x,s=u}return o+=e.slice(s),o}export function mdxIslandTransform(e={}){let{islandPathPatterns:t=n,verbose:r=!1}=e,i=[];return{name:`avalon:mdx-island-transform`,enforce:`post`,configResolved(e){i=e.resolve?.alias??[]},transform(e,n){if(!n.endsWith(`.mdx`)&&!n.includes(`.mdx?`))return null;let a=o(e,t);if(a.length===0)return null;if(r){console.log(`[mdx-island-transform] Found ${a.length} island import(s) in ${n}`);for(let e of a)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 a){let t=s(e.importPath,n,i),r=c(t);l=p(l,e.localName,t,r)}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 ${n}`),{code:l,map:null}}}}
@@ -1 +1 @@
1
- export async function createMDXPlugin(e={}){let{remarkPlugins:t=[],rehypePlugins:n=[],development:r=!1,jsxImportSource:i=`preact`,syntaxHighlighting:a=!0}=e;try{let{default:e}=await import(`@mdx-js/rollup`),{default:o}=await import(`remark-frontmatter`),{default:s}=await import(`remark-mdx-frontmatter`),{default:c}=await import(`remark-gfm`),l=[];if(a)try{let{default:e}=await import(`rehype-highlight`);l.push(e)}catch{console.warn(`[avalon:mdx] rehype-highlight not installed, syntax highlighting disabled. Install it with: npm install rehype-highlight`)}l.push(...n);let u=e({remarkPlugins:[o,s,c,...t],rehypePlugins:l,jsxImportSource:i,development:r,format:`mdx`});return u.sharedDuringBuild=!0,[u]}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`❌ Failed to configure MDX plugin:`,t),console.warn(`💡 Install missing dependencies or check import map`),console.warn(`⚠️ MDX plugin disabled - .mdx files will not be processed`),[]}}
1
+ import e from"rehype-highlight";export async function createMDXPlugin(t={}){let{remarkPlugins:n=[],rehypePlugins:r=[],development:i=!1,jsxImportSource:a=`preact`,syntaxHighlighting:o=!0}=t;try{let{default:t}=await import(`@mdx-js/rollup`),{default:s}=await import(`remark-frontmatter`),{default:c}=await import(`remark-mdx-frontmatter`),{default:l}=await import(`remark-gfm`),u=[];o&&u.push(e),u.push(...r);let d=t({remarkPlugins:[s,c,l,...n],rehypePlugins:u,jsxImportSource:a,development:i,format:`mdx`});return d.sharedDuringBuild=!0,[d]}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`❌ Failed to configure MDX plugin:`,t),console.warn(`💡 Install missing dependencies or check import map`),console.warn(`⚠️ MDX plugin disabled - .mdx files will not be processed`),[]}}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Makes injected `await __pageRenderIsland(...)` calls legal and resolvable
3
+ * during SSR.
4
+ *
5
+ * Parses the page/layout TSX with oxc-parser, then applies source edits:
6
+ * enclosing functions become `async`, `.map`/`.flatMap` callbacks are wrapped
7
+ * in `await Promise.all(...)`, and local helper JSX (`<Card />`) becomes
8
+ * `await Card(...)`.
9
+ *
10
+ * JavaScript forbids `await` in a sync function, so the pre-edit source cannot
11
+ * be parsed as-is. Awaits are masked to `void ` (same length, offsets stay
12
+ * aligned) and matched back to the original tokens.
13
+ */
14
+ /**
15
+ * Rewrites a page/layout module so every `await` sits in an async function
16
+ * and list islands resolve through `await Promise.all`.
17
+ */
18
+ export declare function ensureAwaitContextsAsync(code: string, fileId: string): string;
@@ -0,0 +1,2 @@
1
+ import{parseSync as e,visitorKeys as t}from"oxc-parser";const n=new Set([`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`]);function r(e){return!!e&&typeof e==`object`&&typeof e.type==`string`}function i(e){let t=e;for(;t.type===`ParenthesizedExpression`&&r(t.expression);)t=t.expression;return t}function*a(e){let n=t[e.type];if(n)for(let t of n){let n=e[t];if(Array.isArray(n))for(let e of n)r(e)&&(yield e);else r(n)&&(yield n)}}function*o(e){let t=[];function*n(e){yield{node:e,ancestors:t},t.push(e);for(let t of a(e))yield*n(t);t.pop()}yield*n(e)}function s(t,n){let r=e(n.endsWith(`.jsx`)?`page.jsx`:`page.tsx`,t.replace(/\bawait\b/g,`void `),{lang:n.endsWith(`.jsx`)?`jsx`:`tsx`,range:!0});if(r.errors.length>0){let e=r.errors[0];throw Error(`[avalon] failed to parse ${n} after island transform: ${e.message}`)}return r.program}function c(e,t){return e.type===`UnaryExpression`&&e.operator===`void`&&t.startsWith(`await`,e.start)}function l(e,t){let n=1;for(let r=0;r<t&&r<e.length;r++)e[r]===`
2
+ `&&n++;return n}function u(e){return r(e)&&e.type===`Identifier`&&typeof e.name==`string`?e.name:null}function d(e,t){return u(e.id)||(t?.type===`VariableDeclarator`?u(t.id):t?.type===`AssignmentExpression`?u(t.left):null)}function f(e){for(let t=e.length-1;t>=0;t--)if(n.has(e[t].type))return{fn:e[t],parent:t>0?e[t-1]:null};return null}function p(e){return e?e.type===`MethodDefinition`||e.type===`Property`&&e.method===!0:!1}function m(e){let t=new Set;for(let{node:n}of o(e)){if(n.type!==`ExportDefaultDeclaration`||!r(n.declaration))continue;let e=n.declaration,i=u(e)??u(e.id);i&&t.add(i)}return t}function h(e,t,n,r){let i=l(n,r);throw Error(`[avalon] island at ${t}:${i} sits inside a ${e} that cannot be marked async. Move it into the page default export, a nested function, or a .map() callback.`)}function g(e,t,n,r){p(e.parent)&&h(`method`,t,n,r),e.fn.generator===!0&&h(`generator`,t,n,r)}function _(e,t,n){let r=new Set;for(let{node:i,ancestors:a}of o(e))if(c(i,n)){let e=f(a);if(!e)continue;g(e,t,n,i.start),r.add(e.fn)}return r}function v(e){let t=new Map;for(let{node:n,ancestors:r}of o(e)){if(n.type!==`JSXElement`)continue;let e=C(n);if(!e)continue;let i=t.get(e)??[];i.push({ancestors:r.slice()}),t.set(e,i)}return t}function y(e){let t=new Map;for(let{node:r,ancestors:i}of o(e))n.has(r.type)&&t.set(r,i.at(-1)??null);return t}function b(e,t,n){let r=d(e,t);return!r||!/^[A-Z]/.test(r)||n.has(r)?null:r}function x(e,t,n,r){let i=f(e);return!i||t.has(i.fn)?!1:(g(i,n,r,i.fn.start),t.add(i.fn),!0)}function S(e,t,n,r){let i=y(e),a=v(e),o=m(e),s=!0;for(;s;){s=!1;for(let e of t){let c=b(e,i.get(e)??null,o);if(c)for(let e of a.get(c)??[])x(e.ancestors,t,n,r)&&(s=!0)}}}function C(e){if(!r(e.openingElement))return null;let t=e.openingElement.name;return r(t)&&t.type===`JSXIdentifier`&&typeof t.name==`string`?t.name:null}function w(e){let t=[];for(let n of e)n.async!==!0&&t.push({start:n.start,end:n.start,text:`async `});return t}function T(e){if(!r(e.callee))return null;let t=i(e.callee),n=t.type===`ChainExpression`&&r(t.expression)?t.expression:t;return n.type===`MemberExpression`?n:null}function E(e){let t=T(e);return!t||t.computed===!0||!r(t.property)?null:u(t.property)}function D(e){if(e.type!==`CallExpression`)return!1;let t=i(r(e.callee)?e.callee:e);return t.type!==`MemberExpression`||t.computed===!0?!1:u(t.object)===`Promise`&&u(t.property)===`all`}function O(e){if(e.optional===!0)return!0;if(!r(e.callee))return!1;let t=i(e.callee);return t.type===`ChainExpression`?!0:t.type===`MemberExpression`&&t.optional===!0}function k(e){let t=Array.isArray(e.arguments)?e.arguments:[];return t[0]&&r(t[0])?i(t[0]):null}function A(e,t,n){if(!e)return!1;if(t.has(e))return!0;let r=u(e);return!!(r&&n.has(r))}const j=new Set([`map`,`flatMap`]),M=new Set([`forEach`,`filter`,`reduce`,`reduceRight`,`some`,`every`,`find`,`findIndex`,`findLast`,`findLastIndex`]);function N(e,t,n,r,i){for(let{node:a}of o(e)){if(a.type!==`CallExpression`)continue;let e=E(a);!e||!M.has(e)||A(k(a),t,n)&&h(`${e}() callback`,r,i,a.start)}}function P(e,t,n,r){if(e.type!==`CallExpression`)return null;let i=E(e);if(!i||!j.has(i)||!A(k(e),n,r))return null;let a=t.at(-1)??null;return a&&D(a)?null:e}function F(e,t,n,r,i){let a=!0;for(;a;){a=!1;for(let{node:s,ancestors:c}of o(e)){if(!P(s,c,t,n))continue;let e=f(c);e&&(g(e,r,i,s.start),!t.has(e.fn)&&(t.add(e.fn),a=!0))}}}function I(e,t){let n=T(e),i=n&&r(n.property)?n.property:null;return[{start:e.start,end:e.start,text:`(await Promise.all(`},...i?[{start:i.start,end:i.end,text:`map`}]:[],{start:e.end,end:e.end,text:t?` ?? [])).flat()`:`)).flat()`}]}function L(e){let t=O(e);return E(e)===`flatMap`?I(e,t):[{start:e.start,end:e.start,text:`await Promise.all(`},{start:e.end,end:e.end,text:t?` ?? [])`:`)`}]}function R(e,t){let n=z(t,e),r=[];for(let{node:i,ancestors:a}of o(e))P(i,a,t,n)&&r.push(...L(i));return r}function z(e,t){let n=m(t),r=new Set;for(let{node:i,ancestors:a}of o(t)){if(!e.has(i))continue;let t=d(i,a.at(-1)??null);t&&/^[A-Z]/.test(t)&&!n.has(t)&&r.add(t)}return r}function B(e,t){if(e.type===`JSXSpreadAttribute`&&r(e.argument))return`...${t.slice(e.argument.start,e.argument.end)}`;if(e.type!==`JSXAttribute`||!r(e.name))return null;let n=typeof e.name.name==`string`?e.name.name:null;if(!n||n===`key`)return null;if(!r(e.value))return`${n}: true`;if(e.value.type===`JSXExpressionContainer`&&r(e.value.expression)){let r=e.value.expression;return`${n}: ${t.slice(r.start,r.end)}`}return`${n}: ${t.slice(e.value.start,e.value.end)}`}function V(e,t){if(e.type!==`JSXAttribute`||!r(e.name)||(typeof e.name.name==`string`?e.name.name:null)!==`key`||!r(e.value))return null;if(e.value.type===`JSXExpressionContainer`&&r(e.value.expression)){let n=e.value.expression;return t.slice(n.start,n.end)}return t.slice(e.value.start,e.value.end)}function H(e,t){let n=[],i=null,a=e&&Array.isArray(e.attributes)?e.attributes:[];for(let e of a){if(!r(e))continue;let a=V(e,t);if(a!=null){i=a;continue}let o=B(e,t);o&&n.push(o)}return{props:n,keyExpr:i}}function U(e,t,n){let i=r(e.openingElement)?e.openingElement:null,{props:a,keyExpr:o}=H(i,n);if(i?.selfClosing!==!0&&r(e.closingElement)){let t=n.slice(i?i.end:e.start,e.closingElement.start);t.trim()&&a.push(`children: (${t})`)}let s=`await ${t}(${a.length>0?`{ ${a.join(`, `)} }`:`{}`})`;return o==null?s:`__pageKeyed(${o}, ${s})`}function W(e,t,n){let r=z(t,e);if(r.size===0)return[];let i=[];for(let{node:t,ancestors:a}of o(e)){if(t.type!==`JSXElement`)continue;let e=C(t);if(!e||!r.has(e))continue;let o=a.at(-1),s=o?.type===`JSXElement`||o?.type===`JSXFragment`,c=U(t,e,n);i.push({start:t.start,end:t.end,text:s?`{${c}}`:c})}return i}function G(e,t){let n=[...t].sort((e,t)=>t.start-e.start||t.end-e.end),r=e;for(let e of n)r=r.slice(0,e.start)+e.text+r.slice(e.end);return r}export function ensureAwaitContextsAsync(e,t){let n=s(e,t),r=_(n,t,e),i=z(r,n),a=0;for(;r.size!==a;)a=r.size,i=z(r,n),F(n,r,i,t,e),S(n,r,t,e);return N(n,r,i,t,e),G(e,[...w(r),...R(n,r),...W(n,r,e)])}
@@ -15,7 +15,9 @@
15
15
  * How it works:
16
16
  * The plugin rewrites each `<Component island={opts} ...props />` JSX usage
17
17
  * into an `{await renderIsland({...})}` expression inline in the JSX.
18
- * Any component can be an island - no special directory required.
18
+ * Enclosing functions are marked `async`; `.map()` callbacks are wrapped in
19
+ * `await Promise.all(...)`. Any component can be an island — no special
20
+ * directory required.
19
21
  *
20
22
  * Preact's renderToString does NOT support async child components in the JSX
21
23
  * tree, so we cannot use async wrapper functions. Instead we directly replace
@@ -1,2 +1,2 @@
1
- import{dirname as e}from"node:path";import{addToManifest as t,generateComponentId as n}from"../server-islands/manifest.js";function r(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}const i=[{prefix:`@shared/`,map:e=>`/app/shared/${e}`},{prefix:`@modules/`,map:e=>`/app/modules/${e}`},{prefix:`@/`,map:e=>`/app/${e}`},{prefix:`$components/`,map:e=>`/src/components/${e}`},{prefix:`$islands/`,map:e=>`/src/islands/${e}`},{prefix:`~/`,map:e=>`/src/${e}`}];function a(e){return e.startsWith(`/`)?e:`/${e}`}function o(e,t){for(let{find:n,replacement:r}of t){let t=a(r);if(typeof n==`string`){if(e===n||e.startsWith(`${n}/`))return`${t}${e.slice(n.length)}`}else if(n.test(e))return e.replace(n,t)}return null}function s(e){for(let{prefix:t,map:n}of i)if(e.startsWith(t))return n(e.slice(t.length));return null}function c(t,n){if(!t.startsWith(`.`))return null;let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i===-1)return null;let a=e(r.slice(i)).split(`/`);for(let e of t.split(`/`))e===`..`?a.pop():e!==`.`&&a.push(e);return a.join(`/`)}function l(e,t,n=[]){return e.startsWith(`/`)?e:o(e,n)??s(e)??c(e,t)??`/src/${e.split(`/`).pop()}`}function u(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 d(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 f(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 p=new Set([`qwik`]);function m(e){let t=u(e);return t!==void 0&&p.has(t)}const h=String.raw`[\s][^>]*island[\s]*[={]`,g=String.raw`[\s][^>]*server[\s]*[={]`,_=String.raw`[\s/>]`;function v(e,t){return t.some(t=>RegExp(`<${t}${h}`).test(e))}function y(e,t){return t.some(t=>RegExp(`<${t}${g}`).test(e))}function b(e,t){return t.some(t=>m(t.importPath)?RegExp(`<${t.localName}${_}`).test(e):!1)}function x(e,r,i,a=[]){let o=new Map;for(let s of r){let r=l(s.importPath,i,a),c=u(r),d=RegExp(`<${s.localName}${h}`),f=RegExp(`<${s.localName}${g}`),m=d.test(e),v=f.test(e);if(m||v){o.set(s.localName,{srcPath:r,framework:c,importPath:s.importPath,autoIsland:!1,hasServerProp:v}),v&&t(n(r),r);continue}c&&p.has(c)&&RegExp(`<${s.localName}${_}`).test(e)&&o.set(s.localName,{srcPath:r,framework:c,importPath:s.importPath,autoIsland:!0,hasServerProp:!1})}return o}function S(e,t){for(;t<e.length&&/\s/.test(e[t]);)t++;return t}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 w(e,t){for(t++;t<e.length&&e[t]!=="`";){if(e[t]===`\\`){t+=2;continue}if(e[t]===`$`&&e[t+1]===`{`){t=T(t+1,e);continue}t++}return t<e.length?t+1:t}function T(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=C(t,n):n++}return n<t.length?n+1:n}function E(e,t){let n=t+1,r=T(t,e);return{value:e.slice(n,r-1),endIdx:r}}function D(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 O(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=S(e,r),e[r]!==`=`)return{name:i,value:null,endIdx:r};if(r=S(e,r+1),e[r]===`{`){let t=E(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}if(e[r]===`"`||e[r]===`'`){let t=D(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}return null}function k(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 A(e,t,n){let r=S(e,t+1+n.length),i=null,a=null,o=[];for(;r<e.length;){r=S(e,r);let t=k(e,r,n);if(t)return{endIdx:t.endIdx,islandProp:i,serverProp:a,otherProps:o};let s=O(e,r);if(!s)return null;if(r=s.endIdx,s.name===`island`)i=s.value??`{}`;else if(s.name===`server`)a=s.value??`{}`;else{let e=s.value===null?`${s.name}: true`:`${s.name}: ${s.value}`;o.push(e)}}return null}function j(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 })`;if(e.serverProp){let n=`, server: (${e.serverProp})`,r=e.islandProp?`, island: (${e.islandProp})`:``;return`await __pageRenderIsland({ src: "`+t+`"`+a+s+n+r+o+` })`}let c=e.islandProp??``;return`await __pageRenderIsland({ src: "`+t+`"`+a+s+`, ...(`+c+`)`+o+`, ssr: (`+c+`).ssr !== undefined ? (`+c+`).ssr : true })`}function M(e,t){let n=t-1;for(;n>=0&&/\s/.test(e[n]);)n--;if(n<0)return!1;let r=e[n];return r===`>`?e[n-1]!==`=`:r===`}`}function N(e,t){let n=e.slice(t,t+2);if(e[t]==="`")return w(e,t);if(e[t]===`{`&&n===`{/`&&e[t+2]===`*`)return P(e,t);if(n===`//`){let n=e.indexOf(`
2
- `,t);return n===-1?e.length:n+1}if(n===`/*`){let n=e.indexOf(`*/`,t+2);return n===-1?e.length:n+2}return-1}function P(e,t){let n=e.indexOf(`*/`,t+3);if(n===-1)return-1;let r=n+2;for(;r<e.length&&/\s/.test(e[r]);)r++;return r<e.length&&e[r]===`}`?r+1:-1}function F(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 I(e,t,n,r,i){let a=`<${t}`,o=``,s=0;for(;s<e.length;){let c=N(e,s);if(c!==-1){o+=e.slice(s,c),s=c;continue}let{text:l,next:u}=L(e,s,{tag:a,componentName:t,srcPath:n,framework:r,autoIsland:i});o+=l,s=u}return o}function L(e,t,n){if(!F(e,t,n.tag))return{text:e[t],next:t+1};let r=A(e,t,n.componentName);if(!r||!r.islandProp&&!r.serverProp&&!n.autoIsland){let n=r?r.endIdx:t+1;return{text:e.slice(t,n),next:n}}let i=j(r,n.srcPath,n.framework,n.autoIsland&&!r.islandProp,n.componentName);return{text:M(e,t)?`{${i}}`:i,next:r.endIdx}}function R(e){if(/\bexport\s+default\s+function\b/.test(e))return e.replace(/\bexport\s+default\s+function\b/,`export default async function`);let t=/\bexport\s+default\s+(\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/;if(t.test(e))return e.replace(t,`export default async $1 =>`);let n=/\bexport\s+default\s+([A-Za-z_$][\w$]*)\s*;/.exec(e);if(n){let t=n[1].replaceAll(`$`,String.raw`\$&`),r=new RegExp(String.raw`(^|[^.\w])function\s+${t}\s*\(`,`m`),i=new RegExp(String.raw`\basync\s+function\s+${t}\b`);if(r.test(e)&&!i.test(e))return e.replace(r,e=>e.replace(`function`,`async function`));let a=new RegExp(String.raw`(\b(?:const|let|var)\s+${t}\s*=\s*)(?!async\b)(\([^)]*\)\s*=>|function\b|[A-Za-z_$][\w$]*\s*=>)`);if(a.test(e))return e.replace(a,`$1async $2`)}return e}export function pageIslandTransform(e={}){let{pagesDir:t=`src/pages`,layoutsDir:n=`src/layouts`,modules:i=null}=e,a=[];return{name:`avalon:page-island-transform`,enforce:`pre`,configResolved(e){a=e.resolve?.alias??[]},transform(e,o){let s=f(o,n,i);if(!d(o,t,i)&&!s)return null;let c=r(e);if(c.length===0)return null;let l=c.map(e=>e.localName);if(!v(e,l)&&!y(e,l)&&!b(e,c))return null;let u=x(e,c,o,a);if(u.size===0)return null;let p=`import { renderIsland as __pageRenderIsland } from '@useavalon/avalon';\n${e}`;for(let[e,t]of u)p=I(p,e,t.srcPath,t.framework,t.autoIsland);return p.includes(`__pageRenderIsland(`)&&(p=R(p)),{code:p,map:null}}}}
1
+ import{dirname as e}from"node:path";import{addToManifest as t,generateComponentId as n}from"../server-islands/manifest.js";import{islandSsrExpression as r,isStaticallyClientOnly as i}from"./island-ssr-flag.js";import{ensureAwaitContextsAsync as a}from"./page-island-await.js";function o(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}const s=[{prefix:`@shared/`,map:e=>`/app/shared/${e}`},{prefix:`@modules/`,map:e=>`/app/modules/${e}`},{prefix:`@/`,map:e=>`/app/${e}`},{prefix:`$components/`,map:e=>`/src/components/${e}`},{prefix:`$islands/`,map:e=>`/src/islands/${e}`},{prefix:`~/`,map:e=>`/src/${e}`}];function c(e){return e.startsWith(`/`)?e:`/${e}`}function l(e,t){for(let{find:n,replacement:r}of t){let t=c(r);if(typeof n==`string`){if(e===n||e.startsWith(`${n}/`))return`${t}${e.slice(n.length)}`}else if(n.test(e))return e.replace(n,t)}return null}function u(e){for(let{prefix:t,map:n}of s)if(e.startsWith(t))return n(e.slice(t.length));return null}function d(t,n){if(!t.startsWith(`.`))return null;let r=n.replaceAll(`\\`,`/`),i=r.indexOf(`/app/`);if(i===-1&&(i=r.indexOf(`/src/`)),i===-1)return null;let a=e(r.slice(i)).split(`/`);for(let e of t.split(`/`))e===`..`?a.pop():e!==`.`&&a.push(e);return a.join(`/`)}function f(e,t,n=[]){return e.startsWith(`/`)?e:l(e,n)??u(e)??d(e,t)??`/src/${e.split(`/`).pop()}`}function p(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 m(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 h(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 g=new Set([`qwik`]);function _(e){let t=p(e);return t!==void 0&&g.has(t)}const v=String.raw`[\s][^>]*island[\s]*[={]`,y=String.raw`[\s][^>]*server[\s]*[={]`,b=String.raw`[\s/>]`;function x(e,t){return t.some(t=>RegExp(`<${t}${v}`).test(e))}function S(e,t){return t.some(t=>RegExp(`<${t}${y}`).test(e))}function C(e,t){return t.some(t=>_(t.importPath)?RegExp(`<${t.localName}${b}`).test(e):!1)}function w(e,r,i,a=[]){let o=new Map;for(let s of r){let r=f(s.importPath,i,a),c=p(r),l=RegExp(`<${s.localName}${v}`),u=RegExp(`<${s.localName}${y}`),d=l.test(e),m=u.test(e);if(d||m){o.set(s.localName,{srcPath:r,framework:c,importPath:s.importPath,autoIsland:!1,hasServerProp:m}),m&&t(n(r),r);continue}c&&g.has(c)&&RegExp(`<${s.localName}${b}`).test(e)&&o.set(s.localName,{srcPath:r,framework:c,importPath:s.importPath,autoIsland:!0,hasServerProp:!1})}return o}function T(e,t){for(;t<e.length&&/\s/.test(e[t]);)t++;return t}function E(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 D(e,t){for(t++;t<e.length&&e[t]!=="`";){if(e[t]===`\\`){t+=2;continue}if(e[t]===`$`&&e[t+1]===`{`){t=O(t+1,e);continue}t++}return t<e.length?t+1:t}function O(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=E(t,n):n++}return n<t.length?n+1:n}function k(e,t){let n=t+1,r=O(t,e);return{value:e.slice(n,r-1),endIdx:r}}function A(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 j(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=T(e,r),e[r]!==`=`)return{name:i,value:null,endIdx:r};if(r=T(e,r+1),e[r]===`{`){let t=k(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}if(e[r]===`"`||e[r]===`'`){let t=A(e,r);return{name:i,value:t.value,endIdx:t.endIdx}}return null}function M(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 N(e,t,n){let r=T(e,t+1+n.length),i=null,a=null,o=null,s=[];for(;r<e.length;){r=T(e,r);let t=M(e,r,n);if(t)return{endIdx:t.endIdx,islandProp:i,serverProp:a,keyProp:o,otherProps:s};let c=j(e,r);if(!c)return null;if(r=c.endIdx,c.name===`island`)i=c.value??`{}`;else if(c.name===`server`)a=c.value??`{}`;else if(c.name===`key`)o=c.value;else{let e=c.value===null?`${c.name}: true`:`${c.name}: ${c.value}`;s.push(e)}}return null}function P(e){return e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`)}function F(e,t,n){let r=new RegExp(String.raw`\b${P(t)}\b`,`g`);for(let t=r.exec(e);t!==null;t=r.exec(e)){let e=t.index;if(!n.some(([t,n])=>e>=t&&e<n))return!0}return!1}function I(e,t){let n=new Set;for(let r of t){let t=L(e,r),a=t.filter(e=>e.islandProp&&!e.serverProp&&i(e.islandProp));if(a.length===0||t.filter(e=>e.islandProp).length!==a.length)continue;let o=a.map(e=>[e.start,e.end]),s=new RegExp(String.raw`^[ \t]*import\s+${P(r)}\s+from\s+['"][^'"]+['"];?`,`m`).exec(e);s&&o.push([s.index,s.index+s[0].length]),F(e,r,o)||n.add(r)}return n}function L(e,t){let n=`<${t}`,r=[],i=0;for(;i<e.length;){let a=V(e,i);if(a!==-1){i=a;continue}if(!U(e,i,n)){i++;continue}let o=N(e,i,t);if(!o){i++;continue}r.push({start:i,end:o.endIdx,islandProp:o.islandProp,serverProp:o.serverProp}),i=o.endIdx}return r}function R(e,t){let n=e;for(let e of t)n.includes(`component: ${e}`)||(n=n.replace(new RegExp(String.raw`^[ \t]*import\s+${P(e)}\s+from\s+['"][^'"]+['"];?\s*\n?`,`m`),``));return n}function z(e,t,n,i,a,o){let s=n?`, framework: "${n}"`:``,c=e.otherProps.length>0?`, props: { ${e.otherProps.join(`, `)} }`:``,l=e.keyProp==null?``:`, key: (${e.keyProp})`,u=o?``:`, component: ${a}`;if(i)return`await __pageRenderIsland({ src: "`+t+`"`+s+u+c+l+`, ssr: true, ssrOnly: true })`;if(e.serverProp){let n=`, server: (${e.serverProp})`,r=e.islandProp?`, island: (${e.islandProp})`:``;return`await __pageRenderIsland({ src: "`+t+`"`+s+u+n+r+c+l+` })`}let d=e.islandProp??``;return`await __pageRenderIsland({ src: "`+t+`"`+s+u+`, ...(`+d+`)`+c+`, ssr: `+r(d)+l+` })`}function B(e,t){let n=t-1;for(;n>=0&&/\s/.test(e[n]);)n--;if(n<0)return!1;let r=e[n];return r===`>`?e[n-1]!==`=`:r===`}`}function V(e,t){let n=e.slice(t,t+2);if(e[t]==="`")return D(e,t);if(e[t]===`{`&&n===`{/`&&e[t+2]===`*`)return H(e,t);if(n===`//`){let n=e.indexOf(`
2
+ `,t);return n===-1?e.length:n+1}if(n===`/*`){let n=e.indexOf(`*/`,t+2);return n===-1?e.length:n+2}return-1}function H(e,t){let n=e.indexOf(`*/`,t+3);if(n===-1)return-1;let r=n+2;for(;r<e.length&&/\s/.test(e[r]);)r++;return r<e.length&&e[r]===`}`?r+1:-1}function U(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 W(e,t,n,r,i,a){let o=`<${t}`,s=``,c=0;for(;c<e.length;){let l=V(e,c);if(l!==-1){s+=e.slice(c,l),c=l;continue}let{text:u,next:d}=G(e,c,{tag:o,componentName:t,srcPath:n,framework:r,autoIsland:i,omitComponent:a});s+=u,c=d}return s}function G(e,t,n){if(!U(e,t,n.tag))return{text:e[t],next:t+1};let r=N(e,t,n.componentName);if(!r||!r.islandProp&&!r.serverProp&&!n.autoIsland){let n=r?r.endIdx:t+1;return{text:e.slice(t,n),next:n}}let a=z(r,n.srcPath,n.framework,n.autoIsland&&!r.islandProp,n.componentName,n.omitComponent&&i(r.islandProp));return{text:B(e,t)?`{${a}}`:a,next:r.endIdx}}function K(e){if(/\bexport\s+default\s+function\b(?!\s*\*)/.test(e))return e.replace(/\bexport\s+default\s+function\b(?!\s*\*)/,`export default async function`);let t=/\bexport\s+default\s+(\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/;if(t.test(e))return e.replace(t,`export default async $1 =>`);let n=/\bexport\s+default\s+([A-Za-z_$][\w$]*)\s*;/.exec(e);if(n){let t=n[1].replaceAll(`$`,String.raw`\$&`),r=new RegExp(String.raw`(^|[^.\w])function\s+${t}\s*\(`,`m`),i=new RegExp(String.raw`\basync\s+function\s+${t}\b`);if(r.test(e)&&!i.test(e))return e.replace(r,e=>e.replace(`function`,`async function`));let a=new RegExp(String.raw`(\b(?:const|let|var)\s+${t}\s*=\s*)(?!async\b)(\([^)]*\)\s*=>|function\b|[A-Za-z_$][\w$]*\s*=>)`);if(a.test(e))return e.replace(a,`$1async $2`)}return e}export function pageIslandTransform(e={}){let{pagesDir:t=`src/pages`,layoutsDir:n=`src/layouts`,modules:r=null}=e,i=[];return{name:`avalon:page-island-transform`,enforce:`pre`,configResolved(e){i=e.resolve?.alias??[]},transform(e,s){let c=h(s,n,r);if(!m(s,t,r)&&!c)return null;let l=o(e);if(l.length===0)return null;let u=l.map(e=>e.localName);if(!x(e,u)&&!S(e,u)&&!C(e,l))return null;let d=w(e,l,s,i);if(d.size===0)return null;let f=I(e,[...d.keys()]),p=`import { renderIsland as __pageRenderIsland } from '@useavalon/avalon';\n${e}`;for(let[e,t]of d)p=W(p,e,t.srcPath,t.framework,t.autoIsland,f.has(e));return p=R(p,f),p.includes(`__pageRenderIsland(`)&&(p=K(p),p=a(p,s)),p.includes(`__pageKeyed(`)&&(p=p.replace(`import { renderIsland as __pageRenderIsland } from '@useavalon/avalon';`,`import { renderIsland as __pageRenderIsland, withListKey as __pageKeyed } from '@useavalon/avalon';`)),{code:p,map:null}}}}
@@ -1,94 +1,11 @@
1
1
  /**
2
- * CSS HMR Handler
3
- *
4
- * Handles Hot Module Replacement for CSS files including:
5
- * - Global CSS files
6
- * - CSS modules
7
- * - Component-scoped styles (Svelte, Vue)
2
+ * Apply Avalon-owned CSS HMR. Writes `textContent` on a `<style>` tag so
3
+ * previous rules stay until the new ones are in the DOM.
8
4
  */
9
- import type { Update } from "./hmr-coordinator.ts";
5
+ export declare function normalizeCssHref(path: string): string;
10
6
  /**
11
- * CSS update types
7
+ * Cache-bust the matching `<link>` (`v=`, Vite strips `t=`) and write the
8
+ * payload into a `<style>` tag so the change is visible before the refetch.
12
9
  */
13
- export type CSSUpdateType = "global" | "module" | "scoped";
14
- /**
15
- * CSS update information
16
- */
17
- export interface CSSUpdateInfo {
18
- type: CSSUpdateType;
19
- path: string;
20
- timestamp: number;
21
- affectedComponents?: string[];
22
- }
23
- /**
24
- * CSS HMR Handler class
25
- * Manages CSS hot updates without page reload
26
- */
27
- export declare class CSSHMRHandler {
28
- private cssModuleMap;
29
- private styleElementMap;
30
- /**
31
- * Handle CSS update from Vite HMR
32
- */
33
- handleCSSUpdate(update: Update): void;
34
- /**
35
- * Classify the type of CSS update
36
- */
37
- private classifyCSSUpdate;
38
- /**
39
- * Handle global CSS file update
40
- * Injects updated styles without page reload
41
- */
42
- private handleGlobalCSSUpdate;
43
- /**
44
- * Handle CSS module update
45
- * Re-renders components using the updated CSS module
46
- */
47
- private handleCSSModuleUpdate;
48
- /**
49
- * Handle scoped CSS update (Svelte/Vue)
50
- * Updates only the affected component's styles
51
- */
52
- private handleScopedCSSUpdate;
53
- /**
54
- * Find islands that use a specific CSS module
55
- */
56
- private findIslandsUsingCSSModule;
57
- /**
58
- * Find islands using a specific component file
59
- */
60
- private findIslandsUsingComponent;
61
- /**
62
- * Trigger re-render of an island to apply new CSS module classes
63
- */
64
- private triggerIslandRerender;
65
- /**
66
- * Dispatch CSS update event for feedback
67
- */
68
- private dispatchCSSUpdateEvent;
69
- /**
70
- * Normalize a file path for comparison
71
- */
72
- private normalizePath;
73
- /**
74
- * Get directory from a file path
75
- */
76
- private getDirectory;
77
- /**
78
- * Get file ID from path (for Vite's data-vite-dev-id)
79
- */
80
- private getFileId;
81
- /**
82
- * Clear cached mappings
83
- */
84
- clearCache(): void;
85
- /**
86
- * Register an island as using a CSS module
87
- * Useful for explicit tracking
88
- */
89
- registerCSSModuleUsage(cssPath: string, island: HTMLElement): void;
90
- }
91
- /**
92
- * Get or create the global CSS HMR handler instance
93
- */
94
- export declare function getCSSHMRHandler(): CSSHMRHandler;
10
+ export declare function applyDevCssHot(doc: Document, href: string, css: string): void;
11
+ export declare function applyCssText(doc: Document, href: string, css: string): void;
@@ -1 +1 @@
1
- export class CSSHMRHandler{cssModuleMap=new Map;styleElementMap=new Map;handleCSSUpdate(e){let t=this.classifyCSSUpdate(e);switch(t.type){case`global`:this.handleGlobalCSSUpdate(t);break;case`module`:this.handleCSSModuleUpdate(t);break;case`scoped`:this.handleScopedCSSUpdate(t);break}}classifyCSSUpdate(e){let t=e.path||e.acceptedPath;return t.includes(`.module.css`)||t.includes(`.module.scss`)?{type:`module`,path:t,timestamp:e.timestamp}:t.includes(`.svelte`)||t.includes(`.vue`)?{type:`scoped`,path:t,timestamp:e.timestamp}:{type:`global`,path:t,timestamp:e.timestamp}}handleGlobalCSSUpdate(e){try{let t=this.styleElementMap.get(e.path);t&&(t.remove(),this.styleElementMap.delete(e.path));let n=document.querySelector(`style[data-vite-dev-id*="${this.getFileId(e.path)}"]`);n&&this.styleElementMap.set(e.path,n),this.dispatchCSSUpdateEvent(e,!0)}catch(t){throw console.error(`Failed to update global CSS: ${e.path}`,t),this.dispatchCSSUpdateEvent(e,!1,t),t}}handleCSSModuleUpdate(e){try{let t=this.findIslandsUsingCSSModule(e.path);if(t.length===0)return;for(let n of t)this.triggerIslandRerender(n,e);this.dispatchCSSUpdateEvent(e,!0)}catch(t){throw console.error(`[HMR] Failed to update CSS module: ${e.path}`,t),this.dispatchCSSUpdateEvent(e,!1,t),t}}handleScopedCSSUpdate(e){try{if(this.findIslandsUsingComponent(e.path).length===0)return;this.dispatchCSSUpdateEvent(e,!0)}catch(t){throw console.error(`[HMR] Failed to update scoped CSS: ${e.path}`,t),this.dispatchCSSUpdateEvent(e,!1,t),t}}findIslandsUsingCSSModule(e){let t=[],n=this.normalizePath(e),r=this.cssModuleMap.get(n);if(r)return Array.from(r);let i=document.querySelectorAll(`[data-src]`);for(let n of i){let r=n.getAttribute(`data-src`);r&&this.getDirectory(r)===this.getDirectory(e)&&t.push(n)}return t.length>0&&this.cssModuleMap.set(n,new Set(t)),t}findIslandsUsingComponent(e){let t=[],n=this.normalizePath(e),r=document.querySelectorAll(`[data-src]`);for(let e of r){let r=e.getAttribute(`data-src`);if(!r)continue;let i=this.normalizePath(r);(i===n||i.includes(n))&&t.push(e)}return t}triggerIslandRerender(e,t){e.dispatchEvent(new CustomEvent(`css-module-update`,{detail:{cssPath:t.path,timestamp:t.timestamp},bubbles:!0}));let n=e.getAttribute(`data-src`);n&&e.dispatchEvent(new CustomEvent(`hmr-update-required`,{detail:{src:n,reason:`css-module-update`,cssPath:t.path},bubbles:!0}))}dispatchCSSUpdateEvent(e,t,n){let r=new CustomEvent(`css-hmr-update`,{detail:{type:e.type,path:e.path,timestamp:e.timestamp,success:t,error:n?.message},bubbles:!0});document.dispatchEvent(r)}normalizePath(e){return e.replace(/\\/g,`/`).replace(/^\//,``).replace(/\?.*$/,``).replace(/#.*$/,``)}getDirectory(e){let t=this.normalizePath(e),n=t.lastIndexOf(`/`);return n>=0?t.substring(0,n):``}getFileId(e){return this.normalizePath(e)}clearCache(){this.cssModuleMap.clear(),this.styleElementMap.clear()}registerCSSModuleUsage(e,t){let n=this.normalizePath(e);this.cssModuleMap.has(n)||this.cssModuleMap.set(n,new Set),this.cssModuleMap.get(n).add(t)}}let t=null;export function getCSSHMRHandler(){return t||=new CSSHMRHandler,t}
1
+ export function normalizeCssHref(e){let t=(e.split(`?`)[0]?.split(`#`)[0]??e).replaceAll(`\\`,`/`);return t.startsWith(`/`)?t:`/${t}`}function t(e){return e.dataset.avalonCss}function n(e,n){for(let r of e.querySelectorAll(`style[data-avalon-css]`))if(t(r)===n)return r}export function applyDevCssHot(n,r,a){let o=normalizeCssHref(r);for(let e of n.querySelectorAll(`link[data-avalon-css]`))t(e)===o&&(e.href=`${o}?direct&v=${Date.now()}`);a&&applyCssText(n,r,a)}export function applyCssText(t,r,i){if(!i||i.includes(`__vite__updateStyle`)||i.includes(`import.meta.hot`))return;let a=normalizeCssHref(r),o=n(t,a);o||(o=t.createElement(`style`),o.dataset.avalonCss=a,t.head.appendChild(o)),o.textContent=i}
@@ -1 +1 @@
1
- const e=new Map;export function registerClientDirective(t,n){e.set(t,n)}export function hasClientDirective(t){return e.has(t)}export function executeCustomDirective(t,n,r){let i=t.dataset.conditionArg||void 0;if(e.has(n)){let a=e.get(n);try{a(t,r,i)}catch(e){console.error(`[avalon] Custom directive "${n}" threw:`,e),r()}return!0}let a=t.dataset.directiveScript;if(a){try{let o=Function(`return (`+a+`)`)();e.set(n,o),o(t,r,i)}catch(e){console.error(`[avalon] Failed to execute inline directive "${n}":`,e),r()}return!0}return!1}typeof globalThis<`u`&&(globalThis.__avalon_registerDirective=registerClientDirective);
1
+ const e=new Map;export function registerClientDirective(t,n){e.set(t,n)}export function hasClientDirective(t){return e.has(t)}export function executeCustomDirective(t,n,r){let i=e.get(n),a=t.dataset.conditionArg;if(i)return i(t,r,a),!0;let o=t.dataset.directiveScript;if(!o)return!1;try{let e=Function(`return (${o})`)();return typeof e==`function`?(e(t,r,a),!0):!1}catch(e){return console.warn(`[avalon] Failed to execute custom directive "${n}":`,e),!1}}
@@ -72,7 +72,6 @@ export declare class HMRCoordinator {
72
72
  registerAdapter(framework: string, adapter: FrameworkHMRAdapter): void;
73
73
  getRegistry(): AdapterRegistry;
74
74
  handleUpdate(payload: HMRUpdatePayload): Promise<void>;
75
- private processCSSUpdates;
76
75
  private queueJSUpdates;
77
76
  private processUpdateQueue;
78
77
  findAffectedIslands(modulePath: string): HTMLElement[];
@@ -1 +1 @@
1
- import{getCSSHMRHandler as e}from"./css-hmr-handler.js";import{AdapterRegistry as t}from"./framework-adapter.js";export class HMRCoordinator{registry=new t;stateSnapshots=new Map;updateQueue=new Set;isProcessing=!1;initialize(){import.meta.hot&&(import.meta.hot.accept(),import.meta.hot.on(`vite:beforeUpdate`,e=>{this.handleUpdate(e)}),import.meta.hot.on(`vite:beforeFullReload`,()=>{this.handleBeforeFullReload()}),import.meta.hot.on(`vite:error`,e=>{console.error(`[HMR] error:`,e),this.handleError(e)}),document.addEventListener(`hmr-update-required`,e=>{let{src:t,reason:n}=e.detail;n===`css-module-update`&&(this.updateQueue.add(this.normalizePath(t)),this.isProcessing||this.processUpdateQueue().catch(e=>{console.error(`[HMR] Failed to process CSS module update:`,e)}))}))}registerAdapter(e,t){this.registry.register(e,t)}getRegistry(){return this.registry}async handleUpdate(e){if(e.type!==`update`||!e.updates)return;let t=[],n=[];for(let r of e.updates)r.type===`css-update`?t.push(r):n.push(r);this.processCSSUpdates(t),this.queueJSUpdates(n),!this.isProcessing&&this.updateQueue.size>0&&await this.processUpdateQueue()}processCSSUpdates(t){if(t.length===0)return;let n=e();for(let e of t)try{n.handleCSSUpdate(e)}catch(e){console.error(`[HMR] CSS update failed:`,e)}}queueJSUpdates(e){for(let t of e){let e=this.normalizePath(t.path||t.acceptedPath);this.isIslandModule(e)&&this.updateQueue.add(e)}}async processUpdateQueue(){if(this.updateQueue.size!==0){this.isProcessing=!0;try{let e=Array.from(this.updateQueue);this.updateQueue.clear();for(let t of e){let e=this.findAffectedIslands(t);for(let t of e)try{await this.updateIsland(t)}catch(e){console.error(`[HMR] Failed to update island:`,e)}}}finally{this.isProcessing=!1}}}findAffectedIslands(e){let t=[],n=this.normalizePath(e),r=document.querySelectorAll(`[data-src]`);for(let e of r){let r=e.dataset.src;if(!r)continue;let i=this.normalizePath(r);(i===n||i.endsWith(n)||n.endsWith(i)||i.split(`/`).pop()===n.split(`/`).pop())&&t.push(e)}return t}async updateIsland(e){let t=e.dataset.framework,n=e.dataset.src,r=e.dataset.props;if(!t||!n){console.warn(`[HMR] Island missing framework or src attribute`,e);return}let i=this.registry.get(t.toLowerCase());if(!i){console.warn(`[HMR] No adapter registered for framework: ${t}`);return}try{let a=r?JSON.parse(r):{},o=i.preserveState(e);o&&this.stateSnapshots.set(this.getIslandId(e),o),delete e.dataset.hydrated,delete e.dataset.hydrationStatus,e.querySelector(`.hydration-error-indicator, .hmr-error-indicator`)?.remove();let s=Date.now(),c=await import(n.includes(`?`)?`${n}&t=${s}`:`${n}?t=${s}`),l=this.resolveComponent(c,n);await i.update(e,l,a),o&&(i.restoreState(e,o),this.stateSnapshots.delete(this.getIslandId(e))),e.dataset.hydrated=`true`,e.dispatchEvent(new CustomEvent(`hmr-update`,{detail:{framework:t,src:n,timestamp:Date.now(),success:!0},bubbles:!0}))}catch(r){throw console.error(`[HMR] Failed to update ${t} island ${n}:`,r),i.handleError(e,r),e.dispatchEvent(new CustomEvent(`hmr-error`,{detail:{framework:t,src:n,error:r.message,timestamp:Date.now()},bubbles:!0})),r}}resolveComponent(e,t){if(e.default)return e.default;for(let t of Object.keys(e)){if(t===`default`)continue;let n=e[t];if(typeof n==`function`&&n.prototype)return n}throw Error(`Component ${t} has no default export`)}handleBeforeFullReload(){let e=document.querySelectorAll(`[data-hydrated="true"]`),t={};for(let n of e){let e=n.dataset.framework,r=n.dataset.src;if(!e||!r)continue;let i=this.registry.get(e.toLowerCase());if(!i)continue;let a=i.preserveState(n);a&&(t[r]=a)}try{sessionStorage.setItem(`__avalon_hmr_states__`,JSON.stringify(t))}catch(e){console.warn(`[HMR] Failed to save states:`,e)}}handleError(e){let t=Error(e.err.message);t.stack=e.err.stack,console.error(`[HMR] Error:`,t),globalThis.window!==void 0&&import(`./hmr-error-overlay.js`).then(({showHMRErrorOverlay:n})=>{n({framework:`unknown`,src:`unknown`,error:t,filePath:e.err.id||e.err.loc?.file||`unknown`,line:e.err.loc?.line,column:e.err.loc?.column})}).catch(()=>{console.error(`[HMR] Failed to show error overlay`)})}normalizePath(e){return e.replaceAll(`\\`,`/`).replace(/^\//,``).replace(/\?.*$/,``).replace(/#.*$/,``).replace(/^src\//,``)}isIslandModule(e){return e.includes(`/islands/`)||e.includes(`\\islands\\`)}getIslandId(e){let t=e.dataset.src??``;return`${e.dataset.framework??``}:${t}:${Array.from(document.querySelectorAll(`[data-src="${t}"]`)).indexOf(e)}`}}let r=null;export function getHMRCoordinator(){return r??=new HMRCoordinator,r}export function initializeHMR(){import.meta.hot&&getHMRCoordinator().initialize()}
1
+ import{AdapterRegistry as e}from"./framework-adapter.js";export class HMRCoordinator{registry=new e;stateSnapshots=new Map;updateQueue=new Set;isProcessing=!1;initialize(){import.meta.hot&&(import.meta.hot.accept(),import.meta.hot.on(`vite:beforeUpdate`,e=>this.handleUpdate(e)),import.meta.hot.on(`vite:beforeFullReload`,()=>{this.handleBeforeFullReload()}),import.meta.hot.on(`vite:error`,e=>{console.error(`[HMR] error:`,e),this.handleError(e)}),document.addEventListener(`hmr-update-required`,e=>{let{src:t,reason:n}=e.detail;n===`css-module-update`&&(this.updateQueue.add(this.normalizePath(t)),this.isProcessing||this.processUpdateQueue().catch(e=>{console.error(`[HMR] Failed to process CSS module update:`,e)}))}))}registerAdapter(e,t){this.registry.register(e,t)}getRegistry(){return this.registry}async handleUpdate(e){if(e.type!==`update`||!e.updates)return;let t=[];for(let n of e.updates)n.type===`js-update`&&t.push(n);this.queueJSUpdates(t),!this.isProcessing&&this.updateQueue.size>0&&await this.processUpdateQueue()}queueJSUpdates(e){for(let t of e){let e=this.normalizePath(t.path??t.acceptedPath);this.isIslandModule(e)&&this.updateQueue.add(e)}}async processUpdateQueue(){if(this.updateQueue.size!==0){this.isProcessing=!0;try{let e=Array.from(this.updateQueue);this.updateQueue.clear();for(let t of e){let e=this.findAffectedIslands(t);for(let t of e)try{await this.updateIsland(t)}catch(e){console.error(`[HMR] Failed to update island:`,e)}}}finally{this.isProcessing=!1}}}findAffectedIslands(e){let t=[],n=this.normalizePath(e),r=document.querySelectorAll(`[data-src]`);for(let e of r){let r=e.dataset.src;if(!r)continue;let i=this.normalizePath(r);(i===n||i.endsWith(n)||n.endsWith(i)||i.split(`/`).pop()===n.split(`/`).pop())&&t.push(e)}return t}async updateIsland(e){let t=e.dataset.framework,n=e.dataset.src,r=e.dataset.props;if(!t||!n){console.warn(`[HMR] Island missing framework or src attribute`,e);return}let i=this.registry.get(t.toLowerCase());if(!i){console.warn(`[HMR] No adapter registered for framework: ${t}`);return}try{let a=r?JSON.parse(r):{},o=i.preserveState(e);o&&this.stateSnapshots.set(this.getIslandId(e),o),delete e.dataset.hydrated,delete e.dataset.hydrationStatus,e.querySelector(`.hydration-error-indicator, .hmr-error-indicator`)?.remove();let s=Date.now(),c=await import(n.includes(`?`)?`${n}&t=${s}`:`${n}?t=${s}`),l=this.resolveComponent(c,n);await i.update(e,l,a),o&&(i.restoreState(e,o),this.stateSnapshots.delete(this.getIslandId(e))),e.dataset.hydrated=`true`,e.dispatchEvent(new CustomEvent(`hmr-update`,{detail:{framework:t,src:n,timestamp:Date.now(),success:!0},bubbles:!0}))}catch(r){throw console.error(`[HMR] Failed to update ${t} island ${n}:`,r),i.handleError(e,r),e.dispatchEvent(new CustomEvent(`hmr-error`,{detail:{framework:t,src:n,error:r.message,timestamp:Date.now()},bubbles:!0})),r}}resolveComponent(e,t){if(e.default)return e.default;for(let t of Object.keys(e)){if(t===`default`)continue;let n=e[t];if(typeof n==`function`&&n.prototype)return n}throw Error(`Component ${t} has no default export`)}handleBeforeFullReload(){let e=document.querySelectorAll(`[data-hydrated="true"]`),t={};for(let n of e){let e=n.dataset.framework,r=n.dataset.src;if(!e||!r)continue;let i=this.registry.get(e.toLowerCase());if(!i)continue;let a=i.preserveState(n);a&&(t[r]=a)}try{sessionStorage.setItem(`__avalon_hmr_states__`,JSON.stringify(t))}catch(e){console.warn(`[HMR] Failed to save states:`,e)}}handleError(e){let t=Error(e.err.message);t.stack=e.err.stack,console.error(`[HMR] Error:`,t),globalThis.window!==void 0&&import(`./hmr-error-overlay.js`).then(({showHMRErrorOverlay:n})=>{n({framework:`unknown`,src:`unknown`,error:t,filePath:e.err.id??e.err.loc?.file??`unknown`,line:e.err.loc?.line,column:e.err.loc?.column})}).catch(()=>{console.error(`[HMR] Failed to show error overlay`)})}normalizePath(e){let t=e.replaceAll(`\\`,`/`);t.startsWith(`/`)&&(t=t.slice(1));let n=t.indexOf(`?`);n!==-1&&(t=t.slice(0,n));let r=t.indexOf(`#`);return r!==-1&&(t=t.slice(0,r)),t.startsWith(`src/`)&&(t=t.slice(4)),t}isIslandModule(e){return e.includes(`/islands/`)||e.includes(`\\islands\\`)}getIslandId(e){let t=e.dataset.src??``,n=e.dataset.framework??``,r=0;for(let n of document.querySelectorAll(`[data-src]`)){if(n===e)break;n.dataset.src===t&&(r+=1)}return`${n}:${t}:${r}`}}let n=null;export function getHMRCoordinator(){return n??=new HMRCoordinator,n}export function initializeHMR(){import.meta.hot&&getHMRCoordinator().initialize()}
@@ -0,0 +1,18 @@
1
+ export interface HMRErrorOverlayOptions {
2
+ framework: string;
3
+ src: string;
4
+ error: Error;
5
+ filePath?: string;
6
+ line?: number;
7
+ column?: number;
8
+ }
9
+
10
+ export interface HMRToastOptions {
11
+ message: string;
12
+ type?: "info" | "error" | "success";
13
+ duration?: number;
14
+ }
15
+
16
+ export declare function showHMRErrorOverlay(options: HMRErrorOverlayOptions): void;
17
+ export declare function removeHMRErrorOverlay(): void;
18
+ export declare function showHMRToast(options: HMRToastOptions): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Re-entrant island hydrator.
3
+ *
4
+ * First load and client navigations both call {@link scanAndHydrate}.
5
+ * {@link disposeIslands} tears down every island in a root before a DOM swap.
6
+ */
7
+ export type HydrateFn = (el: HTMLElement, Component: unknown, props: Record<string, unknown>) => void | Promise<void>;
8
+ export type UnmountFn = (el: HTMLElement) => void | Promise<void>;
9
+ export interface IntegrationModule {
10
+ hydrate?: HydrateFn;
11
+ mount?: HydrateFn;
12
+ unmount?: UnmountFn;
13
+ preLitHydration?: () => Promise<void>;
14
+ }
15
+ export interface HydrationLoader {
16
+ loadIntegrationModule: (framework: string) => Promise<IntegrationModule>;
17
+ preLitHydration?: () => Promise<void>;
18
+ /** Test seam — production uses dynamic `import(data-src)`. */
19
+ loadComponent?: (src: string) => Promise<Record<string, unknown>>;
20
+ }
21
+ /** Test seam — production uses `virtual:avalon/integration-loader`. */
22
+ export declare function setHydrationLoader(loader: HydrationLoader | null): void;
23
+ /**
24
+ * Discover `[data-framework]` islands under `root` and hydrate them.
25
+ * Safe to call after a body swap. Already-hydrated islands are skipped.
26
+ */
27
+ export declare function scanAndHydrate(root?: ParentNode): void;
28
+ /**
29
+ * Dispose islands under `root`: observers, idle timers, and framework roots.
30
+ * Nodes inside `[data-router-persist]` stay mounted so persist chrome can
31
+ * remain in the old view-transition snapshot.
32
+ */
33
+ export declare function disposeIslands(root?: ParentNode): Promise<void>;
@@ -0,0 +1 @@
1
+ import{executeCustomDirective as e,hasClientDirective as t}from"./custom-directives.js";const n=new WeakMap;let r=null;export function setHydrationLoader(e){r=e}async function a(){return r||import(`virtual:avalon/integration-loader`)}function o(e,t){let r=n.get(e)??[];r.push(t),n.set(e,r)}function s(e){let t=n.get(e);if(t){for(let e of t)try{e()}catch(e){console.warn(`[avalon] Island cleanup failed:`,e)}n.delete(e)}}function c(e,t){let n=e.default;if(!n){let t=Object.keys(e).filter(e=>e!==`default`);for(let r of t){let t=e[r];if(typeof t==`function`){n=t;break}}n||=e}if(!n)throw Error(`Component ${t} has no default export`);return n}function l(e,t){let n=t?e.__mountIsland:e.__hydrateIsland;return typeof n==`function`?n:void 0}async function u(e,t){return e.loadComponent?await e.loadComponent(t):await import(t)}async function d(e,t,n){let r=e.dataset.src;if(r)try{let t=(await u(n,r)).__unmountIsland;if(typeof t==`function`){await t(e);return}}catch{}let i=await n.loadIntegrationModule(t);typeof i.unmount==`function`&&await i.unmount(e)}async function f(e,t){if(e.dataset.hydrated)return;let n=e.dataset.src;if(!n){console.warn(`Island missing data-src attribute`);return}try{let r=e.dataset.props?JSON.parse(e.dataset.props):{},i=await a();t===`lit`&&await(i.preLitHydration?.()??i.loadIntegrationModule(`lit`).then(e=>e.preLitHydration?.()));let o=await u(i,n),s=c(o,n),d=e.dataset.renderStrategy===`client-only`,f=d?`mount`:`hydrate`,p=l(o,d);if(!p){let e=await i.loadIntegrationModule(t);p=d?e.mount:e.hydrate}if(!p||typeof p!=`function`)throw Error(`Integration ${t} does not export a ${f} function`);await p(e,s,r),e.dataset.hydrated=`true`}catch(r){let i=r instanceof Error?r.message:String(r);console.error(`Hydration error for ${t} island ${n}:`,r),e.dataset.hydrationStatus=`failed`,e.dataset.renderStrategy=`ssr-only`,e.dispatchEvent(new CustomEvent(`hydration-error`,{detail:{framework:t,src:n,error:i,timestamp:Date.now()},bubbles:!0}))}}function p(e,t){try{let n=new IntersectionObserver(r=>{r[0]?.isIntersecting&&(f(e,t),n.disconnect())},{rootMargin:`50px`,threshold:0});n.observe(e.firstElementChild||e),o(e,()=>n.disconnect())}catch(n){console.error(`Failed to setup intersection observer:`,n),f(e,t)}}function m(e,t){let n=[`click`,`touchstart`,`mouseenter`,`focusin`],r=!1,i=e.firstElementChild||e,a=()=>{if(!r){r=!0;for(let e of n)i.removeEventListener(e,a);f(e,t)}};try{for(let e of n)i.addEventListener(e,a,{once:!0,passive:!0});o(e,()=>{r=!0;for(let e of n)i.removeEventListener(e,a)})}catch(n){console.error(`Failed to setup interaction observer:`,n),f(e,t)}}function h(e,t){try{if(`requestIdleCallback`in globalThis){let n=globalThis.requestIdleCallback(()=>{f(e,t)},{timeout:5e3});o(e,()=>globalThis.cancelIdleCallback?.(n));return}let n=setTimeout(()=>{f(e,t)},200);o(e,()=>clearTimeout(n))}catch(n){console.error(`Failed to setup idle callback:`,n),f(e,t)}}function g(e,t,n){try{let r=globalThis.matchMedia(n);if(r.matches){f(e,t);return}let i=n=>{n.matches&&(f(e,t),r.removeEventListener(`change`,i))};r.addEventListener(`change`,i),o(e,()=>r.removeEventListener(`change`,i))}catch(r){console.error(`Failed to setup media query:`,n,r),f(e,t)}}function _(n){let r=n.dataset.framework,i=n.dataset.condition||`on:client`,a=n.dataset.renderStrategy;if(r&&a!==`ssr-only`&&!n.dataset.hydrated){if(i===`on:client`){f(n,r);return}if(i===`on:visible`){p(n,r);return}if(i===`on:interaction`){m(n,r);return}if(i===`on:idle`){h(n,r);return}if(i.startsWith(`media:`)){g(n,r,i.slice(6));return}if(n.dataset.customDirective||n.dataset.directiveScript||t(i)){e(n,i,()=>{f(n,r)})||(console.warn(`[avalon] Unknown hydration condition: "${i}". Hydrating immediately.`),f(n,r));return}f(n,r)}}export function scanAndHydrate(e=document){let t=e.querySelectorAll(`[data-framework]`);for(let e of t)try{_(e)}catch(e){console.error(`Error processing island:`,e)}}export async function disposeIslands(e=document){let t=[...e.querySelectorAll(`[data-framework]`)].filter(e=>!e.closest?.(`[data-router-persist]`)),n=t.length>0?await a():null;for(let e of t){s(e);let t=e.dataset.framework;if(t&&n)try{await d(e,t,n)}catch(e){console.warn(`[avalon] Failed to unmount ${t} island:`,e)}delete e.dataset.hydrated,delete e.dataset.hydrationStatus,delete e.dataset.hydrationError,delete e.dataset.litHydrated}}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared vs per-island hydration.
3
+ *
4
+ * Dev always uses a long-lived entry-client runtime (HMR). Production uses
5
+ * per-island inline scripts unless `clientRouter` is on — the router must
6
+ * re-scan islands after a DOM swap, which inline scripts cannot do.
7
+ */
8
+ export type HydrationMode = "entry-client" | "per-island";
9
+ export declare function resolveHydrationMode(isDev: boolean, clientRouter: boolean): HydrationMode;
10
+ /** Import lines for `virtual:avalon/client-entry` based on hydration mode. */
11
+ export declare function clientEntryImportLines(isDev: boolean, clientRouter: boolean): string[];
@@ -0,0 +1 @@
1
+ export function resolveHydrationMode(e,t){return e||t?`entry-client`:`per-island`}export function clientEntryImportLines(t,n){let r=[];if(resolveHydrationMode(t,n)===`entry-client`){let e=t?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`;r.push(`import '${e}';`)}else r.push(`// Per-island hydration mode — no shared runtime needed`);return n&&r.push(`import '@useavalon/avalon/client/router';`),r}
@@ -0,0 +1 @@
1
+ import{scanAndHydrate as e}from"./hydrate-runtime.ts";import{bootServerIslands as t}from"./server-islands-boot.ts";function n(){e(),t()}document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,n):n();
@@ -1,17 +1,4 @@
1
- import{loadHMRAdapter as e,loadIntegrationModule as t,preLitHydration as n}from"virtual:avalon/integration-loader";import{executeCustomDirective as r,hasClientDirective as i}from"./custom-directives.js";document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,a):a();function a(){let e=document.querySelectorAll(`[data-framework]`);e.length!==0&&e.forEach(e=>{try{let t=e.dataset.framework,n=e.dataset.condition||`on:client`;if(e.dataset.renderStrategy===`ssr-only`||!o(e,n))return;n===`on:client`?f(e,t):n===`on:visible`?s(e,t):n===`on:interaction`?c(e,t):n===`on:idle`?l(e,t):n.startsWith(`media:`)?u(e,t,n.slice(6)):e.dataset.customDirective||e.dataset.directiveScript||i(n)?r(e,n,()=>{f(e,t)})||(console.warn(`[avalon] Unknown hydration condition: "${n}". Hydrating immediately.`),f(e,t)):f(e,t)}catch(t){console.error(`Error processing island:`,t),p(e,e.dataset.framework||`unknown`,e.dataset.src||`unknown`,t)}})}function o(e,t){if(!t||t===`on:client`)return!0;if(t.startsWith(`media:`)){let e=t.slice(6);try{return globalThis.matchMedia(e).matches}catch(t){return console.error(`Invalid media query:`,e,t),!0}}return t===`on:visible`||t===`on:interaction`||t===`on:idle`||e.dataset.customDirective||e.dataset.directiveScript||i(t)||console.warn(`Unknown hydration condition:`,t),!0}function s(e,t){try{let n=new IntersectionObserver(r=>{r[0].isIntersecting&&(f(e,t),n.disconnect())},{rootMargin:`50px`,threshold:0});n.observe(e.firstElementChild||e)}catch(n){console.error(`Failed to setup intersection observer:`,n),f(e,t)}}function c(e,t){let n=[`click`,`touchstart`,`mouseenter`,`focusin`],r=!1,i=e.firstElementChild||e,a=()=>{r||(r=!0,n.forEach(e=>{i.removeEventListener(e,a)}),f(e,t))};try{n.forEach(e=>{i.addEventListener(e,a,{once:!0,passive:!0})})}catch(n){console.error(`Failed to setup interaction observer:`,n),f(e,t)}}function l(e,t){try{`requestIdleCallback`in globalThis?globalThis.requestIdleCallback(()=>{f(e,t)},{timeout:5e3}):document.readyState===`complete`?setTimeout(()=>{f(e,t)},200):globalThis.addEventListener(`load`,()=>{setTimeout(()=>{f(e,t)},200)},{once:!0})}catch(n){console.error(`Failed to setup idle callback:`,n),f(e,t)}}function u(e,t,n){try{let r=globalThis.matchMedia(n);if(r.matches){f(e,t);return}let i=n=>{n.matches&&(f(e,t),r.removeEventListener(`change`,i))};r.addEventListener(`change`,i)}catch(r){console.error(`Failed to setup media query:`,n,r),f(e,t)}}function d(e,t){let n=e.default;if(!n){let t=Object.keys(e).filter(e=>e!==`default`);for(let r of t){let t=e[r];if(typeof t==`function`&&t.prototype){n=t;break}}n||=e}if(!n)throw Error(`Component ${t} has no default export`);return n}async function f(e,r){if(e.dataset.hydrated)return;let i=e.dataset.src,a=e.dataset.props;if(!i){console.warn(`Island missing data-src attribute`);return}try{let o=a?JSON.parse(a):{};r===`lit`&&await n();let s=d(await import(i),i);try{let n=await t(r);if(!n.hydrate||typeof n.hydrate!=`function`)throw Error(`Integration ${r} does not export a hydrate function`);await n.hydrate(e,s,o),e.dataset.hydrated=`true`}catch(t){import.meta.env?.DEV&&console.error(`Integration hydration failed for ${r}: ${i}`,t),e.dataset.hydrationStatus=`failed`,e.dataset.hydrationError=t.message,e.dispatchEvent(new CustomEvent(`hydration-error`,{detail:{framework:r,src:i,error:t.message,timestamp:Date.now(),hydrationType:`integration-level`},bubbles:!0}))}}catch(t){console.error(`❌ Critical error hydrating ${r} island ${i}:`,t),p(e,r,i,t)}}function p(e,t,n,r){console.error(`Hydration error for ${t} island:`,{src:n,error:r.message,stack:r.stack}),e.dataset.hydrationStatus=`failed`,e.dataset.renderStrategy=`ssr-only`,e.classList.add(`hydration-failed`),e.dispatchEvent(new CustomEvent(`hydration-error`,{detail:{framework:t,src:n,error:r.message,timestamp:Date.now()},bubbles:!0})),h()&&m(e,t,n,r)}function m(e,t,n,r){let i=document.createElement(`div`);i.className=`hydration-error-indicator`,i.style.cssText=`
2
- position: absolute;
3
- top: 0;
4
- right: 0;
5
- background: #ff4444;
6
- color: white;
7
- padding: 4px 8px;
8
- font-size: 11px;
9
- font-family: monospace;
10
- border-radius: 0 0 0 4px;
11
- z-index: 9999;
12
- cursor: pointer;
13
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
14
- `,i.textContent=`❌ ${t}`,i.title=`Hydration failed: ${n}\n${r.message}\nClick for details`,i.addEventListener(`click`,()=>{alert(`Hydration Error\n\nFramework: ${t}\nComponent: ${n}\n\nError: ${r.message}\n\nStack:\n${r.stack}`)}),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.appendChild(i)}function h(){return import.meta.env?.DEV||import.meta.env?.MODE===`development`||globalThis.location?.hostname===`localhost`||globalThis.location?.hostname===`127.0.0.1`}function g(e){let t=e.dataset.framework,n=e.dataset.src;if(!n)return null;let r={framework:t,src:n,props:e.dataset.props,scrollPosition:{x:globalThis.scrollX,y:globalThis.scrollY},focusedElement:document.activeElement?.id||null};try{t===`vue`&&e.__vue__?r.vueData=structuredClone(e.__vue__.$data||{}):t===`svelte`&&e.__svelte__?r.svelteState=e.__svelte__:t===`lit`&&e.tagName?.includes(`-`)&&(e.querySelector(`[data-lit-element]`)||e)._$litElement$&&(r.litProperties={})}catch(e){console.warn(`Failed to preserve island state:`,e)}return r}function _(e,t){if(t)try{if(t.scrollPosition&&globalThis.scrollTo(t.scrollPosition.x,t.scrollPosition.y),t.focusedElement){let e=document.getElementById(t.focusedElement);e&&e.focus()}e.dataset.framework===`vue`&&t.vueData&&e.__vue__&&Object.assign(e.__vue__.$data,t.vueData)}catch(e){console.warn(`Failed to restore island state:`,e)}}async function v(e,r,i,a){let o=e.dataset.props,s=o?JSON.parse(o):{};r===`lit`&&await n();let c=d(await import(i),a),l=await t(r);if(!l.hydrate||typeof l.hydrate!=`function`)throw Error(`Integration ${r} does not export a hydrate function`);l.hydrate(e,c,s),e.dataset.hydrated=`true`}function y(e,t,n,r){let i=e.querySelector(`.hmr-error-indicator`);i&&i.remove();let a=document.createElement(`div`);a.className=`hmr-error-indicator`,a.style.cssText=`
1
+ import{loadHMRAdapter as e,loadIntegrationModule as t,preLitHydration as n}from"virtual:avalon/integration-loader";import{scanAndHydrate as r,setHydrationLoader as i}from"./hydrate-runtime.ts";import{bootServerIslands as a}from"./server-islands-boot.ts";i({loadIntegrationModule:t,preLitHydration:n}),document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,o):o();function o(){r(),a()}function s(e,t){let n=e.default;if(!n){let t=Object.keys(e).filter(e=>e!==`default`);for(let r of t){let t=e[r];if(typeof t==`function`&&t.prototype){n=t;break}}n||=e}if(!n)throw Error(`Component ${t} has no default export`);return n}function c(){return import.meta.env?.DEV||import.meta.env?.MODE===`development`||globalThis.location?.hostname===`localhost`||globalThis.location?.hostname===`127.0.0.1`}function l(e){let t=e.dataset.framework,n=e.dataset.src;if(!n)return null;let r={framework:t,src:n,props:e.dataset.props,scrollPosition:{x:globalThis.scrollX,y:globalThis.scrollY},focusedElement:document.activeElement?.id||null};try{t===`vue`&&e.__vue__?r.vueData=structuredClone(e.__vue__.$data||{}):t===`svelte`&&e.__svelte__?r.svelteState=e.__svelte__:t===`lit`&&e.tagName?.includes(`-`)&&(e.querySelector(`[data-lit-element]`)||e)._$litElement$&&(r.litProperties={})}catch(e){console.warn(`Failed to preserve island state:`,e)}return r}function u(e,t){if(t)try{if(t.scrollPosition&&globalThis.scrollTo(t.scrollPosition.x,t.scrollPosition.y),t.focusedElement){let e=document.getElementById(t.focusedElement);e&&e.focus()}e.dataset.framework===`vue`&&t.vueData&&e.__vue__&&Object.assign(e.__vue__.$data,t.vueData)}catch(e){console.warn(`Failed to restore island state:`,e)}}async function d(e,r,i,a){let o=e.dataset.props,c=o?JSON.parse(o):{};r===`lit`&&await n();let l=s(await import(i),a),u=await t(r);if(!u.hydrate||typeof u.hydrate!=`function`)throw Error(`Integration ${r} does not export a hydrate function`);u.hydrate(e,l,c),e.dataset.hydrated=`true`}function f(e,t,n,r){let i=e.querySelector(`.hmr-error-indicator`);i&&i.remove();let a=document.createElement(`div`);a.className=`hmr-error-indicator`,a.style.cssText=`
15
2
  position: absolute;
16
3
  top: 0;
17
4
  left: 0;
@@ -36,4 +23,4 @@ import{loadHMRAdapter as e,loadIntegrationModule as t,preLitHydration as n}from"
36
23
  cursor: pointer;
37
24
  font-size: 14px;
38
25
  line-height: 1;
39
- `,c.onclick=()=>a.remove(),a.appendChild(o),a.appendChild(s),a.appendChild(c),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.insertBefore(a,e.firstChild)}import.meta.hot&&(import.meta.hot.accept(),import(`./hmr-coordinator.js`).then(async({initializeHMR:t,getHMRCoordinator:n})=>{t();let r=n(),i=new Set;document.querySelectorAll(`[data-framework]`).forEach(e=>{let t=e.dataset.framework;t&&i.add(t)});for(let t of i)try{let n=await e(t);n&&r.registerAdapter(t,n)}catch(e){console.warn(`[HMR] Failed to load adapter for ${t}:`,e)}}).catch(e=>{console.error(`[HMR] Failed to initialize:`,e)}),x());async function b(e,t,n,r){try{let{showHMRErrorOverlay:e}=await import(`./hmr-error-overlay.js`);e({framework:t,src:n,error:r,filePath:n})}catch{y(e,t,n,r)}}function x(){if(!import.meta.hot)return;let e=new Map;async function t(e){let t=e.replaceAll(`\\`,`/`),r=document.querySelectorAll(`[data-src*="${t}"], [data-src$="${t}"]`);if(r.length===0){let e=document.querySelectorAll(`[data-src]`);for(let r of e){let e=r.dataset.src;e&&(e.includes(t)||t.includes(e.replace(/^\//,``)))&&await n(r)}return}for(let e of r)await n(e)}async function n(t){let n=t.dataset.framework,r=t.dataset.src;if(!(!r||!n))try{let i=g(t);e.set(r,i),delete t.dataset.hydrated,delete t.dataset.hydrationStatus;let a=t.querySelector(`.hydration-error-indicator`);a&&a.remove();let o=Date.now();await v(t,n,r.includes(`?`)?`${r}&t=${o}`:`${r}?t=${o}`,r);let s=e.get(r);s&&(_(t,s),e.delete(r)),t.dispatchEvent(new CustomEvent(`hmr-update`,{detail:{framework:n,src:r,timestamp:Date.now(),success:!0},bubbles:!0}))}catch(e){console.error(`[HMR] Failed for ${n} island ${r}:`,e),t.dispatchEvent(new CustomEvent(`hmr-error`,{detail:{framework:n,src:r,error:e.message,timestamp:Date.now()},bubbles:!0})),h()&&b(t,n,r,e)}}import.meta.hot.on(`vite:beforeUpdate`,e=>{for(let n of e.updates||[]){let e=n.path||n.acceptedPath;e&&(e.includes(`/islands/`)||e.includes(`\\islands\\`))&&t(e)}}),import.meta.hot.on(`vite:beforeFullReload`,()=>{let e=document.querySelectorAll(`[data-hydrated="true"]`),t={};for(let n of e){let e=n.dataset.src;e&&(t[e]=g(n))}try{sessionStorage.setItem(`__avalon_hmr_states__`,JSON.stringify(t))}catch{}});try{let e=sessionStorage.getItem(`__avalon_hmr_states__`);if(e){let t=JSON.parse(e);sessionStorage.removeItem(`__avalon_hmr_states__`),setTimeout(()=>{for(let[e,n]of Object.entries(t)){let t=document.querySelector(`[data-src="${e}"]`);t&&n&&_(t,n)}},100)}}catch{}}
26
+ `,c.onclick=()=>a.remove(),a.appendChild(o),a.appendChild(s),a.appendChild(c),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.insertBefore(a,e.firstChild)}import.meta.hot&&(import.meta.hot.accept(),await p(),h());async function p(){try{let{initializeHMR:t,getHMRCoordinator:n}=await import(`./hmr-coordinator.js`);t();let r=n(),i=new Set;document.querySelectorAll(`[data-framework]`).forEach(e=>{let t=e.dataset.framework;t&&i.add(t)});for(let t of i)try{let n=await e(t);n&&r.registerAdapter(t,n)}catch(e){console.warn(`[HMR] Failed to load adapter for ${t}:`,e)}}catch(e){console.error(`[HMR] Failed to initialize:`,e)}}async function m(e,t,n,r){try{let{showHMRErrorOverlay:e}=await import(`./hmr-error-overlay.js`);e({framework:t,src:n,error:r,filePath:n})}catch{f(e,t,n,r)}}function h(){if(!import.meta.hot)return;let e=new Map;async function t(e){let t=e.replaceAll(`\\`,`/`),r=document.querySelectorAll(`[data-src*="${t}"], [data-src$="${t}"]`);if(r.length===0){let e=document.querySelectorAll(`[data-src]`);for(let r of e){let e=r.dataset.src;e&&(e.includes(t)||t.includes(e.replace(/^\//,``)))&&await n(r)}return}for(let e of r)await n(e)}async function n(t){let n=t.dataset.framework,r=t.dataset.src;if(!(!r||!n))try{let i=l(t);e.set(r,i),delete t.dataset.hydrated,delete t.dataset.hydrationStatus;let a=t.querySelector(`.hydration-error-indicator`);a&&a.remove();let o=Date.now();await d(t,n,r.includes(`?`)?`${r}&t=${o}`:`${r}?t=${o}`,r);let s=e.get(r);s&&(u(t,s),e.delete(r)),t.dispatchEvent(new CustomEvent(`hmr-update`,{detail:{framework:n,src:r,timestamp:Date.now(),success:!0},bubbles:!0}))}catch(e){console.error(`[HMR] Failed for ${n} island ${r}:`,e),t.dispatchEvent(new CustomEvent(`hmr-error`,{detail:{framework:n,src:r,error:e.message,timestamp:Date.now()},bubbles:!0})),c()&&m(t,n,r,e)}}import.meta.hot.on(`vite:beforeUpdate`,e=>{for(let n of e.updates||[]){let e=n.path||n.acceptedPath;e&&(e.includes(`/islands/`)||e.includes(`\\islands\\`))&&t(e)}}),import.meta.hot.on(`vite:beforeFullReload`,()=>{let e=document.querySelectorAll(`[data-hydrated="true"]`),t={};for(let n of e){let e=n.dataset.src;e&&(t[e]=l(n))}try{sessionStorage.setItem(`__avalon_hmr_states__`,JSON.stringify(t))}catch{}});try{let e=sessionStorage.getItem(`__avalon_hmr_states__`);if(e){let t=JSON.parse(e);sessionStorage.removeItem(`__avalon_hmr_states__`),setTimeout(()=>{for(let[e,n]of Object.entries(t)){let t=document.querySelector(`[data-src="${e}"]`);t&&n&&u(t,n)}},100)}}catch{}}
@@ -0,0 +1,9 @@
1
+ export declare function ensureRouteAnnouncer(doc?: Document): HTMLElement;
2
+ export declare function announceRoute(title: string, doc?: Document): void;
3
+ export declare function restoreFocus(doc?: Document): void;
4
+ export interface ScrollPosition {
5
+ x: number;
6
+ y: number;
7
+ }
8
+ export declare function readScroll(): ScrollPosition;
9
+ export declare function applyScroll(position: ScrollPosition | "top", hash?: string): void;
@@ -0,0 +1 @@
1
+ const e=`avalon-router-announce`;export function ensureRouteAnnouncer(t=document){let n=t.getElementById(e);return n||(n=t.createElement(`p`),n.id=e,n.setAttribute(`aria-live`,`polite`),n.setAttribute(`aria-atomic`,`true`),n.style.cssText=`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0`,t.body.appendChild(n),n)}export function announceRoute(e,n=document){let r=ensureRouteAnnouncer(n);r.textContent=``,r.textContent=e}export function restoreFocus(e=document){let t=e.querySelector(`[autofocus]`);if(t){t.focus();return}let n=e.querySelector(`main`);if(n){n.hasAttribute(`tabindex`)||(n.tabIndex=-1),n.focus({preventScroll:!0});return}e.body.tabIndex=-1,e.body.focus({preventScroll:!0})}export function readScroll(){return{x:window.scrollX,y:window.scrollY}}export function applyScroll(e,t){if(t){let e=decodeURIComponent(t.slice(1)),n=document.getElementById(e);if(n){n.scrollIntoView();return}}if(e===`top`){window.scrollTo(0,0);return}window.scrollTo(e.x,e.y)}