@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.
Files changed (115) hide show
  1. package/dist/client/200.html +61 -54
  2. package/dist/client/404.html +61 -54
  3. package/dist/client/_nuxt/{D7WeZTai.js → -0RnDExV.js} +1 -1
  4. package/dist/client/_nuxt/{DOtRmeXT.js → -4dSXLqG.js} +1 -1
  5. package/dist/client/_nuxt/458cWEat.js +3 -0
  6. package/dist/client/_nuxt/{CFF2d1j6.js → BEZjiGez.js} +1 -1
  7. package/dist/client/_nuxt/{B3g-KkBK.js → BHqu4VKd.js} +1 -1
  8. package/dist/client/_nuxt/{D33OKbkv.js → BM5XuWfj.js} +1 -1
  9. package/dist/client/_nuxt/BMRpS3Xo.js +1 -0
  10. package/dist/client/_nuxt/{1rqFXsGc.js → BUinYsBq.js} +2 -2
  11. package/dist/client/_nuxt/BXP-NDAE.js +1 -0
  12. package/dist/client/_nuxt/{kuh6G-Sk.js → BZ035FK2.js} +1 -1
  13. package/dist/client/_nuxt/{DrnZp123.js → B_kA2_jD.js} +1 -1
  14. package/dist/client/_nuxt/BgSQePf4.js +1 -0
  15. package/dist/client/_nuxt/{CdedUr_-.js → BiVAY1KT.js} +1 -1
  16. package/dist/client/_nuxt/BpDWT_aG.js +1 -0
  17. package/dist/client/_nuxt/BpJyBuO9.js +1 -0
  18. package/dist/client/_nuxt/{BnyYJeap.js → Bpum8voz.js} +1 -1
  19. package/dist/client/_nuxt/Br9pa-sp.js +1 -0
  20. package/dist/client/_nuxt/BspO9hSn.js +1 -0
  21. package/dist/client/_nuxt/{DAP_O-zg.js → Bx64mzUw.js} +1 -1
  22. package/dist/client/_nuxt/Bym0hRiG.js +1 -0
  23. package/dist/client/_nuxt/C8DXlOXe.js +1 -0
  24. package/dist/client/_nuxt/{ECt0lbkd.js → CBks_G0r.js} +1 -1
  25. package/dist/client/_nuxt/COBxEbHI.js +1 -0
  26. package/dist/client/_nuxt/CPw9RxLe.js +1 -0
  27. package/dist/client/_nuxt/{dIHJ9UdL.js → CRYtL1Hd.js} +1 -1
  28. package/dist/client/_nuxt/CX3ZWouj.js +229 -0
  29. package/dist/client/_nuxt/{0ooBkv16.js → CaGCoJJM.js} +1 -1
  30. package/dist/client/_nuxt/Ctb_e1-I.js +1 -0
  31. package/dist/client/_nuxt/{AGFfX61t.js → CuOLCh11.js} +1 -1
  32. package/dist/client/_nuxt/{JgH_6NEN.js → CxBHuulF.js} +1 -1
  33. package/dist/client/_nuxt/{CJIaz0BQ.js → CxLlwT--.js} +1 -1
  34. package/dist/client/_nuxt/{B6bHXiXE.js → D3VHKxjW.js} +1 -1
  35. package/dist/client/_nuxt/D46m5Xd3.js +1 -0
  36. package/dist/client/_nuxt/D5OoM2Ul.js +1 -0
  37. package/dist/client/_nuxt/D5lQfeOG.js +1 -0
  38. package/dist/client/_nuxt/D8V69RRQ.js +1 -0
  39. package/dist/client/_nuxt/{CX_FIdg1.js → DDK5Hw8n.js} +1 -1
  40. package/dist/client/_nuxt/{C1yTBzia.js → DIyf2Ztx.js} +1 -1
  41. package/dist/client/_nuxt/{BZfs-ost.js → DOv5BRyJ.js} +1 -1
  42. package/dist/client/_nuxt/DQ-rpzxz.js +1 -0
  43. package/dist/client/_nuxt/DUsrs60I.js +6 -0
  44. package/dist/client/_nuxt/DV9_Ze0W.js +1 -0
  45. package/dist/client/_nuxt/{Bxkoe-BC.js → EQHFthT6.js} +1 -1
  46. package/dist/client/_nuxt/Ev-gWqHG.js +1 -0
  47. package/dist/client/_nuxt/{BacI6-DX.js → FRbOFgZn.js} +1 -1
  48. package/dist/client/_nuxt/{CqYeW6XZ.js → Gme1ZbSQ.js} +1 -1
  49. package/dist/client/_nuxt/{Br6ll-O0.js → NrGJGX17.js} +1 -1
  50. package/dist/client/_nuxt/{CarfVElc.js → ULUzDaxg.js} +1 -1
  51. package/dist/client/_nuxt/USEQoosB.js +31 -0
  52. package/dist/client/_nuxt/{DGDuLtS6.js → V16qqttt.js} +1 -1
  53. package/dist/client/_nuxt/builds/latest.json +1 -1
  54. package/dist/client/_nuxt/builds/meta/99e0fea3-c4e8-45fe-88b0-f49b86d00f5b.json +1 -0
  55. package/dist/client/_nuxt/d42HzezM.js +1 -0
  56. package/dist/client/_nuxt/entry.BnSVD-Km.css +1 -0
  57. package/dist/client/_nuxt/error-404.BOXiSWAJ.css +1 -0
  58. package/dist/client/_nuxt/error-500.DmKlUOlN.css +1 -0
  59. package/dist/client/_nuxt/{BXR915QZ.js → ewRyznZJ.js} +1 -1
  60. package/dist/client/_nuxt/{BVLuctcA.js → vMuZBeRS.js} +1 -1
  61. package/dist/client/_nuxt/{Bj5xdiaE.js → xuIuMB9j.js} +1 -1
  62. package/dist/client/_nuxt/{ChMCFiS0.js → zIdFMUa4.js} +1 -1
  63. package/dist/client/_nuxt/{BVkeqZ59.js → zbShYgi7.js} +1 -1
  64. package/dist/client/index.html +61 -54
  65. package/dist/module.d.mts +355 -1
  66. package/dist/module.d.ts +355 -1
  67. package/dist/module.json +2 -2
  68. package/dist/module.mjs +178 -32
  69. package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.d.ts +2 -1
  70. package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.js +1 -1
  71. package/dist/runtime/nitro/routes/__sitemap__/debug.d.ts +8 -6
  72. package/dist/runtime/nitro/{middleware/[sitemap]-sitemap.xml.d.ts → routes/sitemap/[sitemap].xml.d.ts} +1 -1
  73. package/dist/runtime/nitro/routes/sitemap/[sitemap].xml.js +20 -0
  74. package/dist/runtime/nitro/routes/sitemap.xsl.js +2 -1
  75. package/dist/runtime/nitro/routes/sitemap_index.xml.js +19 -16
  76. package/dist/runtime/nitro/sitemap/builder/sitemap-index.d.ts +3 -2
  77. package/dist/runtime/nitro/sitemap/builder/sitemap-index.js +14 -28
  78. package/dist/runtime/nitro/sitemap/builder/sitemap.d.ts +9 -2
  79. package/dist/runtime/nitro/sitemap/builder/sitemap.js +154 -54
  80. package/dist/runtime/nitro/sitemap/builder/xml.d.ts +1 -1
  81. package/dist/runtime/nitro/sitemap/builder/xml.js +2 -0
  82. package/dist/runtime/nitro/sitemap/nitro.d.ts +1 -1
  83. package/dist/runtime/nitro/sitemap/nitro.js +47 -11
  84. package/dist/runtime/nitro/sitemap/urlset/normalise.d.ts +3 -2
  85. package/dist/runtime/nitro/sitemap/urlset/normalise.js +64 -53
  86. package/dist/runtime/types.d.ts +35 -4
  87. package/dist/runtime/utils-pure.d.ts +2 -1
  88. package/dist/runtime/utils-pure.js +6 -0
  89. package/package.json +24 -25
  90. package/dist/client/_nuxt/3ghuYFLd.js +0 -1
  91. package/dist/client/_nuxt/9B1nZgL-.js +0 -1
  92. package/dist/client/_nuxt/BG-qYwi8.js +0 -6
  93. package/dist/client/_nuxt/BIxS-Weu.js +0 -1
  94. package/dist/client/_nuxt/BYdKNJ10.js +0 -1
  95. package/dist/client/_nuxt/Bi43K_FX.js +0 -6
  96. package/dist/client/_nuxt/CBPJd_fO.js +0 -1
  97. package/dist/client/_nuxt/CCqFro8U.js +0 -3
  98. package/dist/client/_nuxt/CEfge3mM.js +0 -1
  99. package/dist/client/_nuxt/CSPeAESR.js +0 -1
  100. package/dist/client/_nuxt/D0mw_hZ2.js +0 -31
  101. package/dist/client/_nuxt/DGO8GyiP.js +0 -1
  102. package/dist/client/_nuxt/DOHBU7tp.js +0 -1
  103. package/dist/client/_nuxt/DQoqAi02.js +0 -1
  104. package/dist/client/_nuxt/DVLwECkk.js +0 -1
  105. package/dist/client/_nuxt/Du6_OKDb.js +0 -159
  106. package/dist/client/_nuxt/builds/meta/ab2ad6a2-f67d-4194-8e33-d46fbc5d1290.json +0 -1
  107. package/dist/client/_nuxt/eJfcURhx.js +0 -1
  108. package/dist/client/_nuxt/entry.CfxF9LiM.css +0 -1
  109. package/dist/client/_nuxt/error-404.D56ZPmHb.css +0 -1
  110. package/dist/client/_nuxt/error-500.BYEp4uQX.css +0 -1
  111. package/dist/runtime/nitro/middleware/[sitemap]-sitemap.xml.js +0 -23
  112. package/dist/runtime/nitro/sitemap/urlset/filter.d.ts +0 -5
  113. package/dist/runtime/nitro/sitemap/urlset/filter.js +0 -24
  114. package/dist/runtime/nitro/sitemap/urlset/i18n.d.ts +0 -6
  115. 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 { parseURL, withHttps } from "ufo";
4
- import { normaliseSitemapUrls } from "../urlset/normalise.js";
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 "../../utils.js";
10
- import { createNitroRouteRuleMatcher } from "../../kit.js";
6
+ import { createPathFilter, logger, splitForLocales } from "../../../utils-pure.js";
11
7
  import { handleEntry, wrapSitemapXml } from "./xml.js";
12
- import { useNitroApp } from "#imports";
13
- export async function buildSitemap(sitemap, resolvers, runtimeConfig) {
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(urls2) {
31
- return sortEntries ? sortSitemapUrls(urls2) : urls2;
154
+ function maybeSort(urls) {
155
+ return sortEntries ? sortSitemapUrls(urls) : urls;
32
156
  }
33
- function maybeSlice(urls2) {
157
+ function maybeSlice(urls) {
34
158
  if (isChunking && defaultSitemapsChunkSize) {
35
159
  const chunk = Number(sitemap.sitemapName);
36
- return urls2.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize);
160
+ return urls.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize);
37
161
  }
38
- return urls2;
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
- let resolvedSources = await resolveSitemapSources(sources, resolvers.event);
56
- if (autoI18n)
57
- resolvedSources = normaliseI18nSources(resolvedSources, { autoI18n, isI18nMapped, ...sitemap });
58
- const normalisedUrls = normaliseSitemapUrls(resolvedSources.map((e) => e.urls).flat(), resolvers);
59
- const routeRuleMatcher = createNitroRouteRuleMatcher();
60
- let enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults)).map((e) => {
61
- const path = parseURL(e.loc).pathname;
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
- const slicedUrls = maybeSlice(sortedUrls);
83
- const nitro = useNitroApp();
84
- const ctx = {
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(e: H3Event, definition: SitemapDefinition, runtimeConfig: ModuleRuntimeConfig): Promise<string>;
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 { buildSitemap } from "./builder/sitemap.js";
4
- import { buildSitemapIndex } from "./builder/sitemap-index.js";
5
- import { createSitePathResolver, useNitroApp, useSiteConfig } from "#imports";
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(e, definition, runtimeConfig) {
27
+ export async function createSitemap(event, definition, runtimeConfig) {
23
28
  const { sitemapName } = definition;
24
29
  const nitro = useNitroApp();
25
- let sitemap = await (definition.sitemapName === "index" ? buildSitemapIndex(useNitroUrlResolvers(e), runtimeConfig) : buildSitemap(definition, useNitroUrlResolvers(e), runtimeConfig));
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
- sitemap = ctx.sitemap;
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(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
67
+ setHeader(event, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
32
68
  else
33
- setHeader(e, "Cache-Control", `no-cache, no-store`);
34
- e.context._isSitemap = true;
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, SitemapUrlInput } from '../../../types.js';
2
- export declare function normaliseSitemapUrls(data: SitemapUrlInput[], resolvers: NitroUrlResolvers): ResolvedSitemapUrl[];
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 { fixSlashes } from "site-config-stack/urls";
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
- export function normaliseSitemapUrls(data, resolvers) {
13
- const entries = data.map((e) => typeof e === "string" ? { loc: e } : e).map((e) => {
14
- e = { ...e };
15
- if (e.url) {
16
- e.loc = e.url;
17
- delete e.url;
18
- }
19
- e.loc = fixSlashes(false, e.loc);
20
- return e;
21
- }).filter(Boolean);
22
- function normaliseEntry(e) {
23
- if (e.lastmod) {
24
- const date = normaliseDate(e.lastmod);
25
- if (date)
26
- e.lastmod = date;
27
- else
28
- delete e.lastmod;
29
- }
30
- if (!e.lastmod)
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
- return mergeOnKey(
61
- entries.map(normaliseEntry).map((e) => ({ ...e, _key: `${e._sitemap || ""}${e.loc}` })),
62
- "_key"
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))/,
@@ -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 type NormalisedLocales = {
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[]): (string | null)[];
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]));