From d9aac8cfcefcd4063fc39ff19e9ace373471bbbc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Nov 2024 16:56:18 +0100 Subject: Fix duplicated footnote IDs --- src/librustdoc/html/markdown/footnotes.rs | 33 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'src/librustdoc/html/markdown') diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index 3f0e586b8e3..0958d446c2d 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -8,36 +8,35 @@ use super::SpannedEvent; /// Moves all footnote definitions to the end and add back links to the /// references. -pub(super) struct Footnotes<'a, I> { +pub(super) struct Footnotes<'a, 'b, I> { inner: I, footnotes: FxIndexMap>, + existing_footnotes: &'b mut usize, } /// The definition of a single footnote. struct FootnoteDef<'a> { content: Vec>, /// The number that appears in the footnote reference and list. - id: u16, + id: usize, } -impl<'a, I> Footnotes<'a, I> { - pub(super) fn new(iter: I) -> Self { - Footnotes { inner: iter, footnotes: FxIndexMap::default() } +impl<'a, 'b, I> Footnotes<'a, 'b, I> { + pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self { + Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes } } - fn get_entry(&mut self, key: &str) -> (&mut Vec>, u16) { - let new_id = self.footnotes.len() + 1; + fn get_entry(&mut self, key: &str) -> (&mut Vec>, usize) { + let new_id = self.footnotes.len() + 1 + *self.existing_footnotes; let key = key.to_owned(); - let FootnoteDef { content, id } = self - .footnotes - .entry(key) - .or_insert(FootnoteDef { content: Vec::new(), id: new_id as u16 }); + let FootnoteDef { content, id } = + self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id }); // Don't allow changing the ID of existing entrys, but allow changing the contents. (content, *id) } } -impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { +impl<'a, 'b, I: Iterator>> Iterator for Footnotes<'a, 'b, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { @@ -47,8 +46,13 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { // When we see a reference (to a footnote we may not know) the definition of, // reserve a number for it, and emit a link to that number. let (_, id) = self.get_entry(reference); - let reference = - format!("{0}", id); + let reference = format!( + "{1}", + id, + // Although the ID count is for the whole page, the footnote reference + // are local to the item so we make this ID "local" when displayed. + id - *self.existing_footnotes + ); return Some((Event::Html(reference.into()), range)); } Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => { @@ -64,6 +68,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { // After all the markdown is emmited, emit an
then all the footnotes // in a list. let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect(); + *self.existing_footnotes += defs.len(); let defs_html = render_footnotes_defs(defs); return Some((Event::Html(defs_html.into()), 0..0)); } else { -- cgit 1.4.1-3-g733a5