From c3895cbd66688c8d677d5795813432b9a72b3ef9 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 18 Nov 2022 11:23:56 +0100 Subject: [PATCH] Remove `Target` enum --- library/src/layout/mod.rs | 8 +++--- library/src/lib.rs | 4 ++- src/model/items.rs | 6 +++- src/model/styles.rs | 60 ++++++++++++++++++--------------------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index 605da3b2c..5812115aa 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -33,7 +33,7 @@ use typst::frame::Frame; use typst::geom::*; use typst::model::{ capability, Content, Node, SequenceNode, Show, StyleChain, StyleEntry, - StyleVecBuilder, StyledNode, Target, + StyleVecBuilder, StyledNode, }; use typst::World; @@ -312,8 +312,8 @@ impl<'a> Builder<'a> { content: &'a Content, styles: StyleChain<'a>, ) -> SourceResult<()> { - if let Some(text) = content.downcast::() { - if let Some(realized) = styles.apply(self.world, Target::Text(&text.0))? { + if content.is::() { + if let Some(realized) = styles.apply(self.world, content)? { let stored = self.scratch.content.alloc(realized); return self.accept(stored, styles); } @@ -362,7 +362,7 @@ impl<'a> Builder<'a> { } fn show(&mut self, content: &Content, styles: StyleChain<'a>) -> SourceResult { - let Some(realized) = styles.apply(self.world, Target::Node(content))? else { + let Some(realized) = styles.apply(self.world, content)? else { return Ok(false); }; diff --git a/library/src/lib.rs b/library/src/lib.rs index 6f77e0f33..ca10837fc 100644 --- a/library/src/lib.rs +++ b/library/src/lib.rs @@ -10,7 +10,7 @@ pub mod structure; pub mod text; use typst::geom::{Align, Color, Dir, GenAlign}; -use typst::model::{LangItems, Node, Scope, StyleMap}; +use typst::model::{LangItems, Node, NodeId, Scope, StyleMap}; use self::layout::LayoutRoot; @@ -160,6 +160,8 @@ pub fn items() -> LangItems { space: || text::SpaceNode.pack(), linebreak: |justify| text::LinebreakNode { justify }.pack(), text: |text| text::TextNode(text).pack(), + text_id: NodeId::of::(), + text_str: |content| Some(&content.downcast::()?.0), smart_quote: |double| text::SmartQuoteNode { double }.pack(), parbreak: || text::ParbreakNode.pack(), strong: |body| text::StrongNode(body).pack(), diff --git a/src/model/items.rs b/src/model/items.rs index 40f32fc42..a2c61933d 100644 --- a/src/model/items.rs +++ b/src/model/items.rs @@ -5,7 +5,7 @@ use std::num::NonZeroUsize; use comemo::Tracked; use once_cell::sync::OnceCell; -use super::{Content, StyleChain}; +use super::{Content, NodeId, StyleChain}; use crate::diag::SourceResult; use crate::frame::Frame; use crate::geom::{Abs, Dir}; @@ -54,6 +54,10 @@ pub struct LangItems { pub linebreak: fn(justify: bool) -> Content, /// Plain text without markup. pub text: fn(text: EcoString) -> Content, + /// The id of the text node. + pub text_id: NodeId, + /// Get the string if this is a text node. + pub text_str: fn(&Content) -> Option<&str>, /// A smart quote: `'` or `"`. pub smart_quote: fn(double: bool) -> Content, /// A paragraph break. diff --git a/src/model/styles.rs b/src/model/styles.rs index 98763c50d..7aa041c7a 100644 --- a/src/model/styles.rs +++ b/src/model/styles.rs @@ -247,9 +247,7 @@ impl<'a> StyleChain<'a> { } /// Whether the style chain has a matching recipe for the content. - pub fn applicable(self, content: &Content) -> bool { - let target = Target::Node(content); - + pub fn applicable(self, target: &Content) -> bool { // Find out how many recipes there any and whether any of them match. let mut n = 0; let mut any = true; @@ -278,7 +276,7 @@ impl<'a> StyleChain<'a> { pub fn apply( self, world: Tracked, - target: Target, + target: &Content, ) -> SourceResult> { // Find out how many recipes there any and whether any of them match. let mut n = 0; @@ -306,16 +304,14 @@ impl<'a> StyleChain<'a> { } } - if let Target::Node(node) = target { + if let Some(showable) = target.to::() { // Realize if there was no matching recipe. if realized.is_none() { - let sel = RecipeId::Base(node.id()); + let sel = RecipeId::Base(target.id()); if self.guarded(sel) { guarded = true; } else { - let content = node - .to::() - .unwrap() + let content = showable .unguard_parts(sel) .to::() .unwrap() @@ -327,7 +323,7 @@ impl<'a> StyleChain<'a> { // Finalize only if guarding didn't stop any recipe. if !guarded { - if let Some(node) = node.to::() { + if let Some(node) = target.to::() { if let Some(content) = realized { realized = Some(node.finalize(world, self, content)?); } @@ -1006,7 +1002,7 @@ pub struct Recipe { impl Recipe { /// Whether the recipe is applicable to the target. - pub fn applicable(&self, target: Target) -> bool { + pub fn applicable(&self, target: &Content) -> bool { self.selector .as_ref() .map_or(false, |selector| selector.matches(target)) @@ -1017,16 +1013,24 @@ impl Recipe { &self, world: Tracked, sel: RecipeId, - target: Target, + target: &Content, ) -> SourceResult> { - let content = match (target, &self.selector) { - (Target::Node(node), Some(Selector::Node(id, _))) if node.id() == *id => { + let content = match &self.selector { + Some(Selector::Node(id, _)) => { + if target.id() != *id { + return Ok(None); + } + self.transform.apply(world, self.span, || { - Value::Content(node.to::().unwrap().unguard_parts(sel)) + Value::Content(target.to::().unwrap().unguard_parts(sel)) })? } - (Target::Text(text), Some(Selector::Regex(regex))) => { + Some(Selector::Regex(regex)) => { + let Some(text) = item!(text_str)(target) else { + return Ok(None); + }; + let make = world.config().items.text; let mut result = vec![]; let mut cursor = 0; @@ -1055,7 +1059,7 @@ impl Recipe { Content::sequence(result) } - _ => return Ok(None), + None => return Ok(None), }; Ok(Some(content.styled_with_entry(StyleEntry::Guard(sel)))) @@ -1095,17 +1099,16 @@ impl Selector { } /// Whether the selector matches for the target. - pub fn matches(&self, target: Target) -> bool { - match (self, target) { - (Self::Node(id, dict), Target::Node(node)) => { - *id == node.id() + pub fn matches(&self, target: &Content) -> bool { + match self { + Self::Node(id, dict) => { + *id == target.id() && dict .iter() .flat_map(|dict| dict.iter()) - .all(|(name, value)| node.field(name).as_ref() == Some(value)) + .all(|(name, value)| target.field(name).as_ref() == Some(value)) } - (Self::Regex(_), Target::Text(_)) => true, - _ => false, + Self::Regex(_) => target.id() == item!(text_id), } } } @@ -1140,15 +1143,6 @@ impl Transform { } } -/// A target for a show rule recipe. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum Target<'a> { - /// A showable node. - Node(&'a Content), - /// A slice of text. - Text(&'a str), -} - /// Identifies a show rule recipe. #[derive(Debug, Copy, Clone, PartialEq, Hash)] pub enum RecipeId {