@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 +9 -0
- package/dist/cli.js +31 -3
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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: ${
|
|
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(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\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(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\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.
|
|
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": {
|