Files
smartsitemap/ts/smartsitemap.classes.indexbuilder.ts

83 lines
2.5 KiB
TypeScript

import type * as interfaces from './interfaces/index.js';
import { XmlRenderer } from './smartsitemap.classes.xmlrenderer.js';
import { UrlsetBuilder } from './smartsitemap.classes.urlsetbuilder.js';
/**
* Builder for sitemap index files (<sitemapindex>).
* Used when you have multiple sitemaps that need to be referenced from a single index.
* Every mutating method returns `this` for fluent chaining.
*/
export class SitemapIndexBuilder {
private entries: interfaces.ISitemapIndexEntry[] = [];
private options: interfaces.ISitemapOptions;
constructor(options?: interfaces.ISitemapOptions) {
this.options = options ?? {};
}
/** Add a sitemap index entry */
add(entry: interfaces.ISitemapIndexEntry): this {
this.entries.push(entry);
return this;
}
/** Add a sitemap by URL, optionally with lastmod */
addSitemap(loc: string, lastmod?: Date | string | number): this {
const entry: interfaces.ISitemapIndexEntry = { loc };
if (lastmod != null) {
entry.lastmod = lastmod;
}
this.entries.push(entry);
return this;
}
/** Add multiple sitemap entries */
addSitemaps(entries: interfaces.ISitemapIndexEntry[]): this {
this.entries.push(...entries);
return this;
}
/**
* Build an index and individual sitemaps from a UrlsetBuilder that needs splitting.
* The builder's URLs are divided into chunks of maxUrlsPerSitemap.
*/
static fromBuilder(
builder: UrlsetBuilder,
baseUrl: string,
): { index: SitemapIndexBuilder; sitemaps: UrlsetBuilder[] } {
const urls = builder.getUrls();
const options = builder.getOptions();
const maxUrls = Math.min(options.maxUrlsPerSitemap ?? 50000, 50000);
const index = new SitemapIndexBuilder(options);
const sitemaps: UrlsetBuilder[] = [];
for (let i = 0; i < urls.length; i += maxUrls) {
const chunk = urls.slice(i, i + maxUrls);
const chunkBuilder = new UrlsetBuilder(options);
chunkBuilder.addUrls(chunk);
sitemaps.push(chunkBuilder);
const filename = `sitemap-${sitemaps.length}.xml`;
index.addSitemap(`${baseUrl.replace(/\/$/, '')}/${filename}`);
}
return { index, sitemaps };
}
/** Export as sitemap index XML string */
toXml(): string {
return XmlRenderer.renderIndex(this.entries, this.options);
}
/** Get all entries */
getEntries(): interfaces.ISitemapIndexEntry[] {
return [...this.entries];
}
/** Get the number of sitemaps in this index */
get count(): number {
return this.entries.length;
}
}