diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-05-22 20:50:15 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-05-22 20:56:30 +0200 |
| commit | f4fd6855e7fb833a2125d2e81aa3b9f548b18170 (patch) | |
| tree | 6e3675ca8c4b9f9fae05a598e753e3a410d2cce2 /library/src/math/mod.rs | |
| parent | 183997d5fe76cf0b41fd26bfa29d166071d239eb (diff) | |
Fix and simplify reference supplements
- Fixes #873 by properly handling `none` supplement for`ref`.
- Fixes #523 by adding a `supplement` parameter to `math.equation`
- In the future, we can remove supplement functions in favor of show-set rules with fine-grained selectors. Currently, this is not possible because show-set + synthesis doesn't play well together
Diffstat (limited to 'library/src/math/mod.rs')
| -rw-r--r-- | library/src/math/mod.rs | 100 |
1 files changed, 68 insertions, 32 deletions
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs index c4c18b87..f0e42e68 100644 --- a/library/src/math/mod.rs +++ b/library/src/math/mod.rs @@ -42,8 +42,10 @@ use self::fragment::*; use self::row::*; use self::spacing::*; use crate::layout::{HElem, ParElem, Spacing}; -use crate::meta::Refable; -use crate::meta::{Count, Counter, CounterUpdate, LocalName, Numbering}; +use crate::meta::Supplement; +use crate::meta::{ + Count, Counter, CounterUpdate, LocalName, Numbering, Outlinable, Refable, +}; use crate::prelude::*; use crate::text::{ families, variant, FontFamily, FontList, LinebreakElem, SpaceElem, TextElem, TextSize, @@ -140,7 +142,8 @@ pub fn module() -> Module { /// Display: Equation /// Category: math #[element( - Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName, Refable + Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName, Refable, + Outlinable )] pub struct EquationElem { /// Whether the equation is displayed as a separate block. @@ -160,15 +163,44 @@ pub struct EquationElem { /// ``` pub numbering: Option<Numbering>, + /// A supplement for the equation. + /// + /// For references to equations, this is added before the referenced number. + /// + /// If a function is specified, it is passed the referenced equation and + /// should return content. + /// + /// ```example + /// #set math.equation(numbering: "(1)", supplement: [Eq.]) + /// + /// We define: + /// $ phi.alt := (1 + sqrt(5)) / 2 $ <ratio> + /// + /// With @ratio, we get: + /// $ F_n = floor(1 / sqrt(5) phi.alt^n) $ + /// ``` + pub supplement: Smart<Option<Supplement>>, + /// The contents of the equation. #[required] pub body: Content, } impl Synthesize for EquationElem { - fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> { + fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> { + // Resolve the supplement. + let supplement = match self.supplement(styles) { + Smart::Auto => TextElem::packed(self.local_name_in(styles)), + Smart::Custom(None) => Content::empty(), + Smart::Custom(Some(supplement)) => { + supplement.resolve(vt, [self.clone().into()])? + } + }; + self.push_block(self.block(styles)); self.push_numbering(self.numbering(styles)); + self.push_supplement(Smart::Custom(Some(Supplement::Content(supplement)))); + Ok(()) } } @@ -302,41 +334,45 @@ impl LocalName for EquationElem { } impl Refable for EquationElem { - fn reference( - &self, - vt: &mut Vt, - supplement: Option<Content>, - lang: Lang, - region: Option<Region>, - ) -> SourceResult<Content> { - // first we create the supplement of the heading - let mut supplement = - supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang, region))); - - // we append a space if the supplement is not empty - if !supplement.is_empty() { - supplement += TextElem::packed('\u{a0}') - }; - - // we check for a numbering - let Some(numbering) = self.numbering(StyleChain::default()) else { - bail!(self.span(), "only numbered equations can be referenced"); - }; - - // we get the counter and display it - let numbers = Counter::of(Self::func()) - .at(vt, self.0.location().expect("missing location"))? - .display(vt, &numbering.trimmed())?; + fn supplement(&self) -> Content { + // After synthesis, this should always be custom content. + match self.supplement(StyleChain::default()) { + Smart::Custom(Some(Supplement::Content(content))) => content, + _ => Content::empty(), + } + } - Ok(supplement + numbers) + fn counter(&self) -> Counter { + Counter::of(Self::func()) } fn numbering(&self) -> Option<Numbering> { self.numbering(StyleChain::default()) } +} - fn counter(&self) -> Counter { - Counter::of(Self::func()) +impl Outlinable for EquationElem { + fn outline(&self, vt: &mut Vt) -> SourceResult<Option<Content>> { + let Some(numbering) = self.numbering(StyleChain::default()) else { + return Ok(None); + }; + + // After synthesis, this should always be custom content. + let mut supplement = match self.supplement(StyleChain::default()) { + Smart::Custom(Some(Supplement::Content(content))) => content, + _ => Content::empty(), + }; + + if !supplement.is_empty() { + supplement += TextElem::packed("\u{a0}"); + } + + let numbers = self + .counter() + .at(vt, self.0.location().unwrap())? + .display(vt, &numbering)?; + + Ok(Some(supplement + numbers)) } } |
