Remove Target enum

This commit is contained in:
Laurenz 2022-11-18 11:23:56 +01:00
parent ddb617390c
commit c3895cbd66
4 changed files with 39 additions and 39 deletions

View File

@ -33,7 +33,7 @@ use typst::frame::Frame;
use typst::geom::*; use typst::geom::*;
use typst::model::{ use typst::model::{
capability, Content, Node, SequenceNode, Show, StyleChain, StyleEntry, capability, Content, Node, SequenceNode, Show, StyleChain, StyleEntry,
StyleVecBuilder, StyledNode, Target, StyleVecBuilder, StyledNode,
}; };
use typst::World; use typst::World;
@ -312,8 +312,8 @@ impl<'a> Builder<'a> {
content: &'a Content, content: &'a Content,
styles: StyleChain<'a>, styles: StyleChain<'a>,
) -> SourceResult<()> { ) -> SourceResult<()> {
if let Some(text) = content.downcast::<TextNode>() { if content.is::<TextNode>() {
if let Some(realized) = styles.apply(self.world, Target::Text(&text.0))? { if let Some(realized) = styles.apply(self.world, content)? {
let stored = self.scratch.content.alloc(realized); let stored = self.scratch.content.alloc(realized);
return self.accept(stored, styles); return self.accept(stored, styles);
} }
@ -362,7 +362,7 @@ impl<'a> Builder<'a> {
} }
fn show(&mut self, content: &Content, styles: StyleChain<'a>) -> SourceResult<bool> { fn show(&mut self, content: &Content, styles: StyleChain<'a>) -> SourceResult<bool> {
let Some(realized) = styles.apply(self.world, Target::Node(content))? else { let Some(realized) = styles.apply(self.world, content)? else {
return Ok(false); return Ok(false);
}; };

View File

@ -10,7 +10,7 @@ pub mod structure;
pub mod text; pub mod text;
use typst::geom::{Align, Color, Dir, GenAlign}; 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; use self::layout::LayoutRoot;
@ -160,6 +160,8 @@ pub fn items() -> LangItems {
space: || text::SpaceNode.pack(), space: || text::SpaceNode.pack(),
linebreak: |justify| text::LinebreakNode { justify }.pack(), linebreak: |justify| text::LinebreakNode { justify }.pack(),
text: |text| text::TextNode(text).pack(), text: |text| text::TextNode(text).pack(),
text_id: NodeId::of::<text::TextNode>(),
text_str: |content| Some(&content.downcast::<text::TextNode>()?.0),
smart_quote: |double| text::SmartQuoteNode { double }.pack(), smart_quote: |double| text::SmartQuoteNode { double }.pack(),
parbreak: || text::ParbreakNode.pack(), parbreak: || text::ParbreakNode.pack(),
strong: |body| text::StrongNode(body).pack(), strong: |body| text::StrongNode(body).pack(),

View File

@ -5,7 +5,7 @@ use std::num::NonZeroUsize;
use comemo::Tracked; use comemo::Tracked;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use super::{Content, StyleChain}; use super::{Content, NodeId, StyleChain};
use crate::diag::SourceResult; use crate::diag::SourceResult;
use crate::frame::Frame; use crate::frame::Frame;
use crate::geom::{Abs, Dir}; use crate::geom::{Abs, Dir};
@ -54,6 +54,10 @@ pub struct LangItems {
pub linebreak: fn(justify: bool) -> Content, pub linebreak: fn(justify: bool) -> Content,
/// Plain text without markup. /// Plain text without markup.
pub text: fn(text: EcoString) -> Content, 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 `"`. /// A smart quote: `'` or `"`.
pub smart_quote: fn(double: bool) -> Content, pub smart_quote: fn(double: bool) -> Content,
/// A paragraph break. /// A paragraph break.

View File

@ -247,9 +247,7 @@ impl<'a> StyleChain<'a> {
} }
/// Whether the style chain has a matching recipe for the content. /// Whether the style chain has a matching recipe for the content.
pub fn applicable(self, content: &Content) -> bool { pub fn applicable(self, target: &Content) -> bool {
let target = Target::Node(content);
// Find out how many recipes there any and whether any of them match. // Find out how many recipes there any and whether any of them match.
let mut n = 0; let mut n = 0;
let mut any = true; let mut any = true;
@ -278,7 +276,7 @@ impl<'a> StyleChain<'a> {
pub fn apply( pub fn apply(
self, self,
world: Tracked<dyn World>, world: Tracked<dyn World>,
target: Target, target: &Content,
) -> SourceResult<Option<Content>> { ) -> SourceResult<Option<Content>> {
// Find out how many recipes there any and whether any of them match. // Find out how many recipes there any and whether any of them match.
let mut n = 0; let mut n = 0;
@ -306,16 +304,14 @@ impl<'a> StyleChain<'a> {
} }
} }
if let Target::Node(node) = target { if let Some(showable) = target.to::<dyn Show>() {
// Realize if there was no matching recipe. // Realize if there was no matching recipe.
if realized.is_none() { if realized.is_none() {
let sel = RecipeId::Base(node.id()); let sel = RecipeId::Base(target.id());
if self.guarded(sel) { if self.guarded(sel) {
guarded = true; guarded = true;
} else { } else {
let content = node let content = showable
.to::<dyn Show>()
.unwrap()
.unguard_parts(sel) .unguard_parts(sel)
.to::<dyn Show>() .to::<dyn Show>()
.unwrap() .unwrap()
@ -327,7 +323,7 @@ impl<'a> StyleChain<'a> {
// Finalize only if guarding didn't stop any recipe. // Finalize only if guarding didn't stop any recipe.
if !guarded { if !guarded {
if let Some(node) = node.to::<dyn Finalize>() { if let Some(node) = target.to::<dyn Finalize>() {
if let Some(content) = realized { if let Some(content) = realized {
realized = Some(node.finalize(world, self, content)?); realized = Some(node.finalize(world, self, content)?);
} }
@ -1006,7 +1002,7 @@ pub struct Recipe {
impl Recipe { impl Recipe {
/// Whether the recipe is applicable to the target. /// Whether the recipe is applicable to the target.
pub fn applicable(&self, target: Target) -> bool { pub fn applicable(&self, target: &Content) -> bool {
self.selector self.selector
.as_ref() .as_ref()
.map_or(false, |selector| selector.matches(target)) .map_or(false, |selector| selector.matches(target))
@ -1017,16 +1013,24 @@ impl Recipe {
&self, &self,
world: Tracked<dyn World>, world: Tracked<dyn World>,
sel: RecipeId, sel: RecipeId,
target: Target, target: &Content,
) -> SourceResult<Option<Content>> { ) -> SourceResult<Option<Content>> {
let content = match (target, &self.selector) { let content = match &self.selector {
(Target::Node(node), Some(Selector::Node(id, _))) if node.id() == *id => { Some(Selector::Node(id, _)) => {
if target.id() != *id {
return Ok(None);
}
self.transform.apply(world, self.span, || { self.transform.apply(world, self.span, || {
Value::Content(node.to::<dyn Show>().unwrap().unguard_parts(sel)) Value::Content(target.to::<dyn Show>().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 make = world.config().items.text;
let mut result = vec![]; let mut result = vec![];
let mut cursor = 0; let mut cursor = 0;
@ -1055,7 +1059,7 @@ impl Recipe {
Content::sequence(result) Content::sequence(result)
} }
_ => return Ok(None), None => return Ok(None),
}; };
Ok(Some(content.styled_with_entry(StyleEntry::Guard(sel)))) Ok(Some(content.styled_with_entry(StyleEntry::Guard(sel))))
@ -1095,17 +1099,16 @@ impl Selector {
} }
/// Whether the selector matches for the target. /// Whether the selector matches for the target.
pub fn matches(&self, target: Target) -> bool { pub fn matches(&self, target: &Content) -> bool {
match (self, target) { match self {
(Self::Node(id, dict), Target::Node(node)) => { Self::Node(id, dict) => {
*id == node.id() *id == target.id()
&& dict && dict
.iter() .iter()
.flat_map(|dict| 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, Self::Regex(_) => target.id() == item!(text_id),
_ => false,
} }
} }
} }
@ -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. /// Identifies a show rule recipe.
#[derive(Debug, Copy, Clone, PartialEq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Hash)]
pub enum RecipeId { pub enum RecipeId {