about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2017-12-28 16:29:20 +0530
committerManish Goregaokar <manishsmail@gmail.com>2018-01-22 15:24:27 +0530
commite8dd5df69b67b30ec92e0198f1ade6476916d463 (patch)
tree7030870d43eaea9792ec5ace426254a471064b71
parentdae2e22e814931ea26e571c7d6e72aa1b05a871d (diff)
downloadrust-e8dd5df69b67b30ec92e0198f1ade6476916d463.tar.gz
rust-e8dd5df69b67b30ec92e0198f1ade6476916d463.zip
Add LinkReplacer pass for pulldown
-rw-r--r--src/librustdoc/clean/mod.rs19
-rw-r--r--src/librustdoc/externalfiles.rs4
-rw-r--r--src/librustdoc/html/markdown.rs47
-rw-r--r--src/librustdoc/html/render.rs13
-rw-r--r--src/librustdoc/markdown.rs2
5 files changed, 69 insertions, 16 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b890a980d43..c91be9ad7b8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -308,6 +308,11 @@ impl Item {
     pub fn collapsed_doc_value(&self) -> Option<String> {
         self.attrs.collapsed_doc_value()
     }
+
+    pub fn links(&self) -> Vec<(String, String)> {
+        self.attrs.links()
+    }
+
     pub fn is_crate(&self) -> bool {
         match self.inner {
             StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
@@ -791,6 +796,20 @@ impl Attributes {
             None
         }
     }
+
+    /// Get links as a vector
+    ///
+    /// Cache must be populated before call
+    pub fn links(&self) -> Vec<(String, String)> {
+        use html::format::href;
+        self.links.iter().filter_map(|&(ref s, did)| {
+            if let Some((href, ..)) = href(did) {
+                Some((s.clone(), href))
+            } else {
+                None
+            }
+        }).collect()
+    }
 }
 
 impl AttributesExt for Attributes {
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index f8320330ad2..f7d07af04ea 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -37,7 +37,7 @@ impl ExternalHtml {
             )
             .and_then(|(ih, bc)|
                 load_external_files(md_before_content)
-                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
+                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[], render))))
             )
             .and_then(|(ih, bc)|
                 load_external_files(after_content)
@@ -45,7 +45,7 @@ impl ExternalHtml {
             )
             .and_then(|(ih, bc, ac)|
                 load_external_files(md_after_content)
-                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
+                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[], render))))
             )
             .map(|(ih, bc, ac)|
                 ExternalHtml {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 9bb35da246c..9e875a7c280 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -56,15 +56,16 @@ pub enum RenderType {
 /// A unit struct which has the `fmt::Display` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
-// The second parameter is whether we need a shorter version or not.
-pub struct Markdown<'a>(pub &'a str, pub RenderType);
+/// The second parameter is a list of link replacements
+// The third parameter is whether we need a shorter version or not.
+pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)], pub RenderType);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
 pub struct MarkdownWithToc<'a>(pub &'a str, pub RenderType);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
 pub struct MarkdownHtml<'a>(pub &'a str, pub RenderType);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
-pub struct MarkdownSummaryLine<'a>(pub &'a str);
+pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
 /// Controls whether a line will be hidden or shown in HTML output.
 ///
@@ -248,6 +249,38 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
 }
 
 /// Make headings links with anchor ids and build up TOC.
+struct LinkReplacer<'a, 'b, I: Iterator<Item = Event<'a>>> {
+    inner: I,
+    links: &'b [(String, String)]
+}
+
+impl<'a, 'b, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, 'b, I> {
+    fn new(iter: I, links: &'b [(String, String)]) -> Self {
+        LinkReplacer {
+            inner: iter,
+            links
+        }
+    }
+}
+
+impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, 'b, I> {
+    type Item = Event<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let event = self.inner.next();
+        if let Some(Event::Start(Tag::Link(dest, text))) = event {
+            if let Some(&(_, ref replace)) = self.links.into_iter().find(|link| &*link.0 == &*dest) {
+                Some(Event::Start(Tag::Link(replace.to_owned().into(), text)))
+            } else {
+                Some(Event::Start(Tag::Link(dest, text)))
+            }
+        } else {
+            event
+        }
+    }
+}
+
+/// Make headings links with anchor ids and build up TOC.
 struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
@@ -996,7 +1029,7 @@ impl LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md, render_type) = *self;
+        let Markdown(md, links, render_type) = *self;
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -1012,7 +1045,7 @@ impl<'a> fmt::Display for Markdown<'a> {
             let mut s = String::with_capacity(md.len() * 3 / 2);
 
             html::push_html(&mut s,
-                            Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
+                            Footnotes::new(CodeBlocks::new(LinkReplacer::new(HeadingLinks::new(p, None), links))));
 
             fmt.write_str(&s)
         }
@@ -1079,7 +1112,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
 
 impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownSummaryLine(md) = *self;
+        let MarkdownSummaryLine(md, links) = *self;
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
 
@@ -1087,7 +1120,7 @@ impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
 
         let mut s = String::new();
 
-        html::push_html(&mut s, SummaryLine::new(p));
+        html::push_html(&mut s, LinkReplacer::new(SummaryLine::new(p), links));
 
         fmt.write_str(&s)
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f335e073d56..52200f5afd7 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1861,12 +1861,13 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
 /// rendering between Pulldown and Hoedown.
 fn render_markdown(w: &mut fmt::Formatter,
                    md_text: &str,
+                   links: Vec<(String, String)>,
                    span: Span,
                    render_type: RenderType,
                    prefix: &str,
                    scx: &SharedContext)
                    -> fmt::Result {
-    let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, ty)));
+    let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, &links, ty)));
     let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
     differences.retain(|s| {
         match *s {
@@ -1898,7 +1899,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
         } else {
             format!("{}", &plain_summary_line(Some(s)))
         };
-        render_markdown(w, &markdown, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
+        render_markdown(w, &markdown, item.links(), item.source.clone(), cx.render_type, prefix, &cx.shared)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -1924,7 +1925,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
                  cx: &Context, prefix: &str) -> fmt::Result {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, &*s, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
+        render_markdown(w, &*s, item.links(), item.source.clone(), cx.render_type, prefix, &cx.shared)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -2146,10 +2147,10 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
                        stab_docs = stab_docs,
                        docs = if cx.render_type == RenderType::Hoedown {
                            format!("{}",
-                                   shorter(Some(&Markdown(doc_value,
+                                   shorter(Some(&Markdown(doc_value, &item.links(),
                                                           RenderType::Hoedown).to_string())))
                        } else {
-                           format!("{}", MarkdownSummaryLine(doc_value))
+                           format!("{}", MarkdownSummaryLine(doc_value, &item.links()))
                        },
                        class = myitem.type_(),
                        stab = myitem.stability_class().unwrap_or("".to_string()),
@@ -3338,7 +3339,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
         write!(w, "</span>")?;
         write!(w, "</h3>\n")?;
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
-            write!(w, "<div class='docblock'>{}</div>", Markdown(&*dox, cx.render_type))?;
+            write!(w, "<div class='docblock'>{}</div>", Markdown(&*dox, &i.impl_item.links(), cx.render_type))?;
         }
     }
 
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index af93505293c..9af2ebf0661 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -104,7 +104,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
     } else {
         // Save the state of USED_ID_MAP so it only gets updated once even
         // though we're rendering twice.
-        render_text(|ty| format!("{}", Markdown(text, ty)))
+        render_text(|ty| format!("{}", Markdown(text, &[], ty)))
     };
 
     let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);