@tanstack/vue-router 1.147.1 → 1.149.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.
Files changed (41) hide show
  1. package/dist/esm/HeadContent.d.ts +0 -2
  2. package/dist/esm/HeadContent.dev.d.ts +10 -0
  3. package/dist/esm/HeadContent.dev.js +26 -0
  4. package/dist/esm/HeadContent.dev.js.map +1 -0
  5. package/dist/esm/HeadContent.js +3 -135
  6. package/dist/esm/HeadContent.js.map +1 -1
  7. package/dist/esm/headContentUtils.d.ts +3 -0
  8. package/dist/esm/headContentUtils.js +128 -0
  9. package/dist/esm/headContentUtils.js.map +1 -0
  10. package/dist/esm/index.d.ts +1 -0
  11. package/dist/esm/index.dev.d.ts +2 -0
  12. package/dist/esm/index.dev.js +146 -0
  13. package/dist/esm/index.dev.js.map +1 -0
  14. package/dist/esm/index.js +3 -1
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/ssr/RouterServer.js +1 -1
  17. package/dist/esm/ssr/RouterServer.js.map +1 -1
  18. package/dist/source/HeadContent.d.ts +0 -2
  19. package/dist/source/HeadContent.dev.d.ts +10 -0
  20. package/dist/source/HeadContent.dev.jsx +35 -0
  21. package/dist/source/HeadContent.dev.jsx.map +1 -0
  22. package/dist/source/HeadContent.jsx +2 -165
  23. package/dist/source/HeadContent.jsx.map +1 -1
  24. package/dist/source/headContentUtils.d.ts +3 -0
  25. package/dist/source/headContentUtils.jsx +150 -0
  26. package/dist/source/headContentUtils.jsx.map +1 -0
  27. package/dist/source/index.d.ts +1 -0
  28. package/dist/source/index.dev.d.ts +2 -0
  29. package/dist/source/index.dev.jsx +6 -0
  30. package/dist/source/index.dev.jsx.map +1 -0
  31. package/dist/source/index.jsx +1 -0
  32. package/dist/source/index.jsx.map +1 -1
  33. package/dist/source/ssr/RouterServer.jsx +1 -1
  34. package/dist/source/ssr/RouterServer.jsx.map +1 -1
  35. package/package.json +3 -2
  36. package/src/HeadContent.dev.tsx +42 -0
  37. package/src/HeadContent.tsx +2 -194
  38. package/src/headContentUtils.tsx +176 -0
  39. package/src/index.dev.tsx +6 -0
  40. package/src/index.tsx +1 -0
  41. package/src/ssr/RouterServer.tsx +1 -1
@@ -1,6 +1,4 @@
1
- import { RouterManagedTag } from '@tanstack/router-core';
2
1
  import * as Vue from 'vue';
3
- export declare const useTags: () => () => RouterManagedTag[];
4
2
  /**
5
3
  * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
6
4
  * It should be rendered in the `<head>` of your document.
@@ -0,0 +1,10 @@
1
+ import * as Vue from 'vue';
2
+ /**
3
+ * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
4
+ * It should be rendered in the `<head>` of your document.
5
+ *
6
+ * This is the development version that filters out dev styles after hydration.
7
+ */
8
+ export declare const HeadContent: Vue.DefineComponent<{}, () => Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
9
+ [key: string]: any;
10
+ }>[], {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,26 @@
1
+ import * as Vue from "vue";
2
+ import { Asset } from "./Asset.js";
3
+ import { useHydrated } from "./ClientOnly.js";
4
+ import { useTags } from "./headContentUtils.js";
5
+ const DEV_STYLES_ATTR = "data-tanstack-router-dev-styles";
6
+ const HeadContent = Vue.defineComponent({
7
+ name: "HeadContent",
8
+ setup() {
9
+ const tags = useTags();
10
+ const hydrated = useHydrated();
11
+ Vue.onMounted(() => {
12
+ document.querySelectorAll(`link[${DEV_STYLES_ATTR}]`).forEach((el) => el.remove());
13
+ });
14
+ return () => {
15
+ const filteredTags = hydrated.value ? tags().filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR]) : tags();
16
+ return filteredTags.map((tag) => Vue.h(Asset, {
17
+ ...tag,
18
+ key: `tsr-meta-${JSON.stringify(tag)}`
19
+ }));
20
+ };
21
+ }
22
+ });
23
+ export {
24
+ HeadContent
25
+ };
26
+ //# sourceMappingURL=HeadContent.dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeadContent.dev.js","sources":["../../src/HeadContent.dev.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\nimport { Asset } from './Asset'\nimport { useHydrated } from './ClientOnly'\nimport { useTags } from './headContentUtils'\n\nconst DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles'\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 *\n * This is the development version that filters out dev styles after hydration.\n */\nexport const HeadContent = Vue.defineComponent({\n name: 'HeadContent',\n setup() {\n const tags = useTags()\n const hydrated = useHydrated()\n\n // Fallback cleanup for hydration mismatch cases\n Vue.onMounted(() => {\n document\n .querySelectorAll(`link[${DEV_STYLES_ATTR}]`)\n .forEach((el) => el.remove())\n })\n\n return () => {\n // Filter out dev styles after hydration\n const filteredTags = hydrated.value\n ? tags().filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR])\n : tags()\n\n return filteredTags.map((tag) =>\n Vue.h(Asset, {\n ...tag,\n key: `tsr-meta-${JSON.stringify(tag)}`,\n }),\n )\n }\n },\n})\n"],"names":["DEV_STYLES_ATTR","HeadContent","Vue","defineComponent","name","setup","tags","useTags","hydrated","useHydrated","onMounted","document","querySelectorAll","forEach","el","remove","filteredTags","value","filter","tag","attrs","map","h","Asset","key","JSON","stringify"],"mappings":";;;;AAMA,MAAMA,kBAAkB;MAQXC,cAAcC,IAAIC,gBAAgB;AAAA,EAC7CC,MAAM;AAAA,EACNC,QAAQ;AACN,UAAMC,OAAOC,QAAO;AACpB,UAAMC,WAAWC,YAAW;AAG5BP,QAAIQ,UAAU,MAAM;AAClBC,eACGC,iBAAiB,QAAQZ,eAAe,GAAG,EAC3Ca,QAASC,QAAOA,GAAGC,OAAM,CAAE;AAAA,IAChC,CAAC;AAED,WAAO,MAAM;AAEX,YAAMC,eAAeR,SAASS,QAC1BX,KAAI,EAAGY,OAAQC,SAAQ,CAACA,IAAIC,QAAQpB,eAAe,CAAC,IACpDM,KAAI;AAER,aAAOU,aAAaK,IAAKF,SACvBjB,IAAIoB,EAAEC,OAAO;AAAA,QACX,GAAGJ;AAAAA,QACHK,KAAK,YAAYC,KAAKC,UAAUP,GAAG,CAAC;AAAA,MACtC,CAAC,CACH;AAAA,IACF;AAAA,EACF;AACF,CAAC;"}
@@ -1,151 +1,19 @@
1
1
  import * as Vue from "vue";
2
- import { escapeHtml, buildDevStylesUrl } from "@tanstack/router-core";
3
2
  import { Asset } from "./Asset.js";
4
- import { useRouter } from "./useRouter.js";
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
- });
24
- const useTags = () => {
25
- const router = useRouter();
26
- const routeMeta = useRouterState({
27
- select: (state) => {
28
- return state.matches.map((match) => match.meta).filter(Boolean);
29
- }
30
- });
31
- const meta = Vue.computed(() => {
32
- const resultMeta = [];
33
- const metaByAttribute = {};
34
- let title;
35
- [...routeMeta.value].reverse().forEach((metas) => {
36
- [...metas].reverse().forEach((m) => {
37
- if (!m) return;
38
- if (m.title) {
39
- if (!title) {
40
- title = {
41
- tag: "title",
42
- children: m.title
43
- };
44
- }
45
- } else if ("script:ld+json" in m) {
46
- try {
47
- const json = JSON.stringify(m["script:ld+json"]);
48
- resultMeta.push({
49
- tag: "script",
50
- attrs: {
51
- type: "application/ld+json"
52
- },
53
- children: escapeHtml(json)
54
- });
55
- } catch {
56
- }
57
- } else {
58
- const attribute = m.name ?? m.property;
59
- if (attribute) {
60
- if (metaByAttribute[attribute]) {
61
- return;
62
- } else {
63
- metaByAttribute[attribute] = true;
64
- }
65
- }
66
- resultMeta.push({
67
- tag: "meta",
68
- attrs: {
69
- ...m
70
- }
71
- });
72
- }
73
- });
74
- });
75
- if (title) {
76
- resultMeta.push(title);
77
- }
78
- resultMeta.reverse();
79
- return resultMeta;
80
- });
81
- const links = useRouterState({
82
- select: (state) => state.matches.map((match) => match.links).filter(Boolean).flat(1).map((link) => ({
83
- tag: "link",
84
- attrs: {
85
- ...link
86
- }
87
- }))
88
- });
89
- const preloadMeta = useRouterState({
90
- select: (state) => {
91
- const preloadMeta2 = [];
92
- state.matches.map((match) => router.looseRoutesById[match.routeId]).forEach((route) => router.ssr?.manifest?.routes[route.id]?.preloads?.filter(Boolean).forEach((preload) => {
93
- preloadMeta2.push({
94
- tag: "link",
95
- attrs: {
96
- rel: "modulepreload",
97
- href: preload
98
- }
99
- });
100
- }));
101
- return preloadMeta2;
102
- }
103
- });
104
- const headScripts = useRouterState({
105
- select: (state) => state.matches.map((match) => match.headScripts).flat(1).filter(Boolean).map(({
106
- children,
107
- ...script
108
- }) => ({
109
- tag: "script",
110
- attrs: {
111
- ...script
112
- },
113
- children
114
- }))
115
- });
116
- return () => uniqBy([...meta.value, ...preloadMeta.value, ...links.value, ...headScripts.value], (d) => {
117
- return JSON.stringify(d);
118
- });
119
- };
3
+ import { useTags } from "./headContentUtils.js";
120
4
  const HeadContent = Vue.defineComponent({
121
5
  name: "HeadContent",
122
6
  setup() {
123
7
  const tags = useTags();
124
8
  return () => {
125
- const children = tags().map((tag) => Vue.h(Asset, {
9
+ return tags().map((tag) => Vue.h(Asset, {
126
10
  ...tag,
127
11
  key: `tsr-meta-${JSON.stringify(tag)}`
128
12
  }));
129
- if (process.env.NODE_ENV !== "production") {
130
- return [Vue.h(DevStylesLink), ...children];
131
- }
132
- return children;
133
13
  };
134
14
  }
135
15
  });
136
- function uniqBy(arr, fn) {
137
- const seen = /* @__PURE__ */ new Set();
138
- return arr.filter((item) => {
139
- const key = fn(item);
140
- if (seen.has(key)) {
141
- return false;
142
- }
143
- seen.add(key);
144
- return true;
145
- });
146
- }
147
16
  export {
148
- HeadContent,
149
- useTags
17
+ HeadContent
150
18
  };
151
19
  //# sourceMappingURL=HeadContent.js.map
@@ -1 +1 @@
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
+ {"version":3,"file":"HeadContent.js","sources":["../../src/HeadContent.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\nimport { Asset } from './Asset'\nimport { useTags } from './headContentUtils'\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 return tags().map((tag) =>\n Vue.h(Asset, {\n ...tag,\n key: `tsr-meta-${JSON.stringify(tag)}`,\n }),\n )\n }\n },\n})\n"],"names":["HeadContent","Vue","defineComponent","name","setup","tags","useTags","map","tag","h","Asset","key","JSON","stringify"],"mappings":";;;MASaA,cAAcC,IAAIC,gBAAgB;AAAA,EAC7CC,MAAM;AAAA,EACNC,QAAQ;AACN,UAAMC,OAAOC,QAAO;AAEpB,WAAO,MAAM;AACX,aAAOD,KAAI,EAAGE,IAAKC,SACjBP,IAAIQ,EAAEC,OAAO;AAAA,QACX,GAAGF;AAAAA,QACHG,KAAK,YAAYC,KAAKC,UAAUL,GAAG,CAAC;AAAA,MACtC,CAAC,CACH;AAAA,IACF;AAAA,EACF;AACF,CAAC;"}
@@ -0,0 +1,3 @@
1
+ import { RouterManagedTag } from '@tanstack/router-core';
2
+ export declare const useTags: () => () => RouterManagedTag[];
3
+ export declare function uniqBy<T>(arr: Array<T>, fn: (item: T) => string): T[];
@@ -0,0 +1,128 @@
1
+ import * as Vue from "vue";
2
+ import { escapeHtml } from "@tanstack/router-core";
3
+ import { useRouter } from "./useRouter.js";
4
+ import { useRouterState } from "./useRouterState.js";
5
+ const useTags = () => {
6
+ const router = useRouter();
7
+ const routeMeta = useRouterState({
8
+ select: (state) => {
9
+ return state.matches.map((match) => match.meta).filter(Boolean);
10
+ }
11
+ });
12
+ const meta = Vue.computed(() => {
13
+ const resultMeta = [];
14
+ const metaByAttribute = {};
15
+ let title;
16
+ [...routeMeta.value].reverse().forEach((metas) => {
17
+ [...metas].reverse().forEach((m) => {
18
+ if (!m) return;
19
+ if (m.title) {
20
+ if (!title) {
21
+ title = {
22
+ tag: "title",
23
+ children: m.title
24
+ };
25
+ }
26
+ } else if ("script:ld+json" in m) {
27
+ try {
28
+ const json = JSON.stringify(m["script:ld+json"]);
29
+ resultMeta.push({
30
+ tag: "script",
31
+ attrs: {
32
+ type: "application/ld+json"
33
+ },
34
+ children: escapeHtml(json)
35
+ });
36
+ } catch {
37
+ }
38
+ } else {
39
+ const attribute = m.name ?? m.property;
40
+ if (attribute) {
41
+ if (metaByAttribute[attribute]) {
42
+ return;
43
+ } else {
44
+ metaByAttribute[attribute] = true;
45
+ }
46
+ }
47
+ resultMeta.push({
48
+ tag: "meta",
49
+ attrs: {
50
+ ...m
51
+ }
52
+ });
53
+ }
54
+ });
55
+ });
56
+ if (title) {
57
+ resultMeta.push(title);
58
+ }
59
+ resultMeta.reverse();
60
+ return resultMeta;
61
+ });
62
+ const links = useRouterState({
63
+ select: (state) => state.matches.map((match) => match.links).filter(Boolean).flat(1).map((link) => ({
64
+ tag: "link",
65
+ attrs: {
66
+ ...link
67
+ }
68
+ }))
69
+ });
70
+ const preloadMeta = useRouterState({
71
+ select: (state) => {
72
+ const preloadMeta2 = [];
73
+ state.matches.map((match) => router.looseRoutesById[match.routeId]).forEach((route) => router.ssr?.manifest?.routes[route.id]?.preloads?.filter(Boolean).forEach((preload) => {
74
+ preloadMeta2.push({
75
+ tag: "link",
76
+ attrs: {
77
+ rel: "modulepreload",
78
+ href: preload
79
+ }
80
+ });
81
+ }));
82
+ return preloadMeta2;
83
+ }
84
+ });
85
+ const headScripts = useRouterState({
86
+ select: (state) => state.matches.map((match) => match.headScripts).flat(1).filter(Boolean).map(({
87
+ children,
88
+ ...script
89
+ }) => ({
90
+ tag: "script",
91
+ attrs: {
92
+ ...script
93
+ },
94
+ children
95
+ }))
96
+ });
97
+ const manifestAssets = useRouterState({
98
+ select: (state) => {
99
+ const manifest = router.ssr?.manifest;
100
+ const assets = state.matches.map((match) => manifest?.routes[match.routeId]?.assets ?? []).filter(Boolean).flat(1).filter((asset) => asset.tag === "link").map((asset) => ({
101
+ tag: "link",
102
+ attrs: {
103
+ ...asset.attrs
104
+ }
105
+ }));
106
+ return assets;
107
+ }
108
+ });
109
+ return () => uniqBy([...manifestAssets.value, ...meta.value, ...preloadMeta.value, ...links.value, ...headScripts.value], (d) => {
110
+ return JSON.stringify(d);
111
+ });
112
+ };
113
+ function uniqBy(arr, fn) {
114
+ const seen = /* @__PURE__ */ new Set();
115
+ return arr.filter((item) => {
116
+ const key = fn(item);
117
+ if (seen.has(key)) {
118
+ return false;
119
+ }
120
+ seen.add(key);
121
+ return true;
122
+ });
123
+ }
124
+ export {
125
+ uniqBy,
126
+ useTags
127
+ };
128
+ //# sourceMappingURL=headContentUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headContentUtils.js","sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\nimport { escapeHtml } from '@tanstack/router-core'\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 const manifestAssets = useRouterState({\n select: (state) => {\n const manifest = router.ssr?.manifest\n\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: { ...asset.attrs },\n }) satisfies RouterManagedTag,\n )\n\n return assets\n },\n })\n\n return () =>\n uniqBy(\n [\n ...manifestAssets.value,\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\nexport function 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":["useTags","router","useRouter","routeMeta","useRouterState","select","state","matches","map","match","meta","filter","Boolean","Vue","computed","resultMeta","metaByAttribute","title","value","reverse","forEach","metas","m","tag","children","json","JSON","stringify","push","attrs","type","escapeHtml","attribute","name","property","links","flat","link","preloadMeta","looseRoutesById","routeId","route","ssr","manifest","routes","id","preloads","preload","rel","href","headScripts","script","manifestAssets","assets","asset","uniqBy","d","arr","fn","seen","Set","item","key","has","add"],"mappings":"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"}
@@ -46,6 +46,7 @@ export type { ValidateFromPath, ValidateToPath, ValidateSearch, ValidateParams,
46
46
  export { ScriptOnce } from './ScriptOnce.js';
47
47
  export { Asset } from './Asset.js';
48
48
  export { HeadContent } from './HeadContent.js';
49
+ export { useTags } from './headContentUtils.js';
49
50
  export { Scripts } from './Scripts.js';
50
51
  export { Body } from './Body.js';
51
52
  export { Html } from './Html.js';
@@ -0,0 +1,2 @@
1
+ export * from './index.js';
2
+ export { HeadContent } from './HeadContent.dev';
@@ -0,0 +1,146 @@
1
+ import { PathParamError, SearchParamError, TSR_DEFERRED_PROMISE, cleanPath, componentTypes, composeRewrites, createControlledPromise, createRouterConfig, createSerializationAdapter, deepEqual, defaultParseSearch, defaultSerializeError, defaultStringifySearch, defer, functionalUpdate, getInitialRouterState, interpolatePath, isMatch, isNotFound, isPlainArray, isPlainObject, isRedirect, joinPaths, lazyFn, notFound, parseSearchWith, redirect, replaceEqualDeep, resolvePath, retainSearchParams, rootRouteId, stringifySearchWith, stripSearchParams, trimPath, trimPathLeft, trimPathRight } from "@tanstack/router-core";
2
+ import { createBrowserHistory, createHashHistory, createHistory, createMemoryHistory } from "@tanstack/history";
3
+ import { Await, useAwaited } from "./awaited.js";
4
+ import { CatchBoundary, ErrorComponent } from "./CatchBoundary.js";
5
+ import { FileRoute, FileRouteLoader, LazyRoute, createFileRoute, createLazyFileRoute, createLazyRoute } from "./fileRoute.js";
6
+ import { lazyRouteComponent } from "./lazyRouteComponent.js";
7
+ import { Link, createLink, linkOptions, useLinkProps } from "./link.js";
8
+ import { MatchRoute, Matches, useChildMatches, useMatchRoute, useMatches, useParentMatches } from "./Matches.js";
9
+ import { matchContext } from "./matchContext.js";
10
+ import { Match, Outlet } from "./Match.js";
11
+ import { useMatch } from "./useMatch.js";
12
+ import { useLoaderDeps } from "./useLoaderDeps.js";
13
+ import { useLoaderData } from "./useLoaderData.js";
14
+ import { NotFoundRoute, RootRoute, Route, RouteApi, createRootRoute, createRootRouteWithContext, createRoute, createRouteMask, getRouteApi, rootRouteWithContext } from "./route.js";
15
+ import { Router, createRouter } from "./router.js";
16
+ import { RouterContextProvider, RouterProvider } from "./RouterProvider.js";
17
+ import { ScrollRestoration, useElementScrollRestoration } from "./ScrollRestoration.js";
18
+ import { Block, useBlocker } from "./useBlocker.js";
19
+ import { Navigate, useNavigate } from "./useNavigate.js";
20
+ import { useParams } from "./useParams.js";
21
+ import { useSearch } from "./useSearch.js";
22
+ import { getRouterContext } from "./routerContext.js";
23
+ import { useRouteContext } from "./useRouteContext.js";
24
+ import { useRouter } from "./useRouter.js";
25
+ import { useRouterState } from "./useRouterState.js";
26
+ import { useLocation } from "./useLocation.js";
27
+ import { useCanGoBack } from "./useCanGoBack.js";
28
+ import { useLayoutEffect } from "./utils.js";
29
+ import { CatchNotFound, DefaultGlobalNotFound } from "./not-found.js";
30
+ import { ScriptOnce } from "./ScriptOnce.js";
31
+ import { Asset } from "./Asset.js";
32
+ import { useTags } from "./headContentUtils.js";
33
+ import { Scripts } from "./Scripts.js";
34
+ import { Body } from "./Body.js";
35
+ import { Html } from "./Html.js";
36
+ import { ClientOnly } from "./ClientOnly.js";
37
+ import { HeadContent } from "./HeadContent.dev.js";
38
+ export {
39
+ Asset,
40
+ Await,
41
+ Block,
42
+ Body,
43
+ CatchBoundary,
44
+ CatchNotFound,
45
+ ClientOnly,
46
+ DefaultGlobalNotFound,
47
+ ErrorComponent,
48
+ FileRoute,
49
+ FileRouteLoader,
50
+ HeadContent,
51
+ Html,
52
+ LazyRoute,
53
+ Link,
54
+ Match,
55
+ MatchRoute,
56
+ Matches,
57
+ Navigate,
58
+ NotFoundRoute,
59
+ Outlet,
60
+ PathParamError,
61
+ RootRoute,
62
+ Route,
63
+ RouteApi,
64
+ Router,
65
+ RouterContextProvider,
66
+ RouterProvider,
67
+ ScriptOnce,
68
+ Scripts,
69
+ ScrollRestoration,
70
+ SearchParamError,
71
+ TSR_DEFERRED_PROMISE,
72
+ cleanPath,
73
+ componentTypes,
74
+ composeRewrites,
75
+ createBrowserHistory,
76
+ createControlledPromise,
77
+ createFileRoute,
78
+ createHashHistory,
79
+ createHistory,
80
+ createLazyFileRoute,
81
+ createLazyRoute,
82
+ createLink,
83
+ createMemoryHistory,
84
+ createRootRoute,
85
+ createRootRouteWithContext,
86
+ createRoute,
87
+ createRouteMask,
88
+ createRouter,
89
+ createRouterConfig,
90
+ createSerializationAdapter,
91
+ deepEqual,
92
+ defaultParseSearch,
93
+ defaultSerializeError,
94
+ defaultStringifySearch,
95
+ defer,
96
+ functionalUpdate,
97
+ getInitialRouterState,
98
+ getRouteApi,
99
+ getRouterContext,
100
+ interpolatePath,
101
+ isMatch,
102
+ isNotFound,
103
+ isPlainArray,
104
+ isPlainObject,
105
+ isRedirect,
106
+ joinPaths,
107
+ lazyFn,
108
+ lazyRouteComponent,
109
+ linkOptions,
110
+ matchContext,
111
+ notFound,
112
+ parseSearchWith,
113
+ redirect,
114
+ replaceEqualDeep,
115
+ resolvePath,
116
+ retainSearchParams,
117
+ rootRouteId,
118
+ rootRouteWithContext,
119
+ stringifySearchWith,
120
+ stripSearchParams,
121
+ trimPath,
122
+ trimPathLeft,
123
+ trimPathRight,
124
+ useAwaited,
125
+ useBlocker,
126
+ useCanGoBack,
127
+ useChildMatches,
128
+ useElementScrollRestoration,
129
+ useLayoutEffect,
130
+ useLinkProps,
131
+ useLoaderData,
132
+ useLoaderDeps,
133
+ useLocation,
134
+ useMatch,
135
+ useMatchRoute,
136
+ useMatches,
137
+ useNavigate,
138
+ useParams,
139
+ useParentMatches,
140
+ useRouteContext,
141
+ useRouter,
142
+ useRouterState,
143
+ useSearch,
144
+ useTags
145
+ };
146
+ //# sourceMappingURL=index.dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.dev.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/esm/index.js CHANGED
@@ -30,6 +30,7 @@ import { CatchNotFound, DefaultGlobalNotFound } from "./not-found.js";
30
30
  import { ScriptOnce } from "./ScriptOnce.js";
31
31
  import { Asset } from "./Asset.js";
32
32
  import { HeadContent } from "./HeadContent.js";
33
+ import { useTags } from "./headContentUtils.js";
33
34
  import { Scripts } from "./Scripts.js";
34
35
  import { Body } from "./Body.js";
35
36
  import { Html } from "./Html.js";
@@ -139,6 +140,7 @@ export {
139
140
  useRouteContext,
140
141
  useRouter,
141
142
  useRouterState,
142
- useSearch
143
+ useSearch,
144
+ useTags
143
145
  };
144
146
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,6 +1,6 @@
1
1
  import * as Vue from "vue";
2
2
  import { Asset } from "../Asset.js";
3
- import { useTags } from "../HeadContent.js";
3
+ import { useTags } from "../headContentUtils.js";
4
4
  import { RouterProvider } from "../RouterProvider.js";
5
5
  import { Scripts } from "../Scripts.js";
6
6
  const ServerHeadContent = Vue.defineComponent({
@@ -1 +1 @@
1
- {"version":3,"file":"RouterServer.js","sources":["../../../src/ssr/RouterServer.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { Asset } from '../Asset'\nimport { useTags } from '../HeadContent'\nimport { RouterProvider } from '../RouterProvider'\nimport { Scripts } from '../Scripts'\nimport type { AnyRouter, RouterManagedTag } from '@tanstack/router-core'\n\nconst ServerHeadContent = Vue.defineComponent({\n name: 'ServerHeadContent',\n setup() {\n const getTags = useTags()\n\n return () =>\n getTags().map((tag: RouterManagedTag) =>\n Vue.h(Asset, { key: tag.tag + (tag as any).id, ...tag }),\n )\n },\n})\n\nexport const RouterServer = Vue.defineComponent({\n name: 'RouterServer',\n props: {\n router: {\n type: Object as () => AnyRouter,\n required: true,\n },\n },\n setup(props) {\n return () =>\n Vue.h('html', null, [\n Vue.h('head', null, [Vue.h(ServerHeadContent)]),\n Vue.h('body', null, [\n Vue.h('div', { id: '__app' }, [\n Vue.h(\n RouterProvider,\n {\n router: props.router,\n },\n {\n innerWrap: (innerProps: { children: any }) => [\n Vue.h(ServerHeadContent),\n innerProps.children,\n Vue.h(Scripts),\n ],\n },\n ),\n ]),\n ]),\n ])\n },\n})\n"],"names":["ServerHeadContent","Vue","defineComponent","name","setup","getTags","useTags","map","tag","h","Asset","key","id","RouterServer","props","router","type","Object","required","RouterProvider","innerWrap","innerProps","children","Scripts"],"mappings":";;;;;AAOA,MAAMA,oBAAoBC,IAAIC,gBAAgB;AAAA,EAC5CC,MAAM;AAAA,EACNC,QAAQ;AACN,UAAMC,UAAUC,QAAO;AAEvB,WAAO,MACLD,QAAO,EAAGE,IAAKC,SACbP,IAAIQ,EAAEC,OAAO;AAAA,MAAEC,KAAKH,IAAIA,MAAOA,IAAYI;AAAAA,MAAI,GAAGJ;AAAAA,IAAI,CAAC,CACzD;AAAA,EACJ;AACF,CAAC;MAEYK,eAAeZ,IAAIC,gBAAgB;AAAA,EAC9CC,MAAM;AAAA,EACNW,OAAO;AAAA,IACLC,QAAQ;AAAA,MACNC,MAAMC;AAAAA,MACNC,UAAU;AAAA,IACZ;AAAA;EAEFd,MAAMU,OAAO;AACX,WAAO,MACLb,IAAIQ,EAAE,QAAQ,MAAM,CAClBR,IAAIQ,EAAE,QAAQ,MAAM,CAACR,IAAIQ,EAAET,iBAAiB,CAAC,CAAC,GAC9CC,IAAIQ,EAAE,QAAQ,MAAM,CAClBR,IAAIQ,EAAE,OAAO;AAAA,MAAEG,IAAI;AAAA,IAAQ,GAAG,CAC5BX,IAAIQ,EACFU,gBACA;AAAA,MACEJ,QAAQD,MAAMC;AAAAA,IAChB,GACA;AAAA,MACEK,WAAYC,gBAAkC,CAC5CpB,IAAIQ,EAAET,iBAAiB,GACvBqB,WAAWC,UACXrB,IAAIQ,EAAEc,OAAO,CAAC;AAAA,IAElB,CACF,CAAC,CACF,CAAC,CACH,CAAC,CACH;AAAA,EACL;AACF,CAAC;"}
1
+ {"version":3,"file":"RouterServer.js","sources":["../../../src/ssr/RouterServer.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { Asset } from '../Asset'\nimport { useTags } from '../headContentUtils'\nimport { RouterProvider } from '../RouterProvider'\nimport { Scripts } from '../Scripts'\nimport type { AnyRouter, RouterManagedTag } from '@tanstack/router-core'\n\nconst ServerHeadContent = Vue.defineComponent({\n name: 'ServerHeadContent',\n setup() {\n const getTags = useTags()\n\n return () =>\n getTags().map((tag: RouterManagedTag) =>\n Vue.h(Asset, { key: tag.tag + (tag as any).id, ...tag }),\n )\n },\n})\n\nexport const RouterServer = Vue.defineComponent({\n name: 'RouterServer',\n props: {\n router: {\n type: Object as () => AnyRouter,\n required: true,\n },\n },\n setup(props) {\n return () =>\n Vue.h('html', null, [\n Vue.h('head', null, [Vue.h(ServerHeadContent)]),\n Vue.h('body', null, [\n Vue.h('div', { id: '__app' }, [\n Vue.h(\n RouterProvider,\n {\n router: props.router,\n },\n {\n innerWrap: (innerProps: { children: any }) => [\n Vue.h(ServerHeadContent),\n innerProps.children,\n Vue.h(Scripts),\n ],\n },\n ),\n ]),\n ]),\n ])\n },\n})\n"],"names":["ServerHeadContent","Vue","defineComponent","name","setup","getTags","useTags","map","tag","h","Asset","key","id","RouterServer","props","router","type","Object","required","RouterProvider","innerWrap","innerProps","children","Scripts"],"mappings":";;;;;AAOA,MAAMA,oBAAoBC,IAAIC,gBAAgB;AAAA,EAC5CC,MAAM;AAAA,EACNC,QAAQ;AACN,UAAMC,UAAUC,QAAO;AAEvB,WAAO,MACLD,QAAO,EAAGE,IAAKC,SACbP,IAAIQ,EAAEC,OAAO;AAAA,MAAEC,KAAKH,IAAIA,MAAOA,IAAYI;AAAAA,MAAI,GAAGJ;AAAAA,IAAI,CAAC,CACzD;AAAA,EACJ;AACF,CAAC;MAEYK,eAAeZ,IAAIC,gBAAgB;AAAA,EAC9CC,MAAM;AAAA,EACNW,OAAO;AAAA,IACLC,QAAQ;AAAA,MACNC,MAAMC;AAAAA,MACNC,UAAU;AAAA,IACZ;AAAA;EAEFd,MAAMU,OAAO;AACX,WAAO,MACLb,IAAIQ,EAAE,QAAQ,MAAM,CAClBR,IAAIQ,EAAE,QAAQ,MAAM,CAACR,IAAIQ,EAAET,iBAAiB,CAAC,CAAC,GAC9CC,IAAIQ,EAAE,QAAQ,MAAM,CAClBR,IAAIQ,EAAE,OAAO;AAAA,MAAEG,IAAI;AAAA,IAAQ,GAAG,CAC5BX,IAAIQ,EACFU,gBACA;AAAA,MACEJ,QAAQD,MAAMC;AAAAA,IAChB,GACA;AAAA,MACEK,WAAYC,gBAAkC,CAC5CpB,IAAIQ,EAAET,iBAAiB,GACvBqB,WAAWC,UACXrB,IAAIQ,EAAEc,OAAO,CAAC;AAAA,IAElB,CACF,CAAC,CACF,CAAC,CACH,CAAC,CACH;AAAA,EACL;AACF,CAAC;"}
@@ -1,6 +1,4 @@
1
1
  import * as Vue from 'vue';
2
- import type { RouterManagedTag } from '@tanstack/router-core';
3
- export declare const useTags: () => () => RouterManagedTag[];
4
2
  /**
5
3
  * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
6
4
  * It should be rendered in the `<head>` of your document.
@@ -0,0 +1,10 @@
1
+ import * as Vue from 'vue';
2
+ /**
3
+ * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
4
+ * It should be rendered in the `<head>` of your document.
5
+ *
6
+ * This is the development version that filters out dev styles after hydration.
7
+ */
8
+ export declare const HeadContent: Vue.DefineComponent<{}, () => Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
9
+ [key: string]: any;
10
+ }>[], {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,35 @@
1
+ import * as Vue from 'vue';
2
+ import { Asset } from './Asset';
3
+ import { useHydrated } from './ClientOnly';
4
+ import { useTags } from './headContentUtils';
5
+ const DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles';
6
+ /**
7
+ * @description The `HeadContent` component is used to render meta tags, links, and scripts for the current route.
8
+ * It should be rendered in the `<head>` of your document.
9
+ *
10
+ * This is the development version that filters out dev styles after hydration.
11
+ */
12
+ export const HeadContent = Vue.defineComponent({
13
+ name: 'HeadContent',
14
+ setup() {
15
+ const tags = useTags();
16
+ const hydrated = useHydrated();
17
+ // Fallback cleanup for hydration mismatch cases
18
+ Vue.onMounted(() => {
19
+ document
20
+ .querySelectorAll(`link[${DEV_STYLES_ATTR}]`)
21
+ .forEach((el) => el.remove());
22
+ });
23
+ return () => {
24
+ // Filter out dev styles after hydration
25
+ const filteredTags = hydrated.value
26
+ ? tags().filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR])
27
+ : tags();
28
+ return filteredTags.map((tag) => Vue.h(Asset, {
29
+ ...tag,
30
+ key: `tsr-meta-${JSON.stringify(tag)}`,
31
+ }));
32
+ };
33
+ },
34
+ });
35
+ //# sourceMappingURL=HeadContent.dev.jsx.map