11//! Markdown footnote handling.
22use std:: fmt:: Write as _;
33
4- use pulldown_cmark:: { Event , Tag , TagEnd , html} ;
4+ use pulldown_cmark:: { CowStr , Event , Tag , TagEnd , html} ;
55use rustc_data_structures:: fx:: FxIndexMap ;
66
77use super :: SpannedEvent ;
@@ -21,7 +21,7 @@ struct FootnoteDef<'a> {
2121 id : usize ,
2222}
2323
24- impl < ' a , ' b , I > Footnotes < ' a , ' b , I > {
24+ impl < ' a , ' b , I : Iterator < Item = SpannedEvent < ' a > > > Footnotes < ' a , ' b , I > {
2525 pub ( super ) fn new ( iter : I , existing_footnotes : & ' b mut usize ) -> Self {
2626 Footnotes { inner : iter, footnotes : FxIndexMap :: default ( ) , existing_footnotes }
2727 }
@@ -34,31 +34,50 @@ impl<'a, 'b, I> Footnotes<'a, 'b, I> {
3434 // Don't allow changing the ID of existing entrys, but allow changing the contents.
3535 ( content, * id)
3636 }
37+
38+ fn handle_footnote_reference ( & mut self , reference : & CowStr < ' a > ) -> Event < ' a > {
39+ // When we see a reference (to a footnote we may not know) the definition of,
40+ // reserve a number for it, and emit a link to that number.
41+ let ( _, id) = self . get_entry ( reference) ;
42+ let reference = format ! (
43+ "<sup id=\" fnref{0}\" ><a href=\" #fn{0}\" >{1}</a></sup>" ,
44+ id,
45+ // Although the ID count is for the whole page, the footnote reference
46+ // are local to the item so we make this ID "local" when displayed.
47+ id - * self . existing_footnotes
48+ ) ;
49+ Event :: Html ( reference. into ( ) )
50+ }
51+
52+ fn collect_footnote_def ( & mut self ) -> Vec < Event < ' a > > {
53+ let mut content = Vec :: new ( ) ;
54+ while let Some ( ( event, _) ) = self . inner . next ( ) {
55+ match event {
56+ Event :: End ( TagEnd :: FootnoteDefinition ) => break ,
57+ Event :: FootnoteReference ( ref reference) => {
58+ content. push ( self . handle_footnote_reference ( reference) ) ;
59+ }
60+ event => content. push ( event) ,
61+ }
62+ }
63+ content
64+ }
3765}
3866
3967impl < ' a , ' b , I : Iterator < Item = SpannedEvent < ' a > > > Iterator for Footnotes < ' a , ' b , I > {
4068 type Item = SpannedEvent < ' a > ;
4169
4270 fn next ( & mut self ) -> Option < Self :: Item > {
4371 loop {
44- match self . inner . next ( ) {
72+ let next = self . inner . next ( ) ;
73+ match next {
4574 Some ( ( Event :: FootnoteReference ( ref reference) , range) ) => {
46- // When we see a reference (to a footnote we may not know) the definition of,
47- // reserve a number for it, and emit a link to that number.
48- let ( _, id) = self . get_entry ( reference) ;
49- let reference = format ! (
50- "<sup id=\" fnref{0}\" ><a href=\" #fn{0}\" >{1}</a></sup>" ,
51- id,
52- // Although the ID count is for the whole page, the footnote reference
53- // are local to the item so we make this ID "local" when displayed.
54- id - * self . existing_footnotes
55- ) ;
56- return Some ( ( Event :: Html ( reference. into ( ) ) , range) ) ;
75+ return Some ( ( self . handle_footnote_reference ( reference) , range) ) ;
5776 }
5877 Some ( ( Event :: Start ( Tag :: FootnoteDefinition ( def) ) , _) ) => {
5978 // When we see a footnote definition, collect the assocated content, and store
6079 // that for rendering later.
61- let content = collect_footnote_def ( & mut self . inner ) ;
80+ let content = self . collect_footnote_def ( ) ;
6281 let ( entry_content, _) = self . get_entry ( & def) ;
6382 * entry_content = content;
6483 }
@@ -80,17 +99,6 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b
8099 }
81100}
82101
83- fn collect_footnote_def < ' a > ( events : impl Iterator < Item = SpannedEvent < ' a > > ) -> Vec < Event < ' a > > {
84- let mut content = Vec :: new ( ) ;
85- for ( event, _) in events {
86- if let Event :: End ( TagEnd :: FootnoteDefinition ) = event {
87- break ;
88- }
89- content. push ( event) ;
90- }
91- content
92- }
93-
94102fn render_footnotes_defs ( mut footnotes : Vec < FootnoteDef < ' _ > > ) -> String {
95103 let mut ret = String :: from ( "<div class=\" footnotes\" ><hr><ol>" ) ;
96104
0 commit comments