diff --git a/test/fixtures/directory-path-links-test.html b/test/fixtures/directory-path-links-test.html new file mode 100644 index 0000000..0484884 --- /dev/null +++ b/test/fixtures/directory-path-links-test.html @@ -0,0 +1,25 @@ + + + + + Directory Path Links Test + + + +

Testing Directory Path Links

+

This page tests various directory link scenarios:

+ + + diff --git a/test/fixtures/directory-with-index/index.html b/test/fixtures/directory-with-index/index.html new file mode 100644 index 0000000..ea32756 --- /dev/null +++ b/test/fixtures/directory-with-index/index.html @@ -0,0 +1,12 @@ + + + + + Directory Index + + + +

Directory Index Page

+

This is the index page for a directory that has an index.html file.

+ + diff --git a/test/fixtures/directory-with-no-index-with-twin.html b/test/fixtures/directory-with-no-index-with-twin.html new file mode 100644 index 0000000..4ec7a21 --- /dev/null +++ b/test/fixtures/directory-with-no-index-with-twin.html @@ -0,0 +1,12 @@ + + + + + Twin File + + + +

Twin File

+

This is the twin HTML file for the directory-with-no-index-with-twin directory.

+ + diff --git a/test/fixtures/directory-with-no-index-with-twin/some-page.html b/test/fixtures/directory-with-no-index-with-twin/some-page.html new file mode 100644 index 0000000..6f6ab9b --- /dev/null +++ b/test/fixtures/directory-with-no-index-with-twin/some-page.html @@ -0,0 +1,12 @@ + + + + + Some Page in Twin Directory + + + +

Some Page in Directory with No Index but Has Twin

+

This is a page in a directory that has no index.html file but has a twin HTML file at the same level.

+ + diff --git a/test/fixtures/directory-with-no-index/some-page.html b/test/fixtures/directory-with-no-index/some-page.html new file mode 100644 index 0000000..e72b2a7 --- /dev/null +++ b/test/fixtures/directory-with-no-index/some-page.html @@ -0,0 +1,12 @@ + + + + + Some Page + + + +

Some Page in Directory with No Index

+

This is a page in a directory that has no index.html file.

+ + diff --git a/test/fixtures/required-results.json b/test/fixtures/required-results.json index a818324..b0b9eae 100644 --- a/test/fixtures/required-results.json +++ b/test/fixtures/required-results.json @@ -141,5 +141,67 @@ "selector": "html > body > img", "ruleUrl": "https://html-validate.org/rules/wcag/h37.html" } + ], + "test/fixtures/directory-path-links-test.html": [ + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-no-index\" is broken.", + "offset": 367, + "line": 12, + "column": 44, + "size": 1, + "selector": "html > body > ul > li:nth-child(1) > a" + }, + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-no-index/\" is broken.", + "offset": 464, + "line": 13, + "column": 45, + "size": 1, + "selector": "html > body > ul > li:nth-child(2) > a" + }, + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-no-index/index\" is broken.", + "offset": 567, + "line": 14, + "column": 50, + "size": 1, + "selector": "html > body > ul > li:nth-child(3) > a" + }, + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-index\" is broken.", + "offset": 666, + "line": 15, + "column": 41, + "size": 1, + "selector": "html > body > ul > li:nth-child(4) > a" + }, + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-no-index-with-twin/\" is broken.", + "offset": 1068, + "line": 19, + "column": 55, + "size": 1, + "selector": "html > body > ul > li:nth-child(8) > a" + }, + { + "ruleId": "pacific-medical-training/internal-links", + "severity": 2, + "message": "internal link \"directory-with-no-index-with-twin/index\" is broken.", + "offset": 1200, + "line": 21, + "column": 58, + "size": 1, + "selector": "html > body > ul > li:nth-child(9) > a" + } ] } diff --git a/test/plugin.html-validate.https-links.mjs b/test/plugin.html-validate.https-links.mjs index d9c7bcf..903833f 100644 --- a/test/plugin.html-validate.https-links.mjs +++ b/test/plugin.html-validate.https-links.mjs @@ -60,7 +60,7 @@ export default class EnsureHttpsRules extends Rule { const curlOutput = execSync(curlCommand, { encoding: "utf-8" }); // If the link is accessible via HTTPS, report it as insecure - if (curlOutput.includes("HTTP/2 200")) { + if (curlOutput.includes("200")) { this.db.prepare("REPLACE INTO urls (url, found, time) VALUES (?, 1, unixepoch())").run(url); const insecureRow = this.db.prepare("SELECT found, time FROM urls WHERE url = ?").get(url); this.report({ diff --git a/test/plugin.html-validate.internal-links.mjs b/test/plugin.html-validate.internal-links.mjs index 85c2d4c..10101f2 100644 --- a/test/plugin.html-validate.internal-links.mjs +++ b/test/plugin.html-validate.internal-links.mjs @@ -44,7 +44,7 @@ export default class CheckInternalLinks extends Rule { return this.fileExistsCache.get(path); } - const exists = fs.existsSync(path); + const exists = fs.existsSync(path) && fs.lstatSync(path).isFile(); this.fileExistsCache.set(path, exists); return exists; } @@ -60,17 +60,25 @@ export default class CheckInternalLinks extends Rule { const basePath = path.dirname(element.location.filename); let resolvedPath = path.resolve(basePath, resolvedLink); - // If it's a directory, append the index file - if (fs.existsSync(resolvedPath) && fs.lstatSync(resolvedPath).isDirectory()) { - resolvedPath = path.join(resolvedPath, this.indexFile); - } - - // Pass if the URL matches a file or an alternative extension - if ( - this.doesFileExist(resolvedPath) || - this.alternativeExtensions.some((ext) => this.doesFileExist(`${resolvedPath}${ext}`)) - ) { - return; + // Handle links ending with "/" - these should only work if directory has index file + if (internalLink.endsWith("/")) { + if (fs.existsSync(resolvedPath) && fs.lstatSync(resolvedPath).isDirectory()) { + resolvedPath = path.join(resolvedPath, this.indexFile); + if (this.doesFileExist(resolvedPath)) { + return; + } + } + } else { + // Handle links not ending with "/" - first check for file with extensions + if ( + this.doesFileExist(resolvedPath) || + this.alternativeExtensions.some((ext) => this.doesFileExist(`${resolvedPath}${ext}`)) + ) { + return; + } + + // Do NOT automatically check directories for links not ending with "/" + // This ensures bare directory names like "directory-with-index" are treated as broken } // Report an error with the resolved path