@nuxtjs/sitemap 8.3.3 → 8.3.4
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/module.json +1 -1
- package/dist/module.mjs +33 -29
- package/dist/runtime/server/sitemap/builder/entries.d.ts +7 -0
- package/dist/runtime/server/sitemap/builder/entries.js +100 -0
- package/dist/runtime/server/sitemap/builder/sitemap.d.ts +1 -7
- package/dist/runtime/server/sitemap/builder/sitemap.js +3 -161
- package/dist/runtime/utils-pure.d.ts +7 -7
- package/dist/runtime/utils-pure.js +44 -22
- package/package.json +14 -14
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { isNuxtGenerate, renderNitroTypeAugmentations, useModuleLogger, setupNit
|
|
|
6
6
|
import { serializeFilters } from 'nuxtseo-shared/utils';
|
|
7
7
|
import { dirname, extname } from 'pathe';
|
|
8
8
|
import { readPackageJSON } from 'pkg-types';
|
|
9
|
-
import { withBase, withHttps, withTrailingSlash, withoutLeadingSlash, joinURL, withLeadingSlash
|
|
9
|
+
import { withBase, withHttps, withTrailingSlash, withoutLeadingSlash, joinURL, withLeadingSlash } from 'ufo';
|
|
10
10
|
import { setupDevToolsUI as setupDevToolsUI$1 } from 'nuxtseo-shared/devtools';
|
|
11
11
|
import { readFileSync, statSync } from 'node:fs';
|
|
12
12
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
@@ -15,7 +15,7 @@ import { colors } from 'consola/utils';
|
|
|
15
15
|
import { splitForLocales, createPathFilter } from '../dist/runtime/utils-pure.js';
|
|
16
16
|
import { p as parseHtmlExtractSitemapMeta } from './shared/sitemap.BoMnWHOt.mjs';
|
|
17
17
|
import { normaliseDate } from '../dist/runtime/server/sitemap/urlset/normalise.js';
|
|
18
|
-
import { splitPathForI18nLocales as splitPathForI18nLocales$1, expandCompactLocaleRoute, normalizeLocales, generatePathForI18nPages } from 'nuxtseo-shared/i18n';
|
|
18
|
+
import { mapPathForI18nPages, splitPathForI18nLocales as splitPathForI18nLocales$1, expandCompactLocaleRoute, normalizeLocales, generatePathForI18nPages } from 'nuxtseo-shared/i18n';
|
|
19
19
|
import 'ultrahtml';
|
|
20
20
|
|
|
21
21
|
function setupDevToolsUI(_options, resolve, nuxt = useNuxt()) {
|
|
@@ -260,6 +260,33 @@ function splitPathForI18nLocales(path, autoI18n) {
|
|
|
260
260
|
return path;
|
|
261
261
|
return splitPathForI18nLocales$1(path, autoI18n);
|
|
262
262
|
}
|
|
263
|
+
function uniquePaths(paths) {
|
|
264
|
+
return [...new Set(paths)];
|
|
265
|
+
}
|
|
266
|
+
function resolveI18nFilterPaths(path, autoI18n) {
|
|
267
|
+
if (typeof path !== "string")
|
|
268
|
+
return [path];
|
|
269
|
+
const mappedPaths = mapPathForI18nPages(path, autoI18n);
|
|
270
|
+
if (mappedPaths === false) {
|
|
271
|
+
if (autoI18n.strategy === "no_prefix")
|
|
272
|
+
return [path];
|
|
273
|
+
const splitPaths = splitPathForI18nLocales$1(path, autoI18n);
|
|
274
|
+
return Array.isArray(splitPaths) ? splitPaths : [splitPaths];
|
|
275
|
+
}
|
|
276
|
+
if (autoI18n.strategy === "prefix" || autoI18n.strategy === "no_prefix")
|
|
277
|
+
return uniquePaths(mappedPaths);
|
|
278
|
+
const defaultLocales = autoI18n.locales.filter((locale) => locale.code === autoI18n.defaultLocale);
|
|
279
|
+
const defaultStrategy = autoI18n.strategy === "prefix_and_default" ? "prefix" : "no_prefix";
|
|
280
|
+
const defaultPaths = mapPathForI18nPages(path, {
|
|
281
|
+
...autoI18n,
|
|
282
|
+
locales: defaultLocales,
|
|
283
|
+
strategy: defaultStrategy
|
|
284
|
+
});
|
|
285
|
+
return uniquePaths([
|
|
286
|
+
...defaultPaths || [path],
|
|
287
|
+
...mappedPaths
|
|
288
|
+
]);
|
|
289
|
+
}
|
|
263
290
|
|
|
264
291
|
async function resolveUrls(urls, ctx) {
|
|
265
292
|
try {
|
|
@@ -966,38 +993,15 @@ ${onUrlEntries.join("\n")}`;
|
|
|
966
993
|
};
|
|
967
994
|
}
|
|
968
995
|
if (resolvedAutoI18n && usingI18nPages && !hasDisabledAutoI18n) {
|
|
969
|
-
const
|
|
996
|
+
const i18n = resolvedAutoI18n;
|
|
970
997
|
for (const sitemapName in sitemaps) {
|
|
971
|
-
let mapToI18nPages = function(path) {
|
|
972
|
-
if (typeof path !== "string")
|
|
973
|
-
return [path];
|
|
974
|
-
const withoutSlashes = withoutTrailingSlash(withoutLeadingSlash(path)).replace("/index", "");
|
|
975
|
-
if (pages && withoutSlashes in pages) {
|
|
976
|
-
const pageLocales = pages[withoutSlashes];
|
|
977
|
-
if (pageLocales) {
|
|
978
|
-
return Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({
|
|
979
|
-
localeCode,
|
|
980
|
-
pageLocales: pageLocales[localeCode],
|
|
981
|
-
nuxtI18nConfig,
|
|
982
|
-
normalisedLocales
|
|
983
|
-
})));
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
let match = [path];
|
|
987
|
-
Object.values(pages).forEach((pageLocales) => {
|
|
988
|
-
if (pageLocales && nuxtI18nConfig.defaultLocale in pageLocales && pageLocales[nuxtI18nConfig.defaultLocale] === path)
|
|
989
|
-
match = Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({ localeCode, pageLocales: pageLocales[localeCode], nuxtI18nConfig, normalisedLocales })));
|
|
990
|
-
});
|
|
991
|
-
return match;
|
|
992
|
-
};
|
|
993
998
|
if (["index", "chunks"].includes(sitemapName))
|
|
994
999
|
continue;
|
|
995
1000
|
const sitemap = sitemaps[sitemapName];
|
|
996
|
-
sitemap.include = (sitemap.include || []).flatMap((path) =>
|
|
997
|
-
sitemap.exclude = (sitemap.exclude || []).flatMap((path) =>
|
|
1001
|
+
sitemap.include = (sitemap.include || []).flatMap((path) => resolveI18nFilterPaths(path, i18n));
|
|
1002
|
+
sitemap.exclude = (sitemap.exclude || []).flatMap((path) => resolveI18nFilterPaths(path, i18n));
|
|
998
1003
|
}
|
|
999
|
-
}
|
|
1000
|
-
if (resolvedAutoI18n && resolvedAutoI18n.locales && resolvedAutoI18n.strategy !== "no_prefix") {
|
|
1004
|
+
} else if (resolvedAutoI18n && resolvedAutoI18n.locales && resolvedAutoI18n.strategy !== "no_prefix") {
|
|
1001
1005
|
const i18n = resolvedAutoI18n;
|
|
1002
1006
|
for (const sitemapName in sitemaps) {
|
|
1003
1007
|
if (["index", "chunks"].includes(sitemapName))
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AutoI18nConfig, ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl, SitemapDefinition, SitemapUrlInput } from '../../../types.js';
|
|
2
|
+
export interface NormalizedI18n extends ResolvedSitemapUrl {
|
|
3
|
+
_pathWithoutPrefix: string;
|
|
4
|
+
_locale: AutoI18nConfig['locales'][number];
|
|
5
|
+
_index?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapUrlInput[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>, resolvers?: NitroUrlResolvers, baseURL?: string): ResolvedSitemapUrl[];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createPathFilter, resolveI18nRouteEntries, splitForLocales } from "../../../utils-pure.js";
|
|
2
|
+
import { preNormalizeEntry } from "../urlset/normalise.js";
|
|
3
|
+
export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, baseURL) {
|
|
4
|
+
const {
|
|
5
|
+
autoI18n,
|
|
6
|
+
isI18nMapped
|
|
7
|
+
} = runtimeConfig;
|
|
8
|
+
const hasFilters = !!sitemap.include?.length || !!sitemap.exclude?.length;
|
|
9
|
+
const filterPath = hasFilters ? createPathFilter({
|
|
10
|
+
include: sitemap.include,
|
|
11
|
+
exclude: sitemap.exclude
|
|
12
|
+
}, baseURL || "/") : void 0;
|
|
13
|
+
const _urls = [];
|
|
14
|
+
for (const _e of urls) {
|
|
15
|
+
const e = preNormalizeEntry(_e, resolvers);
|
|
16
|
+
if (e.loc && (!filterPath || filterPath(e.loc, e._path?.pathname)))
|
|
17
|
+
_urls.push(e);
|
|
18
|
+
}
|
|
19
|
+
const withoutPrefixPaths = {};
|
|
20
|
+
if (autoI18n && autoI18n.strategy !== "no_prefix") {
|
|
21
|
+
const localeCodes = new Set(autoI18n.locales.map((l) => l.code));
|
|
22
|
+
const localeByCode = new Map(autoI18n.locales.map((l) => [l.code, l]));
|
|
23
|
+
const defaultLocale = autoI18n.defaultLocale;
|
|
24
|
+
const hasDifferentDomains = !!autoI18n.differentDomains;
|
|
25
|
+
const validI18nUrlsForTransform = [];
|
|
26
|
+
for (let i = 0; i < _urls.length; i++) {
|
|
27
|
+
const _e = _urls[i];
|
|
28
|
+
if (_e._abs)
|
|
29
|
+
continue;
|
|
30
|
+
const split = splitForLocales(_e._relativeLoc, localeCodes);
|
|
31
|
+
let localeCode = split[0];
|
|
32
|
+
const pathWithoutPrefix = split[1];
|
|
33
|
+
if (!localeCode)
|
|
34
|
+
localeCode = defaultLocale;
|
|
35
|
+
const e = _e;
|
|
36
|
+
e._pathWithoutPrefix = pathWithoutPrefix;
|
|
37
|
+
const locale = localeByCode.get(localeCode);
|
|
38
|
+
if (!locale)
|
|
39
|
+
continue;
|
|
40
|
+
e._locale = locale;
|
|
41
|
+
e._index = i;
|
|
42
|
+
e._key = `${e._sitemap || ""}${e._path?.pathname || "/"}${e._path?.search || ""}`;
|
|
43
|
+
withoutPrefixPaths[pathWithoutPrefix] = withoutPrefixPaths[pathWithoutPrefix] || [];
|
|
44
|
+
if (!withoutPrefixPaths[pathWithoutPrefix].some((e2) => e2._locale.code === locale.code))
|
|
45
|
+
withoutPrefixPaths[pathWithoutPrefix].push(e);
|
|
46
|
+
validI18nUrlsForTransform.push(e);
|
|
47
|
+
}
|
|
48
|
+
for (const e of validI18nUrlsForTransform) {
|
|
49
|
+
if (!e._i18nTransform && !e.alternatives?.length) {
|
|
50
|
+
const alternatives = [];
|
|
51
|
+
for (const u of withoutPrefixPaths[e._pathWithoutPrefix] || []) {
|
|
52
|
+
if (u._locale.code === defaultLocale) {
|
|
53
|
+
alternatives.push({
|
|
54
|
+
href: u.loc,
|
|
55
|
+
hreflang: "x-default"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
alternatives.push({
|
|
59
|
+
href: u.loc,
|
|
60
|
+
hreflang: u._locale._hreflang || defaultLocale
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (alternatives.length)
|
|
64
|
+
e.alternatives = alternatives;
|
|
65
|
+
} else if (e._i18nTransform) {
|
|
66
|
+
delete e._i18nTransform;
|
|
67
|
+
const routeEntries = resolveI18nRouteEntries(e._relativeLoc, autoI18n, (href) => !filterPath || filterPath(href));
|
|
68
|
+
if (hasDifferentDomains) {
|
|
69
|
+
e.alternatives = routeEntries[0]?.alternatives;
|
|
70
|
+
} else {
|
|
71
|
+
for (const { alternatives, locale: l, loc } of routeEntries) {
|
|
72
|
+
const _sitemap = isI18nMapped ? l._sitemap : void 0;
|
|
73
|
+
const { _index: _, ...rest } = e;
|
|
74
|
+
const newEntry = preNormalizeEntry({
|
|
75
|
+
_sitemap,
|
|
76
|
+
...rest,
|
|
77
|
+
_key: `${_sitemap || ""}${loc || "/"}`,
|
|
78
|
+
_locale: l,
|
|
79
|
+
loc,
|
|
80
|
+
alternatives
|
|
81
|
+
}, resolvers);
|
|
82
|
+
if (e._locale.code === newEntry._locale.code) {
|
|
83
|
+
_urls[e._index] = newEntry;
|
|
84
|
+
e._index = void 0;
|
|
85
|
+
} else {
|
|
86
|
+
_urls.push(newEntry);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (isI18nMapped) {
|
|
92
|
+
e._sitemap = e._sitemap || e._locale._sitemap;
|
|
93
|
+
e._key = `${e._sitemap || ""}${e.loc || "/"}${e._path?.search || ""}`;
|
|
94
|
+
}
|
|
95
|
+
if (e._index)
|
|
96
|
+
_urls[e._index] = e;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return _urls;
|
|
100
|
+
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl, SitemapDefinition } from '../../../types.js';
|
|
2
2
|
type NitroApp = ReturnType<typeof import('#nuxtseo/nitro').useNitroApp>;
|
|
3
|
-
export interface NormalizedI18n extends ResolvedSitemapUrl {
|
|
4
|
-
_pathWithoutPrefix: string;
|
|
5
|
-
_locale: AutoI18nConfig['locales'][number];
|
|
6
|
-
_index?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapUrlInput[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>, resolvers?: NitroUrlResolvers, baseURL?: string): ResolvedSitemapUrl[];
|
|
9
3
|
export interface ResolvedSitemapUrlsResult {
|
|
10
4
|
urls: ResolvedSitemapUrl[];
|
|
11
5
|
failedSources: Array<{
|
|
@@ -1,172 +1,14 @@
|
|
|
1
1
|
import { resolveSitePath } from "nuxt-site-config/urls";
|
|
2
|
-
import {
|
|
2
|
+
import { withHttps } from "ufo";
|
|
3
3
|
import { getHeader } from "#nuxtseo/h3";
|
|
4
4
|
import { defineCachedFunction, useRuntimeConfig } from "#nuxtseo/nitro";
|
|
5
5
|
import staticConfig from "#sitemap-virtual/static-config.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { preNormalizeEntry } from "../urlset/normalise.js";
|
|
6
|
+
import { logger, resolveI18nSitemapLocaleKey } from "../../../utils-pure.js";
|
|
8
7
|
import { sortInPlace } from "../urlset/sort.js";
|
|
9
8
|
import { childSitemapSources, globalSitemapSources, resolveSitemapSources } from "../urlset/sources.js";
|
|
10
9
|
import { parseChunkInfo, sliceUrlsForChunk } from "../utils/chunk.js";
|
|
10
|
+
import { resolveSitemapEntries } from "./entries.js";
|
|
11
11
|
const SERVER_CACHE_MAX_AGE = staticConfig.cacheMaxAgeSeconds || 60 * 10;
|
|
12
|
-
export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, baseURL) {
|
|
13
|
-
const {
|
|
14
|
-
autoI18n,
|
|
15
|
-
isI18nMapped
|
|
16
|
-
} = runtimeConfig;
|
|
17
|
-
const hasFilters = !!sitemap.include?.length || !!sitemap.exclude?.length;
|
|
18
|
-
const filterPath = hasFilters ? createPathFilter({
|
|
19
|
-
include: sitemap.include,
|
|
20
|
-
exclude: sitemap.exclude
|
|
21
|
-
}, baseURL || "/") : void 0;
|
|
22
|
-
const _urls = [];
|
|
23
|
-
for (const _e of urls) {
|
|
24
|
-
const e = preNormalizeEntry(_e, resolvers);
|
|
25
|
-
if (e.loc && (!filterPath || filterPath(e.loc, e._path?.pathname)))
|
|
26
|
-
_urls.push(e);
|
|
27
|
-
}
|
|
28
|
-
const withoutPrefixPaths = {};
|
|
29
|
-
if (autoI18n && autoI18n.strategy !== "no_prefix") {
|
|
30
|
-
const localeCodes = new Set(autoI18n.locales.map((l) => l.code));
|
|
31
|
-
const localeByCode = new Map(autoI18n.locales.map((l) => [l.code, l]));
|
|
32
|
-
const isPrefixStrategy = autoI18n.strategy === "prefix";
|
|
33
|
-
const isPrefixExceptOrAndDefault = autoI18n.strategy === "prefix_and_default" || autoI18n.strategy === "prefix_except_default";
|
|
34
|
-
const xDefaultAndLocales = [{ code: "x-default", _hreflang: "x-default" }, ...autoI18n.locales];
|
|
35
|
-
const defaultLocale = autoI18n.defaultLocale;
|
|
36
|
-
const hasPages = !!autoI18n.pages;
|
|
37
|
-
const sortedPageKeys = hasPages ? Object.keys(autoI18n.pages).sort((a, b) => b.length - a.length) : void 0;
|
|
38
|
-
const hasDifferentDomains = !!autoI18n.differentDomains;
|
|
39
|
-
const validI18nUrlsForTransform = [];
|
|
40
|
-
for (let i = 0; i < _urls.length; i++) {
|
|
41
|
-
const _e = _urls[i];
|
|
42
|
-
if (_e._abs)
|
|
43
|
-
continue;
|
|
44
|
-
const split = splitForLocales(_e._relativeLoc, localeCodes);
|
|
45
|
-
let localeCode = split[0];
|
|
46
|
-
const pathWithoutPrefix = split[1];
|
|
47
|
-
if (!localeCode)
|
|
48
|
-
localeCode = defaultLocale;
|
|
49
|
-
const e = _e;
|
|
50
|
-
e._pathWithoutPrefix = pathWithoutPrefix;
|
|
51
|
-
const locale = localeByCode.get(localeCode);
|
|
52
|
-
if (!locale)
|
|
53
|
-
continue;
|
|
54
|
-
e._locale = locale;
|
|
55
|
-
e._index = i;
|
|
56
|
-
e._key = `${e._sitemap || ""}${e._path?.pathname || "/"}${e._path?.search || ""}`;
|
|
57
|
-
withoutPrefixPaths[pathWithoutPrefix] = withoutPrefixPaths[pathWithoutPrefix] || [];
|
|
58
|
-
if (!withoutPrefixPaths[pathWithoutPrefix].some((e2) => e2._locale.code === locale.code))
|
|
59
|
-
withoutPrefixPaths[pathWithoutPrefix].push(e);
|
|
60
|
-
validI18nUrlsForTransform.push(e);
|
|
61
|
-
}
|
|
62
|
-
for (const e of validI18nUrlsForTransform) {
|
|
63
|
-
if (!e._i18nTransform && !e.alternatives?.length) {
|
|
64
|
-
const alternatives = [];
|
|
65
|
-
for (const u of withoutPrefixPaths[e._pathWithoutPrefix] || []) {
|
|
66
|
-
if (u._locale.code === defaultLocale) {
|
|
67
|
-
alternatives.push({
|
|
68
|
-
href: u.loc,
|
|
69
|
-
hreflang: "x-default"
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
alternatives.push({
|
|
73
|
-
href: u.loc,
|
|
74
|
-
hreflang: u._locale._hreflang || defaultLocale
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
if (alternatives.length)
|
|
78
|
-
e.alternatives = alternatives;
|
|
79
|
-
} else if (e._i18nTransform) {
|
|
80
|
-
delete e._i18nTransform;
|
|
81
|
-
if (hasDifferentDomains) {
|
|
82
|
-
const defLocale = localeByCode.get(defaultLocale);
|
|
83
|
-
e.alternatives = [
|
|
84
|
-
{
|
|
85
|
-
...defLocale,
|
|
86
|
-
code: "x-default"
|
|
87
|
-
},
|
|
88
|
-
...autoI18n.locales.filter((l) => !!l.domain)
|
|
89
|
-
].map((locale) => {
|
|
90
|
-
return {
|
|
91
|
-
hreflang: locale._hreflang,
|
|
92
|
-
href: joinURL(withHttps(locale.domain), e._pathWithoutPrefix)
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
|
-
} else {
|
|
96
|
-
const pageMatch = hasPages ? findPageMapping(e._pathWithoutPrefix, autoI18n.pages, sortedPageKeys) : null;
|
|
97
|
-
const pathSearch = e._path?.search || "";
|
|
98
|
-
const pathWithoutPrefix = e._pathWithoutPrefix;
|
|
99
|
-
for (const l of autoI18n.locales) {
|
|
100
|
-
let loc = pathWithoutPrefix;
|
|
101
|
-
if (pageMatch && pageMatch.mappings[l.code] !== void 0) {
|
|
102
|
-
const customPath = pageMatch.mappings[l.code];
|
|
103
|
-
if (customPath === false)
|
|
104
|
-
continue;
|
|
105
|
-
if (typeof customPath === "string") {
|
|
106
|
-
loc = customPath[0] === "/" ? customPath : `/${customPath}`;
|
|
107
|
-
loc = applyDynamicParams(loc, pageMatch.paramSegments);
|
|
108
|
-
if (isPrefixStrategy || isPrefixExceptOrAndDefault && l.code !== defaultLocale)
|
|
109
|
-
loc = joinURL(`/${l.code}`, loc);
|
|
110
|
-
}
|
|
111
|
-
} else if (!hasDifferentDomains && !(isPrefixExceptOrAndDefault && l.code === defaultLocale)) {
|
|
112
|
-
loc = joinURL(`/${l.code}`, pathWithoutPrefix);
|
|
113
|
-
}
|
|
114
|
-
const _sitemap = isI18nMapped ? l._sitemap : void 0;
|
|
115
|
-
const alternatives = [];
|
|
116
|
-
for (const locale of xDefaultAndLocales) {
|
|
117
|
-
const code = locale.code === "x-default" ? defaultLocale : locale.code;
|
|
118
|
-
const isDefault = locale.code === "x-default" || locale.code === defaultLocale;
|
|
119
|
-
let href = pathWithoutPrefix;
|
|
120
|
-
if (pageMatch && pageMatch.mappings[code] !== void 0) {
|
|
121
|
-
const customPath = pageMatch.mappings[code];
|
|
122
|
-
if (customPath === false)
|
|
123
|
-
continue;
|
|
124
|
-
if (typeof customPath === "string") {
|
|
125
|
-
href = customPath[0] === "/" ? customPath : `/${customPath}`;
|
|
126
|
-
href = applyDynamicParams(href, pageMatch.paramSegments);
|
|
127
|
-
if (isPrefixStrategy || isPrefixExceptOrAndDefault && !isDefault)
|
|
128
|
-
href = joinURL("/", code, href);
|
|
129
|
-
}
|
|
130
|
-
} else if (isPrefixStrategy) {
|
|
131
|
-
href = joinURL("/", code, pathWithoutPrefix);
|
|
132
|
-
} else if (isPrefixExceptOrAndDefault && !isDefault) {
|
|
133
|
-
href = joinURL("/", code, pathWithoutPrefix);
|
|
134
|
-
}
|
|
135
|
-
if (filterPath && !filterPath(href))
|
|
136
|
-
continue;
|
|
137
|
-
alternatives.push({
|
|
138
|
-
hreflang: locale._hreflang,
|
|
139
|
-
href
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
const { _index: _, ...rest } = e;
|
|
143
|
-
const newEntry = preNormalizeEntry({
|
|
144
|
-
_sitemap,
|
|
145
|
-
...rest,
|
|
146
|
-
_key: `${_sitemap || ""}${loc || "/"}${pathSearch}`,
|
|
147
|
-
_locale: l,
|
|
148
|
-
loc,
|
|
149
|
-
alternatives
|
|
150
|
-
}, resolvers);
|
|
151
|
-
if (e._locale.code === newEntry._locale.code) {
|
|
152
|
-
_urls[e._index] = newEntry;
|
|
153
|
-
e._index = void 0;
|
|
154
|
-
} else {
|
|
155
|
-
_urls.push(newEntry);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
if (isI18nMapped) {
|
|
161
|
-
e._sitemap = e._sitemap || e._locale._sitemap;
|
|
162
|
-
e._key = `${e._sitemap || ""}${e.loc || "/"}${e._path?.search || ""}`;
|
|
163
|
-
}
|
|
164
|
-
if (e._index)
|
|
165
|
-
_urls[e._index] = e;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return _urls;
|
|
169
|
-
}
|
|
170
12
|
export async function buildResolvedSitemapUrls(effectiveSitemap, matchName, isChunked, resolvers, runtimeConfig, nitro) {
|
|
171
13
|
const { sitemaps, autoI18n, isI18nMapped, isMultiSitemap, sortEntries } = runtimeConfig;
|
|
172
14
|
let sourcesInput = effectiveSitemap.includeAppSources ? [...await globalSitemapSources(), ...await childSitemapSources(effectiveSitemap)] : await childSitemapSources(effectiveSitemap);
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { FilterInput } from './types.js';
|
|
1
|
+
import type { AlternativeEntry, AutoI18nConfig, FilterInput } from './types.js';
|
|
2
2
|
export { createFilter, type CreateFilterOptions } from 'nuxtseo-shared/utils';
|
|
3
3
|
export declare const logger: import("consola").ConsolaInstance;
|
|
4
4
|
export declare function xmlEscape(value: string | number | boolean | Date): string;
|
|
5
5
|
export declare function mergeOnKey<T, K extends keyof T>(arr: T[], key: K, onMerge?: (key: T[K]) => void): T[];
|
|
6
6
|
export declare function splitForLocales(path: string, locales: readonly string[] | Set<string>): [string | null, string];
|
|
7
|
+
export interface ResolvedI18nRouteEntry {
|
|
8
|
+
locale: AutoI18nConfig['locales'][number];
|
|
9
|
+
loc: string;
|
|
10
|
+
alternatives: AlternativeEntry[];
|
|
11
|
+
}
|
|
12
|
+
export declare function resolveI18nRouteEntries(route: string, i18n: AutoI18nConfig, includeHref?: (href: string) => boolean): ResolvedI18nRouteEntry[];
|
|
7
13
|
/**
|
|
8
14
|
* Resolve which locale a multi-sitemap name belongs to.
|
|
9
15
|
*
|
|
@@ -22,9 +28,3 @@ export declare function createPathFilter(options?: {
|
|
|
22
28
|
include?: (FilterInput | string | RegExp)[];
|
|
23
29
|
exclude?: (FilterInput | string | RegExp)[];
|
|
24
30
|
}, baseURL?: string): (loc: string, pathname?: string) => boolean;
|
|
25
|
-
export interface PageMatch {
|
|
26
|
-
mappings: Record<string, string | false>;
|
|
27
|
-
paramSegments: string[];
|
|
28
|
-
}
|
|
29
|
-
export declare function findPageMapping(pathWithoutPrefix: string, pages: Record<string, Record<string, string | false>>, sortedKeys?: string[]): PageMatch | null;
|
|
30
|
-
export declare function applyDynamicParams(customPath: string, paramSegments: string[]): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createDefu } from "defu";
|
|
2
|
+
import { computeLocaleAlternates, resolveLocaleFromRoute } from "nuxtseo-shared/i18n-runtime";
|
|
2
3
|
import { createFilter, createModuleLogger } from "nuxtseo-shared/utils";
|
|
3
|
-
import { parseURL, withoutBase } from "ufo";
|
|
4
|
+
import { joinURL, parseURL, withHttps, withLeadingSlash, withoutBase } from "ufo";
|
|
4
5
|
export { createFilter } from "nuxtseo-shared/utils";
|
|
5
6
|
export const logger = createModuleLogger("@nuxt/sitemap");
|
|
6
7
|
const XML_ENTITIES = {
|
|
@@ -51,6 +52,47 @@ export function splitForLocales(path, locales) {
|
|
|
51
52
|
}
|
|
52
53
|
return [null, path];
|
|
53
54
|
}
|
|
55
|
+
function toRuntimeI18nConfig(i18n) {
|
|
56
|
+
return {
|
|
57
|
+
...i18n,
|
|
58
|
+
// Sitemap transforms keep the unprefixed default URL alongside Nuxt's prefixed route.
|
|
59
|
+
strategy: i18n.strategy === "prefix_and_default" ? "prefix_except_default" : i18n.strategy,
|
|
60
|
+
pages: i18n.pages && Object.fromEntries(
|
|
61
|
+
Object.entries(i18n.pages).map(([pageName, pageLocales]) => [
|
|
62
|
+
pageName,
|
|
63
|
+
Object.fromEntries(i18n.locales.map((locale) => {
|
|
64
|
+
const configuredPath = pageLocales[locale.code];
|
|
65
|
+
return [locale.code, configuredPath === void 0 ? withLeadingSlash(pageName) : configuredPath];
|
|
66
|
+
}))
|
|
67
|
+
])
|
|
68
|
+
),
|
|
69
|
+
locales: i18n.locales.map((locale) => ({
|
|
70
|
+
...locale,
|
|
71
|
+
hreflang: locale._hreflang
|
|
72
|
+
}))
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function localeAlternateHref(alternate) {
|
|
76
|
+
return alternate.domain ? joinURL(withHttps(alternate.domain), alternate.path) : alternate.path;
|
|
77
|
+
}
|
|
78
|
+
export function resolveI18nRouteEntries(route, i18n, includeHref = () => true) {
|
|
79
|
+
const runtimeConfig = toRuntimeI18nConfig(i18n);
|
|
80
|
+
const currentLocale = resolveLocaleFromRoute(route, runtimeConfig).locale;
|
|
81
|
+
const alternates = computeLocaleAlternates(route, runtimeConfig, { locale: currentLocale });
|
|
82
|
+
const localizedAlternates = alternates.map((alternate) => ({
|
|
83
|
+
alternate,
|
|
84
|
+
href: localeAlternateHref(alternate)
|
|
85
|
+
}));
|
|
86
|
+
const defaultHref = localizedAlternates.find(({ alternate }) => alternate.code === i18n.defaultLocale)?.href;
|
|
87
|
+
const sitemapAlternatives = [
|
|
88
|
+
...defaultHref && includeHref(defaultHref) ? [{ hreflang: "x-default", href: defaultHref }] : [],
|
|
89
|
+
...localizedAlternates.filter(({ href }) => includeHref(href)).map(({ alternate, href }) => ({ hreflang: alternate.hreflang, href }))
|
|
90
|
+
];
|
|
91
|
+
return localizedAlternates.flatMap(({ alternate, href }) => {
|
|
92
|
+
const locale = i18n.locales.find((locale2) => locale2.code === alternate.code);
|
|
93
|
+
return locale ? [{ locale, loc: href, alternatives: sitemapAlternatives }] : [];
|
|
94
|
+
});
|
|
95
|
+
}
|
|
54
96
|
export function resolveI18nSitemapLocaleKey(sitemapName, localeSitemapKeys) {
|
|
55
97
|
let best = null;
|
|
56
98
|
for (const key of localeSitemapKeys) {
|
|
@@ -89,26 +131,6 @@ export function createPathFilter(options = {}, baseURL) {
|
|
|
89
131
|
}
|
|
90
132
|
if (hasBase)
|
|
91
133
|
path = withoutBase(path, baseURL);
|
|
92
|
-
return urlFilter(path);
|
|
134
|
+
return urlFilter(withLeadingSlash(path));
|
|
93
135
|
};
|
|
94
136
|
}
|
|
95
|
-
export function findPageMapping(pathWithoutPrefix, pages, sortedKeys) {
|
|
96
|
-
const stripped = pathWithoutPrefix[0] === "/" ? pathWithoutPrefix.slice(1) : pathWithoutPrefix;
|
|
97
|
-
const pageKey = stripped.endsWith("/index") ? stripped.slice(0, -6) || "index" : stripped || "index";
|
|
98
|
-
if (pages[pageKey])
|
|
99
|
-
return { mappings: pages[pageKey], paramSegments: [] };
|
|
100
|
-
const keys = sortedKeys || Object.keys(pages).sort((a, b) => b.length - a.length);
|
|
101
|
-
for (const key of keys) {
|
|
102
|
-
if (pageKey.startsWith(`${key}/`)) {
|
|
103
|
-
const paramPath = pageKey.slice(key.length + 1);
|
|
104
|
-
return { mappings: pages[key], paramSegments: paramPath.split("/") };
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
export function applyDynamicParams(customPath, paramSegments) {
|
|
110
|
-
if (!paramSegments.length)
|
|
111
|
-
return customPath;
|
|
112
|
-
let i = 0;
|
|
113
|
-
return customPath.replace(/\[[^\]]+\]/g, () => paramSegments[i++] || "");
|
|
114
|
-
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/sitemap",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "8.3.
|
|
4
|
+
"version": "8.3.4",
|
|
5
5
|
"description": "Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@nuxt/kit": "^4.5.
|
|
58
|
+
"@nuxt/kit": "^4.5.2",
|
|
59
59
|
"consola": "^3.4.2",
|
|
60
60
|
"defu": "^6.1.7",
|
|
61
|
-
"nuxt-site-config": "^4.
|
|
62
|
-
"nuxtseo-shared": "^5.3.
|
|
61
|
+
"nuxt-site-config": "^4.2.0",
|
|
62
|
+
"nuxtseo-shared": "^5.3.11",
|
|
63
63
|
"ofetch": "^1.5.1",
|
|
64
64
|
"pathe": "^2.0.3",
|
|
65
65
|
"pkg-types": "^2.3.1",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"sitemapd": "^0.2.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@antfu/eslint-config": "^9.
|
|
72
|
+
"@antfu/eslint-config": "^9.3.0",
|
|
73
73
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
74
74
|
"@nuxt/content": "^3.15.2",
|
|
75
75
|
"@nuxt/devtools-kit": "4.0.0-alpha.9",
|
|
@@ -77,23 +77,23 @@
|
|
|
77
77
|
"@nuxt/test-utils": "^4.1.0",
|
|
78
78
|
"@nuxt/ui": "^4.10.0",
|
|
79
79
|
"@nuxtjs/i18n": "^10.6.0",
|
|
80
|
-
"@nuxtjs/robots": "^6.1.
|
|
80
|
+
"@nuxtjs/robots": "^6.1.4",
|
|
81
81
|
"@vue/test-utils": "^2.4.11",
|
|
82
|
-
"better-sqlite3": "^13.0.
|
|
83
|
-
"bumpp": "^12.
|
|
84
|
-
"eslint": "^10.8.
|
|
82
|
+
"better-sqlite3": "^13.0.3",
|
|
83
|
+
"bumpp": "^12.2.0",
|
|
84
|
+
"eslint": "^10.8.1",
|
|
85
85
|
"eslint-plugin-harlanzw": "^0.17.1",
|
|
86
|
-
"happy-dom": "^20.11.
|
|
87
|
-
"nuxt": "^4.5.
|
|
88
|
-
"nuxt-i18n-micro": "^3.
|
|
89
|
-
"nuxtseo-layer-devtools": "^5.3.
|
|
86
|
+
"happy-dom": "^20.11.2",
|
|
87
|
+
"nuxt": "^4.5.2",
|
|
88
|
+
"nuxt-i18n-micro": "^3.28.0",
|
|
89
|
+
"nuxtseo-layer-devtools": "^5.3.11",
|
|
90
90
|
"std-env": "^4.2.0",
|
|
91
91
|
"typescript": "6.0.3",
|
|
92
92
|
"unbuild": "^3.6.1",
|
|
93
93
|
"vitest": "^4.1.10",
|
|
94
94
|
"vue-tsc": "^3.3.9",
|
|
95
95
|
"zod": "^4.4.3",
|
|
96
|
-
"@nuxtjs/sitemap": "8.3.
|
|
96
|
+
"@nuxtjs/sitemap": "8.3.4"
|
|
97
97
|
},
|
|
98
98
|
"scripts": {
|
|
99
99
|
"lint": "eslint .",
|