@nuxtjs/sitemap 8.2.3 → 8.3.1
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 +11 -8
- package/dist/devtools/lib/sitemap/state.ts +4 -1
- package/dist/devtools/pages/sitemap/index.vue +2 -2
- package/dist/module.json +2 -2
- package/dist/module.mjs +29 -45
- package/dist/runtime/server/plugins/compression.js +57 -13
- package/dist/runtime/server/plugins/stream-transport.d.ts +2 -0
- package/dist/runtime/server/plugins/stream-transport.js +16 -0
- package/dist/runtime/server/routes/__sitemap__/debug-production.d.ts +3 -3
- package/dist/runtime/server/routes/__sitemap__/debug-production.js +43 -27
- package/dist/runtime/server/routes/__sitemap__/debug.d.ts +1 -0
- package/dist/runtime/server/routes/__zero-runtime/sitemap/[sitemap].xml.d.ts +1 -1
- package/dist/runtime/server/routes/__zero-runtime/sitemap.xml.d.ts +1 -1
- package/dist/runtime/server/routes/__zero-runtime/sitemap_index.xml.d.ts +1 -1
- package/dist/runtime/server/routes/sitemap/[sitemap].xml.d.ts +1 -1
- package/dist/runtime/server/routes/sitemap.xml.d.ts +1 -1
- package/dist/runtime/server/routes/sitemap_index.xml.d.ts +1 -1
- package/dist/runtime/server/sitemap/builder/index-xml.d.ts +13 -0
- package/dist/runtime/server/sitemap/builder/index-xml.js +67 -0
- package/dist/runtime/server/sitemap/builder/sitemap-index.d.ts +1 -4
- package/dist/runtime/server/sitemap/builder/sitemap-index.js +15 -60
- package/dist/runtime/server/sitemap/builder/sitemap.d.ts +1 -1
- package/dist/runtime/server/sitemap/builder/sitemap.js +36 -25
- package/dist/runtime/server/sitemap/builder/xml.d.ts +9 -1
- package/dist/runtime/server/sitemap/builder/xml.js +37 -11
- package/dist/runtime/server/sitemap/event-handlers.d.ts +3 -3
- package/dist/runtime/server/sitemap/event-handlers.js +18 -23
- package/dist/runtime/server/sitemap/nitro.d.ts +4 -1
- package/dist/runtime/server/sitemap/nitro.js +116 -26
- package/dist/runtime/server/sitemap/stream.d.ts +30 -0
- package/dist/runtime/server/sitemap/stream.js +144 -0
- package/dist/runtime/server/sitemap/urlset/normalise.d.ts +6 -1
- package/dist/runtime/server/sitemap/urlset/normalise.js +26 -6
- package/dist/runtime/server/sitemap/urlset/sort.js +12 -3
- package/dist/runtime/server/sitemap/urlset/sources.js +50 -9
- package/dist/runtime/server/utils.d.ts +0 -1
- package/dist/runtime/server/utils.js +12 -12
- package/dist/runtime/types.d.ts +14 -3
- package/dist/runtime/utils-pure.d.ts +5 -4
- package/dist/runtime/utils-pure.js +43 -26
- package/dist/utils.d.mts +5 -29
- package/dist/utils.d.ts +5 -29
- package/dist/utils.mjs +3 -418
- package/package.json +28 -30
- package/dist/runtime/server/kit.d.ts +0 -2
- package/dist/runtime/server/kit.js +0 -23
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { getHeader } from "h3";
|
|
2
2
|
import { defineCachedFunction } from "nitropack/runtime";
|
|
3
|
-
import { joinURL
|
|
3
|
+
import { joinURL } from "ufo";
|
|
4
4
|
import staticConfig from "#sitemap-virtual/static-config.mjs";
|
|
5
5
|
import { normaliseDate } from "../urlset/normalise.js";
|
|
6
6
|
import { getResolvedSitemapUrls } from "./sitemap.js";
|
|
7
|
-
import { escapeValueForXml } from "./xml.js";
|
|
8
7
|
const SERVER_CACHE_MAX_AGE = staticConfig.cacheMaxAgeSeconds || 60 * 10;
|
|
9
8
|
const buildSitemapIndexCached = defineCachedFunction(
|
|
10
9
|
async (event, resolvers, runtimeConfig, nitro) => {
|
|
@@ -49,22 +48,7 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
|
|
|
49
48
|
}
|
|
50
49
|
const indexLastmod = autoLastmod ? normaliseDate(/* @__PURE__ */ new Date()) : void 0;
|
|
51
50
|
const entries = [];
|
|
52
|
-
|
|
53
|
-
const sitemap = sitemaps.chunks;
|
|
54
|
-
const resolved = await getResolvedSitemapUrls(sitemap, "sitemap", true, resolvers, runtimeConfig, nitro);
|
|
55
|
-
allFailedSources.push(...resolved.failedSources);
|
|
56
|
-
const chunkCount = Math.ceil(resolved.urls.length / defaultSitemapsChunkSize);
|
|
57
|
-
for (let i = 0; i < chunkCount; i++) {
|
|
58
|
-
const entry = {
|
|
59
|
-
_sitemapName: String(i),
|
|
60
|
-
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${i}.xml`))
|
|
61
|
-
};
|
|
62
|
-
if (indexLastmod)
|
|
63
|
-
entry.lastmod = indexLastmod;
|
|
64
|
-
entries.push(entry);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
for (const name of nonChunkedNames) {
|
|
51
|
+
const pushEntry = (name) => {
|
|
68
52
|
const entry = {
|
|
69
53
|
_sitemapName: name,
|
|
70
54
|
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${name}.xml`))
|
|
@@ -72,7 +56,17 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
|
|
|
72
56
|
if (indexLastmod)
|
|
73
57
|
entry.lastmod = indexLastmod;
|
|
74
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));
|
|
75
67
|
}
|
|
68
|
+
for (const name of nonChunkedNames)
|
|
69
|
+
pushEntry(name);
|
|
76
70
|
for (const sitemapName in sitemaps) {
|
|
77
71
|
const sitemapConfig = sitemaps[sitemapName];
|
|
78
72
|
if (sitemapName !== "index" && sitemapConfig._isChunking) {
|
|
@@ -86,16 +80,8 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
|
|
|
86
80
|
chunkCount = Math.ceil(resolved.urls.length / chunkSize);
|
|
87
81
|
}
|
|
88
82
|
sitemapConfig._chunkCount = chunkCount;
|
|
89
|
-
for (let i = 0; i < chunkCount; i++)
|
|
90
|
-
|
|
91
|
-
const entry = {
|
|
92
|
-
_sitemapName: chunkName,
|
|
93
|
-
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${chunkName}.xml`))
|
|
94
|
-
};
|
|
95
|
-
if (indexLastmod)
|
|
96
|
-
entry.lastmod = indexLastmod;
|
|
97
|
-
entries.push(entry);
|
|
98
|
-
}
|
|
83
|
+
for (let i = 0; i < chunkCount; i++)
|
|
84
|
+
pushEntry(`${sitemapName}-${i}`);
|
|
99
85
|
}
|
|
100
86
|
}
|
|
101
87
|
if (sitemaps.index) {
|
|
@@ -105,41 +91,10 @@ async function buildSitemapIndexInternal(resolvers, runtimeConfig, nitro) {
|
|
|
105
91
|
}
|
|
106
92
|
return { entries, failedSources: allFailedSources };
|
|
107
93
|
}
|
|
108
|
-
export function urlsToIndexXml(sitemaps, resolvers, { version, xsl, credits, minify }, errorInfo) {
|
|
109
|
-
const sitemapXml = sitemaps.map((e) => [
|
|
110
|
-
" <sitemap>",
|
|
111
|
-
` <loc>${escapeValueForXml(e.sitemap)}</loc>`,
|
|
112
|
-
// lastmod is optional
|
|
113
|
-
e.lastmod ? ` <lastmod>${escapeValueForXml(e.lastmod)}</lastmod>` : false,
|
|
114
|
-
" </sitemap>"
|
|
115
|
-
].filter(Boolean).join("\n")).join("\n");
|
|
116
|
-
const xmlParts = [
|
|
117
|
-
'<?xml version="1.0" encoding="UTF-8"?>'
|
|
118
|
-
];
|
|
119
|
-
if (xsl) {
|
|
120
|
-
let relativeBaseUrl = resolvers.relativeBaseUrlResolver?.(xsl) ?? xsl;
|
|
121
|
-
if (errorInfo && errorInfo.messages.length > 0) {
|
|
122
|
-
relativeBaseUrl = withQuery(relativeBaseUrl, {
|
|
123
|
-
errors: "true",
|
|
124
|
-
error_messages: errorInfo.messages,
|
|
125
|
-
error_urls: errorInfo.urls
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
xmlParts.push(`<?xml-stylesheet type="text/xsl" href="${escapeValueForXml(relativeBaseUrl)}"?>`);
|
|
129
|
-
}
|
|
130
|
-
xmlParts.push(
|
|
131
|
-
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
132
|
-
sitemapXml,
|
|
133
|
-
"</sitemapindex>"
|
|
134
|
-
);
|
|
135
|
-
if (credits) {
|
|
136
|
-
xmlParts.push(`<!-- XML Sitemap Index generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
|
|
137
|
-
}
|
|
138
|
-
return minify ? xmlParts.join("").replace(/(?<!<[^>]*)\s(?![^<]*>)/g, "") : xmlParts.join("\n");
|
|
139
|
-
}
|
|
140
94
|
export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
|
|
141
95
|
if (!import.meta.dev && !import.meta.prerender && typeof runtimeConfig.cacheMaxAgeSeconds === "number" && runtimeConfig.cacheMaxAgeSeconds > 0 && resolvers.event) {
|
|
142
96
|
return buildSitemapIndexCached(resolvers.event, resolvers, runtimeConfig, nitro);
|
|
143
97
|
}
|
|
144
98
|
return buildSitemapIndexInternal(resolvers, runtimeConfig, nitro);
|
|
145
99
|
}
|
|
100
|
+
export { urlsToIndexXml, urlsToIndexXmlStream } from "./index-xml.js";
|
|
@@ -18,4 +18,4 @@ export declare function buildResolvedSitemapUrls(effectiveSitemap: SitemapDefini
|
|
|
18
18
|
export declare const buildResolvedSitemapUrlsCached: (_event: H3Event<import("h3").EventHandlerRequest>, effectiveSitemap: SitemapDefinition, matchName: string, isChunked: boolean, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp | undefined) => Promise<ResolvedSitemapUrlsResult>;
|
|
19
19
|
export declare function getResolvedSitemapUrls(effectiveSitemap: SitemapDefinition, matchName: string, isChunked: boolean, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<ResolvedSitemapUrlsResult>;
|
|
20
20
|
export declare function buildSitemapUrls(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<ResolvedSitemapUrlsResult>;
|
|
21
|
-
export { urlsToXml } from './xml.js';
|
|
21
|
+
export { urlsToXml, urlsToXmlStream } from './xml.js';
|
|
@@ -14,30 +14,33 @@ export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, b
|
|
|
14
14
|
autoI18n,
|
|
15
15
|
isI18nMapped
|
|
16
16
|
} = runtimeConfig;
|
|
17
|
-
const
|
|
17
|
+
const hasFilters = !!sitemap.include?.length || !!sitemap.exclude?.length;
|
|
18
|
+
const filterPath = hasFilters ? createPathFilter({
|
|
18
19
|
include: sitemap.include,
|
|
19
20
|
exclude: sitemap.exclude
|
|
20
|
-
}, baseURL || "/");
|
|
21
|
-
const _urls =
|
|
21
|
+
}, baseURL || "/") : void 0;
|
|
22
|
+
const _urls = [];
|
|
23
|
+
for (const _e of urls) {
|
|
22
24
|
const e = preNormalizeEntry(_e, resolvers);
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}).filter(Boolean);
|
|
27
|
-
let validI18nUrlsForTransform = [];
|
|
25
|
+
if (e.loc && (!filterPath || filterPath(e.loc, e._path?.pathname)))
|
|
26
|
+
_urls.push(e);
|
|
27
|
+
}
|
|
28
28
|
const withoutPrefixPaths = {};
|
|
29
29
|
if (autoI18n && autoI18n.strategy !== "no_prefix") {
|
|
30
|
-
const localeCodes = autoI18n.locales.map((l) => l.code);
|
|
30
|
+
const localeCodes = new Set(autoI18n.locales.map((l) => l.code));
|
|
31
31
|
const localeByCode = new Map(autoI18n.locales.map((l) => [l.code, l]));
|
|
32
32
|
const isPrefixStrategy = autoI18n.strategy === "prefix";
|
|
33
33
|
const isPrefixExceptOrAndDefault = autoI18n.strategy === "prefix_and_default" || autoI18n.strategy === "prefix_except_default";
|
|
34
34
|
const xDefaultAndLocales = [{ code: "x-default", _hreflang: "x-default" }, ...autoI18n.locales];
|
|
35
35
|
const defaultLocale = autoI18n.defaultLocale;
|
|
36
36
|
const hasPages = !!autoI18n.pages;
|
|
37
|
+
const sortedPageKeys = hasPages ? Object.keys(autoI18n.pages).sort((a, b) => b.length - a.length) : void 0;
|
|
37
38
|
const hasDifferentDomains = !!autoI18n.differentDomains;
|
|
38
|
-
validI18nUrlsForTransform =
|
|
39
|
+
const validI18nUrlsForTransform = [];
|
|
40
|
+
for (let i = 0; i < _urls.length; i++) {
|
|
41
|
+
const _e = _urls[i];
|
|
39
42
|
if (_e._abs)
|
|
40
|
-
|
|
43
|
+
continue;
|
|
41
44
|
const split = splitForLocales(_e._relativeLoc, localeCodes);
|
|
42
45
|
let localeCode = split[0];
|
|
43
46
|
const pathWithoutPrefix = split[1];
|
|
@@ -47,31 +50,30 @@ export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, b
|
|
|
47
50
|
e._pathWithoutPrefix = pathWithoutPrefix;
|
|
48
51
|
const locale = localeByCode.get(localeCode);
|
|
49
52
|
if (!locale)
|
|
50
|
-
|
|
53
|
+
continue;
|
|
51
54
|
e._locale = locale;
|
|
52
55
|
e._index = i;
|
|
53
56
|
e._key = `${e._sitemap || ""}${e._path?.pathname || "/"}${e._path?.search || ""}`;
|
|
54
57
|
withoutPrefixPaths[pathWithoutPrefix] = withoutPrefixPaths[pathWithoutPrefix] || [];
|
|
55
58
|
if (!withoutPrefixPaths[pathWithoutPrefix].some((e2) => e2._locale.code === locale.code))
|
|
56
59
|
withoutPrefixPaths[pathWithoutPrefix].push(e);
|
|
57
|
-
|
|
58
|
-
}
|
|
60
|
+
validI18nUrlsForTransform.push(e);
|
|
61
|
+
}
|
|
59
62
|
for (const e of validI18nUrlsForTransform) {
|
|
60
63
|
if (!e._i18nTransform && !e.alternatives?.length) {
|
|
61
|
-
const alternatives =
|
|
62
|
-
|
|
64
|
+
const alternatives = [];
|
|
65
|
+
for (const u of withoutPrefixPaths[e._pathWithoutPrefix] || []) {
|
|
63
66
|
if (u._locale.code === defaultLocale) {
|
|
64
|
-
|
|
67
|
+
alternatives.push({
|
|
65
68
|
href: u.loc,
|
|
66
69
|
hreflang: "x-default"
|
|
67
70
|
});
|
|
68
71
|
}
|
|
69
|
-
|
|
72
|
+
alternatives.push({
|
|
70
73
|
href: u.loc,
|
|
71
74
|
hreflang: u._locale._hreflang || defaultLocale
|
|
72
75
|
});
|
|
73
|
-
|
|
74
|
-
}).flat().filter(Boolean);
|
|
76
|
+
}
|
|
75
77
|
if (alternatives.length)
|
|
76
78
|
e.alternatives = alternatives;
|
|
77
79
|
} else if (e._i18nTransform) {
|
|
@@ -91,7 +93,7 @@ export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, b
|
|
|
91
93
|
};
|
|
92
94
|
});
|
|
93
95
|
} else {
|
|
94
|
-
const pageMatch = hasPages ? findPageMapping(e._pathWithoutPrefix, autoI18n.pages) : null;
|
|
96
|
+
const pageMatch = hasPages ? findPageMapping(e._pathWithoutPrefix, autoI18n.pages, sortedPageKeys) : null;
|
|
95
97
|
const pathSearch = e._path?.search || "";
|
|
96
98
|
const pathWithoutPrefix = e._pathWithoutPrefix;
|
|
97
99
|
for (const l of autoI18n.locales) {
|
|
@@ -130,7 +132,7 @@ export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers, b
|
|
|
130
132
|
} else if (isPrefixExceptOrAndDefault && !isDefault) {
|
|
131
133
|
href = joinURL("/", code, pathWithoutPrefix);
|
|
132
134
|
}
|
|
133
|
-
if (!filterPath(href))
|
|
135
|
+
if (filterPath && !filterPath(href))
|
|
134
136
|
continue;
|
|
135
137
|
alternatives.push({
|
|
136
138
|
hreflang: locale._hreflang,
|
|
@@ -192,9 +194,17 @@ export async function buildResolvedSitemapUrls(effectiveSitemap, matchName, isCh
|
|
|
192
194
|
const localeSitemapKeys = isI18nMapped && autoI18n ? autoI18n.locales.map((l) => l._sitemap) : [];
|
|
193
195
|
if (isMultiSitemap) {
|
|
194
196
|
const sitemapNames = Object.keys(sitemaps).filter((k) => k !== "index");
|
|
197
|
+
const validSitemapNames = new Set(sitemapNames);
|
|
198
|
+
if (isI18nMapped) {
|
|
199
|
+
for (const name of sitemapNames) {
|
|
200
|
+
const localeKey = resolveI18nSitemapLocaleKey(name, localeSitemapKeys);
|
|
201
|
+
if (localeKey)
|
|
202
|
+
validSitemapNames.add(localeKey);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
195
205
|
const warnedSitemaps = nitro?._sitemapWarnedSitemaps || /* @__PURE__ */ new Set();
|
|
196
206
|
for (const e of enhancedUrls) {
|
|
197
|
-
const hasMatchingSitemap = typeof e._sitemap === "string" &&
|
|
207
|
+
const hasMatchingSitemap = typeof e._sitemap === "string" && validSitemapNames.has(e._sitemap);
|
|
198
208
|
if (typeof e._sitemap === "string" && !hasMatchingSitemap) {
|
|
199
209
|
if (!warnedSitemaps.has(e._sitemap)) {
|
|
200
210
|
warnedSitemaps.add(e._sitemap);
|
|
@@ -206,6 +216,7 @@ export async function buildResolvedSitemapUrls(effectiveSitemap, matchName, isCh
|
|
|
206
216
|
nitro._sitemapWarnedSitemaps = warnedSitemaps;
|
|
207
217
|
}
|
|
208
218
|
}
|
|
219
|
+
const matchedLocaleSitemap = isI18nMapped ? resolveI18nSitemapLocaleKey(matchName, localeSitemapKeys) : null;
|
|
209
220
|
const filteredUrls = enhancedUrls.filter((e) => {
|
|
210
221
|
if (e._sitemap === false)
|
|
211
222
|
return false;
|
|
@@ -215,7 +226,7 @@ export async function buildResolvedSitemapUrls(effectiveSitemap, matchName, isCh
|
|
|
215
226
|
if (e._sitemap === matchName)
|
|
216
227
|
return true;
|
|
217
228
|
if (isI18nMapped)
|
|
218
|
-
return e._sitemap ===
|
|
229
|
+
return e._sitemap === matchedLocaleSitemap;
|
|
219
230
|
return false;
|
|
220
231
|
}
|
|
221
232
|
return true;
|
|
@@ -273,4 +284,4 @@ export async function buildSitemapUrls(sitemap, resolvers, runtimeConfig, nitro)
|
|
|
273
284
|
const urls = sliceUrlsForChunk(resolved.urls, sitemap.sitemapName, sitemaps, chunkSize);
|
|
274
285
|
return { urls, failedSources: resolved.failedSources };
|
|
275
286
|
}
|
|
276
|
-
export { urlsToXml } from "./xml.js";
|
|
287
|
+
export { urlsToXml, urlsToXmlStream } from "./xml.js";
|
|
@@ -1,6 +1,14 @@
|
|
|
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
|
|
3
|
+
export declare function renderSitemapXmlChunks(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, config: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
|
|
4
|
+
messages: string[];
|
|
5
|
+
urls: string[];
|
|
6
|
+
}): Generator<string>;
|
|
7
|
+
export declare function urlsToXml(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, config: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
|
|
4
8
|
messages: string[];
|
|
5
9
|
urls: string[];
|
|
6
10
|
}): string;
|
|
11
|
+
export declare function urlsToXmlStream(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, config: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>, errorInfo?: {
|
|
12
|
+
messages: string[];
|
|
13
|
+
urls: string[];
|
|
14
|
+
}): ReadableStream<Uint8Array>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { withQuery } from "ufo";
|
|
2
|
-
import { xmlEscape } from "
|
|
2
|
+
import { xmlEscape } from "../../../utils-pure.js";
|
|
3
|
+
import { createChunkedXmlStream } from "../stream.js";
|
|
3
4
|
export function escapeValueForXml(value) {
|
|
4
5
|
if (value === true || value === false)
|
|
5
6
|
return value ? "yes" : "no";
|
|
@@ -24,7 +25,10 @@ function buildUrlXml(url, NL, I1, I2, I3, I4) {
|
|
|
24
25
|
if (url.alternatives) {
|
|
25
26
|
for (const alt of url.alternatives) {
|
|
26
27
|
let attrs = "";
|
|
27
|
-
for (const
|
|
28
|
+
for (const k in alt) {
|
|
29
|
+
if (Object.hasOwn(alt, k))
|
|
30
|
+
attrs += ` ${k}="${xmlEscape(String(alt[k]))}"`;
|
|
31
|
+
}
|
|
28
32
|
xml += `${I2}<xhtml:link rel="alternate"${attrs} />${NL}`;
|
|
29
33
|
}
|
|
30
34
|
}
|
|
@@ -112,7 +116,7 @@ function buildUrlXml(url, NL, I1, I2, I3, I4) {
|
|
|
112
116
|
xml += `${I1}</url>`;
|
|
113
117
|
return xml;
|
|
114
118
|
}
|
|
115
|
-
|
|
119
|
+
function resolveXmlRenderContext(resolvers, { xsl, minify }, errorInfo) {
|
|
116
120
|
let xslHref = xsl ? resolvers.relativeBaseUrlResolver(xsl) : false;
|
|
117
121
|
if (xslHref && errorInfo?.messages.length) {
|
|
118
122
|
xslHref = withQuery(xslHref, {
|
|
@@ -122,18 +126,40 @@ export function urlsToXml(urls, resolvers, { version, xsl, credits, minify }, er
|
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
const NL = minify ? "" : "\n";
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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);
|
|
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}`;
|
|
142
|
+
yield URLSET_OPENING_TAG + NL;
|
|
143
|
+
for (const url of urls) {
|
|
144
|
+
yield buildUrlXml(url, NL, I1, I2, I3, I4) + NL;
|
|
145
|
+
}
|
|
146
|
+
yield "</urlset>";
|
|
147
|
+
if (credits) {
|
|
148
|
+
yield `${NL}<!-- XML Sitemap generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
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);
|
|
129
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}`;
|
|
130
155
|
xml += URLSET_OPENING_TAG + NL;
|
|
131
|
-
for (const url of urls)
|
|
156
|
+
for (const url of urls)
|
|
132
157
|
xml += buildUrlXml(url, NL, I1, I2, I3, I4) + NL;
|
|
133
|
-
}
|
|
134
158
|
xml += "</urlset>";
|
|
135
|
-
if (credits)
|
|
159
|
+
if (credits)
|
|
136
160
|
xml += `${NL}<!-- XML Sitemap generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
|
|
137
|
-
}
|
|
138
161
|
return xml;
|
|
139
162
|
}
|
|
163
|
+
export function urlsToXmlStream(urls, resolvers, config, errorInfo) {
|
|
164
|
+
return createChunkedXmlStream(renderSitemapXmlChunks(urls, resolvers, config, errorInfo));
|
|
165
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
export declare function sitemapXmlEventHandler(e: H3Event): Promise<string | void
|
|
3
|
-
export declare function sitemapIndexXmlEventHandler(e: H3Event): Promise<string
|
|
4
|
-
export declare function sitemapChildXmlEventHandler(e: H3Event): Promise<string | undefined>;
|
|
2
|
+
export declare function sitemapXmlEventHandler(e: H3Event): Promise<string | void | ReadableStream<Uint8Array<ArrayBufferLike>>>;
|
|
3
|
+
export declare function sitemapIndexXmlEventHandler(e: H3Event): Promise<string | ReadableStream<Uint8Array<ArrayBufferLike>>>;
|
|
4
|
+
export declare function sitemapChildXmlEventHandler(e: H3Event): Promise<string | ReadableStream<Uint8Array<ArrayBufferLike>> | undefined>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { appendHeader, createError, getRouterParam, sendRedirect
|
|
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
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { urlsToIndexXml, urlsToIndexXmlStream } from "./builder/index-xml.js";
|
|
6
|
+
import { buildSitemapIndex } from "./builder/sitemap-index.js";
|
|
7
|
+
import { createSitemap, renderSitemapOutput, setSitemapResponseHeaders, useNitroUrlResolvers } from "./nitro.js";
|
|
7
8
|
import { getSitemapConfig, parseChunkInfo } from "./utils/chunk.js";
|
|
8
9
|
export async function sitemapXmlEventHandler(e) {
|
|
9
10
|
const runtimeConfig = useSitemapRuntimeConfig();
|
|
@@ -27,33 +28,27 @@ export async function sitemapIndexXmlEventHandler(e) {
|
|
|
27
28
|
const indexResolvedCtx = { sitemaps, event: e };
|
|
28
29
|
await nitro.hooks.callHook("sitemap:index-resolved", indexResolvedCtx);
|
|
29
30
|
const errorInfo = failedSources.length > 0 ? { messages: failedSources.map((f) => f.error), urls: failedSources.map((f) => f.url) } : void 0;
|
|
30
|
-
const output =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const remainingSeconds = Math.floor((expiryTime.getTime() - now.getTime()) / 1e3);
|
|
42
|
-
setHeader(e, "X-Sitemap-Cache-Remaining", `${remainingSeconds}s`);
|
|
43
|
-
} else {
|
|
44
|
-
setHeader(e, "Cache-Control", `no-cache, no-store`);
|
|
45
|
-
}
|
|
46
|
-
return ctx.sitemap;
|
|
31
|
+
const output = await renderSitemapOutput(
|
|
32
|
+
nitro,
|
|
33
|
+
e,
|
|
34
|
+
"sitemap",
|
|
35
|
+
() => urlsToIndexXml(indexResolvedCtx.sitemaps, resolvers, runtimeConfig, errorInfo),
|
|
36
|
+
() => urlsToIndexXmlStream(indexResolvedCtx.sitemaps, resolvers, runtimeConfig, errorInfo),
|
|
37
|
+
!!runtimeConfig.experimentalStreaming && !import.meta.prerender,
|
|
38
|
+
runtimeConfig.debug
|
|
39
|
+
);
|
|
40
|
+
setSitemapResponseHeaders(e, runtimeConfig);
|
|
41
|
+
return output;
|
|
47
42
|
}
|
|
48
43
|
export async function sitemapChildXmlEventHandler(e) {
|
|
49
|
-
|
|
44
|
+
const pathname = getRequestURL(e).pathname;
|
|
45
|
+
if (!pathname.endsWith(".xml"))
|
|
50
46
|
return;
|
|
51
47
|
const runtimeConfig = useSitemapRuntimeConfig(e);
|
|
52
48
|
const { sitemaps } = runtimeConfig;
|
|
53
49
|
let sitemapName = getRouterParam(e, "sitemap");
|
|
54
50
|
if (!sitemapName) {
|
|
55
|
-
const
|
|
56
|
-
const match = path.match(/(?:\/__sitemap__\/)?(.+)\.xml$/);
|
|
51
|
+
const match = pathname.match(/(?:\/__sitemap__\/)?(.+)\.xml$/);
|
|
57
52
|
if (match)
|
|
58
53
|
sitemapName = match[1];
|
|
59
54
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
+
import type { NitroApp } from 'nitropack/types';
|
|
2
3
|
import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapDefinition } from '../../types.js';
|
|
3
4
|
export declare function useNitroUrlResolvers(e: H3Event): NitroUrlResolvers;
|
|
4
|
-
export declare function
|
|
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;
|
|
7
|
+
export declare function createSitemap(event: H3Event, definition: SitemapDefinition, runtimeConfig: ModuleRuntimeConfig): Promise<string | ReadableStream<Uint8Array<ArrayBufferLike>>>;
|