@tanstack/vue-router 1.146.2 → 1.147.1
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/esm/HeadContent.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import * as Vue from "vue";
|
|
2
|
-
import { escapeHtml } from "@tanstack/router-core";
|
|
2
|
+
import { escapeHtml, buildDevStylesUrl } from "@tanstack/router-core";
|
|
3
3
|
import { Asset } from "./Asset.js";
|
|
4
4
|
import { useRouter } from "./useRouter.js";
|
|
5
5
|
import { useRouterState } from "./useRouterState.js";
|
|
6
|
+
const DevStylesLink = Vue.defineComponent({
|
|
7
|
+
name: "DevStylesLink",
|
|
8
|
+
setup() {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const routeIds = useRouterState({
|
|
11
|
+
select: (state) => state.matches.map((match) => match.routeId)
|
|
12
|
+
});
|
|
13
|
+
Vue.onMounted(() => {
|
|
14
|
+
document.querySelectorAll("[data-tanstack-start-dev-styles]").forEach((el) => el.remove());
|
|
15
|
+
});
|
|
16
|
+
const href = Vue.computed(() => buildDevStylesUrl(router.basepath, routeIds.value));
|
|
17
|
+
return () => Vue.h("link", {
|
|
18
|
+
rel: "stylesheet",
|
|
19
|
+
href: href.value,
|
|
20
|
+
"data-tanstack-start-dev-styles": true
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
6
24
|
const useTags = () => {
|
|
7
25
|
const router = useRouter();
|
|
8
26
|
const routeMeta = useRouterState({
|
|
@@ -104,10 +122,14 @@ const HeadContent = Vue.defineComponent({
|
|
|
104
122
|
setup() {
|
|
105
123
|
const tags = useTags();
|
|
106
124
|
return () => {
|
|
107
|
-
|
|
125
|
+
const children = tags().map((tag) => Vue.h(Asset, {
|
|
108
126
|
...tag,
|
|
109
127
|
key: `tsr-meta-${JSON.stringify(tag)}`
|
|
110
128
|
}));
|
|
129
|
+
if (process.env.NODE_ENV !== "production") {
|
|
130
|
+
return [Vue.h(DevStylesLink), ...children];
|
|
131
|
+
}
|
|
132
|
+
return children;
|
|
111
133
|
};
|
|
112
134
|
}
|
|
113
135
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadContent.js","sources":["../../src/HeadContent.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\nimport { 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\nexport const useTags = () => {\n const router = useRouter()\n\n const routeMeta = useRouterState({\n select: (state) => {\n return state.matches.map((match) => match.meta!).filter(Boolean)\n },\n })\n\n const meta: Vue.Ref<Array<RouterManagedTag>> = Vue.computed(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n ;[...routeMeta.value].reverse().forEach((metas) => {\n ;[...metas].reverse().forEach((m) => {\n if (!m) return\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 innerHTML\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 return\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n },\n })\n }\n })\n })\n\n if (title) {\n resultMeta.push(title)\n }\n\n resultMeta.reverse()\n\n return resultMeta\n })\n\n const links = useRouterState({\n select: (state) =>\n state.matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n },\n })) as Array<RouterManagedTag>,\n })\n\n const preloadMeta = useRouterState({\n select: (state) => {\n const preloadMeta: 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 preloadMeta.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preload,\n },\n })\n }),\n )\n\n return preloadMeta\n },\n })\n\n const headScripts = 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 },\n children,\n })),\n })\n\n return () =>\n uniqBy(\n [\n ...meta.value,\n ...preloadMeta.value,\n ...links.value,\n ...headScripts.value,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\n/**\n * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.\n * It should be rendered in the `<head>` of your document.\n */\nexport const HeadContent = Vue.defineComponent({\n name: 'HeadContent',\n setup() {\n const tags = useTags()\n\n return () => {\n
|
|
1
|
+
{"version":3,"file":"HeadContent.js","sources":["../../src/HeadContent.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\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 * 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 */\nconst DevStylesLink = Vue.defineComponent({\n name: 'DevStylesLink',\n setup() {\n const router = useRouter()\n const routeIds = useRouterState({\n select: (state) => state.matches.map((match) => match.routeId),\n })\n\n Vue.onMounted(() => {\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 = Vue.computed(() =>\n buildDevStylesUrl(router.basepath, routeIds.value),\n )\n\n return () =>\n Vue.h('link', {\n rel: 'stylesheet',\n href: href.value,\n 'data-tanstack-start-dev-styles': true,\n })\n },\n})\n\nexport const useTags = () => {\n const router = useRouter()\n\n const routeMeta = useRouterState({\n select: (state) => {\n return state.matches.map((match) => match.meta!).filter(Boolean)\n },\n })\n\n const meta: Vue.Ref<Array<RouterManagedTag>> = Vue.computed(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n ;[...routeMeta.value].reverse().forEach((metas) => {\n ;[...metas].reverse().forEach((m) => {\n if (!m) return\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 innerHTML\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 return\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n },\n })\n }\n })\n })\n\n if (title) {\n resultMeta.push(title)\n }\n\n resultMeta.reverse()\n\n return resultMeta\n })\n\n const links = useRouterState({\n select: (state) =>\n state.matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n },\n })) as Array<RouterManagedTag>,\n })\n\n const preloadMeta = useRouterState({\n select: (state) => {\n const preloadMeta: 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 preloadMeta.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preload,\n },\n })\n }),\n )\n\n return preloadMeta\n },\n })\n\n const headScripts = 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 },\n children,\n })),\n })\n\n return () =>\n uniqBy(\n [\n ...meta.value,\n ...preloadMeta.value,\n ...links.value,\n ...headScripts.value,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\n/**\n * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.\n * It should be rendered in the `<head>` of your document.\n */\nexport const HeadContent = Vue.defineComponent({\n name: 'HeadContent',\n setup() {\n const tags = useTags()\n\n return () => {\n const children = tags().map((tag) =>\n Vue.h(Asset, {\n ...tag,\n key: `tsr-meta-${JSON.stringify(tag)}`,\n }),\n )\n\n // In dev mode, prepend the DevStylesLink\n if (process.env.NODE_ENV !== 'production') {\n return [Vue.h(DevStylesLink), ...children]\n }\n\n return children\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":["DevStylesLink","Vue","defineComponent","name","setup","router","useRouter","routeIds","useRouterState","select","state","matches","map","match","routeId","onMounted","document","querySelectorAll","forEach","el","remove","href","computed","buildDevStylesUrl","basepath","value","h","rel","useTags","routeMeta","meta","filter","Boolean","resultMeta","metaByAttribute","title","reverse","metas","m","tag","children","json","JSON","stringify","push","attrs","type","escapeHtml","attribute","property","links","flat","link","preloadMeta","looseRoutesById","route","ssr","manifest","routes","id","preloads","preload","headScripts","script","uniqBy","d","HeadContent","tags","Asset","key","process","env","NODE_ENV","arr","fn","seen","Set","item","has","add"],"mappings":"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"}
|
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
import * as Vue from 'vue';
|
|
2
|
-
import { escapeHtml } from '@tanstack/router-core';
|
|
2
|
+
import { buildDevStylesUrl, escapeHtml } from '@tanstack/router-core';
|
|
3
3
|
import { Asset } from './Asset';
|
|
4
4
|
import { useRouter } from './useRouter';
|
|
5
5
|
import { useRouterState } from './useRouterState';
|
|
6
|
+
/**
|
|
7
|
+
* Renders a stylesheet link for dev mode CSS collection.
|
|
8
|
+
* On the server, renders the full link with route-scoped CSS URL.
|
|
9
|
+
* On the client, renders the same link to avoid hydration mismatch,
|
|
10
|
+
* then removes it after hydration since Vite's HMR handles CSS updates.
|
|
11
|
+
*/
|
|
12
|
+
const DevStylesLink = Vue.defineComponent({
|
|
13
|
+
name: 'DevStylesLink',
|
|
14
|
+
setup() {
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const routeIds = useRouterState({
|
|
17
|
+
select: (state) => state.matches.map((match) => match.routeId),
|
|
18
|
+
});
|
|
19
|
+
Vue.onMounted(() => {
|
|
20
|
+
// After hydration, remove the SSR-rendered dev styles link
|
|
21
|
+
document
|
|
22
|
+
.querySelectorAll('[data-tanstack-start-dev-styles]')
|
|
23
|
+
.forEach((el) => el.remove());
|
|
24
|
+
});
|
|
25
|
+
const href = Vue.computed(() => buildDevStylesUrl(router.basepath, routeIds.value));
|
|
26
|
+
return () => Vue.h('link', {
|
|
27
|
+
rel: 'stylesheet',
|
|
28
|
+
href: href.value,
|
|
29
|
+
'data-tanstack-start-dev-styles': true,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
});
|
|
6
33
|
export const useTags = () => {
|
|
7
34
|
const router = useRouter();
|
|
8
35
|
const routeMeta = useRouterState({
|
|
@@ -130,10 +157,15 @@ export const HeadContent = Vue.defineComponent({
|
|
|
130
157
|
setup() {
|
|
131
158
|
const tags = useTags();
|
|
132
159
|
return () => {
|
|
133
|
-
|
|
160
|
+
const children = tags().map((tag) => Vue.h(Asset, {
|
|
134
161
|
...tag,
|
|
135
162
|
key: `tsr-meta-${JSON.stringify(tag)}`,
|
|
136
163
|
}));
|
|
164
|
+
// In dev mode, prepend the DevStylesLink
|
|
165
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
166
|
+
return [Vue.h(DevStylesLink), ...children];
|
|
167
|
+
}
|
|
168
|
+
return children;
|
|
137
169
|
};
|
|
138
170
|
},
|
|
139
171
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadContent.jsx","sourceRoot":"","sources":["../../src/HeadContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAA;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"HeadContent.jsx","sourceRoot":"","sources":["../../src/HeadContent.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/vue-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.147.1",
|
|
4
4
|
"description": "Modern and scalable routing for Vue applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"tiny-invariant": "^1.3.3",
|
|
64
64
|
"tiny-warning": "^1.0.3",
|
|
65
65
|
"@tanstack/history": "1.145.7",
|
|
66
|
-
"@tanstack/router-core": "1.
|
|
66
|
+
"@tanstack/router-core": "1.147.1"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@testing-library/jest-dom": "^6.6.3",
|
package/src/HeadContent.tsx
CHANGED
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
import * as Vue from 'vue'
|
|
2
2
|
|
|
3
|
-
import { escapeHtml } from '@tanstack/router-core'
|
|
3
|
+
import { buildDevStylesUrl, escapeHtml } from '@tanstack/router-core'
|
|
4
4
|
import { Asset } from './Asset'
|
|
5
5
|
import { useRouter } from './useRouter'
|
|
6
6
|
import { useRouterState } from './useRouterState'
|
|
7
7
|
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Renders a stylesheet link for dev mode CSS collection.
|
|
11
|
+
* On the server, renders the full link with route-scoped CSS URL.
|
|
12
|
+
* On the client, renders the same link to avoid hydration mismatch,
|
|
13
|
+
* then removes it after hydration since Vite's HMR handles CSS updates.
|
|
14
|
+
*/
|
|
15
|
+
const DevStylesLink = Vue.defineComponent({
|
|
16
|
+
name: 'DevStylesLink',
|
|
17
|
+
setup() {
|
|
18
|
+
const router = useRouter()
|
|
19
|
+
const routeIds = useRouterState({
|
|
20
|
+
select: (state) => state.matches.map((match) => match.routeId),
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
Vue.onMounted(() => {
|
|
24
|
+
// After hydration, remove the SSR-rendered dev styles link
|
|
25
|
+
document
|
|
26
|
+
.querySelectorAll('[data-tanstack-start-dev-styles]')
|
|
27
|
+
.forEach((el) => el.remove())
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const href = Vue.computed(() =>
|
|
31
|
+
buildDevStylesUrl(router.basepath, routeIds.value),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return () =>
|
|
35
|
+
Vue.h('link', {
|
|
36
|
+
rel: 'stylesheet',
|
|
37
|
+
href: href.value,
|
|
38
|
+
'data-tanstack-start-dev-styles': true,
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
|
|
9
43
|
export const useTags = () => {
|
|
10
44
|
const router = useRouter()
|
|
11
45
|
|
|
@@ -152,12 +186,19 @@ export const HeadContent = Vue.defineComponent({
|
|
|
152
186
|
const tags = useTags()
|
|
153
187
|
|
|
154
188
|
return () => {
|
|
155
|
-
|
|
189
|
+
const children = tags().map((tag) =>
|
|
156
190
|
Vue.h(Asset, {
|
|
157
191
|
...tag,
|
|
158
192
|
key: `tsr-meta-${JSON.stringify(tag)}`,
|
|
159
193
|
}),
|
|
160
194
|
)
|
|
195
|
+
|
|
196
|
+
// In dev mode, prepend the DevStylesLink
|
|
197
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
198
|
+
return [Vue.h(DevStylesLink), ...children]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return children
|
|
161
202
|
}
|
|
162
203
|
},
|
|
163
204
|
})
|