@tanstack/react-router 1.147.2 → 1.147.3

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.
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const routerCore = require("@tanstack/router-core");
4
+ const history = require("@tanstack/history");
5
+ const awaited = require("./awaited.cjs");
6
+ const CatchBoundary = require("./CatchBoundary.cjs");
7
+ const ClientOnly = require("./ClientOnly.cjs");
8
+ const fileRoute = require("./fileRoute.cjs");
9
+ const lazyRouteComponent = require("./lazyRouteComponent.cjs");
10
+ const link = require("./link.cjs");
11
+ const Matches = require("./Matches.cjs");
12
+ const matchContext = require("./matchContext.cjs");
13
+ const Match = require("./Match.cjs");
14
+ const useMatch = require("./useMatch.cjs");
15
+ const useLoaderDeps = require("./useLoaderDeps.cjs");
16
+ const useLoaderData = require("./useLoaderData.cjs");
17
+ const route = require("./route.cjs");
18
+ const router = require("./router.cjs");
19
+ const RouterProvider = require("./RouterProvider.cjs");
20
+ const ScrollRestoration = require("./ScrollRestoration.cjs");
21
+ const useBlocker = require("./useBlocker.cjs");
22
+ const useNavigate = require("./useNavigate.cjs");
23
+ const useParams = require("./useParams.cjs");
24
+ const useSearch = require("./useSearch.cjs");
25
+ const routerContext = require("./routerContext.cjs");
26
+ const useRouteContext = require("./useRouteContext.cjs");
27
+ const useRouter = require("./useRouter.cjs");
28
+ const useRouterState = require("./useRouterState.cjs");
29
+ const useLocation = require("./useLocation.cjs");
30
+ const useCanGoBack = require("./useCanGoBack.cjs");
31
+ const utils = require("./utils.cjs");
32
+ const notFound = require("./not-found.cjs");
33
+ const ScriptOnce = require("./ScriptOnce.cjs");
34
+ const Asset = require("./Asset.cjs");
35
+ const headContentUtils = require("./headContentUtils.cjs");
36
+ const Scripts = require("./Scripts.cjs");
37
+ const HeadContent_dev = require("./HeadContent.dev.cjs");
38
+ Object.defineProperty(exports, "PathParamError", {
39
+ enumerable: true,
40
+ get: () => routerCore.PathParamError
41
+ });
42
+ Object.defineProperty(exports, "SearchParamError", {
43
+ enumerable: true,
44
+ get: () => routerCore.SearchParamError
45
+ });
46
+ Object.defineProperty(exports, "TSR_DEFERRED_PROMISE", {
47
+ enumerable: true,
48
+ get: () => routerCore.TSR_DEFERRED_PROMISE
49
+ });
50
+ Object.defineProperty(exports, "cleanPath", {
51
+ enumerable: true,
52
+ get: () => routerCore.cleanPath
53
+ });
54
+ Object.defineProperty(exports, "componentTypes", {
55
+ enumerable: true,
56
+ get: () => routerCore.componentTypes
57
+ });
58
+ Object.defineProperty(exports, "composeRewrites", {
59
+ enumerable: true,
60
+ get: () => routerCore.composeRewrites
61
+ });
62
+ Object.defineProperty(exports, "createControlledPromise", {
63
+ enumerable: true,
64
+ get: () => routerCore.createControlledPromise
65
+ });
66
+ Object.defineProperty(exports, "createRouterConfig", {
67
+ enumerable: true,
68
+ get: () => routerCore.createRouterConfig
69
+ });
70
+ Object.defineProperty(exports, "createSerializationAdapter", {
71
+ enumerable: true,
72
+ get: () => routerCore.createSerializationAdapter
73
+ });
74
+ Object.defineProperty(exports, "deepEqual", {
75
+ enumerable: true,
76
+ get: () => routerCore.deepEqual
77
+ });
78
+ Object.defineProperty(exports, "defaultParseSearch", {
79
+ enumerable: true,
80
+ get: () => routerCore.defaultParseSearch
81
+ });
82
+ Object.defineProperty(exports, "defaultSerializeError", {
83
+ enumerable: true,
84
+ get: () => routerCore.defaultSerializeError
85
+ });
86
+ Object.defineProperty(exports, "defaultStringifySearch", {
87
+ enumerable: true,
88
+ get: () => routerCore.defaultStringifySearch
89
+ });
90
+ Object.defineProperty(exports, "defer", {
91
+ enumerable: true,
92
+ get: () => routerCore.defer
93
+ });
94
+ Object.defineProperty(exports, "functionalUpdate", {
95
+ enumerable: true,
96
+ get: () => routerCore.functionalUpdate
97
+ });
98
+ Object.defineProperty(exports, "getInitialRouterState", {
99
+ enumerable: true,
100
+ get: () => routerCore.getInitialRouterState
101
+ });
102
+ Object.defineProperty(exports, "interpolatePath", {
103
+ enumerable: true,
104
+ get: () => routerCore.interpolatePath
105
+ });
106
+ Object.defineProperty(exports, "isMatch", {
107
+ enumerable: true,
108
+ get: () => routerCore.isMatch
109
+ });
110
+ Object.defineProperty(exports, "isNotFound", {
111
+ enumerable: true,
112
+ get: () => routerCore.isNotFound
113
+ });
114
+ Object.defineProperty(exports, "isPlainArray", {
115
+ enumerable: true,
116
+ get: () => routerCore.isPlainArray
117
+ });
118
+ Object.defineProperty(exports, "isPlainObject", {
119
+ enumerable: true,
120
+ get: () => routerCore.isPlainObject
121
+ });
122
+ Object.defineProperty(exports, "isRedirect", {
123
+ enumerable: true,
124
+ get: () => routerCore.isRedirect
125
+ });
126
+ Object.defineProperty(exports, "joinPaths", {
127
+ enumerable: true,
128
+ get: () => routerCore.joinPaths
129
+ });
130
+ Object.defineProperty(exports, "lazyFn", {
131
+ enumerable: true,
132
+ get: () => routerCore.lazyFn
133
+ });
134
+ Object.defineProperty(exports, "notFound", {
135
+ enumerable: true,
136
+ get: () => routerCore.notFound
137
+ });
138
+ Object.defineProperty(exports, "parseSearchWith", {
139
+ enumerable: true,
140
+ get: () => routerCore.parseSearchWith
141
+ });
142
+ Object.defineProperty(exports, "redirect", {
143
+ enumerable: true,
144
+ get: () => routerCore.redirect
145
+ });
146
+ Object.defineProperty(exports, "replaceEqualDeep", {
147
+ enumerable: true,
148
+ get: () => routerCore.replaceEqualDeep
149
+ });
150
+ Object.defineProperty(exports, "resolvePath", {
151
+ enumerable: true,
152
+ get: () => routerCore.resolvePath
153
+ });
154
+ Object.defineProperty(exports, "retainSearchParams", {
155
+ enumerable: true,
156
+ get: () => routerCore.retainSearchParams
157
+ });
158
+ Object.defineProperty(exports, "rootRouteId", {
159
+ enumerable: true,
160
+ get: () => routerCore.rootRouteId
161
+ });
162
+ Object.defineProperty(exports, "stringifySearchWith", {
163
+ enumerable: true,
164
+ get: () => routerCore.stringifySearchWith
165
+ });
166
+ Object.defineProperty(exports, "stripSearchParams", {
167
+ enumerable: true,
168
+ get: () => routerCore.stripSearchParams
169
+ });
170
+ Object.defineProperty(exports, "trimPath", {
171
+ enumerable: true,
172
+ get: () => routerCore.trimPath
173
+ });
174
+ Object.defineProperty(exports, "trimPathLeft", {
175
+ enumerable: true,
176
+ get: () => routerCore.trimPathLeft
177
+ });
178
+ Object.defineProperty(exports, "trimPathRight", {
179
+ enumerable: true,
180
+ get: () => routerCore.trimPathRight
181
+ });
182
+ Object.defineProperty(exports, "createBrowserHistory", {
183
+ enumerable: true,
184
+ get: () => history.createBrowserHistory
185
+ });
186
+ Object.defineProperty(exports, "createHashHistory", {
187
+ enumerable: true,
188
+ get: () => history.createHashHistory
189
+ });
190
+ Object.defineProperty(exports, "createHistory", {
191
+ enumerable: true,
192
+ get: () => history.createHistory
193
+ });
194
+ Object.defineProperty(exports, "createMemoryHistory", {
195
+ enumerable: true,
196
+ get: () => history.createMemoryHistory
197
+ });
198
+ exports.Await = awaited.Await;
199
+ exports.useAwaited = awaited.useAwaited;
200
+ exports.CatchBoundary = CatchBoundary.CatchBoundary;
201
+ exports.ErrorComponent = CatchBoundary.ErrorComponent;
202
+ exports.ClientOnly = ClientOnly.ClientOnly;
203
+ exports.useHydrated = ClientOnly.useHydrated;
204
+ exports.FileRoute = fileRoute.FileRoute;
205
+ exports.FileRouteLoader = fileRoute.FileRouteLoader;
206
+ exports.LazyRoute = fileRoute.LazyRoute;
207
+ exports.createFileRoute = fileRoute.createFileRoute;
208
+ exports.createLazyFileRoute = fileRoute.createLazyFileRoute;
209
+ exports.createLazyRoute = fileRoute.createLazyRoute;
210
+ exports.lazyRouteComponent = lazyRouteComponent.lazyRouteComponent;
211
+ exports.Link = link.Link;
212
+ exports.createLink = link.createLink;
213
+ exports.linkOptions = link.linkOptions;
214
+ exports.useLinkProps = link.useLinkProps;
215
+ exports.MatchRoute = Matches.MatchRoute;
216
+ exports.Matches = Matches.Matches;
217
+ exports.useChildMatches = Matches.useChildMatches;
218
+ exports.useMatchRoute = Matches.useMatchRoute;
219
+ exports.useMatches = Matches.useMatches;
220
+ exports.useParentMatches = Matches.useParentMatches;
221
+ exports.matchContext = matchContext.matchContext;
222
+ exports.Match = Match.Match;
223
+ exports.Outlet = Match.Outlet;
224
+ exports.useMatch = useMatch.useMatch;
225
+ exports.useLoaderDeps = useLoaderDeps.useLoaderDeps;
226
+ exports.useLoaderData = useLoaderData.useLoaderData;
227
+ exports.NotFoundRoute = route.NotFoundRoute;
228
+ exports.RootRoute = route.RootRoute;
229
+ exports.Route = route.Route;
230
+ exports.RouteApi = route.RouteApi;
231
+ exports.createRootRoute = route.createRootRoute;
232
+ exports.createRootRouteWithContext = route.createRootRouteWithContext;
233
+ exports.createRoute = route.createRoute;
234
+ exports.createRouteMask = route.createRouteMask;
235
+ exports.getRouteApi = route.getRouteApi;
236
+ exports.rootRouteWithContext = route.rootRouteWithContext;
237
+ exports.Router = router.Router;
238
+ exports.createRouter = router.createRouter;
239
+ exports.RouterContextProvider = RouterProvider.RouterContextProvider;
240
+ exports.RouterProvider = RouterProvider.RouterProvider;
241
+ exports.ScrollRestoration = ScrollRestoration.ScrollRestoration;
242
+ exports.useElementScrollRestoration = ScrollRestoration.useElementScrollRestoration;
243
+ exports.Block = useBlocker.Block;
244
+ exports.useBlocker = useBlocker.useBlocker;
245
+ exports.Navigate = useNavigate.Navigate;
246
+ exports.useNavigate = useNavigate.useNavigate;
247
+ exports.useParams = useParams.useParams;
248
+ exports.useSearch = useSearch.useSearch;
249
+ exports.getRouterContext = routerContext.getRouterContext;
250
+ exports.useRouteContext = useRouteContext.useRouteContext;
251
+ exports.useRouter = useRouter.useRouter;
252
+ exports.useRouterState = useRouterState.useRouterState;
253
+ exports.useLocation = useLocation.useLocation;
254
+ exports.useCanGoBack = useCanGoBack.useCanGoBack;
255
+ exports.useLayoutEffect = utils.useLayoutEffect;
256
+ exports.useStableCallback = utils.useStableCallback;
257
+ exports.CatchNotFound = notFound.CatchNotFound;
258
+ exports.DefaultGlobalNotFound = notFound.DefaultGlobalNotFound;
259
+ exports.ScriptOnce = ScriptOnce.ScriptOnce;
260
+ exports.Asset = Asset.Asset;
261
+ exports.useTags = headContentUtils.useTags;
262
+ exports.Scripts = Scripts.Scripts;
263
+ exports.HeadContent = HeadContent_dev.HeadContent;
264
+ //# sourceMappingURL=index.dev.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.dev.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ export * from './index.cjs';
2
+ export { HeadContent } from './HeadContent.dev';
@@ -1,9 +1,3 @@
1
- import { RouterManagedTag } from '@tanstack/router-core';
2
- /**
3
- * Build the list of head/link/meta/script tags to render for active matches.
4
- * Used internally by `HeadContent`.
5
- */
6
- export declare const useTags: () => RouterManagedTag[];
7
1
  /**
8
2
  * Render route-managed head tags (title, meta, links, styles, head scripts).
9
3
  * Place inside the document head of your app shell.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Render route-managed head tags (title, meta, links, styles, head scripts).
3
+ * Place inside the document head of your app shell.
4
+ *
5
+ * Development version: filters out dev styles link after hydration and
6
+ * includes a fallback cleanup effect for hydration mismatch cases.
7
+ *
8
+ * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management
9
+ */
10
+ export declare function HeadContent(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { jsx, Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { createElement } from "react";
4
+ import { Asset } from "./Asset.js";
5
+ import { useRouter } from "./useRouter.js";
6
+ import { useHydrated } from "./ClientOnly.js";
7
+ import { useTags } from "./headContentUtils.js";
8
+ const DEV_STYLES_ATTR = "data-tanstack-router-dev-styles";
9
+ function HeadContent() {
10
+ const tags = useTags();
11
+ const router = useRouter();
12
+ const nonce = router.options.ssr?.nonce;
13
+ const hydrated = useHydrated();
14
+ React.useEffect(() => {
15
+ if (hydrated) {
16
+ document.querySelectorAll(`link[${DEV_STYLES_ATTR}]`).forEach((el) => el.remove());
17
+ }
18
+ }, [hydrated]);
19
+ const filteredTags = hydrated ? tags.filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR]) : tags;
20
+ return /* @__PURE__ */ jsx(Fragment, { children: filteredTags.map((tag) => /* @__PURE__ */ createElement(Asset, { ...tag, key: `tsr-meta-${JSON.stringify(tag)}`, nonce })) });
21
+ }
22
+ export {
23
+ HeadContent
24
+ };
25
+ //# sourceMappingURL=HeadContent.dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeadContent.dev.js","sources":["../../src/HeadContent.dev.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport { useHydrated } from './ClientOnly'\nimport { useTags } from './headContentUtils'\n\nconst DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles'\n\n/**\n * Render route-managed head tags (title, meta, links, styles, head scripts).\n * Place inside the document head of your app shell.\n *\n * Development version: filters out dev styles link after hydration and\n * includes a fallback cleanup effect for hydration mismatch cases.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management\n */\nexport function HeadContent() {\n const tags = useTags()\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n const hydrated = useHydrated()\n\n // Fallback cleanup for hydration mismatch cases\n // Runs when hydration completes to remove any orphaned dev styles links from DOM\n React.useEffect(() => {\n if (hydrated) {\n document\n .querySelectorAll(`link[${DEV_STYLES_ATTR}]`)\n .forEach((el) => el.remove())\n }\n }, [hydrated])\n\n // Filter out dev styles after hydration\n const filteredTags = hydrated\n ? tags.filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR])\n : tags\n\n return (\n <>\n {filteredTags.map((tag) => (\n <Asset {...tag} key={`tsr-meta-${JSON.stringify(tag)}`} nonce={nonce} />\n ))}\n </>\n )\n}\n"],"names":[],"mappings":";;;;;;;AAMA,MAAM,kBAAkB;AAWjB,SAAS,cAAc;AAC5B,QAAM,OAAO,QAAA;AACb,QAAM,SAAS,UAAA;AACf,QAAM,QAAQ,OAAO,QAAQ,KAAK;AAClC,QAAM,WAAW,YAAA;AAIjB,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU;AACZ,eACG,iBAAiB,QAAQ,eAAe,GAAG,EAC3C,QAAQ,CAAC,OAAO,GAAG,OAAA,CAAQ;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,eAAe,WACjB,KAAK,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,eAAe,CAAC,IAClD;AAEJ,yCAEK,UAAA,aAAa,IAAI,CAAC,QACjB,8BAAC,SAAO,GAAG,KAAK,KAAK,YAAY,KAAK,UAAU,GAAG,CAAC,IAAI,OAAc,CACvE,GACH;AAEJ;"}
@@ -1,197 +1,15 @@
1
- import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
- import * as React from "react";
1
+ import { jsx, Fragment } from "react/jsx-runtime";
3
2
  import { createElement } from "react";
4
- import { escapeHtml, buildDevStylesUrl } from "@tanstack/router-core";
5
3
  import { Asset } from "./Asset.js";
6
4
  import { useRouter } from "./useRouter.js";
7
- import { useRouterState } from "./useRouterState.js";
8
- const useTags = () => {
9
- const router = useRouter();
10
- const nonce = router.options.ssr?.nonce;
11
- const routeMeta = useRouterState({
12
- select: (state) => {
13
- return state.matches.map((match) => match.meta).filter(Boolean);
14
- }
15
- });
16
- const meta = React.useMemo(() => {
17
- const resultMeta = [];
18
- const metaByAttribute = {};
19
- let title;
20
- for (let i = routeMeta.length - 1; i >= 0; i--) {
21
- const metas = routeMeta[i];
22
- for (let j = metas.length - 1; j >= 0; j--) {
23
- const m = metas[j];
24
- if (!m) continue;
25
- if (m.title) {
26
- if (!title) {
27
- title = {
28
- tag: "title",
29
- children: m.title
30
- };
31
- }
32
- } else if ("script:ld+json" in m) {
33
- try {
34
- const json = JSON.stringify(m["script:ld+json"]);
35
- resultMeta.push({
36
- tag: "script",
37
- attrs: {
38
- type: "application/ld+json"
39
- },
40
- children: escapeHtml(json)
41
- });
42
- } catch {
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
- resultMeta.push({
54
- tag: "meta",
55
- attrs: {
56
- ...m,
57
- nonce
58
- }
59
- });
60
- }
61
- }
62
- }
63
- if (title) {
64
- resultMeta.push(title);
65
- }
66
- if (nonce) {
67
- resultMeta.push({
68
- tag: "meta",
69
- attrs: {
70
- property: "csp-nonce",
71
- content: nonce
72
- }
73
- });
74
- }
75
- resultMeta.reverse();
76
- return resultMeta;
77
- }, [routeMeta, nonce]);
78
- const links = useRouterState({
79
- select: (state) => {
80
- const constructed = state.matches.map((match) => match.links).filter(Boolean).flat(1).map((link) => ({
81
- tag: "link",
82
- attrs: {
83
- ...link,
84
- nonce
85
- }
86
- }));
87
- const manifest = router.ssr?.manifest;
88
- const assets = state.matches.map((match) => manifest?.routes[match.routeId]?.assets ?? []).filter(Boolean).flat(1).filter((asset) => asset.tag === "link").map(
89
- (asset) => ({
90
- tag: "link",
91
- attrs: {
92
- ...asset.attrs,
93
- suppressHydrationWarning: true,
94
- nonce
95
- }
96
- })
97
- );
98
- return [...constructed, ...assets];
99
- },
100
- structuralSharing: true
101
- });
102
- const preloadLinks = useRouterState({
103
- select: (state) => {
104
- const preloadLinks2 = [];
105
- state.matches.map((match) => router.looseRoutesById[match.routeId]).forEach(
106
- (route) => router.ssr?.manifest?.routes[route.id]?.preloads?.filter(Boolean).forEach((preload) => {
107
- preloadLinks2.push({
108
- tag: "link",
109
- attrs: {
110
- rel: "modulepreload",
111
- href: preload,
112
- nonce
113
- }
114
- });
115
- })
116
- );
117
- return preloadLinks2;
118
- },
119
- structuralSharing: true
120
- });
121
- const styles = useRouterState({
122
- select: (state) => state.matches.map((match) => match.styles).flat(1).filter(Boolean).map(({ children, ...attrs }) => ({
123
- tag: "style",
124
- attrs,
125
- children,
126
- nonce
127
- })),
128
- structuralSharing: true
129
- });
130
- const headScripts = useRouterState({
131
- select: (state) => state.matches.map((match) => match.headScripts).flat(1).filter(Boolean).map(({ children, ...script }) => ({
132
- tag: "script",
133
- attrs: {
134
- ...script,
135
- nonce
136
- },
137
- children
138
- })),
139
- structuralSharing: true
140
- });
141
- return uniqBy(
142
- [
143
- ...meta,
144
- ...preloadLinks,
145
- ...links,
146
- ...styles,
147
- ...headScripts
148
- ],
149
- (d) => {
150
- return JSON.stringify(d);
151
- }
152
- );
153
- };
154
- function DevStylesLink() {
155
- const router = useRouter();
156
- const routeIds = useRouterState({
157
- select: (state) => state.matches.map((match) => match.routeId)
158
- });
159
- React.useEffect(() => {
160
- document.querySelectorAll("[data-tanstack-start-dev-styles]").forEach((el) => el.remove());
161
- }, []);
162
- const href = buildDevStylesUrl(router.basepath, routeIds);
163
- return /* @__PURE__ */ jsx(
164
- "link",
165
- {
166
- rel: "stylesheet",
167
- href,
168
- "data-tanstack-start-dev-styles": true,
169
- suppressHydrationWarning: true
170
- }
171
- );
172
- }
5
+ import { useTags } from "./headContentUtils.js";
173
6
  function HeadContent() {
174
7
  const tags = useTags();
175
8
  const router = useRouter();
176
9
  const nonce = router.options.ssr?.nonce;
177
- return /* @__PURE__ */ jsxs(Fragment, { children: [
178
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsx(DevStylesLink, {}),
179
- tags.map((tag) => /* @__PURE__ */ createElement(Asset, { ...tag, key: `tsr-meta-${JSON.stringify(tag)}`, nonce }))
180
- ] });
181
- }
182
- function uniqBy(arr, fn) {
183
- const seen = /* @__PURE__ */ new Set();
184
- return arr.filter((item) => {
185
- const key = fn(item);
186
- if (seen.has(key)) {
187
- return false;
188
- }
189
- seen.add(key);
190
- return true;
191
- });
10
+ return /* @__PURE__ */ jsx(Fragment, { children: tags.map((tag) => /* @__PURE__ */ createElement(Asset, { ...tag, key: `tsr-meta-${JSON.stringify(tag)}`, nonce })) });
192
11
  }
193
12
  export {
194
- HeadContent,
195
- useTags
13
+ HeadContent
196
14
  };
197
15
  //# sourceMappingURL=HeadContent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HeadContent.js","sources":["../../src/HeadContent.tsx"],"sourcesContent":["import * as React from 'react'\nimport { buildDevStylesUrl, escapeHtml } from '@tanstack/router-core'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport { useRouterState } from './useRouterState'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\n/**\n * Build the list of head/link/meta/script tags to render for active matches.\n * Used internally by `HeadContent`.\n */\nexport const useTags = () => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n const routeMeta = useRouterState({\n select: (state) => {\n return state.matches.map((match) => match.meta!).filter(Boolean)\n },\n })\n\n const meta: Array<RouterManagedTag> = React.useMemo(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n // Handle JSON-LD structured data\n // Content is HTML-escaped to prevent XSS when injected via dangerouslySetInnerHTML\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n return resultMeta\n }, [routeMeta, nonce])\n\n const links = useRouterState({\n select: (state) => {\n const constructed = state.matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n\n // These are the assets extracted from the ViteManifest\n // using the `startManifestPlugin`\n const assets = state.matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n return [...constructed, ...assets]\n },\n structuralSharing: true as any,\n })\n\n const preloadLinks = useRouterState({\n select: (state) => {\n const preloadLinks: Array<RouterManagedTag> = []\n\n state.matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preload,\n nonce,\n },\n })\n }),\n )\n\n return preloadLinks\n },\n structuralSharing: true as any,\n })\n\n const styles = useRouterState({\n select: (state) =>\n (\n state.matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs,\n children,\n nonce,\n })),\n structuralSharing: true as any,\n })\n\n const headScripts: Array<RouterManagedTag> = useRouterState({\n select: (state) =>\n (\n state.matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n structuralSharing: true as any,\n })\n\n return uniqBy(\n [\n ...meta,\n ...preloadLinks,\n ...links,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\n/**\n * Renders a stylesheet link for dev mode CSS collection.\n * On the server, renders the full link with route-scoped CSS URL.\n * On the client, renders the same link to avoid hydration mismatch,\n * then removes it after hydration since Vite's HMR handles CSS updates.\n */\nfunction DevStylesLink() {\n const router = useRouter()\n const routeIds = useRouterState({\n select: (state) => state.matches.map((match) => match.routeId),\n })\n\n React.useEffect(() => {\n // After hydration, remove the SSR-rendered dev styles link\n document\n .querySelectorAll('[data-tanstack-start-dev-styles]')\n .forEach((el) => el.remove())\n }, [])\n\n const href = buildDevStylesUrl(router.basepath, routeIds)\n\n return (\n <link\n rel=\"stylesheet\"\n href={href}\n data-tanstack-start-dev-styles\n suppressHydrationWarning\n />\n )\n}\n\n/**\n * Render route-managed head tags (title, meta, links, styles, head scripts).\n * Place inside the document head of your app shell.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management\n */\nexport function HeadContent() {\n const tags = useTags()\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n return (\n <>\n {process.env.NODE_ENV !== 'production' && <DevStylesLink />}\n {tags.map((tag) => (\n <Asset {...tag} key={`tsr-meta-${JSON.stringify(tag)}`} nonce={nonce} />\n ))}\n </>\n )\n}\n\nfunction uniqBy<T>(arr: Array<T>, fn: (item: T) => string) {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = fn(item)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n"],"names":["preloadLinks"],"mappings":"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"}
1
+ {"version":3,"file":"HeadContent.js","sources":["../../src/HeadContent.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport { useTags } from './headContentUtils'\n\n/**\n * Render route-managed head tags (title, meta, links, styles, head scripts).\n * Place inside the document head of your app shell.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management\n */\nexport function HeadContent() {\n const tags = useTags()\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n return (\n <>\n {tags.map((tag) => (\n <Asset {...tag} key={`tsr-meta-${JSON.stringify(tag)}`} nonce={nonce} />\n ))}\n </>\n )\n}\n"],"names":[],"mappings":";;;;;AAUO,SAAS,cAAc;AAC5B,QAAM,OAAO,QAAA;AACb,QAAM,SAAS,UAAA;AACf,QAAM,QAAQ,OAAO,QAAQ,KAAK;AAClC,yCAEK,UAAA,KAAK,IAAI,CAAC,QACT,8BAAC,SAAO,GAAG,KAAK,KAAK,YAAY,KAAK,UAAU,GAAG,CAAC,IAAI,OAAc,CACvE,GACH;AAEJ;"}
@@ -0,0 +1,7 @@
1
+ import { RouterManagedTag } from '@tanstack/router-core';
2
+ /**
3
+ * Build the list of head/link/meta/script tags to render for active matches.
4
+ * Used internally by `HeadContent`.
5
+ */
6
+ export declare const useTags: () => RouterManagedTag[];
7
+ export declare function uniqBy<T>(arr: Array<T>, fn: (item: T) => string): T[];