@useavalon/avalon 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -54
- package/dist/mod.js +1 -0
- package/dist/src/build/integration-bundler-plugin.js +1 -0
- package/dist/src/build/integration-config.js +1 -0
- package/dist/src/build/integration-detection-plugin.js +1 -0
- package/dist/src/build/integration-resolver-plugin.js +1 -0
- package/dist/src/build/island-manifest.js +1 -0
- package/dist/src/build/island-types-generator.js +5 -0
- package/dist/src/build/mdx-island-transform.js +2 -0
- package/dist/src/build/mdx-plugin.js +1 -0
- package/dist/src/build/page-island-transform.js +3 -0
- package/dist/src/build/prop-extractors/index.js +1 -0
- package/dist/src/build/prop-extractors/lit.js +1 -0
- package/dist/src/build/prop-extractors/qwik.js +1 -0
- package/dist/src/build/prop-extractors/solid.js +1 -0
- package/dist/src/build/prop-extractors/svelte.js +1 -0
- package/dist/src/build/prop-extractors/vue.js +1 -0
- package/dist/src/build/sidecar-file-manager.js +1 -0
- package/dist/src/build/sidecar-renderer.js +6 -0
- package/dist/src/client/adapters/index.js +1 -0
- package/dist/src/client/components.js +1 -0
- package/dist/src/client/css-hmr-handler.js +1 -0
- package/dist/src/client/framework-adapter.js +13 -0
- package/dist/src/client/hmr-coordinator.js +1 -0
- package/dist/src/client/hmr-error-overlay.js +214 -0
- package/dist/src/client/main.js +39 -0
- package/{src → dist/src}/client/types/framework-runtime.d.ts +68 -68
- package/{src → dist/src}/client/types/vite-hmr.d.ts +46 -46
- package/dist/src/client/types/vite-virtual-modules.d.ts +70 -0
- package/dist/src/components/Image.js +1 -0
- package/dist/src/components/IslandErrorBoundary.js +1 -0
- package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
- package/dist/src/components/LayoutErrorBoundary.js +1 -0
- package/dist/src/components/PersistentIsland.js +1 -0
- package/dist/src/components/StreamingErrorBoundary.js +1 -0
- package/dist/src/components/StreamingLayout.js +29 -0
- package/dist/src/core/components/component-analyzer.js +1 -0
- package/dist/src/core/components/component-detection.js +5 -0
- package/dist/src/core/components/enhanced-framework-detector.js +1 -0
- package/dist/src/core/components/framework-registry.js +1 -0
- package/dist/src/core/content/mdx-processor.js +1 -0
- package/dist/src/core/integrations/index.js +1 -0
- package/dist/src/core/integrations/loader.js +1 -0
- package/dist/src/core/integrations/registry.js +1 -0
- package/dist/src/core/islands/island-persistence.js +1 -0
- package/dist/src/core/islands/island-state-serializer.js +1 -0
- package/dist/src/core/islands/persistent-island-context.js +1 -0
- package/dist/src/core/islands/use-persistent-state.js +1 -0
- package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
- package/dist/src/core/layout/layout-cache-manager.js +1 -0
- package/dist/src/core/layout/layout-composer.js +1 -0
- package/dist/src/core/layout/layout-data-loader.js +1 -0
- package/dist/src/core/layout/layout-discovery.js +1 -0
- package/dist/src/core/layout/layout-matcher.js +1 -0
- package/dist/src/core/layout/layout-types.js +1 -0
- package/dist/src/core/modules/framework-module-resolver.js +1 -0
- package/dist/src/islands/component-analysis.js +1 -0
- package/dist/src/islands/css-utils.js +17 -0
- package/dist/src/islands/discovery/index.js +1 -0
- package/dist/src/islands/discovery/registry.js +1 -0
- package/dist/src/islands/discovery/resolver.js +2 -0
- package/dist/src/islands/discovery/scanner.js +1 -0
- package/dist/src/islands/discovery/types.js +1 -0
- package/dist/src/islands/discovery/validator.js +18 -0
- package/dist/src/islands/discovery/watcher.js +1 -0
- package/dist/src/islands/framework-detection.js +1 -0
- package/dist/src/islands/integration-loader.js +1 -0
- package/dist/src/islands/island.js +1 -0
- package/dist/src/islands/render-cache.js +1 -0
- package/dist/src/islands/types.js +1 -0
- package/dist/src/islands/universal-css-collector.js +5 -0
- package/dist/src/islands/universal-head-collector.js +2 -0
- package/{src → dist/src}/layout-system.d.ts +592 -592
- package/dist/src/layout-system.js +1 -0
- package/dist/src/middleware/discovery.js +1 -0
- package/dist/src/middleware/executor.js +1 -0
- package/dist/src/middleware/index.js +1 -0
- package/dist/src/middleware/types.js +1 -0
- package/dist/src/nitro/build-config.js +1 -0
- package/dist/src/nitro/config.js +1 -0
- package/dist/src/nitro/error-handler.js +198 -0
- package/dist/src/nitro/index.js +1 -0
- package/dist/src/nitro/island-manifest.js +2 -0
- package/dist/src/nitro/middleware-adapter.js +1 -0
- package/dist/src/nitro/renderer.js +183 -0
- package/dist/src/nitro/route-discovery.js +1 -0
- package/dist/src/nitro/types.js +1 -0
- package/dist/src/render/collect-css.js +3 -0
- package/{src/render/error-pages.ts → dist/src/render/error-pages.js} +7 -38
- package/dist/src/render/isolated-ssr-renderer.js +1 -0
- package/dist/src/render/ssr.js +90 -0
- package/dist/src/schemas/api.js +1 -0
- package/dist/src/schemas/core.js +1 -0
- package/dist/src/schemas/index.js +1 -0
- package/dist/src/schemas/layout.js +1 -0
- package/dist/src/schemas/routing/index.js +1 -0
- package/dist/src/schemas/routing.js +1 -0
- package/dist/src/types/as-island.js +1 -0
- package/{src → dist/src}/types/image.d.ts +106 -106
- package/{src → dist/src}/types/index.d.ts +22 -22
- package/{src → dist/src}/types/island-jsx.d.ts +33 -33
- package/{src → dist/src}/types/island-prop.d.ts +20 -20
- package/dist/src/types/layout.js +1 -0
- package/{src → dist/src}/types/mdx.d.ts +6 -6
- package/dist/src/types/routing.js +1 -0
- package/dist/src/types/types.js +1 -0
- package/{src → dist/src}/types/urlpattern.d.ts +49 -49
- package/{src → dist/src}/types/vite-env.d.ts +11 -11
- package/dist/src/utils/dev-logger.js +12 -0
- package/dist/src/utils/fs.js +1 -0
- package/dist/src/vite-plugin/auto-discover.js +1 -0
- package/dist/src/vite-plugin/config.js +1 -0
- package/dist/src/vite-plugin/errors.js +1 -0
- package/dist/src/vite-plugin/image-optimization.js +45 -0
- package/dist/src/vite-plugin/integration-activator.js +1 -0
- package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
- package/dist/src/vite-plugin/module-discovery.js +1 -0
- package/dist/src/vite-plugin/nitro-integration.js +42 -0
- package/dist/src/vite-plugin/plugin.js +1 -0
- package/dist/src/vite-plugin/types.js +1 -0
- package/dist/src/vite-plugin/validation.js +2 -0
- package/package.json +57 -26
- package/mod.ts +0 -302
- package/src/build/integration-bundler-plugin.ts +0 -116
- package/src/build/integration-config.ts +0 -168
- package/src/build/integration-detection-plugin.ts +0 -117
- package/src/build/integration-resolver-plugin.ts +0 -90
- package/src/build/island-manifest.ts +0 -269
- package/src/build/island-types-generator.ts +0 -476
- package/src/build/mdx-island-transform.ts +0 -464
- package/src/build/mdx-plugin.ts +0 -98
- package/src/build/page-island-transform.ts +0 -598
- package/src/build/prop-extractors/index.ts +0 -21
- package/src/build/prop-extractors/lit.ts +0 -140
- package/src/build/prop-extractors/qwik.ts +0 -16
- package/src/build/prop-extractors/solid.ts +0 -125
- package/src/build/prop-extractors/svelte.ts +0 -194
- package/src/build/prop-extractors/vue.ts +0 -111
- package/src/build/sidecar-file-manager.ts +0 -104
- package/src/build/sidecar-renderer.ts +0 -30
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/index.ts +0 -13
- package/src/client/adapters/lit-adapter.js +0 -467
- package/src/client/adapters/lit-adapter.ts +0 -654
- package/src/client/adapters/preact-adapter.js +0 -223
- package/src/client/adapters/preact-adapter.ts +0 -331
- package/src/client/adapters/qwik-adapter.js +0 -259
- package/src/client/adapters/qwik-adapter.ts +0 -345
- package/src/client/adapters/react-adapter.js +0 -220
- package/src/client/adapters/react-adapter.ts +0 -353
- package/src/client/adapters/solid-adapter.js +0 -295
- package/src/client/adapters/solid-adapter.ts +0 -451
- package/src/client/adapters/svelte-adapter.js +0 -368
- package/src/client/adapters/svelte-adapter.ts +0 -524
- package/src/client/adapters/vue-adapter.js +0 -278
- package/src/client/adapters/vue-adapter.ts +0 -467
- package/src/client/components.js +0 -23
- package/src/client/components.ts +0 -35
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/css-hmr-handler.ts +0 -344
- package/src/client/framework-adapter.js +0 -283
- package/src/client/framework-adapter.ts +0 -462
- package/src/client/hmr-coordinator.js +0 -274
- package/src/client/hmr-coordinator.ts +0 -396
- package/src/client/hmr-error-overlay.js +0 -533
- package/src/client/main.js +0 -816
- package/src/client/types/vite-virtual-modules.d.ts +0 -60
- package/src/components/Image.tsx +0 -123
- package/src/components/IslandErrorBoundary.tsx +0 -145
- package/src/components/LayoutDataErrorBoundary.tsx +0 -141
- package/src/components/LayoutErrorBoundary.tsx +0 -127
- package/src/components/PersistentIsland.tsx +0 -52
- package/src/components/StreamingErrorBoundary.tsx +0 -233
- package/src/components/StreamingLayout.tsx +0 -538
- package/src/core/components/component-analyzer.ts +0 -192
- package/src/core/components/component-detection.ts +0 -508
- package/src/core/components/enhanced-framework-detector.ts +0 -500
- package/src/core/components/framework-registry.ts +0 -563
- package/src/core/content/mdx-processor.ts +0 -46
- package/src/core/integrations/index.ts +0 -19
- package/src/core/integrations/loader.ts +0 -125
- package/src/core/integrations/registry.ts +0 -175
- package/src/core/islands/island-persistence.ts +0 -325
- package/src/core/islands/island-state-serializer.ts +0 -258
- package/src/core/islands/persistent-island-context.tsx +0 -80
- package/src/core/islands/use-persistent-state.ts +0 -68
- package/src/core/layout/enhanced-layout-resolver.ts +0 -322
- package/src/core/layout/layout-cache-manager.ts +0 -485
- package/src/core/layout/layout-composer.ts +0 -357
- package/src/core/layout/layout-data-loader.ts +0 -516
- package/src/core/layout/layout-discovery.ts +0 -243
- package/src/core/layout/layout-matcher.ts +0 -299
- package/src/core/layout/layout-types.ts +0 -110
- package/src/core/modules/framework-module-resolver.ts +0 -273
- package/src/islands/component-analysis.ts +0 -213
- package/src/islands/css-utils.ts +0 -565
- package/src/islands/discovery/index.ts +0 -80
- package/src/islands/discovery/registry.ts +0 -340
- package/src/islands/discovery/resolver.ts +0 -477
- package/src/islands/discovery/scanner.ts +0 -386
- package/src/islands/discovery/types.ts +0 -117
- package/src/islands/discovery/validator.ts +0 -544
- package/src/islands/discovery/watcher.ts +0 -368
- package/src/islands/framework-detection.ts +0 -428
- package/src/islands/integration-loader.ts +0 -490
- package/src/islands/island.tsx +0 -565
- package/src/islands/render-cache.ts +0 -550
- package/src/islands/types.ts +0 -80
- package/src/islands/universal-css-collector.ts +0 -157
- package/src/islands/universal-head-collector.ts +0 -137
- package/src/layout-system.ts +0 -218
- package/src/middleware/discovery.ts +0 -268
- package/src/middleware/executor.ts +0 -315
- package/src/middleware/index.ts +0 -76
- package/src/middleware/types.ts +0 -99
- package/src/nitro/build-config.ts +0 -576
- package/src/nitro/config.ts +0 -483
- package/src/nitro/error-handler.ts +0 -636
- package/src/nitro/index.ts +0 -173
- package/src/nitro/island-manifest.ts +0 -584
- package/src/nitro/middleware-adapter.ts +0 -260
- package/src/nitro/renderer.ts +0 -1471
- package/src/nitro/route-discovery.ts +0 -439
- package/src/nitro/types.ts +0 -321
- package/src/render/collect-css.ts +0 -198
- package/src/render/isolated-ssr-renderer.ts +0 -654
- package/src/render/ssr.ts +0 -1030
- package/src/schemas/api.ts +0 -30
- package/src/schemas/core.ts +0 -64
- package/src/schemas/index.ts +0 -212
- package/src/schemas/layout.ts +0 -279
- package/src/schemas/routing/index.ts +0 -38
- package/src/schemas/routing.ts +0 -376
- package/src/types/as-island.ts +0 -20
- package/src/types/layout.ts +0 -285
- package/src/types/routing.ts +0 -555
- package/src/types/types.ts +0 -5
- package/src/utils/dev-logger.ts +0 -299
- package/src/utils/fs.ts +0 -151
- package/src/vite-plugin/auto-discover.ts +0 -551
- package/src/vite-plugin/config.ts +0 -266
- package/src/vite-plugin/errors.ts +0 -127
- package/src/vite-plugin/image-optimization.ts +0 -156
- package/src/vite-plugin/integration-activator.ts +0 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
- package/src/vite-plugin/module-discovery.ts +0 -189
- package/src/vite-plugin/nitro-integration.ts +0 -1354
- package/src/vite-plugin/plugin.ts +0 -409
- package/src/vite-plugin/types.ts +0 -327
- package/src/vite-plugin/validation.ts +0 -228
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CSS HMR Handler class
|
|
3
|
-
* Manages CSS hot updates without page reload
|
|
4
|
-
*/
|
|
5
|
-
export class CSSHMRHandler {
|
|
6
|
-
cssModuleMap = new Map();
|
|
7
|
-
styleElementMap = new Map();
|
|
8
|
-
/**
|
|
9
|
-
* Handle CSS update from Vite HMR
|
|
10
|
-
*/
|
|
11
|
-
handleCSSUpdate(update) {
|
|
12
|
-
const updateInfo = this.classifyCSSUpdate(update);
|
|
13
|
-
switch (updateInfo.type) {
|
|
14
|
-
case "global":
|
|
15
|
-
this.handleGlobalCSSUpdate(updateInfo);
|
|
16
|
-
break;
|
|
17
|
-
case "module":
|
|
18
|
-
this.handleCSSModuleUpdate(updateInfo);
|
|
19
|
-
break;
|
|
20
|
-
case "scoped":
|
|
21
|
-
this.handleScopedCSSUpdate(updateInfo);
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Classify the type of CSS update
|
|
27
|
-
*/
|
|
28
|
-
classifyCSSUpdate(update) {
|
|
29
|
-
const path = update.path || update.acceptedPath;
|
|
30
|
-
// Check if it's a CSS module
|
|
31
|
-
if (path.includes(".module.css") || path.includes(".module.scss")) {
|
|
32
|
-
return {
|
|
33
|
-
type: "module",
|
|
34
|
-
path,
|
|
35
|
-
timestamp: update.timestamp
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
// Check if it's a scoped style (Svelte or Vue)
|
|
39
|
-
if (path.includes(".svelte") || path.includes(".vue")) {
|
|
40
|
-
return {
|
|
41
|
-
type: "scoped",
|
|
42
|
-
path,
|
|
43
|
-
timestamp: update.timestamp
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
// Default to global CSS
|
|
47
|
-
return {
|
|
48
|
-
type: "global",
|
|
49
|
-
path,
|
|
50
|
-
timestamp: update.timestamp
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Handle global CSS file update
|
|
55
|
-
* Injects updated styles without page reload
|
|
56
|
-
*/
|
|
57
|
-
handleGlobalCSSUpdate(info) {
|
|
58
|
-
try {
|
|
59
|
-
// Find existing style element for this CSS file
|
|
60
|
-
const existingStyle = this.styleElementMap.get(info.path);
|
|
61
|
-
if (existingStyle) {
|
|
62
|
-
// Remove old style element
|
|
63
|
-
existingStyle.remove();
|
|
64
|
-
this.styleElementMap.delete(info.path);
|
|
65
|
-
}
|
|
66
|
-
// Vite automatically injects the updated CSS via its HMR mechanism
|
|
67
|
-
// We just need to ensure old styles are removed
|
|
68
|
-
// The new styles will be injected by Vite's CSS handling
|
|
69
|
-
// Find the newly injected style element
|
|
70
|
-
// Vite adds a data-vite-dev-id attribute to style elements
|
|
71
|
-
const newStyle = document.querySelector(`style[data-vite-dev-id*="${this.getFileId(info.path)}"]`);
|
|
72
|
-
if (newStyle) {
|
|
73
|
-
this.styleElementMap.set(info.path, newStyle);
|
|
74
|
-
}
|
|
75
|
-
// Dispatch event for feedback
|
|
76
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error(`Failed to update global CSS: ${info.path}`, error);
|
|
79
|
-
this.dispatchCSSUpdateEvent(info, false, error);
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Handle CSS module update
|
|
85
|
-
* Re-renders components using the updated CSS module
|
|
86
|
-
*/
|
|
87
|
-
handleCSSModuleUpdate(info) {
|
|
88
|
-
try {
|
|
89
|
-
const affectedIslands = this.findIslandsUsingCSSModule(info.path);
|
|
90
|
-
if (affectedIslands.length === 0) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
for (const island of affectedIslands) {
|
|
94
|
-
this.triggerIslandRerender(island, info);
|
|
95
|
-
}
|
|
96
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.error(`[HMR] Failed to update CSS module: ${info.path}`, error);
|
|
99
|
-
this.dispatchCSSUpdateEvent(info, false, error);
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Handle scoped CSS update (Svelte/Vue)
|
|
105
|
-
* Updates only the affected component's styles
|
|
106
|
-
*/
|
|
107
|
-
handleScopedCSSUpdate(info) {
|
|
108
|
-
try {
|
|
109
|
-
const affectedIslands = this.findIslandsUsingComponent(info.path);
|
|
110
|
-
if (affectedIslands.length === 0) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(`[HMR] Failed to update scoped CSS: ${info.path}`, error);
|
|
116
|
-
this.dispatchCSSUpdateEvent(info, false, error);
|
|
117
|
-
throw error;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Find islands that use a specific CSS module
|
|
122
|
-
*/
|
|
123
|
-
findIslandsUsingCSSModule(cssPath) {
|
|
124
|
-
const islands = [];
|
|
125
|
-
const normalizedPath = this.normalizePath(cssPath);
|
|
126
|
-
// Check cached mapping first
|
|
127
|
-
const cached = this.cssModuleMap.get(normalizedPath);
|
|
128
|
-
if (cached) {
|
|
129
|
-
return Array.from(cached);
|
|
130
|
-
}
|
|
131
|
-
// Find all islands
|
|
132
|
-
const allIslands = document.querySelectorAll("[data-src]");
|
|
133
|
-
for (const island of allIslands) {
|
|
134
|
-
const src = island.getAttribute("data-src");
|
|
135
|
-
if (!src) continue;
|
|
136
|
-
// Check if the island's component likely imports this CSS module
|
|
137
|
-
// This is a heuristic - we look for islands in the same directory
|
|
138
|
-
const componentDir = this.getDirectory(src);
|
|
139
|
-
const cssDir = this.getDirectory(cssPath);
|
|
140
|
-
if (componentDir === cssDir) {
|
|
141
|
-
islands.push(island);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Cache the mapping
|
|
145
|
-
if (islands.length > 0) {
|
|
146
|
-
this.cssModuleMap.set(normalizedPath, new Set(islands));
|
|
147
|
-
}
|
|
148
|
-
return islands;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Find islands using a specific component file
|
|
152
|
-
*/
|
|
153
|
-
findIslandsUsingComponent(componentPath) {
|
|
154
|
-
const islands = [];
|
|
155
|
-
const normalizedPath = this.normalizePath(componentPath);
|
|
156
|
-
const allIslands = document.querySelectorAll("[data-src]");
|
|
157
|
-
for (const island of allIslands) {
|
|
158
|
-
const src = island.getAttribute("data-src");
|
|
159
|
-
if (!src) continue;
|
|
160
|
-
const normalizedSrc = this.normalizePath(src);
|
|
161
|
-
if (normalizedSrc === normalizedPath || normalizedSrc.includes(normalizedPath)) {
|
|
162
|
-
islands.push(island);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return islands;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Trigger re-render of an island to apply new CSS module classes
|
|
169
|
-
*/
|
|
170
|
-
triggerIslandRerender(island, info) {
|
|
171
|
-
// Dispatch event to trigger island re-render
|
|
172
|
-
// The HMR coordinator will handle the actual re-render
|
|
173
|
-
island.dispatchEvent(new CustomEvent("css-module-update", {
|
|
174
|
-
detail: {
|
|
175
|
-
cssPath: info.path,
|
|
176
|
-
timestamp: info.timestamp
|
|
177
|
-
},
|
|
178
|
-
bubbles: true
|
|
179
|
-
}));
|
|
180
|
-
// Also trigger a standard HMR update event
|
|
181
|
-
// This will be picked up by the HMR coordinator
|
|
182
|
-
const src = island.getAttribute("data-src");
|
|
183
|
-
if (src) {
|
|
184
|
-
island.dispatchEvent(new CustomEvent("hmr-update-required", {
|
|
185
|
-
detail: {
|
|
186
|
-
src,
|
|
187
|
-
reason: "css-module-update",
|
|
188
|
-
cssPath: info.path
|
|
189
|
-
},
|
|
190
|
-
bubbles: true
|
|
191
|
-
}));
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Dispatch CSS update event for feedback
|
|
196
|
-
*/
|
|
197
|
-
dispatchCSSUpdateEvent(info, success, error) {
|
|
198
|
-
const event = new CustomEvent("css-hmr-update", {
|
|
199
|
-
detail: {
|
|
200
|
-
type: info.type,
|
|
201
|
-
path: info.path,
|
|
202
|
-
timestamp: info.timestamp,
|
|
203
|
-
success,
|
|
204
|
-
error: error?.message
|
|
205
|
-
},
|
|
206
|
-
bubbles: true
|
|
207
|
-
});
|
|
208
|
-
document.dispatchEvent(event);
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Normalize a file path for comparison
|
|
212
|
-
*/
|
|
213
|
-
normalizePath(path) {
|
|
214
|
-
return path.replace(/\\/g, "/").replace(/^\//, "").replace(/\?.*$/, "").replace(/#.*$/, "");
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Get directory from a file path
|
|
218
|
-
*/
|
|
219
|
-
getDirectory(path) {
|
|
220
|
-
const normalized = this.normalizePath(path);
|
|
221
|
-
const lastSlash = normalized.lastIndexOf("/");
|
|
222
|
-
return lastSlash >= 0 ? normalized.substring(0, lastSlash) : "";
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Get file ID from path (for Vite's data-vite-dev-id)
|
|
226
|
-
*/
|
|
227
|
-
getFileId(path) {
|
|
228
|
-
const normalized = this.normalizePath(path);
|
|
229
|
-
// Vite uses the file path as the ID
|
|
230
|
-
return normalized;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Clear cached mappings
|
|
234
|
-
*/
|
|
235
|
-
clearCache() {
|
|
236
|
-
this.cssModuleMap.clear();
|
|
237
|
-
this.styleElementMap.clear();
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Register an island as using a CSS module
|
|
241
|
-
* Useful for explicit tracking
|
|
242
|
-
*/
|
|
243
|
-
registerCSSModuleUsage(cssPath, island) {
|
|
244
|
-
const normalized = this.normalizePath(cssPath);
|
|
245
|
-
if (!this.cssModuleMap.has(normalized)) {
|
|
246
|
-
this.cssModuleMap.set(normalized, new Set());
|
|
247
|
-
}
|
|
248
|
-
this.cssModuleMap.get(normalized).add(island);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Global CSS HMR handler instance
|
|
253
|
-
*/
|
|
254
|
-
let cssHandlerInstance = null;
|
|
255
|
-
/**
|
|
256
|
-
* Get or create the global CSS HMR handler instance
|
|
257
|
-
*/
|
|
258
|
-
export function getCSSHMRHandler() {
|
|
259
|
-
if (!cssHandlerInstance) {
|
|
260
|
-
cssHandlerInstance = new CSSHMRHandler();
|
|
261
|
-
}
|
|
262
|
-
return cssHandlerInstance;
|
|
263
|
-
}
|
|
@@ -1,344 +0,0 @@
|
|
|
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)
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/// <reference lib="dom" />
|
|
11
|
-
/// <reference lib="dom.iterable" />
|
|
12
|
-
|
|
13
|
-
import type { Update } from './hmr-coordinator.ts';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* CSS update types
|
|
17
|
-
*/
|
|
18
|
-
export type CSSUpdateType = 'global' | 'module' | 'scoped';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* CSS update information
|
|
22
|
-
*/
|
|
23
|
-
export interface CSSUpdateInfo {
|
|
24
|
-
type: CSSUpdateType;
|
|
25
|
-
path: string;
|
|
26
|
-
timestamp: number;
|
|
27
|
-
affectedComponents?: string[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* CSS HMR Handler class
|
|
32
|
-
* Manages CSS hot updates without page reload
|
|
33
|
-
*/
|
|
34
|
-
export class CSSHMRHandler {
|
|
35
|
-
private cssModuleMap: Map<string, Set<HTMLElement>> = new Map();
|
|
36
|
-
private styleElementMap: Map<string, HTMLStyleElement> = new Map();
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Handle CSS update from Vite HMR
|
|
40
|
-
*/
|
|
41
|
-
handleCSSUpdate(update: Update): void {
|
|
42
|
-
const updateInfo = this.classifyCSSUpdate(update);
|
|
43
|
-
|
|
44
|
-
switch (updateInfo.type) {
|
|
45
|
-
case 'global':
|
|
46
|
-
this.handleGlobalCSSUpdate(updateInfo);
|
|
47
|
-
break;
|
|
48
|
-
case 'module':
|
|
49
|
-
this.handleCSSModuleUpdate(updateInfo);
|
|
50
|
-
break;
|
|
51
|
-
case 'scoped':
|
|
52
|
-
this.handleScopedCSSUpdate(updateInfo);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Classify the type of CSS update
|
|
59
|
-
*/
|
|
60
|
-
private classifyCSSUpdate(update: Update): CSSUpdateInfo {
|
|
61
|
-
const path = update.path || update.acceptedPath;
|
|
62
|
-
|
|
63
|
-
// Check if it's a CSS module
|
|
64
|
-
if (path.includes('.module.css') || path.includes('.module.scss')) {
|
|
65
|
-
return {
|
|
66
|
-
type: 'module',
|
|
67
|
-
path,
|
|
68
|
-
timestamp: update.timestamp,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Check if it's a scoped style (Svelte or Vue)
|
|
73
|
-
if (path.includes('.svelte') || path.includes('.vue')) {
|
|
74
|
-
return {
|
|
75
|
-
type: 'scoped',
|
|
76
|
-
path,
|
|
77
|
-
timestamp: update.timestamp,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Default to global CSS
|
|
82
|
-
return {
|
|
83
|
-
type: 'global',
|
|
84
|
-
path,
|
|
85
|
-
timestamp: update.timestamp,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Handle global CSS file update
|
|
91
|
-
* Injects updated styles without page reload
|
|
92
|
-
*/
|
|
93
|
-
private handleGlobalCSSUpdate(info: CSSUpdateInfo): void {
|
|
94
|
-
try {
|
|
95
|
-
// Find existing style element for this CSS file
|
|
96
|
-
const existingStyle = this.styleElementMap.get(info.path);
|
|
97
|
-
|
|
98
|
-
if (existingStyle) {
|
|
99
|
-
// Remove old style element
|
|
100
|
-
existingStyle.remove();
|
|
101
|
-
this.styleElementMap.delete(info.path);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Vite automatically injects the updated CSS via its HMR mechanism
|
|
105
|
-
// We just need to ensure old styles are removed
|
|
106
|
-
// The new styles will be injected by Vite's CSS handling
|
|
107
|
-
|
|
108
|
-
// Find the newly injected style element
|
|
109
|
-
// Vite adds a data-vite-dev-id attribute to style elements
|
|
110
|
-
const newStyle = document.querySelector<HTMLStyleElement>(
|
|
111
|
-
`style[data-vite-dev-id*="${this.getFileId(info.path)}"]`,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
if (newStyle) {
|
|
115
|
-
this.styleElementMap.set(info.path, newStyle);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Dispatch event for feedback
|
|
119
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error(`Failed to update global CSS: ${info.path}`, error);
|
|
122
|
-
this.dispatchCSSUpdateEvent(info, false, error as Error);
|
|
123
|
-
throw error;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Handle CSS module update
|
|
129
|
-
* Re-renders components using the updated CSS module
|
|
130
|
-
*/
|
|
131
|
-
private handleCSSModuleUpdate(info: CSSUpdateInfo): void {
|
|
132
|
-
try {
|
|
133
|
-
const affectedIslands = this.findIslandsUsingCSSModule(info.path);
|
|
134
|
-
|
|
135
|
-
if (affectedIslands.length === 0) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
for (const island of affectedIslands) {
|
|
140
|
-
this.triggerIslandRerender(island, info);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.error(`[HMR] Failed to update CSS module: ${info.path}`, error);
|
|
146
|
-
this.dispatchCSSUpdateEvent(info, false, error as Error);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Handle scoped CSS update (Svelte/Vue)
|
|
153
|
-
* Updates only the affected component's styles
|
|
154
|
-
*/
|
|
155
|
-
private handleScopedCSSUpdate(info: CSSUpdateInfo): void {
|
|
156
|
-
try {
|
|
157
|
-
const affectedIslands = this.findIslandsUsingComponent(info.path);
|
|
158
|
-
|
|
159
|
-
if (affectedIslands.length === 0) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
this.dispatchCSSUpdateEvent(info, true);
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error(`[HMR] Failed to update scoped CSS: ${info.path}`, error);
|
|
166
|
-
this.dispatchCSSUpdateEvent(info, false, error as Error);
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Find islands that use a specific CSS module
|
|
173
|
-
*/
|
|
174
|
-
private findIslandsUsingCSSModule(cssPath: string): HTMLElement[] {
|
|
175
|
-
const islands: HTMLElement[] = [];
|
|
176
|
-
const normalizedPath = this.normalizePath(cssPath);
|
|
177
|
-
|
|
178
|
-
// Check cached mapping first
|
|
179
|
-
const cached = this.cssModuleMap.get(normalizedPath);
|
|
180
|
-
if (cached) {
|
|
181
|
-
return Array.from(cached);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Find all islands
|
|
185
|
-
const allIslands = document.querySelectorAll<HTMLElement>('[data-src]');
|
|
186
|
-
|
|
187
|
-
for (const island of allIslands) {
|
|
188
|
-
const src = island.getAttribute('data-src');
|
|
189
|
-
if (!src) continue;
|
|
190
|
-
|
|
191
|
-
// Check if the island's component likely imports this CSS module
|
|
192
|
-
// This is a heuristic - we look for islands in the same directory
|
|
193
|
-
const componentDir = this.getDirectory(src);
|
|
194
|
-
const cssDir = this.getDirectory(cssPath);
|
|
195
|
-
|
|
196
|
-
if (componentDir === cssDir) {
|
|
197
|
-
islands.push(island);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Cache the mapping
|
|
202
|
-
if (islands.length > 0) {
|
|
203
|
-
this.cssModuleMap.set(normalizedPath, new Set(islands));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return islands;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Find islands using a specific component file
|
|
211
|
-
*/
|
|
212
|
-
private findIslandsUsingComponent(componentPath: string): HTMLElement[] {
|
|
213
|
-
const islands: HTMLElement[] = [];
|
|
214
|
-
const normalizedPath = this.normalizePath(componentPath);
|
|
215
|
-
|
|
216
|
-
const allIslands = document.querySelectorAll<HTMLElement>('[data-src]');
|
|
217
|
-
|
|
218
|
-
for (const island of allIslands) {
|
|
219
|
-
const src = island.getAttribute('data-src');
|
|
220
|
-
if (!src) continue;
|
|
221
|
-
|
|
222
|
-
const normalizedSrc = this.normalizePath(src);
|
|
223
|
-
|
|
224
|
-
if (normalizedSrc === normalizedPath || normalizedSrc.includes(normalizedPath)) {
|
|
225
|
-
islands.push(island);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return islands;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Trigger re-render of an island to apply new CSS module classes
|
|
234
|
-
*/
|
|
235
|
-
private triggerIslandRerender(island: HTMLElement, info: CSSUpdateInfo): void {
|
|
236
|
-
// Dispatch event to trigger island re-render
|
|
237
|
-
// The HMR coordinator will handle the actual re-render
|
|
238
|
-
island.dispatchEvent(
|
|
239
|
-
new CustomEvent('css-module-update', {
|
|
240
|
-
detail: {
|
|
241
|
-
cssPath: info.path,
|
|
242
|
-
timestamp: info.timestamp,
|
|
243
|
-
},
|
|
244
|
-
bubbles: true,
|
|
245
|
-
}),
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
// Also trigger a standard HMR update event
|
|
249
|
-
// This will be picked up by the HMR coordinator
|
|
250
|
-
const src = island.getAttribute('data-src');
|
|
251
|
-
if (src) {
|
|
252
|
-
island.dispatchEvent(
|
|
253
|
-
new CustomEvent('hmr-update-required', {
|
|
254
|
-
detail: {
|
|
255
|
-
src,
|
|
256
|
-
reason: 'css-module-update',
|
|
257
|
-
cssPath: info.path,
|
|
258
|
-
},
|
|
259
|
-
bubbles: true,
|
|
260
|
-
}),
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Dispatch CSS update event for feedback
|
|
267
|
-
*/
|
|
268
|
-
private dispatchCSSUpdateEvent(info: CSSUpdateInfo, success: boolean, error?: Error): void {
|
|
269
|
-
const event = new CustomEvent('css-hmr-update', {
|
|
270
|
-
detail: {
|
|
271
|
-
type: info.type,
|
|
272
|
-
path: info.path,
|
|
273
|
-
timestamp: info.timestamp,
|
|
274
|
-
success,
|
|
275
|
-
error: error?.message,
|
|
276
|
-
},
|
|
277
|
-
bubbles: true,
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
document.dispatchEvent(event);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Normalize a file path for comparison
|
|
285
|
-
*/
|
|
286
|
-
private normalizePath(path: string): string {
|
|
287
|
-
return path.replace(/\\/g, '/').replace(/^\//, '').replace(/\?.*$/, '').replace(/#.*$/, '');
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Get directory from a file path
|
|
292
|
-
*/
|
|
293
|
-
private getDirectory(path: string): string {
|
|
294
|
-
const normalized = this.normalizePath(path);
|
|
295
|
-
const lastSlash = normalized.lastIndexOf('/');
|
|
296
|
-
return lastSlash >= 0 ? normalized.substring(0, lastSlash) : '';
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Get file ID from path (for Vite's data-vite-dev-id)
|
|
301
|
-
*/
|
|
302
|
-
private getFileId(path: string): string {
|
|
303
|
-
const normalized = this.normalizePath(path);
|
|
304
|
-
// Vite uses the file path as the ID
|
|
305
|
-
return normalized;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Clear cached mappings
|
|
310
|
-
*/
|
|
311
|
-
clearCache(): void {
|
|
312
|
-
this.cssModuleMap.clear();
|
|
313
|
-
this.styleElementMap.clear();
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Register an island as using a CSS module
|
|
318
|
-
* Useful for explicit tracking
|
|
319
|
-
*/
|
|
320
|
-
registerCSSModuleUsage(cssPath: string, island: HTMLElement): void {
|
|
321
|
-
const normalized = this.normalizePath(cssPath);
|
|
322
|
-
|
|
323
|
-
if (!this.cssModuleMap.has(normalized)) {
|
|
324
|
-
this.cssModuleMap.set(normalized, new Set());
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
this.cssModuleMap.get(normalized)!.add(island);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Global CSS HMR handler instance
|
|
333
|
-
*/
|
|
334
|
-
let cssHandlerInstance: CSSHMRHandler | null = null;
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Get or create the global CSS HMR handler instance
|
|
338
|
-
*/
|
|
339
|
-
export function getCSSHMRHandler(): CSSHMRHandler {
|
|
340
|
-
if (!cssHandlerInstance) {
|
|
341
|
-
cssHandlerInstance = new CSSHMRHandler();
|
|
342
|
-
}
|
|
343
|
-
return cssHandlerInstance;
|
|
344
|
-
}
|