Skip to content

Commit

Permalink
Infrastructure: link-checker.js: Check if any of the known pageIds
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
howard-e committed Oct 2, 2023
1 parent 2b619c1 commit f97050b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
9 changes: 8 additions & 1 deletion .link-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@ module.exports = {
'.carousel-image a',
],
},
hashCheckHandlers: [
{
name: 'github',
pattern: /^https:\/\/github\.com\/.*/,
matchHash: (ids, hash) =>
ids.includes(hash) || ids.includes(`user-content-${hash}`),
},
],
ignoreHashesOnExternalPagesMatchingRegex: [
// Some hash links are resolved with JS and are therefore difficult to check algorithmically
/^https:\/\/github\.com\/.*\/wiki\//,
/^https:\/\/html\.spec\.whatwg\.org\/multipage\//,
],
};
29 changes: 27 additions & 2 deletions scripts/link-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ async function checkLinks() {
return getLineNumber;
};

const checkPathForHash = (hrefOrSrc, ids = [], hash) => {
// On some websites, the ids may not exactly match the hash included
// in the link.
// For e.g. GitHub will prepend client facing ids with their own
// calculated value. A heading in a README for example could be
// 'Foo bar', navigated to with https://github.com/foo/bar#foo-bar,
// but GitHub calculates the actual markup id included in the document
// as being 'user-content-foo-bar' for its own page processing purposes.
//
// See https://github.com/w3c/aria-practices/issues/2809
const handler = options.hashCheckHandlers.find(({ pattern }) =>
pattern.test(hrefOrSrc)
);
if (handler) return handler.matchHash(ids, hash);
else return ids.includes(hash);
};

const countConsoleErrors = () => {
let errorCount = 0;

Expand Down Expand Up @@ -227,7 +244,11 @@ async function checkLinks() {

let matchesHash = true;
if (hash) {
matchesHash = !!matchingPage?.ids.includes(hash);
matchesHash = !!checkPathForHash(
pathMinusHash,
matchingPage?.ids,
hash
);
}

const isLinkBroken = !(
Expand Down Expand Up @@ -274,7 +295,11 @@ async function checkLinks() {
hrefOrSrc.match(pattern)
);

if (!isHashCheckingDisabled && hash && !pageData.ids.includes(hash)) {
if (
!isHashCheckingDisabled &&
hash &&
!checkPathForHash(hrefOrSrc, pageData.ids, hash)
) {
consoleError(
`Found broken external link on ${htmlPath}:${lineNumber}:${columnNumber}, ` +
'hash not found on page'
Expand Down

0 comments on commit f97050b

Please sign in to comment.