veryfront 0.1.993 → 0.1.994
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/esm/deno.js +1 -1
- package/esm/src/html/html-injection.d.ts +7 -0
- package/esm/src/html/html-injection.d.ts.map +1 -1
- package/esm/src/html/html-injection.js +7 -1
- package/esm/src/html/hydration-script-builder/templates/renderer.d.ts.map +1 -1
- package/esm/src/html/hydration-script-builder/templates/renderer.js +6 -2
- package/esm/src/html/hydration-script-builder/templates/router.d.ts.map +1 -1
- package/esm/src/html/hydration-script-builder/templates/router.js +49 -8
- package/esm/src/rendering/layouts/layout-applicator.d.ts.map +1 -1
- package/esm/src/rendering/layouts/layout-applicator.js +2 -5
- package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/html.js +1 -0
- package/esm/src/rendering/page-rendering.d.ts.map +1 -1
- package/esm/src/rendering/page-rendering.js +2 -5
- package/esm/src/rendering/script-page-handling.d.ts.map +1 -1
- package/esm/src/rendering/script-page-handling.js +2 -5
- package/esm/src/routing/api/context-builder.d.ts +4 -0
- package/esm/src/routing/api/context-builder.d.ts.map +1 -1
- package/esm/src/routing/api/context-builder.js +6 -5
- package/esm/src/routing/flatten-route-params.d.ts +11 -0
- package/esm/src/routing/flatten-route-params.d.ts.map +1 -0
- package/esm/src/routing/flatten-route-params.js +20 -0
- package/esm/src/routing/index.d.ts +1 -0
- package/esm/src/routing/index.d.ts.map +1 -1
- package/esm/src/routing/index.js +1 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
package/esm/deno.js
CHANGED
|
@@ -9,6 +9,13 @@ export interface InjectHTMLContentOptions {
|
|
|
9
9
|
projectDir?: string;
|
|
10
10
|
/** Whether the page has 'use client' directive */
|
|
11
11
|
isClientPage?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Route params from the initial match, seeded into the 'use client' hydration
|
|
14
|
+
* payload so full-HTML-document client pages hydrate with their params
|
|
15
|
+
* instead of an empty object (issue #2741). Catch-all arrays are preserved;
|
|
16
|
+
* the client runtime joins them (issue #2742).
|
|
17
|
+
*/
|
|
18
|
+
params?: Record<string, string | string[]>;
|
|
12
19
|
/** Whether page is embedded in Studio iframe */
|
|
13
20
|
studioEmbed?: boolean;
|
|
14
21
|
/** Project ID for Studio communication */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-injection.d.ts","sourceRoot":"","sources":["../../../src/src/html/html-injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"html-injection.d.ts","sourceRoot":"","sources":["../../../src/src/html/html-injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAmB/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAgBD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,wBAAwB,GAChC,MAAM,CA6GR"}
|
|
@@ -2,6 +2,7 @@ import { resolveRelativePath } from "../modules/react-loader/path-resolver.js";
|
|
|
2
2
|
import { determineClientModuleStrategy } from "../rendering/rsc/client-module-strategy.js";
|
|
3
3
|
import { generateLinkTags, generateMetaTags, generateScriptTags, generateStyleTags, } from "./tag-generators.js";
|
|
4
4
|
import { buildNonceAttribute } from "./html-escape.js";
|
|
5
|
+
import { jsonForInlineScript } from "../security/client/html-sanitizer.js";
|
|
5
6
|
import { getDevScripts, getDevStyles, getPreviewStylesheetLink, getProdScripts, getStudioScripts, } from "./dev-scripts.js";
|
|
6
7
|
function toProjectRelativePath(absolutePath, projectDir) {
|
|
7
8
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
@@ -49,10 +50,15 @@ export function injectHTMLContent(template, content, metadata, options) {
|
|
|
49
50
|
const hasBodyClose = /<\/body>/i.test(html);
|
|
50
51
|
// Inject hydration data for 'use client' pages (before scripts, so client.js can find it)
|
|
51
52
|
if (options.pagePath && options.isClientPage && hasBodyClose) {
|
|
52
|
-
|
|
53
|
+
// Serialize with jsonForInlineScript, not raw JSON.stringify: route params
|
|
54
|
+
// (and slug) are URL-derived and decoded, so a segment like `%3C/script%3E`
|
|
55
|
+
// would otherwise break out of the <script> tag (reflected XSS). This escapes
|
|
56
|
+
// `<`, `>`, `&`, and line separators, matching the main shell hydration path.
|
|
57
|
+
const hydrationData = jsonForInlineScript({
|
|
53
58
|
pagePath: toProjectRelativePath(options.pagePath, options.projectDir),
|
|
54
59
|
slug: options.slug,
|
|
55
60
|
isClientPage: true,
|
|
61
|
+
params: options.params ?? {},
|
|
56
62
|
clientModuleStrategy: determineClientModuleStrategy({
|
|
57
63
|
isLocalProject: options.isLocalProject ?? options.mode === "development",
|
|
58
64
|
environment: options.environment,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,cA4N7B,CAAC"}
|
|
@@ -112,7 +112,11 @@ export const getRendererScript = () => `
|
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
// Normalize catch-all params (arrays -> joined strings) so the hydrated
|
|
116
|
+
// props and page context match the server render. normalizeRouteParams
|
|
117
|
+
// is defined in router.ts, which loads first (issue #2742).
|
|
118
|
+
const normalizedParams = normalizeRouteParams(data.params);
|
|
119
|
+
const pageProps = { ...(data.props || {}), params: normalizedParams };
|
|
116
120
|
let tree = React.createElement(PageComponent, pageProps);
|
|
117
121
|
|
|
118
122
|
const layouts = data.layouts;
|
|
@@ -143,7 +147,7 @@ export const getRendererScript = () => `
|
|
|
143
147
|
const pageContext = {
|
|
144
148
|
slug: data.slug || '',
|
|
145
149
|
path: data.pagePath || resolvedPathname,
|
|
146
|
-
params:
|
|
150
|
+
params: normalizedParams,
|
|
147
151
|
query: Object.fromEntries(new URLSearchParams(window.location.search)),
|
|
148
152
|
frontmatter: data.frontmatter || {},
|
|
149
153
|
headings,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/router.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/router.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,cA2nC3B,CAAC"}
|
|
@@ -604,13 +604,18 @@ export const getRouterScript = () => `
|
|
|
604
604
|
window.history.pushState({ pageData, scrollY: 0 }, '', href);
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
607
|
+
// Update the shared router snapshot BEFORE rendering. RouterProvider
|
|
608
|
+
// reads router.params during render, so mutating after renderPageFromData
|
|
609
|
+
// would leave the new page's first render with the previous route's
|
|
610
|
+
// params (issue #2741). pathname/query move up for the same reason.
|
|
611
611
|
currentPath = targetPath;
|
|
612
612
|
window.__veryfrontRouter.pathname = targetPath;
|
|
613
613
|
window.__veryfrontRouter.query = Object.fromEntries(new URLSearchParams(window.location.search));
|
|
614
|
+
window.__veryfrontRouter.params = normalizeRouteParams(pageData.params);
|
|
615
|
+
|
|
616
|
+
perfStart('nav:render:' + href);
|
|
617
|
+
await renderPageFromData(pageData, targetPath);
|
|
618
|
+
perfEnd('nav:render:' + href);
|
|
614
619
|
|
|
615
620
|
if (restoreScroll) {
|
|
616
621
|
restoreScrollPosition(targetPath);
|
|
@@ -708,9 +713,15 @@ export const getRouterScript = () => `
|
|
|
708
713
|
}
|
|
709
714
|
}
|
|
710
715
|
|
|
716
|
+
// Normalize catch-all params (arrays -> joined strings) so page props and
|
|
717
|
+
// page context match the server render exactly. SSR emits joined strings
|
|
718
|
+
// via flattenRouteParams; without this the client would hand raw arrays to
|
|
719
|
+
// props and usePageContext() after navigation (issue #2742).
|
|
720
|
+
const normalizedParams = normalizeRouteParams(pageData.params);
|
|
721
|
+
|
|
711
722
|
let tree = React.createElement(PageComponent, {
|
|
712
723
|
...pageData.props,
|
|
713
|
-
params:
|
|
724
|
+
params: normalizedParams
|
|
714
725
|
});
|
|
715
726
|
|
|
716
727
|
if (pageData.layouts?.length) {
|
|
@@ -733,7 +744,7 @@ export const getRouterScript = () => `
|
|
|
733
744
|
const pageContext = {
|
|
734
745
|
slug: pageData.slug || '',
|
|
735
746
|
path: pageData.pagePath || targetPath,
|
|
736
|
-
params:
|
|
747
|
+
params: normalizedParams,
|
|
737
748
|
query: Object.fromEntries(new URLSearchParams(window.location.search)),
|
|
738
749
|
frontmatter: pageData.frontmatter || {},
|
|
739
750
|
headings: headingsArray,
|
|
@@ -951,6 +962,22 @@ export const getRouterScript = () => `
|
|
|
951
962
|
}, IDLE_PREFETCH_DELAY_MS);
|
|
952
963
|
}
|
|
953
964
|
|
|
965
|
+
// ============================================
|
|
966
|
+
// Route params normalization
|
|
967
|
+
// ============================================
|
|
968
|
+
// Catch-all segments arrive as arrays and are joined so no path info is
|
|
969
|
+
// lost, matching the server flattenRouteParams + RSC hydration normalizer.
|
|
970
|
+
function normalizeRouteParams(raw) {
|
|
971
|
+
const out = {};
|
|
972
|
+
if (!raw) return out;
|
|
973
|
+
for (const key in raw) {
|
|
974
|
+
const value = raw[key];
|
|
975
|
+
if (value === undefined) continue;
|
|
976
|
+
out[key] = Array.isArray(value) ? value.join('/') : value;
|
|
977
|
+
}
|
|
978
|
+
return out;
|
|
979
|
+
}
|
|
980
|
+
|
|
954
981
|
// ============================================
|
|
955
982
|
// Router object
|
|
956
983
|
// ============================================
|
|
@@ -974,7 +1001,17 @@ export const getRouterScript = () => `
|
|
|
974
1001
|
},
|
|
975
1002
|
pathname: window.location.pathname,
|
|
976
1003
|
query: Object.fromEntries(new URLSearchParams(window.location.search)),
|
|
977
|
-
params
|
|
1004
|
+
// Seed route params from the hydration data (issue #2741). Catch-all
|
|
1005
|
+
// segments arrive as arrays and are joined so no path info is lost.
|
|
1006
|
+
params: (function () {
|
|
1007
|
+
try {
|
|
1008
|
+
const el = document.getElementById('veryfront-hydration-data');
|
|
1009
|
+
const raw = (JSON.parse(el && el.textContent ? el.textContent : '{}') || {}).params || {};
|
|
1010
|
+
return normalizeRouteParams(raw);
|
|
1011
|
+
} catch (_) {
|
|
1012
|
+
return {};
|
|
1013
|
+
}
|
|
1014
|
+
})(),
|
|
978
1015
|
isPreview: false,
|
|
979
1016
|
isMounted: true,
|
|
980
1017
|
navigate: (path) => navigateSPA(path, true),
|
|
@@ -999,10 +1036,14 @@ export const getRouterScript = () => `
|
|
|
999
1036
|
|
|
1000
1037
|
showNavigationProgress();
|
|
1001
1038
|
try {
|
|
1002
|
-
|
|
1039
|
+
// Update the router snapshot before rendering so RouterProvider reads
|
|
1040
|
+
// this route's params, not the previous route's (issue #2741).
|
|
1003
1041
|
currentPath = path;
|
|
1004
1042
|
window.__veryfrontRouter.pathname = path;
|
|
1005
1043
|
window.__veryfrontRouter.query = Object.fromEntries(new URLSearchParams(window.location.search));
|
|
1044
|
+
window.__veryfrontRouter.params = normalizeRouteParams(e.state.pageData.params);
|
|
1045
|
+
|
|
1046
|
+
await renderPageFromData(e.state.pageData, path);
|
|
1006
1047
|
|
|
1007
1048
|
restoreScrollPosition(path);
|
|
1008
1049
|
hideNavigationProgress();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-applicator.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-applicator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"layout-applicator.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-applicator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAKzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAiBxE,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5C,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,oBAAoB,CAAC;IAClC,gBAAgB,EAAE,aAAa,CAAC;IAChC,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,MAAM,CAAC,CAAoC;IACnD,OAAO,CAAC,WAAW,CAAC,CAA0B;IAC9C,OAAO,CAAC,QAAQ,CAAC,CAAqD;IACtE,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAC,CAAyB;IACpD,OAAO,CAAC,+BAA+B,CAAC,CAGrC;gBAES,OAAO,EAAE,wBAAwB;IAiBvC,YAAY,CAChB,WAAW,EAAE,YAAY,CAAC,YAAY,EACtC,QAAQ,EAAE,UAAU,EACpB,YAAY,EAAE,SAAS,GAAG,SAAS,EACnC,aAAa,EAAE,UAAU,EAAE,EAC3B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACnD,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC;YAyFvB,gBAAgB;YAuDhB,sBAAsB;YAWtB,8BAA8B;YA4D9B,oBAAoB;YAqDpB,mBAAmB;YAuCnB,0BAA0B;CAgEzC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { dirname, join } from "../../platform/compat/path/index.js";
|
|
2
2
|
import { rendererLogger } from "../../utils/index.js";
|
|
3
|
+
import { flattenRouteParams } from "../../routing/index.js";
|
|
3
4
|
import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
4
5
|
import { SpanNames } from "../../observability/tracing/span-names.js";
|
|
5
6
|
import { resolve as resolveContract } from "../../extensions/contracts.js";
|
|
@@ -66,11 +67,7 @@ export class LayoutApplicator {
|
|
|
66
67
|
}
|
|
67
68
|
const React = await getProjectReact();
|
|
68
69
|
const headingsArray = this.headings ?? [];
|
|
69
|
-
const flatParams = this.params
|
|
70
|
-
? Object.fromEntries(Object.entries(this.params)
|
|
71
|
-
.map(([key, value]) => [key, Array.isArray(value) ? value[0] : value])
|
|
72
|
-
.filter((entry) => entry[1] !== undefined))
|
|
73
|
-
: {};
|
|
70
|
+
const flatParams = flattenRouteParams(this.params);
|
|
74
71
|
const query = this.requestUrl ? Object.fromEntries(this.requestUrl.searchParams) : {};
|
|
75
72
|
const pageContext = {
|
|
76
73
|
slug: pageInfo.entity.slug || "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AA+FlF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AA+FlF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;YAwDtB,4BAA4B;YAiB5B,wBAAwB;YAmBxB,gBAAgB;YAyBhB,kBAAkB;IAwDhC,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAoF9B;;;;OAIG;YACW,gBAAgB;CAc/B"}
|
|
@@ -163,6 +163,7 @@ export class HTMLGenerator {
|
|
|
163
163
|
pagePath,
|
|
164
164
|
projectDir: this.config.projectDir,
|
|
165
165
|
isClientPage,
|
|
166
|
+
params: context.options?.params,
|
|
166
167
|
environment: context.options?.environment,
|
|
167
168
|
isLocalProject: this.config.mode === "development",
|
|
168
169
|
nonce: context.options?.nonce,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-rendering.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/page-rendering.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"page-rendering.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/page-rendering.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,mBAAmB,CAAC;AASrG,UAAU,aAAa;IACrB,WAAW,EAAE,YAAY,CAAC,YAAY,CAAC;IACvC,UAAU,EAAE,UAAU,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;AAED,UAAU,sBAAsB;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,0BAA0B;IAClC,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAInE;AAED,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,UAAU,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IACR,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GACA,OAAO,CAAC,sBAAsB,CAAC,CA4CjC;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,aAAa,EAC/B,WAAW,EAAE,CACX,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,SAAS,CAAC,EACvB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,OAAO,CAAC,aAAa,CAAC,CAmHxB"}
|
|
@@ -3,6 +3,7 @@ import { RENDER_ERROR } from "../errors/error-registry.js";
|
|
|
3
3
|
import { mdxRenderer } from "../transforms/mdx/index.js";
|
|
4
4
|
import { clearMdxEsmCacheNamespace } from "../transforms/mdx/esm-module-loader/index.js";
|
|
5
5
|
import { getProjectReact } from "../react/index.js";
|
|
6
|
+
import { flattenRouteParams } from "../routing/index.js";
|
|
6
7
|
import { compileContent } from "../transforms/mdx/compiler/index.js";
|
|
7
8
|
import { ensureError, getErrorMessage } from "../errors/veryfront-error.js";
|
|
8
9
|
import { withSpan } from "../observability/tracing/otlp-setup.js";
|
|
@@ -77,11 +78,7 @@ export function handleMDXPage(pageInfo, slug, projectDir, mergedComponents, _com
|
|
|
77
78
|
}
|
|
78
79
|
if (typeof mod.generateMetadata === "function") {
|
|
79
80
|
try {
|
|
80
|
-
const params = options?.params
|
|
81
|
-
? Object.fromEntries(Object.entries(options.params)
|
|
82
|
-
.map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])
|
|
83
|
-
.filter((entry) => entry[1] !== undefined))
|
|
84
|
-
: {};
|
|
81
|
+
const params = flattenRouteParams(options?.params);
|
|
85
82
|
const query = options?.url ? Object.fromEntries(options.url.searchParams) : {};
|
|
86
83
|
const gen = await mod.generateMetadata({
|
|
87
84
|
params,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-page-handling.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/script-page-handling.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"script-page-handling.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/script-page-handling.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EAGV,YAAY,EAEb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAenE,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+GD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,YAAY,CAAC,CAiDvB"}
|
|
@@ -9,6 +9,7 @@ import { rewriteNpmImports } from "../transforms/npm-import-rewrites.js";
|
|
|
9
9
|
import { dirname, join } from "../platform/compat/path/index.js";
|
|
10
10
|
import { cwd } from "../platform/compat/process.js";
|
|
11
11
|
import { RENDER_ERROR } from "../errors/error-registry.js";
|
|
12
|
+
import { flattenRouteParams } from "../routing/index.js";
|
|
12
13
|
import { createError, toError } from "../errors/veryfront-error.js";
|
|
13
14
|
import { computeHash } from "./utils/index.js";
|
|
14
15
|
import { wrapInHTMLShell } from "../html/index.js";
|
|
@@ -75,11 +76,7 @@ function extractHtmlAndMetadata(output) {
|
|
|
75
76
|
}));
|
|
76
77
|
}
|
|
77
78
|
function buildPageContext(pageInfo, slug, params, url) {
|
|
78
|
-
const flatParams = params
|
|
79
|
-
? Object.fromEntries(Object.entries(params)
|
|
80
|
-
.map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])
|
|
81
|
-
.filter((entry) => entry[1] !== undefined))
|
|
82
|
-
: {};
|
|
79
|
+
const flatParams = flattenRouteParams(params);
|
|
83
80
|
return {
|
|
84
81
|
params: flatParams,
|
|
85
82
|
query: url ? Object.fromEntries(url.searchParams) : {},
|
|
@@ -16,5 +16,9 @@ export interface APIContext {
|
|
|
16
16
|
fs: FileSystemAdapter;
|
|
17
17
|
}
|
|
18
18
|
export declare function createContext(request: Request, match: RouteMatch, fs: FileSystemAdapter): APIContext;
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Use {@link flattenRouteParams} directly. Kept as a thin alias so
|
|
21
|
+
* the routing barrel exposes a single flattener implementation (issue #2742).
|
|
22
|
+
*/
|
|
19
23
|
export declare function normalizeParams(params: Record<string, string | string[]>): Record<string, string>;
|
|
20
24
|
//# sourceMappingURL=context-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC;IACvD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC;IACtD,EAAE,EAAE,iBAAiB,CAAC;CACvB;AAgBD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,iBAAiB,GACpB,UAAU,CAmBZ;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseCookies } from "../../utils/cookie-utils.js";
|
|
2
|
+
import { flattenRouteParams } from "../flatten-route-params.js";
|
|
2
3
|
export { parseCookies };
|
|
3
4
|
function createResponse(body, contentType, init) {
|
|
4
5
|
return new Response(body, {
|
|
@@ -26,10 +27,10 @@ export function createContext(request, match, fs) {
|
|
|
26
27
|
fs,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use {@link flattenRouteParams} directly. Kept as a thin alias so
|
|
32
|
+
* the routing barrel exposes a single flattener implementation (issue #2742).
|
|
33
|
+
*/
|
|
29
34
|
export function normalizeParams(params) {
|
|
30
|
-
|
|
31
|
-
for (const [key, value] of Object.entries(params)) {
|
|
32
|
-
out[key] = Array.isArray(value) ? value.join("/") : value;
|
|
33
|
-
}
|
|
34
|
-
return out;
|
|
35
|
+
return flattenRouteParams(params);
|
|
35
36
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flattens matched route params (which may be arrays for catch-all `[...slug]`
|
|
3
|
+
* segments) into the `Record<string, string>` shape the router value exposes.
|
|
4
|
+
*
|
|
5
|
+
* Catch-all segments are **joined with `/`** so no path information is lost —
|
|
6
|
+
* `/docs/guides/intro` -> `{ slug: "guides/intro" }`, not `{ slug: "guides" }`.
|
|
7
|
+
* This matches the client SPA normalizer and the RSC hydration normalizer, so
|
|
8
|
+
* server and client agree.
|
|
9
|
+
*/
|
|
10
|
+
export declare function flattenRouteParams(params?: Record<string, string | string[]>): Record<string, string>;
|
|
11
|
+
//# sourceMappingURL=flatten-route-params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flatten-route-params.d.ts","sourceRoot":"","sources":["../../../src/src/routing/flatten-route-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flattens matched route params (which may be arrays for catch-all `[...slug]`
|
|
3
|
+
* segments) into the `Record<string, string>` shape the router value exposes.
|
|
4
|
+
*
|
|
5
|
+
* Catch-all segments are **joined with `/`** so no path information is lost —
|
|
6
|
+
* `/docs/guides/intro` -> `{ slug: "guides/intro" }`, not `{ slug: "guides" }`.
|
|
7
|
+
* This matches the client SPA normalizer and the RSC hydration normalizer, so
|
|
8
|
+
* server and client agree.
|
|
9
|
+
*/
|
|
10
|
+
export function flattenRouteParams(params) {
|
|
11
|
+
if (!params)
|
|
12
|
+
return {};
|
|
13
|
+
const flat = {};
|
|
14
|
+
for (const [key, value] of Object.entries(params)) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
flat[key] = Array.isArray(value) ? value.join("/") : value;
|
|
18
|
+
}
|
|
19
|
+
return flat;
|
|
20
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module routing
|
|
6
6
|
*/
|
|
7
7
|
export type { Route, RouteMatch } from "./matchers/index.js";
|
|
8
|
+
export { flattenRouteParams } from "./flatten-route-params.js";
|
|
8
9
|
export { getSpecificityScore, matchRoute, normalizePath, PageRouteMatcher, parseRoute, } from "./matchers/index.js";
|
|
9
10
|
export type { PathCandidates, RouteParams } from "./slug-mapper/index.js";
|
|
10
11
|
export { extractParams, getPathCandidates, getSlugFromPath, getSupportedExtensions, isDynamicRoute, matchesPattern, normalizeSlug, pathToSlug, slugToPath, } from "./slug-mapper/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,GACX,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,UAAU,GACX,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,GACX,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,UAAU,GACX,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,gBAAgB,CAAC"}
|
package/esm/src/routing/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module routing
|
|
6
6
|
*/
|
|
7
|
+
export { flattenRouteParams } from "./flatten-route-params.js";
|
|
7
8
|
export { getSpecificityScore, matchRoute, normalizePath, PageRouteMatcher, parseRoute, } from "./matchers/index.js";
|
|
8
9
|
export { extractParams, getPathCandidates, getSlugFromPath, getSupportedExtensions, isDynamicRoute, matchesPattern, normalizeSlug, pathToSlug, slugToPath, } from "./slug-mapper/index.js";
|
|
9
10
|
export { extractPageDataFromScript, NavigationHandlers, PageLoader, PageTransition, ViewportPrefetch, } from "./client/index.js";
|