-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlink-checker.js
65 lines (56 loc) · 1.92 KB
/
link-checker.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import graph from "./public/graph.json" with { type: "json" };
import { parse } from "node-html-parser";
import fs from "fs/promises";
const report = {};
for (const page of graph) {
const { outputHref, route } = page;
const html = await fs.readFile(new URL(outputHref), "utf-8");
const root = parse(html);
const links = root.querySelectorAll("a");
links.forEach((link) => {
if (!route.startsWith("/blog/") && link.getAttribute("href").startsWith("/")) {
const linkUrl = new URL(`https://www.greenwoodjs.dev${link.getAttribute("href")}`);
const { pathname, hash } = linkUrl;
const matchingRoute = graph.find((page) => page.route === pathname);
if (!matchingRoute) {
if (!report[route]) {
report[route] = {
violations: [],
};
}
report[route].violations.push({
link: pathname,
});
}
if (matchingRoute && hash !== "") {
const { tableOfContents } = matchingRoute.data;
const match = tableOfContents.find((toc) => toc.slug === hash.replace("#", ""));
if (!match) {
if (!report[route]) {
report[route] = {
violations: [],
};
}
report[route].violations.push({
hash,
});
}
}
}
});
}
if (Object.keys(report).length === 0) {
console.log("✅ all links checked successfully and no broken links found");
} else {
for (const r of Object.keys(report)) {
console.log("---------------------------------");
console.log(`🚨 reporting violations for route ${r}...`);
report[r].violations.forEach((violation, idx) => {
if (violation.link) {
console.error(`${idx + 1}) Could not find matching route for href => ${violation.link}`);
} else if (violation.hash) {
console.error(`${idx + 1}) Could not find matching heading for hash => ${violation.hash}`);
}
});
}
}