use mdbook_markdown::pulldown_cmark::{
BrokenLink, BrokenLinkCallback, CowStr, Event, Options, Parser,
};
use tap::Pipe;
use mdbookkit::markdown::default_markdown_options;
pub fn stream(text: &str, options: Options) -> MarkdownStream<'_> {
Parser::new_with_broken_link_callback(text, options, Some(ItemLinks))
}
pub type MarkdownStream<'a> = Parser<'a, ItemLinks>;
pub struct ItemLinks;
impl ItemLinks {
const OPTIONS: Options =
default_markdown_options().intersection(Options::ENABLE_SMART_PUNCTUATION.complement());
}
impl<'input> BrokenLinkCallback<'input> for ItemLinks {
fn handle_broken_link(
&mut self,
link: BrokenLink<'input>,
) -> Option<(CowStr<'input>, CowStr<'input>)> {
let inner = if let CowStr::Borrowed(inner) = link.reference {
let parse = stream(inner, Self::OPTIONS);
let inner = parse
.filter_map(|event| match event {
Event::Text(inner) => Some(inner),
Event::Code(inner) => Some(inner),
_ => None,
})
.collect::<Vec<_>>();
if inner.len() == 1 {
inner.into_iter().next().expect("has 1 item")
} else {
inner
.iter()
.map(ToString::to_string)
.collect::<Box<str>>()
.pipe(CowStr::Boxed)
}
} else {
link.reference.clone()
};
if inner.is_empty() {
None
} else {
let title = inner.clone();
Some((inner, title))
}
}
}