-
Notifications
You must be signed in to change notification settings - Fork 23
/
remark-lint-nodejs-links.js
51 lines (46 loc) · 1.46 KB
/
remark-lint-nodejs-links.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import fs from "fs";
import path from "path";
import { pathToFileURL } from "url";
import { lintRule } from "unified-lint-rule";
function* getLinksRecursively(node) {
if (node.url) {
yield node;
}
for (const child of node.children || []) {
yield* getLinksRecursively(child);
}
}
function validateLinks(tree, vfile) {
const currentFileURL = pathToFileURL(path.join(vfile.cwd, vfile.path));
let previousDefinitionLabel;
for (const node of getLinksRecursively(tree)) {
if (node.url[0] !== "#") {
const targetURL = new URL(node.url, currentFileURL);
if (targetURL.protocol === "file:" && !fs.existsSync(targetURL)) {
vfile.message("Broken link", node);
} else if (targetURL.pathname === currentFileURL.pathname) {
const expected = node.url.includes("#")
? node.url.slice(node.url.indexOf("#"))
: "#";
vfile.message(
`Self-reference must start with hash (expected "${expected}", got "${node.url}")`,
node,
);
}
}
if (node.type === "definition") {
if (previousDefinitionLabel && previousDefinitionLabel > node.label) {
vfile.message(
`Unordered reference ("${node.label}" should be before "${previousDefinitionLabel}")`,
node,
);
}
previousDefinitionLabel = node.label;
}
}
}
const remarkLintNodejsLinks = lintRule(
"remark-lint:nodejs-links",
validateLinks,
);
export default remarkLintNodejsLinks;