diff options
| author | Sébastien d'Herbais de Thun <sebastien.d.herbais@gmail.com> | 2023-04-04 19:21:25 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-04 19:21:25 +0200 |
| commit | f347ed4314e32383dc09ff234180e8ea6fef7b8b (patch) | |
| tree | dba4296812a131e52da4eb0079fd0d240860d832 /src/model/content.rs | |
| parent | 5b0297464efc131beb7be84fa7a02b9a8670b5dd (diff) | |
Improved figure numbering, labelling and referencing (#491)
Diffstat (limited to 'src/model/content.rs')
| -rw-r--r-- | src/model/content.rs | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/src/model/content.rs b/src/model/content.rs index f95ce104..db867715 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -7,7 +7,7 @@ use ecow::{eco_format, EcoString, EcoVec}; use super::{ element, Behave, Behaviour, ElemFunc, Element, Fold, Guard, Label, Locatable, - Location, Recipe, Style, Styles, Synthesize, + Location, Recipe, Selector, Style, Styles, Synthesize, }; use crate::diag::{SourceResult, StrResult}; use crate::doc::Meta; @@ -105,6 +105,12 @@ impl Content { (self.func.0.vtable)(TypeId::of::<C>()).is_some() } + /// Whether the contained element has the given capability. + /// Where the capability is given by a `TypeId`. + pub fn can_type_id(&self, type_id: TypeId) -> bool { + (self.func.0.vtable)(type_id).is_some() + } + /// Cast to a trait object if the contained element has the given /// capability. pub fn with<C>(&self) -> Option<&C> @@ -347,6 +353,62 @@ impl Content { pub fn set_location(&mut self, location: Location) { self.attrs.push(Attr::Location(location)); } + + /// Gives an iterator over the children of this content + pub fn children(&self) -> impl Iterator<Item = &Content> { + self.attrs.iter().filter_map(Attr::child) + } + + /// Gives an iterator over the children of this content that are contained + /// within the arguments of the content. + pub fn children_in_args(&self) -> impl Iterator<Item = &Content> { + self.attrs + .iter() + .filter_map(Attr::value) + .filter_map(|value| match value { + Value::Content(content) => Some(content), + _ => None, + }) + } + + /// Queries the content tree for all elements that match the given selector. + /// + /// # Show rules + /// Elements produced in `show` rules will not be included in the results. + pub fn query(&self, selector: Selector) -> Vec<Content> { + let mut results = Vec::new(); + self.query_into(&selector, &mut results); + results + } + + /// Queries the content tree for all elements that match the given selector + /// and stores the results inside of the `results` vec. + fn query_into(&self, selector: &Selector, results: &mut Vec<Content>) { + if selector.matches(self) { + results.push(self.clone()); + } + + for attr in &self.attrs { + match attr { + Attr::Child(child) => child.query_into(selector, results), + Attr::Value(value) => walk_value(&value, selector, results), + _ => {} + } + } + + /// Walks a given value to find any content that matches the selector. + fn walk_value(value: &Value, selector: &Selector, results: &mut Vec<Content>) { + match value { + Value::Content(content) => content.query_into(selector, results), + Value::Array(array) => { + for value in array { + walk_value(value, selector, results); + } + } + _ => {} + } + } + } } impl Debug for Content { |
