@absolutejs/absolute 0.19.0-beta.704 → 0.19.0-beta.706

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 (103) hide show
  1. package/dist/angular/browser.js +6 -4
  2. package/dist/angular/browser.js.map +3 -3
  3. package/dist/angular/index.js +71 -82
  4. package/dist/angular/index.js.map +10 -10
  5. package/dist/angular/server.js +70 -81
  6. package/dist/angular/server.js.map +10 -10
  7. package/dist/build.js +152 -84
  8. package/dist/build.js.map +15 -15
  9. package/dist/cli/index.js +330 -296
  10. package/dist/client/index.js +7 -4
  11. package/dist/client/index.js.map +3 -3
  12. package/dist/index.js +253 -153
  13. package/dist/index.js.map +24 -24
  14. package/dist/islands/index.js +9 -6
  15. package/dist/islands/index.js.map +5 -5
  16. package/dist/react/browser.js +7 -7
  17. package/dist/react/browser.js.map +2 -2
  18. package/dist/react/components/browser/index.js +101 -101
  19. package/dist/react/components/index.js +104 -104
  20. package/dist/react/components/index.js.map +2 -2
  21. package/dist/react/index.js +77 -88
  22. package/dist/react/index.js.map +10 -10
  23. package/dist/react/jsxDevRuntimeCompat.js +1 -6
  24. package/dist/react/jsxDevRuntimeCompat.js.map +3 -3
  25. package/dist/react/server.js +57 -71
  26. package/dist/react/server.js.map +8 -8
  27. package/dist/src/angular/components/defer-slot-templates.directive.d.ts +0 -7
  28. package/dist/src/angular/components/defer-slot.component.d.ts +2 -5
  29. package/dist/src/angular/components/image.component.d.ts +2 -5
  30. package/dist/src/angular/components/index.d.ts +4 -4
  31. package/dist/src/angular/components/stream-slot.component.d.ts +0 -3
  32. package/dist/src/angular/pageHandler.d.ts +6 -1
  33. package/dist/src/angular/ssrRender.d.ts +1 -1
  34. package/dist/src/build/buildAngularVendor.d.ts +3 -4
  35. package/dist/src/constants.d.ts +21 -0
  36. package/dist/src/core/ssrCache.d.ts +1 -1
  37. package/dist/src/core/wrapPageHandlerWithStreamingSlots.d.ts +1 -1
  38. package/dist/src/react/jsxDevRuntimeCompat.d.ts +3 -6
  39. package/dist/src/react/pageHandler.d.ts +2 -1
  40. package/dist/src/svelte/pageHandler.d.ts +2 -2
  41. package/dist/src/utils/defineConfig.d.ts +2 -2
  42. package/dist/src/utils/imageProcessing.d.ts +1 -1
  43. package/dist/src/utils/loadConfig.d.ts +38 -2
  44. package/dist/src/vue/components/Image.d.ts +3 -3
  45. package/dist/src/vue/components/index.d.ts +1 -1
  46. package/dist/src/vue/index.d.ts +1 -1
  47. package/dist/src/vue/pageHandler.d.ts +2 -1
  48. package/dist/svelte/index.js +52 -58
  49. package/dist/svelte/index.js.map +10 -10
  50. package/dist/svelte/server.js +46 -55
  51. package/dist/svelte/server.js.map +9 -9
  52. package/dist/vue/components/Image.js +18 -18
  53. package/dist/vue/components/Image.js.map +3 -3
  54. package/dist/vue/components/index.js +77 -62
  55. package/dist/vue/components/index.js.map +5 -5
  56. package/dist/vue/index.js +137 -142
  57. package/dist/vue/index.js.map +13 -13
  58. package/dist/vue/server.js +54 -77
  59. package/dist/vue/server.js.map +8 -8
  60. package/package.json +42 -42
  61. package/dist/angular/components/constants.js +0 -56
  62. package/dist/angular/components/core/streamingSlotRegistrar.js +0 -58
  63. package/dist/angular/components/core/streamingSlotRegistry.js +0 -114
  64. package/dist/angular/components/defer-slot-payload.js +0 -6
  65. package/dist/angular/components/defer-slot-templates.directive.js +0 -44
  66. package/dist/angular/components/defer-slot.component.js +0 -149
  67. package/dist/angular/components/image.component.js +0 -202
  68. package/dist/angular/components/index.js +0 -4
  69. package/dist/angular/components/stream-slot.component.js +0 -103
  70. package/dist/dev/client/constants.ts +0 -26
  71. package/dist/dev/client/cssUtils.ts +0 -307
  72. package/dist/dev/client/domDiff.ts +0 -226
  73. package/dist/dev/client/domState.ts +0 -421
  74. package/dist/dev/client/domTracker.ts +0 -61
  75. package/dist/dev/client/errorOverlay.ts +0 -184
  76. package/dist/dev/client/frameworkDetect.ts +0 -63
  77. package/dist/dev/client/handlers/angular.ts +0 -551
  78. package/dist/dev/client/handlers/angularRuntime.ts +0 -206
  79. package/dist/dev/client/handlers/html.ts +0 -363
  80. package/dist/dev/client/handlers/htmx.ts +0 -272
  81. package/dist/dev/client/handlers/react.ts +0 -108
  82. package/dist/dev/client/handlers/rebuild.ts +0 -153
  83. package/dist/dev/client/handlers/svelte.ts +0 -332
  84. package/dist/dev/client/handlers/vue.ts +0 -292
  85. package/dist/dev/client/headPatch.ts +0 -233
  86. package/dist/dev/client/hmrClient.ts +0 -251
  87. package/dist/dev/client/hmrState.ts +0 -14
  88. package/dist/dev/client/moduleVersions.ts +0 -62
  89. package/dist/dev/client/reactRefreshSetup.ts +0 -33
  90. package/dist/src/angular/components/constants.d.ts +0 -53
  91. package/dist/svelte/components/AwaitSlot.svelte +0 -39
  92. package/dist/svelte/components/AwaitSlot.svelte.d.ts +0 -2
  93. package/dist/svelte/components/Head.svelte +0 -144
  94. package/dist/svelte/components/Head.svelte.d.ts +0 -2
  95. package/dist/svelte/components/Image.svelte +0 -164
  96. package/dist/svelte/components/Image.svelte.d.ts +0 -5
  97. package/dist/svelte/components/Island.svelte +0 -71
  98. package/dist/svelte/components/Island.svelte.d.ts +0 -5
  99. package/dist/svelte/components/JsonLd.svelte +0 -21
  100. package/dist/svelte/components/JsonLd.svelte.d.ts +0 -2
  101. package/dist/svelte/components/StreamSlot.svelte +0 -41
  102. package/dist/svelte/components/StreamSlot.svelte.d.ts +0 -2
  103. package/dist/types/globals.d.ts +0 -121
@@ -1,206 +0,0 @@
1
- import type {} from '../../../types/globals';
2
- /* Angular HMR — Zoneless Runtime Preservation
3
- DEV MODE ONLY — never included in production builds.
4
-
5
- Runtime component patching via prototype swap and ɵcmp metadata swap.
6
- State persists naturally via instance continuity — NO serialization.
7
-
8
- Why state serialization was removed:
9
- Angular component + service state lives on JS object instances.
10
- Prototype swapping replaces method implementations without destroying
11
- instances, so all state (properties, injected services, etc.) survives.
12
- Serializing and reassigning state is fragile, lossy, and unnecessary.
13
-
14
- Why zoneless requires manual tick():
15
- With provideZonelessChangeDetection(), there is no Zone.js to
16
- auto-trigger change detection. After swapping prototypes or templates,
17
- we must explicitly call ApplicationRef.tick() to re-render.
18
-
19
- Why this is safe in a multi-framework environment:
20
- This module only touches Angular-specific globals (__ANGULAR_APP__,
21
- __ANGULAR_HMR__). It never modifies document.body, React roots,
22
- Vue instances, or Svelte components. The registry is keyed by
23
- source file path, so name collisions across frameworks are impossible. */
24
-
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- type ComponentCtor = any;
27
-
28
- type RegistryEntry = {
29
- liveCtor: ComponentCtor;
30
- id: string;
31
- registeredAt: number;
32
- updateCount: number;
33
- };
34
-
35
- const componentRegistry = new Map<string, RegistryEntry>();
36
- let globalUpdateCount = 0;
37
-
38
- const hasInjectorProviderChanges = (
39
- oldCtor: ComponentCtor,
40
- newCtor: ComponentCtor
41
- ) => {
42
- if (oldCtor.ɵinj === undefined || newCtor.ɵinj === undefined) return false;
43
- const oldP = oldCtor.ɵinj?.providers;
44
- const newP = newCtor.ɵinj?.providers;
45
- if (!Array.isArray(oldP) || !Array.isArray(newP)) return false;
46
-
47
- return oldP.length !== newP.length;
48
- };
49
-
50
- const hasComponentProviderChanges = (
51
- oldCtor: ComponentCtor,
52
- newCtor: ComponentCtor
53
- ) => {
54
- if (!oldCtor.ɵcmp || !newCtor.ɵcmp) return false;
55
- const oldResolver = oldCtor.ɵcmp.providersResolver;
56
- const newResolver = newCtor.ɵcmp.providersResolver;
57
-
58
- return (oldResolver === undefined) !== (newResolver === undefined);
59
- };
60
-
61
- const hasProviderChanges = (oldCtor: ComponentCtor, newCtor: ComponentCtor) => {
62
- if (hasInjectorProviderChanges(oldCtor, newCtor)) return true;
63
- if (hasComponentProviderChanges(oldCtor, newCtor)) return true;
64
-
65
- return false;
66
- };
67
-
68
- const register = (id: string, ctor: ComponentCtor) => {
69
- if (!id || typeof ctor !== 'function') return;
70
- if (!componentRegistry.has(id)) {
71
- componentRegistry.set(id, {
72
- id,
73
- liveCtor: ctor,
74
- registeredAt: Date.now(),
75
- updateCount: 0
76
- });
77
- }
78
- };
79
-
80
- const SKIP_STATIC_PROPS = [
81
- 'prototype',
82
- 'length',
83
- 'name',
84
- 'caller',
85
- 'arguments'
86
- ];
87
-
88
- const swapPrototypeProp = (
89
- liveCtor: ComponentCtor,
90
- newProto: ComponentCtor,
91
- prop: string
92
- ) => {
93
- if (prop === 'constructor') return;
94
- try {
95
- const desc = Object.getOwnPropertyDescriptor(newProto, prop);
96
- if (desc) Object.defineProperty(liveCtor.prototype, prop, desc);
97
- } catch {
98
- /* non-configurable */
99
- }
100
- };
101
-
102
- const swapStaticProp = (
103
- liveCtor: ComponentCtor,
104
- newCtor: ComponentCtor,
105
- prop: string
106
- ) => {
107
- if (SKIP_STATIC_PROPS.includes(prop)) return true;
108
- try {
109
- const desc = Object.getOwnPropertyDescriptor(newCtor, prop);
110
- if (!desc) return true;
111
- if (!desc.configurable) return prop !== 'ɵcmp' && prop !== 'ɵfac';
112
- Object.defineProperty(liveCtor, prop, desc);
113
-
114
- return true;
115
- } catch {
116
- return prop !== 'ɵcmp' && prop !== 'ɵfac';
117
- }
118
- };
119
-
120
- const patchConstructor = (entry: RegistryEntry, newCtor: ComponentCtor) => {
121
- const { liveCtor } = entry;
122
-
123
- const newProto = newCtor.prototype;
124
- Object.getOwnPropertyNames(newProto).forEach((prop) => {
125
- swapPrototypeProp(liveCtor, newProto, prop);
126
- });
127
-
128
- const allPatched = Object.getOwnPropertyNames(newCtor).every((prop) =>
129
- swapStaticProp(liveCtor, newCtor, prop)
130
- );
131
-
132
- if (!allPatched) {
133
- throw new Error('Cannot patch non-configurable Angular metadata');
134
- }
135
-
136
- globalUpdateCount++;
137
- entry.updateCount++;
138
- entry.registeredAt = Date.now();
139
- };
140
-
141
- const applyUpdate = (id: string, newCtor: ComponentCtor) => {
142
- const entry = componentRegistry.get(id);
143
- if (!entry) {
144
- register(id, newCtor);
145
-
146
- return true;
147
- }
148
-
149
- const { liveCtor } = entry;
150
- if (liveCtor === newCtor) return true;
151
-
152
- if (hasProviderChanges(liveCtor, newCtor)) {
153
- console.warn(
154
- '[HMR] Angular provider change detected for',
155
- id,
156
- '→ full reload'
157
- );
158
-
159
- return false;
160
- }
161
- if (newCtor.ɵcmp === undefined && liveCtor.ɵcmp !== undefined) {
162
- console.warn(
163
- '[HMR] New constructor missing ɵcmp for',
164
- id,
165
- '→ full reload'
166
- );
167
-
168
- return false;
169
- }
170
-
171
- try {
172
- patchConstructor(entry, newCtor);
173
-
174
- return true;
175
- } catch (err) {
176
- console.error('[HMR] Angular runtime patch failed for', id, ':', err);
177
-
178
- return false;
179
- }
180
- };
181
-
182
- const refresh = () => {
183
- if (!window.__ANGULAR_APP__) return;
184
- try {
185
- window.__ANGULAR_APP__.tick();
186
- } catch (err) {
187
- console.warn('[HMR] Angular tick() failed after patch:', err);
188
- }
189
- };
190
-
191
- export const installAngularHMRRuntime = () => {
192
- if (typeof window === 'undefined') return;
193
- window.__ANGULAR_HMR__ = {
194
- applyUpdate,
195
- refresh,
196
- register,
197
- getRegistry: () => componentRegistry,
198
- // eslint-disable-next-line absolute/no-useless-function -- must be a callable method on the HMR API
199
- getStats: () => ({
200
- componentCount: componentRegistry.size,
201
- updateCount: globalUpdateCount
202
- })
203
- };
204
- };
205
-
206
- installAngularHMRRuntime();
@@ -1,363 +0,0 @@
1
- import type {} from '../../../types/globals';
2
- /* HTML + script HMR update handlers */
3
-
4
- import { DOM_UPDATE_DELAY_MS } from '../constants';
5
- import { patchDOMInPlace } from '../domDiff';
6
- import {
7
- saveDOMState,
8
- restoreDOMState,
9
- saveFormState,
10
- restoreFormState,
11
- saveScrollState,
12
- restoreScrollState
13
- } from '../domState';
14
- import { processCSSLinks, waitForCSSAndUpdate } from '../cssUtils';
15
- import { patchHeadInPlace } from '../headPatch';
16
- import { detectCurrentFramework } from '../frameworkDetect';
17
- import type { ScriptInfo } from '../../../types/client';
18
- import { restoreDOMChanges, snapshotDOMChanges } from '../domTracker';
19
- import { hmrState } from '../hmrState';
20
-
21
- const parseHTMLMessage = (
22
- html: string | { body?: string; head?: string } | null | undefined
23
- ) => {
24
- let body: string | null = null;
25
- let head: string | null = null;
26
- if (typeof html === 'string') {
27
- body = html;
28
- } else if (html && typeof html === 'object') {
29
- body = html.body || null;
30
- head = html.head || null;
31
- }
32
-
33
- return { body, head };
34
- };
35
-
36
- const applyHeadPatch = (htmlHead: string | null) => {
37
- if (!htmlHead) {
38
- return;
39
- }
40
-
41
- const doPatchHead = () => {
42
- patchHeadInPlace(htmlHead);
43
- };
44
- if (hmrState.isFirstHMRUpdate) {
45
- setTimeout(doPatchHead, DOM_UPDATE_DELAY_MS);
46
- } else {
47
- doPatchHead();
48
- }
49
- };
50
-
51
- const handleHTMLBodyWithHead = (
52
- htmlBody: string,
53
- htmlHead: string,
54
- htmlDomState: ReturnType<typeof saveDOMState>
55
- ) => {
56
- applyHeadPatch(htmlHead);
57
-
58
- const cssResult = processCSSLinks(htmlHead);
59
-
60
- const updateBodyAfterCSS = () => {
61
- updateHTMLBody(htmlBody, htmlDomState, document.body);
62
- };
63
-
64
- waitForCSSAndUpdate(cssResult, updateBodyAfterCSS);
65
- };
66
-
67
- const handleHTMLBodyWithoutHead = (
68
- htmlBody: string,
69
- htmlDomState: ReturnType<typeof saveDOMState>
70
- ) => {
71
- const container = document.body;
72
- if (!container) {
73
- sessionStorage.removeItem('__HMR_ACTIVE__');
74
-
75
- return;
76
- }
77
-
78
- updateHTMLBodyDirect(htmlBody, htmlDomState, container);
79
- restoreDOMState(container, htmlDomState);
80
- };
81
-
82
- export const handleHTMLUpdate = (message: {
83
- data: {
84
- html?: string | { body?: string; head?: string } | null;
85
- };
86
- }) => {
87
- const htmlFrameworkCheck = detectCurrentFramework();
88
- if (htmlFrameworkCheck !== 'html') {
89
- return;
90
- }
91
-
92
- if (window.__REACT_ROOT__) {
93
- window.__REACT_ROOT__ = undefined;
94
- }
95
-
96
- sessionStorage.setItem('__HMR_ACTIVE__', 'true');
97
-
98
- const htmlDomState = saveDOMState(document.body);
99
- const { body: htmlBody, head: htmlHead } = parseHTMLMessage(
100
- message.data.html
101
- );
102
-
103
- if (!htmlBody) {
104
- sessionStorage.removeItem('__HMR_ACTIVE__');
105
-
106
- return;
107
- }
108
-
109
- if (htmlHead) {
110
- handleHTMLBodyWithHead(htmlBody, htmlHead, htmlDomState);
111
- } else {
112
- handleHTMLBodyWithoutHead(htmlBody, htmlDomState);
113
- }
114
- };
115
- export const handleScriptUpdate = (message: {
116
- data: { framework?: string; scriptPath?: string };
117
- }) => {
118
- const scriptFramework = message.data.framework;
119
- const currentFw = detectCurrentFramework();
120
-
121
- if (currentFw !== scriptFramework) {
122
- return;
123
- }
124
-
125
- const { scriptPath } = message.data;
126
- if (!scriptPath) {
127
- console.warn('[HMR] No script path in update');
128
-
129
- return;
130
- }
131
-
132
- const interactiveSelectors =
133
- 'button, [onclick], [onchange], [oninput], details, input, select, textarea';
134
- document.body.querySelectorAll(interactiveSelectors).forEach((elem) => {
135
- const cloned = elem.cloneNode(true);
136
- if (elem.parentNode) {
137
- elem.parentNode.replaceChild(cloned, elem);
138
- }
139
- });
140
-
141
- const cacheBustedPath = `${scriptPath}?t=${Date.now()}`;
142
- import(cacheBustedPath)
143
- .then(() => true)
144
- .catch((err: unknown) => {
145
- console.error(
146
- '[HMR] Script hot-reload failed, falling back to page reload:',
147
- err
148
- );
149
- window.location.reload();
150
- });
151
- };
152
-
153
- // eslint-disable-next-line absolute/no-useless-function -- must be called each time to capture current state
154
- const saveHTMLState = () => ({
155
- forms: saveFormState(),
156
- scroll: saveScrollState()
157
- });
158
-
159
- const preserveHmrScript = (
160
- container: HTMLElement,
161
- hmrScript: Element | null
162
- ) => {
163
- if (hmrScript && !container.querySelector('script[data-hmr-client]')) {
164
- container.appendChild(hmrScript);
165
- }
166
- };
167
-
168
- const updateHTMLBody = (
169
- htmlBody: string,
170
- htmlDomState: ReturnType<typeof saveDOMState>,
171
- container: HTMLElement
172
- ) => {
173
- if (!container) {
174
- return;
175
- }
176
-
177
- const savedState = saveHTMLState();
178
- const domSnapshot = snapshotDOMChanges(container);
179
-
180
- const existingScripts = collectScripts(container);
181
- const hmrScript = container.querySelector('script[data-hmr-client]');
182
- const tempDiv = document.createElement('div');
183
- tempDiv.innerHTML = htmlBody;
184
- const newScripts = collectScriptsFromElement(tempDiv);
185
-
186
- const htmlStructureChanged = didHTMLStructureChange(container, tempDiv);
187
-
188
- if (htmlStructureChanged || didScriptsChange(existingScripts, newScripts)) {
189
- patchDOMInPlace(container, htmlBody);
190
- restoreDOMChanges(container, domSnapshot, htmlBody);
191
- }
192
-
193
- preserveHmrScript(container, hmrScript);
194
-
195
- requestAnimationFrame(() => {
196
- restoreDOMState(container, htmlDomState);
197
- restoreFormState(savedState.forms);
198
- restoreScrollState(savedState.scroll);
199
-
200
- if (
201
- didScriptsChange(existingScripts, newScripts) ||
202
- htmlStructureChanged
203
- ) {
204
- cloneInteractiveElements(container);
205
- reExecuteScripts(container, newScripts);
206
- }
207
- });
208
- sessionStorage.removeItem('__HMR_ACTIVE__');
209
- };
210
-
211
- const cloneHmrListenerElements = (container: HTMLElement) => {
212
- container
213
- .querySelectorAll('[data-hmr-listeners-attached]')
214
- .forEach((elem) => {
215
- const cloned = elem.cloneNode(true);
216
- if (elem.parentNode) {
217
- elem.parentNode.replaceChild(cloned, elem);
218
- }
219
- if (cloned instanceof Element) {
220
- cloned.removeAttribute('data-hmr-listeners-attached');
221
- }
222
- });
223
- };
224
-
225
- const replaceInlineScript = (script: Element) => {
226
- if (script.hasAttribute('data-hmr-client')) {
227
- return;
228
- }
229
-
230
- const newScript = document.createElement('script');
231
- newScript.textContent = script.textContent || '';
232
- const scriptEl = script instanceof HTMLScriptElement ? script : null;
233
- newScript.type = scriptEl?.type || 'text/javascript';
234
- if (script.parentNode) {
235
- script.parentNode.replaceChild(newScript, script);
236
- }
237
- };
238
-
239
- const updateHTMLBodyDirect = (
240
- htmlBody: string,
241
- htmlDomState: ReturnType<typeof saveDOMState>,
242
- container: HTMLElement
243
- ) => {
244
- const savedState = saveHTMLState();
245
- const domSnapshot = snapshotDOMChanges(container);
246
-
247
- const tempDiv = document.createElement('div');
248
- tempDiv.innerHTML = htmlBody;
249
- const newScripts = collectScriptsFromElement(tempDiv);
250
- const hmrScript = container.querySelector('script[data-hmr-client]');
251
-
252
- patchDOMInPlace(container, htmlBody);
253
- restoreDOMChanges(container, domSnapshot, htmlBody);
254
-
255
- preserveHmrScript(container, hmrScript);
256
-
257
- requestAnimationFrame(() => {
258
- restoreDOMState(container, htmlDomState);
259
- restoreFormState(savedState.forms);
260
- restoreScrollState(savedState.scroll);
261
-
262
- cloneHmrListenerElements(container);
263
-
264
- removeOldScripts(container);
265
- newScripts.forEach((scriptInfo) => {
266
- const newScript = document.createElement('script');
267
- const separator = scriptInfo.src.includes('?') ? '&' : '?';
268
- newScript.src = `${scriptInfo.src + separator}t=${Date.now()}`;
269
- newScript.type = scriptInfo.type;
270
- container.appendChild(newScript);
271
- });
272
-
273
- const inlineScripts = container.querySelectorAll('script:not([src])');
274
- inlineScripts.forEach(replaceInlineScript);
275
- });
276
- sessionStorage.removeItem('__HMR_ACTIVE__');
277
- };
278
-
279
- /* Shared helpers for HTML body updates */
280
-
281
- const collectScripts = (container: HTMLElement) =>
282
- Array.from(container.querySelectorAll('script[src]')).map((script) => ({
283
- src: script.getAttribute('src') || '',
284
- type: script.getAttribute('type') || 'text/javascript'
285
- }));
286
-
287
- const collectScriptsFromElement = (elem: HTMLElement) =>
288
- Array.from(elem.querySelectorAll('script[src]')).map((script) => ({
289
- src: script.getAttribute('src') || '',
290
- type: script.getAttribute('type') || 'text/javascript'
291
- }));
292
-
293
- const didScriptsChange = (oldScripts: ScriptInfo[], newScripts: ScriptInfo[]) =>
294
- oldScripts.length !== newScripts.length ||
295
- oldScripts.some((oldScript, idx) => {
296
- const [oldSrcBase] = oldScript.src.split('?')[0]?.split('&') ?? [''];
297
- const newScript = newScripts[idx];
298
- if (!newScript) return true;
299
- const [newSrcBase] = newScript.src.split('?')[0]?.split('&') ?? [''];
300
-
301
- return oldSrcBase !== newSrcBase;
302
- });
303
-
304
- const normalizeHTMLForComparison = (element: HTMLElement) => {
305
- const clonedNode = element.cloneNode(true);
306
- if (!(clonedNode instanceof HTMLElement)) return '';
307
- const clone = clonedNode;
308
- const scripts = clone.querySelectorAll('script');
309
- scripts.forEach((script) => {
310
- if (script.parentNode) {
311
- script.parentNode.removeChild(script);
312
- }
313
- });
314
- const allElements = clone.querySelectorAll('*');
315
- allElements.forEach((elem) => {
316
- elem.removeAttribute('data-hmr-listeners-attached');
317
- });
318
- if (clone.removeAttribute) {
319
- clone.removeAttribute('data-hmr-listeners-attached');
320
- }
321
-
322
- return clone.innerHTML;
323
- };
324
-
325
- const didHTMLStructureChange = (container: HTMLElement, tempDiv: HTMLElement) =>
326
- normalizeHTMLForComparison(container) !==
327
- normalizeHTMLForComparison(tempDiv);
328
-
329
- const cloneInteractiveElements = (container: HTMLElement) => {
330
- const interactiveSelectors =
331
- 'button, [onclick], [onchange], [oninput], [onsubmit], ' +
332
- 'details, input[type="button"], input[type="submit"], input[type="reset"]';
333
- container.querySelectorAll(interactiveSelectors).forEach((elem) => {
334
- const cloned = elem.cloneNode(true);
335
- if (elem.parentNode) {
336
- elem.parentNode.replaceChild(cloned, elem);
337
- }
338
- });
339
- };
340
-
341
- const removeOldScripts = (container: HTMLElement) => {
342
- const scriptsInNewHTML = container.querySelectorAll('script[src]');
343
- scriptsInNewHTML.forEach((script) => {
344
- if (!script.hasAttribute('data-hmr-client')) {
345
- script.remove();
346
- }
347
- });
348
- };
349
-
350
- const reExecuteScripts = (container: HTMLElement, newScripts: ScriptInfo[]) => {
351
- removeOldScripts(container);
352
-
353
- newScripts.forEach((scriptInfo) => {
354
- const newScript = document.createElement('script');
355
- const separator = scriptInfo.src.includes('?') ? '&' : '?';
356
- newScript.src = `${scriptInfo.src + separator}t=${Date.now()}`;
357
- newScript.type = scriptInfo.type;
358
- container.appendChild(newScript);
359
- });
360
-
361
- const inlineScripts = container.querySelectorAll('script:not([src])');
362
- inlineScripts.forEach(replaceInlineScript);
363
- };