about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlona Enraght-Moony <code@alona.page>2024-10-19 14:37:11 +0000
committerAlona Enraght-Moony <code@alona.page>2024-10-19 14:37:11 +0000
commitebb842328af5ef19c98cc361e1a27dc8f87ff8cd (patch)
treed9171e1b78c305508cac0c2b5b4f40a974ed9b4a
parentb27f33a4d9c42ee6b5347a75a8a990a883437da9 (diff)
downloadrust-ebb842328af5ef19c98cc361e1a27dc8f87ff8cd.tar.gz
rust-ebb842328af5ef19c98cc361e1a27dc8f87ff8cd.zip
rustdoc: Extract footnote logic into it's own module.
-rw-r--r--src/librustdoc/html/markdown.rs84
-rw-r--r--src/librustdoc/html/markdown/footnotes.rs82
2 files changed, 87 insertions, 79 deletions
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 315b7742a4c..7826a5d8394 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -37,7 +37,7 @@ use std::sync::OnceLock;
 use pulldown_cmark::{
     BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
 };
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagMessage};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
@@ -57,6 +57,7 @@ use crate::html::length_limit::HtmlWithLimit;
 use crate::html::render::small_url_encode;
 use crate::html::toc::{Toc, TocBuilder};
 
+mod footnotes;
 #[cfg(test)]
 mod tests;
 
@@ -646,81 +647,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
     }
 }
 
-/// Moves all footnote definitions to the end and add back links to the
-/// references.
-struct Footnotes<'a, I> {
-    inner: I,
-    footnotes: FxIndexMap<String, (Vec<Event<'a>>, u16)>,
-}
-
-impl<'a, I> Footnotes<'a, I> {
-    fn new(iter: I) -> Self {
-        Footnotes { inner: iter, footnotes: FxIndexMap::default() }
-    }
-
-    fn get_entry(&mut self, key: &str) -> &mut (Vec<Event<'a>>, u16) {
-        let new_id = self.footnotes.len() + 1;
-        let key = key.to_owned();
-        self.footnotes.entry(key).or_insert((Vec::new(), new_id as u16))
-    }
-}
-
-impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
-    type Item = SpannedEvent<'a>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        loop {
-            match self.inner.next() {
-                Some((Event::FootnoteReference(ref reference), range)) => {
-                    let entry = self.get_entry(reference);
-                    let reference = format!(
-                        "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>",
-                        (*entry).1
-                    );
-                    return Some((Event::Html(reference.into()), range));
-                }
-                Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
-                    let mut content = Vec::new();
-                    for (event, _) in &mut self.inner {
-                        if let Event::End(TagEnd::FootnoteDefinition) = event {
-                            break;
-                        }
-                        content.push(event);
-                    }
-                    let entry = self.get_entry(&def);
-                    (*entry).0 = content;
-                }
-                Some(e) => return Some(e),
-                None => {
-                    if !self.footnotes.is_empty() {
-                        let mut v: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
-                        v.sort_by(|a, b| a.1.cmp(&b.1));
-                        let mut ret = String::from("<div class=\"footnotes\"><hr><ol>");
-                        for (mut content, id) in v {
-                            write!(ret, "<li id=\"fn{id}\">").unwrap();
-                            let mut is_paragraph = false;
-                            if let Some(&Event::End(TagEnd::Paragraph)) = content.last() {
-                                content.pop();
-                                is_paragraph = true;
-                            }
-                            html::push_html(&mut ret, content.into_iter());
-                            write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩</a>").unwrap();
-                            if is_paragraph {
-                                ret.push_str("</p>");
-                            }
-                            ret.push_str("</li>");
-                        }
-                        ret.push_str("</ol></div>");
-                        return Some((Event::Html(ret.into()), 0..0));
-                    } else {
-                        return None;
-                    }
-                }
-            }
-        }
-    }
-}
-
 /// A newtype that represents a relative line number in Markdown.
 ///
 /// In other words, this represents an offset from the first line of Markdown
@@ -1408,7 +1334,7 @@ impl Markdown<'_> {
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, ids, heading_offset);
-        let p = Footnotes::new(p);
+        let p = footnotes::Footnotes::new(p);
         let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
         let p = TableWrapper::new(p);
         let p = CodeBlocks::new(p, codes, edition, playground);
@@ -1443,7 +1369,7 @@ impl MarkdownWithToc<'_> {
 
         {
             let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
-            let p = Footnotes::new(p);
+            let p = footnotes::Footnotes::new(p);
             let p = TableWrapper::new(p.map(|(ev, _)| ev));
             let p = CodeBlocks::new(p, codes, edition, playground);
             html::push_html(&mut s, p);
@@ -1476,7 +1402,7 @@ impl MarkdownItemInfo<'_> {
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
-        let p = Footnotes::new(p);
+        let p = footnotes::Footnotes::new(p);
         let p = TableWrapper::new(p.map(|(ev, _)| ev));
         let p = p.filter(|event| {
             !matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph))
diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs
new file mode 100644
index 00000000000..47e248b891c
--- /dev/null
+++ b/src/librustdoc/html/markdown/footnotes.rs
@@ -0,0 +1,82 @@
+//! Markdown footnote handling.
+use std::fmt::Write as _;
+
+use pulldown_cmark::{Event, Tag, TagEnd, html};
+use rustc_data_structures::fx::FxIndexMap;
+
+use super::SpannedEvent;
+
+/// Moves all footnote definitions to the end and add back links to the
+/// references.
+pub(super) struct Footnotes<'a, I> {
+    inner: I,
+    footnotes: FxIndexMap<String, (Vec<Event<'a>>, u16)>,
+}
+
+impl<'a, I> Footnotes<'a, I> {
+    pub(super) fn new(iter: I) -> Self {
+        Footnotes { inner: iter, footnotes: FxIndexMap::default() }
+    }
+
+    fn get_entry(&mut self, key: &str) -> &mut (Vec<Event<'a>>, u16) {
+        let new_id = self.footnotes.len() + 1;
+        let key = key.to_owned();
+        self.footnotes.entry(key).or_insert((Vec::new(), new_id as u16))
+    }
+}
+
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
+    type Item = SpannedEvent<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        loop {
+            match self.inner.next() {
+                Some((Event::FootnoteReference(ref reference), range)) => {
+                    let entry = self.get_entry(reference);
+                    let reference = format!(
+                        "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>",
+                        (*entry).1
+                    );
+                    return Some((Event::Html(reference.into()), range));
+                }
+                Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
+                    let mut content = Vec::new();
+                    for (event, _) in &mut self.inner {
+                        if let Event::End(TagEnd::FootnoteDefinition) = event {
+                            break;
+                        }
+                        content.push(event);
+                    }
+                    let entry = self.get_entry(&def);
+                    (*entry).0 = content;
+                }
+                Some(e) => return Some(e),
+                None => {
+                    if !self.footnotes.is_empty() {
+                        let mut v: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
+                        v.sort_by(|a, b| a.1.cmp(&b.1));
+                        let mut ret = String::from("<div class=\"footnotes\"><hr><ol>");
+                        for (mut content, id) in v {
+                            write!(ret, "<li id=\"fn{id}\">").unwrap();
+                            let mut is_paragraph = false;
+                            if let Some(&Event::End(TagEnd::Paragraph)) = content.last() {
+                                content.pop();
+                                is_paragraph = true;
+                            }
+                            html::push_html(&mut ret, content.into_iter());
+                            write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩</a>").unwrap();
+                            if is_paragraph {
+                                ret.push_str("</p>");
+                            }
+                            ret.push_str("</li>");
+                        }
+                        ret.push_str("</ol></div>");
+                        return Some((Event::Html(ret.into()), 0..0));
+                    } else {
+                        return None;
+                    }
+                }
+            }
+        }
+    }
+}