website hosted
This commit is contained in:
10
node_modules/@astrojs/sitemap/dist/config-defaults.d.ts
generated
vendored
Normal file
10
node_modules/@astrojs/sitemap/dist/config-defaults.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export declare const SITEMAP_CONFIG_DEFAULTS: {
|
||||
filenameBase: string;
|
||||
entryLimit: number;
|
||||
namespaces: {
|
||||
news: true;
|
||||
xhtml: true;
|
||||
image: true;
|
||||
video: true;
|
||||
};
|
||||
};
|
||||
13
node_modules/@astrojs/sitemap/dist/config-defaults.js
generated
vendored
Normal file
13
node_modules/@astrojs/sitemap/dist/config-defaults.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
const SITEMAP_CONFIG_DEFAULTS = {
|
||||
filenameBase: "sitemap",
|
||||
entryLimit: 45e3,
|
||||
namespaces: {
|
||||
news: true,
|
||||
xhtml: true,
|
||||
image: true,
|
||||
video: true
|
||||
}
|
||||
};
|
||||
export {
|
||||
SITEMAP_CONFIG_DEFAULTS
|
||||
};
|
||||
3
node_modules/@astrojs/sitemap/dist/generate-sitemap.d.ts
generated
vendored
Normal file
3
node_modules/@astrojs/sitemap/dist/generate-sitemap.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { SitemapItem, SitemapOptions } from './index.js';
|
||||
/** Construct sitemap.xml given a set of URLs */
|
||||
export declare function generateSitemap(pages: string[], finalSiteUrl: string, opts?: SitemapOptions): SitemapItem[];
|
||||
52
node_modules/@astrojs/sitemap/dist/generate-sitemap.js
generated
vendored
Normal file
52
node_modules/@astrojs/sitemap/dist/generate-sitemap.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import { parseI18nUrl } from "./utils/parse-i18n-url.js";
|
||||
function generateSitemap(pages, finalSiteUrl, opts) {
|
||||
const { changefreq, priority, lastmod: lastmodSrc, i18n } = opts ?? {};
|
||||
const urls = [...pages];
|
||||
urls.sort((a, b) => a.localeCompare(b, "en", { numeric: true }));
|
||||
const lastmod = lastmodSrc?.toISOString();
|
||||
const { defaultLocale, locales } = i18n ?? {};
|
||||
let getI18nLinks;
|
||||
if (defaultLocale && locales) {
|
||||
getI18nLinks = createGetI18nLinks(urls, defaultLocale, locales, finalSiteUrl);
|
||||
}
|
||||
const urlData = urls.map((url, i) => ({
|
||||
url,
|
||||
links: getI18nLinks?.(i),
|
||||
lastmod,
|
||||
priority,
|
||||
changefreq
|
||||
}));
|
||||
return urlData;
|
||||
}
|
||||
function createGetI18nLinks(urls, defaultLocale, locales, finalSiteUrl) {
|
||||
const parsedI18nUrls = urls.map((url) => parseI18nUrl(url, defaultLocale, locales, finalSiteUrl));
|
||||
const i18nPathToLinksCache = /* @__PURE__ */ new Map();
|
||||
return (urlIndex) => {
|
||||
const i18nUrl = parsedI18nUrls[urlIndex];
|
||||
if (!i18nUrl) {
|
||||
return void 0;
|
||||
}
|
||||
const cached = i18nPathToLinksCache.get(i18nUrl.path);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const links = [];
|
||||
for (let i = 0; i < parsedI18nUrls.length; i++) {
|
||||
const parsed = parsedI18nUrls[i];
|
||||
if (parsed?.path === i18nUrl.path) {
|
||||
links.push({
|
||||
url: urls[i],
|
||||
lang: locales[parsed.locale]
|
||||
});
|
||||
}
|
||||
}
|
||||
if (links.length <= 1) {
|
||||
return void 0;
|
||||
}
|
||||
i18nPathToLinksCache.set(i18nUrl.path, links);
|
||||
return links;
|
||||
};
|
||||
}
|
||||
export {
|
||||
generateSitemap
|
||||
};
|
||||
30
node_modules/@astrojs/sitemap/dist/index.d.ts
generated
vendored
Normal file
30
node_modules/@astrojs/sitemap/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { AstroIntegration } from 'astro';
|
||||
import type { EnumChangefreq, LinkItem as LinkItemBase, SitemapItemLoose } from 'sitemap';
|
||||
export { EnumChangefreq as ChangeFreqEnum } from 'sitemap';
|
||||
export type ChangeFreq = `${EnumChangefreq}`;
|
||||
export type SitemapItem = Pick<SitemapItemLoose, 'url' | 'lastmod' | 'changefreq' | 'priority' | 'links'>;
|
||||
export type LinkItem = LinkItemBase;
|
||||
export type SitemapOptions = {
|
||||
filenameBase?: string;
|
||||
filter?(page: string): boolean;
|
||||
customSitemaps?: string[];
|
||||
customPages?: string[];
|
||||
i18n?: {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
};
|
||||
entryLimit?: number;
|
||||
changefreq?: ChangeFreq;
|
||||
lastmod?: Date;
|
||||
priority?: number;
|
||||
serialize?(item: SitemapItem): SitemapItem | Promise<SitemapItem | undefined> | undefined;
|
||||
xslURL?: string;
|
||||
namespaces?: {
|
||||
news?: boolean;
|
||||
xhtml?: boolean;
|
||||
image?: boolean;
|
||||
video?: boolean;
|
||||
};
|
||||
} | undefined;
|
||||
declare const createPlugin: (options?: SitemapOptions) => AstroIntegration;
|
||||
export default createPlugin;
|
||||
138
node_modules/@astrojs/sitemap/dist/index.js
generated
vendored
Normal file
138
node_modules/@astrojs/sitemap/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { ZodError } from "zod";
|
||||
import { generateSitemap } from "./generate-sitemap.js";
|
||||
import { validateOptions } from "./validate-options.js";
|
||||
import { writeSitemap } from "./write-sitemap.js";
|
||||
import { EnumChangefreq } from "sitemap";
|
||||
function formatConfigErrorMessage(err) {
|
||||
const errorList = err.issues.map((issue) => ` ${issue.path.join(".")} ${issue.message + "."}`);
|
||||
return errorList.join("\n");
|
||||
}
|
||||
const PKG_NAME = "@astrojs/sitemap";
|
||||
const STATUS_CODE_PAGES = /* @__PURE__ */ new Set(["404", "500"]);
|
||||
const isStatusCodePage = (locales) => {
|
||||
const statusPathNames = new Set(
|
||||
locales.flatMap((locale) => [...STATUS_CODE_PAGES].map((page) => `${locale}/${page}`)).concat([...STATUS_CODE_PAGES])
|
||||
);
|
||||
return (pathname) => {
|
||||
if (pathname.endsWith("/")) {
|
||||
pathname = pathname.slice(0, -1);
|
||||
}
|
||||
if (pathname.startsWith("/")) {
|
||||
pathname = pathname.slice(1);
|
||||
}
|
||||
return statusPathNames.has(pathname);
|
||||
};
|
||||
};
|
||||
const createPlugin = (options) => {
|
||||
let config;
|
||||
return {
|
||||
name: PKG_NAME,
|
||||
hooks: {
|
||||
"astro:config:done": async ({ config: cfg }) => {
|
||||
config = cfg;
|
||||
},
|
||||
"astro:build:done": async ({ dir, routes, pages, logger }) => {
|
||||
try {
|
||||
if (!config.site) {
|
||||
logger.warn(
|
||||
"The Sitemap integration requires the `site` astro.config option. Skipping."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const opts = validateOptions(config.site, options);
|
||||
const { filenameBase, filter, customPages, customSitemaps, serialize, entryLimit } = opts;
|
||||
const outFile = `${filenameBase}-index.xml`;
|
||||
const finalSiteUrl = new URL(config.base, config.site);
|
||||
const shouldIgnoreStatus = isStatusCodePage(Object.keys(opts.i18n?.locales ?? {}));
|
||||
let pageUrls = pages.filter((p) => !shouldIgnoreStatus(p.pathname)).map((p) => {
|
||||
if (p.pathname !== "" && !finalSiteUrl.pathname.endsWith("/"))
|
||||
finalSiteUrl.pathname += "/";
|
||||
if (p.pathname.startsWith("/")) p.pathname = p.pathname.slice(1);
|
||||
const fullPath = finalSiteUrl.pathname + p.pathname;
|
||||
return new URL(fullPath, finalSiteUrl).href;
|
||||
});
|
||||
const routeUrls = routes.reduce((urls, r) => {
|
||||
if (r.type !== "page") return urls;
|
||||
if (r.pathname) {
|
||||
if (shouldIgnoreStatus(r.pathname ?? r.route)) return urls;
|
||||
let fullPath = finalSiteUrl.pathname;
|
||||
if (fullPath.endsWith("/")) fullPath += r.generate(r.pathname).substring(1);
|
||||
else fullPath += r.generate(r.pathname);
|
||||
const newUrl = new URL(fullPath, finalSiteUrl).href;
|
||||
if (config.trailingSlash === "never") {
|
||||
urls.push(newUrl);
|
||||
} else if (config.build.format === "directory" && !newUrl.endsWith("/")) {
|
||||
urls.push(newUrl + "/");
|
||||
} else {
|
||||
urls.push(newUrl);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}, []);
|
||||
pageUrls = Array.from(/* @__PURE__ */ new Set([...pageUrls, ...routeUrls, ...customPages ?? []]));
|
||||
if (filter) {
|
||||
pageUrls = pageUrls.filter(filter);
|
||||
}
|
||||
if (pageUrls.length === 0) {
|
||||
logger.warn(`No pages found!
|
||||
\`${outFile}\` not created.`);
|
||||
return;
|
||||
}
|
||||
let urlData = generateSitemap(pageUrls, finalSiteUrl.href, opts);
|
||||
if (serialize) {
|
||||
try {
|
||||
const serializedUrls = [];
|
||||
for (const item of urlData) {
|
||||
const serialized = await Promise.resolve(serialize(item));
|
||||
if (serialized) {
|
||||
serializedUrls.push(serialized);
|
||||
}
|
||||
}
|
||||
if (serializedUrls.length === 0) {
|
||||
logger.warn("No pages found!");
|
||||
return;
|
||||
}
|
||||
urlData = serializedUrls;
|
||||
} catch (err) {
|
||||
logger.error(`Error serializing pages
|
||||
${err.toString()}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const destDir = fileURLToPath(dir);
|
||||
const lastmod = opts.lastmod?.toISOString();
|
||||
const xslURL = opts.xslURL ? new URL(opts.xslURL, finalSiteUrl).href : void 0;
|
||||
await writeSitemap(
|
||||
{
|
||||
filenameBase,
|
||||
hostname: finalSiteUrl.href,
|
||||
destinationDir: destDir,
|
||||
publicBasePath: config.base,
|
||||
sourceData: urlData,
|
||||
limit: entryLimit,
|
||||
customSitemaps,
|
||||
xslURL,
|
||||
lastmod,
|
||||
namespaces: opts.namespaces
|
||||
},
|
||||
config
|
||||
);
|
||||
logger.info(`\`${outFile}\` created at \`${path.relative(process.cwd(), destDir)}\``);
|
||||
} catch (err) {
|
||||
if (err instanceof ZodError) {
|
||||
logger.warn(formatConfigErrorMessage(err));
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
var index_default = createPlugin;
|
||||
export {
|
||||
EnumChangefreq as ChangeFreqEnum,
|
||||
index_default as default
|
||||
};
|
||||
91
node_modules/@astrojs/sitemap/dist/schema.d.ts
generated
vendored
Normal file
91
node_modules/@astrojs/sitemap/dist/schema.d.ts
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
import { EnumChangefreq as ChangeFreq } from 'sitemap';
|
||||
import { z } from 'zod';
|
||||
export declare const SitemapOptionsSchema: z.ZodDefault<z.ZodObject<{
|
||||
filenameBase: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
||||
filter: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodBoolean>>;
|
||||
customSitemaps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
||||
customPages: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
||||
canonicalURL: z.ZodOptional<z.ZodString>;
|
||||
xslURL: z.ZodOptional<z.ZodString>;
|
||||
i18n: z.ZodOptional<z.ZodEffects<z.ZodObject<{
|
||||
defaultLocale: z.ZodString;
|
||||
locales: z.ZodRecord<z.ZodString, z.ZodString>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
}, {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
}>, {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
}, {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
}>>;
|
||||
entryLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
||||
serialize: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodAny], z.ZodUnknown>, z.ZodAny>>;
|
||||
changefreq: z.ZodOptional<z.ZodNativeEnum<typeof ChangeFreq>>;
|
||||
lastmod: z.ZodOptional<z.ZodDate>;
|
||||
priority: z.ZodOptional<z.ZodNumber>;
|
||||
namespaces: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
||||
news: z.ZodOptional<z.ZodBoolean>;
|
||||
xhtml: z.ZodOptional<z.ZodBoolean>;
|
||||
image: z.ZodOptional<z.ZodBoolean>;
|
||||
video: z.ZodOptional<z.ZodBoolean>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
news?: boolean | undefined;
|
||||
xhtml?: boolean | undefined;
|
||||
image?: boolean | undefined;
|
||||
video?: boolean | undefined;
|
||||
}, {
|
||||
news?: boolean | undefined;
|
||||
xhtml?: boolean | undefined;
|
||||
image?: boolean | undefined;
|
||||
video?: boolean | undefined;
|
||||
}>>>;
|
||||
}, "strict", z.ZodTypeAny, {
|
||||
filenameBase: string;
|
||||
entryLimit: number;
|
||||
namespaces: {
|
||||
news?: boolean | undefined;
|
||||
xhtml?: boolean | undefined;
|
||||
image?: boolean | undefined;
|
||||
video?: boolean | undefined;
|
||||
};
|
||||
changefreq?: ChangeFreq | undefined;
|
||||
priority?: number | undefined;
|
||||
lastmod?: Date | undefined;
|
||||
i18n?: {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
} | undefined;
|
||||
filter?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
|
||||
customSitemaps?: string[] | undefined;
|
||||
customPages?: string[] | undefined;
|
||||
canonicalURL?: string | undefined;
|
||||
xslURL?: string | undefined;
|
||||
serialize?: ((args_0: any, ...args: unknown[]) => any) | undefined;
|
||||
}, {
|
||||
changefreq?: ChangeFreq | undefined;
|
||||
priority?: number | undefined;
|
||||
lastmod?: Date | undefined;
|
||||
i18n?: {
|
||||
defaultLocale: string;
|
||||
locales: Record<string, string>;
|
||||
} | undefined;
|
||||
filter?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
|
||||
filenameBase?: string | undefined;
|
||||
entryLimit?: number | undefined;
|
||||
customSitemaps?: string[] | undefined;
|
||||
customPages?: string[] | undefined;
|
||||
canonicalURL?: string | undefined;
|
||||
xslURL?: string | undefined;
|
||||
serialize?: ((args_0: any, ...args: unknown[]) => any) | undefined;
|
||||
namespaces?: {
|
||||
news?: boolean | undefined;
|
||||
xhtml?: boolean | undefined;
|
||||
image?: boolean | undefined;
|
||||
video?: boolean | undefined;
|
||||
} | undefined;
|
||||
}>>;
|
||||
37
node_modules/@astrojs/sitemap/dist/schema.js
generated
vendored
Normal file
37
node_modules/@astrojs/sitemap/dist/schema.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { EnumChangefreq as ChangeFreq } from "sitemap";
|
||||
import { z } from "zod";
|
||||
import { SITEMAP_CONFIG_DEFAULTS } from "./config-defaults.js";
|
||||
const localeKeySchema = z.string().min(1);
|
||||
const SitemapOptionsSchema = z.object({
|
||||
filenameBase: z.string().optional().default(SITEMAP_CONFIG_DEFAULTS.filenameBase),
|
||||
filter: z.function().args(z.string()).returns(z.boolean()).optional(),
|
||||
customSitemaps: z.string().url().array().optional(),
|
||||
customPages: z.string().url().array().optional(),
|
||||
canonicalURL: z.string().url().optional(),
|
||||
xslURL: z.string().optional(),
|
||||
i18n: z.object({
|
||||
defaultLocale: localeKeySchema,
|
||||
locales: z.record(
|
||||
localeKeySchema,
|
||||
z.string().min(2).regex(/^[a-zA-Z\-]+$/gm, {
|
||||
message: "Only English alphabet symbols and hyphen allowed"
|
||||
})
|
||||
)
|
||||
}).refine((val) => !val || val.locales[val.defaultLocale], {
|
||||
message: "`defaultLocale` must exist in `locales` keys"
|
||||
}).optional(),
|
||||
entryLimit: z.number().nonnegative().optional().default(SITEMAP_CONFIG_DEFAULTS.entryLimit),
|
||||
serialize: z.function().args(z.any()).returns(z.any()).optional(),
|
||||
changefreq: z.nativeEnum(ChangeFreq).optional(),
|
||||
lastmod: z.date().optional(),
|
||||
priority: z.number().min(0).max(1).optional(),
|
||||
namespaces: z.object({
|
||||
news: z.boolean().optional(),
|
||||
xhtml: z.boolean().optional(),
|
||||
image: z.boolean().optional(),
|
||||
video: z.boolean().optional()
|
||||
}).optional().default(SITEMAP_CONFIG_DEFAULTS.namespaces)
|
||||
}).strict().default(SITEMAP_CONFIG_DEFAULTS);
|
||||
export {
|
||||
SitemapOptionsSchema
|
||||
};
|
||||
6
node_modules/@astrojs/sitemap/dist/utils/parse-i18n-url.d.ts
generated
vendored
Normal file
6
node_modules/@astrojs/sitemap/dist/utils/parse-i18n-url.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
interface ParsedI18nUrl {
|
||||
locale: string;
|
||||
path: string;
|
||||
}
|
||||
export declare function parseI18nUrl(url: string, defaultLocale: string, locales: Record<string, string>, base: string): ParsedI18nUrl | undefined;
|
||||
export {};
|
||||
24
node_modules/@astrojs/sitemap/dist/utils/parse-i18n-url.js
generated
vendored
Normal file
24
node_modules/@astrojs/sitemap/dist/utils/parse-i18n-url.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
function parseI18nUrl(url, defaultLocale, locales, base) {
|
||||
if (!url.startsWith(base)) {
|
||||
return void 0;
|
||||
}
|
||||
let s = url.slice(base.length);
|
||||
if (!s || s === "/") {
|
||||
return { locale: defaultLocale, path: "/" };
|
||||
}
|
||||
if (s[0] !== "/") {
|
||||
s = "/" + s;
|
||||
}
|
||||
const locale = s.split("/")[1];
|
||||
if (locale in locales) {
|
||||
let path = s.slice(1 + locale.length);
|
||||
if (!path) {
|
||||
path = "/";
|
||||
}
|
||||
return { locale, path };
|
||||
}
|
||||
return { locale: defaultLocale, path: s };
|
||||
}
|
||||
export {
|
||||
parseI18nUrl
|
||||
};
|
||||
1
node_modules/@astrojs/sitemap/dist/validate-options.d.ts
generated
vendored
Normal file
1
node_modules/@astrojs/sitemap/dist/validate-options.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
20
node_modules/@astrojs/sitemap/dist/validate-options.js
generated
vendored
Normal file
20
node_modules/@astrojs/sitemap/dist/validate-options.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { z } from "zod";
|
||||
import { SitemapOptionsSchema } from "./schema.js";
|
||||
const validateOptions = (site, opts) => {
|
||||
const result = SitemapOptionsSchema.parse(opts);
|
||||
z.object({
|
||||
site: z.string().optional(),
|
||||
// Astro takes care of `site`: how to validate, transform and refine
|
||||
canonicalURL: z.string().optional()
|
||||
// `canonicalURL` is already validated in prev step
|
||||
}).refine((options) => options.site || options.canonicalURL, {
|
||||
message: "Required `site` astro.config option or `canonicalURL` integration option"
|
||||
}).parse({
|
||||
site,
|
||||
canonicalURL: result.canonicalURL
|
||||
});
|
||||
return result;
|
||||
};
|
||||
export {
|
||||
validateOptions
|
||||
};
|
||||
22
node_modules/@astrojs/sitemap/dist/write-sitemap.d.ts
generated
vendored
Normal file
22
node_modules/@astrojs/sitemap/dist/write-sitemap.d.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { AstroConfig } from 'astro';
|
||||
import type { SitemapItem } from './index.js';
|
||||
type WriteSitemapConfig = {
|
||||
filenameBase: string;
|
||||
hostname: string;
|
||||
sitemapHostname?: string;
|
||||
customSitemaps?: string[];
|
||||
sourceData: SitemapItem[];
|
||||
destinationDir: string;
|
||||
publicBasePath?: string;
|
||||
limit?: number;
|
||||
xslURL?: string;
|
||||
lastmod?: string;
|
||||
namespaces?: {
|
||||
news?: boolean;
|
||||
xhtml?: boolean;
|
||||
image?: boolean;
|
||||
video?: boolean;
|
||||
};
|
||||
};
|
||||
export declare function writeSitemap({ filenameBase, hostname, sitemapHostname, sourceData, destinationDir, limit, customSitemaps, publicBasePath, xslURL: xslUrl, lastmod, namespaces, }: WriteSitemapConfig, astroConfig: AstroConfig): Promise<void>;
|
||||
export {};
|
||||
71
node_modules/@astrojs/sitemap/dist/write-sitemap.js
generated
vendored
Normal file
71
node_modules/@astrojs/sitemap/dist/write-sitemap.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { normalize, resolve } from "node:path";
|
||||
import { pipeline, Readable } from "node:stream";
|
||||
import { promisify } from "node:util";
|
||||
import { SitemapAndIndexStream, SitemapIndexStream, SitemapStream } from "sitemap";
|
||||
import replace from "stream-replace-string";
|
||||
async function writeSitemap({
|
||||
filenameBase,
|
||||
hostname,
|
||||
sitemapHostname = hostname,
|
||||
sourceData,
|
||||
destinationDir,
|
||||
limit = 5e4,
|
||||
customSitemaps = [],
|
||||
publicBasePath = "./",
|
||||
xslURL: xslUrl,
|
||||
lastmod,
|
||||
namespaces = { news: true, xhtml: true, image: true, video: true }
|
||||
}, astroConfig) {
|
||||
await mkdir(destinationDir, { recursive: true });
|
||||
const sitemapAndIndexStream = new SitemapAndIndexStream({
|
||||
limit,
|
||||
xslUrl,
|
||||
getSitemapStream: (i) => {
|
||||
const sitemapStream = new SitemapStream({
|
||||
hostname,
|
||||
xslUrl,
|
||||
// Custom namespace handling
|
||||
xmlns: {
|
||||
news: namespaces?.news !== false,
|
||||
xhtml: namespaces?.xhtml !== false,
|
||||
image: namespaces?.image !== false,
|
||||
video: namespaces?.video !== false
|
||||
}
|
||||
});
|
||||
const path = `./${filenameBase}-${i}.xml`;
|
||||
const writePath = resolve(destinationDir, path);
|
||||
if (!publicBasePath.endsWith("/")) {
|
||||
publicBasePath += "/";
|
||||
}
|
||||
const publicPath = normalize(publicBasePath + path);
|
||||
let stream;
|
||||
if (astroConfig.trailingSlash === "never" || astroConfig.build.format === "file") {
|
||||
const host = hostname.endsWith("/") ? hostname.slice(0, -1) : hostname;
|
||||
const searchStr = `<loc>${host}/</loc>`;
|
||||
const replaceStr = `<loc>${host}</loc>`;
|
||||
stream = sitemapStream.pipe(replace(searchStr, replaceStr)).pipe(createWriteStream(writePath));
|
||||
} else {
|
||||
stream = sitemapStream.pipe(createWriteStream(writePath));
|
||||
}
|
||||
const url = new URL(publicPath, sitemapHostname).toString();
|
||||
return [{ url, lastmod }, sitemapStream, stream];
|
||||
}
|
||||
});
|
||||
const src = Readable.from(sourceData);
|
||||
const indexPath = resolve(destinationDir, `./${filenameBase}-index.xml`);
|
||||
for (const url of customSitemaps) {
|
||||
SitemapIndexStream.prototype._transform.call(
|
||||
sitemapAndIndexStream,
|
||||
{ url, lastmod },
|
||||
"utf8",
|
||||
() => {
|
||||
}
|
||||
);
|
||||
}
|
||||
return promisify(pipeline)(src, sitemapAndIndexStream, createWriteStream(indexPath));
|
||||
}
|
||||
export {
|
||||
writeSitemap
|
||||
};
|
||||
Reference in New Issue
Block a user