Skip to content

Commit 76c771f

Browse files
committed
fix: do not fail on empty # and #top fragments
The empty "#" and "#top" fragments are always valid without related HTML element. Browser will scroll to the top of the page. Hence lychee must not fail on those. Credits go to @thiru-appitap for initial attempt and helping to find missing parts of the implementation. Solves: lycheeverse#1599 Signed-off-by: MichaIng <[email protected]>
1 parent a11d515 commit 76c771f

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

fixtures/fragments/file.html

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<a href="#Upper-ÄÖö">back to Upper-ÄÖö</a><br>
2323
<a href="#Upper-%C3%84%C3%96%C3%B6">back to öüä encoded</a><br>
2424
<a href="#in-the-end">doesn't exist</a><br>
25+
<a href="#">To the top</a><br>
26+
<a href="#top">To the top alt</a><br>
2527
</section>
2628
</body>
2729
</html>

fixtures/fragments/file1.md

+8
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,12 @@ Therefore we put the test into a code block for now to prevent false positives.
5454
[Link to umlauts wrong case](#fünf-sÜße-Äpfel)
5555
[Link to umlauts with percent encoding](#f%C3%BCnf-s%C3%BC%C3%9Fe-%C3%A4pfel)
5656

57+
# To top fragments
58+
59+
The empty "#" and "#top" fragments are always valid
60+
without related HTML element. Browser will scroll to the top of the page.
61+
62+
[Link to top of file2](file2.md#)
63+
[Alternative link to top of file2](file2.md#top)
64+
5765
##### Lets wear a hat: être

lychee-bin/tests/cli.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1834,8 +1834,10 @@ mod cli {
18341834
.stderr(contains(
18351835
"fixtures/fragments/file1.md#kebab-case-fragment-1",
18361836
))
1837-
.stdout(contains("21 Total"))
1838-
.stdout(contains("17 OK"))
1837+
.stderr(contains("fixtures/fragments/file.html#top"))
1838+
.stderr(contains("fixtures/fragments/file2.md#top"))
1839+
.stdout(contains("25 Total"))
1840+
.stdout(contains("21 OK"))
18391841
// 4 failures because of missing fragments
18401842
.stdout(contains("4 Errors"));
18411843
}

lychee-lib/src/utils/fragment_checker.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,20 @@ impl FragmentChecker {
5959
if file_type == FileType::Markdown {
6060
fragment_decoded = fragment_decoded.to_lowercase().into();
6161
}
62+
// Empty # and #top fragments are always valid, triggering the browser to scroll to top.
63+
let is_emtpty_or_top_fragment = fragment.is_empty() || fragment.eq_ignore_ascii_case("top");
6264
match self.cache.lock().await.entry(url_without_frag) {
6365
Entry::Vacant(entry) => {
6466
let content = fs::read_to_string(path).await?;
6567
let file_frags = extractor(&content);
6668
let contains_fragment =
6769
file_frags.contains(fragment) || file_frags.contains(&fragment_decoded as &str);
6870
entry.insert(file_frags);
69-
Ok(contains_fragment)
70-
}
71-
Entry::Occupied(entry) => {
72-
Ok(entry.get().contains(fragment)
73-
|| entry.get().contains(&fragment_decoded as &str))
71+
Ok(is_emtpty_or_top_fragment || contains_fragment)
7472
}
73+
Entry::Occupied(entry) => Ok(is_emtpty_or_top_fragment
74+
|| entry.get().contains(fragment)
75+
|| entry.get().contains(&fragment_decoded as &str)),
7576
}
7677
}
7778

0 commit comments

Comments
 (0)