@nuxtjs/sitemap 7.2.9 → 7.3.0
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 +9 -9
- package/dist/client/404.html +9 -9
- package/dist/client/_nuxt/Cp-IABpG.js +1 -0
- package/dist/client/_nuxt/DJVkgDQ2.js +1 -0
- package/dist/client/_nuxt/SmY-NWqO.js +172 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/e48bfd5b-6605-4bbc-a466-32a664787616.json +1 -0
- package/dist/client/_nuxt/{entry.CJ2Eg9q-.css → entry.CgW0_noo.css} +1 -1
- package/dist/client/_nuxt/error-404.CtcyoHAN.css +1 -0
- package/dist/client/_nuxt/error-500.BIlfyoPk.css +1 -0
- package/dist/client/_nuxt/lL_X76lO.js +1 -0
- package/dist/client/index.html +9 -9
- package/dist/content.d.cts +2 -1
- package/dist/content.d.mts +2 -1
- package/dist/content.d.ts +2 -1
- package/dist/module.cjs +83 -42
- package/dist/module.d.cts +3 -1
- package/dist/module.d.mts +3 -1
- package/dist/module.d.ts +3 -1
- package/dist/module.json +3 -3
- package/dist/module.mjs +84 -43
- package/dist/runtime/server/plugins/warm-up.js +20 -4
- package/dist/runtime/server/routes/__sitemap__/debug.d.ts +4 -4
- package/dist/runtime/server/routes/__sitemap__/debug.js +2 -2
- package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.js +7 -2
- package/dist/runtime/server/routes/sitemap/[sitemap].xml.js +37 -7
- package/dist/runtime/server/routes/sitemap_index.xml.js +11 -3
- package/dist/runtime/server/sitemap/builder/sitemap-index.d.ts +1 -1
- package/dist/runtime/server/sitemap/builder/sitemap-index.js +110 -16
- package/dist/runtime/server/sitemap/builder/sitemap.d.ts +1 -1
- package/dist/runtime/server/sitemap/builder/sitemap.js +62 -36
- package/dist/runtime/server/sitemap/builder/xml.d.ts +2 -3
- package/dist/runtime/server/sitemap/builder/xml.js +182 -80
- package/dist/runtime/server/sitemap/nitro.js +68 -20
- package/dist/runtime/server/sitemap/urlset/normalise.js +21 -19
- package/dist/runtime/server/sitemap/urlset/sort.d.ts +1 -1
- package/dist/runtime/server/sitemap/urlset/sort.js +9 -15
- package/dist/runtime/server/sitemap/utils/chunk.d.ts +10 -0
- package/dist/runtime/server/sitemap/utils/chunk.js +66 -0
- package/dist/runtime/types.d.ts +44 -0
- package/dist/runtime/utils-pure.js +13 -5
- package/dist/types.d.mts +5 -1
- package/package.json +32 -38
- package/content.d.ts +0 -1
- package/dist/client/_nuxt/BQoSv7ci.js +0 -1
- package/dist/client/_nuxt/BuImKM08.js +0 -1
- package/dist/client/_nuxt/DGiw9jHL.js +0 -172
- package/dist/client/_nuxt/LwtYuSjN.js +0 -1
- package/dist/client/_nuxt/builds/meta/491f5d1a-004d-407a-b464-c3363f77bc23.json +0 -1
- package/dist/client/_nuxt/error-404.CmL6pbzl.css +0 -1
- package/dist/client/_nuxt/error-500.CnmYQu0q.css +0 -1
- package/dist/types.d.ts +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useNuxt, loadNuxtModuleInstance, createResolver, addTemplate, extendPages, tryUseNuxt, defineNuxtModule, useLogger, hasNuxtModule, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addServerPlugin, resolveModule, addServerHandler, addPrerenderRoutes } from '@nuxt/kit';
|
|
2
|
-
import { withHttps, withBase, parseURL, joinURL, withoutLeadingSlash, withLeadingSlash, withoutTrailingSlash } from 'ufo';
|
|
2
|
+
import { withHttps, withBase, parseURL, joinURL, withTrailingSlash, withoutLeadingSlash, withLeadingSlash, withoutTrailingSlash } from 'ufo';
|
|
3
3
|
import { withSiteUrl, installNuxtSiteConfig } from 'nuxt-site-config/kit';
|
|
4
4
|
import { defu } from 'defu';
|
|
5
5
|
import { readPackageJSON } from 'pkg-types';
|
|
@@ -321,35 +321,25 @@ function extractSitemapMetaFromHtml(html, options) {
|
|
|
321
321
|
description
|
|
322
322
|
};
|
|
323
323
|
const player_loc = (videoPlayerLocRegex.exec(videoTag) || [])[1];
|
|
324
|
-
if (player_loc)
|
|
325
|
-
videoObj.player_loc = player_loc;
|
|
324
|
+
if (player_loc) videoObj.player_loc = player_loc;
|
|
326
325
|
const duration = (videoDurationRegex.exec(videoTag) || [])[1];
|
|
327
|
-
if (duration)
|
|
328
|
-
videoObj.duration = Number.parseInt(duration, 10);
|
|
326
|
+
if (duration) videoObj.duration = Number.parseInt(duration, 10);
|
|
329
327
|
const expiration_date = (videoExpirationDateRegex.exec(videoTag) || [])[1];
|
|
330
|
-
if (expiration_date)
|
|
331
|
-
videoObj.expiration_date = expiration_date;
|
|
328
|
+
if (expiration_date) videoObj.expiration_date = expiration_date;
|
|
332
329
|
const rating = (videoRatingRegex.exec(videoTag) || [])[1];
|
|
333
|
-
if (rating)
|
|
334
|
-
videoObj.rating = Number.parseFloat(rating);
|
|
330
|
+
if (rating) videoObj.rating = Number.parseFloat(rating);
|
|
335
331
|
const view_count = (videoViewCountRegex.exec(videoTag) || [])[1];
|
|
336
|
-
if (view_count)
|
|
337
|
-
videoObj.view_count = Number.parseInt(view_count, 10);
|
|
332
|
+
if (view_count) videoObj.view_count = Number.parseInt(view_count, 10);
|
|
338
333
|
const publication_date = (videoPublicationDateRegex.exec(videoTag) || [])[1];
|
|
339
|
-
if (publication_date)
|
|
340
|
-
videoObj.publication_date = publication_date;
|
|
334
|
+
if (publication_date) videoObj.publication_date = publication_date;
|
|
341
335
|
const family_friendly = (videoFamilyFriendlyRegex.exec(videoTag) || [])[1];
|
|
342
|
-
if (family_friendly)
|
|
343
|
-
videoObj.family_friendly = family_friendly;
|
|
336
|
+
if (family_friendly) videoObj.family_friendly = family_friendly;
|
|
344
337
|
const requires_subscription = (videoRequiresSubscriptionRegex.exec(videoTag) || [])[1];
|
|
345
|
-
if (requires_subscription)
|
|
346
|
-
videoObj.requires_subscription = requires_subscription;
|
|
338
|
+
if (requires_subscription) videoObj.requires_subscription = requires_subscription;
|
|
347
339
|
const live = (videoLiveRegex.exec(videoTag) || [])[1];
|
|
348
|
-
if (live)
|
|
349
|
-
videoObj.live = live;
|
|
340
|
+
if (live) videoObj.live = live;
|
|
350
341
|
const tag = (videoTagRegex.exec(videoTag) || [])[1];
|
|
351
|
-
if (tag)
|
|
352
|
-
videoObj.tag = tag;
|
|
342
|
+
if (tag) videoObj.tag = tag;
|
|
353
343
|
const sources = [];
|
|
354
344
|
let sourceMatch;
|
|
355
345
|
while ((sourceMatch = sourceRegex.exec(videoContent)) !== null) {
|
|
@@ -653,7 +643,7 @@ const module = defineNuxtModule({
|
|
|
653
643
|
defaults: {},
|
|
654
644
|
// index sitemap options filtering
|
|
655
645
|
include: [],
|
|
656
|
-
exclude: ["/
|
|
646
|
+
exclude: ["/_**"],
|
|
657
647
|
// sources
|
|
658
648
|
sources: [],
|
|
659
649
|
excludeAppSources: []
|
|
@@ -667,6 +657,7 @@ const module = defineNuxtModule({
|
|
|
667
657
|
logger.debug("The module is disabled, skipping setup.");
|
|
668
658
|
return;
|
|
669
659
|
}
|
|
660
|
+
config.exclude.push(`${withTrailingSlash(nuxt.options.app.buildAssetsDir)}**`);
|
|
670
661
|
nuxt.options.alias["#sitemap"] = resolve("./runtime");
|
|
671
662
|
nuxt.options.nitro.alias = nuxt.options.nitro.alias || {};
|
|
672
663
|
nuxt.options.nitro.alias["#sitemap"] = resolve("./runtime");
|
|
@@ -749,11 +740,11 @@ const module = defineNuxtModule({
|
|
|
749
740
|
const locale = normalisedLocales.find((l) => l.code === localeCode);
|
|
750
741
|
if (!locale || !pageLocales[localeCode] || pageLocales[localeCode].includes("["))
|
|
751
742
|
continue;
|
|
752
|
-
const alternatives = Object.keys(pageLocales).map((l) => ({
|
|
743
|
+
const alternatives = Object.keys(pageLocales).filter((l) => pageLocales[l] !== false).map((l) => ({
|
|
753
744
|
hreflang: normalisedLocales.find((nl) => nl.code === l)?._hreflang || l,
|
|
754
745
|
href: generatePathForI18nPages({ localeCode: l, pageLocales: pageLocales[l], nuxtI18nConfig, normalisedLocales })
|
|
755
746
|
}));
|
|
756
|
-
if (alternatives.length && nuxtI18nConfig.defaultLocale && pageLocales[nuxtI18nConfig.defaultLocale])
|
|
747
|
+
if (alternatives.length && nuxtI18nConfig.defaultLocale && pageLocales[nuxtI18nConfig.defaultLocale] && pageLocales[nuxtI18nConfig.defaultLocale] !== false)
|
|
757
748
|
alternatives.push({ hreflang: "x-default", href: generatePathForI18nPages({ normalisedLocales, localeCode: nuxtI18nConfig.defaultLocale, pageLocales: pageLocales[nuxtI18nConfig.defaultLocale], nuxtI18nConfig }) });
|
|
758
749
|
i18nPagesSources.urls.push({
|
|
759
750
|
_sitemap: locale._sitemap,
|
|
@@ -783,7 +774,9 @@ const module = defineNuxtModule({
|
|
|
783
774
|
differentDomains: nuxtI18nConfig.differentDomains,
|
|
784
775
|
defaultLocale: nuxtI18nConfig.defaultLocale,
|
|
785
776
|
locales: normalisedLocales,
|
|
786
|
-
strategy: nuxtI18nConfig.strategy
|
|
777
|
+
strategy: nuxtI18nConfig.strategy,
|
|
778
|
+
// @ts-expect-error untyped
|
|
779
|
+
pages: nuxtI18nConfig.pages
|
|
787
780
|
};
|
|
788
781
|
}
|
|
789
782
|
let canI18nMap = config.sitemaps !== false && nuxtI18nConfig.strategy !== "no_prefix";
|
|
@@ -840,6 +833,7 @@ declare module 'nitropack' {
|
|
|
840
833
|
'sitemap:input': (ctx: import('${typesPath}').SitemapInputCtx) => void | Promise<void>
|
|
841
834
|
'sitemap:resolved': (ctx: import('${typesPath}').SitemapRenderCtx) => void | Promise<void>
|
|
842
835
|
'sitemap:output': (ctx: import('${typesPath}').SitemapOutputHookCtx) => void | Promise<void>
|
|
836
|
+
'sitemap:sources': (ctx: import('${typesPath}').SitemapSourcesHookCtx) => void | Promise<void>
|
|
843
837
|
}
|
|
844
838
|
}
|
|
845
839
|
declare module 'vue-router' {
|
|
@@ -849,7 +843,6 @@ declare module 'vue-router' {
|
|
|
849
843
|
}
|
|
850
844
|
`;
|
|
851
845
|
});
|
|
852
|
-
const nitroPreset = resolveNitroPreset();
|
|
853
846
|
const prerenderedRoutes = nuxt.options.nitro.prerender?.routes || [];
|
|
854
847
|
const prerenderSitemap = isNuxtGenerate() || includesSitemapRoot(config.sitemapName, prerenderedRoutes);
|
|
855
848
|
const routeRules = {};
|
|
@@ -861,17 +854,6 @@ declare module 'vue-router' {
|
|
|
861
854
|
"X-Sitemap-Prerendered": (/* @__PURE__ */ new Date()).toISOString()
|
|
862
855
|
};
|
|
863
856
|
}
|
|
864
|
-
if (!nuxt.options.dev && !isNuxtGenerate() && config.cacheMaxAgeSeconds && config.runtimeCacheStorage !== false) {
|
|
865
|
-
routeRules[nitroPreset.includes("vercel") ? "isr" : "swr"] = config.cacheMaxAgeSeconds;
|
|
866
|
-
routeRules.cache = {
|
|
867
|
-
// handle multi-tenancy
|
|
868
|
-
swr: true,
|
|
869
|
-
maxAge: config.cacheMaxAgeSeconds,
|
|
870
|
-
varies: ["X-Forwarded-Host", "X-Forwarded-Proto", "Host"]
|
|
871
|
-
};
|
|
872
|
-
if (typeof config.runtimeCacheStorage === "object")
|
|
873
|
-
routeRules.cache.base = "sitemap";
|
|
874
|
-
}
|
|
875
857
|
if (config.xsl) {
|
|
876
858
|
nuxt.options.nitro.routeRules[config.xsl] = {
|
|
877
859
|
headers: {
|
|
@@ -884,10 +866,16 @@ declare module 'vue-router' {
|
|
|
884
866
|
nuxt.options.nitro.routeRules["/sitemap_index.xml"] = routeRules;
|
|
885
867
|
if (typeof config.sitemaps === "object") {
|
|
886
868
|
for (const k in config.sitemaps) {
|
|
869
|
+
if (k === "index")
|
|
870
|
+
continue;
|
|
887
871
|
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix || "", `/${k}.xml`)] = routeRules;
|
|
872
|
+
const sitemapConfig = config.sitemaps[k];
|
|
873
|
+
if (sitemapConfig.chunks) {
|
|
874
|
+
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix || "", `/${k}-*.xml`)] = routeRules;
|
|
875
|
+
}
|
|
888
876
|
}
|
|
889
877
|
} else {
|
|
890
|
-
nuxt.options.nitro.routeRules[
|
|
878
|
+
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix || "", `/[0-9]+.xml`)] = routeRules;
|
|
891
879
|
}
|
|
892
880
|
} else {
|
|
893
881
|
nuxt.options.nitro.routeRules[`/${config.sitemapName}`] = routeRules;
|
|
@@ -905,14 +893,25 @@ declare module 'vue-router' {
|
|
|
905
893
|
if (nuxt.options._installedModules.some((m) => m.meta.name === "Content")) {
|
|
906
894
|
logger.warn("You have loaded `@nuxt/content` before `@nuxtjs/sitemap`, this may cause issues with the integration. Please ensure `@nuxtjs/sitemap` is loaded first.");
|
|
907
895
|
}
|
|
896
|
+
config.exclude.push("/__nuxt_content/**");
|
|
908
897
|
nuxt.options.alias["#sitemap/content-v3-nitro-path"] = resolve(dirname(resolveModule("@nuxt/content")), "runtime/nitro");
|
|
909
898
|
nuxt.hooks.hook("content:file:afterParse", (ctx) => {
|
|
910
899
|
const content = ctx.content;
|
|
911
900
|
nuxtV3Collections.add(ctx.collection.name);
|
|
912
|
-
if (ctx.
|
|
901
|
+
if (String(ctx.content.path).includes("/.")) {
|
|
902
|
+
ctx.content.sitemap = null;
|
|
913
903
|
return;
|
|
914
904
|
}
|
|
915
905
|
if (!("sitemap" in ctx.collection.fields)) {
|
|
906
|
+
ctx.content.sitemap = null;
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
if (typeof content.sitemap !== "undefined" && !content.sitemap) {
|
|
910
|
+
ctx.content.sitemap = null;
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
if (ctx.content.robots === false) {
|
|
914
|
+
ctx.content.sitemap = null;
|
|
916
915
|
return;
|
|
917
916
|
}
|
|
918
917
|
const images = [];
|
|
@@ -986,13 +985,25 @@ declare module 'vue-router' {
|
|
|
986
985
|
middleware: false
|
|
987
986
|
});
|
|
988
987
|
} else {
|
|
989
|
-
|
|
988
|
+
const sitemapNames = Object.keys(config.sitemaps || {});
|
|
989
|
+
for (const sitemapName of sitemapNames) {
|
|
990
|
+
if (sitemapName === "index")
|
|
991
|
+
continue;
|
|
992
|
+
const sitemapConfig = config.sitemaps[sitemapName];
|
|
990
993
|
addServerHandler({
|
|
991
994
|
route: withLeadingSlash(`${sitemapName}.xml`),
|
|
992
995
|
handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
|
|
993
996
|
lazy: true,
|
|
994
997
|
middleware: false
|
|
995
998
|
});
|
|
999
|
+
if (sitemapConfig.chunks) {
|
|
1000
|
+
addServerHandler({
|
|
1001
|
+
route: `/${sitemapName}-*.xml`,
|
|
1002
|
+
handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
|
|
1003
|
+
lazy: true,
|
|
1004
|
+
middleware: false
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
996
1007
|
}
|
|
997
1008
|
}
|
|
998
1009
|
sitemaps.index = {
|
|
@@ -1006,7 +1017,7 @@ declare module 'vue-router' {
|
|
|
1006
1017
|
if (sitemapName === "index")
|
|
1007
1018
|
continue;
|
|
1008
1019
|
const definition = config.sitemaps[sitemapName];
|
|
1009
|
-
|
|
1020
|
+
const sitemapConfig = defu(
|
|
1010
1021
|
{
|
|
1011
1022
|
sitemapName,
|
|
1012
1023
|
_route: withBase(joinURL(config.sitemapsPathPrefix || "", `${sitemapName}.xml`), nuxt.options.app.baseURL || "/"),
|
|
@@ -1015,6 +1026,28 @@ declare module 'vue-router' {
|
|
|
1015
1026
|
{ ...definition, urls: void 0, sources: void 0 },
|
|
1016
1027
|
{ include: config.include, exclude: config.exclude }
|
|
1017
1028
|
);
|
|
1029
|
+
if (definition.chunks) {
|
|
1030
|
+
let chunkSize = config.defaultSitemapsChunkSize || 1e3;
|
|
1031
|
+
if (typeof definition.chunks === "number") {
|
|
1032
|
+
if (definition.chunks <= 0) {
|
|
1033
|
+
logger.warn(`Invalid chunks value (${definition.chunks}) for sitemap "${sitemapName}". Using default.`);
|
|
1034
|
+
} else {
|
|
1035
|
+
chunkSize = definition.chunks;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
if (definition.chunkSize !== void 0) {
|
|
1039
|
+
if (typeof definition.chunkSize !== "number" || definition.chunkSize <= 0) {
|
|
1040
|
+
logger.warn(`Invalid chunkSize value (${definition.chunkSize}) for sitemap "${sitemapName}". Using default.`);
|
|
1041
|
+
} else {
|
|
1042
|
+
chunkSize = definition.chunkSize;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
sitemapConfig._isChunking = true;
|
|
1046
|
+
sitemapConfig._chunkSize = chunkSize;
|
|
1047
|
+
sitemapConfig.chunks = definition.chunks;
|
|
1048
|
+
sitemapConfig.chunkSize = definition.chunkSize;
|
|
1049
|
+
}
|
|
1050
|
+
sitemaps[sitemapName] = sitemapConfig;
|
|
1018
1051
|
}
|
|
1019
1052
|
} else {
|
|
1020
1053
|
sitemaps.chunks = {
|
|
@@ -1043,7 +1076,7 @@ declare module 'vue-router' {
|
|
|
1043
1076
|
if (typeof path !== "string")
|
|
1044
1077
|
return [path];
|
|
1045
1078
|
const withoutSlashes = withoutTrailingSlash(withoutLeadingSlash(path)).replace("/index", "");
|
|
1046
|
-
if (withoutSlashes in pages) {
|
|
1079
|
+
if (pages && withoutSlashes in pages) {
|
|
1047
1080
|
const pageLocales = pages[withoutSlashes];
|
|
1048
1081
|
if (pageLocales) {
|
|
1049
1082
|
return Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({
|
|
@@ -1056,7 +1089,7 @@ declare module 'vue-router' {
|
|
|
1056
1089
|
}
|
|
1057
1090
|
let match = [path];
|
|
1058
1091
|
Object.values(pages).forEach((pageLocales) => {
|
|
1059
|
-
if (nuxtI18nConfig.defaultLocale in pageLocales && pageLocales[nuxtI18nConfig.defaultLocale] === path)
|
|
1092
|
+
if (pageLocales && nuxtI18nConfig.defaultLocale in pageLocales && pageLocales[nuxtI18nConfig.defaultLocale] === path)
|
|
1060
1093
|
match = Object.keys(pageLocales).map((localeCode) => withLeadingSlash(generatePathForI18nPages({ localeCode, pageLocales: pageLocales[localeCode], nuxtI18nConfig, normalisedLocales })));
|
|
1061
1094
|
});
|
|
1062
1095
|
return match;
|
|
@@ -1116,6 +1149,14 @@ declare module 'vue-router' {
|
|
|
1116
1149
|
route: "/__sitemap__/debug.json",
|
|
1117
1150
|
handler: resolve("./runtime/server/routes/__sitemap__/debug")
|
|
1118
1151
|
});
|
|
1152
|
+
if (usingMultiSitemaps) {
|
|
1153
|
+
addServerHandler({
|
|
1154
|
+
route: "/__sitemap__/**:sitemap",
|
|
1155
|
+
handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
|
|
1156
|
+
lazy: true,
|
|
1157
|
+
middleware: true
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1119
1160
|
setupDevToolsUI(config, resolve);
|
|
1120
1161
|
}
|
|
1121
1162
|
const imports = [
|
|
@@ -4,20 +4,36 @@ import { useSitemapRuntimeConfig } from "../utils.js";
|
|
|
4
4
|
export default defineNitroPlugin((nitroApp) => {
|
|
5
5
|
const { sitemaps } = useSitemapRuntimeConfig();
|
|
6
6
|
const queue = [];
|
|
7
|
+
const timeoutIds = [];
|
|
7
8
|
const sitemapsWithRoutes = Object.entries(sitemaps).filter(([, sitemap]) => sitemap._route);
|
|
8
9
|
for (const [, sitemap] of sitemapsWithRoutes)
|
|
9
10
|
queue.push(() => nitroApp.localFetch(withLeadingSlash(sitemap._route), {}));
|
|
10
|
-
setTimeout(
|
|
11
|
+
const initialTimeout = setTimeout(
|
|
11
12
|
() => {
|
|
12
13
|
const next = async () => {
|
|
13
|
-
if (queue.length === 0)
|
|
14
|
+
if (queue.length === 0) {
|
|
15
|
+
timeoutIds.length = 0;
|
|
14
16
|
return;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
await queue.shift()();
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error("[sitemap:warm-up] Error warming up sitemap:", error);
|
|
22
|
+
}
|
|
23
|
+
if (queue.length > 0) {
|
|
24
|
+
const nextTimeout = setTimeout(next, 1e3);
|
|
25
|
+
timeoutIds.push(nextTimeout);
|
|
26
|
+
}
|
|
17
27
|
};
|
|
18
28
|
next();
|
|
19
29
|
},
|
|
20
30
|
2500
|
|
21
31
|
/* https://github.com/unjs/nitro/pull/1906 */
|
|
22
32
|
);
|
|
33
|
+
timeoutIds.push(initialTimeout);
|
|
34
|
+
nitroApp.hooks.hook("close", () => {
|
|
35
|
+
timeoutIds.forEach((id) => clearTimeout(id));
|
|
36
|
+
timeoutIds.length = 0;
|
|
37
|
+
queue.length = 0;
|
|
38
|
+
});
|
|
23
39
|
});
|
|
@@ -7,18 +7,18 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
|
|
|
7
7
|
isNuxtContentDocumentDriven: boolean;
|
|
8
8
|
sitemaps: {
|
|
9
9
|
index?: Pick<SitemapDefinition, "sitemapName" | "_route"> & {
|
|
10
|
-
sitemaps: import("../../../types").SitemapIndexEntry[];
|
|
10
|
+
sitemaps: import("../../../types.js").SitemapIndexEntry[];
|
|
11
11
|
};
|
|
12
12
|
} & Record<string, Omit<SitemapDefinition, "urls"> & {
|
|
13
13
|
_hasSourceChunk?: boolean;
|
|
14
14
|
}>;
|
|
15
|
-
autoI18n?: import("../../../types").AutoI18nConfig;
|
|
15
|
+
autoI18n?: import("../../../types.js").AutoI18nConfig;
|
|
16
16
|
isMultiSitemap: boolean;
|
|
17
17
|
isI18nMapped: boolean;
|
|
18
18
|
sitemapsPathPrefix: string | false;
|
|
19
19
|
cacheMaxAgeSeconds: number | false;
|
|
20
20
|
sitemapName: string;
|
|
21
|
-
excludeAppSources: true | (import("../../../types").AppSourceContext[]);
|
|
21
|
+
excludeAppSources: true | (import("../../../types.js").AppSourceContext[]);
|
|
22
22
|
sortEntries: boolean;
|
|
23
23
|
defaultSitemapsChunkSize: number | false;
|
|
24
24
|
xslColumns?: {
|
|
@@ -35,6 +35,6 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
|
|
|
35
35
|
credits: boolean;
|
|
36
36
|
minify: boolean;
|
|
37
37
|
};
|
|
38
|
-
globalSources: import("../../../types").SitemapSourceResolved[];
|
|
38
|
+
globalSources: import("../../../types.js").SitemapSourceResolved[];
|
|
39
39
|
}>>;
|
|
40
40
|
export default _default;
|
|
@@ -17,13 +17,13 @@ export default defineEventHandler(async (e) => {
|
|
|
17
17
|
for (const s of Object.keys(_sitemaps)) {
|
|
18
18
|
sitemaps[s] = {
|
|
19
19
|
..._sitemaps[s],
|
|
20
|
-
sources: await resolveSitemapSources(await childSitemapSources(_sitemaps[s]))
|
|
20
|
+
sources: await resolveSitemapSources(await childSitemapSources(_sitemaps[s]), e)
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
return {
|
|
24
24
|
nitroOrigin,
|
|
25
25
|
sitemaps,
|
|
26
26
|
runtimeConfig,
|
|
27
|
-
globalSources: await resolveSitemapSources(globalSources)
|
|
27
|
+
globalSources: await resolveSitemapSources(globalSources, e)
|
|
28
28
|
};
|
|
29
29
|
});
|
|
@@ -10,8 +10,13 @@ export default defineEventHandler(async (e) => {
|
|
|
10
10
|
}
|
|
11
11
|
const contentList = [];
|
|
12
12
|
for (const collection of collections) {
|
|
13
|
-
contentList.push(queryCollectionWithEvent(e, collection).select("path", "sitemap").where("path", "IS NOT NULL").all());
|
|
13
|
+
contentList.push(queryCollectionWithEvent(e, collection).select("path", "sitemap").where("path", "IS NOT NULL").where("sitemap", "IS NOT NULL").all());
|
|
14
14
|
}
|
|
15
15
|
const results = await Promise.all(contentList);
|
|
16
|
-
return results.
|
|
16
|
+
return results.flatMap((c) => {
|
|
17
|
+
return c.filter((c2) => c2.sitemap !== false && c2.path).flatMap((c2) => ({
|
|
18
|
+
loc: c2.path,
|
|
19
|
+
...c2.sitemap || {}
|
|
20
|
+
}));
|
|
21
|
+
}).filter(Boolean);
|
|
17
22
|
});
|
|
@@ -2,19 +2,49 @@ import { createError, defineEventHandler, getRouterParam } from "h3";
|
|
|
2
2
|
import { withoutLeadingSlash, withoutTrailingSlash } from "ufo";
|
|
3
3
|
import { useSitemapRuntimeConfig } from "../../utils.js";
|
|
4
4
|
import { createSitemap } from "../../sitemap/nitro.js";
|
|
5
|
+
import { parseChunkInfo, getSitemapConfig } from "../../sitemap/utils/chunk.js";
|
|
5
6
|
export default defineEventHandler(async (e) => {
|
|
6
7
|
const runtimeConfig = useSitemapRuntimeConfig(e);
|
|
7
8
|
const { sitemaps } = runtimeConfig;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
let sitemapName = getRouterParam(e, "sitemap");
|
|
10
|
+
if (!sitemapName) {
|
|
11
|
+
const path = e.path;
|
|
12
|
+
const match = path.match(/(?:\/__sitemap__\/)?([^/]+)\.xml$/);
|
|
13
|
+
if (match) {
|
|
14
|
+
sitemapName = match[1];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (!sitemapName) {
|
|
18
|
+
return createError({
|
|
19
|
+
statusCode: 400,
|
|
20
|
+
message: "Invalid sitemap request"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
sitemapName = withoutLeadingSlash(withoutTrailingSlash(sitemapName.replace(".xml", "").replace("__sitemap__/", "").replace(runtimeConfig.sitemapsPathPrefix || "", "")));
|
|
24
|
+
const chunkInfo = parseChunkInfo(sitemapName, sitemaps, runtimeConfig.defaultSitemapsChunkSize);
|
|
25
|
+
const isAutoChunked = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemapName));
|
|
26
|
+
const sitemapExists = sitemapName in sitemaps || chunkInfo.baseSitemapName in sitemaps || isAutoChunked;
|
|
27
|
+
if (!sitemapExists) {
|
|
11
28
|
return createError({
|
|
12
29
|
statusCode: 404,
|
|
13
30
|
message: `Sitemap "${sitemapName}" not found.`
|
|
14
31
|
});
|
|
15
32
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
if (chunkInfo.isChunked && chunkInfo.chunkIndex !== void 0) {
|
|
34
|
+
const baseSitemap = sitemaps[chunkInfo.baseSitemapName];
|
|
35
|
+
if (baseSitemap && !baseSitemap.chunks && !baseSitemap._isChunking) {
|
|
36
|
+
return createError({
|
|
37
|
+
statusCode: 404,
|
|
38
|
+
message: `Sitemap "${chunkInfo.baseSitemapName}" does not support chunking.`
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (baseSitemap?._chunkCount !== void 0 && chunkInfo.chunkIndex >= baseSitemap._chunkCount) {
|
|
42
|
+
return createError({
|
|
43
|
+
statusCode: 404,
|
|
44
|
+
message: `Chunk ${chunkInfo.chunkIndex} does not exist for sitemap "${chunkInfo.baseSitemapName}".`
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const sitemapConfig = getSitemapConfig(sitemapName, sitemaps, runtimeConfig.defaultSitemapsChunkSize);
|
|
49
|
+
return createSitemap(e, sitemapConfig, runtimeConfig);
|
|
20
50
|
});
|
|
@@ -22,9 +22,17 @@ export default defineEventHandler(async (e) => {
|
|
|
22
22
|
const ctx = { sitemap: output, sitemapName: "sitemap", event: e };
|
|
23
23
|
await nitro.hooks.callHook("sitemap:output", ctx);
|
|
24
24
|
setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
|
|
25
|
-
if (runtimeConfig.cacheMaxAgeSeconds)
|
|
26
|
-
setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds},
|
|
27
|
-
|
|
25
|
+
if (runtimeConfig.cacheMaxAgeSeconds) {
|
|
26
|
+
setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, s-maxage=${runtimeConfig.cacheMaxAgeSeconds}, stale-while-revalidate=3600`);
|
|
27
|
+
const now = /* @__PURE__ */ new Date();
|
|
28
|
+
setHeader(e, "X-Sitemap-Generated", now.toISOString());
|
|
29
|
+
setHeader(e, "X-Sitemap-Cache-Duration", `${runtimeConfig.cacheMaxAgeSeconds}s`);
|
|
30
|
+
const expiryTime = new Date(now.getTime() + runtimeConfig.cacheMaxAgeSeconds * 1e3);
|
|
31
|
+
setHeader(e, "X-Sitemap-Cache-Expires", expiryTime.toISOString());
|
|
32
|
+
const remainingSeconds = Math.floor((expiryTime.getTime() - now.getTime()) / 1e3);
|
|
33
|
+
setHeader(e, "X-Sitemap-Cache-Remaining", `${remainingSeconds}s`);
|
|
34
|
+
} else {
|
|
28
35
|
setHeader(e, "Cache-Control", `no-cache, no-store`);
|
|
36
|
+
}
|
|
29
37
|
return ctx.sitemap;
|
|
30
38
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { NitroApp } from 'nitropack/types';
|
|
2
2
|
import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapIndexEntry } from '../../../types.js';
|
|
3
|
-
export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<SitemapIndexEntry[]>;
|
|
4
3
|
export declare function urlsToIndexXml(sitemaps: SitemapIndexEntry[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;
|
|
4
|
+
export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<SitemapIndexEntry[]>;
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
import { defu } from "defu";
|
|
2
2
|
import { joinURL } from "ufo";
|
|
3
|
+
import { defineCachedFunction } from "nitropack/runtime";
|
|
4
|
+
import { getHeader } from "h3";
|
|
3
5
|
import { normaliseDate } from "../urlset/normalise.js";
|
|
4
|
-
import { globalSitemapSources, resolveSitemapSources } from "../urlset/sources.js";
|
|
5
|
-
import {
|
|
6
|
-
import { escapeValueForXml
|
|
6
|
+
import { globalSitemapSources, childSitemapSources, resolveSitemapSources } from "../urlset/sources.js";
|
|
7
|
+
import { sortInPlace } from "../urlset/sort.js";
|
|
8
|
+
import { escapeValueForXml } from "./xml.js";
|
|
7
9
|
import { resolveSitemapEntries } from "./sitemap.js";
|
|
8
|
-
|
|
10
|
+
const buildSitemapIndexCached = defineCachedFunction(
|
|
11
|
+
async (event, resolvers, runtimeConfig, nitro) => {
|
|
12
|
+
return buildSitemapIndexInternal(resolvers, runtimeConfig, nitro);
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "sitemap:index",
|
|
16
|
+
group: "sitemap",
|
|
17
|
+
maxAge: 60 * 10,
|
|
18
|
+
// 10 minutes default
|
|
19
|
+
base: "sitemap",
|
|
20
|
+
// Use the sitemap storage
|
|
21
|
+
getKey: (event) => {
|
|
22
|
+
const host = getHeader(event, "host") || getHeader(event, "x-forwarded-host") || "";
|
|
23
|
+
const proto = getHeader(event, "x-forwarded-proto") || "https";
|
|
24
|
+
return `sitemap-index-${proto}-${host}`;
|
|
25
|
+
},
|
|
26
|
+
swr: true
|
|
27
|
+
// Enable stale-while-revalidate
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
|
|
9
31
|
const {
|
|
10
32
|
sitemaps,
|
|
11
33
|
// enhancing
|
|
@@ -20,13 +42,32 @@ export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
|
|
|
20
42
|
if (!sitemaps)
|
|
21
43
|
throw new Error("Attempting to build a sitemap index without required `sitemaps` configuration.");
|
|
22
44
|
function maybeSort(urls) {
|
|
23
|
-
return sortEntries ?
|
|
45
|
+
return sortEntries ? sortInPlace(urls) : urls;
|
|
24
46
|
}
|
|
25
|
-
const isChunking = typeof sitemaps.chunks !== "undefined";
|
|
26
47
|
const chunks = {};
|
|
27
|
-
|
|
48
|
+
for (const sitemapName in sitemaps) {
|
|
49
|
+
if (sitemapName === "index" || sitemapName === "chunks") continue;
|
|
50
|
+
const sitemapConfig = sitemaps[sitemapName];
|
|
51
|
+
if (sitemapConfig.chunks || sitemapConfig._isChunking) {
|
|
52
|
+
sitemapConfig._isChunking = true;
|
|
53
|
+
sitemapConfig._chunkSize = typeof sitemapConfig.chunks === "number" ? sitemapConfig.chunks : sitemapConfig.chunkSize || defaultSitemapsChunkSize || 1e3;
|
|
54
|
+
} else {
|
|
55
|
+
chunks[sitemapName] = chunks[sitemapName] || { urls: [] };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (typeof sitemaps.chunks !== "undefined") {
|
|
28
59
|
const sitemap = sitemaps.chunks;
|
|
29
|
-
|
|
60
|
+
let sourcesInput = await globalSitemapSources();
|
|
61
|
+
if (nitro && resolvers.event) {
|
|
62
|
+
const ctx = {
|
|
63
|
+
event: resolvers.event,
|
|
64
|
+
sitemapName: sitemap.sitemapName,
|
|
65
|
+
sources: sourcesInput
|
|
66
|
+
};
|
|
67
|
+
await nitro.hooks.callHook("sitemap:sources", ctx);
|
|
68
|
+
sourcesInput = ctx.sources;
|
|
69
|
+
}
|
|
70
|
+
const sources = await resolveSitemapSources(sourcesInput, resolvers.event);
|
|
30
71
|
const resolvedCtx = {
|
|
31
72
|
urls: sources.flatMap((s) => s.urls),
|
|
32
73
|
sitemapName: sitemap.sitemapName,
|
|
@@ -41,12 +82,6 @@ export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
|
|
|
41
82
|
chunks[chunkIndex] = chunks[chunkIndex] || { urls: [] };
|
|
42
83
|
chunks[chunkIndex].urls.push(url);
|
|
43
84
|
});
|
|
44
|
-
} else {
|
|
45
|
-
for (const sitemap in sitemaps) {
|
|
46
|
-
if (sitemap !== "index") {
|
|
47
|
-
chunks[sitemap] = chunks[sitemap] || { urls: [] };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
85
|
}
|
|
51
86
|
const entries = [];
|
|
52
87
|
for (const name in chunks) {
|
|
@@ -62,6 +97,48 @@ export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
|
|
|
62
97
|
entry.lastmod = normaliseDate(lastmod);
|
|
63
98
|
entries.push(entry);
|
|
64
99
|
}
|
|
100
|
+
for (const sitemapName in sitemaps) {
|
|
101
|
+
if (sitemapName !== "index" && sitemaps[sitemapName]._isChunking) {
|
|
102
|
+
const sitemapConfig = sitemaps[sitemapName];
|
|
103
|
+
const chunkSize = sitemapConfig._chunkSize || defaultSitemapsChunkSize || 1e3;
|
|
104
|
+
let sourcesInput = sitemapConfig.includeAppSources ? await globalSitemapSources() : [];
|
|
105
|
+
sourcesInput.push(...await childSitemapSources(sitemapConfig));
|
|
106
|
+
if (nitro && resolvers.event) {
|
|
107
|
+
const ctx = {
|
|
108
|
+
event: resolvers.event,
|
|
109
|
+
sitemapName: sitemapConfig.sitemapName,
|
|
110
|
+
sources: sourcesInput
|
|
111
|
+
};
|
|
112
|
+
await nitro.hooks.callHook("sitemap:sources", ctx);
|
|
113
|
+
sourcesInput = ctx.sources;
|
|
114
|
+
}
|
|
115
|
+
const sources = await resolveSitemapSources(sourcesInput, resolvers.event);
|
|
116
|
+
const resolvedCtx = {
|
|
117
|
+
urls: sources.flatMap((s) => s.urls),
|
|
118
|
+
sitemapName: sitemapConfig.sitemapName,
|
|
119
|
+
event: resolvers.event
|
|
120
|
+
};
|
|
121
|
+
await nitro?.hooks.callHook("sitemap:input", resolvedCtx);
|
|
122
|
+
const normalisedUrls = resolveSitemapEntries(sitemapConfig, resolvedCtx.urls, { autoI18n, isI18nMapped }, resolvers);
|
|
123
|
+
const totalUrls = normalisedUrls.length;
|
|
124
|
+
const chunkCount = Math.ceil(totalUrls / chunkSize);
|
|
125
|
+
sitemapConfig._chunkCount = chunkCount;
|
|
126
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
127
|
+
const chunkName = `${sitemapName}-${i}`;
|
|
128
|
+
const entry = {
|
|
129
|
+
_sitemapName: chunkName,
|
|
130
|
+
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${chunkName}.xml`))
|
|
131
|
+
};
|
|
132
|
+
const chunkUrls = normalisedUrls.slice(i * chunkSize, (i + 1) * chunkSize);
|
|
133
|
+
let lastmod = chunkUrls.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];
|
|
134
|
+
if (!lastmod && autoLastmod)
|
|
135
|
+
lastmod = /* @__PURE__ */ new Date();
|
|
136
|
+
if (lastmod)
|
|
137
|
+
entry.lastmod = normaliseDate(lastmod);
|
|
138
|
+
entries.push(entry);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
65
142
|
if (sitemaps.index) {
|
|
66
143
|
entries.push(...sitemaps.index.sitemaps.map((entry) => {
|
|
67
144
|
return typeof entry === "string" ? { sitemap: entry } : entry;
|
|
@@ -77,9 +154,26 @@ export function urlsToIndexXml(sitemaps, resolvers, { version, xsl, credits, min
|
|
|
77
154
|
e.lastmod ? ` <lastmod>${escapeValueForXml(e.lastmod)}</lastmod>` : false,
|
|
78
155
|
" </sitemap>"
|
|
79
156
|
].filter(Boolean).join("\n")).join("\n");
|
|
80
|
-
|
|
157
|
+
const xmlParts = [
|
|
158
|
+
'<?xml version="1.0" encoding="UTF-8"?>'
|
|
159
|
+
];
|
|
160
|
+
if (xsl) {
|
|
161
|
+
const relativeBaseUrl = resolvers.relativeBaseUrlResolver?.(xsl) ?? xsl;
|
|
162
|
+
xmlParts.push(`<?xml-stylesheet type="text/xsl" href="${escapeValueForXml(relativeBaseUrl)}"?>`);
|
|
163
|
+
}
|
|
164
|
+
xmlParts.push(
|
|
81
165
|
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
82
166
|
sitemapXml,
|
|
83
167
|
"</sitemapindex>"
|
|
84
|
-
|
|
168
|
+
);
|
|
169
|
+
if (credits) {
|
|
170
|
+
xmlParts.push(`<!-- XML Sitemap Index generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
|
|
171
|
+
}
|
|
172
|
+
return minify ? xmlParts.join("").replace(/(?<!<[^>]*)\s(?![^<]*>)/g, "") : xmlParts.join("\n");
|
|
173
|
+
}
|
|
174
|
+
export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
|
|
175
|
+
if (!import.meta.dev && !!runtimeConfig.cacheMaxAgeSeconds && runtimeConfig.cacheMaxAgeSeconds > 0 && resolvers.event) {
|
|
176
|
+
return buildSitemapIndexCached(resolvers.event, resolvers, runtimeConfig, nitro);
|
|
177
|
+
}
|
|
178
|
+
return buildSitemapIndexInternal(resolvers, runtimeConfig, nitro);
|
|
85
179
|
}
|
|
@@ -7,4 +7,4 @@ export interface NormalizedI18n extends ResolvedSitemapUrl {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapUrlInput[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>, resolvers?: NitroUrlResolvers): ResolvedSitemapUrl[];
|
|
9
9
|
export declare function buildSitemapUrls(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<ResolvedSitemapUrl[]>;
|
|
10
|
-
export
|
|
10
|
+
export { urlsToXml } from './xml.js';
|