series
}
+ /// Decodes the table of footnotes from the `graph` and the collection of
+ /// all the footnote labels. Any [Value] might refer to footnotes, so it's
+ /// important to process the footnotes early to ensure that those references
+ /// can be resolved.
+ fn decode_footnotes(&self, graph: &Graph, footnote_labels: &[&Label]) -> pivot::Footnotes {
+ let mut footnote_builder = BTreeMap::<usize, Footnote>::new();
+ if let Some(f) = &graph.interval.footnotes {
+ f.decode(&mut footnote_builder);
+ }
+ for child in &graph.interval.labeling.children {
+ if let LabelingChild::Footnotes(f) = child {
+ f.decode(&mut footnote_builder);
+ }
+ }
+ for label in footnote_labels {
+ for (index, text) in label.text().iter().enumerate() {
+ if let Some(uses_reference) = text.uses_reference {
+ let entry = footnote_builder
+ .entry(uses_reference.get() - 1)
+ .or_default();
+ if index % 2 == 1 {
+ entry.content = text.text.strip_suffix('\n').unwrap_or(&text.text).into();
+ } else {
+ entry.marker = Some(
+ text.text
+ .trim_end()
+ .strip_suffix('.')
+ .unwrap_or(&text.text)
+ .into(),
+ );
+ }
+ }
+ }
+ }
+ let mut footnotes = Vec::new();
+ for (index, footnote) in footnote_builder {
+ while footnotes.len() < index {
+ footnotes.push(pivot::Footnote::default());
+ }
+ footnotes.push(
+ pivot::Footnote::new(footnote.content)
+ .with_marker(footnote.marker.map(|s| Value::new_user_text(s))),
+ );
+ }
+ pivot::Footnotes::from_iter(footnotes)
+ }
+
pub fn decode(
&self,
data: IndexMap<String, IndexMap<String, Vec<DataValue>>>,
}
}
- // Footnotes.
- //
- // Any [Value] might refer to footnotes, so it's important to process
- // the footnotes early to ensure that those references can be resolved.
- // There is a possible problem that a footnote might itself reference an
- // as-yet-unprocessed footnote, but that's OK because footnote
- // references don't actually look at the footnote contents but only
- // resolve a pointer to where the footnote will go later.
- //
- // Before we really start, create all the footnotes we'll fill in. This
- // is because sometimes footnotes refer to themselves or to each other
- // and we don't want to reject those references.
- let mut footnote_builder = BTreeMap::<usize, Footnote>::new();
- if let Some(f) = &graph.interval.footnotes {
- f.decode(&mut footnote_builder);
- }
- for child in &graph.interval.labeling.children {
- if let LabelingChild::Footnotes(f) = child {
- f.decode(&mut footnote_builder);
- }
- }
- for label in &labels[Purpose::Footnote] {
- for (index, text) in label.text().iter().enumerate() {
- if let Some(uses_reference) = text.uses_reference {
- let entry = footnote_builder
- .entry(uses_reference.get() - 1)
- .or_default();
- if index % 2 == 1 {
- entry.content = text.text.strip_suffix('\n').unwrap_or(&text.text).into();
- } else {
- entry.marker = Some(
- text.text
- .trim_end()
- .strip_suffix('.')
- .unwrap_or(&text.text)
- .into(),
- );
- }
- }
- }
- }
- let mut footnotes = Vec::new();
- for (index, footnote) in footnote_builder {
- while footnotes.len() < index {
- footnotes.push(pivot::Footnote::default());
- }
- footnotes.push(
- pivot::Footnote::new(footnote.content)
- .with_marker(footnote.marker.map(|s| Value::new_user_text(s))),
- );
- }
- let footnotes = pivot::Footnotes::from_iter(footnotes);
+ let footnotes = self.decode_footnotes(graph, &labels[Purpose::Footnote]);
let title = LabelFrame::decode_label(&labels[Purpose::Title], &footnotes);
let mut caption_labels = &labels[Purpose::SubTitle];