lychee_lib/checker/wikilink/
mod.rs1pub(crate) mod index;
10pub(crate) mod resolver;
11
12use crate::ErrorKind;
13use pulldown_cmark::CowStr;
14
15const MARKDOWN_FRAGMENT_MARKER: char = '#';
19const MARKDOWN_POTHOLE_MARKER: char = '|';
20
21pub(crate) fn wikilink(input: &str, has_pothole: bool) -> Result<CowStr<'_>, ErrorKind> {
23 let mut stripped_input = if has_pothole {
25 pulldown_cmark::CowStr::Borrowed(
26 &input[0..input.find(MARKDOWN_POTHOLE_MARKER).unwrap_or(input.len())],
27 )
28 } else {
29 CowStr::Borrowed(input)
30 };
31
32 if stripped_input.contains(MARKDOWN_FRAGMENT_MARKER) {
36 stripped_input = pulldown_cmark::CowStr::Borrowed(
37 &input[0..input.find(MARKDOWN_FRAGMENT_MARKER).unwrap_or(input.len())],
40 );
41 }
42 if stripped_input.is_empty() {
43 return Err(ErrorKind::EmptyUrl);
44 }
45 Ok(stripped_input)
46}
47
48#[cfg(test)]
49mod tests {
50 use pulldown_cmark::CowStr;
51 use rstest::rstest;
52
53 use crate::checker::wikilink::wikilink;
54
55 #[rstest]
58 #[case("|foo", true)]
59 #[case("|foo#bar", true)]
60 #[case("|foo#bar|foo#bar", true)]
61 #[case("#baz", false)]
62 #[case("#baz#baz|foo", false)]
63 fn test_empty_wikilinks_are_detected(#[case] input: &str, #[case] has_pothole: bool) {
64 let result = wikilink(input, has_pothole);
65 assert!(result.is_err());
66 }
67
68 #[rstest]
69 #[case("link with spaces", true, "link with spaces")]
70 #[case("foo.fileextension", true, "foo.fileextension")]
71 #[case("specialcharacters !_@$&(){}", true, "specialcharacters !_@$&(){}")]
72 fn test_valid_wikilinks(#[case] input: &str, #[case] has_pothole: bool, #[case] actual: &str) {
73 let result = wikilink(input, has_pothole).unwrap();
74 let actual = CowStr::Borrowed(actual);
75 assert_eq!(result, actual);
76 }
77
78 #[rstest]
79 #[case("foo|bar", true, "foo")]
80 #[case("foo#bar", true, "foo")]
81 #[case("foo#bar|baz", false, "foo")]
82 #[case("foo#bar|baz#hashtag_in_pothole", false, "foo")]
83 #[case("foo with spaces#bar|baz#hashtag_in_pothole", false, "foo with spaces")]
84 #[case(
85 "specialcharacters !_@$&(){}#bar|baz#hashtag_in_pothole",
86 true,
87 "specialcharacters !_@$&(){}"
88 )]
89 fn test_fragment_and_pothole_removal(
90 #[case] input: &str,
91 #[case] has_pothole: bool,
92 #[case] actual: &str,
93 ) {
94 let result = wikilink(input, has_pothole).unwrap();
95 let actual = CowStr::Borrowed(actual);
96 assert_eq!(result, actual);
97 }
98}