studiocms
Version:
Astro Native CMS for AstroDB. Built from the ground up by the Astro community.
103 lines (91 loc) • 3.15 kB
text/typescript
import { convertToSafeString } from '@withstudiocms/internal_helpers/utils';
import type { AstroIntegration } from 'astro';
import { addVirtualImports, createResolver } from 'astro-integration-kit';
/**
* Options for configuring the dynamic sitemap.
*/
interface DynamicSitemapOptions {
/**
* An array of sitemap configurations.
*/
sitemaps: {
/**
* The name of the plugin that generates the sitemap.
*/
pluginName: string;
/**
* The endpoint path or URL where the sitemap XML can be accessed.
*/
sitemapXMLEndpointPath: string | URL;
}[];
}
/**
* Converts a given string to a safe string format by removing leading and trailing underscores,
* and replacing the prefix 'studiocms_' if present.
*
* @param str - The input string to be converted.
* @returns The converted safe string.
*/
export function safeString(str: string) {
return convertToSafeString(str).replace(/^_+/, '').replace(/_+$/, '').replace('studiocms_', '');
}
/**
* Generates a dynamic sitemap integration for Astro.
*
* @param {DynamicSitemapOptions} options - Configuration options for the dynamic sitemap.
* @returns {AstroIntegration} The Astro integration object.
*
* The integration adds virtual imports for sitemaps and injects routes for the sitemap index and individual sitemaps.
*
* The `options` parameter should include:
* - `sitemaps`: An array of objects, each containing:
* - `pluginName`: The name of the plugin.
* - `sitemapXMLEndpointPath`: The entry point path for the sitemap XML.
*
* The function performs the following steps:
* 1. Creates a resolver using the current module URL.
* 2. Adds virtual imports for the sitemaps.
* 3. Injects a route for the sitemap index.
* 4. Iterates over the provided sitemaps and injects routes for each sitemap.
*
* If multiple sitemaps have the same pattern, a unique pattern is generated by appending an index.
*/
export function dynamicSitemap(options: DynamicSitemapOptions): AstroIntegration {
const { resolve } = createResolver(import.meta.url);
return {
name: 'studiocms/dynamic-sitemap',
hooks: {
/* v8 ignore start */
'astro:config:setup': (params) => {
const { injectRoute } = params;
const { sitemaps } = options;
addVirtualImports(params, {
name: 'studiocms/dynamic-sitemap',
imports: {
'virtual:studiocms/sitemaps': `
export const sitemaps = ${JSON.stringify([...sitemaps.map(({ pluginName }) => `./sitemap-${safeString(pluginName)}.xml`)])};
`,
},
});
injectRoute({
entrypoint: resolve('./sitemap-index.xml.js'),
pattern: '/sitemap-index.xml',
prerender: false,
});
const existingSitemaps: string[] = [];
for (const { pluginName, sitemapXMLEndpointPath: entrypoint } of sitemaps) {
let pattern = `/sitemap-${safeString(pluginName)}.xml`;
if (existingSitemaps.includes(pattern)) {
pattern = `/sitemap-${safeString(pluginName)}-${existingSitemaps.length}.xml`;
}
injectRoute({
entrypoint,
pattern,
prerender: false,
});
}
},
/* v8 ignore stop */
},
};
}