nuxt-simple-sitemap
Version:
Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.
88 lines (87 loc) • 3.4 kB
JavaScript
import { defu } from "defu";
import { appendHeader } from "h3";
import { normaliseDate, normaliseSitemapUrls } from "../urlset/normalise.mjs";
import { globalSitemapSources, resolveSitemapSources } from "../urlset/sources.mjs";
import { applyI18nEnhancements } from "../urlset/i18n.mjs";
import { filterSitemapUrls } from "../urlset/filter.mjs";
import { sortSitemapUrls } from "../urlset/sort.mjs";
import { useSimpleSitemapRuntimeConfig } from "../../utils.mjs";
import { escapeValueForXml, wrapSitemapXml } from "./xml.mjs";
export async function buildSitemapIndex(resolvers) {
const {
sitemaps,
// enhancing
autoLastmod,
// chunking
defaultSitemapsChunkSize,
autoI18n,
isI18nMapped,
sortEntries,
// xls
version,
xsl,
credits
} = useSimpleSitemapRuntimeConfig();
if (!sitemaps)
throw new Error("Attempting to build a sitemap index without required `sitemaps` configuration.");
function maybeSort(urls) {
return sortEntries ? sortSitemapUrls(urls) : urls;
}
const isChunking = typeof sitemaps.chunks !== "undefined";
const chunks = {};
if (isChunking) {
const sitemap = sitemaps.chunks;
const sources = await resolveSitemapSources(await globalSitemapSources());
const normalisedUrls = normaliseSitemapUrls(sources.map((e) => e.urls).flat(), resolvers);
let enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults));
if (autoI18n?.locales)
enhancedUrls = applyI18nEnhancements(enhancedUrls, { isI18nMapped, autoI18n, sitemapName: sitemap.sitemapName });
const filteredUrls = filterSitemapUrls(enhancedUrls, { ...sitemap, autoI18n, isMultiSitemap: true });
const sortedUrls = maybeSort(filteredUrls);
sortedUrls.forEach((url, i) => {
const chunkIndex = Math.floor(i / defaultSitemapsChunkSize);
chunks[chunkIndex] = chunks[chunkIndex] || { urls: [] };
chunks[chunkIndex].urls.push(url);
});
} else {
for (const sitemap in sitemaps) {
if (sitemap !== "index") {
chunks[sitemap] = chunks[sitemap] || { urls: [] };
}
}
}
if (import.meta.prerender) {
appendHeader(
resolvers.event,
"x-nitro-prerender",
Object.keys(chunks).map((name) => encodeURIComponent(`/${name}-sitemap.xml`)).join(", ")
);
}
const entries = [];
for (const name in chunks) {
const sitemap = chunks[name];
const entry = {
sitemap: resolvers.canonicalUrlResolver(`${name}-sitemap.xml`)
};
let lastmod = sitemap.urls.filter((a) => !!a?.lastmod).map((a) => typeof a.lastmod === "string" ? new Date(a.lastmod) : a.lastmod).sort((a, b) => (b?.getTime() || 0) - (a?.getTime() || 0))?.[0];
if (!lastmod && autoLastmod)
lastmod = /* @__PURE__ */ new Date();
if (lastmod)
entry.lastmod = normaliseDate(lastmod);
entries.push(entry);
}
if (sitemaps.index)
entries.push(...sitemaps.index.sitemaps);
const sitemapXml = entries.map((e) => [
" <sitemap>",
` <loc>${escapeValueForXml(e.sitemap)}</loc>`,
// lastmod is optional
e.lastmod ? ` <lastmod>${escapeValueForXml(e.lastmod)}</lastmod>` : false,
" </sitemap>"
].filter(Boolean).join("\n")).join("\n");
return wrapSitemapXml([
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
sitemapXml,
"</sitemapindex>"
], resolvers, { version, xsl, credits });
}