@depup/tanstack__react-router 1.167.5-depup.0 → 1.168.2-depup.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/README.md +3 -4
- package/changes.json +2 -6
- package/dist/cjs/Match.cjs +147 -58
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +22 -24
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Scripts.cjs +36 -32
- package/dist/cjs/Scripts.cjs.map +1 -1
- package/dist/cjs/Transitioner.cjs +10 -16
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/fileRoute.cjs +4 -6
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/headContentUtils.cjs +147 -59
- package/dist/cjs/headContentUtils.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.dev.cjs +1 -1
- package/dist/cjs/link.cjs +34 -29
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/not-found.cjs +20 -2
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/renderRouteNotFound.cjs +3 -3
- package/dist/cjs/renderRouteNotFound.cjs.map +1 -1
- package/dist/cjs/route.cjs +0 -2
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +2 -1
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/routerStores.cjs +21 -0
- package/dist/cjs/routerStores.cjs.map +1 -0
- package/dist/cjs/routerStores.d.cts +7 -0
- package/dist/cjs/ssr/RouterClient.cjs +1 -1
- package/dist/cjs/ssr/RouterClient.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToStream.cjs +2 -2
- package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -1
- package/dist/cjs/useCanGoBack.cjs +7 -2
- package/dist/cjs/useCanGoBack.cjs.map +1 -1
- package/dist/cjs/useLocation.cjs +21 -2
- package/dist/cjs/useLocation.cjs.map +1 -1
- package/dist/cjs/useMatch.cjs +35 -11
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/useRouter.cjs +3 -3
- package/dist/cjs/useRouter.cjs.map +1 -1
- package/dist/cjs/useRouterState.cjs +2 -2
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/esm/Match.js +148 -57
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +23 -24
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/Scripts.js +36 -32
- package/dist/esm/Scripts.js.map +1 -1
- package/dist/esm/Transitioner.js +10 -16
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/fileRoute.js +4 -4
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/headContentUtils.js +148 -60
- package/dist/esm/headContentUtils.js.map +1 -1
- package/dist/esm/index.dev.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/link.js +34 -29
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/not-found.js +20 -2
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/renderRouteNotFound.js +3 -2
- package/dist/esm/renderRouteNotFound.js.map +1 -1
- package/dist/esm/route.js +0 -2
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.js +2 -1
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/routerStores.d.ts +7 -0
- package/dist/esm/routerStores.js +20 -0
- package/dist/esm/routerStores.js.map +1 -0
- package/dist/esm/ssr/RouterClient.js +1 -1
- package/dist/esm/ssr/RouterClient.js.map +1 -1
- package/dist/esm/ssr/renderRouterToStream.js +2 -2
- package/dist/esm/ssr/renderRouterToStream.js.map +1 -1
- package/dist/esm/ssr/renderRouterToString.js +1 -1
- package/dist/esm/ssr/renderRouterToString.js.map +1 -1
- package/dist/esm/useCanGoBack.js +6 -2
- package/dist/esm/useCanGoBack.js.map +1 -1
- package/dist/esm/useLocation.js +20 -2
- package/dist/esm/useLocation.js.map +1 -1
- package/dist/esm/useMatch.js +35 -10
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useRouter.js +3 -2
- package/dist/esm/useRouter.js.map +1 -1
- package/dist/esm/useRouterState.js +2 -2
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/llms/rules/api.d.ts +1 -1
- package/dist/llms/rules/api.js +13 -19
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +27 -6
- package/package.json +5 -11
- package/src/Match.tsx +274 -81
- package/src/Matches.tsx +48 -30
- package/src/Scripts.tsx +72 -44
- package/src/Transitioner.tsx +24 -16
- package/src/fileRoute.ts +7 -9
- package/src/headContentUtils.tsx +210 -27
- package/src/link.tsx +66 -71
- package/src/not-found.tsx +41 -4
- package/src/renderRouteNotFound.tsx +6 -6
- package/src/route.tsx +0 -2
- package/src/router.ts +2 -1
- package/src/routerStores.ts +26 -0
- package/src/ssr/RouterClient.tsx +1 -1
- package/src/ssr/renderRouterToStream.tsx +2 -2
- package/src/ssr/renderRouterToString.tsx +1 -1
- package/src/useCanGoBack.ts +14 -2
- package/src/useLocation.tsx +32 -5
- package/src/useMatch.tsx +68 -19
- package/src/useRouter.tsx +7 -5
- package/src/useRouterState.tsx +4 -2
package/src/Scripts.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { useStore } from '@tanstack/react-store'
|
|
2
|
+
import { deepEqual } from '@tanstack/router-core'
|
|
3
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
1
4
|
import { Asset } from './Asset'
|
|
2
|
-
import { useRouterState } from './useRouterState'
|
|
3
5
|
import { useRouter } from './useRouter'
|
|
4
6
|
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
5
7
|
|
|
@@ -10,54 +12,80 @@ import type { RouterManagedTag } from '@tanstack/router-core'
|
|
|
10
12
|
export const Scripts = () => {
|
|
11
13
|
const router = useRouter()
|
|
12
14
|
const nonce = router.options.ssr?.nonce
|
|
13
|
-
const assetScripts = useRouterState({
|
|
14
|
-
select: (state) => {
|
|
15
|
-
const assetScripts: Array<RouterManagedTag> = []
|
|
16
|
-
const manifest = router.ssr?.manifest
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
const getAssetScripts = (matches: Array<any>) => {
|
|
17
|
+
const assetScripts: Array<RouterManagedTag> = []
|
|
18
|
+
const manifest = router.ssr?.manifest
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
manifest.routes[route.id]?.assets
|
|
26
|
-
?.filter((d) => d.tag === 'script')
|
|
27
|
-
.forEach((asset) => {
|
|
28
|
-
assetScripts.push({
|
|
29
|
-
tag: 'script',
|
|
30
|
-
attrs: { ...asset.attrs, nonce },
|
|
31
|
-
children: asset.children,
|
|
32
|
-
} as any)
|
|
33
|
-
}),
|
|
34
|
-
)
|
|
20
|
+
if (!manifest) {
|
|
21
|
+
return []
|
|
22
|
+
}
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
matches
|
|
25
|
+
.map((match) => router.looseRoutesById[match.routeId]!)
|
|
26
|
+
.forEach((route) =>
|
|
27
|
+
manifest.routes[route.id]?.assets
|
|
28
|
+
?.filter((d) => d.tag === 'script')
|
|
29
|
+
.forEach((asset) => {
|
|
30
|
+
assetScripts.push({
|
|
31
|
+
tag: 'script',
|
|
32
|
+
attrs: { ...asset.attrs, nonce },
|
|
33
|
+
children: asset.children,
|
|
34
|
+
} as any)
|
|
35
|
+
}),
|
|
36
|
+
)
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
38
|
+
return assetScripts
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const getScripts = (matches: Array<any>): Array<RouterManagedTag> =>
|
|
42
|
+
(
|
|
43
|
+
matches
|
|
44
|
+
.map((match) => match.scripts!)
|
|
45
|
+
.flat(1)
|
|
46
|
+
.filter(Boolean) as Array<RouterManagedTag>
|
|
47
|
+
).map(
|
|
48
|
+
({ children, ...script }) =>
|
|
49
|
+
({
|
|
50
|
+
tag: 'script',
|
|
51
|
+
attrs: {
|
|
52
|
+
...script,
|
|
53
|
+
suppressHydrationWarning: true,
|
|
54
|
+
nonce,
|
|
55
|
+
},
|
|
56
|
+
children,
|
|
57
|
+
}) satisfies RouterManagedTag,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if (isServer ?? router.isServer) {
|
|
61
|
+
const assetScripts = getAssetScripts(
|
|
62
|
+
router.stores.activeMatchesSnapshot.state,
|
|
63
|
+
)
|
|
64
|
+
const scripts = getScripts(router.stores.activeMatchesSnapshot.state)
|
|
65
|
+
return renderScripts(router, scripts, assetScripts)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
69
|
+
const assetScripts = useStore(
|
|
70
|
+
router.stores.activeMatchesSnapshot,
|
|
71
|
+
getAssetScripts,
|
|
72
|
+
deepEqual,
|
|
73
|
+
)
|
|
74
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
75
|
+
const scripts = useStore(
|
|
76
|
+
router.stores.activeMatchesSnapshot,
|
|
77
|
+
getScripts,
|
|
78
|
+
deepEqual,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return renderScripts(router, scripts, assetScripts)
|
|
82
|
+
}
|
|
60
83
|
|
|
84
|
+
function renderScripts(
|
|
85
|
+
router: ReturnType<typeof useRouter>,
|
|
86
|
+
scripts: Array<RouterManagedTag>,
|
|
87
|
+
assetScripts: Array<RouterManagedTag>,
|
|
88
|
+
) {
|
|
61
89
|
let serverBufferedScript: RouterManagedTag | undefined = undefined
|
|
62
90
|
|
|
63
91
|
if (router.serverSsr) {
|
package/src/Transitioner.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
+
import { batch, useStore } from '@tanstack/react-store'
|
|
2
3
|
import {
|
|
3
4
|
getLocationChangeInfo,
|
|
4
5
|
handleHashScroll,
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
} from '@tanstack/router-core'
|
|
7
8
|
import { useLayoutEffect, usePrevious } from './utils'
|
|
8
9
|
import { useRouter } from './useRouter'
|
|
9
|
-
import { useRouterState } from './useRouterState'
|
|
10
10
|
|
|
11
11
|
export function Transitioner() {
|
|
12
12
|
const router = useRouter()
|
|
@@ -14,13 +14,11 @@ export function Transitioner() {
|
|
|
14
14
|
|
|
15
15
|
const [isTransitioning, setIsTransitioning] = React.useState(false)
|
|
16
16
|
// Track pending state changes
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
structuralSharing: true,
|
|
23
|
-
})
|
|
17
|
+
const isLoading = useStore(router.stores.isLoading, (value) => value)
|
|
18
|
+
const hasPendingMatches = useStore(
|
|
19
|
+
router.stores.hasPendingMatches,
|
|
20
|
+
(value) => value,
|
|
21
|
+
)
|
|
24
22
|
|
|
25
23
|
const previousIsLoading = usePrevious(isLoading)
|
|
26
24
|
|
|
@@ -95,7 +93,10 @@ export function Transitioner() {
|
|
|
95
93
|
if (previousIsLoading && !isLoading) {
|
|
96
94
|
router.emit({
|
|
97
95
|
type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches
|
|
98
|
-
...getLocationChangeInfo(
|
|
96
|
+
...getLocationChangeInfo(
|
|
97
|
+
router.stores.location.state,
|
|
98
|
+
router.stores.resolvedLocation.state,
|
|
99
|
+
),
|
|
99
100
|
})
|
|
100
101
|
}
|
|
101
102
|
}, [previousIsLoading, router, isLoading])
|
|
@@ -105,24 +106,31 @@ export function Transitioner() {
|
|
|
105
106
|
if (previousIsPagePending && !isPagePending) {
|
|
106
107
|
router.emit({
|
|
107
108
|
type: 'onBeforeRouteMount',
|
|
108
|
-
...getLocationChangeInfo(
|
|
109
|
+
...getLocationChangeInfo(
|
|
110
|
+
router.stores.location.state,
|
|
111
|
+
router.stores.resolvedLocation.state,
|
|
112
|
+
),
|
|
109
113
|
})
|
|
110
114
|
}
|
|
111
115
|
}, [isPagePending, previousIsPagePending, router])
|
|
112
116
|
|
|
113
117
|
useLayoutEffect(() => {
|
|
114
118
|
if (previousIsAnyPending && !isAnyPending) {
|
|
115
|
-
const changeInfo = getLocationChangeInfo(
|
|
119
|
+
const changeInfo = getLocationChangeInfo(
|
|
120
|
+
router.stores.location.state,
|
|
121
|
+
router.stores.resolvedLocation.state,
|
|
122
|
+
)
|
|
116
123
|
router.emit({
|
|
117
124
|
type: 'onResolved',
|
|
118
125
|
...changeInfo,
|
|
119
126
|
})
|
|
120
127
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
batch(() => {
|
|
129
|
+
router.stores.status.setState(() => 'idle')
|
|
130
|
+
router.stores.resolvedLocation.setState(
|
|
131
|
+
() => router.stores.location.state,
|
|
132
|
+
)
|
|
133
|
+
})
|
|
126
134
|
|
|
127
135
|
if (changeInfo.hrefChanged) {
|
|
128
136
|
handleHashScroll(router)
|
package/src/fileRoute.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import warning from 'tiny-warning'
|
|
2
1
|
import { createRoute } from './route'
|
|
3
2
|
|
|
4
3
|
import { useMatch } from './useMatch'
|
|
@@ -151,10 +150,11 @@ export class FileRoute<
|
|
|
151
150
|
THandlers
|
|
152
151
|
> => {
|
|
153
152
|
if (process.env.NODE_ENV !== 'production') {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
if (!this.silent) {
|
|
154
|
+
console.warn(
|
|
155
|
+
'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
158
|
}
|
|
159
159
|
const route = createRoute(options as any)
|
|
160
160
|
;(route as any).isRoot = false
|
|
@@ -187,9 +187,8 @@ export function FileRouteLoader<
|
|
|
187
187
|
>,
|
|
188
188
|
) => TLoaderFn {
|
|
189
189
|
if (process.env.NODE_ENV !== 'production') {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
`FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
|
|
190
|
+
console.warn(
|
|
191
|
+
`Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
|
|
193
192
|
)
|
|
194
193
|
}
|
|
195
194
|
return (loaderFn) => loaderFn as any
|
|
@@ -218,7 +217,6 @@ export class LazyRoute<TRoute extends AnyRoute> {
|
|
|
218
217
|
} & LazyRouteOptions,
|
|
219
218
|
) {
|
|
220
219
|
this.options = opts
|
|
221
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
222
220
|
}
|
|
223
221
|
|
|
224
222
|
useMatch: UseMatchRoute<TRoute['id']> = (opts) => {
|
package/src/headContentUtils.tsx
CHANGED
|
@@ -1,9 +1,171 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { useStore } from '@tanstack/react-store'
|
|
3
|
+
import { deepEqual, escapeHtml } from '@tanstack/router-core'
|
|
4
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
3
5
|
import { useRouter } from './useRouter'
|
|
4
|
-
import { useRouterState } from './useRouterState'
|
|
5
6
|
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
6
7
|
|
|
8
|
+
function buildTagsFromMatches(
|
|
9
|
+
router: ReturnType<typeof useRouter>,
|
|
10
|
+
nonce: string | undefined,
|
|
11
|
+
matches: Array<any>,
|
|
12
|
+
): Array<RouterManagedTag> {
|
|
13
|
+
const routeMeta = matches.map((match) => match.meta!).filter(Boolean)
|
|
14
|
+
|
|
15
|
+
const resultMeta: Array<RouterManagedTag> = []
|
|
16
|
+
const metaByAttribute: Record<string, true> = {}
|
|
17
|
+
let title: RouterManagedTag | undefined
|
|
18
|
+
for (let i = routeMeta.length - 1; i >= 0; i--) {
|
|
19
|
+
const metas = routeMeta[i]!
|
|
20
|
+
for (let j = metas.length - 1; j >= 0; j--) {
|
|
21
|
+
const m = metas[j]
|
|
22
|
+
if (!m) continue
|
|
23
|
+
|
|
24
|
+
if (m.title) {
|
|
25
|
+
if (!title) {
|
|
26
|
+
title = {
|
|
27
|
+
tag: 'title',
|
|
28
|
+
children: m.title,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} else if ('script:ld+json' in m) {
|
|
32
|
+
try {
|
|
33
|
+
const json = JSON.stringify(m['script:ld+json'])
|
|
34
|
+
resultMeta.push({
|
|
35
|
+
tag: 'script',
|
|
36
|
+
attrs: {
|
|
37
|
+
type: 'application/ld+json',
|
|
38
|
+
},
|
|
39
|
+
children: escapeHtml(json),
|
|
40
|
+
})
|
|
41
|
+
} catch {
|
|
42
|
+
// Skip invalid JSON-LD objects
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
const attribute = m.name ?? m.property
|
|
46
|
+
if (attribute) {
|
|
47
|
+
if (metaByAttribute[attribute]) {
|
|
48
|
+
continue
|
|
49
|
+
} else {
|
|
50
|
+
metaByAttribute[attribute] = true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
resultMeta.push({
|
|
55
|
+
tag: 'meta',
|
|
56
|
+
attrs: {
|
|
57
|
+
...m,
|
|
58
|
+
nonce,
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (title) {
|
|
66
|
+
resultMeta.push(title)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (nonce) {
|
|
70
|
+
resultMeta.push({
|
|
71
|
+
tag: 'meta',
|
|
72
|
+
attrs: {
|
|
73
|
+
property: 'csp-nonce',
|
|
74
|
+
content: nonce,
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
resultMeta.reverse()
|
|
79
|
+
|
|
80
|
+
const constructedLinks = matches
|
|
81
|
+
.map((match) => match.links!)
|
|
82
|
+
.filter(Boolean)
|
|
83
|
+
.flat(1)
|
|
84
|
+
.map((link) => ({
|
|
85
|
+
tag: 'link',
|
|
86
|
+
attrs: {
|
|
87
|
+
...link,
|
|
88
|
+
nonce,
|
|
89
|
+
},
|
|
90
|
+
})) satisfies Array<RouterManagedTag>
|
|
91
|
+
|
|
92
|
+
const manifest = router.ssr?.manifest
|
|
93
|
+
const assetLinks = matches
|
|
94
|
+
.map((match) => manifest?.routes[match.routeId]?.assets ?? [])
|
|
95
|
+
.filter(Boolean)
|
|
96
|
+
.flat(1)
|
|
97
|
+
.filter((asset) => asset.tag === 'link')
|
|
98
|
+
.map(
|
|
99
|
+
(asset) =>
|
|
100
|
+
({
|
|
101
|
+
tag: 'link',
|
|
102
|
+
attrs: {
|
|
103
|
+
...asset.attrs,
|
|
104
|
+
suppressHydrationWarning: true,
|
|
105
|
+
nonce,
|
|
106
|
+
},
|
|
107
|
+
}) satisfies RouterManagedTag,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
const preloadLinks: Array<RouterManagedTag> = []
|
|
111
|
+
matches
|
|
112
|
+
.map((match) => router.looseRoutesById[match.routeId]!)
|
|
113
|
+
.forEach((route) =>
|
|
114
|
+
router.ssr?.manifest?.routes[route.id]?.preloads
|
|
115
|
+
?.filter(Boolean)
|
|
116
|
+
.forEach((preload) => {
|
|
117
|
+
preloadLinks.push({
|
|
118
|
+
tag: 'link',
|
|
119
|
+
attrs: {
|
|
120
|
+
rel: 'modulepreload',
|
|
121
|
+
href: preload,
|
|
122
|
+
nonce,
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
}),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
const styles = (
|
|
129
|
+
matches
|
|
130
|
+
.map((match) => match.styles!)
|
|
131
|
+
.flat(1)
|
|
132
|
+
.filter(Boolean) as Array<RouterManagedTag>
|
|
133
|
+
).map(({ children, ...attrs }) => ({
|
|
134
|
+
tag: 'style',
|
|
135
|
+
attrs: {
|
|
136
|
+
...attrs,
|
|
137
|
+
nonce,
|
|
138
|
+
},
|
|
139
|
+
children,
|
|
140
|
+
}))
|
|
141
|
+
|
|
142
|
+
const headScripts = (
|
|
143
|
+
matches
|
|
144
|
+
.map((match) => match.headScripts!)
|
|
145
|
+
.flat(1)
|
|
146
|
+
.filter(Boolean) as Array<RouterManagedTag>
|
|
147
|
+
).map(({ children, ...script }) => ({
|
|
148
|
+
tag: 'script',
|
|
149
|
+
attrs: {
|
|
150
|
+
...script,
|
|
151
|
+
nonce,
|
|
152
|
+
},
|
|
153
|
+
children,
|
|
154
|
+
}))
|
|
155
|
+
|
|
156
|
+
return uniqBy(
|
|
157
|
+
[
|
|
158
|
+
...resultMeta,
|
|
159
|
+
...preloadLinks,
|
|
160
|
+
...constructedLinks,
|
|
161
|
+
...assetLinks,
|
|
162
|
+
...styles,
|
|
163
|
+
...headScripts,
|
|
164
|
+
] as Array<RouterManagedTag>,
|
|
165
|
+
(d) => JSON.stringify(d),
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
7
169
|
/**
|
|
8
170
|
* Build the list of head/link/meta/script tags to render for active matches.
|
|
9
171
|
* Used internally by `HeadContent`.
|
|
@@ -11,12 +173,25 @@ import type { RouterManagedTag } from '@tanstack/router-core'
|
|
|
11
173
|
export const useTags = () => {
|
|
12
174
|
const router = useRouter()
|
|
13
175
|
const nonce = router.options.ssr?.nonce
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
176
|
+
|
|
177
|
+
if (isServer ?? router.isServer) {
|
|
178
|
+
return buildTagsFromMatches(
|
|
179
|
+
router,
|
|
180
|
+
nonce,
|
|
181
|
+
router.stores.activeMatchesSnapshot.state,
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
186
|
+
const routeMeta = useStore(
|
|
187
|
+
router.stores.activeMatchesSnapshot,
|
|
188
|
+
(matches) => {
|
|
189
|
+
return matches.map((match) => match.meta!).filter(Boolean)
|
|
17
190
|
},
|
|
18
|
-
|
|
191
|
+
deepEqual,
|
|
192
|
+
)
|
|
19
193
|
|
|
194
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
20
195
|
const meta: Array<RouterManagedTag> = React.useMemo(() => {
|
|
21
196
|
const resultMeta: Array<RouterManagedTag> = []
|
|
22
197
|
const metaByAttribute: Record<string, true> = {}
|
|
@@ -88,9 +263,11 @@ export const useTags = () => {
|
|
|
88
263
|
return resultMeta
|
|
89
264
|
}, [routeMeta, nonce])
|
|
90
265
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
266
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
267
|
+
const links = useStore(
|
|
268
|
+
router.stores.activeMatchesSnapshot,
|
|
269
|
+
(matches) => {
|
|
270
|
+
const constructed = matches
|
|
94
271
|
.map((match) => match.links!)
|
|
95
272
|
.filter(Boolean)
|
|
96
273
|
.flat(1)
|
|
@@ -106,7 +283,7 @@ export const useTags = () => {
|
|
|
106
283
|
|
|
107
284
|
// These are the assets extracted from the ViteManifest
|
|
108
285
|
// using the `startManifestPlugin`
|
|
109
|
-
const assets =
|
|
286
|
+
const assets = matches
|
|
110
287
|
.map((match) => manifest?.routes[match.routeId]?.assets ?? [])
|
|
111
288
|
.filter(Boolean)
|
|
112
289
|
.flat(1)
|
|
@@ -125,14 +302,16 @@ export const useTags = () => {
|
|
|
125
302
|
|
|
126
303
|
return [...constructed, ...assets]
|
|
127
304
|
},
|
|
128
|
-
|
|
129
|
-
|
|
305
|
+
deepEqual,
|
|
306
|
+
)
|
|
130
307
|
|
|
131
|
-
|
|
132
|
-
|
|
308
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
309
|
+
const preloadLinks = useStore(
|
|
310
|
+
router.stores.activeMatchesSnapshot,
|
|
311
|
+
(matches) => {
|
|
133
312
|
const preloadLinks: Array<RouterManagedTag> = []
|
|
134
313
|
|
|
135
|
-
|
|
314
|
+
matches
|
|
136
315
|
.map((match) => router.looseRoutesById[match.routeId]!)
|
|
137
316
|
.forEach((route) =>
|
|
138
317
|
router.ssr?.manifest?.routes[route.id]?.preloads
|
|
@@ -151,13 +330,15 @@ export const useTags = () => {
|
|
|
151
330
|
|
|
152
331
|
return preloadLinks
|
|
153
332
|
},
|
|
154
|
-
|
|
155
|
-
|
|
333
|
+
deepEqual,
|
|
334
|
+
)
|
|
156
335
|
|
|
157
|
-
|
|
158
|
-
|
|
336
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
337
|
+
const styles = useStore(
|
|
338
|
+
router.stores.activeMatchesSnapshot,
|
|
339
|
+
(matches) =>
|
|
159
340
|
(
|
|
160
|
-
|
|
341
|
+
matches
|
|
161
342
|
.map((match) => match.styles!)
|
|
162
343
|
.flat(1)
|
|
163
344
|
.filter(Boolean) as Array<RouterManagedTag>
|
|
@@ -169,13 +350,15 @@ export const useTags = () => {
|
|
|
169
350
|
},
|
|
170
351
|
children,
|
|
171
352
|
})),
|
|
172
|
-
|
|
173
|
-
|
|
353
|
+
deepEqual,
|
|
354
|
+
)
|
|
174
355
|
|
|
175
|
-
|
|
176
|
-
|
|
356
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
357
|
+
const headScripts: Array<RouterManagedTag> = useStore(
|
|
358
|
+
router.stores.activeMatchesSnapshot,
|
|
359
|
+
(matches) =>
|
|
177
360
|
(
|
|
178
|
-
|
|
361
|
+
matches
|
|
179
362
|
.map((match) => match.headScripts!)
|
|
180
363
|
.flat(1)
|
|
181
364
|
.filter(Boolean) as Array<RouterManagedTag>
|
|
@@ -187,8 +370,8 @@ export const useTags = () => {
|
|
|
187
370
|
},
|
|
188
371
|
children,
|
|
189
372
|
})),
|
|
190
|
-
|
|
191
|
-
|
|
373
|
+
deepEqual,
|
|
374
|
+
)
|
|
192
375
|
|
|
193
376
|
return uniqBy(
|
|
194
377
|
[
|