BREAKING CHANGE(api): redesign smartsitemap around builder-based sitemap creation, parsing, validation, and import utilities
This commit is contained in:
82
ts/smartsitemap.classes.indexbuilder.ts
Normal file
82
ts/smartsitemap.classes.indexbuilder.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user