@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
package/dist/module.json CHANGED
@@ -5,9 +5,9 @@
5
5
  "bridge": false
6
6
  },
7
7
  "configKey": "sitemap",
8
- "version": "5.3.4",
8
+ "version": "6.0.0-beta.1",
9
9
  "builder": {
10
- "@nuxt/module-builder": "0.8.1",
10
+ "@nuxt/module-builder": "0.8.3",
11
11
  "unbuild": "2.0.0"
12
12
  }
13
13
  }
package/dist/module.mjs CHANGED
@@ -1,18 +1,81 @@
1
1
  import { useNuxt, loadNuxtModuleInstance, createResolver, addTemplate, extendPages, defineNuxtModule, useLogger, hasNuxtModule, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addServerPlugin, addServerHandler, findPath, addPrerenderRoutes } from '@nuxt/kit';
2
- import { withHttps, withBase, parseURL, joinURL, withoutLeadingSlash } from 'ufo';
2
+ import { withLeadingSlash, parseURL, withHttps, withBase, joinURL, withoutLeadingSlash, withoutTrailingSlash } from 'ufo';
3
3
  import { assertSiteConfig, installNuxtSiteConfig } from 'nuxt-site-config-kit';
4
- import { defu } from 'defu';
4
+ import { createDefu, defu } from 'defu';
5
5
  import { readPackageJSON } from 'pkg-types';
6
6
  import { statSync, existsSync } from 'node:fs';
7
7
  import { extname, relative, dirname } from 'pathe';
8
- import { createPathFilter, splitForLocales, mergeOnKey } from '../dist/runtime/utils-pure.js';
8
+ import { toRouteMatcher, createRouter } from 'radix3';
9
+ import { createConsola } from 'consola';
9
10
  import { provider, env } from 'std-env';
10
11
  import { mkdir, writeFile } from 'node:fs/promises';
11
12
  import { join } from 'node:path';
12
13
  import chalk from 'chalk';
13
14
  import { build } from 'nitropack';
14
15
  import { withSiteUrl } from 'nuxt-site-config-kit/urls';
15
- import { normaliseDate } from '../dist/runtime/nitro/sitemap/urlset/normalise.js';
16
+
17
+ createConsola({
18
+ defaults: {
19
+ tag: "@nuxt/sitemap"
20
+ }
21
+ });
22
+ const merger = createDefu((obj, key, value) => {
23
+ if (Array.isArray(obj[key]) && Array.isArray(value))
24
+ obj[key] = Array.from(/* @__PURE__ */ new Set([...obj[key], ...value]));
25
+ return obj[key];
26
+ });
27
+ function mergeOnKey(arr, key) {
28
+ const res = {};
29
+ arr.forEach((item) => {
30
+ const k = item[key];
31
+ res[k] = merger(item, res[k] || {});
32
+ });
33
+ return Object.values(res);
34
+ }
35
+ function splitForLocales(path, locales) {
36
+ const prefix = withLeadingSlash(path).split("/")[1];
37
+ if (locales.includes(prefix))
38
+ return [prefix, path.replace(`/${prefix}`, "")];
39
+ return [null, path];
40
+ }
41
+ function createPathFilter(options = {}) {
42
+ const urlFilter = createFilter(options);
43
+ return (loc) => {
44
+ let path = loc;
45
+ try {
46
+ path = parseURL(loc).pathname;
47
+ } catch {
48
+ return false;
49
+ }
50
+ return urlFilter(path);
51
+ };
52
+ }
53
+ function createFilter(options = {}) {
54
+ const include = options.include || [];
55
+ const exclude = options.exclude || [];
56
+ if (include.length === 0 && exclude.length === 0)
57
+ return () => true;
58
+ return function(path) {
59
+ for (const v of [{ rules: exclude, result: false }, { rules: include, result: true }]) {
60
+ const regexRules = v.rules.filter((r) => r instanceof RegExp);
61
+ if (regexRules.some((r) => r.test(path)))
62
+ return v.result;
63
+ const stringRules = v.rules.filter((r) => typeof r === "string");
64
+ if (stringRules.length > 0) {
65
+ const routes = {};
66
+ for (const r of stringRules) {
67
+ if (r === path)
68
+ return v.result;
69
+ routes[r] = true;
70
+ }
71
+ const routeRulesMatcher = toRouteMatcher(createRouter({ routes, strictTrailingSlash: false }));
72
+ if (routeRulesMatcher.matchAll(path).length > 0)
73
+ return Boolean(v.result);
74
+ }
75
+ }
76
+ return include.length === 0;
77
+ };
78
+ }
16
79
 
17
80
  async function resolveUrls(urls, ctx) {
18
81
  if (typeof urls === "function")
@@ -237,7 +300,7 @@ function resolveNitroPreset(nitroConfig) {
237
300
  if (nitroConfig && nitroConfig?.preset)
238
301
  preset = nitroConfig.preset;
239
302
  if (!preset)
240
- preset = env.NITRO_PRESET || detectTarget() || "node-server";
303
+ preset = env.NITRO_PRESET || env.SERVER_PRESET || detectTarget() || "node-server";
241
304
  return preset.replace("_", "-");
242
305
  }
243
306
 
@@ -354,9 +417,14 @@ function isNuxtGenerate(nuxt = useNuxt()) {
354
417
  "github-pages"
355
418
  ].includes(resolveNitroPreset());
356
419
  }
357
- function setupPrerenderHandler(options, nuxt = useNuxt()) {
420
+ function setupPrerenderHandler(_options, nuxt = useNuxt()) {
421
+ const { runtimeConfig: options, logger } = _options;
358
422
  const prerenderedRoutes = nuxt.options.nitro.prerender?.routes || [];
359
- const prerenderSitemap = isNuxtGenerate() || includesSitemapRoot(options.sitemapName, prerenderedRoutes);
423
+ let prerenderSitemap = isNuxtGenerate() || includesSitemapRoot(options.sitemapName, prerenderedRoutes);
424
+ if (resolveNitroPreset() === "vercel-edge") {
425
+ logger.warn("Runtime sitemaps are not supported on Vercel Edge, falling back to prerendering sitemaps.");
426
+ prerenderSitemap = true;
427
+ }
360
428
  if (nuxt.options.nitro.prerender?.routes)
361
429
  nuxt.options.nitro.prerender.routes = nuxt.options.nitro.prerender.routes.filter((r) => r && !includesSitemapRoot(options.sitemapName, [r]));
362
430
  nuxt.hooks.hook("nitro:init", async (nitro) => {
@@ -478,6 +546,38 @@ function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
478
546
  });
479
547
  }
480
548
 
549
+ const IS_VALID_W3C_DATE = [
550
+ /(\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))/,
551
+ /^\d{4}-[01]\d-[0-3]\d$/,
552
+ /^\d{4}-[01]\d$/,
553
+ /^\d{4}$/
554
+ ];
555
+ function isValidW3CDate(d) {
556
+ return IS_VALID_W3C_DATE.some((r) => r.test(d));
557
+ }
558
+ function normaliseDate(d) {
559
+ if (typeof d === "string") {
560
+ if (d.includes("T")) {
561
+ const t = d.split("T")[1];
562
+ if (!t.includes("+") && !t.includes("-") && !t.includes("Z")) {
563
+ d += "Z";
564
+ }
565
+ }
566
+ if (!isValidW3CDate(d))
567
+ return false;
568
+ d = new Date(d);
569
+ d.setMilliseconds(0);
570
+ if (Number.isNaN(d.getTime()))
571
+ return false;
572
+ }
573
+ const z = (n) => `0${n}`.slice(-2);
574
+ const date = `${d.getUTCFullYear()}-${z(d.getUTCMonth() + 1)}-${z(d.getUTCDate())}`;
575
+ if (d.getUTCHours() > 0 || d.getUTCMinutes() > 0 || d.getUTCSeconds() > 0) {
576
+ return `${date}T${z(d.getUTCHours())}:${z(d.getUTCMinutes())}:${z(d.getUTCSeconds())}Z`;
577
+ }
578
+ return date;
579
+ }
580
+
481
581
  function splitPathForI18nLocales(path, autoI18n) {
482
582
  const locales = autoI18n.strategy === "prefix_except_default" ? autoI18n.locales.filter((l) => l.code !== autoI18n.defaultLocale) : autoI18n.locales;
483
583
  if (typeof path !== "string" || path.startsWith("/_"))
@@ -491,6 +591,13 @@ function splitPathForI18nLocales(path, autoI18n) {
491
591
  ...locales.map((l) => `/${l.code}${path}`)
492
592
  ];
493
593
  }
594
+ function getExcludedLocalesFromI18nConfig(nuxtI18nConfig) {
595
+ const onlyLocales = nuxtI18nConfig?.bundle?.onlyLocales;
596
+ if (!onlyLocales)
597
+ return [];
598
+ const excludedLocales = typeof onlyLocales === "string" ? [onlyLocales] : onlyLocales;
599
+ return excludedLocales;
600
+ }
494
601
  function generatePathForI18nPages(ctx) {
495
602
  const { localeCode, pageLocales, nuxtI18nConfig, forcedStrategy, normalisedLocales } = ctx;
496
603
  const locale = normalisedLocales.find((l) => l.code === localeCode);
@@ -540,6 +647,7 @@ const module = defineNuxtModule({
540
647
  credits: true,
541
648
  cacheMaxAgeSeconds: 60 * 10,
542
649
  // cache for 10 minutes
650
+ minify: false,
543
651
  debug: false,
544
652
  defaultSitemapsChunkSize: 1e3,
545
653
  autoLastmod: false,
@@ -548,6 +656,7 @@ const module = defineNuxtModule({
548
656
  dynamicUrlsApiEndpoint: "/api/_sitemap-urls",
549
657
  urls: [],
550
658
  sortEntries: true,
659
+ sitemapsPathPrefix: "/__sitemap__/",
551
660
  xsl: "/__sitemap__/style.xsl",
552
661
  xslTips: true,
553
662
  strictNuxtContentPaths: false,
@@ -592,15 +701,17 @@ const module = defineNuxtModule({
592
701
  if (!nuxt.options._prepare && Object.keys(normalizedSitemaps).length) {
593
702
  const isSitemapIndexOnly = typeof normalizedSitemaps?.index !== "undefined" && Object.keys(normalizedSitemaps).length === 1;
594
703
  if (!isSitemapIndexOnly) {
595
- const invalidRootKeys = [
596
- "includeAppSources",
597
- "sources"
598
- ];
599
- for (const key of invalidRootKeys) {
600
- if (Object.keys(config).includes(key)) {
601
- logger.warn(`You are using multiple-sitemaps but have provided \`sitemap.${key}\` in your Nuxt config. This will be ignored, please move it to the child sitemap config.`);
602
- logger.warn("Learn more at: https://nuxtseo.com/sitemap/guides/multi-sitemaps");
603
- }
704
+ const warnForIgnoredKey = (key) => {
705
+ logger.warn(`You are using multiple-sitemaps but have provided \`sitemap.${key}\` in your Nuxt config. This will be ignored, please move it to the child sitemap config.`);
706
+ logger.warn("Learn more at: https://nuxtseo.com/sitemap/guides/multi-sitemaps");
707
+ };
708
+ switch (true) {
709
+ case config?.sources?.length !== 0:
710
+ warnForIgnoredKey("sources");
711
+ break;
712
+ case config?.includeAppSources !== void 0:
713
+ warnForIgnoredKey("includeAppSources");
714
+ break;
604
715
  }
605
716
  }
606
717
  }
@@ -624,13 +735,15 @@ const module = defineNuxtModule({
624
735
  let resolvedAutoI18n = typeof config.autoI18n === "boolean" ? false : config.autoI18n || false;
625
736
  const hasDisabledAutoI18n = typeof config.autoI18n === "boolean" && !config.autoI18n;
626
737
  let normalisedLocales = [];
738
+ let usingI18nPages = false;
627
739
  if (hasNuxtModule("@nuxtjs/i18n")) {
628
740
  const i18nVersion = await getNuxtModuleVersion("@nuxtjs/i18n");
629
741
  if (!await hasNuxtModuleCompatibility("@nuxtjs/i18n", ">=8"))
630
742
  logger.warn(`You are using @nuxtjs/i18n v${i18nVersion}. For the best compatibility, please upgrade to @nuxtjs/i18n v8.0.0 or higher.`);
631
743
  nuxtI18nConfig = await getNuxtModuleOptions("@nuxtjs/i18n") || {};
632
- normalisedLocales = mergeOnKey((nuxtI18nConfig.locales || []).map((locale) => typeof locale === "string" ? { code: locale } : locale), "code");
633
- const usingI18nPages = Object.keys(nuxtI18nConfig.pages || {}).length;
744
+ const excludedLocales = getExcludedLocalesFromI18nConfig(nuxtI18nConfig);
745
+ normalisedLocales = mergeOnKey((nuxtI18nConfig.locales || []).map((locale) => typeof locale === "string" ? { code: locale } : locale), "code").filter((locale) => !excludedLocales.includes(locale.code));
746
+ usingI18nPages = !!Object.keys(nuxtI18nConfig.pages || {}).length;
634
747
  if (usingI18nPages && !hasDisabledAutoI18n) {
635
748
  const i18nPagesSources = {
636
749
  context: {
@@ -773,8 +886,10 @@ declare module 'vue-router' {
773
886
  nuxt.options.nitro.routeRules["/sitemap.xml"] = { redirect: "/sitemap_index.xml" };
774
887
  nuxt.options.nitro.routeRules["/sitemap_index.xml"] = routeRules;
775
888
  if (typeof config.sitemaps === "object") {
776
- for (const k in config.sitemaps)
777
- nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = routeRules;
889
+ for (const k in config.sitemaps) {
890
+ nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix, `/${k}.xml`)] = routeRules;
891
+ nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = { redirect: joinURL(config.sitemapsPathPrefix, `${k}.xml`) };
892
+ }
778
893
  } else {
779
894
  nuxt.options.nitro.routeRules[`/${config.sitemapName}`] = routeRules;
780
895
  }
@@ -831,7 +946,15 @@ declare module 'vue-router' {
831
946
  if (usingMultiSitemaps) {
832
947
  addServerHandler({
833
948
  route: "/sitemap_index.xml",
834
- handler: resolve("./runtime/nitro/routes/sitemap_index.xml")
949
+ handler: resolve("./runtime/nitro/routes/sitemap_index.xml"),
950
+ lazy: true,
951
+ middleware: false
952
+ });
953
+ addServerHandler({
954
+ route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
955
+ handler: resolve("./runtime/nitro/routes/sitemap/[sitemap].xml"),
956
+ lazy: true,
957
+ middleware: false
835
958
  });
836
959
  sitemaps.index = {
837
960
  sitemapName: "index",
@@ -843,15 +966,11 @@ declare module 'vue-router' {
843
966
  for (const sitemapName in config.sitemaps) {
844
967
  if (sitemapName === "index")
845
968
  continue;
846
- addServerHandler({
847
- route: `/${sitemapName}-sitemap.xml`,
848
- handler: resolve("./runtime/nitro/middleware/[sitemap]-sitemap.xml")
849
- });
850
969
  const definition = config.sitemaps[sitemapName];
851
970
  sitemaps[sitemapName] = defu(
852
971
  {
853
972
  sitemapName,
854
- _route: withBase(`${sitemapName}-sitemap.xml`, nuxt.options.app.baseURL || "/"),
973
+ _route: withBase(`sitemap/${sitemapName}.xml`, nuxt.options.app.baseURL || "/"),
855
974
  _hasSourceChunk: typeof definition.urls !== "undefined" || definition.sources?.length || !!definition.dynamicUrlsApiEndpoint
856
975
  },
857
976
  { ...definition, urls: void 0, sources: void 0 },
@@ -859,9 +978,6 @@ declare module 'vue-router' {
859
978
  );
860
979
  }
861
980
  } else {
862
- addServerHandler({
863
- handler: resolve("./runtime/nitro/middleware/[sitemap]-sitemap.xml")
864
- });
865
981
  sitemaps.chunks = {
866
982
  sitemapName: "chunks",
867
983
  defaults: config.defaults,
@@ -881,6 +997,31 @@ declare module 'vue-router' {
881
997
  includeAppSources: true
882
998
  };
883
999
  }
1000
+ if (resolvedAutoI18n && usingI18nPages && !hasDisabledAutoI18n) {
1001
+ const pages = nuxtI18nConfig?.pages || {};
1002
+ for (const sitemapName in sitemaps) {
1003
+ let mapToI18nPages = function(path) {
1004
+ if (typeof path !== "string")
1005
+ return [path];
1006
+ const withoutSlashes = withoutTrailingSlash(withoutLeadingSlash(path)).replace("/index", "");
1007
+ if (withoutSlashes in pages) {
1008
+ const pageLocales = pages[withoutSlashes];
1009
+ return Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({ localeCode, pageLocales: pageLocales[localeCode], nuxtI18nConfig, normalisedLocales })));
1010
+ }
1011
+ let match = [path];
1012
+ Object.values(pages).forEach((pageLocales) => {
1013
+ if (nuxtI18nConfig.defaultLocale in pageLocales && pageLocales[nuxtI18nConfig.defaultLocale] === path)
1014
+ match = Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({ localeCode, pageLocales: pageLocales[localeCode], nuxtI18nConfig, normalisedLocales })));
1015
+ });
1016
+ return match;
1017
+ };
1018
+ if (["index", "chunks"].includes(sitemapName))
1019
+ continue;
1020
+ const sitemap = sitemaps[sitemapName];
1021
+ sitemap.include = (sitemap.include || []).flatMap((path) => mapToI18nPages(path));
1022
+ sitemap.exclude = (sitemap.exclude || []).flatMap((path) => mapToI18nPages(path));
1023
+ }
1024
+ }
884
1025
  if (resolvedAutoI18n && resolvedAutoI18n.locales && resolvedAutoI18n.strategy !== "no_prefix") {
885
1026
  const i18n = resolvedAutoI18n;
886
1027
  for (const sitemapName in sitemaps) {
@@ -904,11 +1045,13 @@ declare module 'vue-router' {
904
1045
  cacheMaxAgeSeconds: nuxt.options.dev ? 0 : config.cacheMaxAgeSeconds,
905
1046
  autoLastmod: config.autoLastmod,
906
1047
  defaultSitemapsChunkSize: config.defaultSitemapsChunkSize,
1048
+ minify: config.minify,
907
1049
  sortEntries: config.sortEntries,
908
1050
  debug: config.debug,
909
1051
  // needed for nuxt/content integration and prerendering
910
1052
  discoverImages: config.discoverImages,
911
1053
  discoverVideos: config.discoverVideos,
1054
+ sitemapsPathPrefix: config.sitemapsPathPrefix,
912
1055
  /* @nuxt/content */
913
1056
  isNuxtContentDocumentDriven,
914
1057
  /* xsl styling */
@@ -951,8 +1094,11 @@ declare module 'vue-router' {
951
1094
  const prerenderUrlsFinal = [
952
1095
  ...prerenderUrls,
953
1096
  ...((await nitroPromise)._prerenderedRoutes || []).filter((r) => {
954
- const isExplicitFile = r.route.split("/").pop().includes(".");
955
- return r.contentType?.includes("text/html") && !isExplicitFile;
1097
+ const lastSegment = r.route.split("/").pop();
1098
+ const isExplicitFile = !!lastSegment?.match(/\.[0-9a-z]+$/i)?.[0];
1099
+ if (r.error || ["/200.html", "/404.html", "/index.html"].includes(r.route))
1100
+ return false;
1101
+ return r.contentType?.includes("text/html") || !isExplicitFile;
956
1102
  }).map((r) => r._sitemap)
957
1103
  ];
958
1104
  const pageSource = convertNuxtPagesToSitemapEntries(await pagesPromise, {
@@ -1084,7 +1230,7 @@ declare module 'vue-router' {
1084
1230
  route: `/${config.sitemapName}`,
1085
1231
  handler: resolve("./runtime/nitro/routes/sitemap.xml")
1086
1232
  });
1087
- setupPrerenderHandler(runtimeConfig);
1233
+ setupPrerenderHandler({ runtimeConfig, logger });
1088
1234
  }
1089
1235
  });
1090
1236
 
@@ -1,4 +1,5 @@
1
- export declare function getPathRobotConfigPolyfill(): {
1
+ import type { H3Event } from 'h3';
2
+ export declare function getPathRobotConfigPolyfill(e: H3Event, options: any): {
2
3
  indexable: boolean;
3
4
  rule: string;
4
5
  };
@@ -1,3 +1,3 @@
1
- export function getPathRobotConfigPolyfill() {
1
+ export function getPathRobotConfigPolyfill(e, options) {
2
2
  return { indexable: true, rule: "index, follow" };
3
3
  }
@@ -6,24 +6,25 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
6
6
  version: string;
7
7
  isNuxtContentDocumentDriven: boolean;
8
8
  sitemaps: {
9
- index?: (Pick<SitemapDefinition, "sitemapName" | "_route"> & {
9
+ index?: Pick<SitemapDefinition, "sitemapName" | "_route"> & {
10
10
  sitemaps: import("../../../types").SitemapIndexEntry[];
11
- }) | undefined;
11
+ };
12
12
  } & Record<string, Omit<SitemapDefinition, "urls"> & {
13
- _hasSourceChunk?: boolean | undefined;
13
+ _hasSourceChunk?: boolean;
14
14
  }>;
15
- autoI18n?: import("../../../types").AutoI18nConfig | undefined;
15
+ autoI18n?: import("../../../types").AutoI18nConfig;
16
16
  isMultiSitemap: boolean;
17
17
  isI18nMapped: boolean;
18
+ sitemapsPathPrefix: string;
18
19
  cacheMaxAgeSeconds: number | false;
19
20
  sitemapName: string;
20
- excludeAppSources: true | import("../../../types").AppSourceContext[];
21
+ excludeAppSources: true | (import("../../../types").AppSourceContext[]);
21
22
  sortEntries: boolean;
22
23
  defaultSitemapsChunkSize: number | false;
23
24
  xslColumns?: {
24
25
  label: string;
25
26
  width: `${string}%`;
26
- select?: string | undefined;
27
+ select?: string;
27
28
  }[] | undefined;
28
29
  xslTips: boolean;
29
30
  debug: boolean;
@@ -32,6 +33,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
32
33
  autoLastmod: boolean;
33
34
  xsl: string | false;
34
35
  credits: boolean;
36
+ minify: boolean;
35
37
  };
36
38
  globalSources: import("../../../types").SitemapSourceResolved[];
37
39
  }>>;
@@ -1,2 +1,2 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<string | import("h3").H3Error<unknown> | undefined>>;
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<string | import("h3").H3Error<unknown>>>;
2
2
  export default _default;
@@ -0,0 +1,20 @@
1
+ import { createError, defineEventHandler, getRouterParam } from "h3";
2
+ import { withoutLeadingSlash, withoutTrailingSlash } from "ufo";
3
+ import { useSimpleSitemapRuntimeConfig } from "../../utils.js";
4
+ import { createSitemap } from "../../sitemap/nitro.js";
5
+ export default defineEventHandler(async (e) => {
6
+ const runtimeConfig = useSimpleSitemapRuntimeConfig(e);
7
+ const { sitemaps } = runtimeConfig;
8
+ const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, "sitemap") || e.path)?.replace(".xml", "").replace(runtimeConfig.sitemapsPathPrefix, "")));
9
+ const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemapName));
10
+ if (!sitemapName || !(sitemapName in sitemaps) && !isChunking) {
11
+ return createError({
12
+ statusCode: 404,
13
+ message: `Sitemap "${sitemapName}" not found.`
14
+ });
15
+ }
16
+ return createSitemap(e, isChunking ? {
17
+ ...sitemaps.chunks,
18
+ sitemapName
19
+ } : sitemaps[sitemapName], runtimeConfig);
20
+ });
@@ -14,7 +14,8 @@ export default defineEventHandler(async (e) => {
14
14
  const creditName = `<a href="https://github.com/nuxt-modules/sitemap" style="color: black; display: flex; align-items: center; font-weight: 500;" target="_blank" rel="noopener">${svgIcon} Nuxt Sitemap v${version}</a>`;
15
15
  const { name: siteName, url: siteUrl } = useSiteConfig(e);
16
16
  const referrer = getHeader(e, "Referer") || "/";
17
- const isNotIndexButHasIndex = referrer !== fixPath("/sitemap.xml") && parseURL(referrer).pathname.endsWith("-sitemap.xml");
17
+ const referrerPath = parseURL(referrer).pathname;
18
+ const isNotIndexButHasIndex = referrerPath !== "/sitemap.xml" && referrerPath !== "/sitemap_index.xml" && referrerPath.endsWith(".xml");
18
19
  const sitemapName = parseURL(referrer).pathname.split("/").pop()?.split("-sitemap")[0] || fallbackSitemapName;
19
20
  const title = `${siteName}${sitemapName !== "sitemap.xml" ? ` - ${sitemapName === "sitemap_index.xml" ? "index" : sitemapName}` : ""}`.replace(/&/g, "&amp;");
20
21
  const canonicalQuery = getQuery(referrer).canonical;
@@ -1,27 +1,30 @@
1
- import { defineEventHandler, getQuery, setHeader } from "h3";
2
- import { fixSlashes } from "site-config-stack/urls";
1
+ import { appendHeader, defineEventHandler, setHeader } from "h3";
2
+ import { joinURL } from "ufo";
3
+ import { useNitroApp } from "nitropack/runtime";
3
4
  import { useSimpleSitemapRuntimeConfig } from "../utils.js";
4
- import { buildSitemapIndex } from "../sitemap/builder/sitemap-index.js";
5
- import { createSitePathResolver, useNitroApp, useSiteConfig } from "#imports";
5
+ import { buildSitemapIndex, urlsToIndexXml } from "../sitemap/builder/sitemap-index.js";
6
+ import { useNitroUrlResolvers } from "../sitemap/nitro.js";
6
7
  export default defineEventHandler(async (e) => {
7
- const canonicalQuery = getQuery(e).canonical;
8
- const isShowingCanonical = typeof canonicalQuery !== "undefined" && canonicalQuery !== "false";
9
8
  const runtimeConfig = useSimpleSitemapRuntimeConfig();
10
- const siteConfig = useSiteConfig(e);
11
- let sitemap = await buildSitemapIndex({
12
- event: e,
13
- canonicalUrlResolver: createSitePathResolver(e, { canonical: isShowingCanonical || !import.meta.dev, absolute: true, withBase: true }),
14
- relativeBaseUrlResolver: createSitePathResolver(e, { absolute: false, withBase: true }),
15
- fixSlashes: (path) => fixSlashes(siteConfig.trailingSlash, path)
16
- }, runtimeConfig);
17
9
  const nitro = useNitroApp();
18
- const ctx = { sitemap, sitemapName: "sitemap" };
10
+ const resolvers = useNitroUrlResolvers(e);
11
+ const sitemaps = await buildSitemapIndex(resolvers, runtimeConfig);
12
+ if (import.meta.prerender) {
13
+ appendHeader(
14
+ e,
15
+ "x-nitro-prerender",
16
+ sitemaps.filter((entry) => !!entry._sitemapName).map((entry) => encodeURIComponent(joinURL(runtimeConfig.sitemapsPathPrefix, `/${entry._sitemapName}.xml`))).join(", ")
17
+ );
18
+ }
19
+ const indexResolvedCtx = { sitemaps };
20
+ await nitro.hooks.callHook("sitemap:index-resolved", indexResolvedCtx);
21
+ const output = urlsToIndexXml(indexResolvedCtx.sitemaps, resolvers, runtimeConfig);
22
+ const ctx = { sitemap: output, sitemapName: "sitemap" };
19
23
  await nitro.hooks.callHook("sitemap:output", ctx);
20
- sitemap = ctx.sitemap;
21
24
  setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
22
25
  if (runtimeConfig.cacheMaxAgeSeconds)
23
26
  setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
24
27
  else
25
28
  setHeader(e, "Cache-Control", `no-cache, no-store`);
26
- return sitemap;
29
+ return ctx.sitemap;
27
30
  });
@@ -1,2 +1,3 @@
1
- import type { ModuleRuntimeConfig, NitroUrlResolvers } from '../../../types.js';
2
- export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<string>;
1
+ import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapIndexEntry } from '../../../types.js';
2
+ export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<SitemapIndexEntry[]>;
3
+ export declare function urlsToIndexXml(sitemaps: SitemapIndexEntry[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;
@@ -1,12 +1,10 @@
1
1
  import { defu } from "defu";
2
- import { appendHeader } from "h3";
3
- import { normaliseDate, normaliseSitemapUrls } from "../urlset/normalise.js";
2
+ import { joinURL } from "ufo";
3
+ import { normaliseDate } from "../urlset/normalise.js";
4
4
  import { globalSitemapSources, resolveSitemapSources } from "../urlset/sources.js";
5
- import { applyI18nEnhancements } from "../urlset/i18n.js";
6
- import { filterSitemapUrls } from "../urlset/filter.js";
7
5
  import { sortSitemapUrls } from "../urlset/sort.js";
8
6
  import { escapeValueForXml, wrapSitemapXml } from "./xml.js";
9
- import { useNitroApp } from "#imports";
7
+ import { resolveSitemapEntries } from "./sitemap.js";
10
8
  export async function buildSitemapIndex(resolvers, runtimeConfig) {
11
9
  const {
12
10
  sitemaps,
@@ -17,10 +15,7 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
17
15
  autoI18n,
18
16
  isI18nMapped,
19
17
  sortEntries,
20
- // xls
21
- version,
22
- xsl,
23
- credits
18
+ sitemapsPathPrefix
24
19
  } = runtimeConfig;
25
20
  if (!sitemaps)
26
21
  throw new Error("Attempting to build a sitemap index without required `sitemaps` configuration.");
@@ -32,12 +27,9 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
32
27
  if (isChunking) {
33
28
  const sitemap = sitemaps.chunks;
34
29
  const sources = await resolveSitemapSources(await globalSitemapSources());
35
- const normalisedUrls = normaliseSitemapUrls(sources.map((e) => e.urls).flat(), resolvers);
36
- let enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults));
37
- if (autoI18n?.locales)
38
- enhancedUrls = applyI18nEnhancements(enhancedUrls, { isI18nMapped, autoI18n, sitemapName: sitemap.sitemapName });
39
- const filteredUrls = filterSitemapUrls(enhancedUrls, { ...sitemap, autoI18n, isMultiSitemap: true });
40
- const sortedUrls = maybeSort(filteredUrls);
30
+ const normalisedUrls = resolveSitemapEntries(sitemap, sources, { autoI18n, isI18nMapped });
31
+ const enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults));
32
+ const sortedUrls = maybeSort(enhancedUrls);
41
33
  sortedUrls.forEach((url, i) => {
42
34
  const chunkIndex = Math.floor(i / defaultSitemapsChunkSize);
43
35
  chunks[chunkIndex] = chunks[chunkIndex] || { urls: [] };
@@ -50,18 +42,12 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
50
42
  }
51
43
  }
52
44
  }
53
- if (import.meta.prerender) {
54
- appendHeader(
55
- resolvers.event,
56
- "x-nitro-prerender",
57
- Object.keys(chunks).map((name) => encodeURIComponent(`/${name}-sitemap.xml`)).join(", ")
58
- );
59
- }
60
45
  const entries = [];
61
46
  for (const name in chunks) {
62
47
  const sitemap = chunks[name];
63
48
  const entry = {
64
- sitemap: resolvers.canonicalUrlResolver(`${name}-sitemap.xml`)
49
+ _sitemapName: name,
50
+ sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix, `/${name}.xml`))
65
51
  };
66
52
  let lastmod = sitemap.urls.filter((a) => !!a?.lastmod).map((a) => typeof a.lastmod === "string" ? new Date(a.lastmod) : a.lastmod).sort((a, b) => (b?.getTime() || 0) - (a?.getTime() || 0))?.[0];
67
53
  if (!lastmod && autoLastmod)
@@ -75,10 +61,10 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
75
61
  return typeof entry === "string" ? { sitemap: entry } : entry;
76
62
  }));
77
63
  }
78
- const ctx = { sitemaps: entries };
79
- const nitro = useNitroApp();
80
- await nitro.hooks.callHook("sitemap:index-resolved", ctx);
81
- const sitemapXml = ctx.sitemaps.map((e) => [
64
+ return entries;
65
+ }
66
+ export function urlsToIndexXml(sitemaps, resolvers, { version, xsl, credits, minify }) {
67
+ const sitemapXml = sitemaps.map((e) => [
82
68
  " <sitemap>",
83
69
  ` <loc>${escapeValueForXml(e.sitemap)}</loc>`,
84
70
  // lastmod is optional
@@ -89,5 +75,5 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
89
75
  '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
90
76
  sitemapXml,
91
77
  "</sitemapindex>"
92
- ], resolvers, { version, xsl, credits });
78
+ ], resolvers, { version, xsl, credits, minify });
93
79
  }
@@ -1,2 +1,9 @@
1
- import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapDefinition } from '../../../types.js';
2
- export declare function buildSitemap(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<string>;
1
+ import type { AutoI18nConfig, ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl, SitemapDefinition, SitemapSourceResolved } 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, sources: SitemapSourceResolved[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>): ResolvedSitemapUrl[];
8
+ export declare function buildSitemapUrls(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<ResolvedSitemapUrl[]>;
9
+ export declare function urlsToXml(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;