about summary refs log tree commit diff
path: root/src/librustdoc/html
diff options
context:
space:
mode:
authorKyle Lin <minecraft.kyle.train@gmail.com>2023-06-29 12:07:24 +0800
committerKyle Lin <minecraft.kyle.train@gmail.com>2023-08-18 15:19:07 +0800
commitb1d232a6da800b26f18d79a0340436fa4aec7327 (patch)
tree1075797a4ad4e927251dea705b677fbb7fce94c0 /src/librustdoc/html
parentfe3eae3f310b2f709aa5b39d76a94fc1ea843854 (diff)
downloadrust-b1d232a6da800b26f18d79a0340436fa4aec7327.tar.gz
rust-b1d232a6da800b26f18d79a0340436fa4aec7327.zip
rework link parsing loop
Diffstat (limited to 'src/librustdoc/html')
-rw-r--r--src/librustdoc/html/markdown.rs89
1 files changed, 65 insertions, 24 deletions
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 0ba2d992392..b5ab8a7b12a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -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,32 +1376,72 @@ 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 {
-        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.
-                LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
-                    span_for_offset_backward(span, b'[', b']')
-                }
-                LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
-                LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
-                // Link is pulled from elsewhere in the document.
-                LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
-                    span_for_link(&dest, span)
+    .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.
+                    LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+                        span_for_offset_backward(span, b'[', b']')
+                    }
+                    LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+                    LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+                    // Link is pulled from elsewhere in the document.
+                    LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+                        span_for_link(&dest, span)
+                    }
+                    LinkType::Autolink | LinkType::Email => unreachable!(),
+                };
+
+                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);
                 }
-                LinkType::Autolink | LinkType::Email => unreachable!(),
-            };
-            preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
+            }
+            _ => {}
         }
-        _ => 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)]