{"version":3,"file":"generateSitemap.mjs","names":[],"sources":["../../../src/localization/generateSitemap.ts"],"sourcesContent":["import type { RoutingConfig } from '@intlayer/types/config';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { getMultilingualUrls } from './getMultilingualUrls';\nimport { type RoutingOptions, resolveRoutingConfig } from './getPrefix';\n\nexport type SitemapUrlEntry = {\n  /** The canonical path, e.g. '/dashboard' */\n  path: string;\n  changefreq?: string;\n  priority?: number;\n  /** ISO date string, e.g. '2024-01-15' */\n  lastmod?: string;\n};\n\nexport type GenerateSitemapOptions = {\n  /** Base site URL without trailing slash, e.g. 'https://example.com' */\n  siteUrl: string;\n  /**\n   * Whether to include xhtml:link alternate tags for multilingual support.\n   *\n   * When enabled, alternate links are only generated for modes where URLs\n   * differ per locale:\n   * - 'prefix-no-default': included\n   * - 'prefix-all': included\n   * - 'search-params': included\n   * - 'no-prefix': excluded (all locales share the same URL)\n   *\n   * @default true\n   */\n  xhtmlLinks?: boolean;\n  locales?: LocalesValues[];\n  defaultLocale?: LocalesValues;\n  mode?: RoutingConfig['mode'];\n  rewrite?: RoutingConfig['rewrite'];\n};\n\n/**\n * Returns whether xhtml:link alternate tags should be generated for the given routing mode.\n *\n * Alternates are meaningful only when locale URLs are distinct:\n * - 'no-prefix' produces identical URLs for all locales → no alternates\n * - all other modes produce distinct URLs → alternates are generated\n */\nconst shouldIncludeAlternates = (\n  mode: RoutingConfig['mode'],\n  xhtmlLinks: boolean\n): boolean => xhtmlLinks && mode !== 'no-prefix';\n\n/**\n * Generates a single `<url>` sitemap entry for the given path.\n *\n * Example:\n *\n * ```ts\n * generateSitemapUrl('/dashboard', {\n *   siteUrl: 'https://example.com',\n *   changefreq: 'weekly',\n *   priority: 0.8,\n *   xhtmlLinks: true,\n *   locales: ['en', 'fr'],\n *   defaultLocale: 'en',\n *   mode: 'prefix-no-default',\n * });\n * // Returns:\n * //   <url>\n * //     <loc>https://example.com/dashboard</loc>\n * //     <changefreq>weekly</changefreq>\n * //     <priority>0.8</priority>\n * //     <xhtml:link rel=\"alternate\" hrefLang=\"en\" href=\"https://example.com/dashboard\"/>\n * //     <xhtml:link rel=\"alternate\" hrefLang=\"fr\" href=\"https://example.com/fr/dashboard\"/>\n * //     <xhtml:link rel=\"alternate\" hrefLang=\"x-default\" href=\"https://example.com/dashboard\"/>\n * //   </url>\n * ```\n *\n * @param path - The canonical path to generate the entry for.\n * @param options - Configuration options.\n * @returns A `<url>` XML string.\n */\nexport const generateSitemapUrl = (\n  path: string,\n  options: SitemapUrlEntry & GenerateSitemapOptions\n): string => {\n  const {\n    siteUrl,\n    changefreq,\n    priority,\n    lastmod,\n    xhtmlLinks = true,\n    ...routingOptions\n  } = options;\n\n  const resolved = resolveRoutingConfig(routingOptions as RoutingOptions);\n  const fullUrl = `${siteUrl}${path}`;\n\n  const lines: (string | null)[] = [\n    '  <url>',\n    `    <loc>${fullUrl}</loc>`,\n    lastmod ? `    <lastmod>${lastmod}</lastmod>` : null,\n    changefreq ? `    <changefreq>${changefreq}</changefreq>` : null,\n    priority !== undefined ? `    <priority>${priority}</priority>` : null,\n  ];\n\n  const hasFileExtension = /\\.[a-z0-9]+$/i.test(path);\n  if (shouldIncludeAlternates(resolved.mode, xhtmlLinks) && !hasFileExtension) {\n    const alternates = getMultilingualUrls(\n      path,\n      routingOptions as RoutingOptions\n    );\n\n    for (const [lang, localePath] of Object.entries(alternates)) {\n      lines.push(\n        `    <xhtml:link rel=\"alternate\" hreflang=\"${lang}\" href=\"${siteUrl}${localePath}\"/>`\n      );\n    }\n\n    lines.push(\n      `    <xhtml:link rel=\"alternate\" hreflang=\"x-default\" href=\"${fullUrl}\"/>`\n    );\n  }\n\n  lines.push('  </url>');\n\n  return lines.filter(Boolean).join('\\n');\n};\n\n/**\n * Generates a full XML sitemap string from an array of URL entries.\n *\n * Automatically adds `xmlns:xhtml` to the `<urlset>` declaration when\n * xhtml:link alternate tags are included.\n *\n * Example:\n *\n * ```ts\n * generateSitemap(\n *   [\n *     { path: '/', changefreq: 'daily', priority: 1.0 },\n *     { path: '/about', changefreq: 'monthly', priority: 0.5 },\n *   ],\n *   {\n *     siteUrl: 'https://example.com',\n *     xhtmlLinks: true,\n *     locales: ['en', 'fr'],\n *     defaultLocale: 'en',\n *     mode: 'prefix-no-default',\n *   }\n * );\n * ```\n *\n * @param entries - Array of URL entries to include in the sitemap.\n * @param options - Sitemap generation options.\n * @returns A full XML sitemap string.\n */\nexport const generateSitemap = (\n  entries: SitemapUrlEntry[],\n  options: GenerateSitemapOptions\n): string => {\n  const { siteUrl, xhtmlLinks = true, ...routingOptions } = options;\n\n  const resolved = resolveRoutingConfig(routingOptions as RoutingOptions);\n  const includeAlternates = shouldIncludeAlternates(resolved.mode, xhtmlLinks);\n\n  const xmlEntries = entries.map((entry) =>\n    generateSitemapUrl(entry.path, {\n      ...entry,\n      siteUrl,\n      xhtmlLinks,\n      ...routingOptions,\n    })\n  );\n\n  const xmlns = includeAlternates\n    ? '\\n  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"'\n    : '';\n\n  return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset\n  xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"${xmlns}\n>\n${xmlEntries.join('\\n')}\n</urlset>`;\n};\n"],"mappings":";;;;;;;;;;;AA2CA,MAAM,2BACJ,MACA,eACY,cAAc,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCrC,MAAa,sBACX,MACA,YACW;CACX,MAAM,EACJ,SACA,YACA,UACA,SACA,aAAa,MACb,GAAG,mBACD;CAEJ,MAAM,WAAW,qBAAqB,eAAiC;CACvE,MAAM,UAAU,GAAG,UAAU;CAE7B,MAAM,QAA2B;EAC/B;EACA,YAAY,QAAQ;EACpB,UAAU,gBAAgB,QAAQ,cAAc;EAChD,aAAa,mBAAmB,WAAW,iBAAiB;EAC5D,aAAa,SAAY,iBAAiB,SAAS,eAAe;EACnE;CAED,MAAM,mBAAmB,gBAAgB,KAAK,KAAK;AACnD,KAAI,wBAAwB,SAAS,MAAM,WAAW,IAAI,CAAC,kBAAkB;EAC3E,MAAM,aAAa,oBACjB,MACA,eACD;AAED,OAAK,MAAM,CAAC,MAAM,eAAe,OAAO,QAAQ,WAAW,CACzD,OAAM,KACJ,6CAA6C,KAAK,UAAU,UAAU,WAAW,KAClF;AAGH,QAAM,KACJ,8DAA8D,QAAQ,KACvE;;AAGH,OAAM,KAAK,WAAW;AAEtB,QAAO,MAAM,OAAO,QAAQ,CAAC,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BzC,MAAa,mBACX,SACA,YACW;CACX,MAAM,EAAE,SAAS,aAAa,MAAM,GAAG,mBAAmB;CAG1D,MAAM,oBAAoB,wBADT,qBAAqB,eACoB,CAAC,MAAM,WAAW;CAE5E,MAAM,aAAa,QAAQ,KAAK,UAC9B,mBAAmB,MAAM,MAAM;EAC7B,GAAG;EACH;EACA;EACA,GAAG;EACJ,CAAC,CACH;AAMD,QAAO;;uDAJO,oBACV,qDACA,GAIuD;;EAE3D,WAAW,KAAK,KAAK,CAAC"}