@tanstack/react-router 1.104.0 → 1.105.0
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/dist/cjs/Asset.cjs +41 -0
- package/dist/cjs/Asset.cjs.map +1 -0
- package/dist/cjs/Asset.d.cts +2 -0
- package/dist/cjs/HeadContent.cjs +138 -0
- package/dist/cjs/HeadContent.cjs.map +1 -0
- package/dist/cjs/HeadContent.d.cts +7 -0
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +1 -0
- package/dist/cjs/Scripts.cjs +50 -0
- package/dist/cjs/Scripts.cjs.map +1 -0
- package/dist/cjs/Scripts.d.cts +1 -0
- package/dist/cjs/index.cjs +6 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +3 -0
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +10 -7
- package/dist/cjs/router.cjs +31 -25
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/esm/Asset.d.ts +2 -0
- package/dist/esm/Asset.js +41 -0
- package/dist/esm/Asset.js.map +1 -0
- package/dist/esm/HeadContent.d.ts +7 -0
- package/dist/esm/HeadContent.js +122 -0
- package/dist/esm/HeadContent.js.map +1 -0
- package/dist/esm/Matches.d.ts +1 -0
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/Scripts.d.ts +1 -0
- package/dist/esm/Scripts.js +50 -0
- package/dist/esm/Scripts.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/route.d.ts +10 -7
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.js +31 -25
- package/dist/esm/router.js.map +1 -1
- package/package.json +3 -3
- package/src/Asset.tsx +40 -0
- package/src/HeadContent.tsx +151 -0
- package/src/Matches.tsx +1 -0
- package/src/Scripts.tsx +64 -0
- package/src/index.tsx +4 -0
- package/src/route.ts +71 -32
- package/src/router.ts +28 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.105.0",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"jsesc": "^3.1.0",
|
|
54
54
|
"tiny-invariant": "^1.3.3",
|
|
55
55
|
"tiny-warning": "^1.0.3",
|
|
56
|
-
"@tanstack/
|
|
57
|
-
"@tanstack/
|
|
56
|
+
"@tanstack/history": "1.99.13",
|
|
57
|
+
"@tanstack/router-core": "^1.104.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@testing-library/jest-dom": "^6.6.3",
|
package/src/Asset.tsx
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
2
|
+
|
|
3
|
+
export function Asset({ tag, attrs, children }: RouterManagedTag): any {
|
|
4
|
+
switch (tag) {
|
|
5
|
+
case 'title':
|
|
6
|
+
return (
|
|
7
|
+
<title {...attrs} suppressHydrationWarning>
|
|
8
|
+
{children}
|
|
9
|
+
</title>
|
|
10
|
+
)
|
|
11
|
+
case 'meta':
|
|
12
|
+
return <meta {...attrs} suppressHydrationWarning />
|
|
13
|
+
case 'link':
|
|
14
|
+
return <link {...attrs} suppressHydrationWarning />
|
|
15
|
+
case 'style':
|
|
16
|
+
return (
|
|
17
|
+
<style
|
|
18
|
+
{...attrs}
|
|
19
|
+
dangerouslySetInnerHTML={{ __html: children as any }}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
case 'script':
|
|
23
|
+
if ((attrs as any) && (attrs as any).src) {
|
|
24
|
+
return <script {...attrs} suppressHydrationWarning />
|
|
25
|
+
}
|
|
26
|
+
if (typeof children === 'string')
|
|
27
|
+
return (
|
|
28
|
+
<script
|
|
29
|
+
{...attrs}
|
|
30
|
+
dangerouslySetInnerHTML={{
|
|
31
|
+
__html: children,
|
|
32
|
+
}}
|
|
33
|
+
suppressHydrationWarning
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
return null
|
|
37
|
+
default:
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Asset } from './Asset'
|
|
3
|
+
import { useRouter } from './useRouter'
|
|
4
|
+
import { useRouterState } from './useRouterState'
|
|
5
|
+
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
6
|
+
|
|
7
|
+
export const useTags = () => {
|
|
8
|
+
const router = useRouter()
|
|
9
|
+
|
|
10
|
+
const routeMeta = useRouterState({
|
|
11
|
+
select: (state) => {
|
|
12
|
+
return state.matches.map((match) => match.meta!).filter(Boolean)
|
|
13
|
+
},
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const meta: Array<RouterManagedTag> = React.useMemo(() => {
|
|
17
|
+
const resultMeta: Array<RouterManagedTag> = []
|
|
18
|
+
const metaByAttribute: Record<string, true> = {}
|
|
19
|
+
let title: RouterManagedTag | undefined
|
|
20
|
+
;[...routeMeta].reverse().forEach((metas) => {
|
|
21
|
+
;[...metas].reverse().forEach((m) => {
|
|
22
|
+
if (!m) return
|
|
23
|
+
|
|
24
|
+
if (m.title) {
|
|
25
|
+
if (!title) {
|
|
26
|
+
title = {
|
|
27
|
+
tag: 'title',
|
|
28
|
+
children: m.title,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
const attribute = m.name ?? m.property
|
|
33
|
+
if (attribute) {
|
|
34
|
+
if (metaByAttribute[attribute]) {
|
|
35
|
+
return
|
|
36
|
+
} else {
|
|
37
|
+
metaByAttribute[attribute] = true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
resultMeta.push({
|
|
42
|
+
tag: 'meta',
|
|
43
|
+
attrs: {
|
|
44
|
+
...m,
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
if (title) {
|
|
52
|
+
resultMeta.push(title)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
resultMeta.reverse()
|
|
56
|
+
|
|
57
|
+
return resultMeta
|
|
58
|
+
}, [routeMeta])
|
|
59
|
+
|
|
60
|
+
const links = useRouterState({
|
|
61
|
+
select: (state) =>
|
|
62
|
+
state.matches
|
|
63
|
+
.map((match) => match.links!)
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.flat(1)
|
|
66
|
+
.map((link) => ({
|
|
67
|
+
tag: 'link',
|
|
68
|
+
attrs: {
|
|
69
|
+
...link,
|
|
70
|
+
},
|
|
71
|
+
})) as Array<RouterManagedTag>,
|
|
72
|
+
structuralSharing: true as any,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const preloadMeta = useRouterState({
|
|
76
|
+
select: (state) => {
|
|
77
|
+
const preloadMeta: Array<RouterManagedTag> = []
|
|
78
|
+
|
|
79
|
+
state.matches
|
|
80
|
+
.map((match) => router.looseRoutesById[match.routeId]!)
|
|
81
|
+
.forEach((route) =>
|
|
82
|
+
router.ssr?.manifest?.routes[route.id]?.preloads
|
|
83
|
+
?.filter(Boolean)
|
|
84
|
+
.forEach((preload) => {
|
|
85
|
+
preloadMeta.push({
|
|
86
|
+
tag: 'link',
|
|
87
|
+
attrs: {
|
|
88
|
+
rel: 'modulepreload',
|
|
89
|
+
href: preload,
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
}),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return preloadMeta
|
|
96
|
+
},
|
|
97
|
+
structuralSharing: true as any,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const headScripts = useRouterState({
|
|
101
|
+
select: (state) =>
|
|
102
|
+
(
|
|
103
|
+
state.matches
|
|
104
|
+
.map((match) => match.headScripts!)
|
|
105
|
+
.flat(1)
|
|
106
|
+
.filter(Boolean) as Array<RouterManagedTag>
|
|
107
|
+
).map(({ children, ...script }) => ({
|
|
108
|
+
tag: 'script',
|
|
109
|
+
attrs: {
|
|
110
|
+
...script,
|
|
111
|
+
},
|
|
112
|
+
children,
|
|
113
|
+
})),
|
|
114
|
+
structuralSharing: true as any,
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return uniqBy(
|
|
118
|
+
[
|
|
119
|
+
...meta,
|
|
120
|
+
...preloadMeta,
|
|
121
|
+
...links,
|
|
122
|
+
...headScripts,
|
|
123
|
+
] as Array<RouterManagedTag>,
|
|
124
|
+
(d) => {
|
|
125
|
+
return JSON.stringify(d)
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
|
|
132
|
+
* It should be rendered in the `<head>` of your document.
|
|
133
|
+
*/
|
|
134
|
+
export function HeadContent() {
|
|
135
|
+
const tags = useTags()
|
|
136
|
+
return tags.map((tag) => (
|
|
137
|
+
<Asset {...tag} key={`tsr-meta-${JSON.stringify(tag)}`} />
|
|
138
|
+
))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function uniqBy<T>(arr: Array<T>, fn: (item: T) => string) {
|
|
142
|
+
const seen = new Set<string>()
|
|
143
|
+
return arr.filter((item) => {
|
|
144
|
+
const key = fn(item)
|
|
145
|
+
if (seen.has(key)) {
|
|
146
|
+
return false
|
|
147
|
+
}
|
|
148
|
+
seen.add(key)
|
|
149
|
+
return true
|
|
150
|
+
})
|
|
151
|
+
}
|
package/src/Matches.tsx
CHANGED
|
@@ -88,6 +88,7 @@ export interface RouteMatch<
|
|
|
88
88
|
meta?: Array<React.JSX.IntrinsicElements['meta'] | undefined>
|
|
89
89
|
links?: Array<React.JSX.IntrinsicElements['link'] | undefined>
|
|
90
90
|
scripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>
|
|
91
|
+
headScripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>
|
|
91
92
|
headers?: Record<string, string>
|
|
92
93
|
globalNotFound?: boolean
|
|
93
94
|
staticData: StaticDataRouteOption
|
package/src/Scripts.tsx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Asset } from './Asset'
|
|
2
|
+
import { useRouterState } from './useRouterState'
|
|
3
|
+
import { useRouter } from './useRouter'
|
|
4
|
+
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
5
|
+
|
|
6
|
+
export const Scripts = () => {
|
|
7
|
+
const router = useRouter()
|
|
8
|
+
|
|
9
|
+
const assetScripts = useRouterState({
|
|
10
|
+
select: (state) => {
|
|
11
|
+
const assetScripts: Array<RouterManagedTag> = []
|
|
12
|
+
const manifest = router.ssr?.manifest
|
|
13
|
+
|
|
14
|
+
if (!manifest) {
|
|
15
|
+
return []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
state.matches
|
|
19
|
+
.map((match) => router.looseRoutesById[match.routeId]!)
|
|
20
|
+
.forEach((route) =>
|
|
21
|
+
manifest.routes[route.id]?.assets
|
|
22
|
+
?.filter((d) => d.tag === 'script')
|
|
23
|
+
.forEach((asset) => {
|
|
24
|
+
assetScripts.push({
|
|
25
|
+
tag: 'script',
|
|
26
|
+
attrs: asset.attrs,
|
|
27
|
+
children: asset.children,
|
|
28
|
+
} as any)
|
|
29
|
+
}),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return assetScripts
|
|
33
|
+
},
|
|
34
|
+
structuralSharing: true as any,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const { scripts } = useRouterState({
|
|
38
|
+
select: (state) => ({
|
|
39
|
+
scripts: (
|
|
40
|
+
state.matches
|
|
41
|
+
.map((match) => match.scripts!)
|
|
42
|
+
.flat(1)
|
|
43
|
+
.filter(Boolean) as Array<RouterManagedTag>
|
|
44
|
+
).map(({ children, ...script }) => ({
|
|
45
|
+
tag: 'script',
|
|
46
|
+
attrs: {
|
|
47
|
+
...script,
|
|
48
|
+
suppressHydrationWarning: true,
|
|
49
|
+
},
|
|
50
|
+
children,
|
|
51
|
+
})),
|
|
52
|
+
}),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const allScripts = [...scripts, ...assetScripts] as Array<RouterManagedTag>
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<>
|
|
59
|
+
{allScripts.map((asset, i) => (
|
|
60
|
+
<Asset {...asset} key={`tsr-scripts-${asset.tag}-${i}`} />
|
|
61
|
+
))}
|
|
62
|
+
</>
|
|
63
|
+
)
|
|
64
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -356,3 +356,7 @@ export type { NotFoundError } from './not-found'
|
|
|
356
356
|
export * from './typePrimitives'
|
|
357
357
|
|
|
358
358
|
export { ScriptOnce } from './ScriptOnce'
|
|
359
|
+
|
|
360
|
+
export { Asset } from './Asset'
|
|
361
|
+
export { HeadContent } from './HeadContent'
|
|
362
|
+
export { Scripts } from './Scripts'
|
package/src/route.ts
CHANGED
|
@@ -325,6 +325,51 @@ export interface BeforeLoadContextOptions<
|
|
|
325
325
|
>
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
+
type AssetFnContextOptions<
|
|
329
|
+
in out TRouteId,
|
|
330
|
+
in out TFullPath,
|
|
331
|
+
in out TParentRoute extends AnyRoute,
|
|
332
|
+
in out TParams,
|
|
333
|
+
in out TSearchValidator,
|
|
334
|
+
in out TLoaderFn,
|
|
335
|
+
in out TRouterContext,
|
|
336
|
+
in out TRouteContextFn,
|
|
337
|
+
in out TBeforeLoadFn,
|
|
338
|
+
in out TLoaderDeps,
|
|
339
|
+
> = {
|
|
340
|
+
matches: Array<
|
|
341
|
+
RouteMatch<
|
|
342
|
+
TRouteId,
|
|
343
|
+
TFullPath,
|
|
344
|
+
ResolveAllParamsFromParent<TParentRoute, TParams>,
|
|
345
|
+
ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
|
|
346
|
+
ResolveLoaderData<TLoaderFn>,
|
|
347
|
+
ResolveAllContext<
|
|
348
|
+
TParentRoute,
|
|
349
|
+
TRouterContext,
|
|
350
|
+
TRouteContextFn,
|
|
351
|
+
TBeforeLoadFn
|
|
352
|
+
>,
|
|
353
|
+
TLoaderDeps
|
|
354
|
+
>
|
|
355
|
+
>
|
|
356
|
+
match: RouteMatch<
|
|
357
|
+
TRouteId,
|
|
358
|
+
TFullPath,
|
|
359
|
+
ResolveAllParamsFromParent<TParentRoute, TParams>,
|
|
360
|
+
ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
|
|
361
|
+
ResolveLoaderData<TLoaderFn>,
|
|
362
|
+
ResolveAllContext<
|
|
363
|
+
TParentRoute,
|
|
364
|
+
TRouterContext,
|
|
365
|
+
TRouteContextFn,
|
|
366
|
+
TBeforeLoadFn
|
|
367
|
+
>,
|
|
368
|
+
TLoaderDeps
|
|
369
|
+
>
|
|
370
|
+
params: ResolveAllParamsFromParent<TParentRoute, TParams>
|
|
371
|
+
loaderData: ResolveLoaderData<TLoaderFn>
|
|
372
|
+
}
|
|
328
373
|
export interface UpdatableRouteOptions<
|
|
329
374
|
in out TParentRoute extends AnyRoute,
|
|
330
375
|
in out TRouteId,
|
|
@@ -427,44 +472,38 @@ export interface UpdatableRouteOptions<
|
|
|
427
472
|
headers?: (ctx: {
|
|
428
473
|
loaderData: ResolveLoaderData<TLoaderFn>
|
|
429
474
|
}) => Record<string, string>
|
|
430
|
-
head?: (
|
|
431
|
-
|
|
432
|
-
RouteMatch<
|
|
433
|
-
TRouteId,
|
|
434
|
-
TFullPath,
|
|
435
|
-
ResolveAllParamsFromParent<TParentRoute, TParams>,
|
|
436
|
-
ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
|
|
437
|
-
ResolveLoaderData<TLoaderFn>,
|
|
438
|
-
ResolveAllContext<
|
|
439
|
-
TParentRoute,
|
|
440
|
-
TRouterContext,
|
|
441
|
-
TRouteContextFn,
|
|
442
|
-
TBeforeLoadFn
|
|
443
|
-
>,
|
|
444
|
-
TLoaderDeps
|
|
445
|
-
>
|
|
446
|
-
>
|
|
447
|
-
match: RouteMatch<
|
|
475
|
+
head?: (
|
|
476
|
+
ctx: AssetFnContextOptions<
|
|
448
477
|
TRouteId,
|
|
449
478
|
TFullPath,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
TBeforeLoadFn
|
|
458
|
-
>,
|
|
479
|
+
TParentRoute,
|
|
480
|
+
TParams,
|
|
481
|
+
TSearchValidator,
|
|
482
|
+
TLoaderFn,
|
|
483
|
+
TRouterContext,
|
|
484
|
+
TRouteContextFn,
|
|
485
|
+
TBeforeLoadFn,
|
|
459
486
|
TLoaderDeps
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
loaderData: ResolveLoaderData<TLoaderFn> | undefined
|
|
463
|
-
}) => {
|
|
487
|
+
>,
|
|
488
|
+
) => {
|
|
464
489
|
links?: AnyRouteMatch['links']
|
|
465
|
-
scripts?: AnyRouteMatch['
|
|
490
|
+
scripts?: AnyRouteMatch['headScripts']
|
|
466
491
|
meta?: AnyRouteMatch['meta']
|
|
467
492
|
}
|
|
493
|
+
scripts?: (
|
|
494
|
+
ctx: AssetFnContextOptions<
|
|
495
|
+
TRouteId,
|
|
496
|
+
TFullPath,
|
|
497
|
+
TParentRoute,
|
|
498
|
+
TParams,
|
|
499
|
+
TSearchValidator,
|
|
500
|
+
TLoaderFn,
|
|
501
|
+
TRouterContext,
|
|
502
|
+
TRouteContextFn,
|
|
503
|
+
TBeforeLoadFn,
|
|
504
|
+
TLoaderDeps
|
|
505
|
+
>,
|
|
506
|
+
) => AnyRouteMatch['scripts']
|
|
468
507
|
ssr?: boolean
|
|
469
508
|
codeSplitGroupings?: Array<
|
|
470
509
|
Array<
|
package/src/router.ts
CHANGED
|
@@ -1311,6 +1311,7 @@ export class Router<
|
|
|
1311
1311
|
preload: false,
|
|
1312
1312
|
links: undefined,
|
|
1313
1313
|
scripts: undefined,
|
|
1314
|
+
headScripts: undefined,
|
|
1314
1315
|
meta: undefined,
|
|
1315
1316
|
staticData: route.options.staticData || {},
|
|
1316
1317
|
loadPromise: createControlledPromise(),
|
|
@@ -1318,15 +1319,6 @@ export class Router<
|
|
|
1318
1319
|
}
|
|
1319
1320
|
}
|
|
1320
1321
|
|
|
1321
|
-
// If it's already a success, update the headers
|
|
1322
|
-
// These may get updated again if the match is refreshed
|
|
1323
|
-
// due to being stale
|
|
1324
|
-
if (match.status === 'success') {
|
|
1325
|
-
match.headers = route.options.headers?.({
|
|
1326
|
-
loaderData: match.loaderData,
|
|
1327
|
-
})
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
1322
|
if (!opts?.preload) {
|
|
1331
1323
|
// If we have a global not found, mark the right match as global not found
|
|
1332
1324
|
match.globalNotFound = globalNotFoundRouteId === route.id
|
|
@@ -1380,16 +1372,25 @@ export class Router<
|
|
|
1380
1372
|
}
|
|
1381
1373
|
}
|
|
1382
1374
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1375
|
+
// If it's already a success, update headers and head content
|
|
1376
|
+
// These may get updated again if the match is refreshed
|
|
1377
|
+
// due to being stale
|
|
1378
|
+
if (match.status === 'success') {
|
|
1379
|
+
match.headers = route.options.headers?.({
|
|
1380
|
+
loaderData: match.loaderData,
|
|
1381
|
+
})
|
|
1382
|
+
const assetContext = {
|
|
1383
|
+
matches,
|
|
1384
|
+
match,
|
|
1385
|
+
params: match.params,
|
|
1386
|
+
loaderData: match.loaderData,
|
|
1387
|
+
}
|
|
1388
|
+
const headFnContent = route.options.head?.(assetContext)
|
|
1389
|
+
match.links = headFnContent?.links
|
|
1390
|
+
match.headScripts = headFnContent?.scripts
|
|
1391
|
+
match.meta = headFnContent?.meta
|
|
1392
|
+
match.scripts = route.options.scripts?.(assetContext)
|
|
1393
|
+
}
|
|
1393
1394
|
})
|
|
1394
1395
|
|
|
1395
1396
|
return matches
|
|
@@ -2558,16 +2559,19 @@ export class Router<
|
|
|
2558
2559
|
|
|
2559
2560
|
await potentialPendingMinPromise()
|
|
2560
2561
|
|
|
2561
|
-
const
|
|
2562
|
+
const assetContext = {
|
|
2562
2563
|
matches,
|
|
2563
2564
|
match: this.getMatch(matchId)!,
|
|
2564
2565
|
params: this.getMatch(matchId)!.params,
|
|
2565
2566
|
loaderData,
|
|
2566
|
-
}
|
|
2567
|
+
}
|
|
2568
|
+
const headFnContent =
|
|
2569
|
+
route.options.head?.(assetContext)
|
|
2567
2570
|
const meta = headFnContent?.meta
|
|
2568
2571
|
const links = headFnContent?.links
|
|
2569
|
-
const
|
|
2572
|
+
const headScripts = headFnContent?.scripts
|
|
2570
2573
|
|
|
2574
|
+
const scripts = route.options.scripts?.(assetContext)
|
|
2571
2575
|
const headers = route.options.headers?.({
|
|
2572
2576
|
loaderData,
|
|
2573
2577
|
})
|
|
@@ -2581,8 +2585,9 @@ export class Router<
|
|
|
2581
2585
|
loaderData,
|
|
2582
2586
|
meta,
|
|
2583
2587
|
links,
|
|
2584
|
-
|
|
2588
|
+
headScripts,
|
|
2585
2589
|
headers,
|
|
2590
|
+
scripts,
|
|
2586
2591
|
}))
|
|
2587
2592
|
} catch (e) {
|
|
2588
2593
|
let error = e
|