278 lines
8.1 KiB
TypeScript
278 lines
8.1 KiB
TypeScript
// ============================================================
|
||
// CORE TYPES
|
||
// ============================================================
|
||
|
||
/**
|
||
* Change frequency values per the sitemap protocol specification.
|
||
* Note: Google ignores changefreq, but other search engines may use it.
|
||
*/
|
||
export type TChangeFreq =
|
||
| 'always'
|
||
| 'hourly'
|
||
| 'daily'
|
||
| 'weekly'
|
||
| 'monthly'
|
||
| 'yearly'
|
||
| 'never';
|
||
|
||
/** Supported output formats */
|
||
export type TOutputFormat = 'xml' | 'txt' | 'json';
|
||
|
||
// ============================================================
|
||
// URL ENTRY — the core unit of a sitemap
|
||
// ============================================================
|
||
|
||
/**
|
||
* A single URL entry in a sitemap, supporting all standard extensions.
|
||
*/
|
||
export interface ISitemapUrl {
|
||
/** Absolute URL of the page (required, max 2048 chars) */
|
||
loc: string;
|
||
/** Last modification date — accepts Date, ISO string, or Unix timestamp (ms) */
|
||
lastmod?: Date | string | number;
|
||
/** How frequently the page changes */
|
||
changefreq?: TChangeFreq;
|
||
/** Priority relative to other URLs on your site, 0.0 to 1.0 */
|
||
priority?: number;
|
||
/** Image sitemap extension entries */
|
||
images?: ISitemapImage[];
|
||
/** Video sitemap extension entries */
|
||
videos?: ISitemapVideo[];
|
||
/** News sitemap extension */
|
||
news?: ISitemapNews;
|
||
/** Alternate language versions (hreflang) */
|
||
alternates?: ISitemapAlternate[];
|
||
}
|
||
|
||
// ============================================================
|
||
// SITEMAP EXTENSIONS
|
||
// ============================================================
|
||
|
||
export interface ISitemapImage {
|
||
/** URL of the image (required) */
|
||
loc: string;
|
||
/** Caption for the image */
|
||
caption?: string;
|
||
/** Title of the image */
|
||
title?: string;
|
||
/** Geographic location (e.g. "New York, USA") */
|
||
geoLocation?: string;
|
||
/** URL to the image license */
|
||
licenseUrl?: string;
|
||
}
|
||
|
||
export interface ISitemapVideo {
|
||
/** URL to the video thumbnail (required) */
|
||
thumbnailLoc: string;
|
||
/** Title of the video (required) */
|
||
title: string;
|
||
/** Description of the video, max 2048 chars (required) */
|
||
description: string;
|
||
/** URL of the actual video media file */
|
||
contentLoc?: string;
|
||
/** URL of the embeddable player — at least one of contentLoc or playerLoc required */
|
||
playerLoc?: string;
|
||
/** Duration in seconds (1–28800) */
|
||
duration?: number;
|
||
/** Rating 0.0 to 5.0 */
|
||
rating?: number;
|
||
/** Number of views */
|
||
viewCount?: number;
|
||
/** Publication date */
|
||
publicationDate?: Date | string;
|
||
/** Whether the video is family friendly (default true) */
|
||
familyFriendly?: boolean;
|
||
/** Tags for the video (max 32) */
|
||
tags?: string[];
|
||
/** Whether this is a live stream */
|
||
live?: boolean;
|
||
/** Whether a subscription is required to view */
|
||
requiresSubscription?: boolean;
|
||
}
|
||
|
||
export interface ISitemapNews {
|
||
/** Publication information */
|
||
publication: {
|
||
/** Publication name (e.g. "The New York Times") */
|
||
name: string;
|
||
/** Language code (ISO 639, e.g. "en", "de", "zh-cn") */
|
||
language: string;
|
||
};
|
||
/** Publication date of the article */
|
||
publicationDate: Date | string | number;
|
||
/** Article title */
|
||
title: string;
|
||
/** Keywords (array or comma-separated string) */
|
||
keywords?: string[] | string;
|
||
}
|
||
|
||
export interface ISitemapAlternate {
|
||
/** Language code (ISO 639) or 'x-default' for the default version */
|
||
hreflang: string;
|
||
/** URL for this language version */
|
||
href: string;
|
||
}
|
||
|
||
// ============================================================
|
||
// SITEMAP INDEX
|
||
// ============================================================
|
||
|
||
export interface ISitemapIndexEntry {
|
||
/** URL to the sitemap file */
|
||
loc: string;
|
||
/** Last modification date of the referenced sitemap */
|
||
lastmod?: Date | string | number;
|
||
}
|
||
|
||
// ============================================================
|
||
// CONFIGURATION
|
||
// ============================================================
|
||
|
||
export interface ISitemapOptions {
|
||
/** Base URL for the website (used to resolve relative URLs and for auto-split filenames) */
|
||
baseUrl?: string;
|
||
/** XSL stylesheet URL for browser-viewable sitemaps */
|
||
xslUrl?: string;
|
||
/** Default changefreq for URLs that don't specify one */
|
||
defaultChangeFreq?: TChangeFreq;
|
||
/** Default priority for URLs that don't specify one (0.0–1.0) */
|
||
defaultPriority?: number;
|
||
/** Whether to pretty-print XML output (default: true) */
|
||
prettyPrint?: boolean;
|
||
/** Maximum URLs per sitemap file before auto-splitting (default: 50000, max: 50000) */
|
||
maxUrlsPerSitemap?: number;
|
||
/** Enable gzip compression for toGzipBuffer() */
|
||
gzip?: boolean;
|
||
/** Whether to validate URLs and fields (default: true) */
|
||
validate?: boolean;
|
||
}
|
||
|
||
export interface INewsSitemapOptions extends ISitemapOptions {
|
||
/** Publication name — required for news sitemaps */
|
||
publicationName: string;
|
||
/** Publication language (default: 'en') */
|
||
publicationLanguage?: string;
|
||
}
|
||
|
||
export interface IFeedImportOptions {
|
||
/** Publication name for news sitemap mapping */
|
||
publicationName?: string;
|
||
/** Publication language for news sitemap mapping */
|
||
publicationLanguage?: string;
|
||
/** Only include items newer than this date */
|
||
newerThan?: Date | number;
|
||
/** Maximum number of items to import */
|
||
limit?: number;
|
||
/** Custom mapping function from feed item to sitemap URL (return null to skip) */
|
||
mapItem?: (item: IFeedItem) => ISitemapUrl | null;
|
||
}
|
||
|
||
/** Shape of a parsed RSS/Atom feed item */
|
||
export interface IFeedItem {
|
||
title?: string;
|
||
link?: string;
|
||
pubDate?: string;
|
||
author?: string;
|
||
content?: string;
|
||
contentSnippet?: string;
|
||
isoDate?: string;
|
||
id?: string;
|
||
categories?: string[];
|
||
enclosure?: {
|
||
url?: string;
|
||
type?: string;
|
||
length?: string;
|
||
};
|
||
[key: string]: any;
|
||
}
|
||
|
||
// ============================================================
|
||
// YAML CONFIG
|
||
// ============================================================
|
||
|
||
/**
|
||
* Enhanced YAML configuration format for defining sitemaps declaratively.
|
||
* Supports per-frequency URL groups, default settings, and feed imports.
|
||
*/
|
||
export interface ISitemapYamlConfig {
|
||
/** Base URL to prepend to relative paths */
|
||
baseUrl?: string;
|
||
/** Default values for all URLs */
|
||
defaults?: {
|
||
changefreq?: TChangeFreq;
|
||
priority?: number;
|
||
};
|
||
/** URL groups organized by change frequency */
|
||
urls?: { [K in TChangeFreq]?: string[] };
|
||
/** RSS/Atom feeds to import */
|
||
feeds?: Array<{
|
||
url: string;
|
||
type: 'news' | 'standard';
|
||
publicationName?: string;
|
||
publicationLanguage?: string;
|
||
}>;
|
||
}
|
||
|
||
// ============================================================
|
||
// PARSED SITEMAP (bidirectional)
|
||
// ============================================================
|
||
|
||
export interface IParsedSitemap {
|
||
/** Whether this is a urlset or a sitemap index */
|
||
type: 'urlset' | 'sitemapindex';
|
||
/** Parsed URL entries (populated when type is 'urlset') */
|
||
urls: ISitemapUrl[];
|
||
/** Parsed index entries (populated when type is 'sitemapindex') */
|
||
sitemaps: ISitemapIndexEntry[];
|
||
}
|
||
|
||
// ============================================================
|
||
// VALIDATION
|
||
// ============================================================
|
||
|
||
export interface IValidationError {
|
||
field: string;
|
||
message: string;
|
||
url?: string;
|
||
}
|
||
|
||
export interface IValidationWarning {
|
||
field: string;
|
||
message: string;
|
||
url?: string;
|
||
}
|
||
|
||
export interface IValidationResult {
|
||
valid: boolean;
|
||
errors: IValidationError[];
|
||
warnings: IValidationWarning[];
|
||
stats: ISitemapStats;
|
||
}
|
||
|
||
// ============================================================
|
||
// STATISTICS
|
||
// ============================================================
|
||
|
||
export interface ISitemapStats {
|
||
urlCount: number;
|
||
imageCount: number;
|
||
videoCount: number;
|
||
newsCount: number;
|
||
alternateCount: number;
|
||
estimatedSizeBytes: number;
|
||
needsIndex: boolean;
|
||
}
|
||
|
||
// ============================================================
|
||
// AUTO-SPLIT OUTPUT
|
||
// ============================================================
|
||
|
||
export interface ISitemapSet {
|
||
/** Whether the URL count exceeded maxUrlsPerSitemap */
|
||
needsIndex: boolean;
|
||
/** The sitemap index XML (null if all URLs fit in one sitemap) */
|
||
indexXml: string | null;
|
||
/** Individual sitemap chunks */
|
||
sitemaps: Array<{ filename: string; xml: string }>;
|
||
}
|