@hyperspan/framework 1.0.25 → 1.0.26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperspan/framework",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "Hyperspan Web Framework",
5
5
  "main": "src/server.ts",
6
6
  "types": "src/server.ts",
@@ -94,6 +94,8 @@ function formSubmitToRoute(e: Event, form: HTMLFormElement, opts: TFormSubmitOpt
94
94
  }
95
95
  }
96
96
 
97
+ activateScriptsIn(isFullDocument ? document.body : (target as ParentNode));
98
+
97
99
  opts.afterResponse && opts.afterResponse();
98
100
  lazyLoadScripts();
99
101
  }
@@ -126,13 +128,7 @@ function formSubmitToRoute(e: Event, form: HTMLFormElement, opts: TFormSubmitOpt
126
128
  return;
127
129
  }
128
130
 
129
- const content = await res.text();
130
- // No content = DO NOTHING (redirect or something else happened)
131
- if (!content) {
132
- return;
133
- }
134
-
135
- applyResponseHtml(content);
131
+ await consumeStreamingHtmlResponse(res, applyResponseHtml);
136
132
  })
137
133
  .catch((error) => {
138
134
  console.error('[Hyperspan] Error submitting form action:', error);
@@ -153,28 +149,60 @@ function splitInitialStreamHtml(html: string): { initial: string; streamTail: st
153
149
  };
154
150
  }
155
151
 
156
- /** Append streamed HTML to body and run any inline scripts (e.g. window._hsc.push). */
152
+ /** Clone a script node so the browser will execute it (preserves module type). */
153
+ function cloneScriptForExecution(script: HTMLScriptElement): HTMLScriptElement {
154
+ const executable = document.createElement('script');
155
+ if (script.src) {
156
+ executable.src = script.src;
157
+ } else if (script.textContent) {
158
+ executable.textContent = script.textContent;
159
+ }
160
+ if (script.type) {
161
+ executable.type = script.type;
162
+ }
163
+ for (const attr of script.getAttributeNames()) {
164
+ if (attr === 'src' || attr === 'type') {
165
+ continue;
166
+ }
167
+ executable.setAttribute(attr, script.getAttribute(attr) || '');
168
+ }
169
+ return executable;
170
+ }
171
+
172
+ /** Run scripts inserted by Idiomorph (innerHTML/morph does not execute them). */
173
+ function activateScriptsIn(root: ParentNode) {
174
+ root.querySelectorAll('script').forEach((script) => {
175
+ if (script.closest('template[id$="_content"]')) {
176
+ return;
177
+ }
178
+ script.replaceWith(cloneScriptForExecution(script));
179
+ });
180
+ }
181
+
182
+ /** Append streamed HTML to body and run top-level chunk scripts (e.g. window._hsc.push). */
157
183
  function appendHtmlToBody(html: string) {
158
184
  if (!html) {
159
185
  return;
160
186
  }
161
187
 
162
- const template = document.createElement('template');
163
- template.innerHTML = html;
188
+ const container = document.createElement('template');
189
+ container.innerHTML = html;
164
190
  const scripts: HTMLScriptElement[] = [];
165
- template.content.querySelectorAll('script').forEach((script) => {
166
- scripts.push(script);
191
+
192
+ for (const node of Array.from(container.content.childNodes)) {
193
+ if (node.nodeName === 'SCRIPT') {
194
+ scripts.push(node as HTMLScriptElement);
195
+ }
196
+ }
197
+
198
+ for (const script of scripts) {
167
199
  script.remove();
168
- });
169
- document.body.appendChild(template.content);
200
+ }
201
+
202
+ document.body.appendChild(container.content);
203
+
170
204
  for (const script of scripts) {
171
- const executable = document.createElement('script');
172
- if (script.src) {
173
- executable.src = script.src;
174
- } else {
175
- executable.textContent = script.textContent;
176
- }
177
- document.body.appendChild(executable);
205
+ document.body.appendChild(cloneScriptForExecution(script));
178
206
  }
179
207
  }
180
208
 
@@ -227,4 +255,4 @@ async function consumeStreamingHtmlResponse(
227
255
  }
228
256
  processChunk(decoder.decode(value, { stream: true }));
229
257
  }
230
- }
258
+ }