@pas7/nextjs-sitemap-hreflang 0.5.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
@@ -37,7 +37,7 @@ import { withHreflang } from "@pas7/nextjs-sitemap-hreflang";
37
37
  CLI binary stays the same:
38
38
 
39
39
  ```bash
40
- npx nextjs-sitemap-hreflang check --in public/sitemap.xml --fail-on-missing
40
+ npx nextjs-sitemap-hreflang check --fail-on-missing
41
41
  ```
42
42
 
43
43
  ## Quick start: App Router
@@ -73,13 +73,76 @@ Use library generation + XML validation in CI:
73
73
 
74
74
  ```bash
75
75
  next build
76
- npx nextjs-sitemap-hreflang check --in public/sitemap.xml --fail-on-missing
76
+ npx nextjs-sitemap-hreflang check --fail-on-missing
77
77
  ```
78
78
 
79
79
  Optional postbuild fix step:
80
80
 
81
81
  ```bash
82
- npx nextjs-sitemap-hreflang inject --in public/sitemap.xml --out public/sitemap.xml
82
+ npx nextjs-sitemap-hreflang inject --out public/sitemap.xml
83
+ ```
84
+
85
+ Auto-detect order when `--in` is not provided:
86
+ 1. `public/sitemap.xml`
87
+ 2. `out/sitemap.xml`
88
+ 3. `sitemap.xml`
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
+
97
+ ## Next.js Full SEO Stack (App Router)
98
+
99
+ `app/sitemap.ts`:
100
+
101
+ ```ts
102
+ import type { MetadataRoute } from "next";
103
+ import { routingPAS7, withHreflangFromRouting } from "@pas7/nextjs-sitemap-hreflang";
104
+
105
+ const baseUrl = "https://example.com";
106
+
107
+ const routing = routingPAS7({
108
+ defaultLocale: "en",
109
+ locales: ["en", "uk", "de", "it", "hr"],
110
+ suffixPaths: ["/blog", "/projects", "/services", "/cases", "/contact", "/about", "/privacy", "/terms"],
111
+ detailPathPattern: /^\/(blog|projects|services|cases)\//,
112
+ });
113
+
114
+ export default function sitemap(): MetadataRoute.Sitemap {
115
+ return withHreflangFromRouting(
116
+ [
117
+ { url: `${baseUrl}/` },
118
+ { url: `${baseUrl}/blog` },
119
+ { url: `${baseUrl}/blog/en/hello-world` },
120
+ { url: `${baseUrl}/contact` },
121
+ ],
122
+ routing,
123
+ { baseUrl, ensureXDefault: true },
124
+ );
125
+ }
126
+ ```
127
+
128
+ `app/robots.ts`:
129
+
130
+ ```ts
131
+ import type { MetadataRoute } from "next";
132
+
133
+ export default function robots(): MetadataRoute.Robots {
134
+ return {
135
+ rules: { userAgent: "*", allow: "/" },
136
+ sitemap: "https://example.com/sitemap.xml",
137
+ };
138
+ }
139
+ ```
140
+
141
+ CI script:
142
+
143
+ ```bash
144
+ next build
145
+ npx nextjs-sitemap-hreflang check --fail-on-missing
83
146
  ```
84
147
 
85
148
  ## Universal manifest helper (`.ts` / `.json` / `.md`)
@@ -114,6 +177,12 @@ const routing = routingPAS7({
114
177
  });
115
178
  ```
116
179
 
180
+ Hybrid recipes:
181
+ - Home pages: prefix-as-needed (`/`, `/uk`, `/de`)
182
+ - Content hubs and static pages: suffix locale (`/blog/uk`, `/contact/uk`)
183
+ - Detail pages: locale segment (`/blog/en/slug`, `/blog/uk/slug`)
184
+ - Optional mixed prefix pages via `prefixPaths` (`/uk/about`)
185
+
117
186
  Routing priority inside `routingPAS7`:
118
187
  1. `detailPathPattern`
119
188
  2. `suffixPaths` (or legacy `hubPaths`)
@@ -125,9 +194,10 @@ Routing priority inside `routingPAS7`:
125
194
  ### inject
126
195
 
127
196
  ```bash
128
- npx nextjs-sitemap-hreflang inject --in public/sitemap.xml \
197
+ npx nextjs-sitemap-hreflang inject \
129
198
  --x-default loc \
130
199
  --canonical-locale en \
200
+ --prefer public \
131
201
  --order canonical-first \
132
202
  --trailing-slash never
133
203
  ```
@@ -135,7 +205,8 @@ npx nextjs-sitemap-hreflang inject --in public/sitemap.xml \
135
205
  ### check
136
206
 
137
207
  ```bash
138
- npx nextjs-sitemap-hreflang check --in public/sitemap.xml \
208
+ npx nextjs-sitemap-hreflang check \
209
+ --prefer out \
139
210
  --origin-policy same \
140
211
  --fail-on-missing
141
212
  ```
package/dist/cli.js CHANGED
@@ -1,8 +1,47 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
+ import fs2 from "fs";
5
+ import path2 from "path";
6
+
7
+ // src/cli/resolveSitemapInputPath.ts
4
8
  import fs from "fs";
5
9
  import path from "path";
10
+ var DEFAULT_CANDIDATES = [
11
+ path.join("public", "sitemap.xml"),
12
+ path.join("out", "sitemap.xml"),
13
+ "sitemap.xml"
14
+ ];
15
+ function resolveSitemapInputPath(options) {
16
+ if (options.inPath) return options.inPath;
17
+ const cwd = options.cwd ?? process.cwd();
18
+ const exists = options.exists ?? fs.existsSync;
19
+ const candidates = orderedCandidates(options.prefer ?? "public");
20
+ for (const candidate of candidates) {
21
+ const absolutePath = path.resolve(cwd, candidate);
22
+ if (exists(absolutePath)) return absolutePath;
23
+ }
24
+ throw new Error(
25
+ `Missing --in and sitemap file not found. Tried: ${candidates.join(", ")}`
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
+ }
6
45
 
7
46
  // src/lib/url.ts
8
47
  function resolveAbsoluteUrl(input, baseUrl) {
@@ -340,6 +379,7 @@ function parseArgs(argv) {
340
379
  ensureNamespace: true,
341
380
  json: false,
342
381
  failOnMissing: false,
382
+ prefer: "public",
343
383
  canonicalLocale: null,
344
384
  order: "preserve",
345
385
  trailingSlash: "preserve",
@@ -387,6 +427,13 @@ function parseArgs(argv) {
387
427
  args.failOnMissing = true;
388
428
  continue;
389
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
+ }
390
437
  if (a === "--canonical-locale" && v) {
391
438
  args.canonicalLocale = v;
392
439
  i += 1;
@@ -446,19 +493,22 @@ function printHelp() {
446
493
  "nextjs-sitemap-hreflang",
447
494
  "",
448
495
  "Commands:",
449
- " inject --in <path> [--out <path>] [options]",
450
- " check --in <path> [--json] [--fail-on-missing] [options]",
496
+ " inject [--in <path>] [--out <path>] [options]",
497
+ " check [--in <path>] [--json] [--fail-on-missing] [options]",
451
498
  " transform --in <path> --out <path> [options]",
452
499
  "",
453
500
  "Inject options:",
454
501
  " --x-default loc|root|locale:en|custom:https://example.com/path",
455
502
  " --base-url https://example.com",
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)",
456
505
  " --canonical-locale <locale> Canonical locale for ordering",
457
506
  " --order canonical-first|preserve",
458
507
  " --trailing-slash preserve|always|never",
459
508
  " --no-ensure-namespace",
460
509
  "",
461
510
  "Check options:",
511
+ " --prefer public|out|root Change auto-detect priority (default: public)",
462
512
  " --no-check-duplicate-keys Disable duplicate key check",
463
513
  " --no-check-duplicate-hrefs Disable duplicate href check",
464
514
  " --no-check-hreflang-casing Disable hreflang casing check",
@@ -483,11 +533,11 @@ function parseXDefaultStrategy(raw) {
483
533
  return void 0;
484
534
  }
485
535
  function readFileUtf8(p) {
486
- return fs.readFileSync(p, "utf8");
536
+ return fs2.readFileSync(p, "utf8");
487
537
  }
488
538
  function writeFileUtf8(p, content) {
489
- fs.mkdirSync(path.dirname(p), { recursive: true });
490
- fs.writeFileSync(p, content, "utf8");
539
+ fs2.mkdirSync(path2.dirname(p), { recursive: true });
540
+ fs2.writeFileSync(p, content, "utf8");
491
541
  }
492
542
  async function main() {
493
543
  const args = parseArgs(process.argv.slice(2));
@@ -495,11 +545,24 @@ async function main() {
495
545
  printHelp();
496
546
  process.exit(1);
497
547
  }
498
- if (!args.inPath) {
499
- process.stderr.write("Missing --in\n");
548
+ let resolvedInPath;
549
+ try {
550
+ if (args.command === "transform") {
551
+ if (!args.inPath) {
552
+ process.stderr.write("Missing --in for transform\n");
553
+ process.exit(1);
554
+ }
555
+ resolvedInPath = args.inPath;
556
+ } else {
557
+ resolvedInPath = resolveSitemapInputPath({ inPath: args.inPath, prefer: args.prefer });
558
+ }
559
+ } catch (error) {
560
+ const message = error instanceof Error ? error.message : "Failed to resolve sitemap input path";
561
+ process.stderr.write(`${message}
562
+ `);
500
563
  process.exit(1);
501
564
  }
502
- const xml = readFileUtf8(args.inPath);
565
+ const xml = readFileUtf8(resolvedInPath);
503
566
  if (args.command === "inject") {
504
567
  const strategy = parseXDefaultStrategy(args.xDefault) ?? { type: "loc" };
505
568
  const next = injectXDefaultIntoSitemapXml(xml, {
@@ -510,7 +573,7 @@ async function main() {
510
573
  order: args.order,
511
574
  trailingSlash: args.trailingSlash
512
575
  });
513
- const outPath = args.outPath ?? args.inPath;
576
+ const outPath = args.outPath ?? resolvedInPath;
514
577
  writeFileUtf8(outPath, next);
515
578
  process.stdout.write(`ok: injected
516
579
  `);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.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 { 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 \" --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 if (!args.inPath) {\n process.stderr.write(\"Missing --in\\n\");\n process.exit(1);\n }\n\n const xml = readFileUtf8(args.inPath);\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 ?? args.inPath;\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","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":["hasXDefault","isAbsolute"]}
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.5.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": {