@pas7/nextjs-sitemap-hreflang 0.6.0 → 0.6.1

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/README.md CHANGED
@@ -87,6 +87,13 @@ Auto-detect order when `--in` is not provided:
87
87
  2. `out/sitemap.xml`
88
88
  3. `sitemap.xml`
89
89
 
90
+ Prefer explicit source when needed:
91
+
92
+ ```bash
93
+ npx nextjs-sitemap-hreflang check --fail-on-missing --prefer out
94
+ npx nextjs-sitemap-hreflang inject --prefer public --out public/sitemap.xml
95
+ ```
96
+
90
97
  ## Next.js Full SEO Stack (App Router)
91
98
 
92
99
  `app/sitemap.ts`:
@@ -190,6 +197,7 @@ Routing priority inside `routingPAS7`:
190
197
  npx nextjs-sitemap-hreflang inject \
191
198
  --x-default loc \
192
199
  --canonical-locale en \
200
+ --prefer public \
193
201
  --order canonical-first \
194
202
  --trailing-slash never
195
203
  ```
@@ -198,6 +206,7 @@ npx nextjs-sitemap-hreflang inject \
198
206
 
199
207
  ```bash
200
208
  npx nextjs-sitemap-hreflang check \
209
+ --prefer out \
201
210
  --origin-policy same \
202
211
  --fail-on-missing
203
212
  ```
package/dist/cli.js CHANGED
@@ -16,14 +16,32 @@ function resolveSitemapInputPath(options) {
16
16
  if (options.inPath) return options.inPath;
17
17
  const cwd = options.cwd ?? process.cwd();
18
18
  const exists = options.exists ?? fs.existsSync;
19
- for (const candidate of DEFAULT_CANDIDATES) {
19
+ const candidates = orderedCandidates(options.prefer ?? "public");
20
+ for (const candidate of candidates) {
20
21
  const absolutePath = path.resolve(cwd, candidate);
21
22
  if (exists(absolutePath)) return absolutePath;
22
23
  }
23
24
  throw new Error(
24
- `Missing --in and sitemap file not found. Tried: ${DEFAULT_CANDIDATES.join(", ")}`
25
+ `Missing --in and sitemap file not found. Tried: ${candidates.join(", ")}`
25
26
  );
26
27
  }
28
+ function orderedCandidates(prefer) {
29
+ if (prefer === "out") {
30
+ return [
31
+ path.join("out", "sitemap.xml"),
32
+ path.join("public", "sitemap.xml"),
33
+ "sitemap.xml"
34
+ ];
35
+ }
36
+ if (prefer === "root") {
37
+ return [
38
+ "sitemap.xml",
39
+ path.join("public", "sitemap.xml"),
40
+ path.join("out", "sitemap.xml")
41
+ ];
42
+ }
43
+ return DEFAULT_CANDIDATES;
44
+ }
27
45
 
28
46
  // src/lib/url.ts
29
47
  function resolveAbsoluteUrl(input, baseUrl) {
@@ -361,6 +379,7 @@ function parseArgs(argv) {
361
379
  ensureNamespace: true,
362
380
  json: false,
363
381
  failOnMissing: false,
382
+ prefer: "public",
364
383
  canonicalLocale: null,
365
384
  order: "preserve",
366
385
  trailingSlash: "preserve",
@@ -408,6 +427,13 @@ function parseArgs(argv) {
408
427
  args.failOnMissing = true;
409
428
  continue;
410
429
  }
430
+ if (a === "--prefer" && v) {
431
+ if (v === "public" || v === "out" || v === "root") {
432
+ args.prefer = v;
433
+ }
434
+ i += 1;
435
+ continue;
436
+ }
411
437
  if (a === "--canonical-locale" && v) {
412
438
  args.canonicalLocale = v;
413
439
  i += 1;
@@ -475,12 +501,14 @@ function printHelp() {
475
501
  " --x-default loc|root|locale:en|custom:https://example.com/path",
476
502
  " --base-url https://example.com",
477
503
  " --in is optional for inject/check (auto-detect: public/sitemap.xml, out/sitemap.xml, sitemap.xml)",
504
+ " --prefer public|out|root Change auto-detect priority (default: public)",
478
505
  " --canonical-locale <locale> Canonical locale for ordering",
479
506
  " --order canonical-first|preserve",
480
507
  " --trailing-slash preserve|always|never",
481
508
  " --no-ensure-namespace",
482
509
  "",
483
510
  "Check options:",
511
+ " --prefer public|out|root Change auto-detect priority (default: public)",
484
512
  " --no-check-duplicate-keys Disable duplicate key check",
485
513
  " --no-check-duplicate-hrefs Disable duplicate href check",
486
514
  " --no-check-hreflang-casing Disable hreflang casing check",
@@ -526,7 +554,7 @@ async function main() {
526
554
  }
527
555
  resolvedInPath = args.inPath;
528
556
  } else {
529
- resolvedInPath = resolveSitemapInputPath({ inPath: args.inPath });
557
+ resolvedInPath = resolveSitemapInputPath({ inPath: args.inPath, prefer: args.prefer });
530
558
  }
531
559
  } catch (error) {
532
560
  const message = error instanceof Error ? error.message : "Failed to resolve sitemap input path";
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/cli/resolveSitemapInputPath.ts","../src/lib/url.ts","../src/xml/xml.ts","../src/xml/inject.ts","../src/xml/check.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { XDefaultStrategy } from \"./lib/types.js\";\nimport { resolveSitemapInputPath } from \"./cli/resolveSitemapInputPath.js\";\nimport { injectXDefaultIntoSitemapXml } from \"./xml/inject.js\";\nimport { checkSitemapXmlHreflang } from \"./xml/check.js\";\nimport {\n ensureXhtmlNamespace,\n extractUrlBlocks,\n normalizeTrailingSlashInBlock,\n reorderXhtmlLinks,\n} from \"./xml/xml.js\";\n\ntype Args = {\n command: \"inject\" | \"check\" | \"transform\" | null;\n inPath: string | null;\n outPath: string | null;\n baseUrl: string | null;\n xDefault: string | null;\n ensureNamespace: boolean;\n json: boolean;\n failOnMissing: boolean;\n // Inject options\n canonicalLocale: string | null;\n order: \"canonical-first\" | \"preserve\";\n trailingSlash: \"preserve\" | \"always\" | \"never\";\n // Check options\n checkDuplicateKeys: boolean;\n checkDuplicateHrefs: boolean;\n checkHreflangCasing: boolean;\n originPolicy: \"same\" | \"allowlist\" | \"off\";\n allowedOrigins: string[];\n // Transform options\n expandLocales: boolean;\n};\n\nfunction parseArgs(argv: string[]): Args {\n const args: Args = {\n command: null,\n inPath: null,\n outPath: null,\n baseUrl: null,\n xDefault: null,\n ensureNamespace: true,\n json: false,\n failOnMissing: false,\n canonicalLocale: null,\n order: \"preserve\",\n trailingSlash: \"preserve\",\n checkDuplicateKeys: true,\n checkDuplicateHrefs: true,\n checkHreflangCasing: true,\n originPolicy: \"off\",\n allowedOrigins: [],\n expandLocales: false,\n };\n\n const [cmd, ...rest] = argv;\n if (cmd === \"inject\" || cmd === \"check\" || cmd === \"transform\") args.command = cmd;\n\n for (let i = 0; i < rest.length; i += 1) {\n const a = rest[i];\n const v = rest[i + 1];\n\n if (a === \"--in\" && v) {\n args.inPath = v;\n i += 1;\n continue;\n }\n if (a === \"--out\" && v) {\n args.outPath = v;\n i += 1;\n continue;\n }\n if (a === \"--base-url\" && v) {\n args.baseUrl = v;\n i += 1;\n continue;\n }\n if (a === \"--x-default\" && v) {\n args.xDefault = v;\n i += 1;\n continue;\n }\n if (a === \"--no-ensure-namespace\") {\n args.ensureNamespace = false;\n continue;\n }\n if (a === \"--json\") {\n args.json = true;\n continue;\n }\n if (a === \"--fail-on-missing\") {\n args.failOnMissing = true;\n continue;\n }\n if (a === \"--canonical-locale\" && v) {\n args.canonicalLocale = v;\n i += 1;\n continue;\n }\n if (a === \"--order\" && v) {\n if (v === \"canonical-first\" || v === \"preserve\") {\n args.order = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--trailing-slash\" && v) {\n if (v === \"preserve\" || v === \"always\" || v === \"never\") {\n args.trailingSlash = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--no-check-duplicate-keys\") {\n args.checkDuplicateKeys = false;\n continue;\n }\n if (a === \"--no-check-duplicate-hrefs\") {\n args.checkDuplicateHrefs = false;\n continue;\n }\n if (a === \"--no-check-hreflang-casing\") {\n args.checkHreflangCasing = false;\n continue;\n }\n if (a === \"--origin-policy\" && v) {\n if (v === \"same\" || v === \"allowlist\" || v === \"off\") {\n args.originPolicy = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--allowed-origins\" && v) {\n args.allowedOrigins = v.split(\",\").map((s) => s.trim());\n i += 1;\n continue;\n }\n if (a === \"--expand-locales\") {\n args.expandLocales = true;\n continue;\n }\n if (a === \"--help\") {\n printHelp();\n process.exit(0);\n }\n }\n\n return args;\n}\n\nfunction printHelp(): void {\n const text = [\n \"nextjs-sitemap-hreflang\",\n \"\",\n \"Commands:\",\n \" inject [--in <path>] [--out <path>] [options]\",\n \" check [--in <path>] [--json] [--fail-on-missing] [options]\",\n \" transform --in <path> --out <path> [options]\",\n \"\",\n \"Inject options:\",\n \" --x-default loc|root|locale:en|custom:https://example.com/path\",\n \" --base-url https://example.com\",\n \" --in is optional for inject/check (auto-detect: public/sitemap.xml, out/sitemap.xml, sitemap.xml)\",\n \" --canonical-locale <locale> Canonical locale for ordering\",\n \" --order canonical-first|preserve\",\n \" --trailing-slash preserve|always|never\",\n \" --no-ensure-namespace\",\n \"\",\n \"Check options:\",\n \" --no-check-duplicate-keys Disable duplicate key check\",\n \" --no-check-duplicate-hrefs Disable duplicate href check\",\n \" --no-check-hreflang-casing Disable hreflang casing check\",\n \" --origin-policy same|allowlist|off\",\n \" --allowed-origins <comma-separated>\",\n \"\",\n \"Transform options:\",\n \" --expand-locales Expand locale entries\",\n \" --trailing-slash preserve|always|never\",\n \" --order canonical-first|preserve\",\n \" --canonical-locale <locale>\",\n \"\",\n ].join(\"\\n\");\n process.stdout.write(text);\n}\n\nfunction parseXDefaultStrategy(raw: string | null): XDefaultStrategy | undefined {\n if (!raw) return undefined;\n if (raw === \"loc\") return { type: \"loc\" };\n if (raw === \"root\") return { type: \"root\" };\n if (raw.startsWith(\"locale:\")) return { type: \"locale\", locale: raw.slice(\"locale:\".length) };\n if (raw.startsWith(\"custom:\")) return { type: \"custom\", url: raw.slice(\"custom:\".length) };\n return undefined;\n}\n\nfunction readFileUtf8(p: string): string {\n return fs.readFileSync(p, \"utf8\");\n}\n\nfunction writeFileUtf8(p: string, content: string): void {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(p, content, \"utf8\");\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv.slice(2));\n\n if (!args.command) {\n printHelp();\n process.exit(1);\n }\n\n let resolvedInPath: string;\n try {\n if (args.command === \"transform\") {\n if (!args.inPath) {\n process.stderr.write(\"Missing --in for transform\\n\");\n process.exit(1);\n }\n resolvedInPath = args.inPath;\n } else {\n resolvedInPath = resolveSitemapInputPath({ inPath: args.inPath });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to resolve sitemap input path\";\n process.stderr.write(`${message}\\n`);\n process.exit(1);\n }\n\n const xml = readFileUtf8(resolvedInPath);\n\n if (args.command === \"inject\") {\n const strategy = parseXDefaultStrategy(args.xDefault) ?? { type: \"loc\" };\n\n const next = injectXDefaultIntoSitemapXml(xml, {\n ...(args.baseUrl ? { baseUrl: args.baseUrl } : {}),\n xDefaultStrategy: strategy,\n ensureNamespace: args.ensureNamespace,\n ...(args.canonicalLocale ? { canonicalLocale: args.canonicalLocale } : {}),\n order: args.order,\n trailingSlash: args.trailingSlash,\n });\n\n const outPath = args.outPath ?? resolvedInPath;\n writeFileUtf8(outPath, next);\n process.stdout.write(`ok: injected\\n`);\n return;\n }\n\n if (args.command === \"transform\") {\n let result = args.ensureNamespace ? ensureXhtmlNamespace(xml) : xml;\n\n // Apply trailing slash normalization\n if (args.trailingSlash !== \"preserve\") {\n const blocks = extractUrlBlocks(result);\n for (const block of blocks) {\n const transformed = normalizeTrailingSlashInBlock(block, args.trailingSlash);\n result = result.replace(block, transformed);\n }\n }\n\n // Apply reordering\n if (args.order === \"canonical-first\") {\n const blocks = extractUrlBlocks(result);\n for (const block of blocks) {\n const transformed = reorderXhtmlLinks(block, {\n ...(args.canonicalLocale ? { canonicalLocale: args.canonicalLocale } : {}),\n order: \"canonical-first\",\n });\n result = result.replace(block, transformed);\n }\n }\n\n const outPath = args.outPath;\n if (!outPath) {\n process.stderr.write(\"Missing --out for transform\\n\");\n process.exit(1);\n }\n writeFileUtf8(outPath, result);\n process.stdout.write(`ok: transformed\\n`);\n return;\n }\n\n const report = checkSitemapXmlHreflang(xml, {\n requireNamespace: true,\n requireAbsolute: true,\n requireXDefaultWhenMultiple: true,\n checkDuplicateKeys: args.checkDuplicateKeys,\n checkDuplicateHrefs: args.checkDuplicateHrefs,\n checkHreflangCasing: args.checkHreflangCasing,\n originPolicy: args.originPolicy,\n allowedOrigins: args.allowedOrigins,\n });\n\n if (args.json) {\n process.stdout.write(JSON.stringify(report, null, 2));\n process.stdout.write(\"\\n\");\n } else {\n if (report.ok) {\n process.stdout.write(\"ok: sitemap hreflang check passed\\n\");\n } else {\n process.stdout.write(`fail: ${report.issues.length} issue(s)\\n`);\n for (const issue of report.issues) {\n process.stdout.write(`- ${issue.code} ${issue.entryUrl}: ${issue.message}\\n`);\n }\n }\n }\n\n if (!report.ok && args.failOnMissing) process.exit(1);\n}\n\nvoid main();\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ResolveSitemapInputOptions = {\n inPath: string | null;\n cwd?: string;\n exists?: (absolutePath: string) => boolean;\n};\n\nconst DEFAULT_CANDIDATES = [\n path.join(\"public\", \"sitemap.xml\"),\n path.join(\"out\", \"sitemap.xml\"),\n \"sitemap.xml\",\n] as const;\n\nexport function resolveSitemapInputPath(options: ResolveSitemapInputOptions): string {\n if (options.inPath) return options.inPath;\n\n const cwd = options.cwd ?? process.cwd();\n const exists = options.exists ?? fs.existsSync;\n\n for (const candidate of DEFAULT_CANDIDATES) {\n const absolutePath = path.resolve(cwd, candidate);\n if (exists(absolutePath)) return absolutePath;\n }\n\n throw new Error(\n `Missing --in and sitemap file not found. Tried: ${DEFAULT_CANDIDATES.join(\", \")}`,\n );\n}\n","export type TrailingSlashPolicy = \"preserve\" | \"always\" | \"never\";\n\nexport function normalizeUrl(url: string, trailingSlash: TrailingSlashPolicy): string {\n const u = new URL(url);\n if (trailingSlash === \"preserve\") return u.toString();\n if (trailingSlash === \"always\") {\n if (!u.pathname.endsWith(\"/\")) u.pathname = `${u.pathname}/`;\n return u.toString();\n }\n if (u.pathname !== \"/\" && u.pathname.endsWith(\"/\")) u.pathname = u.pathname.slice(0, -1);\n return u.toString();\n}\n\nexport function resolveAbsoluteUrl(input: string, baseUrl: string): string {\n if (input.startsWith(\"http://\") || input.startsWith(\"https://\")) return input;\n return new URL(input.startsWith(\"/\") ? input : `/${input}`, baseUrl).toString();\n}\n\nexport function getOriginFromAbsoluteUrl(absoluteUrl: string): string {\n const u = new URL(absoluteUrl);\n return `${u.protocol}//${u.host}`;\n}\n","export function xmlEscape(input: string): string {\n return input\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&apos;\");\n}\n\nexport function hasXhtmlNamespace(xml: string): boolean {\n return /<urlset[^>]*\\sxmlns:xhtml=\"http:\\/\\/www\\.w3\\.org\\/1999\\/xhtml\"[^>]*>/.test(xml);\n}\n\nexport function ensureXhtmlNamespace(xml: string): string {\n if (hasXhtmlNamespace(xml)) return xml;\n return xml.replace(\n /<urlset(\\s[^>]*?)?>/m,\n (m) => (m.includes(\"xmlns:xhtml=\") ? m : m.replace(\"<urlset\", '<urlset xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"')),\n );\n}\n\nexport function extractUrlBlocks(xml: string): string[] {\n return xml.match(/<url>[\\s\\S]*?<\\/url>/g) ?? [];\n}\n\nexport function extractLoc(urlBlock: string): string | null {\n return urlBlock.match(/<loc>([^<]+)<\\/loc>/)?.[1]?.trim() ?? null;\n}\n\nexport function extractXhtmlLinks(urlBlock: string): Array<{ hreflang: string; href: string }> {\n const out: Array<{ hreflang: string; href: string }> = [];\n const re = /<xhtml:link[^>]*\\shreflang=\"([^\"]+)\"[^>]*\\shref=\"([^\"]+)\"[^>]*\\/>/g;\n for (const m of urlBlock.matchAll(re)) {\n if (m[1] !== undefined && m[2] !== undefined) {\n out.push({ hreflang: m[1], href: m[2] });\n }\n }\n return out;\n}\n\nexport function hasXDefault(urlBlock: string): boolean {\n return /<xhtml:link[^>]*\\shreflang=\"x-default\"[^>]*\\/>/.test(urlBlock);\n}\n\nexport function insertXhtmlLink(urlBlock: string, linkXml: string): string {\n const lastLinkIdx = urlBlock.lastIndexOf(\"<xhtml:link\");\n if (lastLinkIdx === -1) {\n const locEnd = urlBlock.indexOf(\"</loc>\");\n if (locEnd === -1) return urlBlock;\n const insertPos = locEnd + \"</loc>\".length;\n return `${urlBlock.slice(0, insertPos)}\\n ${linkXml}${urlBlock.slice(insertPos)}`;\n }\n const lineEnd = urlBlock.indexOf(\"\\n\", lastLinkIdx);\n if (lineEnd === -1) return `${urlBlock}\\n ${linkXml}`;\n return `${urlBlock.slice(0, lineEnd)}\\n ${linkXml}${urlBlock.slice(lineEnd)}`;\n}\n\nexport type ReorderOptions = {\n canonicalLocale?: string;\n order: \"canonical-first\" | \"preserve\";\n};\n\nexport function reorderXhtmlLinks(urlBlock: string, options: ReorderOptions): string {\n if (options.order === \"preserve\") return urlBlock;\n\n const links = extractXhtmlLinks(urlBlock);\n if (links.length === 0) return urlBlock;\n\n const loc = extractLoc(urlBlock);\n\n // Determine canonical\n let canonical: { hreflang: string; href: string } | undefined;\n if (options.canonicalLocale) {\n canonical = links.find((l) => l.hreflang === options.canonicalLocale);\n }\n if (!canonical && loc) {\n canonical = links.find((l) => l.href === loc);\n }\n\n // Split into groups\n const canonicalLinks = canonical ? [canonical] : [];\n const otherLinks = links.filter((l) => l !== canonical && l.hreflang !== \"x-default\");\n const xDefaultLinks = links.filter((l) => l.hreflang === \"x-default\");\n\n // Build new order\n const orderedLinks = [...canonicalLinks, ...otherLinks, ...xDefaultLinks];\n\n // Remove all existing xhtml:link and insert in new order\n const newBlock = urlBlock.replace(/<xhtml:link[^>]*\\/>\\s*/g, \"\");\n\n // Find position after </loc>\n const locEnd = newBlock.indexOf(\"</loc>\");\n if (locEnd === -1) return urlBlock;\n\n const insertPos = locEnd + \"</loc>\".length;\n const linksXml = orderedLinks\n .map((l) => `\\n <xhtml:link rel=\"alternate\" hreflang=\"${xmlEscape(l.hreflang)}\" href=\"${xmlEscape(l.href)}\" />`)\n .join(\"\");\n\n return `${newBlock.slice(0, insertPos)}${linksXml}\\n ${newBlock.slice(insertPos).trimStart()}`;\n}\n\nexport function normalizeTrailingSlashInBlock(\n urlBlock: string,\n policy: \"preserve\" | \"always\" | \"never\",\n): string {\n if (policy === \"preserve\") return urlBlock;\n\n // Normalize <loc>\n let result = urlBlock.replace(/<loc>([^<]+)<\\/loc>/g, (_, url: string) => {\n return `<loc>${applyTrailingSlashPolicy(url, policy)}</loc>`;\n });\n\n // Normalize href in xhtml:link\n result = result.replace(\n /(<xhtml:link[^>]*href=\")([^\"]+)(\"[^>]*\\/>)/g,\n (_, prefix: string, url: string, suffix: string) => {\n return `${prefix}${applyTrailingSlashPolicy(url, policy)}${suffix}`;\n },\n );\n\n return result;\n}\n\nfunction applyTrailingSlashPolicy(url: string, policy: \"always\" | \"never\"): string {\n try {\n const u = new URL(url);\n if (policy === \"always\" && !u.pathname.endsWith(\"/\")) {\n u.pathname += \"/\";\n } else if (policy === \"never\" && u.pathname !== \"/\" && u.pathname.endsWith(\"/\")) {\n u.pathname = u.pathname.slice(0, -1);\n }\n return u.toString();\n } catch {\n return url;\n }\n}\n","import { getOriginFromAbsoluteUrl, resolveAbsoluteUrl } from \"../lib/url.js\";\nimport type { XDefaultStrategy } from \"../lib/types.js\";\nimport {\n ensureXhtmlNamespace,\n extractLoc,\n extractUrlBlocks,\n extractXhtmlLinks,\n hasXDefault,\n insertXhtmlLink,\n normalizeTrailingSlashInBlock,\n reorderXhtmlLinks,\n xmlEscape,\n} from \"./xml.js\";\n\nexport type InjectOptions = {\n baseUrl?: string;\n xDefaultStrategy?: XDefaultStrategy;\n ensureNamespace?: boolean;\n canonicalLocale?: string;\n order?: \"canonical-first\" | \"preserve\";\n trailingSlash?: \"preserve\" | \"always\" | \"never\";\n};\n\nexport function injectXDefaultIntoSitemapXml(xml: string, options: InjectOptions): string {\n const ensureNamespace = options.ensureNamespace ?? true;\n const xDefaultStrategy = options.xDefaultStrategy ?? { type: \"loc\" };\n const order = options.order ?? \"preserve\";\n const trailingSlash = options.trailingSlash ?? \"preserve\";\n\n const xmlWithNs = ensureNamespace ? ensureXhtmlNamespace(xml) : xml;\n\n const blocks = extractUrlBlocks(xmlWithNs);\n if (blocks.length === 0) return xmlWithNs;\n\n let out = xmlWithNs;\n\n for (const block of blocks) {\n const loc = extractLoc(block);\n if (!loc) continue;\n\n const links = extractXhtmlLinks(block);\n if (links.length === 0) continue;\n\n let nextBlock = block;\n\n if (!hasXDefault(block)) {\n const href = resolveXDefaultHref({\n loc,\n links,\n ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),\n strategy: xDefaultStrategy,\n });\n\n const linkXml = `<xhtml:link rel=\"alternate\" hreflang=\"x-default\" href=\"${xmlEscape(href)}\" />`;\n nextBlock = insertXhtmlLink(nextBlock, linkXml);\n }\n\n // Apply reordering if needed\n if (order === \"canonical-first\") {\n nextBlock = reorderXhtmlLinks(nextBlock, {\n ...(options.canonicalLocale ? { canonicalLocale: options.canonicalLocale } : {}),\n order: \"canonical-first\",\n });\n }\n\n // Apply trailing slash normalization\n if (trailingSlash !== \"preserve\") {\n nextBlock = normalizeTrailingSlashInBlock(nextBlock, trailingSlash);\n }\n\n out = out.replace(block, nextBlock);\n }\n\n return out;\n}\n\nfunction resolveXDefaultHref(args: {\n loc: string;\n links: Array<{ hreflang: string; href: string }>;\n baseUrl?: string;\n strategy: XDefaultStrategy;\n}): string {\n const { loc, links, baseUrl, strategy } = args;\n\n const locAbs = baseUrl ? resolveAbsoluteUrl(loc, baseUrl) : loc;\n const origin = isAbsolute(locAbs) ? getOriginFromAbsoluteUrl(locAbs) : baseUrl;\n\n if (strategy.type === \"loc\") return locAbs;\n if (strategy.type === \"root\") {\n if (!origin) return locAbs;\n return resolveAbsoluteUrl(\"/\", origin);\n }\n if (strategy.type === \"custom\") {\n if (!origin) return strategy.url;\n return resolveAbsoluteUrl(strategy.url, origin);\n }\n if (strategy.type === \"locale\") {\n const found = links.find((l) => l.hreflang === strategy.locale)?.href;\n if (found) return baseUrl ? resolveAbsoluteUrl(found, baseUrl) : found;\n return locAbs;\n }\n const computed = strategy.resolve({ url: locAbs });\n if (!origin) return computed;\n return resolveAbsoluteUrl(computed, origin);\n}\n\nfunction isAbsolute(u: string): boolean {\n return u.startsWith(\"http://\") || u.startsWith(\"https://\");\n}\n","import type { HreflangIssue, HreflangReport } from \"../lib/types.js\";\nimport { extractLoc, extractUrlBlocks, extractXhtmlLinks, hasXhtmlNamespace } from \"./xml.js\";\n\nexport type CheckXmlOptions = {\n requireNamespace?: boolean;\n requireXDefaultWhenMultiple?: boolean;\n requireAbsolute?: boolean;\n checkDuplicateKeys?: boolean;\n checkDuplicateHrefs?: boolean;\n checkHreflangCasing?: boolean;\n originPolicy?: \"same\" | \"allowlist\" | \"off\";\n allowedOrigins?: string[];\n};\n\nexport function checkSitemapXmlHreflang(xml: string, options: CheckXmlOptions): HreflangReport {\n const requireNamespace = options.requireNamespace ?? true;\n const requireXDefaultWhenMultiple = options.requireXDefaultWhenMultiple ?? true;\n const requireAbsolute = options.requireAbsolute ?? true;\n const checkDuplicateKeys = options.checkDuplicateKeys ?? true;\n const checkDuplicateHrefs = options.checkDuplicateHrefs ?? true;\n const checkHreflangCasing = options.checkHreflangCasing ?? true;\n const originPolicy = options.originPolicy ?? \"off\";\n\n const issues: HreflangIssue[] = [];\n\n const blocks = extractUrlBlocks(xml);\n\n if (requireNamespace) {\n const usesXhtml = /<xhtml:link\\b/.test(xml);\n if (usesXhtml && !hasXhtmlNamespace(xml)) {\n issues.push({\n code: \"MISSING_LANGUAGES\",\n entryUrl: \"sitemap.xml\",\n message: 'Missing xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" in <urlset>',\n });\n }\n }\n\n for (const block of blocks) {\n const loc = extractLoc(block);\n if (!loc) continue;\n\n const links = extractXhtmlLinks(block);\n if (links.length === 0) continue;\n\n const hasXDefault = links.some((l) => l.hreflang === \"x-default\");\n if (requireXDefaultWhenMultiple && links.length > 1 && !hasXDefault) {\n issues.push({\n code: \"MISSING_XDEFAULT\",\n entryUrl: loc,\n message: \"Missing x-default hreflang in sitemap url block\",\n });\n }\n\n // Check for duplicate hreflang keys\n if (checkDuplicateKeys) {\n const seenKeys = new Set<string>();\n for (const link of links) {\n if (seenKeys.has(link.hreflang)) {\n issues.push({\n code: \"DUPLICATE_HREFLANG_KEY\",\n entryUrl: loc,\n message: `Duplicate hreflang key: ${link.hreflang}`,\n });\n }\n seenKeys.add(link.hreflang);\n }\n }\n\n // Check for duplicate hrefs (excluding x-default which can share href with another locale)\n if (checkDuplicateHrefs) {\n const hrefToLocales = new Map<string, string[]>();\n for (const link of links) {\n const locales = hrefToLocales.get(link.href) ?? [];\n locales.push(link.hreflang);\n hrefToLocales.set(link.href, locales);\n }\n for (const [href, locales] of hrefToLocales) {\n // Filter out x-default - it's allowed to share href with another locale\n const nonXDefaultLocales = locales.filter((l) => l !== \"x-default\");\n if (nonXDefaultLocales.length > 1) {\n issues.push({\n code: \"DUPLICATE_HREF\",\n entryUrl: loc,\n message: `Duplicate hreflang href detected: ${href} (locales: ${nonXDefaultLocales.join(\", \")})`,\n });\n }\n }\n }\n\n // Check hreflang casing\n if (checkHreflangCasing) {\n for (const link of links) {\n if (!isValidHreflangCasing(link.hreflang)) {\n issues.push({\n code: \"INVALID_HREFLANG_CASING\",\n entryUrl: loc,\n message: `Invalid hreflang casing: ${link.hreflang}. Expected format: en, pt-BR, or x-default`,\n });\n }\n }\n }\n\n // Check origin policy\n if (originPolicy === \"same\") {\n const locOrigin = getOrigin(loc);\n if (locOrigin) {\n for (const link of links) {\n const linkOrigin = getOrigin(link.href);\n if (linkOrigin && linkOrigin !== locOrigin) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Inconsistent origin for ${link.hreflang}: expected ${locOrigin}, got ${linkOrigin}`,\n });\n }\n }\n }\n } else if (originPolicy === \"allowlist\") {\n const allowedOrigins = options.allowedOrigins ?? [];\n for (const link of links) {\n const linkOrigin = getOrigin(link.href);\n if (linkOrigin && !allowedOrigins.includes(linkOrigin)) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Origin not in allowlist for ${link.hreflang}: ${linkOrigin}`,\n });\n }\n }\n const locOrigin = getOrigin(loc);\n if (locOrigin && !allowedOrigins.includes(locOrigin)) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Origin not in allowlist for loc: ${locOrigin}`,\n });\n }\n }\n\n if (requireAbsolute) {\n for (const link of links) {\n if (!isAbsolute(link.href)) {\n issues.push({\n code: \"NON_ABSOLUTE_URL\",\n entryUrl: loc,\n message: `Non-absolute hreflang href for ${link.hreflang}: ${link.href}`,\n });\n }\n }\n if (!isAbsolute(loc)) {\n issues.push({\n code: \"NON_ABSOLUTE_URL\",\n entryUrl: loc,\n message: `Non-absolute <loc>: ${loc}`,\n });\n }\n }\n }\n\n return { ok: issues.length === 0, issues };\n}\n\nfunction isAbsolute(u: string): boolean {\n return u.startsWith(\"http://\") || u.startsWith(\"https://\");\n}\n\nfunction getOrigin(url: string): string | null {\n try {\n const u = new URL(url);\n return u.origin;\n } catch {\n return null;\n }\n}\n\nfunction isValidHreflangCasing(key: string): boolean {\n if (key === \"x-default\") return true;\n // en, de, uk - only lowercase\n if (/^[a-z]{2}$/.test(key)) return true;\n // pt-BR, en-US - lowercase-UPPERCASE\n if (/^[a-z]{2}-[A-Z]{2}$/.test(key)) return true;\n return false;\n}\n"],"mappings":"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","names":["fs","path","hasXDefault","isAbsolute","fs","path"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli/resolveSitemapInputPath.ts","../src/lib/url.ts","../src/xml/xml.ts","../src/xml/inject.ts","../src/xml/check.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { XDefaultStrategy } from \"./lib/types.js\";\nimport type { AutoDetectPreference } from \"./cli/resolveSitemapInputPath.js\";\nimport { resolveSitemapInputPath } from \"./cli/resolveSitemapInputPath.js\";\nimport { injectXDefaultIntoSitemapXml } from \"./xml/inject.js\";\nimport { checkSitemapXmlHreflang } from \"./xml/check.js\";\nimport {\n ensureXhtmlNamespace,\n extractUrlBlocks,\n normalizeTrailingSlashInBlock,\n reorderXhtmlLinks,\n} from \"./xml/xml.js\";\n\ntype Args = {\n command: \"inject\" | \"check\" | \"transform\" | null;\n inPath: string | null;\n outPath: string | null;\n baseUrl: string | null;\n xDefault: string | null;\n ensureNamespace: boolean;\n json: boolean;\n failOnMissing: boolean;\n prefer: AutoDetectPreference;\n // Inject options\n canonicalLocale: string | null;\n order: \"canonical-first\" | \"preserve\";\n trailingSlash: \"preserve\" | \"always\" | \"never\";\n // Check options\n checkDuplicateKeys: boolean;\n checkDuplicateHrefs: boolean;\n checkHreflangCasing: boolean;\n originPolicy: \"same\" | \"allowlist\" | \"off\";\n allowedOrigins: string[];\n // Transform options\n expandLocales: boolean;\n};\n\nfunction parseArgs(argv: string[]): Args {\n const args: Args = {\n command: null,\n inPath: null,\n outPath: null,\n baseUrl: null,\n xDefault: null,\n ensureNamespace: true,\n json: false,\n failOnMissing: false,\n prefer: \"public\",\n canonicalLocale: null,\n order: \"preserve\",\n trailingSlash: \"preserve\",\n checkDuplicateKeys: true,\n checkDuplicateHrefs: true,\n checkHreflangCasing: true,\n originPolicy: \"off\",\n allowedOrigins: [],\n expandLocales: false,\n };\n\n const [cmd, ...rest] = argv;\n if (cmd === \"inject\" || cmd === \"check\" || cmd === \"transform\") args.command = cmd;\n\n for (let i = 0; i < rest.length; i += 1) {\n const a = rest[i];\n const v = rest[i + 1];\n\n if (a === \"--in\" && v) {\n args.inPath = v;\n i += 1;\n continue;\n }\n if (a === \"--out\" && v) {\n args.outPath = v;\n i += 1;\n continue;\n }\n if (a === \"--base-url\" && v) {\n args.baseUrl = v;\n i += 1;\n continue;\n }\n if (a === \"--x-default\" && v) {\n args.xDefault = v;\n i += 1;\n continue;\n }\n if (a === \"--no-ensure-namespace\") {\n args.ensureNamespace = false;\n continue;\n }\n if (a === \"--json\") {\n args.json = true;\n continue;\n }\n if (a === \"--fail-on-missing\") {\n args.failOnMissing = true;\n continue;\n }\n if (a === \"--prefer\" && v) {\n if (v === \"public\" || v === \"out\" || v === \"root\") {\n args.prefer = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--canonical-locale\" && v) {\n args.canonicalLocale = v;\n i += 1;\n continue;\n }\n if (a === \"--order\" && v) {\n if (v === \"canonical-first\" || v === \"preserve\") {\n args.order = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--trailing-slash\" && v) {\n if (v === \"preserve\" || v === \"always\" || v === \"never\") {\n args.trailingSlash = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--no-check-duplicate-keys\") {\n args.checkDuplicateKeys = false;\n continue;\n }\n if (a === \"--no-check-duplicate-hrefs\") {\n args.checkDuplicateHrefs = false;\n continue;\n }\n if (a === \"--no-check-hreflang-casing\") {\n args.checkHreflangCasing = false;\n continue;\n }\n if (a === \"--origin-policy\" && v) {\n if (v === \"same\" || v === \"allowlist\" || v === \"off\") {\n args.originPolicy = v;\n }\n i += 1;\n continue;\n }\n if (a === \"--allowed-origins\" && v) {\n args.allowedOrigins = v.split(\",\").map((s) => s.trim());\n i += 1;\n continue;\n }\n if (a === \"--expand-locales\") {\n args.expandLocales = true;\n continue;\n }\n if (a === \"--help\") {\n printHelp();\n process.exit(0);\n }\n }\n\n return args;\n}\n\nfunction printHelp(): void {\n const text = [\n \"nextjs-sitemap-hreflang\",\n \"\",\n \"Commands:\",\n \" inject [--in <path>] [--out <path>] [options]\",\n \" check [--in <path>] [--json] [--fail-on-missing] [options]\",\n \" transform --in <path> --out <path> [options]\",\n \"\",\n \"Inject options:\",\n \" --x-default loc|root|locale:en|custom:https://example.com/path\",\n \" --base-url https://example.com\",\n \" --in is optional for inject/check (auto-detect: public/sitemap.xml, out/sitemap.xml, sitemap.xml)\",\n \" --prefer public|out|root Change auto-detect priority (default: public)\",\n \" --canonical-locale <locale> Canonical locale for ordering\",\n \" --order canonical-first|preserve\",\n \" --trailing-slash preserve|always|never\",\n \" --no-ensure-namespace\",\n \"\",\n \"Check options:\",\n \" --prefer public|out|root Change auto-detect priority (default: public)\",\n \" --no-check-duplicate-keys Disable duplicate key check\",\n \" --no-check-duplicate-hrefs Disable duplicate href check\",\n \" --no-check-hreflang-casing Disable hreflang casing check\",\n \" --origin-policy same|allowlist|off\",\n \" --allowed-origins <comma-separated>\",\n \"\",\n \"Transform options:\",\n \" --expand-locales Expand locale entries\",\n \" --trailing-slash preserve|always|never\",\n \" --order canonical-first|preserve\",\n \" --canonical-locale <locale>\",\n \"\",\n ].join(\"\\n\");\n process.stdout.write(text);\n}\n\nfunction parseXDefaultStrategy(raw: string | null): XDefaultStrategy | undefined {\n if (!raw) return undefined;\n if (raw === \"loc\") return { type: \"loc\" };\n if (raw === \"root\") return { type: \"root\" };\n if (raw.startsWith(\"locale:\")) return { type: \"locale\", locale: raw.slice(\"locale:\".length) };\n if (raw.startsWith(\"custom:\")) return { type: \"custom\", url: raw.slice(\"custom:\".length) };\n return undefined;\n}\n\nfunction readFileUtf8(p: string): string {\n return fs.readFileSync(p, \"utf8\");\n}\n\nfunction writeFileUtf8(p: string, content: string): void {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(p, content, \"utf8\");\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv.slice(2));\n\n if (!args.command) {\n printHelp();\n process.exit(1);\n }\n\n let resolvedInPath: string;\n try {\n if (args.command === \"transform\") {\n if (!args.inPath) {\n process.stderr.write(\"Missing --in for transform\\n\");\n process.exit(1);\n }\n resolvedInPath = args.inPath;\n } else {\n resolvedInPath = resolveSitemapInputPath({ inPath: args.inPath, prefer: args.prefer });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to resolve sitemap input path\";\n process.stderr.write(`${message}\\n`);\n process.exit(1);\n }\n\n const xml = readFileUtf8(resolvedInPath);\n\n if (args.command === \"inject\") {\n const strategy = parseXDefaultStrategy(args.xDefault) ?? { type: \"loc\" };\n\n const next = injectXDefaultIntoSitemapXml(xml, {\n ...(args.baseUrl ? { baseUrl: args.baseUrl } : {}),\n xDefaultStrategy: strategy,\n ensureNamespace: args.ensureNamespace,\n ...(args.canonicalLocale ? { canonicalLocale: args.canonicalLocale } : {}),\n order: args.order,\n trailingSlash: args.trailingSlash,\n });\n\n const outPath = args.outPath ?? resolvedInPath;\n writeFileUtf8(outPath, next);\n process.stdout.write(`ok: injected\\n`);\n return;\n }\n\n if (args.command === \"transform\") {\n let result = args.ensureNamespace ? ensureXhtmlNamespace(xml) : xml;\n\n // Apply trailing slash normalization\n if (args.trailingSlash !== \"preserve\") {\n const blocks = extractUrlBlocks(result);\n for (const block of blocks) {\n const transformed = normalizeTrailingSlashInBlock(block, args.trailingSlash);\n result = result.replace(block, transformed);\n }\n }\n\n // Apply reordering\n if (args.order === \"canonical-first\") {\n const blocks = extractUrlBlocks(result);\n for (const block of blocks) {\n const transformed = reorderXhtmlLinks(block, {\n ...(args.canonicalLocale ? { canonicalLocale: args.canonicalLocale } : {}),\n order: \"canonical-first\",\n });\n result = result.replace(block, transformed);\n }\n }\n\n const outPath = args.outPath;\n if (!outPath) {\n process.stderr.write(\"Missing --out for transform\\n\");\n process.exit(1);\n }\n writeFileUtf8(outPath, result);\n process.stdout.write(`ok: transformed\\n`);\n return;\n }\n\n const report = checkSitemapXmlHreflang(xml, {\n requireNamespace: true,\n requireAbsolute: true,\n requireXDefaultWhenMultiple: true,\n checkDuplicateKeys: args.checkDuplicateKeys,\n checkDuplicateHrefs: args.checkDuplicateHrefs,\n checkHreflangCasing: args.checkHreflangCasing,\n originPolicy: args.originPolicy,\n allowedOrigins: args.allowedOrigins,\n });\n\n if (args.json) {\n process.stdout.write(JSON.stringify(report, null, 2));\n process.stdout.write(\"\\n\");\n } else {\n if (report.ok) {\n process.stdout.write(\"ok: sitemap hreflang check passed\\n\");\n } else {\n process.stdout.write(`fail: ${report.issues.length} issue(s)\\n`);\n for (const issue of report.issues) {\n process.stdout.write(`- ${issue.code} ${issue.entryUrl}: ${issue.message}\\n`);\n }\n }\n }\n\n if (!report.ok && args.failOnMissing) process.exit(1);\n}\n\nvoid main();\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ResolveSitemapInputOptions = {\n inPath: string | null;\n prefer?: AutoDetectPreference;\n cwd?: string;\n exists?: (absolutePath: string) => boolean;\n};\n\nexport type AutoDetectPreference = \"public\" | \"out\" | \"root\";\n\nconst DEFAULT_CANDIDATES = [\n path.join(\"public\", \"sitemap.xml\"),\n path.join(\"out\", \"sitemap.xml\"),\n \"sitemap.xml\",\n] as const;\n\nexport function resolveSitemapInputPath(options: ResolveSitemapInputOptions): string {\n if (options.inPath) return options.inPath;\n\n const cwd = options.cwd ?? process.cwd();\n const exists = options.exists ?? fs.existsSync;\n const candidates = orderedCandidates(options.prefer ?? \"public\");\n\n for (const candidate of candidates) {\n const absolutePath = path.resolve(cwd, candidate);\n if (exists(absolutePath)) return absolutePath;\n }\n\n throw new Error(\n `Missing --in and sitemap file not found. Tried: ${candidates.join(\", \")}`,\n );\n}\n\nfunction orderedCandidates(prefer: AutoDetectPreference): readonly string[] {\n if (prefer === \"out\") {\n return [\n path.join(\"out\", \"sitemap.xml\"),\n path.join(\"public\", \"sitemap.xml\"),\n \"sitemap.xml\",\n ];\n }\n\n if (prefer === \"root\") {\n return [\n \"sitemap.xml\",\n path.join(\"public\", \"sitemap.xml\"),\n path.join(\"out\", \"sitemap.xml\"),\n ];\n }\n\n return DEFAULT_CANDIDATES;\n}\n","export type TrailingSlashPolicy = \"preserve\" | \"always\" | \"never\";\n\nexport function normalizeUrl(url: string, trailingSlash: TrailingSlashPolicy): string {\n const u = new URL(url);\n if (trailingSlash === \"preserve\") return u.toString();\n if (trailingSlash === \"always\") {\n if (!u.pathname.endsWith(\"/\")) u.pathname = `${u.pathname}/`;\n return u.toString();\n }\n if (u.pathname !== \"/\" && u.pathname.endsWith(\"/\")) u.pathname = u.pathname.slice(0, -1);\n return u.toString();\n}\n\nexport function resolveAbsoluteUrl(input: string, baseUrl: string): string {\n if (input.startsWith(\"http://\") || input.startsWith(\"https://\")) return input;\n return new URL(input.startsWith(\"/\") ? input : `/${input}`, baseUrl).toString();\n}\n\nexport function getOriginFromAbsoluteUrl(absoluteUrl: string): string {\n const u = new URL(absoluteUrl);\n return `${u.protocol}//${u.host}`;\n}\n","export function xmlEscape(input: string): string {\n return input\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&apos;\");\n}\n\nexport function hasXhtmlNamespace(xml: string): boolean {\n return /<urlset[^>]*\\sxmlns:xhtml=\"http:\\/\\/www\\.w3\\.org\\/1999\\/xhtml\"[^>]*>/.test(xml);\n}\n\nexport function ensureXhtmlNamespace(xml: string): string {\n if (hasXhtmlNamespace(xml)) return xml;\n return xml.replace(\n /<urlset(\\s[^>]*?)?>/m,\n (m) => (m.includes(\"xmlns:xhtml=\") ? m : m.replace(\"<urlset\", '<urlset xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"')),\n );\n}\n\nexport function extractUrlBlocks(xml: string): string[] {\n return xml.match(/<url>[\\s\\S]*?<\\/url>/g) ?? [];\n}\n\nexport function extractLoc(urlBlock: string): string | null {\n return urlBlock.match(/<loc>([^<]+)<\\/loc>/)?.[1]?.trim() ?? null;\n}\n\nexport function extractXhtmlLinks(urlBlock: string): Array<{ hreflang: string; href: string }> {\n const out: Array<{ hreflang: string; href: string }> = [];\n const re = /<xhtml:link[^>]*\\shreflang=\"([^\"]+)\"[^>]*\\shref=\"([^\"]+)\"[^>]*\\/>/g;\n for (const m of urlBlock.matchAll(re)) {\n if (m[1] !== undefined && m[2] !== undefined) {\n out.push({ hreflang: m[1], href: m[2] });\n }\n }\n return out;\n}\n\nexport function hasXDefault(urlBlock: string): boolean {\n return /<xhtml:link[^>]*\\shreflang=\"x-default\"[^>]*\\/>/.test(urlBlock);\n}\n\nexport function insertXhtmlLink(urlBlock: string, linkXml: string): string {\n const lastLinkIdx = urlBlock.lastIndexOf(\"<xhtml:link\");\n if (lastLinkIdx === -1) {\n const locEnd = urlBlock.indexOf(\"</loc>\");\n if (locEnd === -1) return urlBlock;\n const insertPos = locEnd + \"</loc>\".length;\n return `${urlBlock.slice(0, insertPos)}\\n ${linkXml}${urlBlock.slice(insertPos)}`;\n }\n const lineEnd = urlBlock.indexOf(\"\\n\", lastLinkIdx);\n if (lineEnd === -1) return `${urlBlock}\\n ${linkXml}`;\n return `${urlBlock.slice(0, lineEnd)}\\n ${linkXml}${urlBlock.slice(lineEnd)}`;\n}\n\nexport type ReorderOptions = {\n canonicalLocale?: string;\n order: \"canonical-first\" | \"preserve\";\n};\n\nexport function reorderXhtmlLinks(urlBlock: string, options: ReorderOptions): string {\n if (options.order === \"preserve\") return urlBlock;\n\n const links = extractXhtmlLinks(urlBlock);\n if (links.length === 0) return urlBlock;\n\n const loc = extractLoc(urlBlock);\n\n // Determine canonical\n let canonical: { hreflang: string; href: string } | undefined;\n if (options.canonicalLocale) {\n canonical = links.find((l) => l.hreflang === options.canonicalLocale);\n }\n if (!canonical && loc) {\n canonical = links.find((l) => l.href === loc);\n }\n\n // Split into groups\n const canonicalLinks = canonical ? [canonical] : [];\n const otherLinks = links.filter((l) => l !== canonical && l.hreflang !== \"x-default\");\n const xDefaultLinks = links.filter((l) => l.hreflang === \"x-default\");\n\n // Build new order\n const orderedLinks = [...canonicalLinks, ...otherLinks, ...xDefaultLinks];\n\n // Remove all existing xhtml:link and insert in new order\n const newBlock = urlBlock.replace(/<xhtml:link[^>]*\\/>\\s*/g, \"\");\n\n // Find position after </loc>\n const locEnd = newBlock.indexOf(\"</loc>\");\n if (locEnd === -1) return urlBlock;\n\n const insertPos = locEnd + \"</loc>\".length;\n const linksXml = orderedLinks\n .map((l) => `\\n <xhtml:link rel=\"alternate\" hreflang=\"${xmlEscape(l.hreflang)}\" href=\"${xmlEscape(l.href)}\" />`)\n .join(\"\");\n\n return `${newBlock.slice(0, insertPos)}${linksXml}\\n ${newBlock.slice(insertPos).trimStart()}`;\n}\n\nexport function normalizeTrailingSlashInBlock(\n urlBlock: string,\n policy: \"preserve\" | \"always\" | \"never\",\n): string {\n if (policy === \"preserve\") return urlBlock;\n\n // Normalize <loc>\n let result = urlBlock.replace(/<loc>([^<]+)<\\/loc>/g, (_, url: string) => {\n return `<loc>${applyTrailingSlashPolicy(url, policy)}</loc>`;\n });\n\n // Normalize href in xhtml:link\n result = result.replace(\n /(<xhtml:link[^>]*href=\")([^\"]+)(\"[^>]*\\/>)/g,\n (_, prefix: string, url: string, suffix: string) => {\n return `${prefix}${applyTrailingSlashPolicy(url, policy)}${suffix}`;\n },\n );\n\n return result;\n}\n\nfunction applyTrailingSlashPolicy(url: string, policy: \"always\" | \"never\"): string {\n try {\n const u = new URL(url);\n if (policy === \"always\" && !u.pathname.endsWith(\"/\")) {\n u.pathname += \"/\";\n } else if (policy === \"never\" && u.pathname !== \"/\" && u.pathname.endsWith(\"/\")) {\n u.pathname = u.pathname.slice(0, -1);\n }\n return u.toString();\n } catch {\n return url;\n }\n}\n","import { getOriginFromAbsoluteUrl, resolveAbsoluteUrl } from \"../lib/url.js\";\nimport type { XDefaultStrategy } from \"../lib/types.js\";\nimport {\n ensureXhtmlNamespace,\n extractLoc,\n extractUrlBlocks,\n extractXhtmlLinks,\n hasXDefault,\n insertXhtmlLink,\n normalizeTrailingSlashInBlock,\n reorderXhtmlLinks,\n xmlEscape,\n} from \"./xml.js\";\n\nexport type InjectOptions = {\n baseUrl?: string;\n xDefaultStrategy?: XDefaultStrategy;\n ensureNamespace?: boolean;\n canonicalLocale?: string;\n order?: \"canonical-first\" | \"preserve\";\n trailingSlash?: \"preserve\" | \"always\" | \"never\";\n};\n\nexport function injectXDefaultIntoSitemapXml(xml: string, options: InjectOptions): string {\n const ensureNamespace = options.ensureNamespace ?? true;\n const xDefaultStrategy = options.xDefaultStrategy ?? { type: \"loc\" };\n const order = options.order ?? \"preserve\";\n const trailingSlash = options.trailingSlash ?? \"preserve\";\n\n const xmlWithNs = ensureNamespace ? ensureXhtmlNamespace(xml) : xml;\n\n const blocks = extractUrlBlocks(xmlWithNs);\n if (blocks.length === 0) return xmlWithNs;\n\n let out = xmlWithNs;\n\n for (const block of blocks) {\n const loc = extractLoc(block);\n if (!loc) continue;\n\n const links = extractXhtmlLinks(block);\n if (links.length === 0) continue;\n\n let nextBlock = block;\n\n if (!hasXDefault(block)) {\n const href = resolveXDefaultHref({\n loc,\n links,\n ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),\n strategy: xDefaultStrategy,\n });\n\n const linkXml = `<xhtml:link rel=\"alternate\" hreflang=\"x-default\" href=\"${xmlEscape(href)}\" />`;\n nextBlock = insertXhtmlLink(nextBlock, linkXml);\n }\n\n // Apply reordering if needed\n if (order === \"canonical-first\") {\n nextBlock = reorderXhtmlLinks(nextBlock, {\n ...(options.canonicalLocale ? { canonicalLocale: options.canonicalLocale } : {}),\n order: \"canonical-first\",\n });\n }\n\n // Apply trailing slash normalization\n if (trailingSlash !== \"preserve\") {\n nextBlock = normalizeTrailingSlashInBlock(nextBlock, trailingSlash);\n }\n\n out = out.replace(block, nextBlock);\n }\n\n return out;\n}\n\nfunction resolveXDefaultHref(args: {\n loc: string;\n links: Array<{ hreflang: string; href: string }>;\n baseUrl?: string;\n strategy: XDefaultStrategy;\n}): string {\n const { loc, links, baseUrl, strategy } = args;\n\n const locAbs = baseUrl ? resolveAbsoluteUrl(loc, baseUrl) : loc;\n const origin = isAbsolute(locAbs) ? getOriginFromAbsoluteUrl(locAbs) : baseUrl;\n\n if (strategy.type === \"loc\") return locAbs;\n if (strategy.type === \"root\") {\n if (!origin) return locAbs;\n return resolveAbsoluteUrl(\"/\", origin);\n }\n if (strategy.type === \"custom\") {\n if (!origin) return strategy.url;\n return resolveAbsoluteUrl(strategy.url, origin);\n }\n if (strategy.type === \"locale\") {\n const found = links.find((l) => l.hreflang === strategy.locale)?.href;\n if (found) return baseUrl ? resolveAbsoluteUrl(found, baseUrl) : found;\n return locAbs;\n }\n const computed = strategy.resolve({ url: locAbs });\n if (!origin) return computed;\n return resolveAbsoluteUrl(computed, origin);\n}\n\nfunction isAbsolute(u: string): boolean {\n return u.startsWith(\"http://\") || u.startsWith(\"https://\");\n}\n","import type { HreflangIssue, HreflangReport } from \"../lib/types.js\";\nimport { extractLoc, extractUrlBlocks, extractXhtmlLinks, hasXhtmlNamespace } from \"./xml.js\";\n\nexport type CheckXmlOptions = {\n requireNamespace?: boolean;\n requireXDefaultWhenMultiple?: boolean;\n requireAbsolute?: boolean;\n checkDuplicateKeys?: boolean;\n checkDuplicateHrefs?: boolean;\n checkHreflangCasing?: boolean;\n originPolicy?: \"same\" | \"allowlist\" | \"off\";\n allowedOrigins?: string[];\n};\n\nexport function checkSitemapXmlHreflang(xml: string, options: CheckXmlOptions): HreflangReport {\n const requireNamespace = options.requireNamespace ?? true;\n const requireXDefaultWhenMultiple = options.requireXDefaultWhenMultiple ?? true;\n const requireAbsolute = options.requireAbsolute ?? true;\n const checkDuplicateKeys = options.checkDuplicateKeys ?? true;\n const checkDuplicateHrefs = options.checkDuplicateHrefs ?? true;\n const checkHreflangCasing = options.checkHreflangCasing ?? true;\n const originPolicy = options.originPolicy ?? \"off\";\n\n const issues: HreflangIssue[] = [];\n\n const blocks = extractUrlBlocks(xml);\n\n if (requireNamespace) {\n const usesXhtml = /<xhtml:link\\b/.test(xml);\n if (usesXhtml && !hasXhtmlNamespace(xml)) {\n issues.push({\n code: \"MISSING_LANGUAGES\",\n entryUrl: \"sitemap.xml\",\n message: 'Missing xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" in <urlset>',\n });\n }\n }\n\n for (const block of blocks) {\n const loc = extractLoc(block);\n if (!loc) continue;\n\n const links = extractXhtmlLinks(block);\n if (links.length === 0) continue;\n\n const hasXDefault = links.some((l) => l.hreflang === \"x-default\");\n if (requireXDefaultWhenMultiple && links.length > 1 && !hasXDefault) {\n issues.push({\n code: \"MISSING_XDEFAULT\",\n entryUrl: loc,\n message: \"Missing x-default hreflang in sitemap url block\",\n });\n }\n\n // Check for duplicate hreflang keys\n if (checkDuplicateKeys) {\n const seenKeys = new Set<string>();\n for (const link of links) {\n if (seenKeys.has(link.hreflang)) {\n issues.push({\n code: \"DUPLICATE_HREFLANG_KEY\",\n entryUrl: loc,\n message: `Duplicate hreflang key: ${link.hreflang}`,\n });\n }\n seenKeys.add(link.hreflang);\n }\n }\n\n // Check for duplicate hrefs (excluding x-default which can share href with another locale)\n if (checkDuplicateHrefs) {\n const hrefToLocales = new Map<string, string[]>();\n for (const link of links) {\n const locales = hrefToLocales.get(link.href) ?? [];\n locales.push(link.hreflang);\n hrefToLocales.set(link.href, locales);\n }\n for (const [href, locales] of hrefToLocales) {\n // Filter out x-default - it's allowed to share href with another locale\n const nonXDefaultLocales = locales.filter((l) => l !== \"x-default\");\n if (nonXDefaultLocales.length > 1) {\n issues.push({\n code: \"DUPLICATE_HREF\",\n entryUrl: loc,\n message: `Duplicate hreflang href detected: ${href} (locales: ${nonXDefaultLocales.join(\", \")})`,\n });\n }\n }\n }\n\n // Check hreflang casing\n if (checkHreflangCasing) {\n for (const link of links) {\n if (!isValidHreflangCasing(link.hreflang)) {\n issues.push({\n code: \"INVALID_HREFLANG_CASING\",\n entryUrl: loc,\n message: `Invalid hreflang casing: ${link.hreflang}. Expected format: en, pt-BR, or x-default`,\n });\n }\n }\n }\n\n // Check origin policy\n if (originPolicy === \"same\") {\n const locOrigin = getOrigin(loc);\n if (locOrigin) {\n for (const link of links) {\n const linkOrigin = getOrigin(link.href);\n if (linkOrigin && linkOrigin !== locOrigin) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Inconsistent origin for ${link.hreflang}: expected ${locOrigin}, got ${linkOrigin}`,\n });\n }\n }\n }\n } else if (originPolicy === \"allowlist\") {\n const allowedOrigins = options.allowedOrigins ?? [];\n for (const link of links) {\n const linkOrigin = getOrigin(link.href);\n if (linkOrigin && !allowedOrigins.includes(linkOrigin)) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Origin not in allowlist for ${link.hreflang}: ${linkOrigin}`,\n });\n }\n }\n const locOrigin = getOrigin(loc);\n if (locOrigin && !allowedOrigins.includes(locOrigin)) {\n issues.push({\n code: \"INCONSISTENT_ORIGIN\",\n entryUrl: loc,\n message: `Origin not in allowlist for loc: ${locOrigin}`,\n });\n }\n }\n\n if (requireAbsolute) {\n for (const link of links) {\n if (!isAbsolute(link.href)) {\n issues.push({\n code: \"NON_ABSOLUTE_URL\",\n entryUrl: loc,\n message: `Non-absolute hreflang href for ${link.hreflang}: ${link.href}`,\n });\n }\n }\n if (!isAbsolute(loc)) {\n issues.push({\n code: \"NON_ABSOLUTE_URL\",\n entryUrl: loc,\n message: `Non-absolute <loc>: ${loc}`,\n });\n }\n }\n }\n\n return { ok: issues.length === 0, issues };\n}\n\nfunction isAbsolute(u: string): boolean {\n return u.startsWith(\"http://\") || u.startsWith(\"https://\");\n}\n\nfunction getOrigin(url: string): string | null {\n try {\n const u = new URL(url);\n return u.origin;\n } catch {\n return null;\n }\n}\n\nfunction isValidHreflangCasing(key: string): boolean {\n if (key === \"x-default\") return true;\n // en, de, uk - only lowercase\n if (/^[a-z]{2}$/.test(key)) return true;\n // pt-BR, en-US - lowercase-UPPERCASE\n if (/^[a-z]{2}-[A-Z]{2}$/.test(key)) return true;\n return false;\n}\n"],"mappings":"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","names":["fs","path","hasXDefault","isAbsolute","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pas7/nextjs-sitemap-hreflang",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Add and validate hreflang alternates + x-default for Next.js sitemaps (App Router / MetadataRoute) with a tiny library + CLI postbuild fixer.",
5
5
  "homepage": "https://github.com/pas7-studio/nextjs-sitemap-hreflang#readme",
6
6
  "repository": {