rework link parsing loop
This commit is contained in:
parent
fe3eae3f31
commit
b1d232a6da
@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
|
||||
use crate::html::toc::TocBuilder;
|
||||
|
||||
use pulldown_cmark::{
|
||||
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
|
||||
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
|
||||
pub(crate) struct MarkdownLink {
|
||||
pub kind: LinkType,
|
||||
pub link: String,
|
||||
pub display_text: String,
|
||||
pub range: MarkdownLinkRange,
|
||||
}
|
||||
|
||||
@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn markdown_links<R>(
|
||||
md: &str,
|
||||
pub(crate) fn markdown_links<'md, R>(
|
||||
md: &'md str,
|
||||
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
|
||||
) -> Vec<R> {
|
||||
if md.is_empty() {
|
||||
@ -1375,13 +1376,17 @@ pub(crate) fn markdown_links<R>(
|
||||
MarkdownLinkRange::Destination(range.clone())
|
||||
};
|
||||
|
||||
Parser::new_with_broken_link_callback(
|
||||
let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
|
||||
let mut event_iter = Parser::new_with_broken_link_callback(
|
||||
md,
|
||||
main_body_opts(),
|
||||
Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
|
||||
Some(&mut broken_link_callback),
|
||||
)
|
||||
.into_offset_iter()
|
||||
.filter_map(|(event, span)| match event {
|
||||
.into_offset_iter();
|
||||
let mut links = Vec::new();
|
||||
|
||||
while let Some((event, span)) = event_iter.next() {
|
||||
match event {
|
||||
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
|
||||
let range = match link_type {
|
||||
// Link is pulled from the link itself.
|
||||
@ -1396,11 +1401,47 @@ pub(crate) fn markdown_links<R>(
|
||||
}
|
||||
LinkType::Autolink | LinkType::Email => unreachable!(),
|
||||
};
|
||||
preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
|
||||
|
||||
let display_text =
|
||||
collect_link_data(&mut event_iter).map_or(String::new(), CowStr::into_string);
|
||||
|
||||
if let Some(link) = preprocess_link(MarkdownLink {
|
||||
kind: link_type,
|
||||
display_text,
|
||||
link: dest.into_string(),
|
||||
range,
|
||||
}) {
|
||||
links.push(link);
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
links
|
||||
}
|
||||
|
||||
fn collect_link_data<'input, 'callback>(
|
||||
event_iter: &mut OffsetIter<'input, 'callback>,
|
||||
) -> Option<CowStr<'input>> {
|
||||
let mut display_text = None;
|
||||
|
||||
while let Some((event, _span)) = event_iter.next() {
|
||||
match event {
|
||||
Event::Text(code) => {
|
||||
display_text = Some(code);
|
||||
}
|
||||
Event::Code(code) => {
|
||||
display_text = Some(code);
|
||||
}
|
||||
Event::End(_) => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
display_text
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user