BREAKING CHANGE(api): redesign smartsitemap around builder-based sitemap creation, parsing, validation, and import utilities

This commit is contained in:
2026-03-20 14:03:33 +00:00
parent 61f6bcebd4
commit 4e707347dd
22 changed files with 4843 additions and 2196 deletions

View File

@@ -1,92 +1,112 @@
import { SitemapNews } from './smartsitemap.classes.sitemapnews.js';
import {
type IUrlInfo,
SitemapWebsite,
} from './smartsitemap.classes.sitemapwebsite.js';
import * as plugins from './smartsitemap.plugins.js';
import * as interfaces from './interfaces/index.js';
import type * as interfaces from './interfaces/index.js';
import { UrlsetBuilder } from './smartsitemap.classes.urlsetbuilder.js';
import { NewsSitemapBuilder } from './smartsitemap.classes.newsbuilder.js';
import { SitemapIndexBuilder } from './smartsitemap.classes.indexbuilder.js';
import { SitemapParser } from './smartsitemap.classes.sitemapparser.js';
import { FeedImporter } from './smartsitemap.classes.feedimporter.js';
import { YamlImporter } from './smartsitemap.classes.yamlimporter.js';
import { SitemapValidator } from './smartsitemap.classes.validator.js';
/**
* Main entry point for @push.rocks/smartsitemap.
* Provides static factory methods for creating, parsing, and validating sitemaps.
*
* @example Simple sitemap
* ```typescript
* const xml = SmartSitemap.create()
* .addUrl('https://example.com/')
* .addUrl('https://example.com/about')
* .toXml();
* ```
*
* @example News sitemap from RSS feed
* ```typescript
* const builder = SmartSitemap.createNews({ publicationName: 'My Pub' });
* await builder.importFromFeedUrl('https://example.com/rss/');
* const xml = builder.toXml();
* ```
*/
export class SmartSitemap {
constructor() {}
// ──────────────────────────────────────────────
// Static Factory Methods
// ──────────────────────────────────────────────
/**
* creates a sitemap for news from feedurl
*/
public async createSitemapNewsFromFeedUrl(
feedUrlArg: string,
): Promise<string> {
const sitemapNewsInstance = new SitemapNews({});
await sitemapNewsInstance.readAndAddFromRssFeedUrl(feedUrlArg);
return sitemapNewsInstance.exportSitemapXml();
/** Create a standard sitemap builder */
static create(options?: interfaces.ISitemapOptions): UrlsetBuilder {
return new UrlsetBuilder(options);
}
/**
* creates a sitemap for news from feedxmlstring
*/
public async createSitemapNewsFromAFeedStringArg(
feedStringArg: string,
): Promise<string> {
const sitemapNewsInstance = new SitemapNews({});
await sitemapNewsInstance.readAndAddFromRssFeedString(feedStringArg);
return sitemapNewsInstance.exportSitemapXml();
/** Create a news sitemap builder */
static createNews(options: interfaces.INewsSitemapOptions): NewsSitemapBuilder {
return new NewsSitemapBuilder(options);
}
/**
* creates a sitemap for news from an array of articles
*/
public async createSitemapNewsFromArticleArray(
articleArrayArg: plugins.tsclass.content.IArticle[],
): Promise<string> {
const sitemapNewsInstance = new SitemapNews({});
await sitemapNewsInstance.readAndParseArticles(articleArrayArg);
return sitemapNewsInstance.exportSitemapXml();
/** Create a sitemap index builder */
static createIndex(options?: interfaces.ISitemapOptions): SitemapIndexBuilder {
return new SitemapIndexBuilder(options);
}
/**
* creates a normal sitemap from a list of urls
*/
public async createSitemapFromYmlString(yamlString: string): Promise<string> {
const yamlObject: interfaces.ISitemapYaml =
await plugins.smartyaml.yamlStringToObject(yamlString);
const sitemapWebsite = new SitemapWebsite();
for (const urlArg of yamlObject.daily) {
sitemapWebsite.addUrl({
url: urlArg,
timestamp: Date.now() - 10000,
frequency: 'daily',
});
}
return sitemapWebsite.exportSitemapXml();
/** Parse a sitemap XML string into structured data */
static async parse(xml: string): Promise<interfaces.IParsedSitemap> {
return SitemapParser.parse(xml);
}
/**
* creates a normal sitemap from a list of urls
*/
public async createSitemapFromUrlInfoArray(urlInfosArg: IUrlInfo[]) {
const sitemapWebsite = new SitemapWebsite();
for (const urlInfo of urlInfosArg) {
sitemapWebsite.addUrl(urlInfo);
}
return sitemapWebsite.exportSitemapXml();
/** Fetch and parse a sitemap from a URL */
static async parseUrl(url: string): Promise<interfaces.IParsedSitemap> {
return SitemapParser.parseUrl(url);
}
/**
* parses a sitemap url
*/
public async parseSitemapUrl(urlArg: string) {
const response = await plugins.webrequest.webrequest(urlArg);
const sitemapXml = await response.text();
const parsedSitemap = await this.parseSitemap(sitemapXml);
return parsedSitemap;
/** Create a UrlsetBuilder populated from an RSS/Atom feed URL */
static async fromFeedUrl(
feedUrl: string,
options?: interfaces.IFeedImportOptions,
): Promise<UrlsetBuilder> {
const urls = await FeedImporter.fromUrl(feedUrl, options);
const builder = new UrlsetBuilder();
builder.addUrls(urls);
return builder;
}
/**
* parses a sitemap
*/
public async parseSitemap(
sitemapXmlArg: string,
): Promise<interfaces.IParsedSiteMap> {
return new plugins.smartxml.SmartXml().parseXmlToObject(sitemapXmlArg);
/** Create a UrlsetBuilder populated from an RSS/Atom feed string */
static async fromFeedString(
feedXml: string,
options?: interfaces.IFeedImportOptions,
): Promise<UrlsetBuilder> {
const urls = await FeedImporter.fromString(feedXml, options);
const builder = new UrlsetBuilder();
builder.addUrls(urls);
return builder;
}
/** Create a UrlsetBuilder populated from a YAML config string */
static async fromYaml(yamlString: string): Promise<UrlsetBuilder> {
const urls = await YamlImporter.parseConfig(yamlString);
const builder = new UrlsetBuilder();
builder.addUrls(urls);
return builder;
}
/** Create a NewsSitemapBuilder populated from @tsclass/tsclass IArticle array */
static fromArticles(
articles: plugins.tsclass.content.IArticle[],
options: interfaces.INewsSitemapOptions,
): NewsSitemapBuilder {
const builder = new NewsSitemapBuilder(options);
builder.importFromArticles(articles);
return builder;
}
/** Create a UrlsetBuilder from a simple URL string array */
static fromUrls(urls: string[], options?: interfaces.ISitemapOptions): UrlsetBuilder {
const builder = new UrlsetBuilder(options);
builder.addFromArray(urls);
return builder;
}
/** Validate a sitemap XML string */
static async validate(xml: string): Promise<interfaces.IValidationResult> {
const parsed = await SitemapParser.parse(xml);
return SitemapValidator.validateUrlset(parsed.urls);
}
}