@developerportalsg/docportal-cli 0.0.0-stage → 0.2.0
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 +108 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +47 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/check-links.d.ts +12 -0
- package/dist/commands/check-links.d.ts.map +1 -0
- package/dist/commands/check-links.js +121 -0
- package/dist/commands/check-links.js.map +1 -0
- package/dist/lib/check-local.d.ts +15 -0
- package/dist/lib/check-local.d.ts.map +1 -0
- package/dist/lib/check-local.js +215 -0
- package/dist/lib/check-local.js.map +1 -0
- package/dist/lib/check-remote.d.ts +3 -0
- package/dist/lib/check-remote.d.ts.map +1 -0
- package/dist/lib/check-remote.js +121 -0
- package/dist/lib/check-remote.js.map +1 -0
- package/dist/lib/parse.d.ts +18 -0
- package/dist/lib/parse.d.ts.map +1 -0
- package/dist/lib/parse.js +110 -0
- package/dist/lib/parse.js.map +1 -0
- package/dist/lib/resolve.d.ts +14 -0
- package/dist/lib/resolve.d.ts.map +1 -0
- package/dist/lib/resolve.js +98 -0
- package/dist/lib/resolve.js.map +1 -0
- package/package.json +33 -4
package/README.md
CHANGED
|
@@ -1,3 +1,109 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @developerportalsg/docportal-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CLI tools for Documentation Portal publishers. Validates links against the platform's custom Docsify link resolution rules.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @developerportalsg/docportal-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or run without installing:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @developerportalsg/docportal-cli check-links .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Local check (filesystem)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
docportal check-links .
|
|
23
|
+
docportal check-links . --base-path docs
|
|
24
|
+
docportal check-links . --verbose
|
|
25
|
+
docportal check-links . --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Remote check (HTTP)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
docportal check-links --url https://docs.developer.tech.gov.sg --slug my-doc
|
|
32
|
+
docportal check-links --url https://docs.developer.tech.gov.sg --slug my-doc --base-path docs
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Options
|
|
36
|
+
|
|
37
|
+
| Flag | Description |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `--base-path <path>` | Subdirectory serving as docs root (matches docsify `basePath`) |
|
|
40
|
+
| `--url <url>` | Base URL for remote checking (requires `--slug`) |
|
|
41
|
+
| `--slug <slug>` | Document slug for remote checking |
|
|
42
|
+
| `--json` | Output results as JSONL (one JSON object per line) |
|
|
43
|
+
| `--verbose`, `-v` | Show OK links in addition to broken ones |
|
|
44
|
+
|
|
45
|
+
### Exit codes
|
|
46
|
+
|
|
47
|
+
| Code | Meaning |
|
|
48
|
+
|---|---|
|
|
49
|
+
| 0 | All links OK (or all EXPECT annotations match) |
|
|
50
|
+
| 1 | Mismatches found between actual status and EXPECT annotations |
|
|
51
|
+
|
|
52
|
+
## What it checks
|
|
53
|
+
|
|
54
|
+
The Documentation Portal uses a custom Docsify fork with non-standard link resolution. This tool encodes those rules:
|
|
55
|
+
|
|
56
|
+
| Link type | Resolution rule | `../` | `/path` |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| Document links | From doc root | **Broken** | Doc root |
|
|
59
|
+
| Sidebar links | From doc root | **Broken** | Doc root |
|
|
60
|
+
| Images | From current page directory | Works | Doc root |
|
|
61
|
+
| Embeds (`:include`) | From current file directory | Works | **Broken** |
|
|
62
|
+
|
|
63
|
+
### Checks performed
|
|
64
|
+
|
|
65
|
+
- Document and sidebar links resolve from doc root (not current file)
|
|
66
|
+
- `../` in document/sidebar links flagged as broken
|
|
67
|
+
- `/path` in `:include` embeds flagged as broken
|
|
68
|
+
- All link targets verified to exist (filesystem or HTTP)
|
|
69
|
+
- Image paths resolve from current page directory
|
|
70
|
+
- Embed paths resolve from current file directory
|
|
71
|
+
- `:disabled` links skipped
|
|
72
|
+
|
|
73
|
+
## EXPECT annotations
|
|
74
|
+
|
|
75
|
+
Test documents can annotate links with expected outcomes:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
[Link](page-a) <!-- EXPECT:ok -->
|
|
79
|
+
[Link](../page) <!-- EXPECT:broken:dotdot-unsupported -->
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The tool reports **mismatches** when actual results differ from annotations — useful for verifying test cases.
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd tools/docportal-cli
|
|
88
|
+
npm install
|
|
89
|
+
npm run build
|
|
90
|
+
npm test
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Project structure
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
src/
|
|
97
|
+
cli.ts # CLI entry point and subcommand dispatcher
|
|
98
|
+
commands/
|
|
99
|
+
check-links.ts # check-links command (local + remote modes)
|
|
100
|
+
lib/
|
|
101
|
+
resolve.ts # Docsify link resolution rules
|
|
102
|
+
parse.ts # Markdown and sidebar link extraction
|
|
103
|
+
check-local.ts # Filesystem-based link checking
|
|
104
|
+
check-remote.ts # HTTP-based link checking
|
|
105
|
+
tests/
|
|
106
|
+
resolve.test.ts # Unit tests for resolution rules
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Zero runtime dependencies — uses only Node.js built-ins and native `fetch`.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCheckLinks } from "./commands/check-links.js";
|
|
3
|
+
const VERSION = "0.2.0";
|
|
4
|
+
const HELP = `
|
|
5
|
+
docportal — CLI tools for Documentation Portal publishers
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
docportal <command> [options]
|
|
9
|
+
|
|
10
|
+
Commands:
|
|
11
|
+
check-links <path> Check links against Doc Portal resolution rules
|
|
12
|
+
check-links --url Check links against a live published doc
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--help, -h Show this help
|
|
16
|
+
--version Show version
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
docportal check-links .
|
|
20
|
+
docportal check-links . --base-path docs
|
|
21
|
+
docportal check-links . --verbose --json
|
|
22
|
+
docportal check-links --url https://docs.developer.tech.gov.sg --slug my-doc
|
|
23
|
+
`.trim();
|
|
24
|
+
async function main() {
|
|
25
|
+
const args = process.argv.slice(2);
|
|
26
|
+
const command = args[0];
|
|
27
|
+
if (!command || command === "--help" || command === "-h") {
|
|
28
|
+
console.log(HELP);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
if (command === "--version") {
|
|
32
|
+
console.log(VERSION);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
if (command === "check-links") {
|
|
36
|
+
const exitCode = await runCheckLinks(args.slice(1));
|
|
37
|
+
process.exit(exitCode);
|
|
38
|
+
}
|
|
39
|
+
console.error(`Unknown command: ${command}`);
|
|
40
|
+
console.error(`Run 'docportal --help' for usage.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
main().catch((err) => {
|
|
44
|
+
console.error(err);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;CAmBZ,CAAC,IAAI,EAAE,CAAC;AAET,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface CheckLinksOptions {
|
|
2
|
+
localPath?: string;
|
|
3
|
+
basePath: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
slug?: string;
|
|
6
|
+
json: boolean;
|
|
7
|
+
verbose: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseCheckLinksArgs(args: string[]): CheckLinksOptions;
|
|
10
|
+
export declare function runCheckLinks(args: string[]): Promise<number>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=check-links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-links.d.ts","sourceRoot":"","sources":["../../src/commands/check-links.ts"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AA6DD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAwBrE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmCnE"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import { checkLocal } from "../lib/check-local.js";
|
|
4
|
+
import { checkRemote } from "../lib/check-remote.js";
|
|
5
|
+
function printResults(results, verbose, json) {
|
|
6
|
+
if (json) {
|
|
7
|
+
for (const r of results)
|
|
8
|
+
console.log(JSON.stringify(r));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const broken = results.filter((r) => r.status === "broken");
|
|
12
|
+
const ok = results.filter((r) => r.status === "ok");
|
|
13
|
+
const mismatches = results.filter((r) => r.mismatch);
|
|
14
|
+
console.log(`\n${"=".repeat(70)}`);
|
|
15
|
+
console.log(`Link Check Results`);
|
|
16
|
+
console.log(`${"=".repeat(70)}\n`);
|
|
17
|
+
if (broken.length > 0) {
|
|
18
|
+
console.log(`BROKEN LINKS (${broken.length}):\n`);
|
|
19
|
+
for (const r of broken) {
|
|
20
|
+
const expectTag = r.expect ? ` [EXPECT:${r.expect}]` : "";
|
|
21
|
+
console.log(` BROKEN ${r.file}:${r.line} [${r.linkText}](${r.href})${expectTag}`);
|
|
22
|
+
console.log(` → resolves to: ${r.resolved}`);
|
|
23
|
+
if (r.reason)
|
|
24
|
+
console.log(` → reason: ${r.reason}`);
|
|
25
|
+
console.log();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (verbose && ok.length > 0) {
|
|
29
|
+
console.log(`OK LINKS (${ok.length}):\n`);
|
|
30
|
+
for (const r of ok) {
|
|
31
|
+
const expectTag = r.expect ? ` [EXPECT:${r.expect}]` : "";
|
|
32
|
+
console.log(` OK ${r.file}:${r.line} [${r.linkText}](${r.href})${expectTag}`);
|
|
33
|
+
console.log(` → resolves to: ${r.resolved}`);
|
|
34
|
+
console.log();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (mismatches.length > 0) {
|
|
38
|
+
console.log(`\nMISMATCHES (${mismatches.length}) — link status doesn't match EXPECT annotation:\n`);
|
|
39
|
+
for (const r of mismatches) {
|
|
40
|
+
console.log(` ${r.status.toUpperCase().padEnd(7)} ${r.file}:${r.line} [${r.linkText}](${r.href})`);
|
|
41
|
+
console.log(` → expected: ${r.expect}${r.expectReason ? ` (${r.expectReason})` : ""}`);
|
|
42
|
+
console.log(` → actual: ${r.status}${r.reason ? ` — ${r.reason}` : ""}`);
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
console.log(`${"─".repeat(70)}`);
|
|
47
|
+
console.log(`Total: ${results.length} links checked`);
|
|
48
|
+
console.log(` OK: ${ok.length}`);
|
|
49
|
+
console.log(` Broken: ${broken.length}`);
|
|
50
|
+
if (mismatches.length > 0)
|
|
51
|
+
console.log(` Mismatches: ${mismatches.length}`);
|
|
52
|
+
const annotated = results.filter((r) => r.expect);
|
|
53
|
+
if (annotated.length > 0) {
|
|
54
|
+
const correct = annotated.filter((r) => !r.mismatch);
|
|
55
|
+
console.log(` Annotations: ${correct.length}/${annotated.length} correct`);
|
|
56
|
+
}
|
|
57
|
+
console.log();
|
|
58
|
+
}
|
|
59
|
+
export function parseCheckLinksArgs(args) {
|
|
60
|
+
let localPath;
|
|
61
|
+
let basePath = "";
|
|
62
|
+
let url;
|
|
63
|
+
let slug;
|
|
64
|
+
let json = false;
|
|
65
|
+
let verbose = false;
|
|
66
|
+
for (let i = 0; i < args.length; i++) {
|
|
67
|
+
if (args[i] === "--base-path" && args[i + 1]) {
|
|
68
|
+
basePath = args[++i];
|
|
69
|
+
}
|
|
70
|
+
else if (args[i] === "--url" && args[i + 1]) {
|
|
71
|
+
url = args[++i];
|
|
72
|
+
}
|
|
73
|
+
else if (args[i] === "--slug" && args[i + 1]) {
|
|
74
|
+
slug = args[++i];
|
|
75
|
+
}
|
|
76
|
+
else if (args[i] === "--json") {
|
|
77
|
+
json = true;
|
|
78
|
+
}
|
|
79
|
+
else if (args[i] === "--verbose" || args[i] === "-v") {
|
|
80
|
+
verbose = true;
|
|
81
|
+
}
|
|
82
|
+
else if (!args[i].startsWith("-")) {
|
|
83
|
+
localPath = args[i];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { localPath, basePath, url, slug, json, verbose };
|
|
87
|
+
}
|
|
88
|
+
export async function runCheckLinks(args) {
|
|
89
|
+
const { localPath, basePath, url, slug, json, verbose } = parseCheckLinksArgs(args);
|
|
90
|
+
if (url) {
|
|
91
|
+
if (!slug) {
|
|
92
|
+
console.error("Error: --slug required with --url");
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
console.log(`Checking remote: ${url}/docs/${slug}/ (basePath: "${basePath || "(none)"}")`);
|
|
96
|
+
const results = await checkRemote(url, slug, basePath);
|
|
97
|
+
printResults(results, verbose, json);
|
|
98
|
+
return results.some((r) => r.mismatch) ? 1 : 0;
|
|
99
|
+
}
|
|
100
|
+
if (!localPath) {
|
|
101
|
+
console.error("Usage:");
|
|
102
|
+
console.error(" docportal check-links <path> [--base-path <bp>] [--verbose] [--json]");
|
|
103
|
+
console.error(" docportal check-links --url <url> --slug <slug> [--base-path <bp>]");
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
const absPath = path.resolve(localPath);
|
|
107
|
+
if (!fs.existsSync(absPath)) {
|
|
108
|
+
console.error(`Path not found: ${absPath}`);
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
if (json) {
|
|
112
|
+
process.stderr.write(`Checking local: ${absPath} (basePath: "${basePath || "(none)"}")\n`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log(`Checking local: ${absPath} (basePath: "${basePath || "(none)"}")`);
|
|
116
|
+
}
|
|
117
|
+
const results = checkLocal(absPath, basePath);
|
|
118
|
+
printResults(results, verbose, json);
|
|
119
|
+
return results.some((r) => r.mismatch) ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=check-links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-links.js","sourceRoot":"","sources":["../../src/commands/check-links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAoB,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAWrD,SAAS,YAAY,CAAC,OAAsB,EAAE,OAAgB,EAAE,IAAa;IAC3E,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAErD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;YACrF,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,CAAC,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,MAAM,MAAM,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;YACrF,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,iBAAiB,UAAU,CAAC,MAAM,oDAAoD,CAAC,CAAC;QACpG,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACrG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClF,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,UAAU,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAc;IAChD,IAAI,SAA6B,CAAC;IAClC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,GAAuB,CAAC;IAC5B,IAAI,IAAwB,CAAC;IAC7B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7C,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9C,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc;IAChD,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAEpF,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACnD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,SAAS,IAAI,iBAAiB,QAAQ,IAAI,QAAQ,IAAI,CAAC,CAAC;QAC3F,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvD,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACrC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACxF,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QACtF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,OAAO,gBAAgB,QAAQ,IAAI,QAAQ,MAAM,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,gBAAgB,QAAQ,IAAI,QAAQ,IAAI,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC9C,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CheckResult {
|
|
2
|
+
file: string;
|
|
3
|
+
line: number;
|
|
4
|
+
href: string;
|
|
5
|
+
linkText: string;
|
|
6
|
+
kind: string;
|
|
7
|
+
resolved: string;
|
|
8
|
+
status: "ok" | "broken";
|
|
9
|
+
reason: string;
|
|
10
|
+
expect?: "ok" | "broken";
|
|
11
|
+
expectReason?: string;
|
|
12
|
+
mismatch?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function checkLocal(docRootDir: string, basePath: string): CheckResult[];
|
|
15
|
+
//# sourceMappingURL=check-local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-local.d.ts","sourceRoot":"","sources":["../../src/lib/check-local.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsHD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAqG9E"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { resolveDocLink, resolveImageLink, resolveEmbedLink, resolveSidebarLink } from "./resolve.js";
|
|
4
|
+
import { extractLinks, parseSidebar } from "./parse.js";
|
|
5
|
+
function walkMdFiles(dir) {
|
|
6
|
+
const results = [];
|
|
7
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
8
|
+
const full = path.join(dir, entry.name);
|
|
9
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules" && entry.name !== "tools") {
|
|
10
|
+
results.push(...walkMdFiles(full));
|
|
11
|
+
}
|
|
12
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
13
|
+
results.push(full);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return results;
|
|
17
|
+
}
|
|
18
|
+
function findSidebars(dir) {
|
|
19
|
+
const results = [];
|
|
20
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
21
|
+
const full = path.join(dir, entry.name);
|
|
22
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules" && entry.name !== "tools" && entry.name !== "assets") {
|
|
23
|
+
results.push(...findSidebars(full));
|
|
24
|
+
}
|
|
25
|
+
else if (entry.isFile() && entry.name === "_sidebar.md") {
|
|
26
|
+
results.push(full);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return results;
|
|
30
|
+
}
|
|
31
|
+
function fileExists(docRootAbs, relativePath) {
|
|
32
|
+
const full = path.join(docRootAbs, relativePath);
|
|
33
|
+
if (fs.existsSync(full))
|
|
34
|
+
return true;
|
|
35
|
+
if (!relativePath.endsWith(".md")) {
|
|
36
|
+
return fs.existsSync(full + ".md");
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const EXPECT_RE = /<!--\s*EXPECT:(ok|broken)(?::([^\s>]+))?\s*-->/;
|
|
41
|
+
function findSidebarExpect(content, targetLine) {
|
|
42
|
+
const lines = content.split("\n");
|
|
43
|
+
const idx = targetLine - 1;
|
|
44
|
+
if (idx < 0 || idx >= lines.length)
|
|
45
|
+
return undefined;
|
|
46
|
+
const match = lines[idx].match(EXPECT_RE);
|
|
47
|
+
if (match)
|
|
48
|
+
return { expect: match[1], expectReason: match[2] };
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
function resolveFilePath(rootAbs, resolved) {
|
|
52
|
+
const full = path.join(rootAbs, resolved);
|
|
53
|
+
if (fs.existsSync(full) && fs.statSync(full).isFile())
|
|
54
|
+
return resolved;
|
|
55
|
+
if (!resolved.endsWith(".md")) {
|
|
56
|
+
const withMd = resolved + ".md";
|
|
57
|
+
if (fs.existsSync(path.join(rootAbs, withMd)))
|
|
58
|
+
return withMd;
|
|
59
|
+
const readme = path.join(resolved, "README.md");
|
|
60
|
+
if (fs.existsSync(path.join(rootAbs, readme)))
|
|
61
|
+
return readme;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function discoverReachablePages(rootAbs) {
|
|
66
|
+
const reachable = new Set();
|
|
67
|
+
const queue = [];
|
|
68
|
+
// Seed from all _sidebar.md files
|
|
69
|
+
const sidebars = findSidebars(rootAbs);
|
|
70
|
+
for (const sidebarPath of sidebars) {
|
|
71
|
+
const content = fs.readFileSync(sidebarPath, "utf-8");
|
|
72
|
+
for (const link of parseSidebar(content)) {
|
|
73
|
+
const resolved = resolveSidebarLink(link.href, "");
|
|
74
|
+
if (resolved.broken || resolved.type !== "sidebar")
|
|
75
|
+
continue;
|
|
76
|
+
const filePath = resolveFilePath(rootAbs, resolved.resolved);
|
|
77
|
+
if (filePath && !reachable.has(filePath)) {
|
|
78
|
+
reachable.add(filePath);
|
|
79
|
+
queue.push(filePath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Add homepage
|
|
84
|
+
if (!reachable.has("README.md") && fs.existsSync(path.join(rootAbs, "README.md"))) {
|
|
85
|
+
reachable.add("README.md");
|
|
86
|
+
queue.push("README.md");
|
|
87
|
+
}
|
|
88
|
+
// BFS: follow internal doc links and embeds from reachable pages
|
|
89
|
+
while (queue.length > 0) {
|
|
90
|
+
const current = queue.shift();
|
|
91
|
+
const fullPath = path.join(rootAbs, current);
|
|
92
|
+
if (!fs.existsSync(fullPath))
|
|
93
|
+
continue;
|
|
94
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
95
|
+
const relDir = path.dirname(current);
|
|
96
|
+
const links = extractLinks(content, content);
|
|
97
|
+
for (const link of links) {
|
|
98
|
+
let targetPath = null;
|
|
99
|
+
if (link.kind === "doc") {
|
|
100
|
+
const resolved = resolveDocLink(link.href, "");
|
|
101
|
+
if (resolved.broken || resolved.type !== "doc")
|
|
102
|
+
continue;
|
|
103
|
+
targetPath = resolveFilePath(rootAbs, resolved.resolved);
|
|
104
|
+
}
|
|
105
|
+
else if (link.kind === "embed") {
|
|
106
|
+
const resolved = resolveEmbedLink(link.href, relDir);
|
|
107
|
+
if (resolved.broken)
|
|
108
|
+
continue;
|
|
109
|
+
targetPath = resolveFilePath(rootAbs, resolved.resolved);
|
|
110
|
+
}
|
|
111
|
+
if (targetPath && !reachable.has(targetPath)) {
|
|
112
|
+
reachable.add(targetPath);
|
|
113
|
+
queue.push(targetPath);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return reachable;
|
|
118
|
+
}
|
|
119
|
+
export function checkLocal(docRootDir, basePath) {
|
|
120
|
+
const rootAbs = basePath ? path.join(docRootDir, basePath) : docRootDir;
|
|
121
|
+
if (!fs.existsSync(rootAbs)) {
|
|
122
|
+
console.error(`Doc root not found: ${rootAbs}`);
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
const results = [];
|
|
126
|
+
// Phase 1: Check sidebar links
|
|
127
|
+
const sidebars = findSidebars(rootAbs);
|
|
128
|
+
for (const sidebarPath of sidebars) {
|
|
129
|
+
const content = fs.readFileSync(sidebarPath, "utf-8");
|
|
130
|
+
const links = parseSidebar(content);
|
|
131
|
+
for (const link of links) {
|
|
132
|
+
const resolved = resolveSidebarLink(link.href, "");
|
|
133
|
+
const exists = fileExists(rootAbs, resolved.resolved);
|
|
134
|
+
const broken = resolved.broken || !exists;
|
|
135
|
+
const expectMatch = findSidebarExpect(content, link.line);
|
|
136
|
+
results.push({
|
|
137
|
+
file: path.relative(docRootDir, sidebarPath),
|
|
138
|
+
line: link.line,
|
|
139
|
+
href: link.href,
|
|
140
|
+
linkText: link.text,
|
|
141
|
+
kind: "sidebar",
|
|
142
|
+
resolved: resolved.resolved,
|
|
143
|
+
status: broken ? "broken" : "ok",
|
|
144
|
+
reason: resolved.reason || (exists ? "" : `file not found: ${resolved.resolved}`),
|
|
145
|
+
expect: expectMatch?.expect,
|
|
146
|
+
expectReason: expectMatch?.expectReason,
|
|
147
|
+
mismatch: expectMatch?.expect ? (broken ? expectMatch.expect === "ok" : expectMatch.expect === "broken") : undefined,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Phase 2: BFS from sidebar to discover reachable pages
|
|
152
|
+
const reachable = discoverReachablePages(rootAbs);
|
|
153
|
+
const allMdFiles = walkMdFiles(rootAbs);
|
|
154
|
+
const skipped = allMdFiles.filter(f => {
|
|
155
|
+
const rel = path.relative(rootAbs, f);
|
|
156
|
+
return !reachable.has(rel) && path.basename(f) !== "_sidebar.md";
|
|
157
|
+
});
|
|
158
|
+
if (skipped.length > 0) {
|
|
159
|
+
console.log(`Skipped ${skipped.length} unreachable file(s) (not linked from sidebar or any reachable page)`);
|
|
160
|
+
}
|
|
161
|
+
// Phase 3: Check links in reachable pages only
|
|
162
|
+
for (const relFile of reachable) {
|
|
163
|
+
const filePath = path.join(rootAbs, relFile);
|
|
164
|
+
if (!fs.existsSync(filePath))
|
|
165
|
+
continue;
|
|
166
|
+
if (path.basename(relFile) === "_sidebar.md")
|
|
167
|
+
continue;
|
|
168
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
169
|
+
const relDir = path.dirname(relFile);
|
|
170
|
+
const links = extractLinks(content, content);
|
|
171
|
+
for (const link of links) {
|
|
172
|
+
let resolved;
|
|
173
|
+
let exists = false;
|
|
174
|
+
if (link.kind === "doc") {
|
|
175
|
+
resolved = resolveDocLink(link.href, "");
|
|
176
|
+
if (resolved.type === "external" || resolved.type === "anchor" || resolved.type === "mailto")
|
|
177
|
+
continue;
|
|
178
|
+
if (resolved.type === "asset")
|
|
179
|
+
continue;
|
|
180
|
+
exists = !resolved.broken && fileExists(rootAbs, resolved.resolved);
|
|
181
|
+
}
|
|
182
|
+
else if (link.kind === "image") {
|
|
183
|
+
resolved = resolveImageLink(link.href, relDir, "");
|
|
184
|
+
if (resolved.type === "external")
|
|
185
|
+
continue;
|
|
186
|
+
const imgPath = path.join(rootAbs, resolved.resolved);
|
|
187
|
+
exists = fs.existsSync(imgPath);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
resolved = resolveEmbedLink(link.href, relDir);
|
|
191
|
+
if (resolved.type === "external")
|
|
192
|
+
continue;
|
|
193
|
+
const embedPath = path.join(rootAbs, resolved.resolved);
|
|
194
|
+
exists = !resolved.broken && fs.existsSync(embedPath);
|
|
195
|
+
}
|
|
196
|
+
const broken = resolved.broken || !exists;
|
|
197
|
+
const reason = resolved.reason || (exists ? "" : `file not found: ${resolved.resolved}`);
|
|
198
|
+
results.push({
|
|
199
|
+
file: basePath ? path.join(basePath, relFile) : relFile,
|
|
200
|
+
line: link.line,
|
|
201
|
+
href: link.href,
|
|
202
|
+
linkText: link.text,
|
|
203
|
+
kind: link.kind,
|
|
204
|
+
resolved: resolved.resolved,
|
|
205
|
+
status: broken ? "broken" : "ok",
|
|
206
|
+
reason,
|
|
207
|
+
expect: link.expect,
|
|
208
|
+
expectReason: link.expectReason,
|
|
209
|
+
mismatch: link.expect ? (broken ? link.expect === "ok" : link.expect === "broken") : undefined,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return results;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=check-local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-local.js","sourceRoot":"","sources":["../../src/lib/check-local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-remote.d.ts","sourceRoot":"","sources":["../../src/lib/check-remote.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA2BpD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,EAAE,CAAC,CAuGxB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { resolveDocLink, resolveSidebarLink } from "./resolve.js";
|
|
2
|
+
import { parseSidebar, extractLinks } from "./parse.js";
|
|
3
|
+
async function fetchText(url) {
|
|
4
|
+
try {
|
|
5
|
+
const resp = await fetch(url, { redirect: "follow" });
|
|
6
|
+
if (!resp.ok)
|
|
7
|
+
return { text: null, status: resp.status };
|
|
8
|
+
const text = await resp.text();
|
|
9
|
+
return { text, status: resp.status };
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return { text: null, status: 0 };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function headCheck(url) {
|
|
16
|
+
try {
|
|
17
|
+
const resp = await fetch(url, { method: "HEAD", redirect: "follow" });
|
|
18
|
+
return resp.status;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isHtml(text) {
|
|
25
|
+
const s = text.trimStart().slice(0, 10).toLowerCase();
|
|
26
|
+
return s.startsWith("<!") || s.startsWith("<html");
|
|
27
|
+
}
|
|
28
|
+
export async function checkRemote(baseUrl, slug, basePath) {
|
|
29
|
+
const contentRoot = basePath
|
|
30
|
+
? `${baseUrl}/docs/${slug}/${basePath}`
|
|
31
|
+
: `${baseUrl}/docs/${slug}`;
|
|
32
|
+
const sidebarUrl = `${contentRoot}/_sidebar.md`;
|
|
33
|
+
console.log(`Fetching sidebar: ${sidebarUrl}`);
|
|
34
|
+
const { text: sidebarContent, status: sidebarStatus } = await fetchText(sidebarUrl);
|
|
35
|
+
if (!sidebarContent || isHtml(sidebarContent)) {
|
|
36
|
+
console.error(`Failed to fetch sidebar (status ${sidebarStatus})`);
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const sidebarLinks = parseSidebar(sidebarContent);
|
|
40
|
+
const results = [];
|
|
41
|
+
for (const link of sidebarLinks) {
|
|
42
|
+
const resolved = resolveSidebarLink(link.href, "");
|
|
43
|
+
if (resolved.broken) {
|
|
44
|
+
results.push({
|
|
45
|
+
file: "_sidebar.md",
|
|
46
|
+
line: link.line,
|
|
47
|
+
href: link.href,
|
|
48
|
+
linkText: link.text,
|
|
49
|
+
kind: "sidebar",
|
|
50
|
+
resolved: resolved.resolved,
|
|
51
|
+
status: "broken",
|
|
52
|
+
reason: resolved.reason || "",
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const pageUrl = `${contentRoot}/${resolved.resolved}`;
|
|
57
|
+
const status = await headCheck(pageUrl);
|
|
58
|
+
const ok = status >= 200 && status < 400;
|
|
59
|
+
results.push({
|
|
60
|
+
file: "_sidebar.md",
|
|
61
|
+
line: link.line,
|
|
62
|
+
href: link.href,
|
|
63
|
+
linkText: link.text,
|
|
64
|
+
kind: "sidebar",
|
|
65
|
+
resolved: resolved.resolved,
|
|
66
|
+
status: ok ? "ok" : "broken",
|
|
67
|
+
reason: ok ? "" : `HTTP ${status}`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const pageUrls = sidebarLinks
|
|
71
|
+
.map((l) => {
|
|
72
|
+
const r = resolveSidebarLink(l.href, "");
|
|
73
|
+
return r.broken ? null : `${contentRoot}/${r.resolved}`;
|
|
74
|
+
})
|
|
75
|
+
.filter(Boolean);
|
|
76
|
+
const homepageUrl = `${contentRoot}/README.md`;
|
|
77
|
+
if (!pageUrls.includes(homepageUrl))
|
|
78
|
+
pageUrls.unshift(homepageUrl);
|
|
79
|
+
for (const pageUrl of pageUrls) {
|
|
80
|
+
const { text: pageContent } = await fetchText(pageUrl);
|
|
81
|
+
if (!pageContent || isHtml(pageContent))
|
|
82
|
+
continue;
|
|
83
|
+
const relPath = pageUrl.replace(contentRoot + "/", "");
|
|
84
|
+
const links = extractLinks(pageContent, pageContent);
|
|
85
|
+
for (const link of links) {
|
|
86
|
+
if (link.kind !== "doc")
|
|
87
|
+
continue;
|
|
88
|
+
const resolved = resolveDocLink(link.href, "");
|
|
89
|
+
if (resolved.type === "external" || resolved.type === "anchor" || resolved.type === "mailto" || resolved.type === "asset")
|
|
90
|
+
continue;
|
|
91
|
+
if (resolved.broken) {
|
|
92
|
+
results.push({
|
|
93
|
+
file: relPath,
|
|
94
|
+
line: link.line,
|
|
95
|
+
href: link.href,
|
|
96
|
+
linkText: link.text,
|
|
97
|
+
kind: "doc",
|
|
98
|
+
resolved: resolved.resolved,
|
|
99
|
+
status: "broken",
|
|
100
|
+
reason: resolved.reason || "",
|
|
101
|
+
});
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const targetUrl = `${contentRoot}/${resolved.resolved}`;
|
|
105
|
+
const status = await headCheck(targetUrl);
|
|
106
|
+
const ok = status >= 200 && status < 400;
|
|
107
|
+
results.push({
|
|
108
|
+
file: relPath,
|
|
109
|
+
line: link.line,
|
|
110
|
+
href: link.href,
|
|
111
|
+
linkText: link.text,
|
|
112
|
+
kind: "doc",
|
|
113
|
+
resolved: resolved.resolved,
|
|
114
|
+
status: ok ? "ok" : "broken",
|
|
115
|
+
reason: ok ? "" : `HTTP ${status}`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return results;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=check-remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-remote.js","sourceRoot":"","sources":["../../src/lib/check-remote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SidebarLink {
|
|
2
|
+
text: string;
|
|
3
|
+
href: string;
|
|
4
|
+
line: number;
|
|
5
|
+
depth: number;
|
|
6
|
+
section: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface PageLink {
|
|
9
|
+
text: string;
|
|
10
|
+
href: string;
|
|
11
|
+
line: number;
|
|
12
|
+
kind: "doc" | "image" | "embed";
|
|
13
|
+
expect?: "ok" | "broken";
|
|
14
|
+
expectReason?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseSidebar(content: string): SidebarLink[];
|
|
17
|
+
export declare function extractLinks(content: string, originalContent: string): PageLink[];
|
|
18
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwCD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAoB3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgCjF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const MD_LINK_RE = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
2
|
+
const IMG_LINK_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
3
|
+
const HTML_COMMENT_RE = /<!--.*?-->/gs;
|
|
4
|
+
const FENCED_CODE_RE = /^```[^\n]*\n.*?^```/gms;
|
|
5
|
+
const INDENTED_CODE_RE = /^(?: {4}|\t)[^\n]*$/gm;
|
|
6
|
+
const INLINE_CODE_RE = /`[^`\n]+`/g;
|
|
7
|
+
const EXPECT_RE = /<!--\s*EXPECT:(ok|broken)(?::([^\s>]+))?\s*-->/;
|
|
8
|
+
function stripCodeBlocks(content) {
|
|
9
|
+
return content
|
|
10
|
+
.replace(FENCED_CODE_RE, (m) => "\n".repeat(countNewlines(m)))
|
|
11
|
+
.replace(INDENTED_CODE_RE, "")
|
|
12
|
+
.replace(INLINE_CODE_RE, "");
|
|
13
|
+
}
|
|
14
|
+
function stripHtmlComments(content) {
|
|
15
|
+
return content.replace(HTML_COMMENT_RE, (m) => "\n".repeat(countNewlines(m)));
|
|
16
|
+
}
|
|
17
|
+
function countNewlines(s) {
|
|
18
|
+
let n = 0;
|
|
19
|
+
for (const c of s)
|
|
20
|
+
if (c === "\n")
|
|
21
|
+
n++;
|
|
22
|
+
return n;
|
|
23
|
+
}
|
|
24
|
+
function cleanHref(href) {
|
|
25
|
+
const i = href.indexOf(" ");
|
|
26
|
+
return i >= 0 ? href.slice(0, i) : href;
|
|
27
|
+
}
|
|
28
|
+
function lineAt(content, offset) {
|
|
29
|
+
let n = 1;
|
|
30
|
+
for (let i = 0; i < offset && i < content.length; i++) {
|
|
31
|
+
if (content[i] === "\n")
|
|
32
|
+
n++;
|
|
33
|
+
}
|
|
34
|
+
return n;
|
|
35
|
+
}
|
|
36
|
+
export function parseSidebar(content) {
|
|
37
|
+
const cleaned = content.replace(HTML_COMMENT_RE, (m) => "\n".repeat(countNewlines(m)));
|
|
38
|
+
const links = [];
|
|
39
|
+
let currentSection = null;
|
|
40
|
+
for (const [lineno, line] of cleaned.split("\n").entries()) {
|
|
41
|
+
const bold = line.match(/\*\*(.+?)\*\*/);
|
|
42
|
+
if (bold)
|
|
43
|
+
currentSection = bold[1];
|
|
44
|
+
for (const m of line.matchAll(MD_LINK_RE)) {
|
|
45
|
+
const href = cleanHref(m[2].trim());
|
|
46
|
+
if (href.startsWith("#") || href.startsWith("http://") || href.startsWith("https://"))
|
|
47
|
+
continue;
|
|
48
|
+
const stripped = href.split("#")[0].split("?")[0];
|
|
49
|
+
if (!stripped)
|
|
50
|
+
continue;
|
|
51
|
+
const depth = Math.floor((line.length - line.trimStart().length) / 2);
|
|
52
|
+
links.push({ text: m[1], href: stripped, line: lineno + 1, depth, section: currentSection });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return links;
|
|
56
|
+
}
|
|
57
|
+
export function extractLinks(content, originalContent) {
|
|
58
|
+
const forParsing = stripHtmlComments(stripCodeBlocks(content));
|
|
59
|
+
const links = [];
|
|
60
|
+
for (const m of forParsing.matchAll(IMG_LINK_RE)) {
|
|
61
|
+
const href = cleanHref(m[2].trim());
|
|
62
|
+
if (href.startsWith("http://") || href.startsWith("https://"))
|
|
63
|
+
continue;
|
|
64
|
+
const line = lineAt(forParsing, m.index);
|
|
65
|
+
const expect = findExpect(originalContent, line);
|
|
66
|
+
links.push({ text: m[1], href, line, kind: "image", ...expect });
|
|
67
|
+
}
|
|
68
|
+
for (const m of forParsing.matchAll(MD_LINK_RE)) {
|
|
69
|
+
if (forParsing[m.index - 1] === "!")
|
|
70
|
+
continue;
|
|
71
|
+
const fullHref = m[2].trim();
|
|
72
|
+
const href = cleanHref(fullHref);
|
|
73
|
+
if (href.startsWith("#") || href.startsWith("http://") || href.startsWith("https://"))
|
|
74
|
+
continue;
|
|
75
|
+
if (href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
76
|
+
continue;
|
|
77
|
+
if (fullHref.includes(":disabled"))
|
|
78
|
+
continue;
|
|
79
|
+
const line = lineAt(forParsing, m.index);
|
|
80
|
+
const expect = findExpect(originalContent, line);
|
|
81
|
+
if (fullHref.includes("':include'") || fullHref.includes('":include"') || fullHref.includes(":include")) {
|
|
82
|
+
const cleanedHref = href.split("#")[0].split("?")[0];
|
|
83
|
+
links.push({ text: m[1], href: cleanedHref, line, kind: "embed", ...expect });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
links.push({ text: m[1], href, line, kind: "doc", ...expect });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return links;
|
|
90
|
+
}
|
|
91
|
+
function findExpect(originalContent, targetLine) {
|
|
92
|
+
const lines = originalContent.split("\n");
|
|
93
|
+
const lineIdx = targetLine - 1;
|
|
94
|
+
if (lineIdx < 0 || lineIdx >= lines.length)
|
|
95
|
+
return {};
|
|
96
|
+
const lineText = lines[lineIdx];
|
|
97
|
+
const match = lineText.match(EXPECT_RE);
|
|
98
|
+
if (!match) {
|
|
99
|
+
if (lineIdx + 1 < lines.length) {
|
|
100
|
+
const nextLine = lines[lineIdx + 1];
|
|
101
|
+
const nextMatch = nextLine.match(EXPECT_RE);
|
|
102
|
+
if (nextMatch) {
|
|
103
|
+
return { expect: nextMatch[1], expectReason: nextMatch[2] };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
return { expect: match[1], expectReason: match[2] };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type LinkType = "doc" | "image" | "embed" | "sidebar" | "external" | "anchor" | "asset" | "mailto";
|
|
2
|
+
export interface ResolvedLink {
|
|
3
|
+
href: string;
|
|
4
|
+
resolved: string;
|
|
5
|
+
type: LinkType;
|
|
6
|
+
exists?: boolean;
|
|
7
|
+
broken?: boolean;
|
|
8
|
+
reason?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveDocLink(href: string, basePath: string): ResolvedLink;
|
|
11
|
+
export declare function resolveSidebarLink(href: string, basePath: string): ResolvedLink;
|
|
12
|
+
export declare function resolveImageLink(href: string, currentPageDir: string, docRoot: string): ResolvedLink;
|
|
13
|
+
export declare function resolveEmbedLink(href: string, currentFileDir: string): ResolvedLink;
|
|
14
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/lib/resolve.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1G,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAyBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAoC3E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAG/E;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GACd,YAAY,CAgBd;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,YAAY,CAiBd"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
const ASSET_EXTENSIONS = new Set([
|
|
3
|
+
".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".ico", ".bmp",
|
|
4
|
+
".pdf", ".zip", ".tar", ".gz",
|
|
5
|
+
".css", ".js", ".json", ".xml", ".yaml", ".yml",
|
|
6
|
+
".woff", ".woff2", ".ttf", ".eot",
|
|
7
|
+
".mp4", ".webm", ".mp3",
|
|
8
|
+
".xls", ".xlsx", ".html", ".txt",
|
|
9
|
+
]);
|
|
10
|
+
function extOf(p) {
|
|
11
|
+
const dot = p.lastIndexOf(".");
|
|
12
|
+
return dot >= 0 ? p.slice(dot).toLowerCase() : "";
|
|
13
|
+
}
|
|
14
|
+
function isAsset(href) {
|
|
15
|
+
return ASSET_EXTENSIONS.has(extOf(href));
|
|
16
|
+
}
|
|
17
|
+
function ensureMd(p) {
|
|
18
|
+
if (!p.endsWith(".md") && !p.endsWith(".txt"))
|
|
19
|
+
return p + ".md";
|
|
20
|
+
return p;
|
|
21
|
+
}
|
|
22
|
+
function cleanHref(href) {
|
|
23
|
+
const spaceIdx = href.indexOf(" ");
|
|
24
|
+
return spaceIdx >= 0 ? href.slice(0, spaceIdx) : href;
|
|
25
|
+
}
|
|
26
|
+
function stripFragmentAndQuery(href) {
|
|
27
|
+
return href.split("#")[0].split("?")[0];
|
|
28
|
+
}
|
|
29
|
+
export function resolveDocLink(href, basePath) {
|
|
30
|
+
const cleaned = stripFragmentAndQuery(cleanHref(href.trim()));
|
|
31
|
+
if (!cleaned)
|
|
32
|
+
return { href, resolved: "", type: "anchor", reason: "empty after strip" };
|
|
33
|
+
if (cleaned.startsWith("http://") || cleaned.startsWith("https://")) {
|
|
34
|
+
return { href, resolved: cleaned, type: "external" };
|
|
35
|
+
}
|
|
36
|
+
if (cleaned.startsWith("#")) {
|
|
37
|
+
return { href, resolved: cleaned, type: "anchor" };
|
|
38
|
+
}
|
|
39
|
+
if (cleaned.startsWith("mailto:") || cleaned.startsWith("tel:")) {
|
|
40
|
+
return { href, resolved: cleaned, type: "mailto" };
|
|
41
|
+
}
|
|
42
|
+
if (isAsset(cleaned)) {
|
|
43
|
+
return { href, resolved: cleaned, type: "asset" };
|
|
44
|
+
}
|
|
45
|
+
if (cleaned.startsWith("../")) {
|
|
46
|
+
return {
|
|
47
|
+
href,
|
|
48
|
+
resolved: cleaned,
|
|
49
|
+
type: "doc",
|
|
50
|
+
broken: true,
|
|
51
|
+
reason: "../ is not supported by the custom renderer for document links",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const stripped = cleaned.replace(/^\.\//, "").replace(/^\//, "");
|
|
55
|
+
if (!stripped) {
|
|
56
|
+
const resolved = basePath ? path.posix.join(basePath, "README.md") : "README.md";
|
|
57
|
+
return { href, resolved, type: "doc" };
|
|
58
|
+
}
|
|
59
|
+
const withMd = ensureMd(stripped);
|
|
60
|
+
const resolved = basePath ? path.posix.join(basePath, withMd) : withMd;
|
|
61
|
+
return { href, resolved, type: "doc" };
|
|
62
|
+
}
|
|
63
|
+
export function resolveSidebarLink(href, basePath) {
|
|
64
|
+
const result = resolveDocLink(href, basePath);
|
|
65
|
+
return { ...result, type: result.type === "doc" ? "sidebar" : result.type };
|
|
66
|
+
}
|
|
67
|
+
export function resolveImageLink(href, currentPageDir, docRoot) {
|
|
68
|
+
const cleaned = stripFragmentAndQuery(cleanHref(href.trim()));
|
|
69
|
+
if (!cleaned)
|
|
70
|
+
return { href, resolved: "", type: "image" };
|
|
71
|
+
if (cleaned.startsWith("http://") || cleaned.startsWith("https://")) {
|
|
72
|
+
return { href, resolved: cleaned, type: "external" };
|
|
73
|
+
}
|
|
74
|
+
if (cleaned.startsWith("/")) {
|
|
75
|
+
const stripped = cleaned.slice(1);
|
|
76
|
+
const resolved = docRoot ? path.posix.join(docRoot, stripped) : stripped;
|
|
77
|
+
return { href, resolved, type: "image" };
|
|
78
|
+
}
|
|
79
|
+
const resolved = path.posix.normalize(path.posix.join(currentPageDir, cleaned));
|
|
80
|
+
return { href, resolved, type: "image" };
|
|
81
|
+
}
|
|
82
|
+
export function resolveEmbedLink(href, currentFileDir) {
|
|
83
|
+
const cleaned = stripFragmentAndQuery(cleanHref(href.trim()));
|
|
84
|
+
if (!cleaned)
|
|
85
|
+
return { href, resolved: "", type: "embed" };
|
|
86
|
+
if (cleaned.startsWith("/")) {
|
|
87
|
+
return {
|
|
88
|
+
href,
|
|
89
|
+
resolved: cleaned,
|
|
90
|
+
type: "embed",
|
|
91
|
+
broken: true,
|
|
92
|
+
reason: "absolute paths are broken for :include embeds",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const resolved = path.posix.normalize(path.posix.join(currentFileDir, cleaned));
|
|
96
|
+
return { href, resolved, type: "embed" };
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/lib/resolve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@developerportalsg/docportal-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "CLI tools for Documentation Portal publishers — link checking, validation, and more",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"docportal": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "node --import tsx --test tests/**/*.test.ts",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18.0.0"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"documentation-portal",
|
|
25
|
+
"docsify",
|
|
26
|
+
"link-checker",
|
|
27
|
+
"devportal"
|
|
28
|
+
],
|
|
29
|
+
"author": "Developer Portal Team",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"tsx": "^4.0.0",
|
|
33
|
+
"typescript": "^5.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|