lychee_lib/checker/wikilink/
resolver.rs1use crate::{BaseInfo, ErrorKind, Uri, checker::wikilink::index::WikilinkIndex};
2use std::path::{Path, PathBuf};
3
4#[derive(Clone, Debug)]
5pub(crate) struct WikilinkResolver {
6 checker: WikilinkIndex,
7 fallback_extensions: Vec<String>,
8}
9
10impl WikilinkResolver {
13 pub(crate) fn new(
17 base: &BaseInfo,
18 fallback_extensions: Vec<String>,
19 ) -> Result<Self, ErrorKind> {
20 let base = match base {
21 BaseInfo::None => Err(ErrorKind::WikilinkInvalidBase(
22 "Base must be specified for wikilink checking".into(),
23 ))?,
24 base => base,
25 };
26 let base = base.to_file_path().ok_or(ErrorKind::WikilinkInvalidBase(
27 "Base cannot be remote".to_string(),
28 ))?;
29
30 Ok(Self {
31 checker: WikilinkIndex::new(base),
32 fallback_extensions,
33 })
34 }
35 pub(crate) fn resolve(&self, path: &Path, uri: &Uri) -> Result<PathBuf, ErrorKind> {
37 for ext in &self.fallback_extensions {
38 let mut candidate = path.to_path_buf();
39 candidate.set_extension(ext);
40
41 if let Some(resolved) = self.checker.contains_path(&candidate) {
42 return Ok(resolved);
43 }
44 }
45
46 Err(ErrorKind::WikilinkNotFound(uri.clone(), path.to_path_buf()))
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::{BaseInfo, ErrorKind, Uri, checker::wikilink::resolver::WikilinkResolver};
53 use test_utils::{fixture_uri, fixtures_path};
54
55 #[test]
56 fn test_wikilink_resolves_to_filename() {
57 let resolver = WikilinkResolver::new(
58 &BaseInfo::from_path(&fixtures_path!().join("wiki")).unwrap(),
59 vec!["md".to_string()],
60 )
61 .unwrap();
62 let uri = Uri {
63 url: fixture_uri!("wiki/Usage"),
64 };
65 let path = fixtures_path!().join("Usage");
66 let expected_result = fixtures_path!().join("wiki/Usage.md");
67 assert_eq!(resolver.resolve(&path, &uri), Ok(expected_result));
68 }
69
70 #[test]
71 fn test_wikilink_not_found() {
72 let resolver = WikilinkResolver::new(
73 &BaseInfo::from_path(&fixtures_path!().join("wiki")).unwrap(),
74 vec!["md".to_string()],
75 )
76 .unwrap();
77 let uri = Uri {
78 url: fixture_uri!("wiki/404"),
79 };
80 let path = fixtures_path!().join("404");
81 assert!(matches!(
82 resolver.resolve(&path, &uri),
83 Err(ErrorKind::WikilinkNotFound(..))
84 ));
85 }
86}