diff --git a/crates/typst/src/model/introspect.rs b/crates/typst/src/model/introspect.rs index 33722706a..439e316d4 100644 --- a/crates/typst/src/model/introspect.rs +++ b/crates/typst/src/model/introspect.rs @@ -1,97 +1,19 @@ use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; -use std::fmt::Debug; use std::hash::Hash; use std::num::NonZeroUsize; use comemo::{Prehashed, Track, Tracked, Validate}; -use ecow::{eco_format, EcoString, EcoVec}; +use ecow::{eco_format, EcoVec}; use indexmap::IndexMap; use crate::diag::{bail, StrResult}; use crate::doc::{Frame, FrameItem, Meta, Position}; -use crate::eval::{cast, func, scope, ty, Dict, Repr, Value, Vm}; +use crate::eval::{Repr, Value}; use crate::geom::{Point, Transform}; -use crate::model::{Content, Label, Selector}; +use crate::model::{Content, Label, Location, Selector}; use crate::util::NonZeroExt; -/// Identifies an element in the document. -/// -/// A location uniquely identifies an element in the document and lets you -/// access its absolute position on the pages. You can retrieve the current -/// location with the [`locate`]($locate) function and the location of a queried -/// or shown element with the [`location()`]($content.location) method on -/// content. -#[ty(scope)] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct Location { - /// The hash of the element. - hash: u128, - /// An unique number among elements with the same hash. This is the reason - /// we need a `Locator` everywhere. - disambiguator: usize, - /// A synthetic location created from another one. This is used for example - /// in bibliography management to create individual linkable locations for - /// reference entries from the bibliography's location. - variant: usize, -} - -impl Location { - /// Produce a variant of this location. - pub fn variant(mut self, n: usize) -> Self { - self.variant = n; - self - } -} - -#[scope] -impl Location { - /// Return the page number for this location. - /// - /// Note that this does not return the value of the [page counter]($counter) - /// at this location, but the true page number (starting from one). - /// - /// If you want to know the value of the page counter, use - /// `{counter(page).at(loc)}` instead. - #[func] - pub fn page(self, vm: &mut Vm) -> NonZeroUsize { - vm.vt.introspector.page(self) - } - - /// Return a dictionary with the page number and the x, y position for this - /// location. The page number starts at one and the coordinates are measured - /// from the top-left of the page. - /// - /// If you only need the page number, use `page()` instead as it allows - /// Typst to skip unnecessary work. - #[func] - pub fn position(self, vm: &mut Vm) -> Dict { - vm.vt.introspector.position(self).into() - } - - /// Returns the page numbering pattern of the page at this location. This - /// can be used when displaying the page counter in order to obtain the - /// local numbering. This is useful if you are building custom indices or - /// outlines. - /// - /// If the page numbering is set to `none` at that location, this function - /// returns `none`. - #[func] - pub fn page_numbering(self, vm: &mut Vm) -> Value { - vm.vt.introspector.page_numbering(self) - } -} - -impl Repr for Location { - fn repr(&self) -> EcoString { - "..".into() - } -} - -cast! { - type Location, -} - /// Provides locations for elements in the document. /// /// A [`Location`] consists of an element's hash plus a disambiguator. Just the diff --git a/crates/typst/src/model/location.rs b/crates/typst/src/model/location.rs new file mode 100644 index 000000000..8303a5f0f --- /dev/null +++ b/crates/typst/src/model/location.rs @@ -0,0 +1,82 @@ +use std::num::NonZeroUsize; + +use ecow::EcoString; + +use crate::eval::{cast, func, scope, ty, Dict, Repr, Value, Vm}; + +/// Identifies an element in the document. +/// +/// A location uniquely identifies an element in the document and lets you +/// access its absolute position on the pages. You can retrieve the current +/// location with the [`locate`]($locate) function and the location of a queried +/// or shown element with the [`location()`]($content.location) method on +/// content. +#[ty(scope)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct Location { + /// The hash of the element. + pub hash: u128, + /// An unique number among elements with the same hash. This is the reason + /// we need a `Locator` everywhere. + pub disambiguator: usize, + /// A synthetic location created from another one. This is used for example + /// in bibliography management to create individual linkable locations for + /// reference entries from the bibliography's location. + pub variant: usize, +} + +impl Location { + /// Produce a variant of this location. + pub fn variant(mut self, n: usize) -> Self { + self.variant = n; + self + } +} + +#[scope] +impl Location { + /// Return the page number for this location. + /// + /// Note that this does not return the value of the [page counter]($counter) + /// at this location, but the true page number (starting from one). + /// + /// If you want to know the value of the page counter, use + /// `{counter(page).at(loc)}` instead. + #[func] + pub fn page(self, vm: &mut Vm) -> NonZeroUsize { + vm.vt.introspector.page(self) + } + + /// Return a dictionary with the page number and the x, y position for this + /// location. The page number starts at one and the coordinates are measured + /// from the top-left of the page. + /// + /// If you only need the page number, use `page()` instead as it allows + /// Typst to skip unnecessary work. + #[func] + pub fn position(self, vm: &mut Vm) -> Dict { + vm.vt.introspector.position(self).into() + } + + /// Returns the page numbering pattern of the page at this location. This + /// can be used when displaying the page counter in order to obtain the + /// local numbering. This is useful if you are building custom indices or + /// outlines. + /// + /// If the page numbering is set to `none` at that location, this function + /// returns `none`. + #[func] + pub fn page_numbering(self, vm: &mut Vm) -> Value { + vm.vt.introspector.page_numbering(self) + } +} + +impl Repr for Location { + fn repr(&self) -> EcoString { + "..".into() + } +} + +cast! { + type Location, +} diff --git a/crates/typst/src/model/mod.rs b/crates/typst/src/model/mod.rs index 89cb009c1..af5c846f4 100644 --- a/crates/typst/src/model/mod.rs +++ b/crates/typst/src/model/mod.rs @@ -5,6 +5,7 @@ mod content; mod element; mod introspect; mod label; +mod location; mod realize; mod selector; mod styles; @@ -18,8 +19,9 @@ pub use self::content::{fat, Content, MetaElem, PlainText}; pub use self::element::{ Construct, Element, ElementFields, LocalName, NativeElement, NativeElementData, Set, }; -pub use self::introspect::{Introspector, Location, Locator}; +pub use self::introspect::{Introspector, Locator}; pub use self::label::{Label, Unlabellable}; +pub use self::location::Location; pub use self::realize::{ applicable, realize, Behave, Behaviour, Finalize, Guard, Locatable, Show, Synthesize, };