From 81f260511846fc6f7e8580c98a088162baa2af8b Mon Sep 17 00:00:00 2001 From: ocavue Date: Fri, 4 Jul 2025 18:25:57 +1000 Subject: [PATCH] fix: treat a fragment in an empty directory as an error (#1756) * fix: treat a fragment in an empty directory as an error * test: add more fragment tests --- fixtures/fragments/file1.md | 23 ++++++++++++++++++++++- fixtures/fragments/sub_dir/index.html | 10 ++++++++++ lychee-bin/tests/cli.rs | 13 ++++++++++--- lychee-lib/src/checker/file.rs | 7 ------- 4 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 fixtures/fragments/sub_dir/index.html diff --git a/fixtures/fragments/file1.md b/fixtures/fragments/file1.md index 18d11a1..4d99aa0 100644 --- a/fixtures/fragments/file1.md +++ b/fixtures/fragments/file1.md @@ -17,6 +17,7 @@ This is a test file for the fragment loader. [Link to missing fragment in file2](file2.md#missing-fragment) ### `Code` ``Heading + [Link to code heading](#code-heading) ## HTML Fragments @@ -66,7 +67,27 @@ without related HTML element. Browser will scroll to the top of the page. A link to the non-existing fragment: [try](https://github.com/lycheeverse/lychee#non-existent-anchor). -Skip the fragment check for directories like: [empty](empty_dir/). + +# Sub directory + +- Link to a sub directory + - Good: [With trailing slash](sub_dir/) + - Good: [Without trailing slash](sub_dir) +- Link to a fragment to index.html in sub directory + - Good: [With trailing slash](sub_dir/#a-link-inside-index-html-inside-sub-dir) + - Good: [Without trailing slash](sub_dir#a-link-inside-index-html-inside-sub-dir) +- Link to a non-existing fragment in a sub directory + - Bad: [With trailing slash](sub_dir/#non-existing-fragment-1) + - Bad: [Without trailing slash](sub_dir#non-existing-fragment-2) +- Link to a non-existing sub directory + - Bad: [With trailing slash](sub_dir_non_existing_1/) + - Bad: [Without trailing slash](sub_dir_non_existing_2) +- Link to a empty directory + - Bad: [With trailing slash](empty_dir/) + - Bad: [Without trailing slash](empty_dir) +- Link to a fragment in a non-existing sub directory + - Bad: [With trailing slash](empty_dir/#non-existing-fragment-3) + - Bad: [Without trailing slash](empty_dir#non-existing-fragment-4) # Binary data URLs checks diff --git a/fixtures/fragments/sub_dir/index.html b/fixtures/fragments/sub_dir/index.html new file mode 100644 index 0000000..85c4d43 --- /dev/null +++ b/fixtures/fragments/sub_dir/index.html @@ -0,0 +1,10 @@ + + + + + For Testing Fragments + + + + + diff --git a/lychee-bin/tests/cli.rs b/lychee-bin/tests/cli.rs index 91aedfc..076ef2b 100644 --- a/lychee-bin/tests/cli.rs +++ b/lychee-bin/tests/cli.rs @@ -1895,6 +1895,13 @@ mod cli { .stderr(contains( "https://github.com/lycheeverse/lychee#non-existent-anchor", )) + .stderr(contains("fixtures/fragments/sub_dir#non-existing-fragment-1")) + .stderr(contains("fixtures/fragments/sub_dir#non-existing-fragment-2")) + .stderr(contains("fixtures/fragments/sub_dir_non_existing_1")) + .stderr(contains("fixtures/fragments/sub_dir_non_existing_2")) + .stderr(contains("fixtures/fragments/empty_dir")) + .stderr(contains("fixtures/fragments/empty_dir#non-existing-fragment-3")) + .stderr(contains("fixtures/fragments/empty_dir#non-existing-fragment-4")) .stderr(contains("fixtures/fragments/zero.bin")) .stderr(contains("fixtures/fragments/zero.bin#")) .stderr(contains( @@ -1907,10 +1914,10 @@ mod cli { .stderr(contains( "https://raw.githubusercontent.com/lycheeverse/lychee/master/fixtures/fragments/zero.bin#fragment", )) - .stdout(contains("34 Total")) - .stdout(contains("28 OK")) + .stdout(contains("42 Total")) + .stdout(contains("29 OK")) // Failures because of missing fragments or failed binary body scan - .stdout(contains("6 Errors")); + .stdout(contains("13 Errors")); } #[test] diff --git a/lychee-lib/src/checker/file.rs b/lychee-lib/src/checker/file.rs index 026a644..b7dec27 100644 --- a/lychee-lib/src/checker/file.rs +++ b/lychee-lib/src/checker/file.rs @@ -106,18 +106,11 @@ impl FileChecker { /// Returns a `Status` indicating the result of the check. async fn check_path(&self, path: &Path, uri: &Uri) -> Status { let file_path = self.resolve_file_path(path); - let has_fragment = uri.url.fragment().is_some_and(|x| !x.is_empty()); // If file_path exists, check this file if file_path.is_some() { return self.check_file(&file_path.unwrap(), uri).await; } - // If path is a directory, and we cannot find an index file inside it, - // and we don't have a fragment, just return success. This is for - // backward compatibility. - else if path.is_dir() && !has_fragment { - return Status::Ok(StatusCode::OK); - } ErrorKind::InvalidFilePath(uri.clone()).into() }