diff --git a/crates/typst-library/src/introspection/location.rs b/crates/typst-library/src/introspection/location.rs index 8f4caaec4..d789a32f1 100644 --- a/crates/typst-library/src/introspection/location.rs +++ b/crates/typst-library/src/introspection/location.rs @@ -108,6 +108,9 @@ impl Repr for Location { /// Makes this element as locatable through the introspector. pub trait Locatable {} +/// Makes this element as not locatable through the introspector. +pub trait Unlocatable {} + /// Marks this element as not being queryable even though it is locatable for /// internal reasons. pub trait Unqueriable {} diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs index c2efe210b..71f2e784b 100644 --- a/crates/typst-library/src/text/mod.rs +++ b/crates/typst-library/src/text/mod.rs @@ -50,6 +50,7 @@ use crate::foundations::{ NativeElement, Never, NoneValue, Packed, PlainText, Regex, Repr, Resolve, Scope, Set, Smart, StyleChain, }; +use crate::introspection::Unlocatable; use crate::layout::{Abs, Axis, Dir, Em, Length, Ratio, Rel}; use crate::math::{EquationElem, MathSize}; use crate::visualize::{Color, Paint, RelativeTo, Stroke}; @@ -90,7 +91,7 @@ pub(super) fn define(global: &mut Scope) { /// With a function call. /// ]) /// ``` -#[elem(Debug, Construct, PlainText, Repr)] +#[elem(Debug, Construct, PlainText, Repr, Unlocatable)] pub struct TextElem { /// A font family descriptor or priority list of font family descriptors. /// @@ -792,6 +793,8 @@ impl PlainText for Packed { } } +impl Unlocatable for Packed {} + /// A lowercased font family like "arial". #[derive(Debug, Clone, PartialEq, Hash)] pub struct FontFamily { diff --git a/crates/typst-library/src/text/smartquote.rs b/crates/typst-library/src/text/smartquote.rs index 375b1cf09..4cfe0fac5 100644 --- a/crates/typst-library/src/text/smartquote.rs +++ b/crates/typst-library/src/text/smartquote.rs @@ -7,9 +7,12 @@ use crate::foundations::{ array, cast, dict, elem, Array, Dict, FromValue, Packed, PlainText, Smart, Str, StyleChain, }; +use crate::introspection::Unlocatable; use crate::layout::Dir; use crate::text::{Lang, Region, TextElem}; +impl Unlocatable for Packed {} + /// A language-aware quote that reacts to its context. /// /// Automatically turns into an appropriate opening or closing quote based on @@ -29,7 +32,7 @@ use crate::text::{Lang, Region, TextElem}; /// # Syntax /// This function also has dedicated syntax: The normal quote characters /// (`'` and `"`). Typst automatically makes your quotes smart. -#[elem(name = "smartquote", PlainText)] +#[elem(name = "smartquote", PlainText, Unlocatable)] pub struct SmartQuoteElem { /// Whether this should be a double quote. #[default(true)] diff --git a/crates/typst-library/src/text/space.rs b/crates/typst-library/src/text/space.rs index 38a554823..011de9716 100644 --- a/crates/typst-library/src/text/space.rs +++ b/crates/typst-library/src/text/space.rs @@ -4,9 +4,10 @@ use typst_utils::singleton; use crate::foundations::{ elem, Content, NativeElement, Packed, PlainText, Repr, Unlabellable, }; +use crate::introspection::Unlocatable; /// A text space. -#[elem(Unlabellable, PlainText, Repr)] +#[elem(Unlabellable, PlainText, Repr, Unlocatable)] pub struct SpaceElem {} impl SpaceElem { @@ -24,6 +25,8 @@ impl Repr for SpaceElem { impl Unlabellable for Packed {} +impl Unlocatable for Packed {} + impl PlainText for Packed { fn plain_text(&self, text: &mut EcoString) { text.push(' '); diff --git a/crates/typst-realize/src/lib.rs b/crates/typst-realize/src/lib.rs index f3f071505..b7a21e789 100644 --- a/crates/typst-realize/src/lib.rs +++ b/crates/typst-realize/src/lib.rs @@ -18,7 +18,7 @@ use typst_library::foundations::{ RecipeIndex, Selector, SequenceElem, ShowSet, Style, StyleChain, StyledElem, Styles, SymbolElem, Synthesize, TargetElem, Transformation, }; -use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem}; +use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem, Unlocatable}; use typst_library::layout::{ AlignElem, BoxElem, HElem, InlineElem, PageElem, PagebreakElem, VElem, }; @@ -506,7 +506,7 @@ fn verdict<'a>( elem.label().is_none() && elem.location().is_none() && !elem.can::() - && !elem.can::() + && !locatable(elem) && !elem.can::() }) { @@ -516,6 +516,10 @@ fn verdict<'a>( Some(Verdict { prepared, map, step }) } +fn locatable(elem: &Content) -> bool { + !elem.can::() +} + /// This is only executed the first time an element is visited. fn prepare( engine: &mut Engine, @@ -531,9 +535,7 @@ 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(&elem); - if elem.location().is_none() - && (elem.can::() || elem.label().is_some()) - { + if elem.location().is_none() && (locatable(elem) || elem.label().is_some()) { let loc = locator.next_location(engine.introspector, key); elem.set_location(loc); }