UNPKG

nuxt-simple-sitemap

Version:

Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.

108 lines (107 loc) 5.11 kB
import { defu } from "defu"; import { resolveSitePath } from "site-config-stack/urls"; import { parseURL, withHttps } from "ufo"; import { normaliseSitemapUrls } from "../urlset/normalise.mjs"; import { childSitemapSources, globalSitemapSources, resolveSitemapSources } from "../urlset/sources.mjs"; import { filterSitemapUrls } from "../urlset/filter.mjs"; import { applyI18nEnhancements, normaliseI18nSources } from "../urlset/i18n.mjs"; import { sortSitemapUrls } from "../urlset/sort.mjs"; import { splitForLocales, useSimpleSitemapRuntimeConfig } from "../../utils.mjs"; import { createNitroRouteRuleMatcher } from "../../nitro/kit.mjs"; import { handleEntry, wrapSitemapXml } from "./xml.mjs"; import { useNitroApp } from "#internal/nitro"; export async function buildSitemap(sitemap, resolvers) { const { sitemaps, // enhancing autoLastmod, autoI18n, isI18nMapped, isMultiSitemap, // sorting sortEntries, // chunking defaultSitemapsChunkSize, // xls version, xsl, credits } = useSimpleSitemapRuntimeConfig(); const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemap.sitemapName)); function maybeSort(urls2) { return sortEntries ? sortSitemapUrls(urls2) : urls2; } function maybeSlice(urls2) { if (isChunking && defaultSitemapsChunkSize) { const chunk = Number(sitemap.sitemapName); return urls2.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize); } return urls2; } if (autoI18n?.differentDomains) { const domain = autoI18n.locales.find((e) => [e.iso, e.code].includes(sitemap.sitemapName))?.domain; if (domain) { const _tester = resolvers.canonicalUrlResolver; resolvers.canonicalUrlResolver = (path) => resolveSitePath(path, { absolute: true, withBase: false, siteUrl: withHttps(domain), trailingSlash: !_tester("/test/").endsWith("/"), base: "/" }); } } const sources = sitemap.includeAppSources ? await globalSitemapSources() : []; sources.push(...await childSitemapSources(sitemap)); let resolvedSources = await resolveSitemapSources(sources); if (autoI18n) resolvedSources = normaliseI18nSources(resolvedSources, { autoI18n, isI18nMapped }); const normalisedUrls = normaliseSitemapUrls(resolvedSources.map((e) => e.urls).flat(), resolvers); const defaults = { ...sitemap.defaults || {} }; if (autoLastmod && defaults?.lastmod) defaults.lastmod = /* @__PURE__ */ new Date(); const routeRuleMatcher = createNitroRouteRuleMatcher(); let enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults)).map((e) => { const path = parseURL(e.loc).pathname; let routeRules = routeRuleMatcher(path); if (autoI18n?.locales && autoI18n?.strategy !== "no_prefix") { const match = splitForLocales(path, autoI18n.locales.map((l) => l.code)); const pathWithoutPrefix = match[1]; if (pathWithoutPrefix && pathWithoutPrefix !== path) routeRules = defu(routeRules, routeRuleMatcher(pathWithoutPrefix)); } if (routeRules.sitemap === false) return false; if (typeof routeRules.index !== "undefined" && !routeRules.index) return false; const hasRobotsDisabled = Object.entries(routeRules.headers || {}).some(([name, value]) => name.toLowerCase() === "x-robots-tag" && value.toLowerCase() === "noindex"); if (routeRules.redirect || hasRobotsDisabled) return false; return routeRules.sitemap ? defu(e, routeRules.sitemap) : e; }).filter(Boolean); if (autoI18n?.locales) enhancedUrls = applyI18nEnhancements(enhancedUrls, { isI18nMapped, autoI18n, sitemapName: sitemap.sitemapName }); const filteredUrls = filterSitemapUrls(enhancedUrls, { event: resolvers.event, isMultiSitemap, autoI18n, ...sitemap }); const sortedUrls = maybeSort(filteredUrls); const slicedUrls = maybeSlice(sortedUrls); const nitro = useNitroApp(); const ctx = { urls: slicedUrls, sitemapName: sitemap.sitemapName }; await nitro.hooks.callHook("sitemap:resolved", ctx); const urls = maybeSort(normaliseSitemapUrls(ctx.urls, resolvers)); const urlset = urls.map((e) => { const keys = Object.keys(e).filter((k) => !k.startsWith("_")); return [ " <url>", keys.map((k) => handleEntry(k, e)).filter(Boolean).join("\n"), " </url>" ].join("\n"); }); return wrapSitemapXml([ '<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">', urlset.join("\n"), "</urlset>" ], resolvers, { version, xsl, credits }); }