forked from graphile/graphile.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
link-check.js
115 lines (109 loc) · 3.65 KB
/
link-check.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* eslint-disable no-console */
const fs = require("fs");
const path = require("path");
const glob = require("glob");
const chalk = require("chalk");
const base = `${__dirname}/public`;
const files = glob.sync(`${base}/**/*.html`);
const validLinks = files.map(f =>
f.substr(base.length).replace(/index.html$/, "")
);
function allMatches(str, regex) {
const all = [];
// eslint-disable-next-line no-constant-condition
while (true) {
const matches = regex.exec(str);
if (!matches) break;
all.push(matches[1]);
}
return all;
}
let invalid = 0;
for (const file of files) {
const filePretty = chalk.bold(
path
.relative(__dirname, file)
.replace(/^public/, "")
.replace(/index.html$/, "")
);
const contents = fs.readFileSync(file, "utf8");
if (contents.indexOf("Postgraphile") >= 0) {
invalid++;
console.error(
`${filePretty} mentions 'Postgraphile'; please change to 'PostGraphile' or 'postgraphile' for consistency.`
);
}
const links = allMatches(contents, /<a[^>]+href="([^"]+)"/g);
for (const link of links) {
const trimmed = link.replace(/[?#].*$/, "");
if (trimmed.match(/\.(js|css|png|svg|webmanifest)$/)) {
// Meh, resources
continue;
}
const isGitHub = trimmed.match(/^https?:\/\/(?:www\.)?github\.com/);
const isLearnDotGraphile = trimmed.match(
/^https?:\/\/learn\.graphile\.org\//
);
const isGraphile = trimmed.match(/^https?:\/\/graphile\.(org|meh)/);
const isLocalhost = trimmed.match(
/^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0):(?:[^5]|5[^0]|50[^0]|500[^0])/
);
const isGraphileOrLocalhost = isGraphile || isLocalhost;
if (isGitHub || isLearnDotGraphile || !isGraphileOrLocalhost) {
const matches = trimmed.match(
/^https?:\/\/(?:www\.)?postgresql.org\/docs\/([^\/]+)\/[^#]*(#.*)?$/
);
if (matches) {
const [_, docVersion, hash] = matches;
const CURRENT_VERSION = "11";
/*
* It's better to link to /docs/current/ in general, but when there's a
* hash we want to ensure the links don't break when we go up a major
* version so linking to /docs/11/ is appropriate then. Linking to
* older docs is currently not accepted, but we may need to add
* exceptions in future.
*/
const isOkay =
docVersion === CURRENT_VERSION || (!hash && docVersion === "current");
if (!isOkay) {
invalid++;
if (hash) {
console.error(
`${filePretty} has disallowed link to '${link}' (please ensure PostgreSQL documentation links with hashes link to the '/docs/${CURRENT_VERSION}/...' documentation, you linked to '/docs/${docVersion}/...')`
);
} else {
console.error(
`${filePretty} has disallowed link to '${link}' (please ensure PostgreSQL documentation links link to the '/docs/current/...' documentation, you linked to '/docs/${docVersion}/...')`
);
}
// Handled above
continue;
}
}
// TODO: check the link resolves
// Absolute, continue
continue;
}
if (trimmed.match(/^mailto:/)) {
// mailto:, continue
continue;
}
if (trimmed === "") {
// Anchor link
continue;
}
if (validLinks.indexOf(trimmed) >= 0) {
// Cool, looks legit
continue;
}
invalid++;
console.error(
`${filePretty} has disallowed link to '${link}' (please ensure links start with '/' if possible, do not include https://graphile.org)`
);
}
}
if (invalid > 0) {
console.log();
console.log(`${invalid} errors found 😔`);
process.exit(1);
}