diff options
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/conversion.rs | 17 | ||||
| -rw-r--r-- | src/parser/conversion/block.rs | 7 | ||||
| -rw-r--r-- | src/parser/conversion/inline.rs | 23 | ||||
| -rw-r--r-- | src/parser/simplify.rs | 197 | 
4 files changed, 183 insertions, 61 deletions
| diff --git a/src/parser/conversion.rs b/src/parser/conversion.rs index 5154f40..32461bf 100644 --- a/src/parser/conversion.rs +++ b/src/parser/conversion.rs @@ -72,6 +72,23 @@ pub fn convert_document(pairs: Pairs<Rule>) -> Result<e::Document, Error> {  	Ok(e::Document::with_children(toplevel))  } +/// Normalizes a name in terms of whitespace. Equivalent to docutils's +/// `docutils.nodes.whitespace_normalize_name`. +pub fn whitespace_normalize_name(name: &str) -> String { +	// Python's string.split() defines whitespace differently than Rust does. +	let split_iter = name.split( +		|ch: char| ch.is_whitespace() || (ch >= '\x1C' && ch <= '\x1F') +	).filter(|split| !split.is_empty()); +	let mut ret = String::new(); +	for split in split_iter { +		if !ret.is_empty() { +			ret.push(' '); +		} +		ret.push_str(split); +	} +	ret +} +  #[cfg(test)]  mod tests { diff --git a/src/parser/conversion/block.rs b/src/parser/conversion/block.rs index 714b410..9552539 100644 --- a/src/parser/conversion/block.rs +++ b/src/parser/conversion/block.rs @@ -6,13 +6,14 @@ use crate::document_tree::{  	elements as e,  	element_categories as c,  	extra_attributes as a, +	attribute_types as at  };  use crate::parser::{  	pest_rst::Rule,  	pair_ext_parse::PairExt,  }; -use super::inline::convert_inline; +use super::{whitespace_normalize_name, inline::convert_inline};  #[derive(PartialEq)] @@ -92,14 +93,14 @@ fn convert_target(pair: Pair<Rule>) -> Result<e::Target, Error> {  fn convert_substitution_def(pair: Pair<Rule>) -> Result<e::SubstitutionDefinition, Error> {  	let mut pairs = pair.into_inner(); -	let name = pairs.next().unwrap().as_str();  // Rule::substitution_name +	let name = whitespace_normalize_name(pairs.next().unwrap().as_str());  // Rule::substitution_name  	let inner_pair = pairs.next().unwrap();  	let inner: c::TextOrInlineElement = match inner_pair.as_rule() {  		Rule::image => convert_image::<e::ImageInline>(inner_pair)?.into(),  		rule => panic!("Unknown substitution rule {:?}", rule),  	};  	let mut subst_def = e::SubstitutionDefinition::with_children(vec![inner]); -	subst_def.names_mut().push(name.into()); +	subst_def.names_mut().push(at::NameToken(name));  	Ok(subst_def)  } diff --git a/src/parser/conversion/inline.rs b/src/parser/conversion/inline.rs index c30b71d..50a6258 100644 --- a/src/parser/conversion/inline.rs +++ b/src/parser/conversion/inline.rs @@ -6,6 +6,7 @@ use crate::document_tree::{  	elements as e,  	element_categories as c,  	extra_attributes as a, +	attribute_types as at  };  use crate::parser::{ @@ -13,11 +14,14 @@ use crate::parser::{  //    pair_ext_parse::PairExt,  }; +use super::whitespace_normalize_name; +  pub fn convert_inline(pair: Pair<Rule>) -> Result<c::TextOrInlineElement, Error> {  	Ok(match pair.as_rule() { -		Rule::str       => pair.as_str().into(), -		Rule::reference => convert_reference(pair)?.into(), +		Rule::str       		=> pair.as_str().into(), +		Rule::reference 		=> convert_reference(pair)?.into(), +		Rule::substitution_ref 	=> convert_substitution(pair)?.into(),  		rule => unimplemented!("unknown rule {:?}", rule),  	})  } @@ -42,3 +46,18 @@ fn convert_reference(pair: Pair<Rule>) -> Result<e::Reference, Error> {  		a::Reference { name, refuri, refid, refname }  	))  } + +fn convert_substitution(pair: Pair<Rule>) -> Result<e::SubstitutionReference, Error> { +	let concrete = pair.into_inner().next().unwrap(); +	match concrete.as_rule() { +		Rule::substitution_name => { +			let name = whitespace_normalize_name(concrete.as_str()); +			Ok(a::ExtraAttributes::with_extra( +				a::SubstitutionReference { +					refname: vec![at::NameToken(name)] +				} +			)) +		} +		_ => unreachable!() +	} +} diff --git a/src/parser/simplify.rs b/src/parser/simplify.rs index 8f699e4..bb47760 100644 --- a/src/parser/simplify.rs +++ b/src/parser/simplify.rs @@ -25,24 +25,55 @@ use crate::target::Target;  use crate::document_tree::{  	Document,  	HasChildren, -	attribute_types::ID, +	attribute_types::{ID, NameToken},  	elements as e,  	element_categories as c,  }; -enum MaybeDirectTarget { -	IndirectTarget(ID), -	DirectTarget(Target), +#[derive(Debug)] +enum NamedTargetType { +	NumberedFootnote(usize), +	LabeledFootnote(usize), +	Citation, +	InternalLink, +	ExternalLink(Target), +	IndirectLink(NameToken), +	SectionTitle +} +impl NamedTargetType { +	fn is_implicit_target(&self) -> bool { +		match self { +			NamedTargetType::SectionTitle => true, +			_ => false +		} +	} +} + +#[derive(Clone, Debug)] +struct Substitution { +	content: e::ImageInline, +	// If `ltrim` is true and the sibling before the reference is a text node, +	// the text node gets right-trimmed. Same for `rtrim` with the sibling after +	// getting left-trimmed. +	ltrim: bool, +	rtrim: bool +} + +#[derive(Default, Debug)] +struct TargetsCollected { +	named_targets: HashMap<NameToken, NamedTargetType>, +	substitutions: HashMap<String, Substitution>, +	normalized_substitutions: HashMap<String, Substitution>  }  trait ResolvableRefs { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>); -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self; +	fn populate_targets(&self, refs: &mut TargetsCollected); +	fn resolve_refs(self, refs: &TargetsCollected) -> Self;  }  pub fn resolve_references(mut doc: Document) -> Document { -	let mut references = HashMap::new(); +	let mut references: TargetsCollected = Default::default();  	for c in doc.children() {  		c.populate_targets(&mut references);  	} @@ -50,32 +81,32 @@ pub fn resolve_references(mut doc: Document) -> Document {  	Document::with_children(new)  } -fn sub_pop<P, C>(parent: &P, refs: &mut HashMap<&ID, Target>) where P: HasChildren<C>, C: ResolvableRefs { +fn sub_pop<P, C>(parent: &P, refs: &mut TargetsCollected) where P: HasChildren<C>, C: ResolvableRefs {  	for c in parent.children() {  		c.populate_targets(refs);  	}  } -fn sub_res<P, C>(mut parent: P, refs: &HashMap<&ID, Target>) -> P where P: e::Element + HasChildren<C>, C: ResolvableRefs { -	let new: Vec<_> = parent.children_mut().drain(..).map(|c| c.resolve_refs(&refs)).collect(); +fn sub_res<P, C>(mut parent: P, refs: &TargetsCollected) -> P where P: e::Element + HasChildren<C>, C: ResolvableRefs { +	let new: Vec<_> = parent.children_mut().drain(..).map(|c| c.resolve_refs(refs)).collect();  	parent.children_mut().extend(new);  	parent  } -fn sub_sub_pop<P, C1, C2>(parent: &P, refs: &mut HashMap<&ID, Target>) where P: HasChildren<C1>, C1: HasChildren<C2>, C2: ResolvableRefs { +fn sub_sub_pop<P, C1, C2>(parent: &P, refs: &mut TargetsCollected) where P: HasChildren<C1>, C1: HasChildren<C2>, C2: ResolvableRefs {  	for c in parent.children() {  		sub_pop(c, refs);  	}  } -fn sub_sub_res<P, C1, C2>(mut parent: P, refs: &HashMap<&ID, Target>) -> P where P: e::Element + HasChildren<C1>, C1: e::Element + HasChildren<C2>, C2: ResolvableRefs { +fn sub_sub_res<P, C1, C2>(mut parent: P, refs: &TargetsCollected) -> P where P: e::Element + HasChildren<C1>, C1: e::Element + HasChildren<C2>, C2: ResolvableRefs {  	let new: Vec<_> = parent.children_mut().drain(..).map(|c| sub_res(c, refs)).collect();  	parent.children_mut().extend(new);  	parent  }  impl ResolvableRefs for c::StructuralSubElement { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::StructuralSubElement::*;  		match self {  			Title(e)        => sub_pop(&**e, refs), @@ -85,7 +116,7 @@ impl ResolvableRefs for c::StructuralSubElement {  			SubStructure(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::StructuralSubElement::*;  		match self {  			Title(e)        => sub_res(*e, refs).into(), @@ -98,7 +129,7 @@ impl ResolvableRefs for c::StructuralSubElement {  }  impl ResolvableRefs for c::SubStructure { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubStructure::*;  		match self {  			Topic(e) => sub_pop(&**e, refs), @@ -110,7 +141,7 @@ impl ResolvableRefs for c::SubStructure {  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubStructure::*;  		match self {  			Topic(e) => sub_res(*e, refs).into(), @@ -123,7 +154,8 @@ impl ResolvableRefs for c::SubStructure {  }  impl ResolvableRefs for c::BodyElement { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) { +		use crate::document_tree::extra_attributes::ExtraAttributes;  		use c::BodyElement::*;  		match self {  			Paragraph(e) => sub_pop(&**e, refs), @@ -133,8 +165,30 @@ impl ResolvableRefs for c::BodyElement {  				// TODO  			},  			Rubric(e) => sub_pop(&**e, refs), -			SubstitutionDefinition(e) => sub_pop(&**e, refs), -			Comment(e) => sub_pop(&**e, refs), +			SubstitutionDefinition(e) => { +				use e::Element; +				let subst_content = if let [c::TextOrInlineElement::ImageInline(content)] = &e.children()[..] { +					content.as_ref() +				} else { +					panic!("Unexpected substitution contents.") +				}; +				let subst = Substitution { +					content: subst_content.clone(), +					ltrim: e.extra().ltrim, +					rtrim: e.extra().rtrim +				}; +				for NameToken(name) in e.names() { +					if refs.substitutions.contains_key(name) { +						// TODO: Duplicate substitution name (level 3 system message). +					} +					// Intentionally overriding any previous values. +					refs.substitutions.insert(name.clone(), subst.clone()); +					refs.normalized_substitutions.insert(name.to_lowercase(), subst.clone()); +				} +			}, +			Comment(e) => { +				// TODO +			},  			Pending(e) => {  				// TODO  			}, @@ -173,7 +227,7 @@ impl ResolvableRefs for c::BodyElement {  			Table(e) => sub_pop(&**e, refs)  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::BodyElement::*;  		match self {  			Paragraph(e) => sub_res(*e, refs).into(), @@ -181,8 +235,8 @@ impl ResolvableRefs for c::BodyElement {  			DoctestBlock(e) => sub_res(*e, refs).into(),  			MathBlock(e) => MathBlock(e),  			Rubric(e) => sub_res(*e, refs).into(), -			SubstitutionDefinition(e) => sub_res(*e, refs).into(), -			Comment(e) => sub_res(*e, refs).into(), +			SubstitutionDefinition(e) => SubstitutionDefinition(e), +			Comment(e) => Comment(e),  			Pending(e) => Pending(e),  			Target(e) => Target(e),  			Raw(e) => Raw(e), @@ -216,7 +270,7 @@ impl ResolvableRefs for c::BodyElement {  }  impl ResolvableRefs for c::BibliographicElement { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::BibliographicElement::*;  		match self {  			Author(e) => sub_pop(&**e, refs), @@ -232,7 +286,7 @@ impl ResolvableRefs for c::BibliographicElement {  			Field(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::BibliographicElement::*;  		match self {  			Author(e) => sub_res(*e, refs).into(), @@ -251,7 +305,7 @@ impl ResolvableRefs for c::BibliographicElement {  }  impl ResolvableRefs for c::TextOrInlineElement { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::TextOrInlineElement::*;  		match self {  			c::TextOrInlineElement::String(e) => { @@ -286,7 +340,7 @@ impl ResolvableRefs for c::TextOrInlineElement {  			}  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::TextOrInlineElement::*;  		match self {  			c::TextOrInlineElement::String(e) => c::TextOrInlineElement::String(e), @@ -296,7 +350,38 @@ impl ResolvableRefs for c::TextOrInlineElement {  			Reference(e) => sub_res(*e, refs).into(),  			FootnoteReference(e) => sub_res(*e, refs).into(),  			CitationReference(e) => sub_res(*e, refs).into(), -			SubstitutionReference(e) => sub_res(*e, refs).into(), +			SubstitutionReference(e) => { +				use crate::document_tree::extra_attributes::ExtraAttributes; +				if e.extra().refname.len() != 1 { +					panic!("Expected exactly one name in a substitution reference."); +				} +				let name = e.extra().refname[0].0.clone(); +				let substitution = refs.substitutions.get(&name).or_else(|| { +					refs.normalized_substitutions.get(&name.to_lowercase()) +				}); +				match substitution { +					Some(Substitution {content, ltrim, rtrim}) => { +						// TODO: Check if the substitution would expand circularly +						// (level 3 system message). +						// TODO: Ltrim and rtrim. +						ImageInline(Box::new(content.clone())) +					}, +					None => { +						// Undefined substitution name (level 3 system message). +						// TODO: This replaces the reference by a Problematic node. +						// The corresponding SystemMessage node should go in a generated +						// section with class "system-messages" at the end of the document. +						use crate::document_tree::{Problematic, element_categories::TextOrInlineElement}; +						let mut replacement: Box<Problematic> = Box::new(Default::default()); +						replacement.children_mut().push( +							TextOrInlineElement::String(Box::new(format!("|{}|", name))) +						); +						// TODO: Create an ID for replacement for the system_message to reference. +						// TODO: replacement.refid pointing to the system_message. +						Problematic(replacement) +					} +				} +			},  			TitleReference(e) => sub_res(*e, refs).into(),  			Abbreviation(e) => sub_res(*e, refs).into(),  			Acronym(e) => sub_res(*e, refs).into(), @@ -314,7 +399,7 @@ impl ResolvableRefs for c::TextOrInlineElement {  }  impl ResolvableRefs for c::AuthorInfo { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::AuthorInfo::*;  		match self {  			Author(e) => sub_pop(&**e, refs), @@ -323,7 +408,7 @@ impl ResolvableRefs for c::AuthorInfo {  			Contact(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::AuthorInfo::*;  		match self {  			Author(e) => sub_res(*e, refs).into(), @@ -335,14 +420,14 @@ impl ResolvableRefs for c::AuthorInfo {  }  impl ResolvableRefs for c::DecorationElement { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::DecorationElement::*;  		match self {  			Header(e) => sub_pop(&**e, refs),  			Footer(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::DecorationElement::*;  		match self {  			Header(e) => sub_res(*e, refs).into(), @@ -352,14 +437,14 @@ impl ResolvableRefs for c::DecorationElement {  }  impl ResolvableRefs for c::SubTopic { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubTopic::*;  		match self {  			Title(e) => sub_pop(&**e, refs),  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubTopic::*;  		match self {  			Title(e) => sub_res(*e, refs).into(), @@ -369,7 +454,7 @@ impl ResolvableRefs for c::SubTopic {  }  impl ResolvableRefs for c::SubSidebar { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubSidebar::*;  		match self {  			Topic(e) => sub_pop(&**e, refs), @@ -378,7 +463,7 @@ impl ResolvableRefs for c::SubSidebar {  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubSidebar::*;  		match self {  			Topic(e) => sub_res(*e, refs).into(), @@ -390,7 +475,7 @@ impl ResolvableRefs for c::SubSidebar {  }  impl ResolvableRefs for c::SubDLItem { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubDLItem::*;  		match self {  			Term(e) => sub_pop(&**e, refs), @@ -398,7 +483,7 @@ impl ResolvableRefs for c::SubDLItem {  			Definition(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubDLItem::*;  		match self {  			Term(e) => sub_res(*e, refs).into(), @@ -409,14 +494,14 @@ impl ResolvableRefs for c::SubDLItem {  }  impl ResolvableRefs for c::SubField { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubField::*;  		match self {  			FieldName(e) => sub_pop(&**e, refs),  			FieldBody(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubField::*;  		match self {  			FieldName(e) => sub_res(*e, refs).into(), @@ -426,14 +511,14 @@ impl ResolvableRefs for c::SubField {  }  impl ResolvableRefs for c::SubOptionListItem { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubOptionListItem::*;  		match self {  			OptionGroup(e) => sub_sub_pop(&**e, refs),  			Description(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubOptionListItem::*;  		match self {  			OptionGroup(e) => sub_sub_res(*e, refs).into(), @@ -443,7 +528,7 @@ impl ResolvableRefs for c::SubOptionListItem {  }  impl ResolvableRefs for c::SubOption { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubOption::*;  		match self {  			OptionString(e) => { @@ -454,7 +539,7 @@ impl ResolvableRefs for c::SubOption {  			},  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubOption::*;  		match self {  			OptionString(e) => OptionString(e), @@ -464,14 +549,14 @@ impl ResolvableRefs for c::SubOption {  }  impl ResolvableRefs for c::SubLineBlock { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubLineBlock::*;  		match self {  			LineBlock(e) => sub_pop(&**e, refs),  			Line(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubLineBlock::*;  		match self {  			LineBlock(e) => sub_res(*e, refs).into(), @@ -481,14 +566,14 @@ impl ResolvableRefs for c::SubLineBlock {  }  impl ResolvableRefs for c::SubBlockQuote { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubBlockQuote::*;  		match self {  			Attribution(e) => sub_pop(&**e, refs),  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubBlockQuote::*;  		match self {  			Attribution(e) => sub_res(*e, refs).into(), @@ -498,14 +583,14 @@ impl ResolvableRefs for c::SubBlockQuote {  }  impl ResolvableRefs for c::SubFootnote { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubFootnote::*;  		match self {  			Label(e) => sub_pop(&**e, refs),  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubFootnote::*;  		match self {  			Label(e) => sub_res(*e, refs).into(), @@ -515,7 +600,7 @@ impl ResolvableRefs for c::SubFootnote {  }  impl ResolvableRefs for c::SubFigure { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubFigure::*;  		match self {  			Caption(e) => sub_pop(&**e, refs), @@ -523,7 +608,7 @@ impl ResolvableRefs for c::SubFigure {  			BodyElement(e) => e.populate_targets(refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubFigure::*;  		match self {  			Caption(e) => sub_res(*e, refs).into(), @@ -534,14 +619,14 @@ impl ResolvableRefs for c::SubFigure {  }  impl ResolvableRefs for c::SubTable { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubTable::*;  		match self {  			Title(e) => sub_pop(&**e, refs),  			TableGroup(e) => sub_pop(&**e, refs),  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubTable::*;  		match self {  			Title(e) => sub_res(*e, refs).into(), @@ -551,7 +636,7 @@ impl ResolvableRefs for c::SubTable {  }  impl ResolvableRefs for c::SubTableGroup { -	fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { +	fn populate_targets(&self, refs: &mut TargetsCollected) {  		use c::SubTableGroup::*;  		match self {  			TableColspec(e) => { @@ -569,7 +654,7 @@ impl ResolvableRefs for c::SubTableGroup {  			},  		}  	} -	fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { +	fn resolve_refs(self, refs: &TargetsCollected) -> Self {  		use c::SubTableGroup::*;  		match self {  			TableColspec(e) => TableColspec(e), @@ -585,4 +670,4 @@ impl ResolvableRefs for c::SubTableGroup {  			},  		}  	} -}
\ No newline at end of file +} | 
