diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-02-02 15:25:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-02 14:25:19 +0000 |
| commit | 2594b367010028277240273e99ab32ac352461f3 (patch) | |
| tree | c589b155f0f425fb38c1114a007d669c7b3bc9ac | |
| parent | 356032bf8cdb759e93c2c6b853fe77b9c5f57c07 (diff) | |
Support for and/or selectors in show rules (#3326)
| -rw-r--r-- | crates/typst/src/foundations/selector.rs | 22 | ||||
| -rw-r--r-- | tests/ref/compiler/show-selector-logical.png | bin | 0 -> 8207 bytes | |||
| -rw-r--r-- | tests/typ/compiler/show-selector-logical.typ | 21 | ||||
| -rw-r--r-- | tests/typ/compiler/show-selector.typ | 4 |
4 files changed, 34 insertions, 13 deletions
diff --git a/crates/typst/src/foundations/selector.rs b/crates/typst/src/foundations/selector.rs index 16bd721d..ee7691b0 100644 --- a/crates/typst/src/foundations/selector.rs +++ b/crates/typst/src/foundations/selector.rs @@ -176,9 +176,9 @@ impl Selector { self, /// The other selectors to match on. #[variadic] - others: Vec<LocatableSelector>, + others: Vec<Selector>, ) -> Selector { - Self::Or(others.into_iter().map(|s| s.0).chain(Some(self)).collect()) + Self::Or(others.into_iter().chain(Some(self)).collect()) } /// Selects all elements that match this and all of the the other selectors. @@ -187,9 +187,9 @@ impl Selector { self, /// The other selectors to match on. #[variadic] - others: Vec<LocatableSelector>, + others: Vec<Selector>, ) -> Selector { - Self::And(others.into_iter().map(|s| s.0).chain(Some(self)).collect()) + Self::And(others.into_iter().chain(Some(self)).collect()) } /// Returns a modified selector that will only match elements that occur @@ -407,13 +407,17 @@ cast! { impl FromValue for ShowableSelector { fn from_value(value: Value) -> StrResult<Self> { - fn validate(selector: &Selector) -> StrResult<()> { + fn validate(selector: &Selector, nested: bool) -> StrResult<()> { match selector { Selector::Elem(_, _) => {} Selector::Label(_) => {} - Selector::Regex(_) => {} - Selector::Or(_) - | Selector::And(_) + Selector::Regex(_) if !nested => {} + Selector::Or(list) | Selector::And(list) => { + for selector in list { + validate(selector, true)?; + } + } + Selector::Regex(_) | Selector::Location(_) | Selector::Can(_) | Selector::Before { .. } @@ -429,7 +433,7 @@ impl FromValue for ShowableSelector { } let selector = Selector::from_value(value)?; - validate(&selector)?; + validate(&selector, false)?; Ok(Self(selector)) } } diff --git a/tests/ref/compiler/show-selector-logical.png b/tests/ref/compiler/show-selector-logical.png Binary files differnew file mode 100644 index 00000000..4d1be5ed --- /dev/null +++ b/tests/ref/compiler/show-selector-logical.png diff --git a/tests/typ/compiler/show-selector-logical.typ b/tests/typ/compiler/show-selector-logical.typ new file mode 100644 index 00000000..a11e20b6 --- /dev/null +++ b/tests/typ/compiler/show-selector-logical.typ @@ -0,0 +1,21 @@ +// Test and/or selectors in show rules. + +--- +// Looking forward to `heading.where(level: 1 | 2)` :) +#show heading.where(level: 1).or(heading.where(level: 2)): set text(red) += L1 +== L2 +=== L3 +==== L4 + +--- +// Test element selector combined with label selector. +#show selector(strong).or(<special>): highlight +I am *strong*, I am _emphasized_, and I am #[special<special>]. + +--- +// Ensure that text selector cannot be nested in and/or. That's too complicated, +// at least for now. + +// Error: 7-41 this selector cannot be used with show +#show heading.where(level: 1).or("more"): set text(red) diff --git a/tests/typ/compiler/show-selector.typ b/tests/typ/compiler/show-selector.typ index 48a26014..db6db40f 100644 --- a/tests/typ/compiler/show-selector.typ +++ b/tests/typ/compiler/show-selector.typ @@ -37,7 +37,3 @@ the ```rs &mut T``` reference. = Red == Blue === Green - ---- -// Error: 7-35 this selector cannot be used with show -#show selector(heading).or(figure): none |
