@nuxtjs/sitemap 5.3.5 → 6.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/200.html +61 -54
- package/dist/client/404.html +61 -54
- package/dist/client/_nuxt/{D7WeZTai.js → -0RnDExV.js} +1 -1
- package/dist/client/_nuxt/{DOtRmeXT.js → -4dSXLqG.js} +1 -1
- package/dist/client/_nuxt/458cWEat.js +3 -0
- package/dist/client/_nuxt/{CFF2d1j6.js → BEZjiGez.js} +1 -1
- package/dist/client/_nuxt/{B3g-KkBK.js → BHqu4VKd.js} +1 -1
- package/dist/client/_nuxt/{D33OKbkv.js → BM5XuWfj.js} +1 -1
- package/dist/client/_nuxt/BMRpS3Xo.js +1 -0
- package/dist/client/_nuxt/{1rqFXsGc.js → BUinYsBq.js} +2 -2
- package/dist/client/_nuxt/BXP-NDAE.js +1 -0
- package/dist/client/_nuxt/{kuh6G-Sk.js → BZ035FK2.js} +1 -1
- package/dist/client/_nuxt/{DrnZp123.js → B_kA2_jD.js} +1 -1
- package/dist/client/_nuxt/BgSQePf4.js +1 -0
- package/dist/client/_nuxt/{CdedUr_-.js → BiVAY1KT.js} +1 -1
- package/dist/client/_nuxt/BpDWT_aG.js +1 -0
- package/dist/client/_nuxt/BpJyBuO9.js +1 -0
- package/dist/client/_nuxt/{BnyYJeap.js → Bpum8voz.js} +1 -1
- package/dist/client/_nuxt/Br9pa-sp.js +1 -0
- package/dist/client/_nuxt/BspO9hSn.js +1 -0
- package/dist/client/_nuxt/{DAP_O-zg.js → Bx64mzUw.js} +1 -1
- package/dist/client/_nuxt/Bym0hRiG.js +1 -0
- package/dist/client/_nuxt/C8DXlOXe.js +1 -0
- package/dist/client/_nuxt/{ECt0lbkd.js → CBks_G0r.js} +1 -1
- package/dist/client/_nuxt/COBxEbHI.js +1 -0
- package/dist/client/_nuxt/CPw9RxLe.js +1 -0
- package/dist/client/_nuxt/{dIHJ9UdL.js → CRYtL1Hd.js} +1 -1
- package/dist/client/_nuxt/CX3ZWouj.js +229 -0
- package/dist/client/_nuxt/{0ooBkv16.js → CaGCoJJM.js} +1 -1
- package/dist/client/_nuxt/Ctb_e1-I.js +1 -0
- package/dist/client/_nuxt/{AGFfX61t.js → CuOLCh11.js} +1 -1
- package/dist/client/_nuxt/{JgH_6NEN.js → CxBHuulF.js} +1 -1
- package/dist/client/_nuxt/{CJIaz0BQ.js → CxLlwT--.js} +1 -1
- package/dist/client/_nuxt/{B6bHXiXE.js → D3VHKxjW.js} +1 -1
- package/dist/client/_nuxt/D46m5Xd3.js +1 -0
- package/dist/client/_nuxt/D5OoM2Ul.js +1 -0
- package/dist/client/_nuxt/D5lQfeOG.js +1 -0
- package/dist/client/_nuxt/D8V69RRQ.js +1 -0
- package/dist/client/_nuxt/{CX_FIdg1.js → DDK5Hw8n.js} +1 -1
- package/dist/client/_nuxt/{C1yTBzia.js → DIyf2Ztx.js} +1 -1
- package/dist/client/_nuxt/{BZfs-ost.js → DOv5BRyJ.js} +1 -1
- package/dist/client/_nuxt/DQ-rpzxz.js +1 -0
- package/dist/client/_nuxt/DUsrs60I.js +6 -0
- package/dist/client/_nuxt/DV9_Ze0W.js +1 -0
- package/dist/client/_nuxt/{Bxkoe-BC.js → EQHFthT6.js} +1 -1
- package/dist/client/_nuxt/Ev-gWqHG.js +1 -0
- package/dist/client/_nuxt/{BacI6-DX.js → FRbOFgZn.js} +1 -1
- package/dist/client/_nuxt/{CqYeW6XZ.js → Gme1ZbSQ.js} +1 -1
- package/dist/client/_nuxt/{Br6ll-O0.js → NrGJGX17.js} +1 -1
- package/dist/client/_nuxt/{CarfVElc.js → ULUzDaxg.js} +1 -1
- package/dist/client/_nuxt/USEQoosB.js +31 -0
- package/dist/client/_nuxt/{DGDuLtS6.js → V16qqttt.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/99e0fea3-c4e8-45fe-88b0-f49b86d00f5b.json +1 -0
- package/dist/client/_nuxt/d42HzezM.js +1 -0
- package/dist/client/_nuxt/entry.BnSVD-Km.css +1 -0
- package/dist/client/_nuxt/error-404.BOXiSWAJ.css +1 -0
- package/dist/client/_nuxt/error-500.DmKlUOlN.css +1 -0
- package/dist/client/_nuxt/{BXR915QZ.js → ewRyznZJ.js} +1 -1
- package/dist/client/_nuxt/{BVLuctcA.js → vMuZBeRS.js} +1 -1
- package/dist/client/_nuxt/{Bj5xdiaE.js → xuIuMB9j.js} +1 -1
- package/dist/client/_nuxt/{ChMCFiS0.js → zIdFMUa4.js} +1 -1
- package/dist/client/_nuxt/{BVkeqZ59.js → zbShYgi7.js} +1 -1
- package/dist/client/index.html +61 -54
- package/dist/module.d.mts +355 -1
- package/dist/module.d.ts +355 -1
- package/dist/module.json +2 -2
- package/dist/module.mjs +178 -32
- package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.d.ts +2 -1
- package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.js +1 -1
- package/dist/runtime/nitro/routes/__sitemap__/debug.d.ts +8 -6
- package/dist/runtime/nitro/{middleware/[sitemap]-sitemap.xml.d.ts → routes/sitemap/[sitemap].xml.d.ts} +1 -1
- package/dist/runtime/nitro/routes/sitemap/[sitemap].xml.js +20 -0
- package/dist/runtime/nitro/routes/sitemap.xsl.js +2 -1
- package/dist/runtime/nitro/routes/sitemap_index.xml.js +19 -16
- package/dist/runtime/nitro/sitemap/builder/sitemap-index.d.ts +3 -2
- package/dist/runtime/nitro/sitemap/builder/sitemap-index.js +14 -28
- package/dist/runtime/nitro/sitemap/builder/sitemap.d.ts +9 -2
- package/dist/runtime/nitro/sitemap/builder/sitemap.js +154 -54
- package/dist/runtime/nitro/sitemap/builder/xml.d.ts +1 -1
- package/dist/runtime/nitro/sitemap/builder/xml.js +2 -0
- package/dist/runtime/nitro/sitemap/nitro.d.ts +1 -1
- package/dist/runtime/nitro/sitemap/nitro.js +47 -11
- package/dist/runtime/nitro/sitemap/urlset/normalise.d.ts +3 -2
- package/dist/runtime/nitro/sitemap/urlset/normalise.js +64 -53
- package/dist/runtime/types.d.ts +35 -4
- package/dist/runtime/utils-pure.d.ts +2 -1
- package/dist/runtime/utils-pure.js +6 -0
- package/package.json +24 -25
- package/dist/client/_nuxt/3ghuYFLd.js +0 -1
- package/dist/client/_nuxt/9B1nZgL-.js +0 -1
- package/dist/client/_nuxt/BG-qYwi8.js +0 -6
- package/dist/client/_nuxt/BIxS-Weu.js +0 -1
- package/dist/client/_nuxt/BYdKNJ10.js +0 -1
- package/dist/client/_nuxt/Bi43K_FX.js +0 -6
- package/dist/client/_nuxt/CBPJd_fO.js +0 -1
- package/dist/client/_nuxt/CCqFro8U.js +0 -3
- package/dist/client/_nuxt/CEfge3mM.js +0 -1
- package/dist/client/_nuxt/CSPeAESR.js +0 -1
- package/dist/client/_nuxt/D0mw_hZ2.js +0 -31
- package/dist/client/_nuxt/DGO8GyiP.js +0 -1
- package/dist/client/_nuxt/DOHBU7tp.js +0 -1
- package/dist/client/_nuxt/DQoqAi02.js +0 -1
- package/dist/client/_nuxt/DVLwECkk.js +0 -1
- package/dist/client/_nuxt/Du6_OKDb.js +0 -159
- package/dist/client/_nuxt/builds/meta/ab2ad6a2-f67d-4194-8e33-d46fbc5d1290.json +0 -1
- package/dist/client/_nuxt/eJfcURhx.js +0 -1
- package/dist/client/_nuxt/entry.CfxF9LiM.css +0 -1
- package/dist/client/_nuxt/error-404.D56ZPmHb.css +0 -1
- package/dist/client/_nuxt/error-500.BYEp4uQX.css +0 -1
- package/dist/runtime/nitro/middleware/[sitemap]-sitemap.xml.js +0 -23
- package/dist/runtime/nitro/sitemap/urlset/filter.d.ts +0 -5
- package/dist/runtime/nitro/sitemap/urlset/filter.js +0 -24
- package/dist/runtime/nitro/sitemap/urlset/i18n.d.ts +0 -6
- package/dist/runtime/nitro/sitemap/urlset/i18n.js +0 -142
|
@@ -1,16 +1,144 @@
|
|
|
1
|
-
import { defu } from "defu";
|
|
2
1
|
import { resolveSitePath } from "site-config-stack/urls";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { joinURL, withHttps } from "ufo";
|
|
3
|
+
import { preNormalizeEntry } from "../urlset/normalise.js";
|
|
5
4
|
import { childSitemapSources, globalSitemapSources, resolveSitemapSources } from "../urlset/sources.js";
|
|
6
|
-
import { filterSitemapUrls } from "../urlset/filter.js";
|
|
7
|
-
import { applyI18nEnhancements, normaliseI18nSources } from "../urlset/i18n.js";
|
|
8
5
|
import { sortSitemapUrls } from "../urlset/sort.js";
|
|
9
|
-
import { splitForLocales } from "
|
|
10
|
-
import { createNitroRouteRuleMatcher } from "../../kit.js";
|
|
6
|
+
import { createPathFilter, logger, splitForLocales } from "../../../utils-pure.js";
|
|
11
7
|
import { handleEntry, wrapSitemapXml } from "./xml.js";
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export function resolveSitemapEntries(sitemap, sources, runtimeConfig) {
|
|
9
|
+
const {
|
|
10
|
+
autoI18n,
|
|
11
|
+
isI18nMapped
|
|
12
|
+
} = runtimeConfig;
|
|
13
|
+
const filterPath = createPathFilter({
|
|
14
|
+
include: sitemap.include,
|
|
15
|
+
exclude: sitemap.exclude
|
|
16
|
+
});
|
|
17
|
+
const _urls = sources.flatMap((e) => e.urls).map((_e) => {
|
|
18
|
+
const e = preNormalizeEntry(_e);
|
|
19
|
+
if (!e.loc || !filterPath(e.loc))
|
|
20
|
+
return false;
|
|
21
|
+
return e;
|
|
22
|
+
}).filter(Boolean);
|
|
23
|
+
let validI18nUrlsForTransform = [];
|
|
24
|
+
let warnIncorrectI18nTransformUsage = false;
|
|
25
|
+
const withoutPrefixPaths = {};
|
|
26
|
+
if (autoI18n && autoI18n.strategy !== "no_prefix") {
|
|
27
|
+
const localeCodes = autoI18n.locales.map((l) => l.code);
|
|
28
|
+
validI18nUrlsForTransform = _urls.map((_e, i) => {
|
|
29
|
+
if (_e._abs)
|
|
30
|
+
return false;
|
|
31
|
+
const split = splitForLocales(_e.loc, localeCodes);
|
|
32
|
+
let localeCode = split[0];
|
|
33
|
+
const pathWithoutPrefix = split[1];
|
|
34
|
+
if (!localeCode)
|
|
35
|
+
localeCode = autoI18n.defaultLocale;
|
|
36
|
+
const e = _e;
|
|
37
|
+
e._pathWithoutPrefix = pathWithoutPrefix;
|
|
38
|
+
const locale = autoI18n.locales.find((l) => l.code === localeCode);
|
|
39
|
+
if (!locale)
|
|
40
|
+
return false;
|
|
41
|
+
e._locale = locale;
|
|
42
|
+
e._index = i;
|
|
43
|
+
withoutPrefixPaths[pathWithoutPrefix] = withoutPrefixPaths[pathWithoutPrefix] || [];
|
|
44
|
+
if (!withoutPrefixPaths[pathWithoutPrefix].some((e2) => e2._locale.code === locale.code))
|
|
45
|
+
withoutPrefixPaths[pathWithoutPrefix].push(e);
|
|
46
|
+
return e;
|
|
47
|
+
}).filter(Boolean);
|
|
48
|
+
for (const e of validI18nUrlsForTransform) {
|
|
49
|
+
if (!e._i18nTransform && !e.alternatives?.length) {
|
|
50
|
+
const alternatives = withoutPrefixPaths[e._pathWithoutPrefix].map((u) => {
|
|
51
|
+
const entries = [];
|
|
52
|
+
if (u._locale.code === autoI18n.defaultLocale) {
|
|
53
|
+
entries.push({
|
|
54
|
+
href: u.loc,
|
|
55
|
+
hreflang: "x-default"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
entries.push({
|
|
59
|
+
href: u.loc,
|
|
60
|
+
hreflang: u._locale.code || autoI18n.defaultLocale
|
|
61
|
+
});
|
|
62
|
+
return entries;
|
|
63
|
+
}).flat().filter(Boolean);
|
|
64
|
+
if (alternatives.length)
|
|
65
|
+
e.alternatives = alternatives;
|
|
66
|
+
} else if (e._i18nTransform) {
|
|
67
|
+
delete e._i18nTransform;
|
|
68
|
+
if (autoI18n.strategy === "no_prefix") {
|
|
69
|
+
warnIncorrectI18nTransformUsage = true;
|
|
70
|
+
}
|
|
71
|
+
if (autoI18n.differentDomains) {
|
|
72
|
+
e.alternatives = [
|
|
73
|
+
{
|
|
74
|
+
// apply default locale domain
|
|
75
|
+
...autoI18n.locales.find((l) => [l.code, l.iso].includes(autoI18n.defaultLocale)),
|
|
76
|
+
code: "x-default"
|
|
77
|
+
},
|
|
78
|
+
...autoI18n.locales.filter((l) => !!l.domain)
|
|
79
|
+
].map((locale) => {
|
|
80
|
+
return {
|
|
81
|
+
hreflang: locale.iso || locale.code,
|
|
82
|
+
href: joinURL(withHttps(locale.domain), e._pathWithoutPrefix)
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
for (const l of autoI18n.locales) {
|
|
87
|
+
let loc = joinURL(`/${l.code}`, e._pathWithoutPrefix);
|
|
88
|
+
if (autoI18n.differentDomains || ["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy) && l.code === autoI18n.defaultLocale)
|
|
89
|
+
loc = e._pathWithoutPrefix;
|
|
90
|
+
const _sitemap = isI18nMapped ? l.iso || l.code : void 0;
|
|
91
|
+
const newEntry = preNormalizeEntry({
|
|
92
|
+
_sitemap,
|
|
93
|
+
...e,
|
|
94
|
+
_index: void 0,
|
|
95
|
+
_key: `${_sitemap || ""}${loc}`,
|
|
96
|
+
_locale: l,
|
|
97
|
+
loc,
|
|
98
|
+
alternatives: [{ code: "x-default" }, ...autoI18n.locales].map((locale) => {
|
|
99
|
+
const code = locale.code === "x-default" ? autoI18n.defaultLocale : locale.code;
|
|
100
|
+
const isDefault = locale.code === "x-default" || locale.code === autoI18n.defaultLocale;
|
|
101
|
+
let href = "";
|
|
102
|
+
if (autoI18n.strategy === "prefix") {
|
|
103
|
+
href = joinURL("/", code, e._pathWithoutPrefix);
|
|
104
|
+
} else if (["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy)) {
|
|
105
|
+
if (isDefault) {
|
|
106
|
+
href = e._pathWithoutPrefix;
|
|
107
|
+
} else {
|
|
108
|
+
href = joinURL("/", code, e._pathWithoutPrefix);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const hreflang = locale.iso || locale.code;
|
|
112
|
+
if (!filterPath(href))
|
|
113
|
+
return false;
|
|
114
|
+
return {
|
|
115
|
+
hreflang,
|
|
116
|
+
href
|
|
117
|
+
};
|
|
118
|
+
}).filter(Boolean)
|
|
119
|
+
});
|
|
120
|
+
if (e._locale.code === newEntry._locale.code) {
|
|
121
|
+
_urls[e._index] = newEntry;
|
|
122
|
+
e._index = void 0;
|
|
123
|
+
} else {
|
|
124
|
+
_urls.push(newEntry);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (isI18nMapped) {
|
|
130
|
+
e._sitemap = e._sitemap || e._locale.iso || e._locale.code;
|
|
131
|
+
}
|
|
132
|
+
if (e._index)
|
|
133
|
+
_urls[e._index] = e;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (import.meta.dev && warnIncorrectI18nTransformUsage) {
|
|
137
|
+
logger.warn("You're using _i18nTransform with the `no_prefix` strategy. This will cause issues with the sitemap. Please remove the _i18nTransform flag or change i18n strategy.");
|
|
138
|
+
}
|
|
139
|
+
return _urls;
|
|
140
|
+
}
|
|
141
|
+
export async function buildSitemapUrls(sitemap, resolvers, runtimeConfig) {
|
|
14
142
|
const {
|
|
15
143
|
sitemaps,
|
|
16
144
|
// enhancing
|
|
@@ -20,22 +148,18 @@ export async function buildSitemap(sitemap, resolvers, runtimeConfig) {
|
|
|
20
148
|
// sorting
|
|
21
149
|
sortEntries,
|
|
22
150
|
// chunking
|
|
23
|
-
defaultSitemapsChunkSize
|
|
24
|
-
// xls
|
|
25
|
-
version,
|
|
26
|
-
xsl,
|
|
27
|
-
credits
|
|
151
|
+
defaultSitemapsChunkSize
|
|
28
152
|
} = runtimeConfig;
|
|
29
153
|
const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemap.sitemapName));
|
|
30
|
-
function maybeSort(
|
|
31
|
-
return sortEntries ? sortSitemapUrls(
|
|
154
|
+
function maybeSort(urls) {
|
|
155
|
+
return sortEntries ? sortSitemapUrls(urls) : urls;
|
|
32
156
|
}
|
|
33
|
-
function maybeSlice(
|
|
157
|
+
function maybeSlice(urls) {
|
|
34
158
|
if (isChunking && defaultSitemapsChunkSize) {
|
|
35
159
|
const chunk = Number(sitemap.sitemapName);
|
|
36
|
-
return
|
|
160
|
+
return urls.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize);
|
|
37
161
|
}
|
|
38
|
-
return
|
|
162
|
+
return urls;
|
|
39
163
|
}
|
|
40
164
|
if (autoI18n?.differentDomains) {
|
|
41
165
|
const domain = autoI18n.locales.find((e) => [e.iso, e.code].includes(sitemap.sitemapName))?.domain;
|
|
@@ -52,41 +176,17 @@ export async function buildSitemap(sitemap, resolvers, runtimeConfig) {
|
|
|
52
176
|
}
|
|
53
177
|
const sources = sitemap.includeAppSources ? await globalSitemapSources() : [];
|
|
54
178
|
sources.push(...await childSitemapSources(sitemap));
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let routeRules = routeRuleMatcher(path);
|
|
63
|
-
if (autoI18n?.locales && autoI18n?.strategy !== "no_prefix") {
|
|
64
|
-
const match = splitForLocales(path, autoI18n.locales.map((l) => l.code));
|
|
65
|
-
const pathWithoutPrefix = match[1];
|
|
66
|
-
if (pathWithoutPrefix && pathWithoutPrefix !== path)
|
|
67
|
-
routeRules = defu(routeRules, routeRuleMatcher(pathWithoutPrefix));
|
|
68
|
-
}
|
|
69
|
-
if (routeRules.sitemap === false)
|
|
70
|
-
return false;
|
|
71
|
-
if (typeof routeRules.index !== "undefined" && !routeRules.index)
|
|
72
|
-
return false;
|
|
73
|
-
const hasRobotsDisabled = Object.entries(routeRules.headers || {}).some(([name, value]) => name.toLowerCase() === "x-robots-tag" && value.toLowerCase() === "noindex");
|
|
74
|
-
if (routeRules.redirect || hasRobotsDisabled)
|
|
75
|
-
return false;
|
|
76
|
-
return routeRules.sitemap ? defu(e, routeRules.sitemap) : e;
|
|
77
|
-
}).filter(Boolean);
|
|
78
|
-
if (autoI18n?.locales)
|
|
79
|
-
enhancedUrls = applyI18nEnhancements(enhancedUrls, { isI18nMapped, autoI18n, ...sitemap });
|
|
80
|
-
const filteredUrls = filterSitemapUrls(enhancedUrls, { event: resolvers.event, isMultiSitemap, autoI18n, ...sitemap });
|
|
179
|
+
const resolvedSources = await resolveSitemapSources(sources, resolvers.event);
|
|
180
|
+
const enhancedUrls = resolveSitemapEntries(sitemap, resolvedSources, { autoI18n, isI18nMapped });
|
|
181
|
+
const filteredUrls = enhancedUrls.filter((e) => {
|
|
182
|
+
if (isMultiSitemap && e._sitemap && sitemap.sitemapName)
|
|
183
|
+
return e._sitemap === sitemap.sitemapName;
|
|
184
|
+
return true;
|
|
185
|
+
});
|
|
81
186
|
const sortedUrls = maybeSort(filteredUrls);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
urls: slicedUrls,
|
|
86
|
-
sitemapName: sitemap.sitemapName
|
|
87
|
-
};
|
|
88
|
-
await nitro.hooks.callHook("sitemap:resolved", ctx);
|
|
89
|
-
const urls = maybeSort(normaliseSitemapUrls(ctx.urls, resolvers));
|
|
187
|
+
return maybeSlice(sortedUrls);
|
|
188
|
+
}
|
|
189
|
+
export function urlsToXml(urls, resolvers, { version, xsl, credits, minify }) {
|
|
90
190
|
const urlset = urls.map((e) => {
|
|
91
191
|
const keys = Object.keys(e).filter((k) => !k.startsWith("_"));
|
|
92
192
|
return [
|
|
@@ -99,5 +199,5 @@ export async function buildSitemap(sitemap, resolvers, runtimeConfig) {
|
|
|
99
199
|
'<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
100
200
|
urlset.join("\n"),
|
|
101
201
|
"</urlset>"
|
|
102
|
-
], resolvers, { version, xsl, credits });
|
|
202
|
+
], resolvers, { version, xsl, credits, minify });
|
|
103
203
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ModuleRuntimeConfig, NitroUrlResolvers } from '../../../types.js';
|
|
2
2
|
export declare function handleEntry(k: string, e: Record<string, any> | (string | Record<string, any>)[]): string | false;
|
|
3
|
-
export declare function wrapSitemapXml(input: string[], resolvers: NitroUrlResolvers, options: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits'>): string;
|
|
3
|
+
export declare function wrapSitemapXml(input: string[], resolvers: NitroUrlResolvers, options: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;
|
|
4
4
|
export declare function escapeValueForXml(value: boolean | string | number): string;
|
|
@@ -74,6 +74,8 @@ export function wrapSitemapXml(input, resolvers, options) {
|
|
|
74
74
|
input.unshift(`<?xml version="1.0" encoding="UTF-8"?>${xsl ? `<?xml-stylesheet type="text/xsl" href="${xsl}"?>` : ""}`);
|
|
75
75
|
if (credits)
|
|
76
76
|
input.push(`<!-- XML Sitemap generated by @nuxtjs/sitemap v${options.version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
|
|
77
|
+
if (options.minify)
|
|
78
|
+
return input.join("").replace(/(?<!<[^>]*)\s(?![^<]*>)/g, "");
|
|
77
79
|
return input.join("\n");
|
|
78
80
|
}
|
|
79
81
|
export function escapeValueForXml(value) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
2
|
import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapDefinition } from '../../types.js';
|
|
3
3
|
export declare function useNitroUrlResolvers(e: H3Event): NitroUrlResolvers;
|
|
4
|
-
export declare function createSitemap(
|
|
4
|
+
export declare function createSitemap(event: H3Event, definition: SitemapDefinition, runtimeConfig: ModuleRuntimeConfig): Promise<string>;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { getQuery, setHeader } from "h3";
|
|
2
2
|
import { fixSlashes } from "site-config-stack/urls";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { useNitroApp } from "nitropack/runtime";
|
|
5
|
+
import { mergeOnKey, splitForLocales } from "../../utils-pure.js";
|
|
6
|
+
import { createNitroRouteRuleMatcher } from "../kit.js";
|
|
7
|
+
import { buildSitemapUrls, urlsToXml } from "./builder/sitemap.js";
|
|
8
|
+
import { normaliseEntry } from "./urlset/normalise.js";
|
|
9
|
+
import { sortSitemapUrls } from "./urlset/sort.js";
|
|
10
|
+
import { createSitePathResolver, getPathRobotConfig, useSiteConfig } from "#imports";
|
|
6
11
|
export function useNitroUrlResolvers(e) {
|
|
7
12
|
const canonicalQuery = getQuery(e).canonical;
|
|
8
13
|
const isShowingCanonical = typeof canonicalQuery !== "undefined" && canonicalQuery !== "false";
|
|
@@ -19,18 +24,49 @@ export function useNitroUrlResolvers(e) {
|
|
|
19
24
|
relativeBaseUrlResolver: createSitePathResolver(e, { absolute: false, withBase: true })
|
|
20
25
|
};
|
|
21
26
|
}
|
|
22
|
-
export async function createSitemap(
|
|
27
|
+
export async function createSitemap(event, definition, runtimeConfig) {
|
|
23
28
|
const { sitemapName } = definition;
|
|
24
29
|
const nitro = useNitroApp();
|
|
25
|
-
|
|
30
|
+
const resolvers = useNitroUrlResolvers(event);
|
|
31
|
+
let sitemapUrls = await buildSitemapUrls(definition, resolvers, runtimeConfig);
|
|
32
|
+
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
33
|
+
const { autoI18n } = runtimeConfig;
|
|
34
|
+
sitemapUrls = sitemapUrls.map((u) => {
|
|
35
|
+
const path = u._path?.pathname || u.loc;
|
|
36
|
+
if (!getPathRobotConfig(event, { path, skipSiteIndexable: true }).indexable)
|
|
37
|
+
return false;
|
|
38
|
+
let routeRules = routeRuleMatcher(path);
|
|
39
|
+
if (autoI18n?.locales && autoI18n?.strategy !== "no_prefix") {
|
|
40
|
+
const match = splitForLocales(path, autoI18n.locales.map((l) => l.code));
|
|
41
|
+
const pathWithoutPrefix = match[1];
|
|
42
|
+
if (pathWithoutPrefix && pathWithoutPrefix !== path)
|
|
43
|
+
routeRules = defu(routeRules, routeRuleMatcher(pathWithoutPrefix));
|
|
44
|
+
}
|
|
45
|
+
if (routeRules.sitemap === false)
|
|
46
|
+
return false;
|
|
47
|
+
if (typeof routeRules.index !== "undefined" && !routeRules.index || typeof routeRules.robots !== "undefined" && !routeRules.robots) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const hasRobotsDisabled = Object.entries(routeRules.headers || {}).some(([name, value]) => name.toLowerCase() === "x-robots-tag" && value.toLowerCase().includes("noindex"));
|
|
51
|
+
if (routeRules.redirect || hasRobotsDisabled)
|
|
52
|
+
return false;
|
|
53
|
+
return routeRules.sitemap ? defu(u, routeRules.sitemap) : u;
|
|
54
|
+
}).filter(Boolean);
|
|
55
|
+
const resolvedCtx = {
|
|
56
|
+
urls: sitemapUrls,
|
|
57
|
+
sitemapName
|
|
58
|
+
};
|
|
59
|
+
await nitro.hooks.callHook("sitemap:resolved", resolvedCtx);
|
|
60
|
+
const maybeSort = (urls2) => runtimeConfig.sortEntries ? sortSitemapUrls(urls2) : urls2;
|
|
61
|
+
const urls = maybeSort(mergeOnKey(resolvedCtx.urls.map((e) => normaliseEntry(e, definition.defaults, resolvers)), "_key"));
|
|
62
|
+
const sitemap = urlsToXml(urls, resolvers, runtimeConfig);
|
|
26
63
|
const ctx = { sitemap, sitemapName };
|
|
27
64
|
await nitro.hooks.callHook("sitemap:output", ctx);
|
|
28
|
-
|
|
29
|
-
setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
|
|
65
|
+
setHeader(event, "Content-Type", "text/xml; charset=UTF-8");
|
|
30
66
|
if (runtimeConfig.cacheMaxAgeSeconds)
|
|
31
|
-
setHeader(
|
|
67
|
+
setHeader(event, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
|
|
32
68
|
else
|
|
33
|
-
setHeader(
|
|
34
|
-
|
|
35
|
-
return sitemap;
|
|
69
|
+
setHeader(event, "Cache-Control", `no-cache, no-store`);
|
|
70
|
+
event.context._isSitemap = true;
|
|
71
|
+
return ctx.sitemap;
|
|
36
72
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { NitroUrlResolvers, ResolvedSitemapUrl,
|
|
2
|
-
export declare function
|
|
1
|
+
import type { NitroUrlResolvers, ResolvedSitemapUrl, SitemapUrl } from '../../../types.js';
|
|
2
|
+
export declare function preNormalizeEntry(_e: SitemapUrl | string): ResolvedSitemapUrl;
|
|
3
|
+
export declare function normaliseEntry(_e: ResolvedSitemapUrl, defaults: Omit<SitemapUrl, 'loc'>, resolvers?: NitroUrlResolvers): ResolvedSitemapUrl;
|
|
3
4
|
export declare function isValidW3CDate(d: string): boolean;
|
|
4
5
|
export declare function normaliseDate(date: string | Date): string;
|
|
@@ -1,66 +1,77 @@
|
|
|
1
|
-
import { hasProtocol } from "ufo";
|
|
2
|
-
import {
|
|
1
|
+
import { hasProtocol, parsePath, parseURL } from "ufo";
|
|
2
|
+
import { defu } from "defu";
|
|
3
3
|
import { mergeOnKey } from "../../../utils-pure.js";
|
|
4
4
|
function resolve(s, resolvers) {
|
|
5
|
-
if (typeof s === "undefined")
|
|
5
|
+
if (typeof s === "undefined" || !resolvers)
|
|
6
6
|
return s;
|
|
7
7
|
s = typeof s === "string" ? s : s.toString();
|
|
8
8
|
if (hasProtocol(s, { acceptRelative: true, strict: false }))
|
|
9
9
|
return resolvers.fixSlashes(s);
|
|
10
10
|
return resolvers.canonicalUrlResolver(s);
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
12
|
+
function removeTrailingSlash(s) {
|
|
13
|
+
return s.replace(/\/(\?|#|$)/, "$1");
|
|
14
|
+
}
|
|
15
|
+
export function preNormalizeEntry(_e) {
|
|
16
|
+
const e = typeof _e === "string" ? { loc: _e } : { ..._e };
|
|
17
|
+
if (e.url && !e.loc) {
|
|
18
|
+
e.loc = e.url;
|
|
19
|
+
delete e.url;
|
|
20
|
+
}
|
|
21
|
+
e.loc = removeTrailingSlash(e.loc || "");
|
|
22
|
+
e._abs = hasProtocol(e.loc, { acceptRelative: false, strict: false });
|
|
23
|
+
try {
|
|
24
|
+
e._path = e._abs ? parseURL(e.loc) : parsePath(e.loc);
|
|
25
|
+
} catch (e2) {
|
|
26
|
+
e2._path = null;
|
|
27
|
+
}
|
|
28
|
+
if (e._path?.pathname === "")
|
|
29
|
+
e.loc = `${e.loc}/`;
|
|
30
|
+
if (e._path) {
|
|
31
|
+
e._key = `${e._sitemap || ""}${e._path?.pathname || "/"}${e._path.search}`;
|
|
32
|
+
} else {
|
|
33
|
+
e._key = e.loc;
|
|
34
|
+
}
|
|
35
|
+
return e;
|
|
36
|
+
}
|
|
37
|
+
export function normaliseEntry(_e, defaults, resolvers) {
|
|
38
|
+
const e = defu(_e, defaults);
|
|
39
|
+
if (e.lastmod) {
|
|
40
|
+
const date = normaliseDate(e.lastmod);
|
|
41
|
+
if (date)
|
|
42
|
+
e.lastmod = date;
|
|
43
|
+
else
|
|
31
44
|
delete e.lastmod;
|
|
32
|
-
e.loc = resolve(e.loc, resolvers);
|
|
33
|
-
if (e.alternatives) {
|
|
34
|
-
e.alternatives = mergeOnKey(e.alternatives.map((e2) => {
|
|
35
|
-
const a = { ...e2 };
|
|
36
|
-
if (typeof a.href === "string")
|
|
37
|
-
a.href = resolve(a.href, resolvers);
|
|
38
|
-
else if (typeof a.href === "object" && a.href)
|
|
39
|
-
a.href = resolve(a.href.href, resolvers);
|
|
40
|
-
return a;
|
|
41
|
-
}), "hreflang");
|
|
42
|
-
}
|
|
43
|
-
if (e.images) {
|
|
44
|
-
e.images = mergeOnKey(e.images.map((i) => {
|
|
45
|
-
i = { ...i };
|
|
46
|
-
i.loc = resolve(i.loc, resolvers);
|
|
47
|
-
return i;
|
|
48
|
-
}), "loc");
|
|
49
|
-
}
|
|
50
|
-
if (e.videos) {
|
|
51
|
-
e.videos = e.videos.map((v) => {
|
|
52
|
-
v = { ...v };
|
|
53
|
-
if (v.content_loc)
|
|
54
|
-
v.content_loc = resolve(v.content_loc, resolvers);
|
|
55
|
-
return v;
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
return e;
|
|
59
45
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
46
|
+
if (!e.lastmod)
|
|
47
|
+
delete e.lastmod;
|
|
48
|
+
e.loc = resolve(e.loc, resolvers);
|
|
49
|
+
if (e.alternatives) {
|
|
50
|
+
e.alternatives = mergeOnKey(e.alternatives.map((e2) => {
|
|
51
|
+
const a = { ...e2 };
|
|
52
|
+
if (typeof a.href === "string")
|
|
53
|
+
a.href = resolve(a.href, resolvers);
|
|
54
|
+
else if (typeof a.href === "object" && a.href)
|
|
55
|
+
a.href = resolve(a.href.href, resolvers);
|
|
56
|
+
return a;
|
|
57
|
+
}), "hreflang");
|
|
58
|
+
}
|
|
59
|
+
if (e.images) {
|
|
60
|
+
e.images = mergeOnKey(e.images.map((i) => {
|
|
61
|
+
i = { ...i };
|
|
62
|
+
i.loc = resolve(i.loc, resolvers);
|
|
63
|
+
return i;
|
|
64
|
+
}), "loc");
|
|
65
|
+
}
|
|
66
|
+
if (e.videos) {
|
|
67
|
+
e.videos = e.videos.map((v) => {
|
|
68
|
+
v = { ...v };
|
|
69
|
+
if (v.content_loc)
|
|
70
|
+
v.content_loc = resolve(v.content_loc, resolvers);
|
|
71
|
+
return v;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return e;
|
|
64
75
|
}
|
|
65
76
|
const IS_VALID_W3C_DATE = [
|
|
66
77
|
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/,
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FetchOptions } from 'ofetch';
|
|
2
2
|
import type { H3Event } from 'h3';
|
|
3
|
+
import type { ParsedURL } from 'ufo';
|
|
3
4
|
export interface ModuleOptions extends SitemapDefinition {
|
|
4
5
|
/**
|
|
5
6
|
* Whether the sitemap.xml should be generated.
|
|
@@ -13,6 +14,12 @@ export interface ModuleOptions extends SitemapDefinition {
|
|
|
13
14
|
* @default false
|
|
14
15
|
*/
|
|
15
16
|
debug: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Minify the sitemap xml
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
minify: boolean;
|
|
16
23
|
/**
|
|
17
24
|
* Should lastmod be automatically added to the sitemap.
|
|
18
25
|
*
|
|
@@ -39,6 +46,12 @@ export interface ModuleOptions extends SitemapDefinition {
|
|
|
39
46
|
* @default false
|
|
40
47
|
*/
|
|
41
48
|
sitemaps?: boolean | MultiSitemapsInput;
|
|
49
|
+
/**
|
|
50
|
+
* The path prefix for the sitemaps.
|
|
51
|
+
*
|
|
52
|
+
* @default /__sitemap__/
|
|
53
|
+
*/
|
|
54
|
+
sitemapsPathPrefix: string;
|
|
42
55
|
/**
|
|
43
56
|
* Sitemaps to append to the sitemap index.
|
|
44
57
|
*
|
|
@@ -182,18 +195,19 @@ export interface SitemapSourceResolved extends Omit<SitemapSourceBase, 'urls'> {
|
|
|
182
195
|
}
|
|
183
196
|
export type AppSourceContext = 'nuxt:pages' | 'nuxt:prerender' | 'nuxt:route-rules' | '@nuxtjs/i18n:pages' | '@nuxt/content:document-driven';
|
|
184
197
|
export type SitemapSourceInput = string | [string, FetchOptions] | SitemapSourceBase | SitemapSourceResolved;
|
|
185
|
-
export
|
|
198
|
+
export interface NormalisedLocale {
|
|
186
199
|
code: string;
|
|
187
200
|
iso?: string;
|
|
188
201
|
domain?: string;
|
|
189
|
-
}
|
|
202
|
+
}
|
|
203
|
+
export type NormalisedLocales = NormalisedLocale[];
|
|
190
204
|
export interface AutoI18nConfig {
|
|
191
205
|
differentDomains?: boolean;
|
|
192
206
|
locales: NormalisedLocales;
|
|
193
207
|
defaultLocale: string;
|
|
194
208
|
strategy: 'prefix' | 'prefix_except_default' | 'prefix_and_default' | 'no_prefix';
|
|
195
209
|
}
|
|
196
|
-
export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits'> {
|
|
210
|
+
export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'sitemapsPathPrefix' | 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits' | 'minify'> {
|
|
197
211
|
version: string;
|
|
198
212
|
isNuxtContentDocumentDriven: boolean;
|
|
199
213
|
sitemaps: {
|
|
@@ -210,11 +224,28 @@ export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'cacheMaxAgeSec
|
|
|
210
224
|
export interface SitemapIndexEntry {
|
|
211
225
|
sitemap: string;
|
|
212
226
|
lastmod?: string;
|
|
227
|
+
/**
|
|
228
|
+
* @internal
|
|
229
|
+
*/
|
|
230
|
+
_sitemapName?: string;
|
|
213
231
|
}
|
|
214
232
|
export type FilterInput = (string | RegExp | {
|
|
215
233
|
regex: string;
|
|
216
234
|
});
|
|
217
|
-
export type ResolvedSitemapUrl = Omit<SitemapUrl, 'url'> & Required<Pick<SitemapUrl, 'loc'
|
|
235
|
+
export type ResolvedSitemapUrl = Omit<SitemapUrl, 'url'> & Required<Pick<SitemapUrl, 'loc'>> & {
|
|
236
|
+
/**
|
|
237
|
+
* @internal
|
|
238
|
+
*/
|
|
239
|
+
_key: string;
|
|
240
|
+
/**
|
|
241
|
+
* @internal
|
|
242
|
+
*/
|
|
243
|
+
_path: ParsedURL;
|
|
244
|
+
/**
|
|
245
|
+
* @internal
|
|
246
|
+
*/
|
|
247
|
+
_abs: boolean;
|
|
248
|
+
};
|
|
218
249
|
export interface SitemapDefinition {
|
|
219
250
|
/**
|
|
220
251
|
* A collection include patterns for filtering which URLs end up in the sitemap.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FilterInput } from './types.js';
|
|
2
|
+
export declare const logger: import("consola").ConsolaInstance;
|
|
2
3
|
export declare function mergeOnKey<T, K extends keyof T>(arr: T[], key: K): T[];
|
|
3
|
-
export declare function splitForLocales(path: string, locales: string[]):
|
|
4
|
+
export declare function splitForLocales(path: string, locales: string[]): [string | null, string];
|
|
4
5
|
/**
|
|
5
6
|
* Transform a literal notation string regex to RegExp
|
|
6
7
|
*/
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { createDefu } from "defu";
|
|
2
2
|
import { parseURL, withLeadingSlash } from "ufo";
|
|
3
3
|
import { createRouter, toRouteMatcher } from "radix3";
|
|
4
|
+
import { createConsola } from "consola";
|
|
5
|
+
export const logger = createConsola({
|
|
6
|
+
defaults: {
|
|
7
|
+
tag: "@nuxt/sitemap"
|
|
8
|
+
}
|
|
9
|
+
});
|
|
4
10
|
const merger = createDefu((obj, key, value) => {
|
|
5
11
|
if (Array.isArray(obj[key]) && Array.isArray(value))
|
|
6
12
|
obj[key] = Array.from(/* @__PURE__ */ new Set([...obj[key], ...value]));
|