@nuxtjs/sitemap 8.3.0 → 8.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/content.mjs CHANGED
@@ -7,6 +7,16 @@ if (!globalThis.__sitemapCollectionOnUrlFns)
7
7
  globalThis.__sitemapCollectionOnUrlFns = /* @__PURE__ */ new Map();
8
8
  const collectionFilters = globalThis.__sitemapCollectionFilters;
9
9
  const collectionOnUrlFns = globalThis.__sitemapCollectionOnUrlFns;
10
+ function registerCollectionHooks(options, callerName) {
11
+ if (!options?.filter && !options?.onUrl)
12
+ return;
13
+ if (!options.name)
14
+ throw new Error(`[sitemap] \`name\` is required when using \`filter\` or \`onUrl\` in ${callerName}()`);
15
+ if (options.filter)
16
+ collectionFilters.set(options.name, options.filter);
17
+ if (options.onUrl)
18
+ collectionOnUrlFns.set(options.name, options.onUrl);
19
+ }
10
20
  const { defineSchema, asCollection, schema } = createContentSchemaFactory({
11
21
  fieldName: "sitemap",
12
22
  label: "sitemap",
@@ -16,14 +26,7 @@ const { defineSchema, asCollection, schema } = createContentSchemaFactory({
16
26
  if ("type" in options || "source" in options)
17
27
  throw new Error("[sitemap] `defineSitemapSchema()` returns a schema field, not a collection wrapper. Use it inside your schema: `schema: z.object({ sitemap: defineSitemapSchema() })`. See https://nuxtseo.com/sitemap/guides/content");
18
28
  warnIfZodMismatch(options?.z);
19
- if (options?.filter || options?.onUrl) {
20
- if (!options.name)
21
- throw new Error("[sitemap] `name` is required when using `filter` or `onUrl` in defineSitemapSchema()");
22
- if (options.filter)
23
- collectionFilters.set(options.name, options.filter);
24
- if (options.onUrl)
25
- collectionOnUrlFns.set(options.name, options.onUrl);
26
- }
29
+ registerCollectionHooks(options, "defineSitemapSchema");
27
30
  }
28
31
  }, z);
29
32
  function asSitemapCollection(collection, options) {
@@ -35,7 +35,10 @@ export async function refreshProductionData() {
35
35
  // Try fetching the full debug endpoint from production first (proxied through local server)
36
36
  const remoteDebug = await appFetch.value('/__sitemap__/debug-production.json', {
37
37
  query: { url: productionUrl.value, mode: 'debug' },
38
- }).catch(() => null) as (typeof data.value & { error?: string }) | null
38
+ }).catch(() => {
39
+ // Production debug is optional; use the public sitemap XML fallback below.
40
+ return null
41
+ }) as (typeof data.value & { error?: string }) | null
39
42
  if (remoteDebug && !remoteDebug.error && remoteDebug.sitemaps && !Array.isArray(remoteDebug.sitemaps)) {
40
43
  // Response has object sitemaps (debug.json format) rather than array (XML fallback format)
41
44
  productionRemoteDebugData.value = remoteDebug
@@ -137,7 +137,7 @@ const totalProductionWarnings = computed(() =>
137
137
  target="_blank"
138
138
  class="link-external"
139
139
  >
140
- Learn more
140
+ Learn more about large sitemaps
141
141
  </a>
142
142
  </DevtoolsAlert>
143
143
  </template>
@@ -320,7 +320,7 @@ const totalProductionWarnings = computed(() =>
320
320
  target="_blank"
321
321
  class="link-external"
322
322
  >
323
- Learn more
323
+ Learn more about large sitemaps
324
324
  </a>
325
325
  </DevtoolsAlert>
326
326
  </template>
package/dist/module.json CHANGED
@@ -4,9 +4,9 @@
4
4
  "nuxt": ">=3.9.0"
5
5
  },
6
6
  "configKey": "sitemap",
7
- "version": "8.3.0",
7
+ "version": "8.3.2",
8
8
  "builder": {
9
- "@nuxt/module-builder": "1.0.2",
9
+ "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
11
11
  }
12
12
  }
package/dist/module.mjs CHANGED
@@ -1,7 +1,9 @@
1
- import { useNuxt, hasNuxtModule, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, useLogger, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addPrerenderRoutes, addServerPlugin, resolveModule, addServerHandler } from '@nuxt/kit';
1
+ import { useNuxt, hasNuxtModule, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addPrerenderRoutes, addServerPlugin, resolveModule, addServerHandler } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
3
  import { withSiteUrl, installNuxtSiteConfig } from 'nuxt-site-config/kit';
4
4
  import { isPathFile } from 'nuxt-site-config/urls';
5
+ import { isNuxtGenerate, useModuleLogger, getNuxtModuleOptions, resolveNitroPreset, resolveNuxtContentVersion, createPagesPromise, createNitroPromise } from 'nuxtseo-shared/kit';
6
+ import { serializeFilters } from 'nuxtseo-shared/utils';
5
7
  import { dirname, extname } from 'pathe';
6
8
  import { readPackageJSON } from 'pkg-types';
7
9
  import { withBase, withHttps, withTrailingSlash, withoutLeadingSlash, joinURL, withLeadingSlash, withoutTrailingSlash } from 'ufo';
@@ -11,7 +13,6 @@ import { mkdir, writeFile } from 'node:fs/promises';
11
13
  import { join } from 'node:path';
12
14
  import { colors } from 'consola/utils';
13
15
  import { splitForLocales, createPathFilter } from '../dist/runtime/utils-pure.js';
14
- import { isNuxtGenerate, getNuxtModuleOptions, resolveNitroPreset, resolveNuxtContentVersion, createPagesPromise, createNitroPromise } from 'nuxtseo-shared/kit';
15
16
  import { p as parseHtmlExtractSitemapMeta } from './shared/sitemap.BoMnWHOt.mjs';
16
17
  import { normaliseDate } from '../dist/runtime/server/sitemap/urlset/normalise.js';
17
18
  import { splitPathForI18nLocales as splitPathForI18nLocales$1, expandCompactLocaleRoute, normalizeLocales, generatePathForI18nPages } from 'nuxtseo-shared/i18n';
@@ -242,6 +243,10 @@ declare module 'nuxt/app' {
242
243
  export {}
243
244
  `;
244
245
  }
246
+ }, {
247
+ nitro: true,
248
+ node: true,
249
+ nuxt: true
245
250
  });
246
251
  addTemplate({
247
252
  filename: "types/nuxt-sitemap-virtual.d.ts",
@@ -272,25 +277,6 @@ declare module '#sitemap/content-on-url' {
272
277
  });
273
278
  }
274
279
 
275
- function isValidFilter(filter) {
276
- if (typeof filter === "string")
277
- return true;
278
- if (filter instanceof RegExp)
279
- return true;
280
- if (typeof filter === "object" && typeof filter.regex === "string")
281
- return true;
282
- return false;
283
- }
284
- function normalizeFilters(filters) {
285
- return (filters || []).map((filter) => {
286
- if (!isValidFilter(filter)) {
287
- console.warn(`[@nuxtjs/sitemap] You have provided an invalid filter: ${filter}, ignoring.`);
288
- return false;
289
- }
290
- return filter instanceof RegExp ? { regex: filter.toString() } : filter;
291
- }).filter(Boolean);
292
- }
293
-
294
280
  function splitPathForI18nLocales(path, autoI18n) {
295
281
  if (typeof path !== "string")
296
282
  return path;
@@ -462,8 +448,7 @@ function generateExtraRoutesFromNuxtConfig(nuxt = useNuxt()) {
462
448
  return false;
463
449
  return !v.redirect;
464
450
  }).map(([k]) => k).filter(filterForValidPage);
465
- const prerenderUrls = (nuxt.options.nitro.prerender?.routes || []).filter(filterForValidPage);
466
- return { routeRules, prerenderUrls };
451
+ return { routeRules };
467
452
  }
468
453
 
469
454
  const module$1 = defineNuxtModule({
@@ -528,8 +513,7 @@ const module$1 = defineNuxtModule({
528
513
  async setup(config, nuxt) {
529
514
  const { resolve } = createResolver(import.meta.url);
530
515
  const { name, version } = await readPackageJSON(resolve("../package.json"));
531
- const logger = useLogger(name);
532
- logger.level = config.debug || nuxt.options.debug ? 4 : 3;
516
+ const logger = useModuleLogger(name, config, nuxt);
533
517
  if (config.enabled === false) {
534
518
  logger.debug("The module is disabled, skipping setup.");
535
519
  return;
@@ -1046,8 +1030,8 @@ ${onUrlEntries.join("\n")}`;
1046
1030
  }
1047
1031
  for (const sitemapName in sitemaps) {
1048
1032
  const sitemap = sitemaps[sitemapName];
1049
- sitemap.include = normalizeFilters(sitemap.include);
1050
- sitemap.exclude = normalizeFilters(sitemap.exclude);
1033
+ sitemap.include = serializeFilters(sitemap.include || [], "@nuxtjs/sitemap");
1034
+ sitemap.exclude = serializeFilters(sitemap.exclude || [], "@nuxtjs/sitemap");
1051
1035
  }
1052
1036
  const runtimeConfig = {
1053
1037
  isI18nMapped,
@@ -1153,8 +1137,8 @@ ${onUrlEntries.join("\n")}`;
1153
1137
  routesNameSeparator: nuxtI18nConfig.routesNameSeparator,
1154
1138
  normalisedLocales,
1155
1139
  filter: {
1156
- include: normalizeFilters(config.include),
1157
- exclude: normalizeFilters(config.exclude)
1140
+ include: serializeFilters(config.include || [], "@nuxtjs/sitemap"),
1141
+ exclude: serializeFilters(config.exclude || [], "@nuxtjs/sitemap")
1158
1142
  },
1159
1143
  autoI18n: !!resolvedAutoI18n
1160
1144
  });
@@ -1286,19 +1270,14 @@ export async function readSourcesFromFilesystem() {
1286
1270
  }
1287
1271
  `;
1288
1272
  }
1289
- if (prerenderSitemap && !nuxt.options.dev) {
1290
- nitroConfig.virtual["#sitemap-virtual/global-sources.mjs"] = `export const sources = []`;
1291
- nitroConfig.virtual[`#sitemap-virtual/child-sources.mjs`] = `export const sources = {}`;
1292
- } else {
1293
- nitroConfig.virtual["#sitemap-virtual/global-sources.mjs"] = async () => {
1294
- const globalSources = await generateGlobalSources();
1295
- return `export const sources = ${JSON.stringify(globalSources, null, 4)}`;
1296
- };
1297
- nitroConfig.virtual[`#sitemap-virtual/child-sources.mjs`] = async () => {
1298
- const childSources = await generateChildSources();
1299
- return `export const sources = ${JSON.stringify(childSources, null, 4)}`;
1300
- };
1301
- }
1273
+ nitroConfig.virtual["#sitemap-virtual/global-sources.mjs"] = async () => {
1274
+ const globalSources = await generateGlobalSources();
1275
+ return `export const sources = ${JSON.stringify(globalSources, null, 4)}`;
1276
+ };
1277
+ nitroConfig.virtual[`#sitemap-virtual/child-sources.mjs`] = async () => {
1278
+ const childSources = await generateChildSources();
1279
+ return `export const sources = ${JSON.stringify(childSources, null, 4)}`;
1280
+ };
1302
1281
  });
1303
1282
  if (config.xsl === "/__sitemap__/style.xsl") {
1304
1283
  addServerHandler({
@@ -1,8 +1,8 @@
1
- import type { SitemapWarning } from '@nuxtjs/sitemap/utils';
1
+ import type { SitemapIssue } from 'sitemapd/parse';
2
2
  export interface ProductionSitemapEntry {
3
3
  loc: string;
4
4
  urlCount: number;
5
- warnings: SitemapWarning[];
5
+ warnings: SitemapIssue[];
6
6
  error?: string;
7
7
  lastmod?: string;
8
8
  }
@@ -10,7 +10,7 @@ export interface ProductionDebugResponse {
10
10
  url: string;
11
11
  isIndex: boolean;
12
12
  sitemaps: ProductionSitemapEntry[];
13
- warnings: SitemapWarning[];
13
+ warnings: SitemapIssue[];
14
14
  error?: string;
15
15
  }
16
16
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, any> | ProductionDebugResponse>>;
@@ -1,13 +1,13 @@
1
- import { isSitemapIndex, parseSitemapIndex, parseSitemapXml } from "@nuxtjs/sitemap/utils";
2
1
  import { defineEventHandler, getQuery } from "h3";
3
- async function fetchXml(url) {
2
+ import { collectSitemap } from "sitemapd/parse";
3
+ async function fetchSitemapBody(url) {
4
4
  const response = await fetch(url, {
5
- headers: { Accept: "application/xml, text/xml" },
5
+ headers: { Accept: "application/xml, text/xml, application/gzip" },
6
6
  signal: AbortSignal.timeout(15e3)
7
7
  });
8
8
  if (!response.ok)
9
9
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
10
- return response.text();
10
+ return new Uint8Array(await response.arrayBuffer());
11
11
  }
12
12
  export default defineEventHandler(async (e) => {
13
13
  const { url, mode } = getQuery(e);
@@ -18,58 +18,74 @@ export default defineEventHandler(async (e) => {
18
18
  const response = await fetch(debugUrl, {
19
19
  headers: { Accept: "application/json" },
20
20
  signal: AbortSignal.timeout(1e4)
21
- }).catch(() => null);
21
+ }).catch(() => {
22
+ return null;
23
+ });
22
24
  if (response?.ok) {
23
- const json = await response.json().catch(() => null);
25
+ const json = await response.json().catch(() => {
26
+ return null;
27
+ });
24
28
  if (json?.sitemaps)
25
29
  return json;
26
30
  }
27
31
  }
28
32
  const sitemapUrl = url.endsWith("/") ? `${url}sitemap.xml` : url;
29
- const xml = await fetchXml(sitemapUrl).catch((err) => {
33
+ const body = await fetchSitemapBody(sitemapUrl).catch((err) => {
30
34
  return err;
31
35
  });
32
- if (xml instanceof Error)
33
- return { url: sitemapUrl, isIndex: false, sitemaps: [], warnings: [], error: `Failed to fetch sitemap: ${xml.message}` };
34
- if (isSitemapIndex(xml)) {
35
- const { entries, warnings } = await parseSitemapIndex(xml);
36
+ if (body instanceof Error)
37
+ return { url: sitemapUrl, isIndex: false, sitemaps: [], warnings: [], error: `Failed to fetch sitemap: ${body.message}` };
38
+ const parsed = await collectSitemap(body);
39
+ if (parsed._tag !== "document") {
40
+ return {
41
+ url: sitemapUrl,
42
+ isIndex: false,
43
+ sitemaps: [],
44
+ warnings: parsed.issues,
45
+ error: parsed.issues.map((issue) => issue.message).join("; ") || "Invalid sitemap document"
46
+ };
47
+ }
48
+ if (parsed.document._tag === "index") {
49
+ const { entries } = parsed.document;
36
50
  const sitemaps = await Promise.all(
37
51
  entries.map(async (entry) => {
38
- const childXml = await fetchXml(entry.loc).catch((err) => err);
39
- if (childXml instanceof Error) {
52
+ const childBody = await fetchSitemapBody(entry.loc).catch((err) => err);
53
+ if (childBody instanceof Error) {
40
54
  return {
41
55
  loc: entry.loc,
42
56
  urlCount: 0,
43
57
  warnings: [],
44
- error: childXml.message,
58
+ error: childBody.message,
59
+ lastmod: entry.lastmod
60
+ };
61
+ }
62
+ const result = await collectSitemap(childBody);
63
+ if (result._tag !== "document" || result.document._tag !== "urlset") {
64
+ return {
65
+ loc: entry.loc,
66
+ urlCount: 0,
67
+ warnings: result.issues,
68
+ error: result.issues.map((issue) => issue.message).join("; ") || "Child is not a URL set",
45
69
  lastmod: entry.lastmod
46
70
  };
47
71
  }
48
- const result2 = await parseSitemapXml(childXml).catch((err) => ({
49
- urls: [],
50
- warnings: [{ type: "validation", message: err.message }]
51
- }));
52
72
  return {
53
73
  loc: entry.loc,
54
- urlCount: result2.urls.length,
55
- warnings: result2.warnings,
74
+ urlCount: result.document.entries.length,
75
+ warnings: result.issues,
56
76
  lastmod: entry.lastmod
57
77
  };
58
78
  })
59
79
  );
60
- return { url: sitemapUrl, isIndex: true, sitemaps, warnings };
80
+ return { url: sitemapUrl, isIndex: true, sitemaps, warnings: parsed.issues };
61
81
  }
62
- const result = await parseSitemapXml(xml).catch((err) => ({
63
- urls: [],
64
- warnings: [{ type: "validation", message: err.message }]
65
- }));
66
82
  return {
67
83
  url: sitemapUrl,
68
84
  isIndex: false,
69
85
  sitemaps: [{
70
86
  loc: sitemapUrl,
71
- urlCount: result.urls.length,
72
- warnings: result.warnings
87
+ urlCount: parsed.document.entries.length,
88
+ warnings: parsed.issues
73
89
  }],
74
90
  warnings: []
75
91
  };
@@ -1,20 +1,24 @@
1
1
  import { withQuery } from "ufo";
2
2
  import { createChunkedXmlStream } from "../stream.js";
3
3
  import { escapeValueForXml } from "./xml.js";
4
+ function resolveIndexXslHref(resolvers, xsl, errorInfo) {
5
+ let relativeBaseUrl = resolvers.relativeBaseUrlResolver?.(xsl) ?? xsl;
6
+ if (errorInfo && errorInfo.messages.length > 0) {
7
+ relativeBaseUrl = withQuery(relativeBaseUrl, {
8
+ errors: "true",
9
+ error_messages: errorInfo.messages,
10
+ error_urls: errorInfo.urls
11
+ });
12
+ }
13
+ return relativeBaseUrl;
14
+ }
4
15
  export function* renderSitemapIndexXmlChunks(sitemaps, resolvers, { version, xsl, credits, minify }, errorInfo) {
5
16
  const NL = minify ? "" : "\n";
6
17
  const I1 = minify ? "" : " ";
7
18
  const I2 = minify ? "" : " ";
8
19
  yield '<?xml version="1.0" encoding="UTF-8"?>';
9
20
  if (xsl) {
10
- let relativeBaseUrl = resolvers.relativeBaseUrlResolver?.(xsl) ?? xsl;
11
- if (errorInfo && errorInfo.messages.length > 0) {
12
- relativeBaseUrl = withQuery(relativeBaseUrl, {
13
- errors: "true",
14
- error_messages: errorInfo.messages,
15
- error_urls: errorInfo.urls
16
- });
17
- }
21
+ const relativeBaseUrl = resolveIndexXslHref(resolvers, xsl, errorInfo);
18
22
  yield `${NL}<?xml-stylesheet type="text/xsl" href="${escapeValueForXml(relativeBaseUrl)}"?>`;
19
23
  }
20
24
  yield `${NL}<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${NL}`;
@@ -46,14 +50,7 @@ export function urlsToIndexXml(sitemaps, resolvers, { version, xsl, credits, min
46
50
  }
47
51
  const xmlParts = ['<?xml version="1.0" encoding="UTF-8"?>'];
48
52
  if (xsl) {
49
- let relativeBaseUrl = resolvers.relativeBaseUrlResolver?.(xsl) ?? xsl;
50
- if (errorInfo && errorInfo.messages.length > 0) {
51
- relativeBaseUrl = withQuery(relativeBaseUrl, {
52
- errors: "true",
53
- error_messages: errorInfo.messages,
54
- error_urls: errorInfo.urls
55
- });
56
- }
53
+ const relativeBaseUrl = resolveIndexXslHref(resolvers, xsl, errorInfo);
57
54
  xmlParts.push(`<?xml-stylesheet type="text/xsl" href="${escapeValueForXml(relativeBaseUrl)}"?>`);
58
55
  }
59
56
  xmlParts.push(
@@ -48,22 +48,7 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
48
48
  }
49
49
  const indexLastmod = autoLastmod ? normaliseDate(/* @__PURE__ */ new Date()) : void 0;
50
50
  const entries = [];
51
- if (typeof sitemaps.chunks !== "undefined") {
52
- const sitemap = sitemaps.chunks;
53
- const resolved = await getResolvedSitemapUrls(sitemap, "sitemap", true, resolvers, runtimeConfig, nitro);
54
- allFailedSources.push(...resolved.failedSources);
55
- const chunkCount = Math.ceil(resolved.urls.length / defaultSitemapsChunkSize);
56
- for (let i = 0; i < chunkCount; i++) {
57
- const entry = {
58
- _sitemapName: String(i),
59
- sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${i}.xml`))
60
- };
61
- if (indexLastmod)
62
- entry.lastmod = indexLastmod;
63
- entries.push(entry);
64
- }
65
- }
66
- for (const name of nonChunkedNames) {
51
+ const pushEntry = (name) => {
67
52
  const entry = {
68
53
  _sitemapName: name,
69
54
  sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${name}.xml`))
@@ -71,7 +56,17 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
71
56
  if (indexLastmod)
72
57
  entry.lastmod = indexLastmod;
73
58
  entries.push(entry);
59
+ };
60
+ if (typeof sitemaps.chunks !== "undefined") {
61
+ const sitemap = sitemaps.chunks;
62
+ const resolved = await getResolvedSitemapUrls(sitemap, "sitemap", true, resolvers, runtimeConfig, nitro);
63
+ allFailedSources.push(...resolved.failedSources);
64
+ const chunkCount = Math.ceil(resolved.urls.length / defaultSitemapsChunkSize);
65
+ for (let i = 0; i < chunkCount; i++)
66
+ pushEntry(String(i));
74
67
  }
68
+ for (const name of nonChunkedNames)
69
+ pushEntry(name);
75
70
  for (const sitemapName in sitemaps) {
76
71
  const sitemapConfig = sitemaps[sitemapName];
77
72
  if (sitemapName !== "index" && sitemapConfig._isChunking) {
@@ -85,16 +80,8 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
85
80
  chunkCount = Math.ceil(resolved.urls.length / chunkSize);
86
81
  }
87
82
  sitemapConfig._chunkCount = chunkCount;
88
- for (let i = 0; i < chunkCount; i++) {
89
- const chunkName = `${sitemapName}-${i}`;
90
- const entry = {
91
- _sitemapName: chunkName,
92
- sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${chunkName}.xml`))
93
- };
94
- if (indexLastmod)
95
- entry.lastmod = indexLastmod;
96
- entries.push(entry);
97
- }
83
+ for (let i = 0; i < chunkCount; i++)
84
+ pushEntry(`${sitemapName}-${i}`);
98
85
  }
99
86
  }
100
87
  if (sitemaps.index) {
@@ -1,10 +1,10 @@
1
1
  import type { ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl } from '../../../types.js';
2
2
  export declare function escapeValueForXml(value: boolean | string | number): string;
3
- export declare function renderSitemapXmlChunks(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
3
+ export declare function renderSitemapXmlChunks(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, config: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
4
4
  messages: string[];
5
5
  urls: string[];
6
6
  }): Generator<string>;
7
- export declare function urlsToXml(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
7
+ export declare function urlsToXml(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, config: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
8
8
  messages: string[];
9
9
  urls: string[];
10
10
  }): string;
@@ -116,7 +116,7 @@ function buildUrlXml(url, NL, I1, I2, I3, I4) {
116
116
  xml += `${I1}</url>`;
117
117
  return xml;
118
118
  }
119
- export function* renderSitemapXmlChunks(urls, resolvers, { version, xsl, credits, minify }, errorInfo) {
119
+ function resolveXmlRenderContext(resolvers, { xsl, minify }, errorInfo) {
120
120
  let xslHref = xsl ? resolvers.relativeBaseUrlResolver(xsl) : false;
121
121
  if (xslHref && errorInfo?.messages.length) {
122
122
  xslHref = withQuery(xslHref, {
@@ -126,10 +126,18 @@ export function* renderSitemapXmlChunks(urls, resolvers, { version, xsl, credits
126
126
  });
127
127
  }
128
128
  const NL = minify ? "" : "\n";
129
- const I1 = minify ? "" : " ";
130
- const I2 = minify ? "" : " ";
131
- const I3 = minify ? "" : " ";
132
- const I4 = minify ? "" : " ";
129
+ return {
130
+ xslHref,
131
+ NL,
132
+ I1: minify ? "" : " ",
133
+ I2: minify ? "" : " ",
134
+ I3: minify ? "" : " ",
135
+ I4: minify ? "" : " "
136
+ };
137
+ }
138
+ export function* renderSitemapXmlChunks(urls, resolvers, config, errorInfo) {
139
+ const { version, credits } = config;
140
+ const { xslHref, NL, I1, I2, I3, I4 } = resolveXmlRenderContext(resolvers, config, errorInfo);
133
141
  yield xslHref ? `<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="${escapeValueForXml(xslHref)}"?>${NL}` : `<?xml version="1.0" encoding="UTF-8"?>${NL}`;
134
142
  yield URLSET_OPENING_TAG + NL;
135
143
  for (const url of urls) {
@@ -140,20 +148,9 @@ export function* renderSitemapXmlChunks(urls, resolvers, { version, xsl, credits
140
148
  yield `${NL}<!-- XML Sitemap generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
141
149
  }
142
150
  }
143
- export function urlsToXml(urls, resolvers, { version, xsl, credits, minify }, errorInfo) {
144
- let xslHref = xsl ? resolvers.relativeBaseUrlResolver(xsl) : false;
145
- if (xslHref && errorInfo?.messages.length) {
146
- xslHref = withQuery(xslHref, {
147
- errors: "true",
148
- error_messages: errorInfo.messages,
149
- error_urls: errorInfo.urls
150
- });
151
- }
152
- const NL = minify ? "" : "\n";
153
- const I1 = minify ? "" : " ";
154
- const I2 = minify ? "" : " ";
155
- const I3 = minify ? "" : " ";
156
- const I4 = minify ? "" : " ";
151
+ export function urlsToXml(urls, resolvers, config, errorInfo) {
152
+ const { version, credits } = config;
153
+ const { xslHref, NL, I1, I2, I3, I4 } = resolveXmlRenderContext(resolvers, config, errorInfo);
157
154
  let xml = xslHref ? `<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="${escapeValueForXml(xslHref)}"?>${NL}` : `<?xml version="1.0" encoding="UTF-8"?>${NL}`;
158
155
  xml += URLSET_OPENING_TAG + NL;
159
156
  for (const url of urls)
@@ -1,10 +1,10 @@
1
- import { appendHeader, createError, getRequestURL, getRouterParam, sendRedirect, setHeader } from "h3";
1
+ import { appendHeader, createError, getRequestURL, getRouterParam, sendRedirect } from "h3";
2
2
  import { useNitroApp, useRuntimeConfig } from "nitropack/runtime";
3
3
  import { joinURL, withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from "ufo";
4
4
  import { useSitemapRuntimeConfig } from "../utils.js";
5
5
  import { urlsToIndexXml, urlsToIndexXmlStream } from "./builder/index-xml.js";
6
6
  import { buildSitemapIndex } from "./builder/sitemap-index.js";
7
- import { createSitemap, renderSitemapOutput, useNitroUrlResolvers } from "./nitro.js";
7
+ import { createSitemap, renderSitemapOutput, setSitemapResponseHeaders, useNitroUrlResolvers } from "./nitro.js";
8
8
  import { getSitemapConfig, parseChunkInfo } from "./utils/chunk.js";
9
9
  export async function sitemapXmlEventHandler(e) {
10
10
  const runtimeConfig = useSitemapRuntimeConfig();
@@ -37,20 +37,7 @@ export async function sitemapIndexXmlEventHandler(e) {
37
37
  !!runtimeConfig.experimentalStreaming && !import.meta.prerender,
38
38
  runtimeConfig.debug
39
39
  );
40
- setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
41
- if (runtimeConfig.cacheMaxAgeSeconds) {
42
- setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, s-maxage=${runtimeConfig.cacheMaxAgeSeconds}, stale-while-revalidate=3600`);
43
- const now = /* @__PURE__ */ new Date();
44
- setHeader(e, "X-Sitemap-Generated", now.toISOString());
45
- setHeader(e, "X-Sitemap-Cache-Duration", `${runtimeConfig.cacheMaxAgeSeconds}s`);
46
- const expiryTime = new Date(now.getTime() + runtimeConfig.cacheMaxAgeSeconds * 1e3);
47
- setHeader(e, "X-Sitemap-Cache-Expires", expiryTime.toISOString());
48
- const remainingSeconds = Math.floor((expiryTime.getTime() - now.getTime()) / 1e3);
49
- setHeader(e, "X-Sitemap-Cache-Remaining", `${remainingSeconds}s`);
50
- } else {
51
- setHeader(e, "Cache-Control", `no-cache, no-store`);
52
- }
53
- e.context._isSitemap = true;
40
+ setSitemapResponseHeaders(e, runtimeConfig);
54
41
  return output;
55
42
  }
56
43
  export async function sitemapChildXmlEventHandler(e) {
@@ -3,4 +3,5 @@ import type { NitroApp } from 'nitropack/types';
3
3
  import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapDefinition } from '../../types.js';
4
4
  export declare function useNitroUrlResolvers(e: H3Event): NitroUrlResolvers;
5
5
  export declare function renderSitemapOutput(nitro: NitroApp, event: H3Event, sitemapName: string, renderString: () => string, renderStream: () => ReadableStream<Uint8Array>, shouldStream: boolean, debug: boolean): Promise<string | ReadableStream<Uint8Array>>;
6
+ export declare function setSitemapResponseHeaders(event: H3Event, runtimeConfig: ModuleRuntimeConfig): void;
6
7
  export declare function createSitemap(event: H3Event, definition: SitemapDefinition, runtimeConfig: ModuleRuntimeConfig): Promise<string | ReadableStream<Uint8Array<ArrayBufferLike>>>;
@@ -1,13 +1,13 @@
1
1
  import { defu } from "defu";
2
2
  import { createError, getHeader, getQuery, setHeader } from "h3";
3
- import { defineCachedFunction, useNitroApp } from "nitropack/runtime";
3
+ import { defineCachedFunction, useNitroApp, useRuntimeConfig } from "nitropack/runtime";
4
4
  import { fixSlashes } from "nuxt-site-config/urls";
5
+ import { createNitroRouteRuleMatcher } from "nuxtseo-shared/server";
5
6
  import { getPathRobotConfig } from "#internal/nuxt-robots/getPathRobotConfig";
6
7
  import { getSiteConfig } from "#site-config/server/composables/getSiteConfig";
7
8
  import { createSitePathResolver } from "#site-config/server/composables/utils";
8
9
  import staticConfig from "#sitemap-virtual/static-config.mjs";
9
10
  import { logger, mergeOnKey, splitForLocales } from "../../utils-pure.js";
10
- import { createNitroRouteRuleMatcher } from "../kit.js";
11
11
  import { buildSitemapUrls, urlsToXml, urlsToXmlStream } from "./builder/sitemap.js";
12
12
  import { createChunkedXmlStream } from "./stream.js";
13
13
  import { normaliseEntry, preNormalizeEntry } from "./urlset/normalise.js";
@@ -52,7 +52,7 @@ async function buildSitemapRenderPlan(event, definition, resolvers, runtimeConfi
52
52
  message: `Sitemap generation failed due to ${failedSources.length} failed sources: ${failedSources.map((s) => `"${s.url}" (${s.error})`).join(", ")}`
53
53
  });
54
54
  }
55
- const routeRuleMatcher = createNitroRouteRuleMatcher();
55
+ const routeRuleMatcher = createNitroRouteRuleMatcher(useRuntimeConfig(event));
56
56
  const { autoI18n } = runtimeConfig;
57
57
  const localeCodes = autoI18n?.locales && autoI18n.strategy !== "no_prefix" ? new Set(autoI18n.locales.map((l) => l.code)) : void 0;
58
58
  const sourceCount = sitemapUrls.length;
@@ -205,6 +205,22 @@ const buildSitemapXmlCached = defineCachedFunction(
205
205
  // Enable stale-while-revalidate
206
206
  }
207
207
  );
208
+ export function setSitemapResponseHeaders(event, runtimeConfig) {
209
+ setHeader(event, "Content-Type", "text/xml; charset=UTF-8");
210
+ if (runtimeConfig.cacheMaxAgeSeconds) {
211
+ setHeader(event, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, s-maxage=${runtimeConfig.cacheMaxAgeSeconds}, stale-while-revalidate=3600`);
212
+ const now = /* @__PURE__ */ new Date();
213
+ setHeader(event, "X-Sitemap-Generated", now.toISOString());
214
+ setHeader(event, "X-Sitemap-Cache-Duration", `${runtimeConfig.cacheMaxAgeSeconds}s`);
215
+ const expiryTime = new Date(now.getTime() + runtimeConfig.cacheMaxAgeSeconds * 1e3);
216
+ setHeader(event, "X-Sitemap-Cache-Expires", expiryTime.toISOString());
217
+ const remainingSeconds = Math.floor((expiryTime.getTime() - now.getTime()) / 1e3);
218
+ setHeader(event, "X-Sitemap-Cache-Remaining", `${remainingSeconds}s`);
219
+ } else {
220
+ setHeader(event, "Cache-Control", `no-cache, no-store`);
221
+ }
222
+ event.context._isSitemap = true;
223
+ }
208
224
  export async function createSitemap(event, definition, runtimeConfig) {
209
225
  const resolvers = useNitroUrlResolvers(event);
210
226
  const shouldStream = !!runtimeConfig.experimentalStreaming && !import.meta.prerender;
@@ -224,19 +240,6 @@ export async function createSitemap(event, definition, runtimeConfig) {
224
240
  } else {
225
241
  xml = shouldCache ? await buildSitemapXmlCached(event, definition, resolvers, runtimeConfig) : await buildSitemapXml(event, definition, resolvers, runtimeConfig);
226
242
  }
227
- setHeader(event, "Content-Type", "text/xml; charset=UTF-8");
228
- if (runtimeConfig.cacheMaxAgeSeconds) {
229
- setHeader(event, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, s-maxage=${runtimeConfig.cacheMaxAgeSeconds}, stale-while-revalidate=3600`);
230
- const now = /* @__PURE__ */ new Date();
231
- setHeader(event, "X-Sitemap-Generated", now.toISOString());
232
- setHeader(event, "X-Sitemap-Cache-Duration", `${runtimeConfig.cacheMaxAgeSeconds}s`);
233
- const expiryTime = new Date(now.getTime() + runtimeConfig.cacheMaxAgeSeconds * 1e3);
234
- setHeader(event, "X-Sitemap-Cache-Expires", expiryTime.toISOString());
235
- const remainingSeconds = Math.floor((expiryTime.getTime() - now.getTime()) / 1e3);
236
- setHeader(event, "X-Sitemap-Cache-Remaining", `${remainingSeconds}s`);
237
- } else {
238
- setHeader(event, "Cache-Control", `no-cache, no-store`);
239
- }
240
- event.context._isSitemap = true;
243
+ setSitemapResponseHeaders(event, runtimeConfig);
241
244
  return xml;
242
245
  }