1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
import { type WriteStream, createWriteStream } from 'fs';
import { normalize, resolve } from 'path';
import { Readable, pipeline } from 'stream';
import { promisify } from 'util';
import { mkdir } from 'fs/promises';
import replace from 'stream-replace-string';
import { SitemapAndIndexStream, SitemapStream } from 'sitemap';
import type { AstroConfig } from 'astro';
import type { SitemapItem } from './index.js';
type WriteSitemapConfig = {
hostname: string;
sitemapHostname?: string;
sourceData: SitemapItem[];
destinationDir: string;
publicBasePath?: string;
limit?: number;
};
// adapted from sitemap.js/sitemap-simple
export async function writeSitemap(
{
hostname,
sitemapHostname = hostname,
sourceData,
destinationDir,
limit = 50000,
publicBasePath = './',
}: WriteSitemapConfig,
astroConfig: AstroConfig,
) {
await mkdir(destinationDir, { recursive: true });
const sitemapAndIndexStream = new SitemapAndIndexStream({
limit,
getSitemapStream: (i) => {
const sitemapStream = new SitemapStream({
hostname,
});
const path = `./sitemap-${i}.xml`;
const writePath = resolve(destinationDir, path);
if (!publicBasePath.endsWith('/')) {
publicBasePath += '/';
}
const publicPath = normalize(publicBasePath + path);
let stream: WriteStream;
if (astroConfig.trailingSlash === 'never' || astroConfig.build.format === 'file') {
// workaround for trailing slash issue in sitemap.js: https://github.com/ekalinin/sitemap.js/issues/403
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));
}
return [new URL(publicPath, sitemapHostname).toString(), sitemapStream, stream];
},
});
let src = Readable.from(sourceData);
const indexPath = resolve(destinationDir, `./sitemap-index.xml`);
return promisify(pipeline)(src, sitemapAndIndexStream, createWriteStream(indexPath));
}
|