From 08067e43c6fea4b090889cfea68f83ecbcdb6e75 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 22:33:12 +0000 Subject: [PATCH] Fix: Re-enable no-broken-links and ignore rel=nofollow Re-enable the `no-broken-links` hint in the web-recommended configuration. Update the hint logic to ignore `` elements that contain `rel="nofollow"` when checking for broken links (404, 410, 500, 503 status codes). This prevents reports for links explicitly marked as not endorsed. Add unit tests to verify that links with `rel="nofollow"` are correctly skipped, while ensuring that regular broken links are still reported as expected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Fix #5754 --- .../configuration-web-recommended/index.json | 1 + packages/hint-no-broken-links/src/hint.ts | 10 +++ packages/hint-no-broken-links/tests/tests.ts | 76 +++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/packages/configuration-web-recommended/index.json b/packages/configuration-web-recommended/index.json index ab84c1dc472..8b0022e86b1 100644 --- a/packages/configuration-web-recommended/index.json +++ b/packages/configuration-web-recommended/index.json @@ -28,6 +28,7 @@ "meta-charset-utf-8", "meta-viewport", "no-bom", + "no-broken-links", "no-disallowed-headers", "no-friendly-error-pages", "no-html-only-headers", diff --git a/packages/hint-no-broken-links/src/hint.ts b/packages/hint-no-broken-links/src/hint.ts index 6b7311789d2..3ffe5ba96ad 100644 --- a/packages/hint-no-broken-links/src/hint.ts +++ b/packages/hint-no-broken-links/src/hint.ts @@ -218,6 +218,16 @@ export default class NoBrokenLinksHint implements IHint { const requests: Promise[] = []; for (const url of urls) { + // Skip anchor links with rel="nofollow". + if (element.nodeName === 'A') { + const rel = element.getAttribute('rel'); + + if (rel && rel.toLowerCase().includes('nofollow')) { + debug(`Skipping URL ${url} due to rel="nofollow"`); + continue; + } + } + /* * If the URL is not HTTP or HTTPS (e.g. `mailto:`), * there is no need to validate. diff --git a/packages/hint-no-broken-links/tests/tests.ts b/packages/hint-no-broken-links/tests/tests.ts index b1a963a42a3..6dc1dff4530 100644 --- a/packages/hint-no-broken-links/tests/tests.ts +++ b/packages/hint-no-broken-links/tests/tests.ts @@ -91,6 +91,30 @@ const bodyWithInvalidDomainPreconnectLinkTag = `
`; +// Snippets for nofollow tests +const bodyWithNoFollowBrokenLink = `
+Broken NoFollow +
`; + +const bodyWithNoFollowValidLink = `
+Valid NoFollow +
`; + +const bodyWithNoFollowMultipleRel = `
+Broken NoFollow Multiple +
`; + +const bodyWithMixedLinks = `
+Broken NoFollow +Broken Regular +
`; + +const bodyWithNoFollowAndRegularBroken = `
+Broken Anchor NoFollow + +
`; + + const tests: HintTest[] = [ { name: `This test should pass as it has links with valid href value`, @@ -288,6 +312,58 @@ const tests: HintTest[] = [ }], serverConfig: generateHTMLPage('', bodyWithInvalidDomainPreconnectLinkTag) }, + // New tests for rel="nofollow" + { + name: `Anchor with rel="nofollow" pointing to a 404 should not report an error`, + serverConfig: { + '/': { content: generateHTMLPage('', bodyWithNoFollowBrokenLink) }, + '/404': { status: 404 } + } + // No reports expected + }, + { + name: `Anchor with rel="nofollow" pointing to a valid resource should not report an error`, + serverConfig: { + '/': { content: generateHTMLPage('', bodyWithNoFollowValidLink) }, + '/valid': { content: 'Valid page' } + } + // No reports expected + }, + { + name: `Anchor with multiple rel values including "nofollow" pointing to a 404 should not report an error`, + serverConfig: { + '/': { content: generateHTMLPage('', bodyWithNoFollowMultipleRel) }, + '/404': { status: 404 } + } + // No reports expected + }, + { + name: `Mixed content: Regular broken link should report, nofollow broken link should not`, + reports: [{ + message: `Broken link found (404 response).`, + severity: Severity.error, + location: { column: 50, line: 2 } // Location of the regular link + }], + serverConfig: { + '/': { content: generateHTMLPage('', bodyWithMixedLinks) }, + '/404-nofollow': { status: 404 }, + '/404-regular': { status: 404 } + } + }, + { + name: `Mixed content: Broken image should report, nofollow broken anchor should not`, + reports: [{ + message: `Broken link found (404 response).`, + severity: Severity.error, + location: { column: 8, line: 3 } // Location of the image tag + }], + serverConfig: { + '/': { content: generateHTMLPage('', bodyWithNoFollowAndRegularBroken) }, + '/404-anchor': { status: 404 }, + '/404.png': { status: 404 } + } + }, + // End of new tests for rel="nofollow" { name: `This test should fail as it has a loop`, reports: [