// ============================================================ // 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 }>; }