Skip to content

Commit b1d232a

Browse files
committed
rework link parsing loop
1 parent fe3eae3 commit b1d232a

File tree

1 file changed

+65
-24
lines changed

1 file changed

+65
-24
lines changed

src/librustdoc/html/markdown.rs

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
5050
use crate::html::toc::TocBuilder;
5151

5252
use pulldown_cmark::{
53-
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
53+
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
5454
};
5555

5656
#[cfg(test)]
@@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
12401240
pub(crate) struct MarkdownLink {
12411241
pub kind: LinkType,
12421242
pub link: String,
1243+
pub display_text: String,
12431244
pub range: MarkdownLinkRange,
12441245
}
12451246

@@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
12631264
}
12641265
}
12651266

1266-
pub(crate) fn markdown_links<R>(
1267-
md: &str,
1267+
pub(crate) fn markdown_links<'md, R>(
1268+
md: &'md str,
12681269
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
12691270
) -> Vec<R> {
12701271
if md.is_empty() {
@@ -1375,32 +1376,72 @@ pub(crate) fn markdown_links<R>(
13751376
MarkdownLinkRange::Destination(range.clone())
13761377
};
13771378

1378-
Parser::new_with_broken_link_callback(
1379+
let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
1380+
let mut event_iter = Parser::new_with_broken_link_callback(
13791381
md,
13801382
main_body_opts(),
1381-
Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
1383+
Some(&mut broken_link_callback),
13821384
)
1383-
.into_offset_iter()
1384-
.filter_map(|(event, span)| match event {
1385-
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
1386-
let range = match link_type {
1387-
// Link is pulled from the link itself.
1388-
LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
1389-
span_for_offset_backward(span, b'[', b']')
1390-
}
1391-
LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
1392-
LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
1393-
// Link is pulled from elsewhere in the document.
1394-
LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
1395-
span_for_link(&dest, span)
1385+
.into_offset_iter();
1386+
let mut links = Vec::new();
1387+
1388+
while let Some((event, span)) = event_iter.next() {
1389+
match event {
1390+
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
1391+
let range = match link_type {
1392+
// Link is pulled from the link itself.
1393+
LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
1394+
span_for_offset_backward(span, b'[', b']')
1395+
}
1396+
LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
1397+
LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
1398+
// Link is pulled from elsewhere in the document.
1399+
LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
1400+
span_for_link(&dest, span)
1401+
}
1402+
LinkType::Autolink | LinkType::Email => unreachable!(),
1403+
};
1404+
1405+
let display_text =
1406+
collect_link_data(&mut event_iter).map_or(String::new(), CowStr::into_string);
1407+
1408+
if let Some(link) = preprocess_link(MarkdownLink {
1409+
kind: link_type,
1410+
display_text,
1411+
link: dest.into_string(),
1412+
range,
1413+
}) {
1414+
links.push(link);
13961415
}
1397-
LinkType::Autolink | LinkType::Email => unreachable!(),
1398-
};
1399-
preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
1416+
}
1417+
_ => {}
14001418
}
1401-
_ => None,
1402-
})
1403-
.collect()
1419+
}
1420+
1421+
links
1422+
}
1423+
1424+
fn collect_link_data<'input, 'callback>(
1425+
event_iter: &mut OffsetIter<'input, 'callback>,
1426+
) -> Option<CowStr<'input>> {
1427+
let mut display_text = None;
1428+
1429+
while let Some((event, _span)) = event_iter.next() {
1430+
match event {
1431+
Event::Text(code) => {
1432+
display_text = Some(code);
1433+
}
1434+
Event::Code(code) => {
1435+
display_text = Some(code);
1436+
}
1437+
Event::End(_) => {
1438+
break;
1439+
}
1440+
_ => {}
1441+
}
1442+
}
1443+
1444+
display_text
14041445
}
14051446

14061447
#[derive(Debug)]

0 commit comments

Comments
 (0)