diff options
Diffstat (limited to 'src/model/content.rs')
| -rw-r--r-- | src/model/content.rs | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/src/model/content.rs b/src/model/content.rs index 15ea33cb..210b8bde 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -11,6 +11,7 @@ use typst_macros::node; use super::{Args, Key, Property, Recipe, RecipeId, Style, StyleMap, Value, Vm}; use crate::diag::{SourceResult, StrResult}; +use crate::syntax::Span; use crate::util::ReadableTypeId; use crate::World; @@ -20,7 +21,7 @@ use crate::World; /// - anything written between square brackets in Typst /// - any constructor function #[derive(Clone, Hash)] -pub struct Content(Arc<dyn Bounds>, Vec<RecipeId>); +pub struct Content(Arc<dyn Bounds>, Vec<RecipeId>, Option<Span>); impl Content { /// Create empty content. @@ -41,6 +42,16 @@ impl Content { self.downcast::<SequenceNode>().map_or(false, |seq| seq.0.is_empty()) } + /// The node's span. + pub fn span(&self) -> Option<Span> { + self.2 + } + + /// The node's human-readable name. + pub fn name(&self) -> &'static str { + (*self.0).name() + } + /// The id of the contained node. pub fn id(&self) -> NodeId { (*self.0).id() @@ -105,7 +116,7 @@ impl Content { recipe: Recipe, ) -> SourceResult<Self> { if recipe.selector.is_none() { - recipe.transform.apply(world, recipe.span, || Value::Content(self)) + recipe.transform.apply(world, recipe.span, self) } else { Ok(self.styled_with_entry(Style::Recipe(recipe))) } @@ -139,6 +150,21 @@ impl Content { StyledNode { sub: self, map: styles }.pack() } + /// Attach a span to the content. + pub fn spanned(mut self, span: Span) -> Self { + if let Some(styled) = self.try_downcast_mut::<StyledNode>() { + styled.sub.2 = Some(span); + } else if let Some(styled) = self.downcast::<StyledNode>() { + self = StyledNode { + sub: styled.sub.clone().spanned(span), + map: styled.map.clone(), + } + .pack(); + } + self.2 = Some(span); + self + } + /// Disable a show rule recipe. pub fn guard(mut self, id: RecipeId) -> Self { self.1.push(id); @@ -252,7 +278,7 @@ pub trait Node: 'static { where Self: Debug + Hash + Sync + Send + Sized + 'static, { - Content(Arc::new(self), vec![]) + Content(Arc::new(self), vec![], None) } /// Construct a node from the arguments. @@ -277,6 +303,9 @@ pub trait Node: 'static { /// A unique identifier of the node type. fn id(&self) -> NodeId; + /// The node's name. + fn name(&self) -> &'static str; + /// Extract the pointer of the vtable of the trait object with the /// given type `id` if this node implements that trait. fn vtable(&self, id: TypeId) -> Option<*const ()>; |
