diff --git a/crates/typst-library/src/foundations/content.rs b/crates/typst-library/src/foundations/content.rs index 76cd6a222..424b4597e 100644 --- a/crates/typst-library/src/foundations/content.rs +++ b/crates/typst-library/src/foundations/content.rs @@ -412,7 +412,7 @@ impl Content { /// Queries the content tree for all elements that match the given selector. /// /// Elements produced in `show` rules will not be included in the results. - pub fn query(&self, selector: Selector) -> Vec { + pub fn query(&self, selector: &Selector) -> Vec { let mut results = Vec::new(); self.traverse(&mut |element| { if selector.matches(&element, None) { diff --git a/crates/typst-library/src/foundations/selector.rs b/crates/typst-library/src/foundations/selector.rs index bf5449d94..1435465ab 100644 --- a/crates/typst-library/src/foundations/selector.rs +++ b/crates/typst-library/src/foundations/selector.rs @@ -93,6 +93,9 @@ pub enum Selector { Before { selector: Arc, end: Arc, inclusive: bool }, /// Matches all matches of `selector` after `start`. After { selector: Arc, start: Arc, inclusive: bool }, + /// Matches all children of `selector` matchin `c` + /// TODO: Better name + Contains { selector: Arc, c: Arc }, } impl Selector { @@ -139,7 +142,10 @@ impl Selector { } Self::Location(location) => target.location() == Some(*location), // Not supported here. - Self::Regex(_) | Self::Before { .. } | Self::After { .. } => false, + Self::Regex(_) + | Self::Before { .. } + | Self::After { .. } + | Self::Contains { .. } => false, } } } @@ -221,6 +227,11 @@ impl Selector { inclusive, } } + + #[func] + pub fn contains(self, c: LocatableSelector) -> Selector { + Self::Contains { selector: Arc::new(self), c: Arc::new(c.0) } + } } impl From for Selector { @@ -266,6 +277,7 @@ impl Repr for Selector { inclusive_arg ) } + Self::Contains { .. } => todo!(), } } } @@ -352,7 +364,8 @@ impl FromValue for LocatableSelector { } } Selector::Before { selector, end: split, .. } - | Selector::After { selector, start: split, .. } => { + | Selector::After { selector, start: split, .. } + | Selector::Contains { selector, c: split } => { for selector in [selector, split] { validate(selector)?; } @@ -431,7 +444,8 @@ impl FromValue for ShowableSelector { | Selector::Location(_) | Selector::Can(_) | Selector::Before { .. } - | Selector::After { .. } => { + | Selector::After { .. } + | Selector::Contains { .. } => { bail!("this selector cannot be used with show") } } diff --git a/crates/typst-library/src/introspection/introspector.rs b/crates/typst-library/src/introspection/introspector.rs index 8cbaea891..1b0f08fcb 100644 --- a/crates/typst-library/src/introspection/introspector.rs +++ b/crates/typst-library/src/introspection/introspector.rs @@ -185,6 +185,11 @@ impl Introspector { } list } + Selector::Contains { selector, c } => self + .query(selector) + .iter() + .flat_map(|children| children.query(c)) + .collect(), // Not supported here. Selector::Can(_) | Selector::Regex(_) => EcoVec::new(), };