@rangojs/router 0.0.0-experimental.10
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/CLAUDE.md +43 -0
- package/README.md +19 -0
- package/dist/bin/rango.js +227 -0
- package/dist/vite/index.js +3039 -0
- package/package.json +171 -0
- package/skills/caching/SKILL.md +191 -0
- package/skills/debug-manifest/SKILL.md +108 -0
- package/skills/document-cache/SKILL.md +180 -0
- package/skills/fonts/SKILL.md +165 -0
- package/skills/hooks/SKILL.md +442 -0
- package/skills/intercept/SKILL.md +190 -0
- package/skills/layout/SKILL.md +213 -0
- package/skills/links/SKILL.md +180 -0
- package/skills/loader/SKILL.md +246 -0
- package/skills/middleware/SKILL.md +202 -0
- package/skills/mime-routes/SKILL.md +124 -0
- package/skills/parallel/SKILL.md +228 -0
- package/skills/prerender/SKILL.md +283 -0
- package/skills/rango/SKILL.md +54 -0
- package/skills/response-routes/SKILL.md +358 -0
- package/skills/route/SKILL.md +173 -0
- package/skills/router-setup/SKILL.md +346 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/theme/SKILL.md +78 -0
- package/skills/typesafety/SKILL.md +394 -0
- package/src/__internal.ts +175 -0
- package/src/bin/rango.ts +24 -0
- package/src/browser/event-controller.ts +876 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/link-interceptor.ts +121 -0
- package/src/browser/lru-cache.ts +69 -0
- package/src/browser/merge-segment-loaders.ts +126 -0
- package/src/browser/navigation-bridge.ts +913 -0
- package/src/browser/navigation-client.ts +165 -0
- package/src/browser/navigation-store.ts +823 -0
- package/src/browser/partial-update.ts +600 -0
- package/src/browser/react/Link.tsx +248 -0
- package/src/browser/react/NavigationProvider.tsx +346 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +53 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +120 -0
- package/src/browser/react/location-state.ts +62 -0
- package/src/browser/react/mount-context.ts +32 -0
- package/src/browser/react/use-action.ts +240 -0
- package/src/browser/react/use-client-cache.ts +56 -0
- package/src/browser/react/use-handle.ts +203 -0
- package/src/browser/react/use-href.tsx +40 -0
- package/src/browser/react/use-link-status.ts +134 -0
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +140 -0
- package/src/browser/react/use-segments.ts +188 -0
- package/src/browser/request-controller.ts +164 -0
- package/src/browser/rsc-router.tsx +352 -0
- package/src/browser/scroll-restoration.ts +324 -0
- package/src/browser/segment-structure-assert.ts +67 -0
- package/src/browser/server-action-bridge.ts +762 -0
- package/src/browser/shallow.ts +35 -0
- package/src/browser/types.ts +478 -0
- package/src/build/generate-manifest.ts +377 -0
- package/src/build/generate-route-types.ts +828 -0
- package/src/build/index.ts +36 -0
- package/src/build/route-trie.ts +239 -0
- package/src/cache/cache-scope.ts +563 -0
- package/src/cache/cf/cf-cache-store.ts +428 -0
- package/src/cache/cf/index.ts +19 -0
- package/src/cache/document-cache.ts +340 -0
- package/src/cache/index.ts +58 -0
- package/src/cache/memory-segment-store.ts +150 -0
- package/src/cache/memory-store.ts +253 -0
- package/src/cache/types.ts +392 -0
- package/src/client.rsc.tsx +83 -0
- package/src/client.tsx +643 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +23 -0
- package/src/debug.ts +233 -0
- package/src/default-error-boundary.tsx +88 -0
- package/src/deps/browser.ts +8 -0
- package/src/deps/html-stream-client.ts +2 -0
- package/src/deps/html-stream-server.ts +2 -0
- package/src/deps/rsc.ts +10 -0
- package/src/deps/ssr.ts +2 -0
- package/src/errors.ts +295 -0
- package/src/handle.ts +130 -0
- package/src/handles/MetaTags.tsx +193 -0
- package/src/handles/index.ts +6 -0
- package/src/handles/meta.ts +247 -0
- package/src/host/cookie-handler.ts +159 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +56 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +330 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +138 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +202 -0
- package/src/href-context.ts +33 -0
- package/src/index.rsc.ts +121 -0
- package/src/index.ts +165 -0
- package/src/loader.rsc.ts +207 -0
- package/src/loader.ts +47 -0
- package/src/network-error-thrower.tsx +21 -0
- package/src/outlet-context.ts +15 -0
- package/src/prerender/param-hash.ts +35 -0
- package/src/prerender/store.ts +40 -0
- package/src/prerender.ts +156 -0
- package/src/reverse.ts +267 -0
- package/src/root-error-boundary.tsx +277 -0
- package/src/route-content-wrapper.tsx +193 -0
- package/src/route-definition.ts +1431 -0
- package/src/route-map-builder.ts +242 -0
- package/src/route-types.ts +220 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/handler-context.ts +158 -0
- package/src/router/intercept-resolution.ts +387 -0
- package/src/router/loader-resolution.ts +327 -0
- package/src/router/manifest.ts +216 -0
- package/src/router/match-api.ts +621 -0
- package/src/router/match-context.ts +264 -0
- package/src/router/match-middleware/background-revalidation.ts +236 -0
- package/src/router/match-middleware/cache-lookup.ts +382 -0
- package/src/router/match-middleware/cache-store.ts +276 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +281 -0
- package/src/router/match-middleware/segment-resolution.ts +184 -0
- package/src/router/match-pipelines.ts +214 -0
- package/src/router/match-result.ts +213 -0
- package/src/router/metrics.ts +62 -0
- package/src/router/middleware.ts +791 -0
- package/src/router/pattern-matching.ts +407 -0
- package/src/router/revalidation.ts +190 -0
- package/src/router/router-context.ts +301 -0
- package/src/router/segment-resolution.ts +1315 -0
- package/src/router/trie-matching.ts +172 -0
- package/src/router/types.ts +163 -0
- package/src/router.gen.ts +6 -0
- package/src/router.ts +2423 -0
- package/src/rsc/handler.ts +1443 -0
- package/src/rsc/helpers.ts +64 -0
- package/src/rsc/index.ts +56 -0
- package/src/rsc/nonce.ts +18 -0
- package/src/rsc/types.ts +236 -0
- package/src/segment-system.tsx +442 -0
- package/src/server/context.ts +466 -0
- package/src/server/handle-store.ts +229 -0
- package/src/server/loader-registry.ts +174 -0
- package/src/server/request-context.ts +554 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +171 -0
- package/src/ssr/index.tsx +296 -0
- package/src/theme/ThemeProvider.tsx +291 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/constants.ts +59 -0
- package/src/theme/index.ts +58 -0
- package/src/theme/theme-context.ts +70 -0
- package/src/theme/theme-script.ts +152 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- package/src/types.ts +1757 -0
- package/src/urls.gen.ts +8 -0
- package/src/urls.ts +1282 -0
- package/src/use-loader.tsx +346 -0
- package/src/vite/expose-action-id.ts +344 -0
- package/src/vite/expose-handle-id.ts +209 -0
- package/src/vite/expose-loader-id.ts +426 -0
- package/src/vite/expose-location-state-id.ts +177 -0
- package/src/vite/expose-prerender-handler-id.ts +429 -0
- package/src/vite/index.ts +2068 -0
- package/src/vite/package-resolution.ts +125 -0
- package/src/vite/version.d.ts +12 -0
- package/src/vite/virtual-entries.ts +114 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Trie Matching
|
|
3
|
+
*
|
|
4
|
+
* Walks the pre-built trie by path segments in O(path_length) time.
|
|
5
|
+
* Falls back to null when no match is found (caller uses regex fallback).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TrieNode, TrieLeaf } from "../build/route-trie.js";
|
|
9
|
+
|
|
10
|
+
export interface TrieMatchResult {
|
|
11
|
+
/** Route name */
|
|
12
|
+
routeKey: string;
|
|
13
|
+
/** Static prefix of the matched entry */
|
|
14
|
+
sp: string;
|
|
15
|
+
/** Matched route params */
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
/** Optional param names (absent params have empty string value) */
|
|
18
|
+
optionalParams?: string[];
|
|
19
|
+
/** Ancestry shortCodes for layout pruning */
|
|
20
|
+
ancestry: string[];
|
|
21
|
+
/** Redirect target if trailing slash requires it */
|
|
22
|
+
redirectTo?: string;
|
|
23
|
+
/** Route has pre-rendered data available */
|
|
24
|
+
pr?: true;
|
|
25
|
+
/** Passthrough: handler kept for live fallback on unknown params */
|
|
26
|
+
pt?: true;
|
|
27
|
+
/** Response type for non-RSC routes (json, text, image, any) */
|
|
28
|
+
responseType?: string;
|
|
29
|
+
/** Negotiate variants: response-type routes sharing this path */
|
|
30
|
+
negotiateVariants?: Array<{ routeKey: string; responseType: string }>;
|
|
31
|
+
/** RSC-first: RSC route was defined before response-type variants */
|
|
32
|
+
rscFirst?: true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Try to match a pathname against the trie.
|
|
37
|
+
* Returns null if no match found (caller should fall back to regex).
|
|
38
|
+
*/
|
|
39
|
+
export function tryTrieMatch(
|
|
40
|
+
trie: TrieNode | null,
|
|
41
|
+
pathname: string,
|
|
42
|
+
): TrieMatchResult | null {
|
|
43
|
+
if (!trie) return null;
|
|
44
|
+
|
|
45
|
+
// Split pathname into segments, filtering empty strings from leading/trailing slashes
|
|
46
|
+
const pathnameHasTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
|
|
47
|
+
const normalizedPath = pathnameHasTrailingSlash ? pathname.slice(0, -1) : pathname;
|
|
48
|
+
|
|
49
|
+
// Handle root path
|
|
50
|
+
if (normalizedPath === "" || normalizedPath === "/") {
|
|
51
|
+
if (trie.r) {
|
|
52
|
+
return validateAndBuild(trie.r, {}, pathname, pathnameHasTrailingSlash);
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Remove leading slash and split
|
|
58
|
+
const segments = normalizedPath.slice(1).split("/");
|
|
59
|
+
|
|
60
|
+
// Try exact match with normalized path (no trailing slash)
|
|
61
|
+
const result = walkTrie(trie, segments, 0, {});
|
|
62
|
+
if (result) {
|
|
63
|
+
return validateAndBuild(result.leaf, result.params, pathname, pathnameHasTrailingSlash);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface WalkResult {
|
|
70
|
+
leaf: TrieLeaf;
|
|
71
|
+
params: Record<string, string>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Walk the trie by segments with priority: static > param > wildcard.
|
|
76
|
+
* Uses backtracking to try all possible matches.
|
|
77
|
+
*/
|
|
78
|
+
function walkTrie(
|
|
79
|
+
node: TrieNode,
|
|
80
|
+
segments: string[],
|
|
81
|
+
index: number,
|
|
82
|
+
params: Record<string, string>,
|
|
83
|
+
): WalkResult | null {
|
|
84
|
+
// All segments consumed: check for terminal
|
|
85
|
+
if (index === segments.length) {
|
|
86
|
+
if (node.r) {
|
|
87
|
+
return { leaf: node.r, params };
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const segment = segments[index];
|
|
93
|
+
|
|
94
|
+
// Priority 1: Static match
|
|
95
|
+
if (node.s?.[segment]) {
|
|
96
|
+
const result = walkTrie(node.s[segment], segments, index + 1, params);
|
|
97
|
+
if (result) return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Priority 2: Param match
|
|
101
|
+
if (node.p) {
|
|
102
|
+
const result = walkTrie(node.p.c, segments, index + 1, {
|
|
103
|
+
...params,
|
|
104
|
+
[node.p.n]: segment,
|
|
105
|
+
});
|
|
106
|
+
if (result) return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Priority 3: Wildcard match (consumes rest)
|
|
110
|
+
if (node.w) {
|
|
111
|
+
const rest = segments.slice(index).join("/");
|
|
112
|
+
return {
|
|
113
|
+
leaf: node.w,
|
|
114
|
+
params: { ...params, [node.w.pn]: rest },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Post-match: validate constraints and handle trailing slash logic.
|
|
123
|
+
*/
|
|
124
|
+
function validateAndBuild(
|
|
125
|
+
leaf: TrieLeaf,
|
|
126
|
+
params: Record<string, string>,
|
|
127
|
+
originalPathname: string,
|
|
128
|
+
pathnameHasTrailingSlash: boolean,
|
|
129
|
+
): TrieMatchResult | null {
|
|
130
|
+
// Validate constraints
|
|
131
|
+
if (leaf.cv) {
|
|
132
|
+
for (const [paramName, allowed] of Object.entries(leaf.cv)) {
|
|
133
|
+
const value = params[paramName];
|
|
134
|
+
if (value !== undefined && value !== "" && !allowed.includes(value)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Fill in empty strings for optional params that weren't matched
|
|
141
|
+
if (leaf.op) {
|
|
142
|
+
for (const name of leaf.op) {
|
|
143
|
+
if (!(name in params)) {
|
|
144
|
+
params[name] = "";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Trailing slash handling
|
|
150
|
+
const tsMode = leaf.ts as "never" | "always" | "ignore" | undefined;
|
|
151
|
+
let redirectTo: string | undefined;
|
|
152
|
+
|
|
153
|
+
if (tsMode === "always" && !pathnameHasTrailingSlash && originalPathname !== "/") {
|
|
154
|
+
redirectTo = originalPathname + "/";
|
|
155
|
+
} else if (tsMode === "never" && pathnameHasTrailingSlash) {
|
|
156
|
+
redirectTo = originalPathname.slice(0, -1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
routeKey: leaf.n,
|
|
161
|
+
sp: leaf.sp,
|
|
162
|
+
params,
|
|
163
|
+
optionalParams: leaf.op,
|
|
164
|
+
ancestry: leaf.a,
|
|
165
|
+
...(redirectTo ? { redirectTo } : {}),
|
|
166
|
+
...(leaf.pr ? { pr: true } : {}),
|
|
167
|
+
...(leaf.pt ? { pt: true } : {}),
|
|
168
|
+
...(leaf.rt ? { responseType: leaf.rt } : {}),
|
|
169
|
+
...(leaf.nv ? { negotiateVariants: leaf.nv } : {}),
|
|
170
|
+
...(leaf.rf ? { rscFirst: true } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Internal Types
|
|
3
|
+
*
|
|
4
|
+
* Shared types for router module utilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ReactNode } from "react";
|
|
8
|
+
import type { EntryData, InterceptEntry, InterceptSelectorContext } from "../server/context";
|
|
9
|
+
import type {
|
|
10
|
+
ErrorInfo,
|
|
11
|
+
ErrorPhase,
|
|
12
|
+
LoaderDataResult,
|
|
13
|
+
ResolvedSegment,
|
|
14
|
+
HandlerContext,
|
|
15
|
+
InternalHandlerContext,
|
|
16
|
+
ErrorBoundaryHandler,
|
|
17
|
+
NotFoundBoundaryHandler,
|
|
18
|
+
ShouldRevalidateFn,
|
|
19
|
+
} from "../types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Result of resolving loaders with revalidation
|
|
23
|
+
* Contains both segments to render and all matched segment IDs
|
|
24
|
+
*/
|
|
25
|
+
export interface LoaderRevalidationResult {
|
|
26
|
+
segments: ResolvedSegment[];
|
|
27
|
+
matchedIds: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Result of resolving segments with revalidation
|
|
32
|
+
* Contains both segments to render and all matched segment IDs
|
|
33
|
+
*/
|
|
34
|
+
export interface SegmentRevalidationResult {
|
|
35
|
+
segments: ResolvedSegment[];
|
|
36
|
+
matchedIds: string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Action context type for revalidation
|
|
41
|
+
*/
|
|
42
|
+
export type ActionContext = {
|
|
43
|
+
actionId?: string;
|
|
44
|
+
actionUrl?: URL;
|
|
45
|
+
actionResult?: any;
|
|
46
|
+
formData?: FormData;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Dependencies passed to segment resolution functions
|
|
51
|
+
* These are created within createRouter and passed to extracted utilities
|
|
52
|
+
*/
|
|
53
|
+
export interface RouterDependencies<TEnv> {
|
|
54
|
+
findNearestErrorBoundary: (
|
|
55
|
+
entry: EntryData | null
|
|
56
|
+
) => ReactNode | ErrorBoundaryHandler | null;
|
|
57
|
+
findNearestNotFoundBoundary: (
|
|
58
|
+
entry: EntryData | null
|
|
59
|
+
) => ReactNode | NotFoundBoundaryHandler | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Dependencies injected from createRouter closure into extracted segment resolution functions.
|
|
64
|
+
* These are the closure-bound helpers that cannot be imported directly.
|
|
65
|
+
*/
|
|
66
|
+
export interface SegmentResolutionDeps<TEnv = any> {
|
|
67
|
+
wrapLoaderPromise: <T>(
|
|
68
|
+
promise: Promise<T>,
|
|
69
|
+
entry: EntryData,
|
|
70
|
+
segmentId: string,
|
|
71
|
+
pathname: string,
|
|
72
|
+
errorContext?: {
|
|
73
|
+
request: Request;
|
|
74
|
+
url: URL;
|
|
75
|
+
routeKey?: string;
|
|
76
|
+
params?: Record<string, string>;
|
|
77
|
+
env?: TEnv;
|
|
78
|
+
isPartial?: boolean;
|
|
79
|
+
requestStartTime?: number;
|
|
80
|
+
},
|
|
81
|
+
) => Promise<LoaderDataResult<T>>;
|
|
82
|
+
trackHandler: <T>(promise: Promise<T>) => Promise<T>;
|
|
83
|
+
findNearestErrorBoundary: (
|
|
84
|
+
entry: EntryData | null,
|
|
85
|
+
) => ReactNode | ErrorBoundaryHandler | null;
|
|
86
|
+
findNearestNotFoundBoundary: (
|
|
87
|
+
entry: EntryData | null,
|
|
88
|
+
) => ReactNode | NotFoundBoundaryHandler | null;
|
|
89
|
+
callOnError: (
|
|
90
|
+
error: unknown,
|
|
91
|
+
phase: ErrorPhase,
|
|
92
|
+
context: any,
|
|
93
|
+
) => void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Dependencies injected from createRouter closure into extracted intercept resolution functions.
|
|
98
|
+
*/
|
|
99
|
+
export interface InterceptResolutionDeps<TEnv = any> {
|
|
100
|
+
wrapLoaderPromise: SegmentResolutionDeps<TEnv>["wrapLoaderPromise"];
|
|
101
|
+
evaluateInterceptWhen: (
|
|
102
|
+
intercept: InterceptEntry,
|
|
103
|
+
selectorContext: InterceptSelectorContext | null,
|
|
104
|
+
isAction: boolean,
|
|
105
|
+
) => boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Dependencies injected from createRouter closure into extracted match API functions.
|
|
110
|
+
*/
|
|
111
|
+
export interface MatchApiDeps<TEnv = any> {
|
|
112
|
+
findMatch: (pathname: string, ms?: any) => any;
|
|
113
|
+
getMetricsStore: () => any;
|
|
114
|
+
findInterceptForRoute: (
|
|
115
|
+
routeKey: string,
|
|
116
|
+
parentEntry: EntryData | null,
|
|
117
|
+
selectorContext: InterceptSelectorContext | null,
|
|
118
|
+
isAction: boolean,
|
|
119
|
+
) => { intercept: InterceptEntry; entry: EntryData } | null;
|
|
120
|
+
callOnError: SegmentResolutionDeps<TEnv>["callOnError"];
|
|
121
|
+
findNearestErrorBoundary: SegmentResolutionDeps<TEnv>["findNearestErrorBoundary"];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Title descriptor types for template support
|
|
126
|
+
*/
|
|
127
|
+
export type TitleDescriptor =
|
|
128
|
+
| string
|
|
129
|
+
| { template: string; default: string } // For layouts - template applied to child titles
|
|
130
|
+
| { absolute: string }; // Bypass parent template
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Unset descriptor to remove inherited meta
|
|
134
|
+
* Key format matches getMetaKey output: "title", "name:description", "property:og:image"
|
|
135
|
+
*/
|
|
136
|
+
export type UnsetDescriptor = { unset: string };
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Base meta descriptor types (sync values)
|
|
140
|
+
*/
|
|
141
|
+
export type MetaDescriptorBase =
|
|
142
|
+
| { charSet: "utf-8" }
|
|
143
|
+
| { title: TitleDescriptor }
|
|
144
|
+
| { name: string; content: string }
|
|
145
|
+
| { property: string; content: string }
|
|
146
|
+
| { httpEquiv: string; content: string }
|
|
147
|
+
| { "script:ld+json": LdJsonObject }
|
|
148
|
+
| { tagName: "meta" | "link"; [name: string]: string }
|
|
149
|
+
| UnsetDescriptor
|
|
150
|
+
| { [name: string]: unknown };
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Meta descriptor that can be sync or async.
|
|
154
|
+
* Use Promise<MetaDescriptorBase> for streaming meta that resolves after initial render.
|
|
155
|
+
*/
|
|
156
|
+
export type MetaDescriptor = MetaDescriptorBase | Promise<MetaDescriptorBase>;
|
|
157
|
+
|
|
158
|
+
type LdJsonObject = { [Key in string]: LdJsonValue } & {
|
|
159
|
+
[Key in string]?: LdJsonValue | undefined;
|
|
160
|
+
};
|
|
161
|
+
type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[];
|
|
162
|
+
type LdJsonPrimitive = string | number | boolean | null;
|
|
163
|
+
type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
|