Skip to content

Commit f97050b

Browse files
authored
Infrastructure: link-checker.js: Check if any of the known pageIds include the hash being checked for (pull #2812)
Modifies link checker so that when GitHub dynamically prepends "user-content-" to fragment IDs that are in user-generated content, the link test will pass.
1 parent 2b619c1 commit f97050b

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

.link-checker.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ module.exports = {
1111
'.carousel-image a',
1212
],
1313
},
14+
hashCheckHandlers: [
15+
{
16+
name: 'github',
17+
pattern: /^https:\/\/github\.com\/.*/,
18+
matchHash: (ids, hash) =>
19+
ids.includes(hash) || ids.includes(`user-content-${hash}`),
20+
},
21+
],
1422
ignoreHashesOnExternalPagesMatchingRegex: [
1523
// Some hash links are resolved with JS and are therefore difficult to check algorithmically
16-
/^https:\/\/github\.com\/.*\/wiki\//,
1724
/^https:\/\/html\.spec\.whatwg\.org\/multipage\//,
1825
],
1926
};

scripts/link-checker.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ async function checkLinks() {
3333
return getLineNumber;
3434
};
3535

36+
const checkPathForHash = (hrefOrSrc, ids = [], hash) => {
37+
// On some websites, the ids may not exactly match the hash included
38+
// in the link.
39+
// For e.g. GitHub will prepend client facing ids with their own
40+
// calculated value. A heading in a README for example could be
41+
// 'Foo bar', navigated to with https://github.com/foo/bar#foo-bar,
42+
// but GitHub calculates the actual markup id included in the document
43+
// as being 'user-content-foo-bar' for its own page processing purposes.
44+
//
45+
// See https://github.com/w3c/aria-practices/issues/2809
46+
const handler = options.hashCheckHandlers.find(({ pattern }) =>
47+
pattern.test(hrefOrSrc)
48+
);
49+
if (handler) return handler.matchHash(ids, hash);
50+
else return ids.includes(hash);
51+
};
52+
3653
const countConsoleErrors = () => {
3754
let errorCount = 0;
3855

@@ -227,7 +244,11 @@ async function checkLinks() {
227244

228245
let matchesHash = true;
229246
if (hash) {
230-
matchesHash = !!matchingPage?.ids.includes(hash);
247+
matchesHash = !!checkPathForHash(
248+
pathMinusHash,
249+
matchingPage?.ids,
250+
hash
251+
);
231252
}
232253

233254
const isLinkBroken = !(
@@ -274,7 +295,11 @@ async function checkLinks() {
274295
hrefOrSrc.match(pattern)
275296
);
276297

277-
if (!isHashCheckingDisabled && hash && !pageData.ids.includes(hash)) {
298+
if (
299+
!isHashCheckingDisabled &&
300+
hash &&
301+
!checkPathForHash(hrefOrSrc, pageData.ids, hash)
302+
) {
278303
consoleError(
279304
`Found broken external link on ${htmlPath}:${lineNumber}:${columnNumber}, ` +
280305
'hash not found on page'

0 commit comments

Comments
 (0)