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