nuxt-seo-utils 7.0.14 → 7.0.15

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 (34) hide show
  1. package/package.json +20 -20
  2. package/dist/module.d.mts +0 -115
  3. package/dist/module.json +0 -12
  4. package/dist/module.mjs +0 -547
  5. package/dist/runtime/app/composables/polyfills.d.ts +0 -11
  6. package/dist/runtime/app/composables/polyfills.js +0 -27
  7. package/dist/runtime/app/composables/useBreadcrumbItems.d.ts +0 -112
  8. package/dist/runtime/app/composables/useBreadcrumbItems.js +0 -193
  9. package/dist/runtime/app/logic/applyDefaults.d.ts +0 -1
  10. package/dist/runtime/app/logic/applyDefaults.js +0 -78
  11. package/dist/runtime/app/plugins/0.routeRules.d.ts +0 -2
  12. package/dist/runtime/app/plugins/0.routeRules.js +0 -24
  13. package/dist/runtime/app/plugins/1.absoluteImageUrls.server.d.ts +0 -2
  14. package/dist/runtime/app/plugins/1.absoluteImageUrls.server.js +0 -33
  15. package/dist/runtime/app/plugins/defaults.d.ts +0 -2
  16. package/dist/runtime/app/plugins/defaults.js +0 -12
  17. package/dist/runtime/app/plugins/defaultsWaitI18n.d.ts +0 -2
  18. package/dist/runtime/app/plugins/defaultsWaitI18n.js +0 -13
  19. package/dist/runtime/app/plugins/inferSeoMetaPlugin.d.ts +0 -2
  20. package/dist/runtime/app/plugins/inferSeoMetaPlugin.js +0 -11
  21. package/dist/runtime/app/plugins/siteConfig.d.ts +0 -2
  22. package/dist/runtime/app/plugins/siteConfig.js +0 -33
  23. package/dist/runtime/app/plugins/titles.d.ts +0 -2
  24. package/dist/runtime/app/plugins/titles.js +0 -30
  25. package/dist/runtime/server/middleware/redirectCanonical.d.ts +0 -2
  26. package/dist/runtime/server/middleware/redirectCanonical.js +0 -28
  27. package/dist/runtime/server/middleware/resolveImagesInPagesDir.d.ts +0 -2
  28. package/dist/runtime/server/middleware/resolveImagesInPagesDir.js +0 -16
  29. package/dist/runtime/server/tsconfig.json +0 -3
  30. package/dist/runtime/shared/breadcrumbs.d.ts +0 -1
  31. package/dist/runtime/shared/breadcrumbs.js +0 -18
  32. package/dist/runtime/types.d.ts +0 -6
  33. package/dist/runtime/types.js +0 -0
  34. package/dist/types.d.mts +0 -3
@@ -1,193 +0,0 @@
1
- import { defineBreadcrumb, useI18n, useSchemaOrg } from "#imports";
2
- import { useSiteConfig } from "#site-config/app/composables/useSiteConfig";
3
- import { createSitePathResolver } from "#site-config/app/composables/utils";
4
- import { defu } from "defu";
5
- import { fixSlashes } from "nuxt-site-config/urls";
6
- import { useNuxtApp, useRoute, useRouter, useState } from "nuxt/app";
7
- import { withoutTrailingSlash } from "ufo";
8
- import {
9
- computed,
10
- getCurrentInstance,
11
- inject,
12
- onScopeDispose,
13
- onUnmounted,
14
- provide,
15
- ref,
16
- toRaw,
17
- toValue,
18
- watch
19
- } from "vue";
20
- import { pathBreadcrumbSegments } from "../../shared/breadcrumbs.js";
21
- function withoutQuery(path) {
22
- return path.split("?")[0];
23
- }
24
- function titleCase(s) {
25
- return s.replaceAll("-", " ").replace(/\w\S*/g, (w) => w.charAt(0).toUpperCase() + w.substr(1).toLowerCase());
26
- }
27
- const BreadcrumbCtx = Symbol("BreadcrumbCtx");
28
- export function useBreadcrumbItems(_options = {}) {
29
- const nuxtApp = useNuxtApp();
30
- const vm = getCurrentInstance();
31
- const id = `${_options.id || "breadcrumb"}`;
32
- const uid = `${vm?.uid || 0}`;
33
- const parentChain = [];
34
- let parent = vm?.parent;
35
- while (parent) {
36
- parentChain.push(parent.uid || 0);
37
- parent = parent.parent;
38
- }
39
- const pauseUpdates = ref(import.meta.client && nuxtApp.isHydrating);
40
- let stateRef = null;
41
- if (vm) {
42
- stateRef = inject(BreadcrumbCtx, null);
43
- if (!stateRef) {
44
- stateRef = ref({});
45
- provide(BreadcrumbCtx, stateRef);
46
- }
47
- const state = stateRef.value;
48
- state[uid] = _options;
49
- stateRef.value = state;
50
- onUnmounted(() => {
51
- const state2 = toRaw(stateRef.value);
52
- delete state2[uid];
53
- stateRef.value = state2;
54
- });
55
- if (import.meta.client) {
56
- const _ = [];
57
- _.push(nuxtApp.hooks.hook("page:start", () => {
58
- pauseUpdates.value = true;
59
- }));
60
- _.push(nuxtApp.hooks.hook("page:finish", () => {
61
- if (!nuxtApp.isHydrating) {
62
- pauseUpdates.value = false;
63
- }
64
- }));
65
- _.push(nuxtApp.hooks.hook("app:error", () => {
66
- pauseUpdates.value = false;
67
- }));
68
- _.push(nuxtApp.hooks.hook("app:suspense:resolve", () => {
69
- pauseUpdates.value = false;
70
- }));
71
- onScopeDispose(() => {
72
- _.forEach((hook) => hook?.());
73
- _.length = 0;
74
- });
75
- }
76
- }
77
- const route = useRoute();
78
- const router = useRouter();
79
- const i18n = useI18n();
80
- const siteResolver = createSitePathResolver({
81
- canonical: true,
82
- absolute: true
83
- });
84
- const lastBreadcrumbs = useState(`nuxt-seo:breadcrumb:${id}`, () => []);
85
- const siteConfig = useSiteConfig();
86
- const items = computed(() => {
87
- if (import.meta.client && pauseUpdates.value) {
88
- return lastBreadcrumbs.value;
89
- }
90
- const state = toValue(stateRef) || {};
91
- const optionStack = [...parentChain, uid].map((parentId) => state[parentId]).filter(Boolean);
92
- const flatOptions = optionStack.reduce((acc, _cur) => {
93
- const cur = {};
94
- Object.entries(_cur).forEach(([key, value]) => {
95
- cur[key] = toValue(value);
96
- });
97
- acc.hideRoot = typeof cur.hideRoot === "undefined" ? acc.hideRoot : cur.hideRoot;
98
- acc.hideCurrent = typeof cur.hideCurrent === "undefined" ? acc.hideCurrent : cur.hideCurrent;
99
- acc.hideNonExisting = typeof cur.hideNonExisting === "undefined" ? acc.hideNonExisting : cur.hideNonExisting;
100
- acc.rootSegment = acc.rootSegment || cur.rootSegment;
101
- acc.path = acc.path || cur.path;
102
- acc.overrides = acc.overrides || [];
103
- const overrides = toRaw(toValue(cur.overrides));
104
- if (overrides) {
105
- overrides.forEach((item, index) => {
106
- if (item !== void 0) {
107
- acc.overrides[index] = toRaw(toValue(item));
108
- }
109
- });
110
- }
111
- const prepend = toRaw(toValue(cur.prepend));
112
- const append = toRaw(toValue(cur.append));
113
- if (prepend && prepend.length) {
114
- acc.prepend = [...acc.prepend || [], ...prepend.map((m) => toRaw(toValue(m)))].filter(Boolean);
115
- }
116
- if (append && append.length)
117
- acc.append = [...acc.append || [], ...append.map((m) => toRaw(toValue(m)))].filter(Boolean);
118
- return acc;
119
- }, {});
120
- let rootNode = flatOptions.rootSegment || "/";
121
- if (i18n) {
122
- if (i18n.strategy === "prefix" || i18n.strategy !== "no_prefix" && toValue(i18n.defaultLocale) !== toValue(i18n.locale))
123
- rootNode = `${rootNode}${toValue(i18n.locale)}`;
124
- }
125
- const current = withoutQuery(withoutTrailingSlash(flatOptions.path || toRaw(route)?.path || rootNode)) || "";
126
- const segments = pathBreadcrumbSegments(current, rootNode).map((path, index) => {
127
- let item = {
128
- to: path
129
- };
130
- const override = flatOptions.overrides?.[index];
131
- if (typeof override !== "undefined") {
132
- if (override === false)
133
- return false;
134
- item = defu(override, item);
135
- }
136
- return item;
137
- });
138
- segments.unshift(...flatOptions.prepend || []);
139
- segments.push(...flatOptions.append || []);
140
- return segments.filter(Boolean).map((item) => {
141
- let fallbackLabel = titleCase(String((item.to || "").split("/").pop()));
142
- let fallbackAriaLabel = "";
143
- const route2 = item.to ? router.resolve(item.to)?.matched?.at(-1) : null;
144
- if (route2) {
145
- const routeMeta = route2?.meta || {};
146
- if (routeMeta.breadcrumb) {
147
- item = defu(item, routeMeta.breadcrumb);
148
- }
149
- const routeName = String(route2.name).split("___")?.[0];
150
- if (routeName === "index") {
151
- fallbackLabel = "Home";
152
- }
153
- fallbackLabel = routeMeta.breadcrumbLabel || routeMeta.breadcrumbTitle || routeMeta.title || fallbackLabel;
154
- fallbackLabel = i18n.t(`breadcrumb.items.${routeName}.label`, fallbackLabel, { missingWarn: false });
155
- fallbackAriaLabel = i18n.t(`breadcrumb.items.${routeName}.ariaLabel`, fallbackAriaLabel, { missingWarn: false });
156
- } else if (flatOptions.hideNonExisting) {
157
- return false;
158
- }
159
- item.label = item.label || fallbackLabel;
160
- item.ariaLabel = item.ariaLabel || fallbackAriaLabel || item.label;
161
- item.current = item.current || item.to === current;
162
- if (flatOptions.hideCurrent && item.current)
163
- return false;
164
- return item;
165
- }).map((m) => {
166
- if (m && m.to) {
167
- m.to = fixSlashes(siteConfig.trailingSlash, m.to);
168
- if (m.to === rootNode && flatOptions.hideRoot)
169
- return false;
170
- }
171
- return m;
172
- }).filter(Boolean);
173
- });
174
- watch(items, (newItems) => {
175
- if (!pauseUpdates.value) {
176
- lastBreadcrumbs.value = newItems;
177
- }
178
- }, { immediate: true, flush: "sync" });
179
- const schemaOrgEnabled = typeof _options.schemaOrg === "undefined" ? true : _options.schemaOrg;
180
- if ((import.meta.dev || import.meta.server || import.meta.env?.NODE_ENV === "test") && schemaOrgEnabled) {
181
- useSchemaOrg([
182
- // @ts-expect-error untyped
183
- defineBreadcrumb({
184
- id: `#${id}`,
185
- itemListElement: computed(() => items.value.map((item) => ({
186
- name: item.label || item.ariaLabel,
187
- item: item.to ? siteResolver(item.to) : void 0
188
- })))
189
- })
190
- ]);
191
- }
192
- return items;
193
- }
@@ -1 +0,0 @@
1
- export declare function applyDefaults(): void;
@@ -1,78 +0,0 @@
1
- import { injectHead, useHead, useSeoMeta } from "#imports";
2
- import { useSiteConfig } from "#site-config/app/composables/useSiteConfig";
3
- import { createSitePathResolver } from "#site-config/app/composables/utils";
4
- import { TemplateParamsPlugin } from "@unhead/vue/plugins";
5
- import { useError, useRoute, useRuntimeConfig } from "nuxt/app";
6
- import { stringifyQuery } from "ufo";
7
- import { computed, toValue } from "vue";
8
- export function applyDefaults() {
9
- const siteConfig = useSiteConfig({
10
- resolveRefs: false
11
- });
12
- const resolveCurrentLocale = () => toValue(siteConfig.currentLocale) || toValue(siteConfig.defaultLocale) || "en";
13
- const head = injectHead();
14
- head.use(TemplateParamsPlugin);
15
- const { canonicalQueryWhitelist, canonicalLowercase } = useRuntimeConfig().public["seo-utils"];
16
- const route = useRoute();
17
- const resolveUrl = createSitePathResolver({ withBase: true, absolute: true });
18
- const err = useError();
19
- const canonicalUrl = computed(() => {
20
- if (err.value) {
21
- return false;
22
- }
23
- const { query } = route;
24
- let url = resolveUrl(route.path || "/").value || route.path;
25
- if (canonicalLowercase) {
26
- try {
27
- url = url.toLocaleLowerCase(resolveCurrentLocale());
28
- } catch {
29
- url = url.toLowerCase();
30
- }
31
- }
32
- const filteredQuery = Object.fromEntries(
33
- Object.entries(query).filter(([key]) => canonicalQueryWhitelist.includes(key)).sort(([a], [b]) => a.localeCompare(b))
34
- // Sort params
35
- );
36
- const href = Object.keys(filteredQuery).length ? `${url}?${stringifyQuery(filteredQuery)}` : url;
37
- return { rel: "canonical", href };
38
- });
39
- const minimalPriority = {
40
- // give nuxt.config values higher priority
41
- tagPriority: "low"
42
- };
43
- useHead({
44
- htmlAttrs: { lang: resolveCurrentLocale },
45
- templateParams: {
46
- site: () => siteConfig,
47
- siteName: () => siteConfig.name
48
- },
49
- titleTemplate: "%s %separator %siteName",
50
- link: [() => canonicalUrl.value]
51
- }, minimalPriority);
52
- const seoMeta = {
53
- ogType: "website",
54
- ogUrl: () => {
55
- const url = canonicalUrl.value;
56
- return url ? url.href : false;
57
- },
58
- ogLocale: () => {
59
- const locale = resolveCurrentLocale();
60
- if (locale) {
61
- const l = locale.replace("-", "_");
62
- if (l.includes("_")) {
63
- return l;
64
- }
65
- }
66
- return false;
67
- },
68
- ogSiteName: siteConfig.name
69
- };
70
- if (siteConfig.description)
71
- seoMeta.description = siteConfig.description;
72
- if (siteConfig.twitter) {
73
- const id = siteConfig.twitter.startsWith("@") ? siteConfig.twitter : `@${siteConfig.twitter}`;
74
- seoMeta.twitterCreator = id;
75
- seoMeta.twitterSite = id;
76
- }
77
- useSeoMeta(seoMeta, minimalPriority);
78
- }
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,24 +0,0 @@
1
- import { injectHead, useSeoMeta } from "#imports";
2
- import { defineNuxtPlugin, getRouteRules, useRequestEvent, useState } from "nuxt/app";
3
- export default defineNuxtPlugin({
4
- enforce: "post",
5
- async setup() {
6
- const head = injectHead();
7
- const routeRuleState = useState("nuxt-seo-utils:routeRules", () => null);
8
- if (import.meta.server) {
9
- const event = useRequestEvent();
10
- const routeRules = await getRouteRules(event);
11
- routeRuleState.value = {
12
- head: routeRules.head,
13
- seoMeta: routeRules.seoMeta
14
- };
15
- }
16
- if (routeRuleState.value) {
17
- const { head: headInput, seoMeta } = routeRuleState.value;
18
- if (headInput)
19
- head.push(headInput);
20
- if (seoMeta)
21
- useSeoMeta(seoMeta);
22
- }
23
- }
24
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,33 +0,0 @@
1
- import { injectHead } from "#imports";
2
- import { createSitePathResolver } from "#site-config/app/composables/utils";
3
- import { defineNuxtPlugin } from "nuxt/app";
4
- import { unref } from "vue";
5
- export default defineNuxtPlugin({
6
- enforce: "post",
7
- setup() {
8
- const head = injectHead();
9
- if (!head)
10
- return;
11
- const resolver = createSitePathResolver({
12
- withBase: true,
13
- absolute: true,
14
- canonical: true
15
- });
16
- head.use({
17
- key: "absoluteImageUrls",
18
- hooks: {
19
- "tags:resolve": async ({ tags }) => {
20
- for (const tag of tags) {
21
- if (tag.tag !== "meta")
22
- continue;
23
- if (tag.props.property !== "og:image:url" && tag.props.property !== "og:image" && tag.props.name !== "twitter:image")
24
- continue;
25
- if (typeof tag.props.content !== "string" || !tag.props.content.trim() || tag.props.content.startsWith("http") || tag.props.content.startsWith("//"))
26
- continue;
27
- tag.props.content = unref(resolver(tag.props.content));
28
- }
29
- }
30
- }
31
- });
32
- }
33
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,12 +0,0 @@
1
- import { defineNuxtPlugin } from "nuxt/app";
2
- import { applyDefaults } from "../logic/applyDefaults.js";
3
- export default defineNuxtPlugin({
4
- name: "nuxt-seo:defaults",
5
- order: 999,
6
- env: {
7
- islands: false
8
- },
9
- setup() {
10
- applyDefaults();
11
- }
12
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,13 +0,0 @@
1
- import { defineNuxtPlugin } from "nuxt/app";
2
- import { applyDefaults } from "../logic/applyDefaults.js";
3
- export default defineNuxtPlugin({
4
- name: "nuxt-seo:defaults",
5
- env: {
6
- islands: false
7
- },
8
- // we need to wait for the i18n plugin to run first
9
- dependsOn: ["nuxt-site-config:i18n"],
10
- setup() {
11
- applyDefaults();
12
- }
13
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,11 +0,0 @@
1
- import { injectHead } from "#imports";
2
- import { InferSeoMetaPlugin } from "@unhead/addons";
3
- import { defineNuxtPlugin } from "nuxt/app";
4
- import { TemplateParamsPlugin } from "unhead/plugins";
5
- export default defineNuxtPlugin(() => {
6
- const head = injectHead();
7
- if (!head)
8
- return;
9
- head.use(TemplateParamsPlugin);
10
- head.use(InferSeoMetaPlugin());
11
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,33 +0,0 @@
1
- import { injectHead } from "#imports";
2
- import { useSiteConfig } from "#site-config/app/composables/useSiteConfig";
3
- import { defineNuxtPlugin } from "nuxt/app";
4
- export default defineNuxtPlugin(() => {
5
- const head = injectHead();
6
- if (!head)
7
- return;
8
- const siteConfig = useSiteConfig();
9
- const input = {
10
- meta: [],
11
- templateParams: {
12
- site: siteConfig,
13
- // support legacy
14
- siteUrl: siteConfig.url,
15
- siteName: siteConfig.name
16
- }
17
- };
18
- if (siteConfig.separator)
19
- input.templateParams.separator = siteConfig.separator;
20
- if (siteConfig.titleSeparator)
21
- input.templateParams.titleSeparator = siteConfig.titleSeparator;
22
- if (siteConfig.description) {
23
- input.templateParams.siteDescription = siteConfig.description;
24
- input.meta.push(
25
- {
26
- name: "description",
27
- content: "%site.description",
28
- tagPriority: "low"
29
- }
30
- );
31
- }
32
- head.push(input);
33
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,30 +0,0 @@
1
- import { useHead } from "#imports";
2
- import { defineNuxtPlugin, useError, useRoute } from "nuxt/app";
3
- import { titleCase } from "scule";
4
- import { withoutTrailingSlash } from "ufo";
5
- import { computed } from "vue";
6
- export default defineNuxtPlugin({
7
- name: "nuxt-seo:fallback-titles",
8
- env: {
9
- islands: false
10
- },
11
- setup() {
12
- const route = useRoute();
13
- const err = useError();
14
- const title = computed(() => {
15
- if (err.value && [404, 500].includes(err.value?.statusCode)) {
16
- return `${err.value.statusCode} - ${err.value.message}`;
17
- }
18
- if (typeof route.meta?.title === "string")
19
- return route.meta?.title;
20
- const path = withoutTrailingSlash(route.path || "/");
21
- const lastSegment = path.split("/").pop();
22
- return lastSegment ? titleCase(lastSegment) : null;
23
- });
24
- const minimalPriority = {
25
- // give nuxt.config values higher priority
26
- tagPriority: 101
27
- };
28
- useHead({ title: () => title.value }, minimalPriority);
29
- }
30
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void> | undefined>;
2
- export default _default;
@@ -1,28 +0,0 @@
1
- import { useSiteConfig } from "#site-config/server/composables/useSiteConfig";
2
- import { defineEventHandler, getRequestHost, sendRedirect, setHeader } from "h3";
3
- import { joinURL } from "ufo";
4
- export default defineEventHandler((e) => {
5
- if (import.meta.prerender) {
6
- return;
7
- }
8
- const path = e.path;
9
- if (path.startsWith("/_nuxt") || path.startsWith("/api")) {
10
- return;
11
- }
12
- if (path.split("/").pop()?.includes(".")) {
13
- return;
14
- }
15
- const siteConfig = useSiteConfig(e);
16
- if (!siteConfig.url || siteConfig.env !== "production") {
17
- return;
18
- }
19
- const siteConfigHostName = new URL(e.path, siteConfig.url).host;
20
- const host = getRequestHost(e, { xForwardedHost: true });
21
- if (e.headers.get("x-nuxt-seo-redirected") || host.includes("http") || host.replace("https://", "").includes(":")) {
22
- return;
23
- }
24
- if (host.split(":")[0] !== siteConfigHostName.split(":")[0]) {
25
- setHeader(e, "x-nuxt-seo-redirected", "true");
26
- return sendRedirect(e, joinURL(siteConfig.url, e.path), 301);
27
- }
28
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<NonSharedBuffer | undefined>>;
2
- export default _default;
@@ -1,16 +0,0 @@
1
- import fs from "node:fs";
2
- import { fileMapping } from "#seo-utils-virtual/pageDirImages";
3
- import { defineEventHandler, setHeader } from "h3";
4
- import { parseURL } from "ufo";
5
- export default defineEventHandler(async (e) => {
6
- const path = parseURL(e.path).pathname;
7
- if (fileMapping[path]) {
8
- if (path.endsWith(".svg"))
9
- setHeader(e, "Content-Type", "image/svg+xml");
10
- else if (path.endsWith(".png"))
11
- setHeader(e, "Content-Type", "image/png");
12
- else if (path.endsWith(".jpg") || path.endsWith(".jpeg"))
13
- setHeader(e, "Content-Type", "image/jpeg");
14
- return fs.readFileSync(fileMapping[path]);
15
- }
16
- });
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "../../../../.nuxt/tsconfig.server.json"
3
- }
@@ -1 +0,0 @@
1
- export declare function pathBreadcrumbSegments(path: string, rootNode?: string): string[];
@@ -1,18 +0,0 @@
1
- import { hasTrailingSlash, parseURL, stringifyParsedURL, withTrailingSlash } from "ufo";
2
- export function pathBreadcrumbSegments(path, rootNode = "/") {
3
- const startNode = parseURL(path);
4
- const appendsTrailingSlash = hasTrailingSlash(startNode.pathname);
5
- const stepNode = (node, nodes = []) => {
6
- const fullPath = stringifyParsedURL(node);
7
- const currentPathName = node.pathname || "/";
8
- nodes.push(fullPath || "/");
9
- if (currentPathName !== rootNode && currentPathName !== "/") {
10
- node.pathname = currentPathName.substring(0, currentPathName.lastIndexOf("/"));
11
- if (appendsTrailingSlash)
12
- node.pathname = withTrailingSlash(node.pathname.substring(0, node.pathname.lastIndexOf("/")));
13
- stepNode(node, nodes);
14
- }
15
- return nodes;
16
- };
17
- return stepNode(startNode).reverse();
18
- }
@@ -1,6 +0,0 @@
1
- import type { Head, MetaFlat, RawInput } from '@unhead/vue/types';
2
- export type MetaFlatSerializable = MetaFlat & {
3
- title?: RawInput<'title'>;
4
- titleTemplate?: RawInput<'titleTemplate'>;
5
- };
6
- export type { Head };
File without changes
package/dist/types.d.mts DELETED
@@ -1,3 +0,0 @@
1
- export { default } from './module.mjs'
2
-
3
- export { type ModuleOptions } from './module.mjs'