1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use codespan::{FileId, Files};
use linkcheck::Link;
use std::{cell::RefCell, fmt::Debug};
pub fn extract<I>(
target_files: I,
files: &Files<String>,
) -> (Vec<Link>, Vec<IncompleteLink>)
where
I: IntoIterator<Item = FileId>,
{
let mut links = Vec::new();
let broken_links = RefCell::new(Vec::new());
for file_id in target_files {
let cb = on_broken_links(file_id, &broken_links);
let src = files.source(file_id);
log::debug!("Scanning {}", files.name(file_id).to_string_lossy());
links.extend(
linkcheck::scanners::markdown_with_broken_link_callback(src, &cb)
.map(|(link, span)| Link::new(link, span, file_id)),
);
}
(links, broken_links.into_inner())
}
fn on_broken_links<'a>(
file: FileId,
dest: &'a RefCell<Vec<IncompleteLink>>,
) -> impl Fn(&str, &str) -> Option<(String, String)> + 'a {
move |raw, _| {
log::debug!("Found a (possibly) broken link to [{}]", raw);
dest.borrow_mut().push(IncompleteLink {
text: raw.to_string(),
file,
});
None
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct IncompleteLink {
pub text: String,
pub file: FileId,
}