diff options
Diffstat (limited to 'crates/typst-realize/src/lib.rs')
| -rw-r--r-- | crates/typst-realize/src/lib.rs | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/crates/typst-realize/src/lib.rs b/crates/typst-realize/src/lib.rs index fcfb4066..6af249cc 100644 --- a/crates/typst-realize/src/lib.rs +++ b/crates/typst-realize/src/lib.rs @@ -14,9 +14,9 @@ use ecow::EcoString; use typst_library::diag::{bail, At, SourceResult}; use typst_library::engine::Engine; use typst_library::foundations::{ - Content, Context, ContextElem, Element, NativeElement, Recipe, RecipeIndex, Selector, - SequenceElem, Show, ShowSet, Style, StyleChain, StyledElem, Styles, SymbolElem, - Synthesize, Transformation, + Content, Context, ContextElem, Element, NativeElement, NativeShowRule, Recipe, + RecipeIndex, Selector, SequenceElem, ShowSet, Style, StyleChain, StyledElem, Styles, + SymbolElem, Synthesize, TargetElem, Transformation, }; use typst_library::html::{tag, FrameElem, HtmlElem}; use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem}; @@ -160,7 +160,7 @@ enum ShowStep<'a> { /// A user-defined transformational show rule. Recipe(&'a Recipe, RecipeIndex), /// The built-in show rule. - Builtin, + Builtin(NativeShowRule), } /// A match of a regex show rule. @@ -382,9 +382,7 @@ fn visit_show_rules<'a>( } // Apply a built-in show rule. - ShowStep::Builtin => { - output.with::<dyn Show>().unwrap().show(s.engine, chained) - } + ShowStep::Builtin(rule) => rule.apply(&output, s.engine, chained), }; // Errors in show rules don't terminate compilation immediately. We just @@ -426,14 +424,14 @@ fn visit_show_rules<'a>( Ok(true) } -/// Inspects a target element and the current styles and determines how to -/// proceed with the styling. +/// Inspects an element and the current styles and determines how to proceed +/// with the styling. fn verdict<'a>( engine: &mut Engine, - target: &'a Content, + elem: &'a Content, styles: StyleChain<'a>, ) -> Option<Verdict<'a>> { - let prepared = target.is_prepared(); + let prepared = elem.is_prepared(); let mut map = Styles::new(); let mut step = None; @@ -441,20 +439,20 @@ fn verdict<'a>( // fields before real synthesis runs (during preparation). It's really // unfortunate that we have to do this, but otherwise // `show figure.where(kind: table)` won't work :( - let mut target = target; + let mut elem = elem; let mut slot; - if !prepared && target.can::<dyn Synthesize>() { - slot = target.clone(); + if !prepared && elem.can::<dyn Synthesize>() { + slot = elem.clone(); slot.with_mut::<dyn Synthesize>() .unwrap() .synthesize(engine, styles) .ok(); - target = &slot; + elem = &slot; } // Lazily computes the total number of recipes in the style chain. We need // it to determine whether a particular show rule was already applied to the - // `target` previously. For this purpose, show rules are indexed from the + // `elem` previously. For this purpose, show rules are indexed from the // top of the chain as the chain might grow to the bottom. let depth = LazyCell::new(|| styles.recipes().count()); @@ -462,7 +460,7 @@ fn verdict<'a>( // We're not interested in recipes that don't match. if !recipe .selector() - .is_some_and(|selector| selector.matches(target, Some(styles))) + .is_some_and(|selector| selector.matches(elem, Some(styles))) { continue; } @@ -480,9 +478,9 @@ fn verdict<'a>( continue; } - // Check whether this show rule was already applied to the target. + // Check whether this show rule was already applied to the element. let index = RecipeIndex(*depth - r); - if target.is_guarded(index) { + if elem.is_guarded(index) { continue; } @@ -498,19 +496,22 @@ fn verdict<'a>( } // If we found no user-defined rule, also consider the built-in show rule. - if step.is_none() && target.can::<dyn Show>() { - step = Some(ShowStep::Builtin); + if step.is_none() { + let target = styles.get(TargetElem::target); + if let Some(rule) = engine.routines.rules.get(target, elem) { + step = Some(ShowStep::Builtin(rule)); + } } // If there's no nothing to do, there is also no verdict. if step.is_none() && map.is_empty() && (prepared || { - target.label().is_none() - && target.location().is_none() - && !target.can::<dyn ShowSet>() - && !target.can::<dyn Locatable>() - && !target.can::<dyn Synthesize>() + elem.label().is_none() + && elem.location().is_none() + && !elem.can::<dyn ShowSet>() + && !elem.can::<dyn Locatable>() + && !elem.can::<dyn Synthesize>() }) { return None; @@ -523,7 +524,7 @@ fn verdict<'a>( fn prepare( engine: &mut Engine, locator: &mut SplitLocator, - target: &mut Content, + elem: &mut Content, map: &mut Styles, styles: StyleChain, ) -> SourceResult<Option<(Tag, Tag)>> { @@ -533,43 +534,43 @@ fn prepare( // // The element could already have a location even if it is not prepared // when it stems from a query. - let key = typst_utils::hash128(&target); - if target.location().is_none() - && (target.can::<dyn Locatable>() || target.label().is_some()) + let key = typst_utils::hash128(&elem); + if elem.location().is_none() + && (elem.can::<dyn Locatable>() || elem.label().is_some()) { let loc = locator.next_location(engine.introspector, key); - target.set_location(loc); + elem.set_location(loc); } // Apply built-in show-set rules. User-defined show-set rules are already // considered in the map built while determining the verdict. - if let Some(show_settable) = target.with::<dyn ShowSet>() { + if let Some(show_settable) = elem.with::<dyn ShowSet>() { map.apply(show_settable.show_set(styles)); } // If necessary, generated "synthesized" fields (which are derived from // other fields or queries). Do this after show-set so that show-set styles // are respected. - if let Some(synthesizable) = target.with_mut::<dyn Synthesize>() { + if let Some(synthesizable) = elem.with_mut::<dyn Synthesize>() { synthesizable.synthesize(engine, styles.chain(map))?; } // Copy style chain fields into the element itself, so that they are // available in rules. - target.materialize(styles.chain(map)); + elem.materialize(styles.chain(map)); // If the element is locatable, create start and end tags to be able to find // the element in the frames after layout. Do this after synthesis and // materialization, so that it includes the synthesized fields. Do it before // marking as prepared so that show-set rules will apply to this element // when queried. - let tags = target + let tags = elem .location() - .map(|loc| (Tag::Start(target.clone()), Tag::End(loc, key))); + .map(|loc| (Tag::Start(elem.clone()), Tag::End(loc, key))); // Ensure that this preparation only runs once by marking the element as // prepared. - target.mark_prepared(); + elem.mark_prepared(); Ok(tags) } |
