Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .changeset/neat-tigers-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@astrojs/sitemap': minor
---

Customize the filenames of sitemap XML files generated by the `@astro/sitemap` integration by setting `filenameBase` in the integration configuration settings. This may be useful when deploying an Astro site at a path on a domain with preexisting sitemap files.

Generated sitemap files will appear at `/sitemap-0.xml` and `/sitemap-index.xml` by default, which may conflict with preexisting files. Set `filenameBase` to a custom value to avoid that if so:

```js
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
site: 'https://example.com',
integrations: [
sitemap({
filenameBase: 'astronomy-sitemap',
}),
],
});
```

This will yield sitemap and index files as `https://example.com/astronomy-sitemap-0.xml` and `https://example.com/astronomy-sitemap-index.xml`.
1 change: 1 addition & 0 deletions packages/integrations/sitemap/src/config-defaults.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { SitemapOptions } from './index.js';

export const SITEMAP_CONFIG_DEFAULTS = {
filenameBase: 'sitemap',
entryLimit: 45000,
} satisfies SitemapOptions;
10 changes: 6 additions & 4 deletions packages/integrations/sitemap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type LinkItem = LinkItemBase;

export type SitemapOptions =
| {
filenameBase?: string;
filter?(page: string): boolean;
customPages?: string[];

Expand Down Expand Up @@ -46,7 +47,6 @@ function formatConfigErrorMessage(err: ZodError) {
}

const PKG_NAME = '@astrojs/sitemap';
const OUTFILE = 'sitemap-index.xml';
const STATUS_CODE_PAGES = new Set(['404', '500']);

const isStatusCodePage = (locales: string[]) => {
Expand Down Expand Up @@ -88,8 +88,9 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {

const opts = validateOptions(config.site, options);

const { filter, customPages, serialize, entryLimit } = opts;
const { filenameBase, filter, customPages, 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
Expand Down Expand Up @@ -144,7 +145,7 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {
}

if (pageUrls.length === 0) {
logger.warn(`No pages found!\n\`${OUTFILE}\` not created.`);
logger.warn(`No pages found!\n\`${outFile}\` not created.`);
return;
}

Expand Down Expand Up @@ -173,6 +174,7 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {
const xslURL = opts.xslURL ? new URL(opts.xslURL, finalSiteUrl).href : undefined;
await writeSitemap(
{
filenameBase: filenameBase,
hostname: finalSiteUrl.href,
destinationDir: destDir,
publicBasePath: config.base,
Expand All @@ -182,7 +184,7 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {
},
config,
);
logger.info(`\`${OUTFILE}\` created at \`${path.relative(process.cwd(), destDir)}\``);
logger.info(`\`${outFile}\` created at \`${path.relative(process.cwd(), destDir)}\``);
} catch (err) {
if (err instanceof ZodError) {
logger.warn(formatConfigErrorMessage(err));
Expand Down
1 change: 1 addition & 0 deletions packages/integrations/sitemap/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const localeKeySchema = z.string().min(1);

export const SitemapOptionsSchema = z
.object({
filenameBase: z.string().optional().default(SITEMAP_CONFIG_DEFAULTS.filenameBase),
filter: z.function().args(z.string()).returns(z.boolean()).optional(),
customPages: z.string().url().array().optional(),
canonicalURL: z.string().url().optional(),
Expand Down
6 changes: 4 additions & 2 deletions packages/integrations/sitemap/src/write-sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { AstroConfig } from 'astro';
import type { SitemapItem } from './index.js';

type WriteSitemapConfig = {
filenameBase: string;
hostname: string;
sitemapHostname?: string;
sourceData: SitemapItem[];
Expand All @@ -23,6 +24,7 @@ type WriteSitemapConfig = {
// adapted from sitemap.js/sitemap-simple
export async function writeSitemap(
{
filenameBase,
hostname,
sitemapHostname = hostname,
sourceData,
Expand All @@ -43,7 +45,7 @@ export async function writeSitemap(
hostname,
xslUrl,
});
const path = `./sitemap-${i}.xml`;
const path = `./${filenameBase}-${i}.xml`;
const writePath = resolve(destinationDir, path);
if (!publicBasePath.endsWith('/')) {
publicBasePath += '/';
Expand All @@ -68,6 +70,6 @@ export async function writeSitemap(
});

const src = Readable.from(sourceData);
const indexPath = resolve(destinationDir, `./sitemap-index.xml`);
const indexPath = resolve(destinationDir, `./${filenameBase}-index.xml`);
return promisify(pipeline)(src, sitemapAndIndexStream, createWriteStream(indexPath));
}
26 changes: 26 additions & 0 deletions packages/integrations/sitemap/test/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,30 @@ describe('Config', () => {
);
});
});

describe('Configuring the filename', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/static/',
integrations: [
sitemap({
filter: (page) => page === 'http://example.com/one/',
filenameBase: 'my-sitemap',
}),
],
});
await fixture.build();
});

it('filenameBase: Sets the generated sitemap filename', async () => {
const data = await readXML(fixture.readFile('/my-sitemap-0.xml'));
const urls = data.urlset.url;
assert.equal(urls.length, 1);

const indexData = await readXML(fixture.readFile('/my-sitemap-index.xml'));
const sitemapUrls = indexData.sitemapindex.sitemap;
assert.equal(sitemapUrls.length, 1);
assert.equal(sitemapUrls[0].loc[0], 'http://example.com/my-sitemap-0.xml');
});
});
});