Skip to content

Commit 56cda15

Browse files
committed
Add custom script for checking lit.dev redirects
1 parent 691ade4 commit 56cda15

File tree

5 files changed

+273
-3
lines changed

5 files changed

+273
-3
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
- name: Build
2323
run: npm run build
2424

25+
- name: Check for broken redirects
26+
run: npm run test:links:redirects
27+
2528
- name: Check for broken links (internal)
2629
run: npm run test:links:internal
2730

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"format": "prettier \"**/*.{ts,js,json,html,css,md}\" --write",
1212
"nuke": "rm -rf node_modules package-lock.json packages/*/node_modules packages/*/package-lock.json && npm install && npx lerna bootstrap",
1313
"test": "npm run test:links",
14-
"test:links": "npm run test:links:internal && npm run test:links:external",
14+
"test:links": "npm run test:links:redirects && npm run test:links:internal && npm run test:links:external",
15+
"test:links:redirects": "node packages/lit-dev-tools-esm/lib/check-redirects.js",
1516
"test:links:internal": "run-p -r start check-links:internal",
1617
"test:links:external": "run-p -r start check-links:external",
1718
"check-links:internal": "wait-on tcp:8080 && blc http://localhost:8080 --recursive --exclude-external --ordered",

packages/lit-dev-tools-esm/package-lock.json

Lines changed: 142 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
import * as pathLib from 'path';
8+
import * as fs from 'fs/promises';
9+
import ansi from 'ansi-escape-sequences';
10+
import fetch from 'node-fetch';
11+
import {pageRedirects} from 'lit-dev-server/redirects.js';
12+
import {fileURLToPath} from 'url';
13+
14+
const __filename = fileURLToPath(import.meta.url);
15+
const __dirname = pathLib.dirname(__filename);
16+
17+
const {red, green, yellow, bold, reset} = ansi.style;
18+
19+
const OK = Symbol();
20+
type ErrorMessage = string;
21+
22+
const isUrl = (str: string) => {
23+
try {
24+
new URL(str);
25+
return true;
26+
} catch {
27+
return false;
28+
}
29+
};
30+
31+
const trimTrailingSlash = (str: string) =>
32+
str.endsWith('/') ? str.slice(0, str.length - 1) : str;
33+
34+
const siteOutputDir = pathLib.resolve(
35+
__dirname,
36+
'../',
37+
'../',
38+
'lit-dev-content',
39+
'_site'
40+
);
41+
42+
const checkRedirect = async (
43+
redirect: string
44+
): Promise<ErrorMessage | typeof OK> => {
45+
if (isUrl(redirect)) {
46+
// Remote URLs.
47+
let res;
48+
try {
49+
res = await fetch(redirect);
50+
} catch (e) {
51+
return `Fetch error: ${(e as Error).message}`;
52+
}
53+
if (res.status !== 200) {
54+
return `HTTP ${res.status} error`;
55+
}
56+
} else {
57+
// Local paths. A bit hacky, but since we know how Eleventy works, we don't
58+
// need to actually run the server, we can just look directly in the built
59+
// HTML output directory.
60+
const {pathname, hash} = new URL(redirect, 'http://lit.dev');
61+
const diskPath = pathLib.relative(
62+
process.cwd(),
63+
pathLib.join(siteOutputDir, trimTrailingSlash(pathname), 'index.html')
64+
);
65+
let data;
66+
try {
67+
data = await fs.readFile(diskPath, {encoding: 'utf8'});
68+
} catch {
69+
return `Could not find file matching path ${pathname}
70+
Searched for file ${diskPath}`;
71+
}
72+
if (hash) {
73+
// Another hack. Just do a regexp search for e.g. id="somesection" instead
74+
// of DOM parsing. Should be good enough, especially given how regular our
75+
// Markdown generated HTML is.
76+
const idAttrRegExp = new RegExp(`\\sid=["']?${hash.slice(1)}["']?[\\s>]`);
77+
if (data.match(idAttrRegExp) === null) {
78+
return `Could not find section matching hash ${hash}.
79+
Searched in file ${diskPath}`;
80+
}
81+
}
82+
}
83+
return OK;
84+
};
85+
86+
const checkAllRedirects = async () => {
87+
console.log('==========================');
88+
console.log('Checking lit.dev redirects');
89+
console.log('==========================');
90+
console.log();
91+
92+
let fail = false;
93+
const promises = [];
94+
for (const [from, to] of pageRedirects) {
95+
promises.push(
96+
(async () => {
97+
const result = await checkRedirect(to);
98+
if (result === OK) {
99+
console.log(`${bold + green}OK${reset} ${from} -> ${to}`);
100+
} else {
101+
console.log();
102+
console.log(
103+
`${bold + red}BROKEN REDIRECT${reset} ${from} -> ${
104+
yellow + to + reset
105+
}`
106+
);
107+
console.log(result);
108+
console.log();
109+
fail = true;
110+
}
111+
})()
112+
);
113+
}
114+
await Promise.all(promises);
115+
console.log();
116+
if (fail) {
117+
console.log('Redirects were broken!');
118+
process.exit(1);
119+
} else {
120+
console.error('All redirects OK!');
121+
}
122+
};
123+
124+
checkAllRedirects();

packages/lit-dev-tools/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
"test": "npm run build && uvu ./lib \".spec.js$\""
1313
},
1414
"dependencies": {
15+
"@types/jsdom": "^16.2.13",
1516
"@types/markdown-it": "^12.0.1",
1617
"@types/source-map": "^0.5.7",
18+
"@types/strip-comments": "^2.0.1",
1719
"@web/dev-server": "^0.1.6",
1820
"@web/dev-server-core": "^0.3.5",
1921
"fast-glob": "^3.2.5",
@@ -27,8 +29,6 @@
2729
"strip-comments": "^2.0.1",
2830
"striptags": "^3.2.0",
2931
"typedoc": "^0.20.30",
30-
"@types/jsdom": "^16.2.13",
31-
"@types/strip-comments": "^2.0.1",
3232
"uvu": "^0.5.1"
3333
}
3434
}

0 commit comments

Comments
 (0)