use mdbook_markdown::pulldown_cmark::{
BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser,
};
use tap::Pipe;
use mdbookkit::markdown::default_markdown_options;
pub fn markdown(source: &str) -> Parser<'_, KeepBrokenLinks> {
Parser::new_with_broken_link_callback(source, default_markdown_options(), Some(KeepBrokenLinks))
}
pub struct KeepBrokenLinks;
impl KeepBrokenLinks {
const OPTIONS: Options =
default_markdown_options().intersection(Options::ENABLE_SMART_PUNCTUATION.complement());
}
impl<'a> BrokenLinkCallback<'a> for KeepBrokenLinks {
fn handle_broken_link(&mut self, link: BrokenLink<'a>) -> Option<(CowStr<'a>, CowStr<'a>)> {
let dest = if matches!(link.link_type, LinkType::Collapsed | LinkType::Shortcut)
&& let CowStr::Borrowed(dest) = link.reference
{
let elements = Parser::new_ext(dest, Self::OPTIONS)
.filter_map(|event| match event {
Event::Text(inner) => Some(inner),
Event::Code(inner) => Some(inner),
Event::InlineHtml(inner) => Some(inner),
_ => None,
})
.collect::<Vec<_>>();
if elements.len() == 1 {
#[allow(clippy::unwrap_used)]
(elements.into_iter()).next().unwrap()
} else {
(elements.iter())
.fold(String::with_capacity(dest.len()), |mut out, elem| {
out.push_str(elem);
out
})
.into_boxed_str()
.pipe(CowStr::Boxed)
}
} else {
link.reference.clone()
};
if dest.is_empty() {
None
} else {
let title = dest.clone();
Some((dest, title))
}
}
}