@webtypen/webframez-react 0.0.48 → 0.0.50

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.
@@ -1,18 +1,92 @@
1
1
  "use client";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
2
27
 
3
- // src/navigation.tsx
4
- import { jsx } from "react/jsx-runtime";
5
- function getDefaultBasename() {
6
- const globalValue = globalThis.__RSC_BASENAME;
7
- if (globalValue && globalValue !== "/") {
8
- return globalValue;
28
+ // node_modules/@webtypen/webframez-core/dist/routing.js
29
+ var require_routing = __commonJS({
30
+ "node_modules/@webtypen/webframez-core/dist/routing.js"(exports) {
31
+ "use strict";
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.appRelativePath = exports.appPath = exports.getBasename = exports.normalizeBasename = void 0;
34
+ function normalizeBasename2(value) {
35
+ if (value == null || value === "" || value === "/")
36
+ return "";
37
+ if (typeof value !== "string")
38
+ throw new Error("Router basename must be a string.");
39
+ const base = value.trim().replace(/\/+$/, "");
40
+ if (!base && value.trim().length <= 1)
41
+ return "";
42
+ if (!/^\/(?:[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)(?:\/[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)*$/.test(base)) {
43
+ throw new Error("Router basename must be empty or an absolute path such as /my-app.");
44
+ }
45
+ return base;
46
+ }
47
+ exports.normalizeBasename = normalizeBasename2;
48
+ function getBasename2() {
49
+ var _a, _b, _c, _d;
50
+ const runtime = globalThis;
51
+ return (_d = (_c = (_b = (_a = runtime.__WEBFRAMEZ_ROUTING_CONTEXT__) === null || _a === void 0 ? void 0 : _a.getStore()) !== null && _b !== void 0 ? _b : runtime.__RSC_BASENAME) !== null && _c !== void 0 ? _c : runtime.__WEBFRAMEZ_ROUTER_BASENAME__) !== null && _d !== void 0 ? _d : "";
52
+ }
53
+ exports.getBasename = getBasename2;
54
+ function appPath2(value, basename = getBasename2()) {
55
+ const base = normalizeBasename2(basename);
56
+ if (!base || !value.startsWith("/") || value.startsWith("//") || hasBasename(value, base))
57
+ return value;
58
+ return base + value;
59
+ }
60
+ exports.appPath = appPath2;
61
+ function appRelativePath2(value, basename = getBasename2()) {
62
+ const base = normalizeBasename2(basename);
63
+ if (!base || !hasBasename(value, base))
64
+ return value;
65
+ const relative = value.slice(base.length);
66
+ return !relative || relative.startsWith("?") || relative.startsWith("#") ? "/" + relative : relative;
67
+ }
68
+ exports.appRelativePath = appRelativePath2;
69
+ function hasBasename(value, base) {
70
+ return value === base || value.startsWith(base + "/") || value.startsWith(base + "?") || value.startsWith(base + "#");
71
+ }
9
72
  }
10
- if (typeof window === "undefined") {
11
- return "";
73
+ });
74
+
75
+ // node_modules/@webtypen/webframez-core/routing.js
76
+ var require_routing2 = __commonJS({
77
+ "node_modules/@webtypen/webframez-core/routing.js"(exports, module) {
78
+ module.exports = require_routing();
12
79
  }
13
- const value = window.__RSC_BASENAME;
14
- return value && value !== "/" ? value : "";
15
- }
80
+ });
81
+
82
+ // src/navigation.tsx
83
+ import React from "react";
84
+
85
+ // src/paths.ts
86
+ var import_routing = __toESM(require_routing2(), 1);
87
+
88
+ // src/navigation.tsx
89
+ import { jsx } from "react/jsx-runtime";
16
90
  function getClientRouter() {
17
91
  if (typeof window === "undefined") {
18
92
  return null;
@@ -74,13 +148,14 @@ function resolveHref(to, basename) {
74
148
  const hash = hashPart ? `#${hashPart}` : "";
75
149
  return `${resolvedPath}${query}${hash}`;
76
150
  }
77
- function Link({ to, basename, onClick, ...rest }) {
78
- const resolvedHref = resolveHref(to, basename ?? getDefaultBasename());
151
+ var Link = React.forwardRef(function Link2({ to, basename, onClick, ...rest }, ref) {
152
+ const resolvedHref = resolveHref(to, basename ?? (0, import_routing.getBasename)());
79
153
  const isServerRender = typeof window === "undefined";
80
154
  return /* @__PURE__ */ jsx(
81
155
  "a",
82
156
  {
83
157
  ...rest,
158
+ ref,
84
159
  href: resolvedHref,
85
160
  onClick: isServerRender ? void 0 : (event) => {
86
161
  onClick?.(event);
@@ -90,6 +165,8 @@ function Link({ to, basename, onClick, ...rest }) {
90
165
  if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
91
166
  return;
92
167
  }
168
+ if (rest.download != null && rest.download !== false)
169
+ return;
93
170
  if (rest.target && rest.target !== "_self") {
94
171
  return;
95
172
  }
@@ -101,9 +178,9 @@ function Link({ to, basename, onClick, ...rest }) {
101
178
  }
102
179
  }
103
180
  );
104
- }
181
+ });
105
182
  function Redirect({ to, basename, replace = true }) {
106
- const resolvedHref = resolveHref(to, basename ?? getDefaultBasename());
183
+ const resolvedHref = resolveHref(to, basename ?? (0, import_routing.getBasename)());
107
184
  if (typeof window !== "undefined") {
108
185
  const currentHref = `${window.location.pathname}${window.location.search}${window.location.hash}`;
109
186
  if (resolvedHref !== currentHref) {
package/dist/paths.cjs ADDED
@@ -0,0 +1,102 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // node_modules/@webtypen/webframez-core/dist/routing.js
33
+ var require_routing = __commonJS({
34
+ "node_modules/@webtypen/webframez-core/dist/routing.js"(exports2) {
35
+ "use strict";
36
+ Object.defineProperty(exports2, "__esModule", { value: true });
37
+ exports2.appRelativePath = exports2.appPath = exports2.getBasename = exports2.normalizeBasename = void 0;
38
+ function normalizeBasename2(value) {
39
+ if (value == null || value === "" || value === "/")
40
+ return "";
41
+ if (typeof value !== "string")
42
+ throw new Error("Router basename must be a string.");
43
+ const base = value.trim().replace(/\/+$/, "");
44
+ if (!base && value.trim().length <= 1)
45
+ return "";
46
+ if (!/^\/(?:[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)(?:\/[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)*$/.test(base)) {
47
+ throw new Error("Router basename must be empty or an absolute path such as /my-app.");
48
+ }
49
+ return base;
50
+ }
51
+ exports2.normalizeBasename = normalizeBasename2;
52
+ function getBasename2() {
53
+ var _a, _b, _c, _d;
54
+ const runtime = globalThis;
55
+ return (_d = (_c = (_b = (_a = runtime.__WEBFRAMEZ_ROUTING_CONTEXT__) === null || _a === void 0 ? void 0 : _a.getStore()) !== null && _b !== void 0 ? _b : runtime.__RSC_BASENAME) !== null && _c !== void 0 ? _c : runtime.__WEBFRAMEZ_ROUTER_BASENAME__) !== null && _d !== void 0 ? _d : "";
56
+ }
57
+ exports2.getBasename = getBasename2;
58
+ function appPath2(value, basename = getBasename2()) {
59
+ const base = normalizeBasename2(basename);
60
+ if (!base || !value.startsWith("/") || value.startsWith("//") || hasBasename(value, base))
61
+ return value;
62
+ return base + value;
63
+ }
64
+ exports2.appPath = appPath2;
65
+ function appRelativePath2(value, basename = getBasename2()) {
66
+ const base = normalizeBasename2(basename);
67
+ if (!base || !hasBasename(value, base))
68
+ return value;
69
+ const relative = value.slice(base.length);
70
+ return !relative || relative.startsWith("?") || relative.startsWith("#") ? "/" + relative : relative;
71
+ }
72
+ exports2.appRelativePath = appRelativePath2;
73
+ function hasBasename(value, base) {
74
+ return value === base || value.startsWith(base + "/") || value.startsWith(base + "?") || value.startsWith(base + "#");
75
+ }
76
+ }
77
+ });
78
+
79
+ // node_modules/@webtypen/webframez-core/routing.js
80
+ var require_routing2 = __commonJS({
81
+ "node_modules/@webtypen/webframez-core/routing.js"(exports2, module2) {
82
+ module2.exports = require_routing();
83
+ }
84
+ });
85
+
86
+ // src/paths.ts
87
+ var paths_exports = {};
88
+ __export(paths_exports, {
89
+ appPath: () => import_routing.appPath,
90
+ appRelativePath: () => import_routing.appRelativePath,
91
+ getBasename: () => import_routing.getBasename,
92
+ normalizeBasename: () => import_routing.normalizeBasename
93
+ });
94
+ module.exports = __toCommonJS(paths_exports);
95
+ var import_routing = __toESM(require_routing2(), 1);
96
+ // Annotate the CommonJS export names for ESM import in node:
97
+ 0 && (module.exports = {
98
+ appPath,
99
+ appRelativePath,
100
+ getBasename,
101
+ normalizeBasename
102
+ });
@@ -0,0 +1,4 @@
1
+ export function normalizeBasename(value?: string | null): string;
2
+ export function getBasename(): string;
3
+ export function appPath(value: string, basename?: string): string;
4
+ export function appRelativePath(value: string, basename?: string): string;
package/dist/paths.js ADDED
@@ -0,0 +1,92 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // node_modules/@webtypen/webframez-core/dist/routing.js
28
+ var require_routing = __commonJS({
29
+ "node_modules/@webtypen/webframez-core/dist/routing.js"(exports) {
30
+ "use strict";
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.appRelativePath = exports.appPath = exports.getBasename = exports.normalizeBasename = void 0;
33
+ function normalizeBasename2(value) {
34
+ if (value == null || value === "" || value === "/")
35
+ return "";
36
+ if (typeof value !== "string")
37
+ throw new Error("Router basename must be a string.");
38
+ const base = value.trim().replace(/\/+$/, "");
39
+ if (!base && value.trim().length <= 1)
40
+ return "";
41
+ if (!/^\/(?:[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)(?:\/[A-Za-z0-9_~-]+(?:\.[A-Za-z0-9_~-]+)*)*$/.test(base)) {
42
+ throw new Error("Router basename must be empty or an absolute path such as /my-app.");
43
+ }
44
+ return base;
45
+ }
46
+ exports.normalizeBasename = normalizeBasename2;
47
+ function getBasename2() {
48
+ var _a, _b, _c, _d;
49
+ const runtime = globalThis;
50
+ return (_d = (_c = (_b = (_a = runtime.__WEBFRAMEZ_ROUTING_CONTEXT__) === null || _a === void 0 ? void 0 : _a.getStore()) !== null && _b !== void 0 ? _b : runtime.__RSC_BASENAME) !== null && _c !== void 0 ? _c : runtime.__WEBFRAMEZ_ROUTER_BASENAME__) !== null && _d !== void 0 ? _d : "";
51
+ }
52
+ exports.getBasename = getBasename2;
53
+ function appPath2(value, basename = getBasename2()) {
54
+ const base = normalizeBasename2(basename);
55
+ if (!base || !value.startsWith("/") || value.startsWith("//") || hasBasename(value, base))
56
+ return value;
57
+ return base + value;
58
+ }
59
+ exports.appPath = appPath2;
60
+ function appRelativePath2(value, basename = getBasename2()) {
61
+ const base = normalizeBasename2(basename);
62
+ if (!base || !hasBasename(value, base))
63
+ return value;
64
+ const relative = value.slice(base.length);
65
+ return !relative || relative.startsWith("?") || relative.startsWith("#") ? "/" + relative : relative;
66
+ }
67
+ exports.appRelativePath = appRelativePath2;
68
+ function hasBasename(value, base) {
69
+ return value === base || value.startsWith(base + "/") || value.startsWith(base + "?") || value.startsWith(base + "#");
70
+ }
71
+ }
72
+ });
73
+
74
+ // node_modules/@webtypen/webframez-core/routing.js
75
+ var require_routing2 = __commonJS({
76
+ "node_modules/@webtypen/webframez-core/routing.js"(exports, module) {
77
+ module.exports = require_routing();
78
+ }
79
+ });
80
+
81
+ // src/paths.ts
82
+ var import_routing = __toESM(require_routing2(), 1);
83
+ var export_appPath = import_routing.appPath;
84
+ var export_appRelativePath = import_routing.appRelativePath;
85
+ var export_getBasename = import_routing.getBasename;
86
+ var export_normalizeBasename = import_routing.normalizeBasename;
87
+ export {
88
+ export_appPath as appPath,
89
+ export_appRelativePath as appRelativePath,
90
+ export_getBasename as getBasename,
91
+ export_normalizeBasename as normalizeBasename
92
+ };
package/dist/router.cjs CHANGED
@@ -103,6 +103,12 @@ function normalizeHeadConfig(head, inheritedBasename) {
103
103
  href: resolveHeadAssetUrl(link.href, effectiveBasename)
104
104
  }));
105
105
  }
106
+ if (normalizedHead.scripts) {
107
+ normalizedHead.scripts = normalizedHead.scripts.map((script) => ({
108
+ ...script,
109
+ ...script.src ? { src: resolveHeadAssetUrl(script.src, effectiveBasename) } : {}
110
+ }));
111
+ }
106
112
  return normalizedHead;
107
113
  }
108
114
 
@@ -215,8 +221,7 @@ var FORCED_PACKAGE_REQUESTS = [
215
221
  "react-server-dom-webpack",
216
222
  "react-server-dom-webpack/server",
217
223
  "react-server-dom-webpack/client",
218
- "react-server-dom-webpack/client.node",
219
- "scheduler"
224
+ "react-server-dom-webpack/client.node"
220
225
  ];
221
226
  var forcedPackageResolutionInstalled = false;
222
227
  function normalizePathname(pathname) {
@@ -355,7 +360,9 @@ function matchRoute(entry, pathname) {
355
360
  function mergeHead(...configs) {
356
361
  const merged = {
357
362
  meta: [],
358
- links: []
363
+ links: [],
364
+ scripts: [],
365
+ html: []
359
366
  };
360
367
  for (const candidate of configs) {
361
368
  const config = normalizeHeadConfig(candidate, merged.basename);
@@ -390,9 +397,28 @@ function mergeHead(...configs) {
390
397
  if (config.links) {
391
398
  merged.links?.push(...config.links);
392
399
  }
400
+ if (config.scripts) {
401
+ merged.scripts?.push(...config.scripts);
402
+ }
403
+ if (config.html) {
404
+ merged.html?.push(...Array.isArray(config.html) ? config.html : [config.html]);
405
+ }
406
+ if (config.bodyStartHtml) {
407
+ merged.bodyStartHtml = [merged.bodyStartHtml, config.bodyStartHtml].filter(Boolean).join("\n");
408
+ }
409
+ if (config.bodyEndHtml) {
410
+ merged.bodyEndHtml = [merged.bodyEndHtml, config.bodyEndHtml].filter(Boolean).join("\n");
411
+ }
393
412
  }
394
413
  return merged;
395
414
  }
415
+ function renderGenericAttributes(entry, excluded = []) {
416
+ return Object.entries(entry).filter(
417
+ ([key, value]) => !excluded.includes(key) && value !== void 0 && value !== null && value !== false
418
+ ).map(
419
+ ([key, value]) => value === true ? key : `${key}="${escapeHtml(String(value))}"`
420
+ ).join(" ");
421
+ }
396
422
  function renderHeadToString(head) {
397
423
  const normalizedHead = normalizeHeadConfig(head) ?? head;
398
424
  const tags = [];
@@ -414,6 +440,23 @@ function renderHeadToString(head) {
414
440
  const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
415
441
  tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
416
442
  }
443
+ for (const script of normalizedHead.scripts ?? []) {
444
+ if (script.html) {
445
+ tags.push(script.html);
446
+ continue;
447
+ }
448
+ const attrs = renderGenericAttributes(script, [
449
+ "content",
450
+ "html"
451
+ ]);
452
+ const content = script.content ? String(script.content) : "";
453
+ tags.push(`<script ${createManagedAttributes()} ${attrs}>${content}</script>`);
454
+ }
455
+ for (const html of normalizedHead.html ?? []) {
456
+ if (typeof html === "string" && html.trim() !== "") {
457
+ tags.push(html);
458
+ }
459
+ }
417
460
  return tags.join("\n");
418
461
  }
419
462
  function clearModuleCache(modulePath, rootDir, visited = /* @__PURE__ */ new Set()) {
@@ -499,6 +542,7 @@ function isRouteAbort(value) {
499
542
  function createFileRouter(options) {
500
543
  installForcedPackageResolution();
501
544
  const pagesDir = options.pagesDir;
545
+ const onData = options.onData;
502
546
  const layoutPath = import_node_path.default.join(pagesDir, "layout.js");
503
547
  const errorPath = import_node_path.default.join(pagesDir, "errors.js");
504
548
  const middlewaresPath = import_node_path.default.join(pagesDir, "middlewares.js");
@@ -663,10 +707,16 @@ function createFileRouter(options) {
663
707
  data: mergeRouteData(middlewareContext.data, pageData)
664
708
  };
665
709
  activeContext = pageContext;
666
- const pageNode = await pageModule.default(pageContext);
667
- const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
668
- const pageHead = await resolveHead(pageModule, pageContext);
669
- const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
710
+ const onDataResult = typeof onData === "function" ? await onData(pageContext) : void 0;
711
+ const eventContext = {
712
+ ...pageContext,
713
+ data: mergeRouteData(pageContext.data, onDataResult)
714
+ };
715
+ activeContext = eventContext;
716
+ const pageNode = await pageModule.default(eventContext);
717
+ const layoutHead = layoutModule ? await resolveHead(layoutModule, eventContext) : void 0;
718
+ const pageHead = await resolveHead(pageModule, eventContext);
719
+ const layoutNode = layoutModule ? await layoutModule.default(eventContext) : null;
670
720
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
671
721
  const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteChildren, {})) : void 0;
672
722
  return {
@@ -675,7 +725,7 @@ function createFileRouter(options) {
675
725
  contextModel,
676
726
  pageModel: pageNode,
677
727
  head: mergeHead(layoutHead, pageHead),
678
- context: pageContext
728
+ context: eventContext
679
729
  };
680
730
  } catch (error) {
681
731
  if (isRouteAbort(error)) {
package/dist/router.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import type { ReactNode } from "react";
2
- import type { HeadConfig, RouteContext, RouteRequestContext, RouteSearchParams } from "./types";
2
+ import type {
3
+ HeadConfig,
4
+ RouteContext,
5
+ RouteDataHook,
6
+ RouteRequestContext,
7
+ RouteSearchParams,
8
+ } from "./types";
3
9
 
4
10
  export type ResolvedRoute = {
5
11
  statusCode: number;
@@ -10,7 +16,7 @@ export type ResolvedRoute = {
10
16
  pageModel?: ReactNode;
11
17
  };
12
18
 
13
- export function createFileRouter(options: { pagesDir: string }): {
19
+ export function createFileRouter(options: { pagesDir: string; onData?: RouteDataHook }): {
14
20
  resolve(input: {
15
21
  pathname: string;
16
22
  searchParams: RouteSearchParams;
package/dist/router.js CHANGED
@@ -73,6 +73,12 @@ function normalizeHeadConfig(head, inheritedBasename) {
73
73
  href: resolveHeadAssetUrl(link.href, effectiveBasename)
74
74
  }));
75
75
  }
76
+ if (normalizedHead.scripts) {
77
+ normalizedHead.scripts = normalizedHead.scripts.map((script) => ({
78
+ ...script,
79
+ ...script.src ? { src: resolveHeadAssetUrl(script.src, effectiveBasename) } : {}
80
+ }));
81
+ }
76
82
  return normalizedHead;
77
83
  }
78
84
 
@@ -185,8 +191,7 @@ var FORCED_PACKAGE_REQUESTS = [
185
191
  "react-server-dom-webpack",
186
192
  "react-server-dom-webpack/server",
187
193
  "react-server-dom-webpack/client",
188
- "react-server-dom-webpack/client.node",
189
- "scheduler"
194
+ "react-server-dom-webpack/client.node"
190
195
  ];
191
196
  var forcedPackageResolutionInstalled = false;
192
197
  function normalizePathname(pathname) {
@@ -325,7 +330,9 @@ function matchRoute(entry, pathname) {
325
330
  function mergeHead(...configs) {
326
331
  const merged = {
327
332
  meta: [],
328
- links: []
333
+ links: [],
334
+ scripts: [],
335
+ html: []
329
336
  };
330
337
  for (const candidate of configs) {
331
338
  const config = normalizeHeadConfig(candidate, merged.basename);
@@ -360,9 +367,28 @@ function mergeHead(...configs) {
360
367
  if (config.links) {
361
368
  merged.links?.push(...config.links);
362
369
  }
370
+ if (config.scripts) {
371
+ merged.scripts?.push(...config.scripts);
372
+ }
373
+ if (config.html) {
374
+ merged.html?.push(...Array.isArray(config.html) ? config.html : [config.html]);
375
+ }
376
+ if (config.bodyStartHtml) {
377
+ merged.bodyStartHtml = [merged.bodyStartHtml, config.bodyStartHtml].filter(Boolean).join("\n");
378
+ }
379
+ if (config.bodyEndHtml) {
380
+ merged.bodyEndHtml = [merged.bodyEndHtml, config.bodyEndHtml].filter(Boolean).join("\n");
381
+ }
363
382
  }
364
383
  return merged;
365
384
  }
385
+ function renderGenericAttributes(entry, excluded = []) {
386
+ return Object.entries(entry).filter(
387
+ ([key, value]) => !excluded.includes(key) && value !== void 0 && value !== null && value !== false
388
+ ).map(
389
+ ([key, value]) => value === true ? key : `${key}="${escapeHtml(String(value))}"`
390
+ ).join(" ");
391
+ }
366
392
  function renderHeadToString(head) {
367
393
  const normalizedHead = normalizeHeadConfig(head) ?? head;
368
394
  const tags = [];
@@ -384,6 +410,23 @@ function renderHeadToString(head) {
384
410
  const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
385
411
  tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
386
412
  }
413
+ for (const script of normalizedHead.scripts ?? []) {
414
+ if (script.html) {
415
+ tags.push(script.html);
416
+ continue;
417
+ }
418
+ const attrs = renderGenericAttributes(script, [
419
+ "content",
420
+ "html"
421
+ ]);
422
+ const content = script.content ? String(script.content) : "";
423
+ tags.push(`<script ${createManagedAttributes()} ${attrs}>${content}</script>`);
424
+ }
425
+ for (const html of normalizedHead.html ?? []) {
426
+ if (typeof html === "string" && html.trim() !== "") {
427
+ tags.push(html);
428
+ }
429
+ }
387
430
  return tags.join("\n");
388
431
  }
389
432
  function clearModuleCache(modulePath, rootDir, visited = /* @__PURE__ */ new Set()) {
@@ -469,6 +512,7 @@ function isRouteAbort(value) {
469
512
  function createFileRouter(options) {
470
513
  installForcedPackageResolution();
471
514
  const pagesDir = options.pagesDir;
515
+ const onData = options.onData;
472
516
  const layoutPath = path.join(pagesDir, "layout.js");
473
517
  const errorPath = path.join(pagesDir, "errors.js");
474
518
  const middlewaresPath = path.join(pagesDir, "middlewares.js");
@@ -633,10 +677,16 @@ function createFileRouter(options) {
633
677
  data: mergeRouteData(middlewareContext.data, pageData)
634
678
  };
635
679
  activeContext = pageContext;
636
- const pageNode = await pageModule.default(pageContext);
637
- const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
638
- const pageHead = await resolveHead(pageModule, pageContext);
639
- const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
680
+ const onDataResult = typeof onData === "function" ? await onData(pageContext) : void 0;
681
+ const eventContext = {
682
+ ...pageContext,
683
+ data: mergeRouteData(pageContext.data, onDataResult)
684
+ };
685
+ activeContext = eventContext;
686
+ const pageNode = await pageModule.default(eventContext);
687
+ const layoutHead = layoutModule ? await resolveHead(layoutModule, eventContext) : void 0;
688
+ const pageHead = await resolveHead(pageModule, eventContext);
689
+ const layoutNode = layoutModule ? await layoutModule.default(eventContext) : null;
640
690
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
641
691
  const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildren, {})) : void 0;
642
692
  return {
@@ -645,7 +695,7 @@ function createFileRouter(options) {
645
695
  contextModel,
646
696
  pageModel: pageNode,
647
697
  head: mergeHead(layoutHead, pageHead),
648
- context: pageContext
698
+ context: eventContext
649
699
  };
650
700
  } catch (error) {
651
701
  if (isRouteAbort(error)) {
package/dist/types.d.ts CHANGED
@@ -57,6 +57,19 @@ export type HeadLinkTag = {
57
57
  media?: string;
58
58
  };
59
59
 
60
+ export type HeadScriptTag = {
61
+ id?: string;
62
+ src?: string;
63
+ type?: string;
64
+ async?: boolean;
65
+ defer?: boolean;
66
+ content?: string;
67
+ html?: string;
68
+ integrity?: string;
69
+ crossOrigin?: string;
70
+ referrerPolicy?: string;
71
+ };
72
+
60
73
  export type HeadConfig = {
61
74
  title?: string;
62
75
  description?: string;
@@ -67,6 +80,10 @@ export type HeadConfig = {
67
80
  favicon?: string;
68
81
  meta?: HeadMetaTag[];
69
82
  links?: HeadLinkTag[];
83
+ scripts?: HeadScriptTag[];
84
+ html?: string[];
85
+ bodyStartHtml?: string;
86
+ bodyEndHtml?: string;
70
87
  };
71
88
 
72
89
  export type ClientNavigationPayload = {
@@ -84,6 +101,11 @@ export type PageDataResolver<TData = any> = (
84
101
  context: RouteContext
85
102
  ) => TData | Promise<TData>;
86
103
 
104
+ export type RouteDataHookResult = Record<string, unknown> | undefined | void;
105
+ export type RouteDataHook<TData = any> = (
106
+ context: RouteContext<TData>
107
+ ) => RouteDataHookResult | Promise<RouteDataHookResult>;
108
+
87
109
  export type RouteMiddlewareResult = Record<string, unknown> | undefined | void;
88
110
  export type RouteMiddlewareResolver<TData = any> = (
89
111
  context: RouteContext<TData>
@@ -115,6 +137,8 @@ export type CreateHtmlShellOptions = {
115
137
  buildId?: string;
116
138
  headTags?: string;
117
139
  bodyClassName?: string;
140
+ bodyStartHtml?: string;
141
+ bodyEndHtml?: string;
118
142
  rootHtml?: string;
119
143
  initialFlightData?: string;
120
144
  basename?: string;