@tanstack/react-router 1.160.0 → 1.160.2
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 +33 -19
- package/dist/cjs/Asset.cjs.map +1 -1
- package/dist/esm/Asset.js +33 -19
- package/dist/esm/Asset.js.map +1 -1
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +2821 -253
- package/dist/llms/rules/installation.d.ts +1 -1
- package/dist/llms/rules/installation.js +376 -357
- package/dist/llms/rules/routing.d.ts +1 -1
- package/dist/llms/rules/routing.js +436 -31
- package/dist/llms/rules/setup-and-architecture.d.ts +1 -1
- package/dist/llms/rules/setup-and-architecture.js +253 -90
- package/package.json +1 -1
- package/src/Asset.tsx +45 -17
package/dist/cjs/Asset.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const isServer = require("@tanstack/router-core/isServer");
|
|
6
6
|
const useRouter = require("./useRouter.cjs");
|
|
7
|
+
const ClientOnly = require("./ClientOnly.cjs");
|
|
7
8
|
function _interopNamespaceDefault(e) {
|
|
8
9
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
9
10
|
if (e) {
|
|
@@ -54,7 +55,13 @@ function Script({
|
|
|
54
55
|
children
|
|
55
56
|
}) {
|
|
56
57
|
const router = useRouter.useRouter();
|
|
58
|
+
const hydrated = ClientOnly.useHydrated();
|
|
57
59
|
const dataScript = typeof attrs?.type === "string" && attrs.type !== "" && attrs.type !== "text/javascript" && attrs.type !== "module";
|
|
60
|
+
if (process.env.NODE_ENV !== "production" && attrs?.src && typeof children === "string" && children.trim().length) {
|
|
61
|
+
console.warn(
|
|
62
|
+
"[TanStack Router] <Script> received both `src` and `children`. The `children` content will be ignored. Remove `children` or remove `src`."
|
|
63
|
+
);
|
|
64
|
+
}
|
|
58
65
|
React__namespace.useEffect(() => {
|
|
59
66
|
if (dataScript) return;
|
|
60
67
|
if (attrs?.src) {
|
|
@@ -123,40 +130,47 @@ function Script({
|
|
|
123
130
|
}
|
|
124
131
|
return void 0;
|
|
125
132
|
}, [attrs, children, dataScript]);
|
|
126
|
-
if (
|
|
127
|
-
if (
|
|
133
|
+
if (isServer.isServer ?? router.isServer) {
|
|
134
|
+
if (attrs?.src) {
|
|
135
|
+
return /* @__PURE__ */ jsxRuntime.jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
136
|
+
}
|
|
137
|
+
if (typeof children === "string") {
|
|
128
138
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
129
139
|
"script",
|
|
130
140
|
{
|
|
131
141
|
...attrs,
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
dangerouslySetInnerHTML: { __html: children },
|
|
143
|
+
suppressHydrationWarning: true
|
|
134
144
|
}
|
|
135
145
|
);
|
|
136
146
|
}
|
|
137
|
-
|
|
138
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
139
|
-
"script",
|
|
140
|
-
{
|
|
141
|
-
suppressHydrationWarning: true,
|
|
142
|
-
dangerouslySetInnerHTML: { __html: "" },
|
|
143
|
-
...rest
|
|
144
|
-
}
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
if (attrs?.src && typeof attrs.src === "string") {
|
|
148
|
-
return /* @__PURE__ */ jsxRuntime.jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
147
|
+
return null;
|
|
149
148
|
}
|
|
150
|
-
if (typeof children === "string") {
|
|
149
|
+
if (dataScript && typeof children === "string") {
|
|
151
150
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
152
151
|
"script",
|
|
153
152
|
{
|
|
154
153
|
...attrs,
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
suppressHydrationWarning: true,
|
|
155
|
+
dangerouslySetInnerHTML: { __html: children }
|
|
157
156
|
}
|
|
158
157
|
);
|
|
159
158
|
}
|
|
159
|
+
if (!hydrated) {
|
|
160
|
+
if (attrs?.src) {
|
|
161
|
+
return /* @__PURE__ */ jsxRuntime.jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
162
|
+
}
|
|
163
|
+
if (typeof children === "string") {
|
|
164
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
165
|
+
"script",
|
|
166
|
+
{
|
|
167
|
+
...attrs,
|
|
168
|
+
dangerouslySetInnerHTML: { __html: children },
|
|
169
|
+
suppressHydrationWarning: true
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
160
174
|
return null;
|
|
161
175
|
}
|
|
162
176
|
exports.Asset = Asset;
|
package/dist/cjs/Asset.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Asset.cjs","sources":["../../src/Asset.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\ninterface ScriptAttrs {\n [key: string]: string | boolean | undefined\n src?: string\n suppressHydrationWarning?: boolean\n}\n\nexport function Asset({\n tag,\n attrs,\n children,\n nonce,\n}: RouterManagedTag & { nonce?: string }): React.ReactElement | null {\n switch (tag) {\n case 'title':\n return (\n <title {...attrs} suppressHydrationWarning>\n {children}\n </title>\n )\n case 'meta':\n return <meta {...attrs} suppressHydrationWarning />\n case 'link':\n return <link {...attrs} nonce={nonce} suppressHydrationWarning />\n case 'style':\n return (\n <style\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children as string }}\n nonce={nonce}\n />\n )\n case 'script':\n return <Script attrs={attrs}>{children}</Script>\n default:\n return null\n }\n}\n\nfunction Script({\n attrs,\n children,\n}: {\n attrs?: ScriptAttrs\n children?: string\n}) {\n const router = useRouter()\n const dataScript =\n typeof attrs?.type === 'string' &&\n attrs.type !== '' &&\n attrs.type !== 'text/javascript' &&\n attrs.type !== 'module'\n\n React.useEffect(() => {\n if (dataScript) return\n\n if (attrs?.src) {\n const normSrc = (() => {\n try {\n const base = document.baseURI || window.location.href\n return new URL(attrs.src, base).href\n } catch {\n return attrs.src\n }\n })()\n const existingScript = Array.from(\n document.querySelectorAll('script[src]'),\n ).find((el) => (el as HTMLScriptElement).src === normSrc)\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n if (typeof children === 'string') {\n const typeAttr =\n typeof attrs?.type === 'string' ? attrs.type : 'text/javascript'\n const nonceAttr =\n typeof attrs?.nonce === 'string' ? attrs.nonce : undefined\n const existingScript = Array.from(\n document.querySelectorAll('script:not([src])'),\n ).find((el) => {\n if (!(el instanceof HTMLScriptElement)) return false\n const sType = el.getAttribute('type') ?? 'text/javascript'\n const sNonce = el.getAttribute('nonce') ?? undefined\n return (\n el.textContent === children &&\n sType === typeAttr &&\n sNonce === nonceAttr\n )\n })\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n script.textContent = children\n\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n return undefined\n }, [attrs, children, dataScript])\n\n if (
|
|
1
|
+
{"version":3,"file":"Asset.cjs","sources":["../../src/Asset.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport { useHydrated } from './ClientOnly'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\ninterface ScriptAttrs {\n [key: string]: string | boolean | undefined\n src?: string\n suppressHydrationWarning?: boolean\n}\n\nexport function Asset({\n tag,\n attrs,\n children,\n nonce,\n}: RouterManagedTag & { nonce?: string }): React.ReactElement | null {\n switch (tag) {\n case 'title':\n return (\n <title {...attrs} suppressHydrationWarning>\n {children}\n </title>\n )\n case 'meta':\n return <meta {...attrs} suppressHydrationWarning />\n case 'link':\n return <link {...attrs} nonce={nonce} suppressHydrationWarning />\n case 'style':\n return (\n <style\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children as string }}\n nonce={nonce}\n />\n )\n case 'script':\n return <Script attrs={attrs}>{children}</Script>\n default:\n return null\n }\n}\n\nfunction Script({\n attrs,\n children,\n}: {\n attrs?: ScriptAttrs\n children?: string\n}) {\n const router = useRouter()\n const hydrated = useHydrated()\n const dataScript =\n typeof attrs?.type === 'string' &&\n attrs.type !== '' &&\n attrs.type !== 'text/javascript' &&\n attrs.type !== 'module'\n\n if (\n process.env.NODE_ENV !== 'production' &&\n attrs?.src &&\n typeof children === 'string' &&\n children.trim().length\n ) {\n console.warn(\n '[TanStack Router] <Script> received both `src` and `children`. The `children` content will be ignored. Remove `children` or remove `src`.',\n )\n }\n\n React.useEffect(() => {\n if (dataScript) return\n\n if (attrs?.src) {\n const normSrc = (() => {\n try {\n const base = document.baseURI || window.location.href\n return new URL(attrs.src, base).href\n } catch {\n return attrs.src\n }\n })()\n const existingScript = Array.from(\n document.querySelectorAll('script[src]'),\n ).find((el) => (el as HTMLScriptElement).src === normSrc)\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n if (typeof children === 'string') {\n const typeAttr =\n typeof attrs?.type === 'string' ? attrs.type : 'text/javascript'\n const nonceAttr =\n typeof attrs?.nonce === 'string' ? attrs.nonce : undefined\n const existingScript = Array.from(\n document.querySelectorAll('script:not([src])'),\n ).find((el) => {\n if (!(el instanceof HTMLScriptElement)) return false\n const sType = el.getAttribute('type') ?? 'text/javascript'\n const sNonce = el.getAttribute('nonce') ?? undefined\n return (\n el.textContent === children &&\n sType === typeAttr &&\n sNonce === nonceAttr\n )\n })\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n script.textContent = children\n\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n return undefined\n }, [attrs, children, dataScript])\n\n // --- Server rendering ---\n if (isServer ?? router.isServer) {\n if (attrs?.src) {\n return <script {...attrs} suppressHydrationWarning />\n }\n\n if (typeof children === 'string') {\n return (\n <script\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children }}\n suppressHydrationWarning\n />\n )\n }\n\n return null\n }\n\n // --- Client rendering ---\n\n // Data scripts (e.g. application/ld+json) are rendered in the tree;\n // the useEffect intentionally skips them.\n if (dataScript && typeof children === 'string') {\n return (\n <script\n {...attrs}\n suppressHydrationWarning\n dangerouslySetInnerHTML={{ __html: children }}\n />\n )\n }\n\n // During hydration (before useEffect has fired), render the script element\n // to match the server-rendered HTML and avoid structural hydration mismatches.\n // After hydration, return null — the useEffect handles imperative injection.\n if (!hydrated) {\n if (attrs?.src) {\n return <script {...attrs} suppressHydrationWarning />\n }\n if (typeof children === 'string') {\n return (\n <script\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children }}\n suppressHydrationWarning\n />\n )\n }\n }\n\n return null\n}\n"],"names":["jsx","useRouter","useHydrated","React","isServer"],"mappings":"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"}
|
package/dist/esm/Asset.js
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { isServer } from "@tanstack/router-core/isServer";
|
|
4
4
|
import { useRouter } from "./useRouter.js";
|
|
5
|
+
import { useHydrated } from "./ClientOnly.js";
|
|
5
6
|
function Asset({
|
|
6
7
|
tag,
|
|
7
8
|
attrs,
|
|
@@ -35,7 +36,13 @@ function Script({
|
|
|
35
36
|
children
|
|
36
37
|
}) {
|
|
37
38
|
const router = useRouter();
|
|
39
|
+
const hydrated = useHydrated();
|
|
38
40
|
const dataScript = typeof attrs?.type === "string" && attrs.type !== "" && attrs.type !== "text/javascript" && attrs.type !== "module";
|
|
41
|
+
if (process.env.NODE_ENV !== "production" && attrs?.src && typeof children === "string" && children.trim().length) {
|
|
42
|
+
console.warn(
|
|
43
|
+
"[TanStack Router] <Script> received both `src` and `children`. The `children` content will be ignored. Remove `children` or remove `src`."
|
|
44
|
+
);
|
|
45
|
+
}
|
|
39
46
|
React.useEffect(() => {
|
|
40
47
|
if (dataScript) return;
|
|
41
48
|
if (attrs?.src) {
|
|
@@ -104,40 +111,47 @@ function Script({
|
|
|
104
111
|
}
|
|
105
112
|
return void 0;
|
|
106
113
|
}, [attrs, children, dataScript]);
|
|
107
|
-
if (
|
|
108
|
-
if (
|
|
114
|
+
if (isServer ?? router.isServer) {
|
|
115
|
+
if (attrs?.src) {
|
|
116
|
+
return /* @__PURE__ */ jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
117
|
+
}
|
|
118
|
+
if (typeof children === "string") {
|
|
109
119
|
return /* @__PURE__ */ jsx(
|
|
110
120
|
"script",
|
|
111
121
|
{
|
|
112
122
|
...attrs,
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
dangerouslySetInnerHTML: { __html: children },
|
|
124
|
+
suppressHydrationWarning: true
|
|
115
125
|
}
|
|
116
126
|
);
|
|
117
127
|
}
|
|
118
|
-
|
|
119
|
-
return /* @__PURE__ */ jsx(
|
|
120
|
-
"script",
|
|
121
|
-
{
|
|
122
|
-
suppressHydrationWarning: true,
|
|
123
|
-
dangerouslySetInnerHTML: { __html: "" },
|
|
124
|
-
...rest
|
|
125
|
-
}
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
if (attrs?.src && typeof attrs.src === "string") {
|
|
129
|
-
return /* @__PURE__ */ jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
128
|
+
return null;
|
|
130
129
|
}
|
|
131
|
-
if (typeof children === "string") {
|
|
130
|
+
if (dataScript && typeof children === "string") {
|
|
132
131
|
return /* @__PURE__ */ jsx(
|
|
133
132
|
"script",
|
|
134
133
|
{
|
|
135
134
|
...attrs,
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
suppressHydrationWarning: true,
|
|
136
|
+
dangerouslySetInnerHTML: { __html: children }
|
|
138
137
|
}
|
|
139
138
|
);
|
|
140
139
|
}
|
|
140
|
+
if (!hydrated) {
|
|
141
|
+
if (attrs?.src) {
|
|
142
|
+
return /* @__PURE__ */ jsx("script", { ...attrs, suppressHydrationWarning: true });
|
|
143
|
+
}
|
|
144
|
+
if (typeof children === "string") {
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
146
|
+
"script",
|
|
147
|
+
{
|
|
148
|
+
...attrs,
|
|
149
|
+
dangerouslySetInnerHTML: { __html: children },
|
|
150
|
+
suppressHydrationWarning: true
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
141
155
|
return null;
|
|
142
156
|
}
|
|
143
157
|
export {
|
package/dist/esm/Asset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Asset.js","sources":["../../src/Asset.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\ninterface ScriptAttrs {\n [key: string]: string | boolean | undefined\n src?: string\n suppressHydrationWarning?: boolean\n}\n\nexport function Asset({\n tag,\n attrs,\n children,\n nonce,\n}: RouterManagedTag & { nonce?: string }): React.ReactElement | null {\n switch (tag) {\n case 'title':\n return (\n <title {...attrs} suppressHydrationWarning>\n {children}\n </title>\n )\n case 'meta':\n return <meta {...attrs} suppressHydrationWarning />\n case 'link':\n return <link {...attrs} nonce={nonce} suppressHydrationWarning />\n case 'style':\n return (\n <style\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children as string }}\n nonce={nonce}\n />\n )\n case 'script':\n return <Script attrs={attrs}>{children}</Script>\n default:\n return null\n }\n}\n\nfunction Script({\n attrs,\n children,\n}: {\n attrs?: ScriptAttrs\n children?: string\n}) {\n const router = useRouter()\n const dataScript =\n typeof attrs?.type === 'string' &&\n attrs.type !== '' &&\n attrs.type !== 'text/javascript' &&\n attrs.type !== 'module'\n\n React.useEffect(() => {\n if (dataScript) return\n\n if (attrs?.src) {\n const normSrc = (() => {\n try {\n const base = document.baseURI || window.location.href\n return new URL(attrs.src, base).href\n } catch {\n return attrs.src\n }\n })()\n const existingScript = Array.from(\n document.querySelectorAll('script[src]'),\n ).find((el) => (el as HTMLScriptElement).src === normSrc)\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n if (typeof children === 'string') {\n const typeAttr =\n typeof attrs?.type === 'string' ? attrs.type : 'text/javascript'\n const nonceAttr =\n typeof attrs?.nonce === 'string' ? attrs.nonce : undefined\n const existingScript = Array.from(\n document.querySelectorAll('script:not([src])'),\n ).find((el) => {\n if (!(el instanceof HTMLScriptElement)) return false\n const sType = el.getAttribute('type') ?? 'text/javascript'\n const sNonce = el.getAttribute('nonce') ?? undefined\n return (\n el.textContent === children &&\n sType === typeAttr &&\n sNonce === nonceAttr\n )\n })\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n script.textContent = children\n\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n return undefined\n }, [attrs, children, dataScript])\n\n if (
|
|
1
|
+
{"version":3,"file":"Asset.js","sources":["../../src/Asset.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport { useHydrated } from './ClientOnly'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\ninterface ScriptAttrs {\n [key: string]: string | boolean | undefined\n src?: string\n suppressHydrationWarning?: boolean\n}\n\nexport function Asset({\n tag,\n attrs,\n children,\n nonce,\n}: RouterManagedTag & { nonce?: string }): React.ReactElement | null {\n switch (tag) {\n case 'title':\n return (\n <title {...attrs} suppressHydrationWarning>\n {children}\n </title>\n )\n case 'meta':\n return <meta {...attrs} suppressHydrationWarning />\n case 'link':\n return <link {...attrs} nonce={nonce} suppressHydrationWarning />\n case 'style':\n return (\n <style\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children as string }}\n nonce={nonce}\n />\n )\n case 'script':\n return <Script attrs={attrs}>{children}</Script>\n default:\n return null\n }\n}\n\nfunction Script({\n attrs,\n children,\n}: {\n attrs?: ScriptAttrs\n children?: string\n}) {\n const router = useRouter()\n const hydrated = useHydrated()\n const dataScript =\n typeof attrs?.type === 'string' &&\n attrs.type !== '' &&\n attrs.type !== 'text/javascript' &&\n attrs.type !== 'module'\n\n if (\n process.env.NODE_ENV !== 'production' &&\n attrs?.src &&\n typeof children === 'string' &&\n children.trim().length\n ) {\n console.warn(\n '[TanStack Router] <Script> received both `src` and `children`. The `children` content will be ignored. Remove `children` or remove `src`.',\n )\n }\n\n React.useEffect(() => {\n if (dataScript) return\n\n if (attrs?.src) {\n const normSrc = (() => {\n try {\n const base = document.baseURI || window.location.href\n return new URL(attrs.src, base).href\n } catch {\n return attrs.src\n }\n })()\n const existingScript = Array.from(\n document.querySelectorAll('script[src]'),\n ).find((el) => (el as HTMLScriptElement).src === normSrc)\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n if (typeof children === 'string') {\n const typeAttr =\n typeof attrs?.type === 'string' ? attrs.type : 'text/javascript'\n const nonceAttr =\n typeof attrs?.nonce === 'string' ? attrs.nonce : undefined\n const existingScript = Array.from(\n document.querySelectorAll('script:not([src])'),\n ).find((el) => {\n if (!(el instanceof HTMLScriptElement)) return false\n const sType = el.getAttribute('type') ?? 'text/javascript'\n const sNonce = el.getAttribute('nonce') ?? undefined\n return (\n el.textContent === children &&\n sType === typeAttr &&\n sNonce === nonceAttr\n )\n })\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n script.textContent = children\n\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (\n key !== 'suppressHydrationWarning' &&\n value !== undefined &&\n value !== false\n ) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n }\n\n document.head.appendChild(script)\n\n return () => {\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }\n\n return undefined\n }, [attrs, children, dataScript])\n\n // --- Server rendering ---\n if (isServer ?? router.isServer) {\n if (attrs?.src) {\n return <script {...attrs} suppressHydrationWarning />\n }\n\n if (typeof children === 'string') {\n return (\n <script\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children }}\n suppressHydrationWarning\n />\n )\n }\n\n return null\n }\n\n // --- Client rendering ---\n\n // Data scripts (e.g. application/ld+json) are rendered in the tree;\n // the useEffect intentionally skips them.\n if (dataScript && typeof children === 'string') {\n return (\n <script\n {...attrs}\n suppressHydrationWarning\n dangerouslySetInnerHTML={{ __html: children }}\n />\n )\n }\n\n // During hydration (before useEffect has fired), render the script element\n // to match the server-rendered HTML and avoid structural hydration mismatches.\n // After hydration, return null — the useEffect handles imperative injection.\n if (!hydrated) {\n if (attrs?.src) {\n return <script {...attrs} suppressHydrationWarning />\n }\n if (typeof children === 'string') {\n return (\n <script\n {...attrs}\n dangerouslySetInnerHTML={{ __html: children }}\n suppressHydrationWarning\n />\n )\n }\n }\n\n return null\n}\n"],"names":[],"mappings":"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"}
|