@power-seo/sitemap 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -25,7 +25,8 @@ function buildImageXml(images) {
25
25
  `;
26
26
  if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>
27
27
  `;
28
- if (img.geoLocation) xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>
28
+ if (img.geoLocation)
29
+ xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>
29
30
  `;
30
31
  if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>
31
32
  `;
@@ -44,23 +45,31 @@ function buildVideoXml(videos) {
44
45
  `;
45
46
  xml += ` <video:description>${escapeXml(vid.description)}</video:description>
46
47
  `;
47
- if (vid.contentLoc) xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>
48
+ if (vid.contentLoc)
49
+ xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>
48
50
  `;
49
- if (vid.playerLoc) xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>
51
+ if (vid.playerLoc)
52
+ xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>
50
53
  `;
51
- if (vid.duration !== void 0) xml += ` <video:duration>${vid.duration}</video:duration>
54
+ if (vid.duration !== void 0)
55
+ xml += ` <video:duration>${vid.duration}</video:duration>
52
56
  `;
53
- if (vid.expirationDate) xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>
57
+ if (vid.expirationDate)
58
+ xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>
54
59
  `;
55
60
  if (vid.rating !== void 0) xml += ` <video:rating>${vid.rating}</video:rating>
56
61
  `;
57
- if (vid.viewCount !== void 0) xml += ` <video:view_count>${vid.viewCount}</video:view_count>
62
+ if (vid.viewCount !== void 0)
63
+ xml += ` <video:view_count>${vid.viewCount}</video:view_count>
58
64
  `;
59
- if (vid.publicationDate) xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>
65
+ if (vid.publicationDate)
66
+ xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>
60
67
  `;
61
- if (vid.familyFriendly !== void 0) xml += ` <video:family_friendly>${vid.familyFriendly ? "yes" : "no"}</video:family_friendly>
68
+ if (vid.familyFriendly !== void 0)
69
+ xml += ` <video:family_friendly>${vid.familyFriendly ? "yes" : "no"}</video:family_friendly>
62
70
  `;
63
- if (vid.live !== void 0) xml += ` <video:live>${vid.live ? "yes" : "no"}</video:live>
71
+ if (vid.live !== void 0)
72
+ xml += ` <video:live>${vid.live ? "yes" : "no"}</video:live>
64
73
  `;
65
74
  xml += " </video:video>\n";
66
75
  return xml;
@@ -206,9 +215,11 @@ function* streamSitemap(hostname, urls) {
206
215
  `;
207
216
  yield ` <video:description>${escapeXml3(vid.description)}</video:description>
208
217
  `;
209
- if (vid.contentLoc) yield ` <video:content_loc>${escapeXml3(vid.contentLoc)}</video:content_loc>
218
+ if (vid.contentLoc)
219
+ yield ` <video:content_loc>${escapeXml3(vid.contentLoc)}</video:content_loc>
210
220
  `;
211
- if (vid.playerLoc) yield ` <video:player_loc>${escapeXml3(vid.playerLoc)}</video:player_loc>
221
+ if (vid.playerLoc)
222
+ yield ` <video:player_loc>${escapeXml3(vid.playerLoc)}</video:player_loc>
212
223
  `;
213
224
  yield " </video:video>\n";
214
225
  }
@@ -278,7 +289,9 @@ function validateSitemapUrl(url) {
278
289
  }
279
290
  }
280
291
  if (url.images.length > 1e3) {
281
- warnings.push(`URL has ${url.images.length} images. Google supports up to 1,000 images per page.`);
292
+ warnings.push(
293
+ `URL has ${url.images.length} images. Google supports up to 1,000 images per page.`
294
+ );
282
295
  }
283
296
  }
284
297
  if (url.videos) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generator.ts","../src/types.ts","../src/sitemap-index.ts","../src/stream.ts","../src/validate.ts"],"names":["normalizeUrl","escapeXml","indexEntries","isAbsoluteUrl","MAX_URL_LENGTH"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/sitemap — XML Sitemap Generator\n// ============================================================================\n\nimport type { SitemapConfig, SitemapURL, SitemapImage, SitemapVideo, SitemapNews } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/** Determine which namespace extensions are needed. */\nfunction detectNamespaces(urls: SitemapURL[]): { image: boolean; video: boolean; news: boolean } {\n let image = false;\n let video = false;\n let news = false;\n for (const url of urls) {\n if (url.images && url.images.length > 0) image = true;\n if (url.videos && url.videos.length > 0) video = true;\n if (url.news) news = true;\n if (image && video && news) break;\n }\n return { image, video, news };\n}\n\nfunction buildImageXml(images: SitemapImage[]): string {\n return images\n .map((img) => {\n let xml = ' <image:image>\\n';\n xml += ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.geoLocation) xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>\\n`;\n if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n if (img.license) xml += ` <image:license>${escapeXml(img.license)}</image:license>\\n`;\n xml += ' </image:image>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildVideoXml(videos: SitemapVideo[]): string {\n return videos\n .map((vid) => {\n let xml = ' <video:video>\\n';\n xml += ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n xml += ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n xml += ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc) xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc) xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n if (vid.duration !== undefined) xml += ` <video:duration>${vid.duration}</video:duration>\\n`;\n if (vid.expirationDate) xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>\\n`;\n if (vid.rating !== undefined) xml += ` <video:rating>${vid.rating}</video:rating>\\n`;\n if (vid.viewCount !== undefined) xml += ` <video:view_count>${vid.viewCount}</video:view_count>\\n`;\n if (vid.publicationDate) xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>\\n`;\n if (vid.familyFriendly !== undefined) xml += ` <video:family_friendly>${vid.familyFriendly ? 'yes' : 'no'}</video:family_friendly>\\n`;\n if (vid.live !== undefined) xml += ` <video:live>${vid.live ? 'yes' : 'no'}</video:live>\\n`;\n xml += ' </video:video>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildNewsXml(news: SitemapNews): string {\n let xml = ' <news:news>\\n';\n xml += ' <news:publication>\\n';\n xml += ` <news:name>${escapeXml(news.publication.name)}</news:name>\\n`;\n xml += ` <news:language>${escapeXml(news.publication.language)}</news:language>\\n`;\n xml += ' </news:publication>\\n';\n xml += ` <news:publication_date>${escapeXml(news.publicationDate)}</news:publication_date>\\n`;\n xml += ` <news:title>${escapeXml(news.title)}</news:title>\\n`;\n xml += ' </news:news>\\n';\n return xml;\n}\n\nfunction buildUrlXml(url: SitemapURL, hostname: string): string {\n const loc = url.loc.startsWith('http') ? url.loc : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n let xml = ' <url>\\n';\n xml += ` <loc>${escapeXml(loc)}</loc>\\n`;\n if (url.lastmod) xml += ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) xml += ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) xml += ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n if (url.images && url.images.length > 0) xml += buildImageXml(url.images);\n if (url.videos && url.videos.length > 0) xml += buildVideoXml(url.videos);\n if (url.news) xml += buildNewsXml(url.news);\n xml += ' </url>\\n';\n return xml;\n}\n\n/**\n * Generate an XML sitemap string from a sitemap configuration.\n *\n * @example\n * ```ts\n * const xml = generateSitemap({\n * hostname: 'https://example.com',\n * urls: [\n * { loc: '/', changefreq: 'daily', priority: 1.0 },\n * { loc: '/about', changefreq: 'monthly', priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport function generateSitemap(config: SitemapConfig): string {\n const { hostname, urls } = config;\n const ns = detectNamespaces(urls);\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"';\n if (ns.image) xml += '\\n xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"';\n if (ns.video) xml += '\\n xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"';\n if (ns.news) xml += '\\n xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\"';\n xml += '>\\n';\n\n for (const url of urls) {\n xml += buildUrlXml(url, hostname);\n }\n\n xml += '</urlset>\\n';\n return xml;\n}\n","// ============================================================================\n// @power-seo/sitemap — Types\n// ============================================================================\n\nexport type {\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n SitemapConfig,\n} from '@power-seo/core';\n\n/** A sitemap entry in a sitemap index. */\nexport interface SitemapIndexEntry {\n loc: string;\n lastmod?: string;\n}\n\n/** Configuration for the sitemap index generator. */\nexport interface SitemapIndexConfig {\n sitemaps: SitemapIndexEntry[];\n}\n\n/** Result of URL validation. */\nexport interface SitemapValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/** Maximum URLs allowed per sitemap file. */\nexport const MAX_URLS_PER_SITEMAP = 50_000;\n\n/** Maximum sitemap file size in bytes (50MB). */\nexport const MAX_SITEMAP_SIZE_BYTES = 50 * 1024 * 1024;\n","// ============================================================================\n// @power-seo/sitemap — Sitemap Index Generator\n// ============================================================================\n\nimport type { SitemapConfig } from '@power-seo/core';\nimport type { SitemapIndexConfig, SitemapIndexEntry } from './types.js';\nimport { MAX_URLS_PER_SITEMAP } from './types.js';\nimport { generateSitemap } from './generator.js';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Generate a sitemap index XML string.\n *\n * @example\n * ```ts\n * const indexXml = generateSitemapIndex({\n * sitemaps: [\n * { loc: 'https://example.com/sitemap-0.xml', lastmod: '2024-01-01' },\n * { loc: 'https://example.com/sitemap-1.xml', lastmod: '2024-01-01' },\n * ],\n * });\n * ```\n */\nexport function generateSitemapIndex(config: SitemapIndexConfig): string {\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n';\n\n for (const sitemap of config.sitemaps) {\n xml += ' <sitemap>\\n';\n xml += ` <loc>${escapeXml(sitemap.loc)}</loc>\\n`;\n if (sitemap.lastmod) {\n xml += ` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>\\n`;\n }\n xml += ' </sitemap>\\n';\n }\n\n xml += '</sitemapindex>\\n';\n return xml;\n}\n\n/**\n * Split a large sitemap config into multiple sitemaps + an index.\n *\n * When a site has more than 50,000 URLs, this function splits them into\n * multiple sitemap files and returns both the individual sitemaps and\n * the index that references them.\n *\n * @example\n * ```ts\n * const { index, sitemaps } = splitSitemap({\n * hostname: 'https://example.com',\n * urls: largeUrlArray,\n * });\n * // sitemaps[0].xml, sitemaps[1].xml, etc.\n * // index = sitemap index XML\n * ```\n */\nexport function splitSitemap(\n config: SitemapConfig,\n sitemapUrlPattern = '/sitemap-{index}.xml',\n): { index: string; sitemaps: Array<{ filename: string; xml: string }> } {\n const maxPerSitemap = config.maxUrlsPerSitemap ?? MAX_URLS_PER_SITEMAP;\n const { hostname, urls } = config;\n\n if (urls.length <= maxPerSitemap) {\n const xml = generateSitemap(config);\n const filename = sitemapUrlPattern.replace('{index}', '0');\n const indexEntries: SitemapIndexEntry[] = [{ loc: `${hostname}${filename}` }];\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps: [{ filename, xml }],\n };\n }\n\n const sitemaps: Array<{ filename: string; xml: string }> = [];\n const indexEntries: SitemapIndexEntry[] = [];\n\n for (let i = 0; i < urls.length; i += maxPerSitemap) {\n const chunk = urls.slice(i, i + maxPerSitemap);\n const chunkIndex = Math.floor(i / maxPerSitemap);\n const filename = sitemapUrlPattern.replace('{index}', String(chunkIndex));\n const xml = generateSitemap({ hostname, urls: chunk });\n\n sitemaps.push({ filename, xml });\n indexEntries.push({ loc: `${hostname}${filename}` });\n }\n\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps,\n };\n}\n","// ============================================================================\n// @power-seo/sitemap — Streaming Sitemap Generator\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * A streaming sitemap generator that yields XML chunks.\n *\n * Useful for server responses where you want to stream the sitemap\n * instead of building the entire XML string in memory.\n *\n * @example\n * ```ts\n * const stream = streamSitemap('https://example.com', urls);\n * for (const chunk of stream) {\n * response.write(chunk);\n * }\n * ```\n */\nexport function* streamSitemap(\n hostname: string,\n urls: Iterable<SitemapURL>,\n): Generator<string, void, undefined> {\n yield '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n yield '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\\n';\n yield ' xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"\\n';\n yield ' xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"\\n';\n yield ' xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\">\\n';\n\n for (const url of urls) {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n yield ' <url>\\n';\n yield ` <loc>${escapeXml(loc)}</loc>\\n`;\n\n if (url.lastmod) yield ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) yield ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) yield ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n\n // Images\n if (url.images) {\n for (const img of url.images) {\n yield ' <image:image>\\n';\n yield ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) yield ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.title) yield ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n yield ' </image:image>\\n';\n }\n }\n\n // Videos\n if (url.videos) {\n for (const vid of url.videos) {\n yield ' <video:video>\\n';\n yield ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n yield ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n yield ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc) yield ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc) yield ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n yield ' </video:video>\\n';\n }\n }\n\n // News\n if (url.news) {\n yield ' <news:news>\\n';\n yield ' <news:publication>\\n';\n yield ` <news:name>${escapeXml(url.news.publication.name)}</news:name>\\n`;\n yield ` <news:language>${escapeXml(url.news.publication.language)}</news:language>\\n`;\n yield ' </news:publication>\\n';\n yield ` <news:publication_date>${escapeXml(url.news.publicationDate)}</news:publication_date>\\n`;\n yield ` <news:title>${escapeXml(url.news.title)}</news:title>\\n`;\n yield ' </news:news>\\n';\n }\n\n yield ' </url>\\n';\n }\n\n yield '</urlset>\\n';\n}\n","// ============================================================================\n// @power-seo/sitemap — URL Validation\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { isAbsoluteUrl, MAX_URL_LENGTH } from '@power-seo/core';\nimport type { SitemapValidationResult } from './types.js';\n\nconst VALID_CHANGEFREQ = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];\n\n/**\n * Validate a sitemap URL entry against the sitemap protocol spec.\n */\nexport function validateSitemapUrl(url: SitemapURL): SitemapValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // loc is required\n if (!url.loc || url.loc.trim().length === 0) {\n errors.push('URL \"loc\" is required and cannot be empty.');\n } else {\n if (!isAbsoluteUrl(url.loc)) {\n errors.push(`URL \"${url.loc}\" must be an absolute URL (starting with http:// or https://).`);\n }\n\n if (url.loc.length > 2048) {\n errors.push(`URL \"${url.loc}\" exceeds the maximum length of 2048 characters.`);\n }\n\n if (url.loc.length > MAX_URL_LENGTH) {\n warnings.push(\n `URL \"${url.loc}\" is ${url.loc.length} characters. URLs under ${MAX_URL_LENGTH} characters are recommended for SEO.`,\n );\n }\n }\n\n // lastmod validation\n if (url.lastmod) {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2})?([+-]\\d{2}:\\d{2}|Z)?)?$/;\n if (!dateRegex.test(url.lastmod)) {\n errors.push(\n `\"lastmod\" value \"${url.lastmod}\" is not a valid W3C datetime format (YYYY-MM-DD or ISO 8601).`,\n );\n }\n }\n\n // changefreq validation\n if (url.changefreq && !VALID_CHANGEFREQ.includes(url.changefreq)) {\n errors.push(\n `\"changefreq\" value \"${url.changefreq}\" is invalid. Must be one of: ${VALID_CHANGEFREQ.join(', ')}.`,\n );\n }\n\n // priority validation\n if (url.priority !== undefined) {\n if (url.priority < 0 || url.priority > 1) {\n errors.push(`\"priority\" value ${url.priority} is out of range. Must be between 0.0 and 1.0.`);\n }\n }\n\n // Image validation\n if (url.images) {\n for (let i = 0; i < url.images.length; i++) {\n const img = url.images[i]!;\n if (!img.loc || img.loc.trim().length === 0) {\n errors.push(`Image ${i + 1}: \"loc\" is required.`);\n } else if (!isAbsoluteUrl(img.loc)) {\n errors.push(`Image ${i + 1}: \"${img.loc}\" must be an absolute URL.`);\n }\n }\n if (url.images.length > 1000) {\n warnings.push(`URL has ${url.images.length} images. Google supports up to 1,000 images per page.`);\n }\n }\n\n // Video validation\n if (url.videos) {\n for (let i = 0; i < url.videos.length; i++) {\n const vid = url.videos[i]!;\n if (!vid.title) errors.push(`Video ${i + 1}: \"title\" is required.`);\n if (!vid.description) errors.push(`Video ${i + 1}: \"description\" is required.`);\n if (!vid.thumbnailLoc) errors.push(`Video ${i + 1}: \"thumbnailLoc\" is required.`);\n if (!vid.contentLoc && !vid.playerLoc) {\n errors.push(`Video ${i + 1}: either \"contentLoc\" or \"playerLoc\" must be provided.`);\n }\n if (vid.rating !== undefined && (vid.rating < 0 || vid.rating > 5)) {\n errors.push(`Video ${i + 1}: \"rating\" must be between 0.0 and 5.0.`);\n }\n }\n }\n\n // News validation\n if (url.news) {\n if (!url.news.publication?.name) errors.push('News: \"publication.name\" is required.');\n if (!url.news.publication?.language) errors.push('News: \"publication.language\" is required.');\n if (!url.news.publicationDate) errors.push('News: \"publicationDate\" is required.');\n if (!url.news.title) errors.push('News: \"title\" is required.');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/generator.ts","../src/types.ts","../src/sitemap-index.ts","../src/stream.ts","../src/validate.ts"],"names":["normalizeUrl","escapeXml","indexEntries","isAbsoluteUrl","MAX_URL_LENGTH"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/sitemap — XML Sitemap Generator\n// ============================================================================\n\nimport type {\n SitemapConfig,\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n} from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/** Determine which namespace extensions are needed. */\nfunction detectNamespaces(urls: SitemapURL[]): { image: boolean; video: boolean; news: boolean } {\n let image = false;\n let video = false;\n let news = false;\n for (const url of urls) {\n if (url.images && url.images.length > 0) image = true;\n if (url.videos && url.videos.length > 0) video = true;\n if (url.news) news = true;\n if (image && video && news) break;\n }\n return { image, video, news };\n}\n\nfunction buildImageXml(images: SitemapImage[]): string {\n return images\n .map((img) => {\n let xml = ' <image:image>\\n';\n xml += ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.geoLocation)\n xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>\\n`;\n if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n if (img.license) xml += ` <image:license>${escapeXml(img.license)}</image:license>\\n`;\n xml += ' </image:image>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildVideoXml(videos: SitemapVideo[]): string {\n return videos\n .map((vid) => {\n let xml = ' <video:video>\\n';\n xml += ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n xml += ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n xml += ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc)\n xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc)\n xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n if (vid.duration !== undefined)\n xml += ` <video:duration>${vid.duration}</video:duration>\\n`;\n if (vid.expirationDate)\n xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>\\n`;\n if (vid.rating !== undefined) xml += ` <video:rating>${vid.rating}</video:rating>\\n`;\n if (vid.viewCount !== undefined)\n xml += ` <video:view_count>${vid.viewCount}</video:view_count>\\n`;\n if (vid.publicationDate)\n xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>\\n`;\n if (vid.familyFriendly !== undefined)\n xml += ` <video:family_friendly>${vid.familyFriendly ? 'yes' : 'no'}</video:family_friendly>\\n`;\n if (vid.live !== undefined)\n xml += ` <video:live>${vid.live ? 'yes' : 'no'}</video:live>\\n`;\n xml += ' </video:video>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildNewsXml(news: SitemapNews): string {\n let xml = ' <news:news>\\n';\n xml += ' <news:publication>\\n';\n xml += ` <news:name>${escapeXml(news.publication.name)}</news:name>\\n`;\n xml += ` <news:language>${escapeXml(news.publication.language)}</news:language>\\n`;\n xml += ' </news:publication>\\n';\n xml += ` <news:publication_date>${escapeXml(news.publicationDate)}</news:publication_date>\\n`;\n xml += ` <news:title>${escapeXml(news.title)}</news:title>\\n`;\n xml += ' </news:news>\\n';\n return xml;\n}\n\nfunction buildUrlXml(url: SitemapURL, hostname: string): string {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n let xml = ' <url>\\n';\n xml += ` <loc>${escapeXml(loc)}</loc>\\n`;\n if (url.lastmod) xml += ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) xml += ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) xml += ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n if (url.images && url.images.length > 0) xml += buildImageXml(url.images);\n if (url.videos && url.videos.length > 0) xml += buildVideoXml(url.videos);\n if (url.news) xml += buildNewsXml(url.news);\n xml += ' </url>\\n';\n return xml;\n}\n\n/**\n * Generate an XML sitemap string from a sitemap configuration.\n *\n * @example\n * ```ts\n * const xml = generateSitemap({\n * hostname: 'https://example.com',\n * urls: [\n * { loc: '/', changefreq: 'daily', priority: 1.0 },\n * { loc: '/about', changefreq: 'monthly', priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport function generateSitemap(config: SitemapConfig): string {\n const { hostname, urls } = config;\n const ns = detectNamespaces(urls);\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"';\n if (ns.image) xml += '\\n xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"';\n if (ns.video) xml += '\\n xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"';\n if (ns.news) xml += '\\n xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\"';\n xml += '>\\n';\n\n for (const url of urls) {\n xml += buildUrlXml(url, hostname);\n }\n\n xml += '</urlset>\\n';\n return xml;\n}\n","// ============================================================================\n// @power-seo/sitemap — Types\n// ============================================================================\n\nexport type {\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n SitemapConfig,\n} from '@power-seo/core';\n\n/** A sitemap entry in a sitemap index. */\nexport interface SitemapIndexEntry {\n loc: string;\n lastmod?: string;\n}\n\n/** Configuration for the sitemap index generator. */\nexport interface SitemapIndexConfig {\n sitemaps: SitemapIndexEntry[];\n}\n\n/** Result of URL validation. */\nexport interface SitemapValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/** Maximum URLs allowed per sitemap file. */\nexport const MAX_URLS_PER_SITEMAP = 50_000;\n\n/** Maximum sitemap file size in bytes (50MB). */\nexport const MAX_SITEMAP_SIZE_BYTES = 50 * 1024 * 1024;\n","// ============================================================================\n// @power-seo/sitemap — Sitemap Index Generator\n// ============================================================================\n\nimport type { SitemapConfig } from '@power-seo/core';\nimport type { SitemapIndexConfig, SitemapIndexEntry } from './types.js';\nimport { MAX_URLS_PER_SITEMAP } from './types.js';\nimport { generateSitemap } from './generator.js';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Generate a sitemap index XML string.\n *\n * @example\n * ```ts\n * const indexXml = generateSitemapIndex({\n * sitemaps: [\n * { loc: 'https://example.com/sitemap-0.xml', lastmod: '2024-01-01' },\n * { loc: 'https://example.com/sitemap-1.xml', lastmod: '2024-01-01' },\n * ],\n * });\n * ```\n */\nexport function generateSitemapIndex(config: SitemapIndexConfig): string {\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n';\n\n for (const sitemap of config.sitemaps) {\n xml += ' <sitemap>\\n';\n xml += ` <loc>${escapeXml(sitemap.loc)}</loc>\\n`;\n if (sitemap.lastmod) {\n xml += ` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>\\n`;\n }\n xml += ' </sitemap>\\n';\n }\n\n xml += '</sitemapindex>\\n';\n return xml;\n}\n\n/**\n * Split a large sitemap config into multiple sitemaps + an index.\n *\n * When a site has more than 50,000 URLs, this function splits them into\n * multiple sitemap files and returns both the individual sitemaps and\n * the index that references them.\n *\n * @example\n * ```ts\n * const { index, sitemaps } = splitSitemap({\n * hostname: 'https://example.com',\n * urls: largeUrlArray,\n * });\n * // sitemaps[0].xml, sitemaps[1].xml, etc.\n * // index = sitemap index XML\n * ```\n */\nexport function splitSitemap(\n config: SitemapConfig,\n sitemapUrlPattern = '/sitemap-{index}.xml',\n): { index: string; sitemaps: Array<{ filename: string; xml: string }> } {\n const maxPerSitemap = config.maxUrlsPerSitemap ?? MAX_URLS_PER_SITEMAP;\n const { hostname, urls } = config;\n\n if (urls.length <= maxPerSitemap) {\n const xml = generateSitemap(config);\n const filename = sitemapUrlPattern.replace('{index}', '0');\n const indexEntries: SitemapIndexEntry[] = [{ loc: `${hostname}${filename}` }];\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps: [{ filename, xml }],\n };\n }\n\n const sitemaps: Array<{ filename: string; xml: string }> = [];\n const indexEntries: SitemapIndexEntry[] = [];\n\n for (let i = 0; i < urls.length; i += maxPerSitemap) {\n const chunk = urls.slice(i, i + maxPerSitemap);\n const chunkIndex = Math.floor(i / maxPerSitemap);\n const filename = sitemapUrlPattern.replace('{index}', String(chunkIndex));\n const xml = generateSitemap({ hostname, urls: chunk });\n\n sitemaps.push({ filename, xml });\n indexEntries.push({ loc: `${hostname}${filename}` });\n }\n\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps,\n };\n}\n","// ============================================================================\n// @power-seo/sitemap — Streaming Sitemap Generator\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * A streaming sitemap generator that yields XML chunks.\n *\n * Useful for server responses where you want to stream the sitemap\n * instead of building the entire XML string in memory.\n *\n * @example\n * ```ts\n * const stream = streamSitemap('https://example.com', urls);\n * for (const chunk of stream) {\n * response.write(chunk);\n * }\n * ```\n */\nexport function* streamSitemap(\n hostname: string,\n urls: Iterable<SitemapURL>,\n): Generator<string, void, undefined> {\n yield '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n yield '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\\n';\n yield ' xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"\\n';\n yield ' xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"\\n';\n yield ' xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\">\\n';\n\n for (const url of urls) {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n yield ' <url>\\n';\n yield ` <loc>${escapeXml(loc)}</loc>\\n`;\n\n if (url.lastmod) yield ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) yield ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) yield ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n\n // Images\n if (url.images) {\n for (const img of url.images) {\n yield ' <image:image>\\n';\n yield ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) yield ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.title) yield ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n yield ' </image:image>\\n';\n }\n }\n\n // Videos\n if (url.videos) {\n for (const vid of url.videos) {\n yield ' <video:video>\\n';\n yield ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n yield ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n yield ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc)\n yield ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc)\n yield ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n yield ' </video:video>\\n';\n }\n }\n\n // News\n if (url.news) {\n yield ' <news:news>\\n';\n yield ' <news:publication>\\n';\n yield ` <news:name>${escapeXml(url.news.publication.name)}</news:name>\\n`;\n yield ` <news:language>${escapeXml(url.news.publication.language)}</news:language>\\n`;\n yield ' </news:publication>\\n';\n yield ` <news:publication_date>${escapeXml(url.news.publicationDate)}</news:publication_date>\\n`;\n yield ` <news:title>${escapeXml(url.news.title)}</news:title>\\n`;\n yield ' </news:news>\\n';\n }\n\n yield ' </url>\\n';\n }\n\n yield '</urlset>\\n';\n}\n","// ============================================================================\n// @power-seo/sitemap — URL Validation\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { isAbsoluteUrl, MAX_URL_LENGTH } from '@power-seo/core';\nimport type { SitemapValidationResult } from './types.js';\n\nconst VALID_CHANGEFREQ = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];\n\n/**\n * Validate a sitemap URL entry against the sitemap protocol spec.\n */\nexport function validateSitemapUrl(url: SitemapURL): SitemapValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // loc is required\n if (!url.loc || url.loc.trim().length === 0) {\n errors.push('URL \"loc\" is required and cannot be empty.');\n } else {\n if (!isAbsoluteUrl(url.loc)) {\n errors.push(`URL \"${url.loc}\" must be an absolute URL (starting with http:// or https://).`);\n }\n\n if (url.loc.length > 2048) {\n errors.push(`URL \"${url.loc}\" exceeds the maximum length of 2048 characters.`);\n }\n\n if (url.loc.length > MAX_URL_LENGTH) {\n warnings.push(\n `URL \"${url.loc}\" is ${url.loc.length} characters. URLs under ${MAX_URL_LENGTH} characters are recommended for SEO.`,\n );\n }\n }\n\n // lastmod validation\n if (url.lastmod) {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2})?([+-]\\d{2}:\\d{2}|Z)?)?$/;\n if (!dateRegex.test(url.lastmod)) {\n errors.push(\n `\"lastmod\" value \"${url.lastmod}\" is not a valid W3C datetime format (YYYY-MM-DD or ISO 8601).`,\n );\n }\n }\n\n // changefreq validation\n if (url.changefreq && !VALID_CHANGEFREQ.includes(url.changefreq)) {\n errors.push(\n `\"changefreq\" value \"${url.changefreq}\" is invalid. Must be one of: ${VALID_CHANGEFREQ.join(', ')}.`,\n );\n }\n\n // priority validation\n if (url.priority !== undefined) {\n if (url.priority < 0 || url.priority > 1) {\n errors.push(`\"priority\" value ${url.priority} is out of range. Must be between 0.0 and 1.0.`);\n }\n }\n\n // Image validation\n if (url.images) {\n for (let i = 0; i < url.images.length; i++) {\n const img = url.images[i]!;\n if (!img.loc || img.loc.trim().length === 0) {\n errors.push(`Image ${i + 1}: \"loc\" is required.`);\n } else if (!isAbsoluteUrl(img.loc)) {\n errors.push(`Image ${i + 1}: \"${img.loc}\" must be an absolute URL.`);\n }\n }\n if (url.images.length > 1000) {\n warnings.push(\n `URL has ${url.images.length} images. Google supports up to 1,000 images per page.`,\n );\n }\n }\n\n // Video validation\n if (url.videos) {\n for (let i = 0; i < url.videos.length; i++) {\n const vid = url.videos[i]!;\n if (!vid.title) errors.push(`Video ${i + 1}: \"title\" is required.`);\n if (!vid.description) errors.push(`Video ${i + 1}: \"description\" is required.`);\n if (!vid.thumbnailLoc) errors.push(`Video ${i + 1}: \"thumbnailLoc\" is required.`);\n if (!vid.contentLoc && !vid.playerLoc) {\n errors.push(`Video ${i + 1}: either \"contentLoc\" or \"playerLoc\" must be provided.`);\n }\n if (vid.rating !== undefined && (vid.rating < 0 || vid.rating > 5)) {\n errors.push(`Video ${i + 1}: \"rating\" must be between 0.0 and 5.0.`);\n }\n }\n }\n\n // News validation\n if (url.news) {\n if (!url.news.publication?.name) errors.push('News: \"publication.name\" is required.');\n if (!url.news.publication?.language) errors.push('News: \"publication.language\" is required.');\n if (!url.news.publicationDate) errors.push('News: \"publicationDate\" is required.');\n if (!url.news.title) errors.push('News: \"title\" is required.');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
package/dist/index.js CHANGED
@@ -23,7 +23,8 @@ function buildImageXml(images) {
23
23
  `;
24
24
  if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>
25
25
  `;
26
- if (img.geoLocation) xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>
26
+ if (img.geoLocation)
27
+ xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>
27
28
  `;
28
29
  if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>
29
30
  `;
@@ -42,23 +43,31 @@ function buildVideoXml(videos) {
42
43
  `;
43
44
  xml += ` <video:description>${escapeXml(vid.description)}</video:description>
44
45
  `;
45
- if (vid.contentLoc) xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>
46
+ if (vid.contentLoc)
47
+ xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>
46
48
  `;
47
- if (vid.playerLoc) xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>
49
+ if (vid.playerLoc)
50
+ xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>
48
51
  `;
49
- if (vid.duration !== void 0) xml += ` <video:duration>${vid.duration}</video:duration>
52
+ if (vid.duration !== void 0)
53
+ xml += ` <video:duration>${vid.duration}</video:duration>
50
54
  `;
51
- if (vid.expirationDate) xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>
55
+ if (vid.expirationDate)
56
+ xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>
52
57
  `;
53
58
  if (vid.rating !== void 0) xml += ` <video:rating>${vid.rating}</video:rating>
54
59
  `;
55
- if (vid.viewCount !== void 0) xml += ` <video:view_count>${vid.viewCount}</video:view_count>
60
+ if (vid.viewCount !== void 0)
61
+ xml += ` <video:view_count>${vid.viewCount}</video:view_count>
56
62
  `;
57
- if (vid.publicationDate) xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>
63
+ if (vid.publicationDate)
64
+ xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>
58
65
  `;
59
- if (vid.familyFriendly !== void 0) xml += ` <video:family_friendly>${vid.familyFriendly ? "yes" : "no"}</video:family_friendly>
66
+ if (vid.familyFriendly !== void 0)
67
+ xml += ` <video:family_friendly>${vid.familyFriendly ? "yes" : "no"}</video:family_friendly>
60
68
  `;
61
- if (vid.live !== void 0) xml += ` <video:live>${vid.live ? "yes" : "no"}</video:live>
69
+ if (vid.live !== void 0)
70
+ xml += ` <video:live>${vid.live ? "yes" : "no"}</video:live>
62
71
  `;
63
72
  xml += " </video:video>\n";
64
73
  return xml;
@@ -204,9 +213,11 @@ function* streamSitemap(hostname, urls) {
204
213
  `;
205
214
  yield ` <video:description>${escapeXml3(vid.description)}</video:description>
206
215
  `;
207
- if (vid.contentLoc) yield ` <video:content_loc>${escapeXml3(vid.contentLoc)}</video:content_loc>
216
+ if (vid.contentLoc)
217
+ yield ` <video:content_loc>${escapeXml3(vid.contentLoc)}</video:content_loc>
208
218
  `;
209
- if (vid.playerLoc) yield ` <video:player_loc>${escapeXml3(vid.playerLoc)}</video:player_loc>
219
+ if (vid.playerLoc)
220
+ yield ` <video:player_loc>${escapeXml3(vid.playerLoc)}</video:player_loc>
210
221
  `;
211
222
  yield " </video:video>\n";
212
223
  }
@@ -276,7 +287,9 @@ function validateSitemapUrl(url) {
276
287
  }
277
288
  }
278
289
  if (url.images.length > 1e3) {
279
- warnings.push(`URL has ${url.images.length} images. Google supports up to 1,000 images per page.`);
290
+ warnings.push(
291
+ `URL has ${url.images.length} images. Google supports up to 1,000 images per page.`
292
+ );
280
293
  }
281
294
  }
282
295
  if (url.videos) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generator.ts","../src/types.ts","../src/sitemap-index.ts","../src/stream.ts","../src/validate.ts"],"names":["escapeXml","indexEntries","normalizeUrl"],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/sitemap — XML Sitemap Generator\n// ============================================================================\n\nimport type { SitemapConfig, SitemapURL, SitemapImage, SitemapVideo, SitemapNews } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/** Determine which namespace extensions are needed. */\nfunction detectNamespaces(urls: SitemapURL[]): { image: boolean; video: boolean; news: boolean } {\n let image = false;\n let video = false;\n let news = false;\n for (const url of urls) {\n if (url.images && url.images.length > 0) image = true;\n if (url.videos && url.videos.length > 0) video = true;\n if (url.news) news = true;\n if (image && video && news) break;\n }\n return { image, video, news };\n}\n\nfunction buildImageXml(images: SitemapImage[]): string {\n return images\n .map((img) => {\n let xml = ' <image:image>\\n';\n xml += ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.geoLocation) xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>\\n`;\n if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n if (img.license) xml += ` <image:license>${escapeXml(img.license)}</image:license>\\n`;\n xml += ' </image:image>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildVideoXml(videos: SitemapVideo[]): string {\n return videos\n .map((vid) => {\n let xml = ' <video:video>\\n';\n xml += ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n xml += ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n xml += ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc) xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc) xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n if (vid.duration !== undefined) xml += ` <video:duration>${vid.duration}</video:duration>\\n`;\n if (vid.expirationDate) xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>\\n`;\n if (vid.rating !== undefined) xml += ` <video:rating>${vid.rating}</video:rating>\\n`;\n if (vid.viewCount !== undefined) xml += ` <video:view_count>${vid.viewCount}</video:view_count>\\n`;\n if (vid.publicationDate) xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>\\n`;\n if (vid.familyFriendly !== undefined) xml += ` <video:family_friendly>${vid.familyFriendly ? 'yes' : 'no'}</video:family_friendly>\\n`;\n if (vid.live !== undefined) xml += ` <video:live>${vid.live ? 'yes' : 'no'}</video:live>\\n`;\n xml += ' </video:video>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildNewsXml(news: SitemapNews): string {\n let xml = ' <news:news>\\n';\n xml += ' <news:publication>\\n';\n xml += ` <news:name>${escapeXml(news.publication.name)}</news:name>\\n`;\n xml += ` <news:language>${escapeXml(news.publication.language)}</news:language>\\n`;\n xml += ' </news:publication>\\n';\n xml += ` <news:publication_date>${escapeXml(news.publicationDate)}</news:publication_date>\\n`;\n xml += ` <news:title>${escapeXml(news.title)}</news:title>\\n`;\n xml += ' </news:news>\\n';\n return xml;\n}\n\nfunction buildUrlXml(url: SitemapURL, hostname: string): string {\n const loc = url.loc.startsWith('http') ? url.loc : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n let xml = ' <url>\\n';\n xml += ` <loc>${escapeXml(loc)}</loc>\\n`;\n if (url.lastmod) xml += ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) xml += ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) xml += ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n if (url.images && url.images.length > 0) xml += buildImageXml(url.images);\n if (url.videos && url.videos.length > 0) xml += buildVideoXml(url.videos);\n if (url.news) xml += buildNewsXml(url.news);\n xml += ' </url>\\n';\n return xml;\n}\n\n/**\n * Generate an XML sitemap string from a sitemap configuration.\n *\n * @example\n * ```ts\n * const xml = generateSitemap({\n * hostname: 'https://example.com',\n * urls: [\n * { loc: '/', changefreq: 'daily', priority: 1.0 },\n * { loc: '/about', changefreq: 'monthly', priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport function generateSitemap(config: SitemapConfig): string {\n const { hostname, urls } = config;\n const ns = detectNamespaces(urls);\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"';\n if (ns.image) xml += '\\n xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"';\n if (ns.video) xml += '\\n xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"';\n if (ns.news) xml += '\\n xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\"';\n xml += '>\\n';\n\n for (const url of urls) {\n xml += buildUrlXml(url, hostname);\n }\n\n xml += '</urlset>\\n';\n return xml;\n}\n","// ============================================================================\n// @power-seo/sitemap — Types\n// ============================================================================\n\nexport type {\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n SitemapConfig,\n} from '@power-seo/core';\n\n/** A sitemap entry in a sitemap index. */\nexport interface SitemapIndexEntry {\n loc: string;\n lastmod?: string;\n}\n\n/** Configuration for the sitemap index generator. */\nexport interface SitemapIndexConfig {\n sitemaps: SitemapIndexEntry[];\n}\n\n/** Result of URL validation. */\nexport interface SitemapValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/** Maximum URLs allowed per sitemap file. */\nexport const MAX_URLS_PER_SITEMAP = 50_000;\n\n/** Maximum sitemap file size in bytes (50MB). */\nexport const MAX_SITEMAP_SIZE_BYTES = 50 * 1024 * 1024;\n","// ============================================================================\n// @power-seo/sitemap — Sitemap Index Generator\n// ============================================================================\n\nimport type { SitemapConfig } from '@power-seo/core';\nimport type { SitemapIndexConfig, SitemapIndexEntry } from './types.js';\nimport { MAX_URLS_PER_SITEMAP } from './types.js';\nimport { generateSitemap } from './generator.js';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Generate a sitemap index XML string.\n *\n * @example\n * ```ts\n * const indexXml = generateSitemapIndex({\n * sitemaps: [\n * { loc: 'https://example.com/sitemap-0.xml', lastmod: '2024-01-01' },\n * { loc: 'https://example.com/sitemap-1.xml', lastmod: '2024-01-01' },\n * ],\n * });\n * ```\n */\nexport function generateSitemapIndex(config: SitemapIndexConfig): string {\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n';\n\n for (const sitemap of config.sitemaps) {\n xml += ' <sitemap>\\n';\n xml += ` <loc>${escapeXml(sitemap.loc)}</loc>\\n`;\n if (sitemap.lastmod) {\n xml += ` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>\\n`;\n }\n xml += ' </sitemap>\\n';\n }\n\n xml += '</sitemapindex>\\n';\n return xml;\n}\n\n/**\n * Split a large sitemap config into multiple sitemaps + an index.\n *\n * When a site has more than 50,000 URLs, this function splits them into\n * multiple sitemap files and returns both the individual sitemaps and\n * the index that references them.\n *\n * @example\n * ```ts\n * const { index, sitemaps } = splitSitemap({\n * hostname: 'https://example.com',\n * urls: largeUrlArray,\n * });\n * // sitemaps[0].xml, sitemaps[1].xml, etc.\n * // index = sitemap index XML\n * ```\n */\nexport function splitSitemap(\n config: SitemapConfig,\n sitemapUrlPattern = '/sitemap-{index}.xml',\n): { index: string; sitemaps: Array<{ filename: string; xml: string }> } {\n const maxPerSitemap = config.maxUrlsPerSitemap ?? MAX_URLS_PER_SITEMAP;\n const { hostname, urls } = config;\n\n if (urls.length <= maxPerSitemap) {\n const xml = generateSitemap(config);\n const filename = sitemapUrlPattern.replace('{index}', '0');\n const indexEntries: SitemapIndexEntry[] = [{ loc: `${hostname}${filename}` }];\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps: [{ filename, xml }],\n };\n }\n\n const sitemaps: Array<{ filename: string; xml: string }> = [];\n const indexEntries: SitemapIndexEntry[] = [];\n\n for (let i = 0; i < urls.length; i += maxPerSitemap) {\n const chunk = urls.slice(i, i + maxPerSitemap);\n const chunkIndex = Math.floor(i / maxPerSitemap);\n const filename = sitemapUrlPattern.replace('{index}', String(chunkIndex));\n const xml = generateSitemap({ hostname, urls: chunk });\n\n sitemaps.push({ filename, xml });\n indexEntries.push({ loc: `${hostname}${filename}` });\n }\n\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps,\n };\n}\n","// ============================================================================\n// @power-seo/sitemap — Streaming Sitemap Generator\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * A streaming sitemap generator that yields XML chunks.\n *\n * Useful for server responses where you want to stream the sitemap\n * instead of building the entire XML string in memory.\n *\n * @example\n * ```ts\n * const stream = streamSitemap('https://example.com', urls);\n * for (const chunk of stream) {\n * response.write(chunk);\n * }\n * ```\n */\nexport function* streamSitemap(\n hostname: string,\n urls: Iterable<SitemapURL>,\n): Generator<string, void, undefined> {\n yield '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n yield '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\\n';\n yield ' xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"\\n';\n yield ' xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"\\n';\n yield ' xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\">\\n';\n\n for (const url of urls) {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n yield ' <url>\\n';\n yield ` <loc>${escapeXml(loc)}</loc>\\n`;\n\n if (url.lastmod) yield ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) yield ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) yield ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n\n // Images\n if (url.images) {\n for (const img of url.images) {\n yield ' <image:image>\\n';\n yield ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) yield ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.title) yield ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n yield ' </image:image>\\n';\n }\n }\n\n // Videos\n if (url.videos) {\n for (const vid of url.videos) {\n yield ' <video:video>\\n';\n yield ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n yield ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n yield ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc) yield ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc) yield ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n yield ' </video:video>\\n';\n }\n }\n\n // News\n if (url.news) {\n yield ' <news:news>\\n';\n yield ' <news:publication>\\n';\n yield ` <news:name>${escapeXml(url.news.publication.name)}</news:name>\\n`;\n yield ` <news:language>${escapeXml(url.news.publication.language)}</news:language>\\n`;\n yield ' </news:publication>\\n';\n yield ` <news:publication_date>${escapeXml(url.news.publicationDate)}</news:publication_date>\\n`;\n yield ` <news:title>${escapeXml(url.news.title)}</news:title>\\n`;\n yield ' </news:news>\\n';\n }\n\n yield ' </url>\\n';\n }\n\n yield '</urlset>\\n';\n}\n","// ============================================================================\n// @power-seo/sitemap — URL Validation\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { isAbsoluteUrl, MAX_URL_LENGTH } from '@power-seo/core';\nimport type { SitemapValidationResult } from './types.js';\n\nconst VALID_CHANGEFREQ = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];\n\n/**\n * Validate a sitemap URL entry against the sitemap protocol spec.\n */\nexport function validateSitemapUrl(url: SitemapURL): SitemapValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // loc is required\n if (!url.loc || url.loc.trim().length === 0) {\n errors.push('URL \"loc\" is required and cannot be empty.');\n } else {\n if (!isAbsoluteUrl(url.loc)) {\n errors.push(`URL \"${url.loc}\" must be an absolute URL (starting with http:// or https://).`);\n }\n\n if (url.loc.length > 2048) {\n errors.push(`URL \"${url.loc}\" exceeds the maximum length of 2048 characters.`);\n }\n\n if (url.loc.length > MAX_URL_LENGTH) {\n warnings.push(\n `URL \"${url.loc}\" is ${url.loc.length} characters. URLs under ${MAX_URL_LENGTH} characters are recommended for SEO.`,\n );\n }\n }\n\n // lastmod validation\n if (url.lastmod) {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2})?([+-]\\d{2}:\\d{2}|Z)?)?$/;\n if (!dateRegex.test(url.lastmod)) {\n errors.push(\n `\"lastmod\" value \"${url.lastmod}\" is not a valid W3C datetime format (YYYY-MM-DD or ISO 8601).`,\n );\n }\n }\n\n // changefreq validation\n if (url.changefreq && !VALID_CHANGEFREQ.includes(url.changefreq)) {\n errors.push(\n `\"changefreq\" value \"${url.changefreq}\" is invalid. Must be one of: ${VALID_CHANGEFREQ.join(', ')}.`,\n );\n }\n\n // priority validation\n if (url.priority !== undefined) {\n if (url.priority < 0 || url.priority > 1) {\n errors.push(`\"priority\" value ${url.priority} is out of range. Must be between 0.0 and 1.0.`);\n }\n }\n\n // Image validation\n if (url.images) {\n for (let i = 0; i < url.images.length; i++) {\n const img = url.images[i]!;\n if (!img.loc || img.loc.trim().length === 0) {\n errors.push(`Image ${i + 1}: \"loc\" is required.`);\n } else if (!isAbsoluteUrl(img.loc)) {\n errors.push(`Image ${i + 1}: \"${img.loc}\" must be an absolute URL.`);\n }\n }\n if (url.images.length > 1000) {\n warnings.push(`URL has ${url.images.length} images. Google supports up to 1,000 images per page.`);\n }\n }\n\n // Video validation\n if (url.videos) {\n for (let i = 0; i < url.videos.length; i++) {\n const vid = url.videos[i]!;\n if (!vid.title) errors.push(`Video ${i + 1}: \"title\" is required.`);\n if (!vid.description) errors.push(`Video ${i + 1}: \"description\" is required.`);\n if (!vid.thumbnailLoc) errors.push(`Video ${i + 1}: \"thumbnailLoc\" is required.`);\n if (!vid.contentLoc && !vid.playerLoc) {\n errors.push(`Video ${i + 1}: either \"contentLoc\" or \"playerLoc\" must be provided.`);\n }\n if (vid.rating !== undefined && (vid.rating < 0 || vid.rating > 5)) {\n errors.push(`Video ${i + 1}: \"rating\" must be between 0.0 and 5.0.`);\n }\n }\n }\n\n // News validation\n if (url.news) {\n if (!url.news.publication?.name) errors.push('News: \"publication.name\" is required.');\n if (!url.news.publication?.language) errors.push('News: \"publication.language\" is required.');\n if (!url.news.publicationDate) errors.push('News: \"publicationDate\" is required.');\n if (!url.news.title) errors.push('News: \"title\" is required.');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/generator.ts","../src/types.ts","../src/sitemap-index.ts","../src/stream.ts","../src/validate.ts"],"names":["escapeXml","indexEntries","normalizeUrl"],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/sitemap — XML Sitemap Generator\n// ============================================================================\n\nimport type {\n SitemapConfig,\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n} from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/** Determine which namespace extensions are needed. */\nfunction detectNamespaces(urls: SitemapURL[]): { image: boolean; video: boolean; news: boolean } {\n let image = false;\n let video = false;\n let news = false;\n for (const url of urls) {\n if (url.images && url.images.length > 0) image = true;\n if (url.videos && url.videos.length > 0) video = true;\n if (url.news) news = true;\n if (image && video && news) break;\n }\n return { image, video, news };\n}\n\nfunction buildImageXml(images: SitemapImage[]): string {\n return images\n .map((img) => {\n let xml = ' <image:image>\\n';\n xml += ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) xml += ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.geoLocation)\n xml += ` <image:geo_location>${escapeXml(img.geoLocation)}</image:geo_location>\\n`;\n if (img.title) xml += ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n if (img.license) xml += ` <image:license>${escapeXml(img.license)}</image:license>\\n`;\n xml += ' </image:image>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildVideoXml(videos: SitemapVideo[]): string {\n return videos\n .map((vid) => {\n let xml = ' <video:video>\\n';\n xml += ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n xml += ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n xml += ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc)\n xml += ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc)\n xml += ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n if (vid.duration !== undefined)\n xml += ` <video:duration>${vid.duration}</video:duration>\\n`;\n if (vid.expirationDate)\n xml += ` <video:expiration_date>${escapeXml(vid.expirationDate)}</video:expiration_date>\\n`;\n if (vid.rating !== undefined) xml += ` <video:rating>${vid.rating}</video:rating>\\n`;\n if (vid.viewCount !== undefined)\n xml += ` <video:view_count>${vid.viewCount}</video:view_count>\\n`;\n if (vid.publicationDate)\n xml += ` <video:publication_date>${escapeXml(vid.publicationDate)}</video:publication_date>\\n`;\n if (vid.familyFriendly !== undefined)\n xml += ` <video:family_friendly>${vid.familyFriendly ? 'yes' : 'no'}</video:family_friendly>\\n`;\n if (vid.live !== undefined)\n xml += ` <video:live>${vid.live ? 'yes' : 'no'}</video:live>\\n`;\n xml += ' </video:video>\\n';\n return xml;\n })\n .join('');\n}\n\nfunction buildNewsXml(news: SitemapNews): string {\n let xml = ' <news:news>\\n';\n xml += ' <news:publication>\\n';\n xml += ` <news:name>${escapeXml(news.publication.name)}</news:name>\\n`;\n xml += ` <news:language>${escapeXml(news.publication.language)}</news:language>\\n`;\n xml += ' </news:publication>\\n';\n xml += ` <news:publication_date>${escapeXml(news.publicationDate)}</news:publication_date>\\n`;\n xml += ` <news:title>${escapeXml(news.title)}</news:title>\\n`;\n xml += ' </news:news>\\n';\n return xml;\n}\n\nfunction buildUrlXml(url: SitemapURL, hostname: string): string {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n let xml = ' <url>\\n';\n xml += ` <loc>${escapeXml(loc)}</loc>\\n`;\n if (url.lastmod) xml += ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) xml += ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) xml += ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n if (url.images && url.images.length > 0) xml += buildImageXml(url.images);\n if (url.videos && url.videos.length > 0) xml += buildVideoXml(url.videos);\n if (url.news) xml += buildNewsXml(url.news);\n xml += ' </url>\\n';\n return xml;\n}\n\n/**\n * Generate an XML sitemap string from a sitemap configuration.\n *\n * @example\n * ```ts\n * const xml = generateSitemap({\n * hostname: 'https://example.com',\n * urls: [\n * { loc: '/', changefreq: 'daily', priority: 1.0 },\n * { loc: '/about', changefreq: 'monthly', priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport function generateSitemap(config: SitemapConfig): string {\n const { hostname, urls } = config;\n const ns = detectNamespaces(urls);\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"';\n if (ns.image) xml += '\\n xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"';\n if (ns.video) xml += '\\n xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"';\n if (ns.news) xml += '\\n xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\"';\n xml += '>\\n';\n\n for (const url of urls) {\n xml += buildUrlXml(url, hostname);\n }\n\n xml += '</urlset>\\n';\n return xml;\n}\n","// ============================================================================\n// @power-seo/sitemap — Types\n// ============================================================================\n\nexport type {\n SitemapURL,\n SitemapImage,\n SitemapVideo,\n SitemapNews,\n SitemapConfig,\n} from '@power-seo/core';\n\n/** A sitemap entry in a sitemap index. */\nexport interface SitemapIndexEntry {\n loc: string;\n lastmod?: string;\n}\n\n/** Configuration for the sitemap index generator. */\nexport interface SitemapIndexConfig {\n sitemaps: SitemapIndexEntry[];\n}\n\n/** Result of URL validation. */\nexport interface SitemapValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/** Maximum URLs allowed per sitemap file. */\nexport const MAX_URLS_PER_SITEMAP = 50_000;\n\n/** Maximum sitemap file size in bytes (50MB). */\nexport const MAX_SITEMAP_SIZE_BYTES = 50 * 1024 * 1024;\n","// ============================================================================\n// @power-seo/sitemap — Sitemap Index Generator\n// ============================================================================\n\nimport type { SitemapConfig } from '@power-seo/core';\nimport type { SitemapIndexConfig, SitemapIndexEntry } from './types.js';\nimport { MAX_URLS_PER_SITEMAP } from './types.js';\nimport { generateSitemap } from './generator.js';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Generate a sitemap index XML string.\n *\n * @example\n * ```ts\n * const indexXml = generateSitemapIndex({\n * sitemaps: [\n * { loc: 'https://example.com/sitemap-0.xml', lastmod: '2024-01-01' },\n * { loc: 'https://example.com/sitemap-1.xml', lastmod: '2024-01-01' },\n * ],\n * });\n * ```\n */\nexport function generateSitemapIndex(config: SitemapIndexConfig): string {\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n xml += '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n';\n\n for (const sitemap of config.sitemaps) {\n xml += ' <sitemap>\\n';\n xml += ` <loc>${escapeXml(sitemap.loc)}</loc>\\n`;\n if (sitemap.lastmod) {\n xml += ` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>\\n`;\n }\n xml += ' </sitemap>\\n';\n }\n\n xml += '</sitemapindex>\\n';\n return xml;\n}\n\n/**\n * Split a large sitemap config into multiple sitemaps + an index.\n *\n * When a site has more than 50,000 URLs, this function splits them into\n * multiple sitemap files and returns both the individual sitemaps and\n * the index that references them.\n *\n * @example\n * ```ts\n * const { index, sitemaps } = splitSitemap({\n * hostname: 'https://example.com',\n * urls: largeUrlArray,\n * });\n * // sitemaps[0].xml, sitemaps[1].xml, etc.\n * // index = sitemap index XML\n * ```\n */\nexport function splitSitemap(\n config: SitemapConfig,\n sitemapUrlPattern = '/sitemap-{index}.xml',\n): { index: string; sitemaps: Array<{ filename: string; xml: string }> } {\n const maxPerSitemap = config.maxUrlsPerSitemap ?? MAX_URLS_PER_SITEMAP;\n const { hostname, urls } = config;\n\n if (urls.length <= maxPerSitemap) {\n const xml = generateSitemap(config);\n const filename = sitemapUrlPattern.replace('{index}', '0');\n const indexEntries: SitemapIndexEntry[] = [{ loc: `${hostname}${filename}` }];\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps: [{ filename, xml }],\n };\n }\n\n const sitemaps: Array<{ filename: string; xml: string }> = [];\n const indexEntries: SitemapIndexEntry[] = [];\n\n for (let i = 0; i < urls.length; i += maxPerSitemap) {\n const chunk = urls.slice(i, i + maxPerSitemap);\n const chunkIndex = Math.floor(i / maxPerSitemap);\n const filename = sitemapUrlPattern.replace('{index}', String(chunkIndex));\n const xml = generateSitemap({ hostname, urls: chunk });\n\n sitemaps.push({ filename, xml });\n indexEntries.push({ loc: `${hostname}${filename}` });\n }\n\n return {\n index: generateSitemapIndex({ sitemaps: indexEntries }),\n sitemaps,\n };\n}\n","// ============================================================================\n// @power-seo/sitemap — Streaming Sitemap Generator\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { normalizeUrl } from '@power-seo/core';\n\n/** Escape special XML characters. */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * A streaming sitemap generator that yields XML chunks.\n *\n * Useful for server responses where you want to stream the sitemap\n * instead of building the entire XML string in memory.\n *\n * @example\n * ```ts\n * const stream = streamSitemap('https://example.com', urls);\n * for (const chunk of stream) {\n * response.write(chunk);\n * }\n * ```\n */\nexport function* streamSitemap(\n hostname: string,\n urls: Iterable<SitemapURL>,\n): Generator<string, void, undefined> {\n yield '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n yield '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\\n';\n yield ' xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"\\n';\n yield ' xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"\\n';\n yield ' xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\">\\n';\n\n for (const url of urls) {\n const loc = url.loc.startsWith('http')\n ? url.loc\n : normalizeUrl(`${hostname}${url.loc.startsWith('/') ? '' : '/'}${url.loc}`);\n\n yield ' <url>\\n';\n yield ` <loc>${escapeXml(loc)}</loc>\\n`;\n\n if (url.lastmod) yield ` <lastmod>${escapeXml(url.lastmod)}</lastmod>\\n`;\n if (url.changefreq) yield ` <changefreq>${url.changefreq}</changefreq>\\n`;\n if (url.priority !== undefined) yield ` <priority>${url.priority.toFixed(1)}</priority>\\n`;\n\n // Images\n if (url.images) {\n for (const img of url.images) {\n yield ' <image:image>\\n';\n yield ` <image:loc>${escapeXml(img.loc)}</image:loc>\\n`;\n if (img.caption) yield ` <image:caption>${escapeXml(img.caption)}</image:caption>\\n`;\n if (img.title) yield ` <image:title>${escapeXml(img.title)}</image:title>\\n`;\n yield ' </image:image>\\n';\n }\n }\n\n // Videos\n if (url.videos) {\n for (const vid of url.videos) {\n yield ' <video:video>\\n';\n yield ` <video:thumbnail_loc>${escapeXml(vid.thumbnailLoc)}</video:thumbnail_loc>\\n`;\n yield ` <video:title>${escapeXml(vid.title)}</video:title>\\n`;\n yield ` <video:description>${escapeXml(vid.description)}</video:description>\\n`;\n if (vid.contentLoc)\n yield ` <video:content_loc>${escapeXml(vid.contentLoc)}</video:content_loc>\\n`;\n if (vid.playerLoc)\n yield ` <video:player_loc>${escapeXml(vid.playerLoc)}</video:player_loc>\\n`;\n yield ' </video:video>\\n';\n }\n }\n\n // News\n if (url.news) {\n yield ' <news:news>\\n';\n yield ' <news:publication>\\n';\n yield ` <news:name>${escapeXml(url.news.publication.name)}</news:name>\\n`;\n yield ` <news:language>${escapeXml(url.news.publication.language)}</news:language>\\n`;\n yield ' </news:publication>\\n';\n yield ` <news:publication_date>${escapeXml(url.news.publicationDate)}</news:publication_date>\\n`;\n yield ` <news:title>${escapeXml(url.news.title)}</news:title>\\n`;\n yield ' </news:news>\\n';\n }\n\n yield ' </url>\\n';\n }\n\n yield '</urlset>\\n';\n}\n","// ============================================================================\n// @power-seo/sitemap — URL Validation\n// ============================================================================\n\nimport type { SitemapURL } from '@power-seo/core';\nimport { isAbsoluteUrl, MAX_URL_LENGTH } from '@power-seo/core';\nimport type { SitemapValidationResult } from './types.js';\n\nconst VALID_CHANGEFREQ = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];\n\n/**\n * Validate a sitemap URL entry against the sitemap protocol spec.\n */\nexport function validateSitemapUrl(url: SitemapURL): SitemapValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // loc is required\n if (!url.loc || url.loc.trim().length === 0) {\n errors.push('URL \"loc\" is required and cannot be empty.');\n } else {\n if (!isAbsoluteUrl(url.loc)) {\n errors.push(`URL \"${url.loc}\" must be an absolute URL (starting with http:// or https://).`);\n }\n\n if (url.loc.length > 2048) {\n errors.push(`URL \"${url.loc}\" exceeds the maximum length of 2048 characters.`);\n }\n\n if (url.loc.length > MAX_URL_LENGTH) {\n warnings.push(\n `URL \"${url.loc}\" is ${url.loc.length} characters. URLs under ${MAX_URL_LENGTH} characters are recommended for SEO.`,\n );\n }\n }\n\n // lastmod validation\n if (url.lastmod) {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2})?([+-]\\d{2}:\\d{2}|Z)?)?$/;\n if (!dateRegex.test(url.lastmod)) {\n errors.push(\n `\"lastmod\" value \"${url.lastmod}\" is not a valid W3C datetime format (YYYY-MM-DD or ISO 8601).`,\n );\n }\n }\n\n // changefreq validation\n if (url.changefreq && !VALID_CHANGEFREQ.includes(url.changefreq)) {\n errors.push(\n `\"changefreq\" value \"${url.changefreq}\" is invalid. Must be one of: ${VALID_CHANGEFREQ.join(', ')}.`,\n );\n }\n\n // priority validation\n if (url.priority !== undefined) {\n if (url.priority < 0 || url.priority > 1) {\n errors.push(`\"priority\" value ${url.priority} is out of range. Must be between 0.0 and 1.0.`);\n }\n }\n\n // Image validation\n if (url.images) {\n for (let i = 0; i < url.images.length; i++) {\n const img = url.images[i]!;\n if (!img.loc || img.loc.trim().length === 0) {\n errors.push(`Image ${i + 1}: \"loc\" is required.`);\n } else if (!isAbsoluteUrl(img.loc)) {\n errors.push(`Image ${i + 1}: \"${img.loc}\" must be an absolute URL.`);\n }\n }\n if (url.images.length > 1000) {\n warnings.push(\n `URL has ${url.images.length} images. Google supports up to 1,000 images per page.`,\n );\n }\n }\n\n // Video validation\n if (url.videos) {\n for (let i = 0; i < url.videos.length; i++) {\n const vid = url.videos[i]!;\n if (!vid.title) errors.push(`Video ${i + 1}: \"title\" is required.`);\n if (!vid.description) errors.push(`Video ${i + 1}: \"description\" is required.`);\n if (!vid.thumbnailLoc) errors.push(`Video ${i + 1}: \"thumbnailLoc\" is required.`);\n if (!vid.contentLoc && !vid.playerLoc) {\n errors.push(`Video ${i + 1}: either \"contentLoc\" or \"playerLoc\" must be provided.`);\n }\n if (vid.rating !== undefined && (vid.rating < 0 || vid.rating > 5)) {\n errors.push(`Video ${i + 1}: \"rating\" must be between 0.0 and 5.0.`);\n }\n }\n }\n\n // News validation\n if (url.news) {\n if (!url.news.publication?.name) errors.push('News: \"publication.name\" is required.');\n if (!url.news.publication?.language) errors.push('News: \"publication.language\" is required.');\n if (!url.news.publicationDate) errors.push('News: \"publicationDate\" is required.');\n if (!url.news.title) errors.push('News: \"title\" is required.');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@power-seo/sitemap",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "XML sitemap generation, streaming, and validation with image, video, and news support",
5
5
  "license": "MIT",
6
6
  "type": "module",