Skip to content

Commit

Permalink
Add custom script for checking lit.dev redirects
Browse files Browse the repository at this point in the history
  • Loading branch information
aomarks committed Sep 1, 2021
1 parent 4d623e0 commit 65e12fc
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
- name: Build
run: npm run build

- name: Check for broken redirects
run: npm run test:links:redirects

- name: Check for broken links (internal)
run: npm run test:links:internal

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"format": "prettier \"**/*.{ts,js,json,html,css,md}\" --write",
"nuke": "rm -rf node_modules package-lock.json packages/*/node_modules packages/*/package-lock.json && npm install && npx lerna bootstrap",
"test": "npm run test:links",
"test:links": "npm run test:links:internal && npm run test:links:external",
"test:links": "npm run test:links:redirects && npm run test:links:internal && npm run test:links:external",
"test:links:redirects": "node packages/lit-dev-tools/lib/check-redirects.js",
"test:links:internal": "run-p -r start check-links:internal",
"test:links:external": "run-p -r start check-links:external",
"check-links:internal": "wait-on tcp:8080 && blc http://localhost:8080 --recursive --exclude-external --ordered",
Expand Down
7 changes: 5 additions & 2 deletions packages/lit-dev-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@
"test": "npm run build && uvu ./lib \".spec.js$\""
},
"dependencies": {
"@types/jsdom": "^16.2.13",
"@types/markdown-it": "^12.0.1",
"@types/source-map": "^0.5.7",
"@types/strip-comments": "^2.0.1",
"@web/dev-server": "^0.1.6",
"@web/dev-server-core": "^0.3.5",
"ansi-escape-sequences": "^6.2.0",
"fast-glob": "^3.2.5",
"jsdom": "^16.6.0",
"lit-dev-server": "^0.0.0",
"markdown-it-anchor": "^7.1.0",
"minisearch": "^3.0.4",
"node-fetch": "^3.0.0",
"outdent": "^0.8.0",
"playground-elements": "^0.12.1",
"playwright": "^1.8.0",
"source-map": "^0.7.3",
"strip-comments": "^2.0.1",
"striptags": "^3.2.0",
"typedoc": "^0.20.30",
"@types/jsdom": "^16.2.13",
"@types/strip-comments": "^2.0.1",
"uvu": "^0.5.1"
}
}
143 changes: 143 additions & 0 deletions packages/lit-dev-tools/src/check-redirects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/

import * as pathLib from 'path';
import * as fs from 'fs/promises';
import ansi from 'ansi-escape-sequences';

/**
* We're a CommonJS module that needs to import some ES modules.
*
* We're a CommonJS module because Eleventy doesn't support ESM
* (https://github.com/11ty/eleventy/issues/836), and most of the tools in this
* package are for Eleventy.
*
* Node supports `await import(<ESM>)` for importing ESM from CommonJS. However,
* TypeScript doesn't support emitting `import` statements -- it will always
* transpile them to `require`, which breaks interop
* (https://github.com/microsoft/TypeScript/issues/43329).
*
* This is a wacky eval hack until either TypeScript supports CommonJS -> ESM
* interop, or we can rewrite this package as ESM, or we split the tools package
* into two packages: one for CommonJS, one for ESM.
*/
const transpileSafeImport = async (specifier: string) =>
eval(`import("${specifier}")`);

const fetchImportPromise = transpileSafeImport('node-fetch');

const {red, green, yellow, bold, reset} = ansi.style;

const OK = Symbol();
type ErrorMessage = string;

const isUrl = (str: string) => {
try {
new URL(str);
return true;
} catch {
return false;
}
};

const trimTrailingSlash = (str: string) =>
str.endsWith('/') ? str.slice(0, str.length - 1) : str;

const siteOutputDir = pathLib.resolve(
__dirname,
'../',
'../',
'lit-dev-content',
'_site'
);

const checkRedirect = async (
redirect: string
): Promise<ErrorMessage | typeof OK> => {
const {default: fetch} = await fetchImportPromise;
if (isUrl(redirect)) {
// Remote URLs.
let res;
try {
res = await fetch(redirect);
} catch (e) {
return `Fetch error: ${(e as Error).message}`;
}
if (res.status !== 200) {
return `HTTP ${res.status} error`;
}
} else {
// Local paths. A bit hacky, but since we know how Eleventy works, we don't
// need to actually run the server, we can just look directly in the built
// HTML output directory.
const {pathname, hash} = new URL(redirect, 'http://lit.dev');
const diskPath = pathLib.relative(
process.cwd(),
pathLib.join(siteOutputDir, trimTrailingSlash(pathname), 'index.html')
);
let data;
try {
data = await fs.readFile(diskPath, {encoding: 'utf8'});
} catch {
return `Could not find file matching path ${pathname}
Searched for file ${diskPath}`;
}
if (hash) {
// Another hack. Just do a regexp search for e.g. id="somesection" instead
// of DOM parsing. Should be good enough, especially given how regular our
// Markdown generated HTML is.
const idAttrRegExp = new RegExp(`\\sid=["']?${hash.slice(1)}["']?[\\s>]`);
if (data.match(idAttrRegExp) === null) {
return `Could not find section matching hash ${hash}.
Searched in file ${diskPath}`;
}
}
}
return OK;
};

const checkAllRedirects = async () => {
console.log('==========================');
console.log('Checking lit.dev redirects');
console.log('==========================');
console.log();

const {pageRedirects} = await transpileSafeImport(
'lit-dev-server/redirects.js'
);
let fail = false;
const promises = [];
for (const [from, to] of pageRedirects) {
promises.push(
(async () => {
const result = await checkRedirect(to);
if (result === OK) {
console.log(`${bold + green}OK${reset} ${from} -> ${to}`);
} else {
console.log();
console.log(
`${bold + red}BROKEN REDIRECT${reset} ${from} -> ${
yellow + to + reset
}`
);
console.log(result);
console.log();
fail = true;
}
})()
);
}
await Promise.all(promises);
console.log();
if (fail) {
console.log('Redirects were broken!');
process.exit(1);
} else {
console.error('All redirects OK!');
}
};

checkAllRedirects();

0 comments on commit 65e12fc

Please sign in to comment.