@nuxtjs/sitemap 2.4.0 → 5.0.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.
Files changed (86) hide show
  1. package/README.md +60 -593
  2. package/dist/client/200.html +11 -0
  3. package/dist/client/404.html +11 -0
  4. package/dist/client/_nuxt/Icon.I3NdYkjC.css +1 -0
  5. package/dist/client/_nuxt/Icon.wdYGFqbO.js +1 -0
  6. package/dist/client/_nuxt/IconCSS.6oz918NR.css +1 -0
  7. package/dist/client/_nuxt/IconCSS.L-uj6Ouj.js +1 -0
  8. package/dist/client/_nuxt/builds/latest.json +1 -0
  9. package/dist/client/_nuxt/builds/meta/c3bdccb2-d4db-4a94-9e61-39b740a57bf8.json +1 -0
  10. package/dist/client/_nuxt/entry.Soe9IWze.js +15 -0
  11. package/dist/client/_nuxt/entry.UqhvG0ao.css +1 -0
  12. package/dist/client/_nuxt/error-404.DkXpI38i.css +1 -0
  13. package/dist/client/_nuxt/error-404.uz-DxZsp.js +1 -0
  14. package/dist/client/_nuxt/error-500.BsNDeZpL.js +1 -0
  15. package/dist/client/_nuxt/error-500.SLhS9LVu.css +1 -0
  16. package/dist/client/_nuxt/index.lSDm5iYo.js +1 -0
  17. package/dist/client/index.html +11 -0
  18. package/dist/module.cjs +5 -0
  19. package/dist/module.d.mts +350 -0
  20. package/dist/module.d.ts +350 -0
  21. package/dist/module.json +9 -0
  22. package/dist/module.mjs +994 -0
  23. package/dist/runtime/nitro/composables/asSitemapUrl.d.ts +2 -0
  24. package/dist/runtime/nitro/composables/asSitemapUrl.mjs +3 -0
  25. package/dist/runtime/nitro/composables/defineSitemapEventHandler.d.ts +3 -0
  26. package/dist/runtime/nitro/composables/defineSitemapEventHandler.mjs +2 -0
  27. package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.d.ts +4 -0
  28. package/dist/runtime/nitro/composables/getPathRobotConfigPolyfill.mjs +3 -0
  29. package/dist/runtime/nitro/kit.d.ts +3 -0
  30. package/dist/runtime/nitro/kit.mjs +23 -0
  31. package/dist/runtime/nitro/middleware/[sitemap]-sitemap.xml.d.ts +2 -0
  32. package/dist/runtime/nitro/middleware/[sitemap]-sitemap.xml.mjs +23 -0
  33. package/dist/runtime/nitro/plugins/compression.d.ts +2 -0
  34. package/dist/runtime/nitro/plugins/compression.mjs +8 -0
  35. package/dist/runtime/nitro/plugins/nuxt-content.d.ts +2 -0
  36. package/dist/runtime/nitro/plugins/nuxt-content.mjs +38 -0
  37. package/dist/runtime/nitro/plugins/warm-up.d.ts +2 -0
  38. package/dist/runtime/nitro/plugins/warm-up.mjs +23 -0
  39. package/dist/runtime/nitro/routes/__sitemap__/debug.d.ts +37 -0
  40. package/dist/runtime/nitro/routes/__sitemap__/debug.mjs +29 -0
  41. package/dist/runtime/nitro/routes/__sitemap__/nuxt-content-urls.d.ts +2 -0
  42. package/dist/runtime/nitro/routes/__sitemap__/nuxt-content-urls.mjs +6 -0
  43. package/dist/runtime/nitro/routes/sitemap.xml.d.ts +2 -0
  44. package/dist/runtime/nitro/routes/sitemap.xml.mjs +13 -0
  45. package/dist/runtime/nitro/routes/sitemap.xsl.d.ts +2 -0
  46. package/dist/runtime/nitro/routes/sitemap.xsl.mjs +230 -0
  47. package/dist/runtime/nitro/routes/sitemap_index.xml.d.ts +2 -0
  48. package/dist/runtime/nitro/routes/sitemap_index.xml.mjs +27 -0
  49. package/dist/runtime/nitro/sitemap/builder/sitemap-index.d.ts +2 -0
  50. package/dist/runtime/nitro/sitemap/builder/sitemap-index.mjs +86 -0
  51. package/dist/runtime/nitro/sitemap/builder/sitemap.d.ts +2 -0
  52. package/dist/runtime/nitro/sitemap/builder/sitemap.mjs +107 -0
  53. package/dist/runtime/nitro/sitemap/builder/xml.d.ts +4 -0
  54. package/dist/runtime/nitro/sitemap/builder/xml.mjs +83 -0
  55. package/dist/runtime/nitro/sitemap/nitro.d.ts +4 -0
  56. package/dist/runtime/nitro/sitemap/nitro.mjs +36 -0
  57. package/dist/runtime/nitro/sitemap/urlset/filter.d.ts +5 -0
  58. package/dist/runtime/nitro/sitemap/urlset/filter.mjs +50 -0
  59. package/dist/runtime/nitro/sitemap/urlset/i18n.d.ts +8 -0
  60. package/dist/runtime/nitro/sitemap/urlset/i18n.mjs +128 -0
  61. package/dist/runtime/nitro/sitemap/urlset/normalise.d.ts +3 -0
  62. package/dist/runtime/nitro/sitemap/urlset/normalise.mjs +77 -0
  63. package/dist/runtime/nitro/sitemap/urlset/sort.d.ts +2 -0
  64. package/dist/runtime/nitro/sitemap/urlset/sort.mjs +19 -0
  65. package/dist/runtime/nitro/sitemap/urlset/sources.d.ts +5 -0
  66. package/dist/runtime/nitro/sitemap/urlset/sources.mjs +82 -0
  67. package/dist/runtime/nitro/tsconfig.json +3 -0
  68. package/dist/runtime/nitro/utils.d.ts +4 -0
  69. package/dist/runtime/nitro/utils.mjs +13 -0
  70. package/dist/runtime/types.d.ts +355 -0
  71. package/dist/runtime/types.mjs +0 -0
  72. package/dist/runtime/utils-pure.d.ts +7 -0
  73. package/dist/runtime/utils-pure.mjs +32 -0
  74. package/dist/types.d.mts +18 -0
  75. package/dist/types.d.ts +18 -0
  76. package/package.json +79 -75
  77. package/CHANGELOG.md +0 -268
  78. package/LICENSE +0 -21
  79. package/lib/builder.js +0 -172
  80. package/lib/cache.js +0 -95
  81. package/lib/generator.js +0 -113
  82. package/lib/logger.js +0 -19
  83. package/lib/middleware.js +0 -195
  84. package/lib/module.js +0 -72
  85. package/lib/options.js +0 -135
  86. package/lib/routes.js +0 -55
@@ -0,0 +1,107 @@
1
+ import { defu } from "defu";
2
+ import { resolveSitePath } from "site-config-stack/urls";
3
+ import { parseURL, withHttps } from "ufo";
4
+ import { normaliseSitemapUrls } from "../urlset/normalise.mjs";
5
+ import { childSitemapSources, globalSitemapSources, resolveSitemapSources } from "../urlset/sources.mjs";
6
+ import { filterSitemapUrls } from "../urlset/filter.mjs";
7
+ import { applyI18nEnhancements, normaliseI18nSources } from "../urlset/i18n.mjs";
8
+ import { sortSitemapUrls } from "../urlset/sort.mjs";
9
+ import { splitForLocales } from "../../utils.mjs";
10
+ import { createNitroRouteRuleMatcher } from "../../kit.mjs";
11
+ import { handleEntry, wrapSitemapXml } from "./xml.mjs";
12
+ import { useNitroApp } from "#imports";
13
+ export async function buildSitemap(sitemap, resolvers, runtimeConfig) {
14
+ const {
15
+ sitemaps,
16
+ // enhancing
17
+ autoLastmod,
18
+ autoI18n,
19
+ isI18nMapped,
20
+ isMultiSitemap,
21
+ // sorting
22
+ sortEntries,
23
+ // chunking
24
+ defaultSitemapsChunkSize,
25
+ // xls
26
+ version,
27
+ xsl,
28
+ credits
29
+ } = runtimeConfig;
30
+ const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemap.sitemapName));
31
+ function maybeSort(urls2) {
32
+ return sortEntries ? sortSitemapUrls(urls2) : urls2;
33
+ }
34
+ function maybeSlice(urls2) {
35
+ if (isChunking && defaultSitemapsChunkSize) {
36
+ const chunk = Number(sitemap.sitemapName);
37
+ return urls2.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize);
38
+ }
39
+ return urls2;
40
+ }
41
+ if (autoI18n?.differentDomains) {
42
+ const domain = autoI18n.locales.find((e) => [e.iso, e.code].includes(sitemap.sitemapName))?.domain;
43
+ if (domain) {
44
+ const _tester = resolvers.canonicalUrlResolver;
45
+ resolvers.canonicalUrlResolver = (path) => resolveSitePath(path, {
46
+ absolute: true,
47
+ withBase: false,
48
+ siteUrl: withHttps(domain),
49
+ trailingSlash: !_tester("/test/").endsWith("/"),
50
+ base: "/"
51
+ });
52
+ }
53
+ }
54
+ const sources = sitemap.includeAppSources ? await globalSitemapSources() : [];
55
+ sources.push(...await childSitemapSources(sitemap));
56
+ let resolvedSources = await resolveSitemapSources(sources);
57
+ if (autoI18n)
58
+ resolvedSources = normaliseI18nSources(resolvedSources, { autoI18n, isI18nMapped });
59
+ const normalisedUrls = normaliseSitemapUrls(resolvedSources.map((e) => e.urls).flat(), resolvers);
60
+ const defaults = { ...sitemap.defaults || {} };
61
+ if (autoLastmod && defaults?.lastmod)
62
+ defaults.lastmod = /* @__PURE__ */ new Date();
63
+ const routeRuleMatcher = createNitroRouteRuleMatcher();
64
+ let enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults)).map((e) => {
65
+ const path = parseURL(e.loc).pathname;
66
+ let routeRules = routeRuleMatcher(path);
67
+ if (autoI18n?.locales && autoI18n?.strategy !== "no_prefix") {
68
+ const match = splitForLocales(path, autoI18n.locales.map((l) => l.code));
69
+ const pathWithoutPrefix = match[1];
70
+ if (pathWithoutPrefix && pathWithoutPrefix !== path)
71
+ routeRules = defu(routeRules, routeRuleMatcher(pathWithoutPrefix));
72
+ }
73
+ if (routeRules.sitemap === false)
74
+ return false;
75
+ if (typeof routeRules.index !== "undefined" && !routeRules.index)
76
+ return false;
77
+ const hasRobotsDisabled = Object.entries(routeRules.headers || {}).some(([name, value]) => name.toLowerCase() === "x-robots-tag" && value.toLowerCase() === "noindex");
78
+ if (routeRules.redirect || hasRobotsDisabled)
79
+ return false;
80
+ return routeRules.sitemap ? defu(e, routeRules.sitemap) : e;
81
+ }).filter(Boolean);
82
+ if (autoI18n?.locales)
83
+ enhancedUrls = applyI18nEnhancements(enhancedUrls, { isI18nMapped, autoI18n, sitemapName: sitemap.sitemapName });
84
+ const filteredUrls = filterSitemapUrls(enhancedUrls, { event: resolvers.event, isMultiSitemap, autoI18n, ...sitemap });
85
+ const sortedUrls = maybeSort(filteredUrls);
86
+ const slicedUrls = maybeSlice(sortedUrls);
87
+ const nitro = useNitroApp();
88
+ const ctx = {
89
+ urls: slicedUrls,
90
+ sitemapName: sitemap.sitemapName
91
+ };
92
+ await nitro.hooks.callHook("sitemap:resolved", ctx);
93
+ const urls = maybeSort(normaliseSitemapUrls(ctx.urls, resolvers));
94
+ const urlset = urls.map((e) => {
95
+ const keys = Object.keys(e).filter((k) => !k.startsWith("_"));
96
+ return [
97
+ " <url>",
98
+ keys.map((k) => handleEntry(k, e)).filter(Boolean).join("\n"),
99
+ " </url>"
100
+ ].join("\n");
101
+ });
102
+ return wrapSitemapXml([
103
+ '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
104
+ urlset.join("\n"),
105
+ "</urlset>"
106
+ ], resolvers, { version, xsl, credits });
107
+ }
@@ -0,0 +1,4 @@
1
+ import type { ModuleRuntimeConfig, NitroUrlResolvers } from '../../../types';
2
+ export declare function handleEntry(k: string, e: Record<string, any> | (string | Record<string, any>)[]): string | false;
3
+ export declare function wrapSitemapXml(input: string[], resolvers: NitroUrlResolvers, options: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits'>): string;
4
+ export declare function escapeValueForXml(value: boolean | string | number): string;
@@ -0,0 +1,83 @@
1
+ function resolveKey(k) {
2
+ switch (k) {
3
+ case "images":
4
+ return "image";
5
+ case "videos":
6
+ return "video";
7
+ case "news":
8
+ return "news";
9
+ default:
10
+ return k;
11
+ }
12
+ }
13
+ function handleObject(key, obj) {
14
+ return [
15
+ ` <${key}:${key}>`,
16
+ ...Object.entries(obj).map(([sk, sv]) => {
17
+ if (key === "video" && Array.isArray(sv)) {
18
+ return sv.map((v) => {
19
+ if (typeof v === "string") {
20
+ return [
21
+ ` `,
22
+ `<${key}:${sk}>`,
23
+ escapeValueForXml(v),
24
+ `</${key}:${sk}>`
25
+ ].join("");
26
+ }
27
+ const attributes = Object.entries(v).filter(([ssk]) => ssk !== sk).map(([ssk, ssv]) => `${ssk}="${escapeValueForXml(ssv)}"`).join(" ");
28
+ return [
29
+ ` <${key}:${sk} ${attributes}>`,
30
+ // value is the same sk
31
+ v[sk],
32
+ `</${key}:${sk}>`
33
+ ].join("");
34
+ }).join("\n");
35
+ }
36
+ if (typeof sv === "object") {
37
+ if (key === "video") {
38
+ const attributes = Object.entries(sv).filter(([ssk]) => ssk !== sk).map(([ssk, ssv]) => `${ssk}="${escapeValueForXml(ssv)}"`).join(" ");
39
+ return [
40
+ ` <${key}:${sk} ${attributes}>`,
41
+ // value is the same sk
42
+ sv[sk],
43
+ `</${key}:${sk}>`
44
+ ].join("");
45
+ }
46
+ return [
47
+ ` <${key}:${sk}>`,
48
+ ...Object.entries(sv).map(([ssk, ssv]) => ` <${key}:${ssk}>${escapeValueForXml(ssv)}</${key}:${ssk}>`),
49
+ ` </${key}:${sk}>`
50
+ ].join("\n");
51
+ }
52
+ return ` <${key}:${sk}>${escapeValueForXml(sv)}</${key}:${sk}>`;
53
+ }),
54
+ ` </${key}:${key}>`
55
+ ].join("\n");
56
+ }
57
+ function handleArray(key, arr) {
58
+ if (arr.length === 0)
59
+ return false;
60
+ key = resolveKey(key);
61
+ if (key === "alternatives") {
62
+ return arr.map((obj) => [
63
+ ` <xhtml:link rel="alternate" ${Object.entries(obj).map(([sk, sv]) => `${sk}="${escapeValueForXml(sv)}"`).join(" ")} />`
64
+ ].join("\n")).join("\n");
65
+ }
66
+ return arr.map((obj) => handleObject(key, obj)).join("\n");
67
+ }
68
+ export function handleEntry(k, e) {
69
+ return Array.isArray(e[k]) ? handleArray(k, e[k]) : typeof e[k] === "object" ? handleObject(k, e[k]) : ` <${k}>${escapeValueForXml(e[k])}</${k}>`;
70
+ }
71
+ export function wrapSitemapXml(input, resolvers, options) {
72
+ const xsl = options.xsl ? resolvers.relativeBaseUrlResolver(options.xsl) : false;
73
+ const credits = options.credits;
74
+ input.unshift(`<?xml version="1.0" encoding="UTF-8"?>${xsl ? `<?xml-stylesheet type="text/xsl" href="${xsl}"?>` : ""}`);
75
+ if (credits)
76
+ input.push(`<!-- XML Sitemap generated by @nuxtjs/sitemap v${options.version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
77
+ return input.join("\n");
78
+ }
79
+ export function escapeValueForXml(value) {
80
+ if (value === true || value === false)
81
+ return value ? "yes" : "no";
82
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
83
+ }
@@ -0,0 +1,4 @@
1
+ import { type H3Event } from 'h3';
2
+ import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapDefinition } from '../../types';
3
+ export declare function useNitroUrlResolvers(e: H3Event): NitroUrlResolvers;
4
+ export declare function createSitemap(e: H3Event, definition: SitemapDefinition, runtimeConfig: ModuleRuntimeConfig): Promise<string>;
@@ -0,0 +1,36 @@
1
+ import { getQuery, setHeader } from "h3";
2
+ import { fixSlashes } from "site-config-stack/urls";
3
+ import { buildSitemap } from "./builder/sitemap.mjs";
4
+ import { buildSitemapIndex } from "./builder/sitemap-index.mjs";
5
+ import { createSitePathResolver, useNitroApp, useSiteConfig } from "#imports";
6
+ export function useNitroUrlResolvers(e) {
7
+ const canonicalQuery = getQuery(e).canonical;
8
+ const isShowingCanonical = typeof canonicalQuery !== "undefined" && canonicalQuery !== "false";
9
+ const siteConfig = useSiteConfig(e);
10
+ return {
11
+ event: e,
12
+ fixSlashes: (path) => fixSlashes(siteConfig.trailingSlash, path),
13
+ // we need these as they depend on the nitro event
14
+ canonicalUrlResolver: createSitePathResolver(e, {
15
+ canonical: isShowingCanonical || !process.dev,
16
+ absolute: true,
17
+ withBase: true
18
+ }),
19
+ relativeBaseUrlResolver: createSitePathResolver(e, { absolute: false, withBase: true })
20
+ };
21
+ }
22
+ export async function createSitemap(e, definition, runtimeConfig) {
23
+ const { sitemapName } = definition;
24
+ const nitro = useNitroApp();
25
+ let sitemap = await (definition.sitemapName === "index" ? buildSitemapIndex(useNitroUrlResolvers(e), runtimeConfig) : buildSitemap(definition, useNitroUrlResolvers(e), runtimeConfig));
26
+ const ctx = { sitemap, sitemapName };
27
+ await nitro.hooks.callHook("sitemap:output", ctx);
28
+ sitemap = ctx.sitemap;
29
+ setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
30
+ if (runtimeConfig.cacheMaxAgeSeconds)
31
+ setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
32
+ else
33
+ setHeader(e, "Cache-Control", `no-cache, no-store`);
34
+ e.context._isSitemap = true;
35
+ return sitemap;
36
+ }
@@ -0,0 +1,5 @@
1
+ import type { H3Event } from 'h3';
2
+ import type { ModuleRuntimeConfig, ResolvedSitemapUrl } from '../../../types';
3
+ export declare function filterSitemapUrls(_urls: ResolvedSitemapUrl[], options: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isMultiSitemap'> & Pick<ModuleRuntimeConfig['sitemaps'][string], 'sitemapName' | 'include' | 'exclude'> & {
4
+ event: H3Event;
5
+ }): ResolvedSitemapUrl[];
@@ -0,0 +1,50 @@
1
+ import { parseURL } from "ufo";
2
+ import { createRouter, toRouteMatcher } from "radix3";
3
+ import { getPathRobotConfig } from "#imports";
4
+ function createFilter(options = {}) {
5
+ const include = options.include || [];
6
+ const exclude = options.exclude || [];
7
+ if (include.length === 0 && exclude.length === 0)
8
+ return () => true;
9
+ return function(path) {
10
+ for (const v of [{ rules: exclude, result: false }, { rules: include, result: true }]) {
11
+ const regexRules = v.rules.filter((r) => r instanceof RegExp);
12
+ if (regexRules.some((r) => r.test(path)))
13
+ return v.result;
14
+ const stringRules = v.rules.filter((r) => typeof r === "string");
15
+ if (stringRules.length > 0) {
16
+ const routes = {};
17
+ for (const r of stringRules) {
18
+ if (r === path)
19
+ return v.result;
20
+ routes[r] = true;
21
+ }
22
+ const routeRulesMatcher = toRouteMatcher(createRouter({ routes, strictTrailingSlash: false }));
23
+ if (routeRulesMatcher.matchAll(path).length > 0)
24
+ return Boolean(v.result);
25
+ }
26
+ }
27
+ return include.length === 0;
28
+ };
29
+ }
30
+ export function filterSitemapUrls(_urls, options) {
31
+ const urlFilter = createFilter({
32
+ include: options.include,
33
+ exclude: options.exclude
34
+ });
35
+ return _urls.filter((e) => {
36
+ let path = e.loc;
37
+ try {
38
+ path = parseURL(e.loc).pathname;
39
+ } catch {
40
+ return false;
41
+ }
42
+ if (!urlFilter(path))
43
+ return false;
44
+ if (options.isMultiSitemap && e._sitemap && options.sitemapName)
45
+ return e._sitemap === options.sitemapName;
46
+ if (!getPathRobotConfig(e, { path, skipSiteIndexable: true }).indexable)
47
+ return false;
48
+ return true;
49
+ });
50
+ }
@@ -0,0 +1,8 @@
1
+ import type { ModuleRuntimeConfig, ResolvedSitemapUrl, SitemapSourceResolved } from '../../../types';
2
+ export declare function normaliseI18nSources(sources: SitemapSourceResolved[], { autoI18n, isI18nMapped }: {
3
+ autoI18n: ModuleRuntimeConfig['autoI18n'];
4
+ isI18nMapped: boolean;
5
+ }): SitemapSourceResolved[];
6
+ export declare function applyI18nEnhancements(_urls: ResolvedSitemapUrl[], options: Pick<Required<ModuleRuntimeConfig>, 'autoI18n' | 'isI18nMapped'> & {
7
+ sitemapName: string;
8
+ }): ResolvedSitemapUrl[];
@@ -0,0 +1,128 @@
1
+ import { joinURL, parseURL, withHttps, withLeadingSlash } from "ufo";
2
+ import { splitForLocales } from "../../../utils-pure.mjs";
3
+ export function normaliseI18nSources(sources, { autoI18n, isI18nMapped }) {
4
+ if (autoI18n && isI18nMapped) {
5
+ return sources.map((s) => {
6
+ const urls = (s.urls || []).map((_url) => {
7
+ const url = typeof _url === "string" ? { loc: _url } : _url;
8
+ url.loc = url.loc || url.url;
9
+ url.loc = withLeadingSlash(url.loc);
10
+ return url;
11
+ });
12
+ s.urls = urls.map((url) => {
13
+ if (url._sitemap || url._i18nTransform)
14
+ return url;
15
+ if (url.loc) {
16
+ const match = splitForLocales(url.loc, autoI18n.locales.map((l) => l.code));
17
+ const localeCode = match[0] || autoI18n.defaultLocale;
18
+ const pathWithoutPrefix = match[1];
19
+ const locale = autoI18n.locales.find((e) => e.code === localeCode);
20
+ if (locale) {
21
+ if (!url.alternatives) {
22
+ const alternatives = urls.map((u) => {
23
+ if (u._sitemap || u._i18nTransform)
24
+ return false;
25
+ if (u?.loc) {
26
+ const [_localeCode, _pathWithoutPrefix] = splitForLocales(u.loc, autoI18n.locales.map((l) => l.code));
27
+ if (pathWithoutPrefix === _pathWithoutPrefix) {
28
+ const entries = [];
29
+ if (_localeCode === autoI18n.defaultLocale) {
30
+ entries.push({
31
+ href: u.loc,
32
+ hreflang: "x-default"
33
+ });
34
+ }
35
+ entries.push({
36
+ href: u.loc,
37
+ hreflang: _localeCode || autoI18n.defaultLocale
38
+ });
39
+ return entries;
40
+ }
41
+ }
42
+ return false;
43
+ }).flat().filter(Boolean);
44
+ if (alternatives.length)
45
+ url.alternatives = alternatives;
46
+ }
47
+ return {
48
+ _sitemap: locale.iso || locale.code,
49
+ ...url
50
+ };
51
+ }
52
+ }
53
+ return url;
54
+ });
55
+ return s;
56
+ });
57
+ }
58
+ return sources;
59
+ }
60
+ export function applyI18nEnhancements(_urls, options) {
61
+ const { autoI18n } = options;
62
+ return _urls.map((e) => {
63
+ if (!e._i18nTransform)
64
+ return e;
65
+ delete e._i18nTransform;
66
+ const path = withLeadingSlash(parseURL(e.loc).pathname);
67
+ const match = splitForLocales(path, autoI18n.locales.map((l) => l.code));
68
+ let pathWithoutLocale = path;
69
+ let locale;
70
+ if (match[0]) {
71
+ pathWithoutLocale = match[1] || "/";
72
+ locale = match[0];
73
+ }
74
+ if (locale && import.meta.dev) {
75
+ console.warn("You're providing a locale in the url, but the url is marked as inheritI18n. This will cause issues with the sitemap. Please remove the locale from the url.");
76
+ return e;
77
+ }
78
+ if (autoI18n.differentDomains) {
79
+ return {
80
+ // will force it to pass filter
81
+ _sitemap: options.sitemapName,
82
+ ...e,
83
+ alternatives: [
84
+ {
85
+ // apply default locale domain
86
+ ...autoI18n.locales.find((l) => [l.code, l.iso].includes(autoI18n.defaultLocale)),
87
+ code: "x-default"
88
+ },
89
+ ...autoI18n.locales.filter((l) => !!l.domain)
90
+ ].map((locale2) => {
91
+ return {
92
+ hreflang: locale2.iso || locale2.code,
93
+ href: joinURL(withHttps(locale2.domain), pathWithoutLocale)
94
+ };
95
+ })
96
+ };
97
+ }
98
+ return autoI18n.locales.map((l) => {
99
+ let loc = joinURL(`/${l.code}`, pathWithoutLocale);
100
+ if (autoI18n.differentDomains || ["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy) && l.code === autoI18n.defaultLocale)
101
+ loc = pathWithoutLocale;
102
+ return {
103
+ _sitemap: options.isI18nMapped ? l.iso || l.code : void 0,
104
+ ...e,
105
+ loc,
106
+ alternatives: [{ code: "x-default" }, ...autoI18n.locales].map((locale2) => {
107
+ const code = locale2.code === "x-default" ? autoI18n.defaultLocale : locale2.code;
108
+ const isDefault = locale2.code === "x-default" || locale2.code === autoI18n.defaultLocale;
109
+ let href = "";
110
+ if (autoI18n.strategy === "prefix") {
111
+ href = joinURL("/", code, pathWithoutLocale);
112
+ } else if (["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy)) {
113
+ if (isDefault) {
114
+ href = pathWithoutLocale;
115
+ } else {
116
+ href = joinURL("/", code, pathWithoutLocale);
117
+ }
118
+ }
119
+ const hreflang = locale2.iso || locale2.code;
120
+ return {
121
+ hreflang,
122
+ href
123
+ };
124
+ })
125
+ };
126
+ });
127
+ }).flat();
128
+ }
@@ -0,0 +1,3 @@
1
+ import type { NitroUrlResolvers, ResolvedSitemapUrl, SitemapUrlInput } from '../../../types';
2
+ export declare function normaliseSitemapUrls(data: SitemapUrlInput[], resolvers: NitroUrlResolvers): ResolvedSitemapUrl[];
3
+ export declare function normaliseDate(date: string | Date): string;
@@ -0,0 +1,77 @@
1
+ import { hasProtocol } from "ufo";
2
+ import { fixSlashes } from "site-config-stack/urls";
3
+ import { mergeOnKey } from "../../../utils-pure.mjs";
4
+ function resolve(s, resolvers) {
5
+ if (typeof s === "undefined")
6
+ return s;
7
+ s = typeof s === "string" ? s : s.toString();
8
+ if (hasProtocol(s, { acceptRelative: true, strict: false }))
9
+ return resolvers.fixSlashes(s);
10
+ return resolvers.canonicalUrlResolver(s);
11
+ }
12
+ export function normaliseSitemapUrls(data, resolvers) {
13
+ const entries = data.map((e) => typeof e === "string" ? { loc: e } : e).map((e) => {
14
+ e = { ...e };
15
+ if (e.url) {
16
+ e.loc = e.url;
17
+ delete e.url;
18
+ }
19
+ e.loc = fixSlashes(false, e.loc);
20
+ return e;
21
+ }).filter(Boolean);
22
+ function normaliseEntry(e) {
23
+ if (e.lastmod) {
24
+ const date = normaliseDate(e.lastmod);
25
+ if (date)
26
+ e.lastmod = date;
27
+ else
28
+ delete e.lastmod;
29
+ }
30
+ if (!e.lastmod)
31
+ delete e.lastmod;
32
+ e.loc = resolve(e.loc, resolvers);
33
+ if (e.alternatives) {
34
+ e.alternatives = mergeOnKey(e.alternatives.map((e2) => {
35
+ const a = { ...e2 };
36
+ if (typeof a.href === "string")
37
+ a.href = resolve(a.href, resolvers);
38
+ else if (typeof a.href === "object" && a.href)
39
+ a.href = resolve(a.href.href, resolvers);
40
+ return a;
41
+ }), "hreflang");
42
+ }
43
+ if (e.images) {
44
+ e.images = mergeOnKey(e.images.map((i) => {
45
+ i = { ...i };
46
+ i.loc = resolve(i.loc, resolvers);
47
+ return i;
48
+ }), "loc");
49
+ }
50
+ if (e.videos) {
51
+ e.videos = e.videos.map((v) => {
52
+ v = { ...v };
53
+ if (v.content_loc)
54
+ v.content_loc = resolve(v.content_loc, resolvers);
55
+ return v;
56
+ });
57
+ }
58
+ return e;
59
+ }
60
+ return mergeOnKey(
61
+ entries.map(normaliseEntry).map((e) => ({ ...e, _key: `${e._sitemap || ""}${e.loc}` })),
62
+ "_key"
63
+ );
64
+ }
65
+ export function normaliseDate(d) {
66
+ if (typeof d === "string") {
67
+ d = d.replace("Z", "");
68
+ d = d.replace(/\.\d+$/, "");
69
+ if (d.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/) || d.match(/^\d{4}-\d{2}-\d{2}$/))
70
+ return d;
71
+ d = new Date(d);
72
+ if (Number.isNaN(d.getTime()))
73
+ return false;
74
+ }
75
+ const z = (n) => `0${n}`.slice(-2);
76
+ return `${d.getUTCFullYear()}-${z(d.getUTCMonth() + 1)}-${z(d.getUTCDate())}T${z(d.getUTCHours())}:${z(d.getUTCMinutes())}:${z(d.getUTCSeconds())}+00:00`;
77
+ }
@@ -0,0 +1,2 @@
1
+ import type { ResolvedSitemapUrl, SitemapUrlInput } from '../../../types';
2
+ export declare function sortSitemapUrls<T extends SitemapUrlInput[] | ResolvedSitemapUrl[]>(urls: T): T;
@@ -0,0 +1,19 @@
1
+ export function sortSitemapUrls(urls) {
2
+ return urls.sort(
3
+ (a, b) => {
4
+ const aLoc = typeof a === "string" ? a : a.loc;
5
+ const bLoc = typeof b === "string" ? b : b.loc;
6
+ return aLoc.localeCompare(bLoc, void 0, { numeric: true });
7
+ }
8
+ ).sort((a, b) => {
9
+ const aLoc = (typeof a === "string" ? a : a.loc) || "";
10
+ const bLoc = (typeof b === "string" ? b : b.loc) || "";
11
+ const aSegments = aLoc.split("/").length;
12
+ const bSegments = bLoc.split("/").length;
13
+ if (aSegments > bSegments)
14
+ return 1;
15
+ if (aSegments < bSegments)
16
+ return -1;
17
+ return 0;
18
+ });
19
+ }
@@ -0,0 +1,5 @@
1
+ import type { ModuleRuntimeConfig, SitemapSourceBase, SitemapSourceResolved } from '../../../types';
2
+ export declare function fetchDataSource(input: SitemapSourceBase | SitemapSourceResolved): Promise<SitemapSourceResolved>;
3
+ export declare function globalSitemapSources(): Promise<(SitemapSourceBase | SitemapSourceResolved)[]>;
4
+ export declare function childSitemapSources(definition: ModuleRuntimeConfig['sitemaps'][string]): Promise<(SitemapSourceBase | SitemapSourceResolved)[]>;
5
+ export declare function resolveSitemapSources(sources: (SitemapSourceBase | SitemapSourceResolved)[]): Promise<SitemapSourceResolved[]>;
@@ -0,0 +1,82 @@
1
+ export async function fetchDataSource(input) {
2
+ const context = typeof input.context === "string" ? { name: input.context } : input.context || { name: "fetch" };
3
+ context.tips = context.tips || [];
4
+ const url = typeof input.fetch === "string" ? input.fetch : input.fetch[0];
5
+ const options = typeof input.fetch === "string" ? {} : input.fetch[1];
6
+ const start = Date.now();
7
+ const timeout = options.timeout || 5e3;
8
+ const timeoutController = new AbortController();
9
+ const abortRequestTimeout = setTimeout(() => timeoutController.abort(), timeout);
10
+ let isHtmlResponse = false;
11
+ try {
12
+ const urls = await globalThis.$fetch(url, {
13
+ responseType: "json",
14
+ signal: timeoutController.signal,
15
+ headers: {
16
+ Accept: "application/json"
17
+ },
18
+ // @ts-expect-error untyped
19
+ onResponse({ response }) {
20
+ if (typeof response._data === "string" && response._data.startsWith("<!DOCTYPE html>"))
21
+ isHtmlResponse = true;
22
+ }
23
+ });
24
+ const timeTakenMs = Date.now() - start;
25
+ if (isHtmlResponse) {
26
+ context.tips.push("This is usually because the URL isn't correct or is throwing an error. Please check the URL");
27
+ return {
28
+ ...input,
29
+ context,
30
+ urls: [],
31
+ timeTakenMs,
32
+ error: "Received HTML response instead of JSON"
33
+ };
34
+ }
35
+ return {
36
+ ...input,
37
+ context,
38
+ timeTakenMs,
39
+ urls
40
+ };
41
+ } catch (_err) {
42
+ const error = _err;
43
+ if (error.message.includes("This operation was aborted"))
44
+ context.tips.push("The request has taken too long. Make sure app sources respond within 5 seconds or adjust the timeout fetch option.");
45
+ else
46
+ context.tips.push(`Response returned a status of ${error.response?.status || "unknown"}.`);
47
+ console.error("[@nuxtjs/sitemap] Failed to fetch source.", { url, error });
48
+ return {
49
+ ...input,
50
+ context,
51
+ urls: [],
52
+ error: error.message
53
+ };
54
+ } finally {
55
+ abortRequestTimeout && clearTimeout(abortRequestTimeout);
56
+ }
57
+ }
58
+ export function globalSitemapSources() {
59
+ return import("#sitemap/global-sources.mjs").then((m) => m.sources);
60
+ }
61
+ export function childSitemapSources(definition) {
62
+ return definition?._hasSourceChunk ? import("#sitemap/child-sources.mjs").then((m) => m.sources[definition.sitemapName] || []) : Promise.resolve([]);
63
+ }
64
+ export async function resolveSitemapSources(sources) {
65
+ return (await Promise.all(
66
+ sources.map((source) => {
67
+ if (typeof source === "object" && "urls" in source) {
68
+ return {
69
+ timeTakenMs: 0,
70
+ ...source,
71
+ urls: source.urls
72
+ };
73
+ }
74
+ if (source.fetch)
75
+ return fetchDataSource(source);
76
+ return {
77
+ ...source,
78
+ error: "Invalid source"
79
+ };
80
+ })
81
+ )).flat();
82
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json"
3
+ }
@@ -0,0 +1,4 @@
1
+ import type { H3Event } from 'h3';
2
+ import type { ModuleRuntimeConfig } from '../types';
3
+ export * from '../utils-pure';
4
+ export declare function useSimpleSitemapRuntimeConfig(e?: H3Event): ModuleRuntimeConfig;
@@ -0,0 +1,13 @@
1
+ import { normalizeRuntimeFilters } from "../utils-pure.mjs";
2
+ import { useRuntimeConfig } from "#imports";
3
+ export * from "../utils-pure.mjs";
4
+ export function useSimpleSitemapRuntimeConfig(e) {
5
+ const clone = JSON.parse(JSON.stringify(useRuntimeConfig(e).sitemap));
6
+ for (const k in clone.sitemaps) {
7
+ const sitemap = clone.sitemaps[k];
8
+ sitemap.include = normalizeRuntimeFilters(sitemap.include);
9
+ sitemap.exclude = normalizeRuntimeFilters(sitemap.exclude);
10
+ clone.sitemaps[k] = sitemap;
11
+ }
12
+ return Object.freeze(clone);
13
+ }