summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/meta
diff options
context:
space:
mode:
Diffstat (limited to 'crates/typst-library/src/meta')
-rw-r--r--crates/typst-library/src/meta/bibliography.rs66
-rw-r--r--crates/typst-library/src/meta/cite.rs2
-rw-r--r--crates/typst-library/src/meta/context.rs2
-rw-r--r--crates/typst-library/src/meta/counter.rs18
-rw-r--r--crates/typst-library/src/meta/document.rs10
-rw-r--r--crates/typst-library/src/meta/figure.rs78
-rw-r--r--crates/typst-library/src/meta/footnote.rs22
-rw-r--r--crates/typst-library/src/meta/heading.rs26
-rw-r--r--crates/typst-library/src/meta/link.rs8
-rw-r--r--crates/typst-library/src/meta/mod.rs18
-rw-r--r--crates/typst-library/src/meta/outline.rs35
-rw-r--r--crates/typst-library/src/meta/reference.rs26
-rw-r--r--crates/typst-library/src/meta/state.rs6
13 files changed, 157 insertions, 160 deletions
diff --git a/crates/typst-library/src/meta/bibliography.rs b/crates/typst-library/src/meta/bibliography.rs
index d429d343..342135ec 100644
--- a/crates/typst-library/src/meta/bibliography.rs
+++ b/crates/typst-library/src/meta/bibliography.rs
@@ -19,13 +19,13 @@ use typed_arena::Arena;
use typst::diag::FileError;
use typst::eval::{eval_string, Bytes, CastInfo, EvalMode, Reflect};
use typst::font::FontStyle;
-use typst::util::option_eq;
+use typst::util::{option_eq, PicoStr};
use super::{CitationForm, CiteGroup, LocalName};
use crate::layout::{
BlockElem, GridElem, HElem, PadElem, ParElem, Sizing, TrackSizings, VElem,
};
-use crate::meta::{FootnoteElem, HeadingElem};
+use crate::meta::{FootnoteElem, HeadingElem, LocalNameIn};
use crate::prelude::*;
use crate::text::{Delta, SubElem, SuperElem, TextElem};
@@ -130,7 +130,7 @@ pub struct BibliographyElem {
}
/// A list of bibliography file paths.
-#[derive(Debug, Default, Clone, Hash)]
+#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct BibPaths(Vec<EcoString>);
cast! {
@@ -153,11 +153,12 @@ impl BibliographyElem {
bail!("multiple bibliographies are not yet supported");
}
- Ok(elem.to::<Self>().unwrap().clone())
+ Ok(elem.to::<Self>().cloned().unwrap())
}
/// Whether the bibliography contains the given key.
- pub fn has(vt: &Vt, key: &str) -> bool {
+ pub fn has(vt: &Vt, key: impl Into<PicoStr>) -> bool {
+ let key = key.into();
vt.introspector
.query(&Self::elem().select())
.iter()
@@ -199,14 +200,9 @@ impl Show for BibliographyElem {
let mut seq = vec![];
if let Some(title) = self.title(styles) {
- let title =
- title.unwrap_or_else(|| {
- TextElem::packed(self.local_name(
- TextElem::lang_in(styles),
- TextElem::region_in(styles),
- ))
- .spanned(self.span())
- });
+ let title = title.unwrap_or_else(|| {
+ TextElem::packed(Self::local_name_in(styles)).spanned(self.span())
+ });
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
}
@@ -220,7 +216,7 @@ impl Show for BibliographyElem {
.ok_or("CSL style is not suitable for bibliographies")
.at(span)?;
- let row_gutter = BlockElem::below_in(styles).amount();
+ let row_gutter = *BlockElem::below_in(styles).amount();
if references.iter().any(|(prefix, _)| prefix.is_some()) {
let mut cells = vec![];
for (prefix, reference) in references {
@@ -231,9 +227,9 @@ impl Show for BibliographyElem {
seq.push(VElem::new(row_gutter).with_weakness(3).pack());
seq.push(
GridElem::new(cells)
- .with_columns(TrackSizings(vec![Sizing::Auto; 2]))
- .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()]))
- .with_row_gutter(TrackSizings(vec![row_gutter.into()]))
+ .with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
+ .with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
+ .with_row_gutter(TrackSizings(smallvec![(row_gutter).into()]))
.pack(),
);
} else {
@@ -263,7 +259,7 @@ impl Finalize for BibliographyElem {
}
impl LocalName for BibliographyElem {
- fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str {
+ fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
match lang {
Lang::ALBANIAN => "Bibliografi",
Lang::ARABIC => "المراجع",
@@ -300,7 +296,7 @@ impl LocalName for BibliographyElem {
#[ty]
#[derive(Debug, Clone, PartialEq)]
pub struct Bibliography {
- map: Arc<IndexMap<EcoString, hayagriva::Entry>>,
+ map: Arc<IndexMap<PicoStr, hayagriva::Entry>>,
hash: u128,
}
@@ -371,8 +367,8 @@ impl Bibliography {
})
}
- fn has(&self, key: &str) -> bool {
- self.map.contains_key(key)
+ fn has(&self, key: impl Into<PicoStr>) -> bool {
+ self.map.contains_key(&key.into())
}
fn entries(&self) -> impl Iterator<Item = &hayagriva::Entry> {
@@ -645,7 +641,7 @@ impl<'a> Generator<'a> {
let mut driver = BibliographyDriver::new();
for elem in &self.groups {
let group = elem.to::<CiteGroup>().unwrap();
- let location = group.0.location().unwrap();
+ let location = group.location().unwrap();
let children = group.children();
// Groups should never be empty.
@@ -657,12 +653,13 @@ impl<'a> Generator<'a> {
let mut normal = true;
// Create infos and items for each child in the group.
- for child in &children {
- let key = child.key();
- let Some(entry) = database.map.get(&key.0) else {
+ for child in children {
+ let key = *child.key();
+ let Some(entry) = database.map.get(&key.into_inner()) else {
errors.push(error!(
child.span(),
- "key `{}` does not exist in the bibliography", key.0
+ "key `{}` does not exist in the bibliography",
+ key.as_str()
));
continue;
};
@@ -714,13 +711,13 @@ impl<'a> Generator<'a> {
driver.citation(CitationRequest::new(
items,
style,
- Some(locale(first.lang(), first.region())),
+ Some(locale(*first.lang(), *first.region())),
&LOCALES,
None,
));
}
- let locale = locale(self.bibliography.lang(), self.bibliography.region());
+ let locale = locale(*self.bibliography.lang(), *self.bibliography.region());
// Add hidden items for everything if we should print the whole
// bibliography.
@@ -761,7 +758,7 @@ impl<'a> Generator<'a> {
// so that we can link there.
let mut links = HashMap::new();
if let Some(bibliography) = &rendered.bibliography {
- let location = self.bibliography.0.location().unwrap();
+ let location = self.bibliography.location().unwrap();
for (k, item) in bibliography.items.iter().enumerate() {
links.insert(item.key.as_str(), location.variant(k + 1));
}
@@ -770,8 +767,7 @@ impl<'a> Generator<'a> {
let mut output = std::mem::take(&mut self.failures);
for (info, citation) in self.infos.iter().zip(&rendered.citations) {
let supplement = |i: usize| info.subinfos.get(i)?.supplement.clone();
- let link =
- |i: usize| links.get(info.subinfos.get(i)?.key.0.as_str()).copied();
+ let link = |i: usize| links.get(info.subinfos.get(i)?.key.as_str()).copied();
let renderer = ElemRenderer {
world: self.world,
@@ -811,13 +807,13 @@ impl<'a> Generator<'a> {
let mut first_occurances = HashMap::new();
for info in &self.infos {
for subinfo in &info.subinfos {
- let key = subinfo.key.0.as_str();
+ let key = subinfo.key.as_str();
first_occurances.entry(key).or_insert(info.location);
}
}
// The location of the bibliography.
- let location = self.bibliography.0.location().unwrap();
+ let location = self.bibliography.location().unwrap();
let mut output = vec![];
for (k, item) in rendered.items.iter().enumerate() {
@@ -918,8 +914,8 @@ impl ElemRenderer<'_> {
if let Some(prefix) = suf_prefix {
const COLUMN_GUTTER: Em = Em::new(0.65);
content = GridElem::new(vec![prefix, content])
- .with_columns(TrackSizings(vec![Sizing::Auto; 2]))
- .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()]))
+ .with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
+ .with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
.pack();
}
diff --git a/crates/typst-library/src/meta/cite.rs b/crates/typst-library/src/meta/cite.rs
index 2e3c4155..a61523d8 100644
--- a/crates/typst-library/src/meta/cite.rs
+++ b/crates/typst-library/src/meta/cite.rs
@@ -141,7 +141,7 @@ impl Show for CiteGroup {
#[tracing::instrument(name = "CiteGroup::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(vt.delayed(|vt| {
- let location = self.0.location().unwrap();
+ let location = self.location().unwrap();
let span = self.span();
Works::generate(vt.world, vt.introspector)
.at(span)?
diff --git a/crates/typst-library/src/meta/context.rs b/crates/typst-library/src/meta/context.rs
index 3a82a925..59b35577 100644
--- a/crates/typst-library/src/meta/context.rs
+++ b/crates/typst-library/src/meta/context.rs
@@ -37,7 +37,7 @@ impl Show for LocateElem {
#[tracing::instrument(name = "LocateElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(vt.delayed(|vt| {
- let location = self.0.location().unwrap();
+ let location = self.location().unwrap();
Ok(self.func().call_vt(vt, [location])?.display())
}))
}
diff --git a/crates/typst-library/src/meta/counter.rs b/crates/typst-library/src/meta/counter.rs
index 1ad0bff1..45041a38 100644
--- a/crates/typst-library/src/meta/counter.rs
+++ b/crates/typst-library/src/meta/counter.rs
@@ -284,9 +284,9 @@ impl Counter {
}
if let Some(update) = match elem.to::<UpdateElem>() {
- Some(elem) => Some(elem.update()),
+ Some(elem) => Some(elem.update().clone()),
None => match elem.with::<dyn Count>() {
- Some(countable) => countable.update(),
+ Some(countable) => countable.update().clone(),
None => Some(CounterUpdate::Step(NonZeroUsize::ONE)),
},
} {
@@ -301,8 +301,7 @@ impl Counter {
/// The selector relevant for this counter's updates.
fn selector(&self) -> Selector {
- let mut selector =
- Selector::Elem(UpdateElem::elem(), Some(dict! { "key" => self.0.clone() }));
+ let mut selector = select_where!(UpdateElem, Key => self.0.clone());
if let CounterKey::Selector(key) = &self.0 {
selector = Selector::Or(eco_vec![selector, key.clone()]);
@@ -613,17 +612,18 @@ impl Show for DisplayElem {
#[tracing::instrument(name = "DisplayElem::show", skip_all)]
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
Ok(vt.delayed(|vt| {
- let location = self.0.location().unwrap();
+ let location = self.location().unwrap();
let counter = self.counter();
let numbering = self
.numbering()
+ .clone()
.or_else(|| {
let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else {
return None;
};
if func == HeadingElem::elem() {
- HeadingElem::numbering_in(styles)
+ HeadingElem::numbering_in(styles).clone()
} else if func == FigureElem::elem() {
FigureElem::numbering_in(styles)
} else if func == EquationElem::elem() {
@@ -634,7 +634,7 @@ impl Show for DisplayElem {
})
.unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into());
- let state = if self.both() {
+ let state = if *self.both() {
counter.both(vt, location)?
} else {
counter.at(vt, location)?
@@ -695,9 +695,9 @@ impl ManualPageCounter {
FrameItem::Group(group) => self.visit(vt, &group.frame)?,
FrameItem::Meta(Meta::Elem(elem), _) => {
let Some(elem) = elem.to::<UpdateElem>() else { continue };
- if elem.key() == CounterKey::Page {
+ if *elem.key() == CounterKey::Page {
let mut state = CounterState(smallvec![self.logical]);
- state.update(vt, elem.update())?;
+ state.update(vt, elem.update().clone())?;
self.logical = state.first();
}
}
diff --git a/crates/typst-library/src/meta/document.rs b/crates/typst-library/src/meta/document.rs
index 55c365ac..f6ff6812 100644
--- a/crates/typst-library/src/meta/document.rs
+++ b/crates/typst-library/src/meta/document.rs
@@ -1,3 +1,4 @@
+use comemo::Prehashed;
use typst::eval::Datetime;
use crate::layout::{LayoutRoot, PageElem};
@@ -43,9 +44,8 @@ pub struct DocumentElem {
pub date: Smart<Option<Datetime>>,
/// The page runs.
- #[internal]
#[variadic]
- pub children: Vec<Content>,
+ pub children: Vec<Prehashed<Content>>,
}
impl Construct for DocumentElem {
@@ -64,7 +64,7 @@ impl LayoutRoot for DocumentElem {
let mut page_counter = ManualPageCounter::new();
let children = self.children();
- let mut iter = children.iter().peekable();
+ let mut iter = children.iter().map(|c| &**c).peekable();
while let Some(mut child) = iter.next() {
let outer = styles;
@@ -99,7 +99,7 @@ impl LayoutRoot for DocumentElem {
}
/// A list of authors.
-#[derive(Debug, Default, Clone, Hash)]
+#[derive(Debug, Default, Clone, PartialEq, Hash)]
pub struct Author(Vec<EcoString>);
cast! {
@@ -110,7 +110,7 @@ cast! {
}
/// A list of keywords.
-#[derive(Debug, Default, Clone, Hash)]
+#[derive(Debug, Default, Clone, PartialEq, Hash)]
pub struct Keywords(Vec<EcoString>);
cast! {
diff --git a/crates/typst-library/src/meta/figure.rs b/crates/typst-library/src/meta/figure.rs
index 990c9860..bfcc9b44 100644
--- a/crates/typst-library/src/meta/figure.rs
+++ b/crates/typst-library/src/meta/figure.rs
@@ -1,9 +1,8 @@
+use std::borrow::Cow;
use std::str::FromStr;
use typst::util::option_eq;
-use super::{
- Count, Counter, CounterKey, CounterUpdate, LocalName, Numbering, NumberingPattern,
-};
+use super::{Count, Counter, CounterKey, CounterUpdate, Numbering, NumberingPattern};
use crate::layout::{BlockElem, PlaceElem, VElem};
use crate::meta::{Outlinable, Refable, Supplement};
use crate::prelude::*;
@@ -170,6 +169,7 @@ pub struct FigureElem {
/// kind: "foo",
/// )
/// ```
+ #[borrowed]
pub supplement: Smart<Option<Supplement>>,
/// How to number the figure. Accepts a
@@ -212,25 +212,21 @@ impl Synthesize for FigureElem {
let kind = self.kind(styles).unwrap_or_else(|| {
self.body()
.query_first(Selector::can::<dyn Figurable>())
- .cloned()
.map(|elem| FigureKind::Elem(elem.func()))
.unwrap_or_else(|| FigureKind::Elem(ImageElem::elem()))
});
// Resolve the supplement.
- let supplement = match self.supplement(styles) {
+ let supplement = match self.supplement(styles).as_ref() {
Smart::Auto => {
// Default to the local name for the kind, if available.
let name = match &kind {
- FigureKind::Elem(func) => {
- let empty = Content::new(*func);
- empty.with::<dyn LocalName>().map(|c| {
- TextElem::packed(c.local_name(
- TextElem::lang_in(styles),
- TextElem::region_in(styles),
- ))
- })
- }
+ FigureKind::Elem(func) => func
+ .local_name(
+ TextElem::lang_in(styles),
+ TextElem::region_in(styles),
+ )
+ .map(TextElem::packed),
FigureKind::Name(_) => None,
};
@@ -245,24 +241,21 @@ impl Synthesize for FigureElem {
// Resolve the supplement with the first descendant of the kind or
// just the body, if none was found.
let descendant = match kind {
- FigureKind::Elem(func) => {
- self.body().query_first(Selector::Elem(func, None)).cloned()
- }
+ FigureKind::Elem(func) => self
+ .body()
+ .query_first(Selector::Elem(func, None))
+ .map(Cow::Owned),
FigureKind::Name(_) => None,
};
- let target = descendant.unwrap_or_else(|| self.body());
+ let target = descendant.unwrap_or_else(|| Cow::Borrowed(self.body()));
Some(supplement.resolve(vt, [target])?)
}
};
// Construct the figure's counter.
- let counter = Counter::new(CounterKey::Selector(Selector::Elem(
- Self::elem(),
- Some(dict! {
- "kind" => kind.clone(),
- }),
- )));
+ let counter =
+ Counter::new(CounterKey::Selector(select_where!(Self, Kind => kind.clone())));
// Fill the figure's caption.
let mut caption = self.caption(styles);
@@ -271,7 +264,7 @@ impl Synthesize for FigureElem {
caption.push_supplement(supplement.clone());
caption.push_numbering(numbering.clone());
caption.push_counter(Some(counter.clone()));
- caption.push_location(self.0.location());
+ caption.push_figure_location(self.location());
}
self.push_placement(self.placement(styles));
@@ -289,7 +282,7 @@ impl Synthesize for FigureElem {
impl Show for FigureElem {
#[tracing::instrument(name = "FigureElem::show", skip_all)]
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut realized = self.body();
+ let mut realized = self.body().clone();
// Build the caption, if any.
if let Some(caption) = self.caption(styles) {
@@ -339,14 +332,15 @@ impl Count for FigureElem {
impl Refable for FigureElem {
fn supplement(&self) -> Content {
// After synthesis, this should always be custom content.
- match self.supplement(StyleChain::default()) {
- Smart::Custom(Some(Supplement::Content(content))) => content,
+ let default = StyleChain::default();
+ match self.supplement(default).as_ref() {
+ Smart::Custom(Some(Supplement::Content(content))) => content.clone(),
_ => Content::empty(),
}
}
fn counter(&self) -> Counter {
- self.counter().unwrap_or_else(|| Counter::of(Self::elem()))
+ self.counter().clone().unwrap_or_else(|| Counter::of(Self::elem()))
}
fn numbering(&self) -> Option<Numbering> {
@@ -364,17 +358,17 @@ impl Outlinable for FigureElem {
return Ok(None);
};
- let mut realized = caption.body();
+ let mut realized = caption.body().clone();
if let (
Smart::Custom(Some(Supplement::Content(mut supplement))),
Some(counter),
Some(numbering),
) = (
- self.supplement(StyleChain::default()),
+ self.supplement(StyleChain::default()).clone(),
self.counter(),
self.numbering(StyleChain::default()),
) {
- let location = self.0.location().unwrap();
+ let location = self.location().unwrap();
let numbers = counter.at(vt, location)?.display(vt, &numbering)?;
if !supplement.is_empty() {
@@ -497,8 +491,9 @@ pub struct FigureCaption {
pub counter: Option<Counter>,
/// The figure's location.
+ #[internal]
#[synthesized]
- pub location: Option<Location>,
+ pub figure_location: Option<Location>,
}
impl FigureCaption {
@@ -542,12 +537,15 @@ impl Synthesize for FigureCaption {
impl Show for FigureCaption {
#[tracing::instrument(name = "FigureCaption::show", skip_all)]
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut realized = self.body();
+ let mut realized = self.body().clone();
- if let (Some(mut supplement), Some(numbering), Some(counter), Some(location)) =
- (self.supplement(), self.numbering(), self.counter(), self.location())
- {
- let numbers = counter.at(vt, location)?.display(vt, &numbering)?;
+ if let (Some(mut supplement), Some(numbering), Some(counter), Some(location)) = (
+ self.supplement().clone(),
+ self.numbering(),
+ self.counter(),
+ self.figure_location(),
+ ) {
+ let numbers = counter.at(vt, *location)?.display(vt, numbering)?;
if !supplement.is_empty() {
supplement += TextElem::packed('\u{a0}');
}
@@ -564,7 +562,7 @@ cast! {
}
/// The `kind` parameter of a [`FigureElem`].
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Hash)]
pub enum FigureKind {
/// The kind is an element function.
Elem(Element),
@@ -585,4 +583,4 @@ cast! {
/// An element that can be auto-detected in a figure.
///
/// This trait is used to determine the type of a figure.
-pub trait Figurable: LocalName {}
+pub trait Figurable {}
diff --git a/crates/typst-library/src/meta/footnote.rs b/crates/typst-library/src/meta/footnote.rs
index a8f0b4dd..4306f833 100644
--- a/crates/typst-library/src/meta/footnote.rs
+++ b/crates/typst-library/src/meta/footnote.rs
@@ -59,6 +59,7 @@ pub struct FootnoteElem {
/// #footnote[Star],
/// #footnote[Dagger]
/// ```
+ #[borrowed]
#[default(Numbering::Pattern(NumberingPattern::from_str("1").unwrap()))]
pub numbering: Numbering,
@@ -91,7 +92,7 @@ impl FootnoteElem {
}
/// Returns the content of the body of this footnote if it is not a ref.
- pub fn body_content(&self) -> Option<Content> {
+ pub fn body_content(&self) -> Option<&Content> {
match self.body() {
FootnoteBody::Content(content) => Some(content),
_ => None,
@@ -102,20 +103,20 @@ impl FootnoteElem {
pub fn declaration_location(&self, vt: &Vt) -> StrResult<Location> {
match self.body() {
FootnoteBody::Reference(label) => {
- let element: Prehashed<Content> = vt.introspector.query_label(&label)?;
+ let element: Prehashed<Content> = vt.introspector.query_label(*label)?;
let footnote = element
.to::<FootnoteElem>()
.ok_or("referenced element should be a footnote")?;
footnote.declaration_location(vt)
}
- _ => Ok(self.0.location().unwrap()),
+ _ => Ok(self.location().unwrap()),
}
}
}
impl Synthesize for FootnoteElem {
fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
- self.push_numbering(self.numbering(styles));
+ self.push_numbering(self.numbering(styles).clone());
Ok(())
}
}
@@ -127,7 +128,7 @@ impl Show for FootnoteElem {
let loc = self.declaration_location(vt).at(self.span())?;
let numbering = self.numbering(styles);
let counter = Counter::of(Self::elem());
- let num = counter.at(vt, loc)?.display(vt, &numbering)?;
+ let num = counter.at(vt, loc)?.display(vt, numbering)?;
let sup = SuperElem::new(num).pack();
let loc = loc.variant(1);
// Add zero-width weak spacing to make the footnote "sticky".
@@ -144,7 +145,7 @@ impl Count for FootnoteElem {
/// The body of a footnote can be either some content or a label referencing
/// another footnote.
-#[derive(Debug)]
+#[derive(Debug, Clone, PartialEq, Hash)]
pub enum FootnoteBody {
Content(Content),
Reference(Label),
@@ -266,10 +267,11 @@ impl Show for FootnoteEntry {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let note = self.note();
let number_gap = Em::new(0.05);
- let numbering = note.numbering(StyleChain::default());
+ let default = StyleChain::default();
+ let numbering = note.numbering(default);
let counter = Counter::of(FootnoteElem::elem());
- let loc = note.0.location().unwrap();
- let num = counter.at(vt, loc)?.display(vt, &numbering)?;
+ let loc = note.location().unwrap();
+ let num = counter.at(vt, loc)?.display(vt, numbering)?;
let sup = SuperElem::new(num)
.pack()
.linked(Destination::Location(loc))
@@ -278,7 +280,7 @@ impl Show for FootnoteEntry {
HElem::new(self.indent(styles).into()).pack(),
sup,
HElem::new(number_gap.into()).with_weak(true).pack(),
- note.body_content().unwrap(),
+ note.body_content().unwrap().clone(),
]))
}
}
diff --git a/crates/typst-library/src/meta/heading.rs b/crates/typst-library/src/meta/heading.rs
index 34af8238..1a2f4dd0 100644
--- a/crates/typst-library/src/meta/heading.rs
+++ b/crates/typst-library/src/meta/heading.rs
@@ -3,7 +3,7 @@ use typst::util::option_eq;
use super::{Counter, CounterUpdate, LocalName, Numbering, Outlinable, Refable};
use crate::layout::{BlockElem, HElem, VElem};
-use crate::meta::{Count, Supplement};
+use crate::meta::{Count, LocalNameIn, Supplement};
use crate::prelude::*;
use crate::text::{SpaceElem, TextElem, TextSize};
@@ -54,6 +54,7 @@ pub struct HeadingElem {
/// == A subsection
/// === A sub-subsection
/// ```
+ #[borrowed]
pub numbering: Option<Numbering>,
/// A supplement for the heading.
@@ -124,13 +125,13 @@ impl Synthesize for HeadingElem {
fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
// Resolve the supplement.
let supplement = match self.supplement(styles) {
- Smart::Auto => TextElem::packed(self.local_name_in(styles)),
+ Smart::Auto => TextElem::packed(Self::local_name_in(styles)),
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(supplement)) => supplement.resolve(vt, [self.clone()])?,
};
self.push_level(self.level(styles));
- self.push_numbering(self.numbering(styles));
+ self.push_numbering(self.numbering(styles).clone());
self.push_supplement(Smart::Custom(Some(Supplement::Content(supplement))));
self.push_outlined(self.outlined(styles));
self.push_bookmarked(self.bookmarked(styles));
@@ -142,10 +143,10 @@ impl Synthesize for HeadingElem {
impl Show for HeadingElem {
#[tracing::instrument(name = "HeadingElem::show", skip_all)]
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut realized = self.body();
- if let Some(numbering) = self.numbering(styles) {
+ let mut realized = self.body().clone();
+ if let Some(numbering) = self.numbering(styles).as_ref() {
realized = Counter::of(Self::elem())
- .display(Some(numbering), false)
+ .display(Some(numbering.clone()), false)
.spanned(self.span())
+ HElem::new(Em::new(0.3).into()).with_weak(true).pack()
+ realized;
@@ -204,7 +205,7 @@ impl Refable for HeadingElem {
}
fn numbering(&self) -> Option<Numbering> {
- self.numbering(StyleChain::default())
+ self.numbering(StyleChain::default()).clone()
}
}
@@ -214,11 +215,12 @@ impl Outlinable for HeadingElem {
return Ok(None);
}
- let mut content = self.body();
- if let Some(numbering) = self.numbering(StyleChain::default()) {
+ let mut content = self.body().clone();
+ let default = StyleChain::default();
+ if let Some(numbering) = self.numbering(default).as_ref() {
let numbers = Counter::of(Self::elem())
- .at(vt, self.0.location().unwrap())?
- .display(vt, &numbering)?;
+ .at(vt, self.location().unwrap())?
+ .display(vt, numbering)?;
content = numbers + SpaceElem::new().pack() + content;
};
@@ -231,7 +233,7 @@ impl Outlinable for HeadingElem {
}
impl LocalName for HeadingElem {
- fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str {
+ fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
match lang {
Lang::ALBANIAN => "Kapitull",
Lang::ARABIC => "الفصل",
diff --git a/crates/typst-library/src/meta/link.rs b/crates/typst-library/src/meta/link.rs
index 7b68b186..74857f1b 100644
--- a/crates/typst-library/src/meta/link.rs
+++ b/crates/typst-library/src/meta/link.rs
@@ -84,12 +84,12 @@ impl LinkElem {
impl Show for LinkElem {
#[tracing::instrument(name = "LinkElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- let body = self.body();
+ let body = self.body().clone();
let linked = match self.dest() {
- LinkTarget::Dest(dest) => body.linked(dest),
+ LinkTarget::Dest(dest) => body.linked(dest.clone()),
LinkTarget::Label(label) => vt
.delayed(|vt| {
- let elem = vt.introspector.query_label(&label).at(self.span())?;
+ let elem = vt.introspector.query_label(*label).at(self.span())?;
let dest = Destination::Location(elem.location().unwrap());
Ok(Some(body.clone().linked(dest)))
})
@@ -110,7 +110,7 @@ fn body_from_url(url: &EcoString) -> Content {
}
/// A target where a link can go.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Hash)]
pub enum LinkTarget {
Dest(Destination),
Label(Label),
diff --git a/crates/typst-library/src/meta/mod.rs b/crates/typst-library/src/meta/mod.rs
index 1019864f..ffe861ab 100644
--- a/crates/typst-library/src/meta/mod.rs
+++ b/crates/typst-library/src/meta/mod.rs
@@ -62,13 +62,15 @@ pub(super) fn define(global: &mut Scope) {
global.define_func::<query>();
}
-/// The named with which an element is referenced.
-pub trait LocalName {
- /// Get the name in the given language and (optionally) region.
- fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str;
-
- /// Resolve the local name with a style chain.
- fn local_name_in(&self, styles: StyleChain) -> &'static str {
- self.local_name(TextElem::lang_in(styles), TextElem::region_in(styles))
+/// An element that has a local name.
+pub trait LocalNameIn: LocalName {
+ /// Gets the local name from the style chain.
+ fn local_name_in(styles: StyleChain) -> &'static str
+ where
+ Self: Sized,
+ {
+ Self::local_name(TextElem::lang_in(styles), TextElem::region_in(styles))
}
}
+
+impl<T: LocalName> LocalNameIn for T {}
diff --git a/crates/typst-library/src/meta/outline.rs b/crates/typst-library/src/meta/outline.rs
index 9266ba2b..e7332ab3 100644
--- a/crates/typst-library/src/meta/outline.rs
+++ b/crates/typst-library/src/meta/outline.rs
@@ -6,6 +6,7 @@ use super::{
Counter, CounterKey, HeadingElem, LocalName, Numbering, NumberingPattern, Refable,
};
use crate::layout::{BoxElem, HElem, HideElem, ParbreakElem, RepeatElem, Spacing};
+use crate::meta::LocalNameIn;
use crate::prelude::*;
use crate::text::{LinebreakElem, SpaceElem, TextElem};
@@ -88,10 +89,8 @@ pub struct OutlineElem {
/// caption: [Experiment results],
/// )
/// ```
- #[default(LocatableSelector(Selector::Elem(
- HeadingElem::elem(),
- Some(dict! { "outlined" => true })
- )))]
+ #[default(LocatableSelector(select_where!(HeadingElem, Outlined => true)))]
+ #[borrowed]
pub target: LocatableSelector,
/// The maximum level up to which elements are included in the outline. When
@@ -161,6 +160,7 @@ pub struct OutlineElem {
/// #lorem(10)
/// ```
#[default(None)]
+ #[borrowed]
pub indent: Option<Smart<OutlineIndent>>,
/// Content to fill the space between the title and the page number. Can be
@@ -187,14 +187,9 @@ impl Show for OutlineElem {
let mut seq = vec![ParbreakElem::new().pack()];
// Build the outline title.
if let Some(title) = self.title(styles) {
- let title =
- title.unwrap_or_else(|| {
- TextElem::packed(self.local_name(
- TextElem::lang_in(styles),
- TextElem::region_in(styles),
- ))
- .spanned(self.span())
- });
+ let title = title.unwrap_or_else(|| {
+ TextElem::packed(Self::local_name_in(styles)).spanned(self.span())
+ });
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
}
@@ -217,7 +212,7 @@ impl Show for OutlineElem {
};
let level = entry.level();
- if depth < level {
+ if depth < *level {
continue;
}
@@ -226,12 +221,12 @@ impl Show for OutlineElem {
while ancestors
.last()
.and_then(|ancestor| ancestor.with::<dyn Outlinable>())
- .map_or(false, |last| last.level() >= level)
+ .map_or(false, |last| last.level() >= *level)
{
ancestors.pop();
}
- OutlineIndent::apply(&indent, vt, &ancestors, &mut seq, self.span())?;
+ OutlineIndent::apply(indent, vt, &ancestors, &mut seq, self.span())?;
// Add the overridable outline entry, followed by a line break.
seq.push(entry.pack());
@@ -255,7 +250,7 @@ impl Finalize for OutlineElem {
}
impl LocalName for OutlineElem {
- fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str {
+ fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
match lang {
Lang::ALBANIAN => "Përmbajtja",
Lang::ARABIC => "المحتويات",
@@ -301,7 +296,7 @@ pub trait Outlinable: Refable {
}
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Hash)]
pub enum OutlineIndent {
Bool(bool),
Rel(Rel<Length>),
@@ -497,14 +492,14 @@ impl Show for OutlineEntry {
};
// The body text remains overridable.
- seq.push(self.body().linked(Destination::Location(location)));
+ seq.push(self.body().clone().linked(Destination::Location(location)));
// Add filler symbols between the section name and page number.
if let Some(filler) = self.fill() {
seq.push(SpaceElem::new().pack());
seq.push(
BoxElem::new()
- .with_body(Some(filler))
+ .with_body(Some(filler.clone()))
.with_width(Fr::one().into())
.pack(),
);
@@ -514,7 +509,7 @@ impl Show for OutlineEntry {
}
// Add the page number.
- let page = self.page().linked(Destination::Location(location));
+ let page = self.page().clone().linked(Destination::Location(location));
seq.push(page);
Ok(Content::sequence(seq))
diff --git a/crates/typst-library/src/meta/reference.rs b/crates/typst-library/src/meta/reference.rs
index 12e13929..3a463c80 100644
--- a/crates/typst-library/src/meta/reference.rs
+++ b/crates/typst-library/src/meta/reference.rs
@@ -115,6 +115,7 @@ pub struct RefElem {
/// in @intro[Part], it is done
/// manually.
/// ```
+ #[borrowed]
pub supplement: Smart<Option<Supplement>>,
/// A synthesized citation.
@@ -132,9 +133,9 @@ impl Synthesize for RefElem {
self.push_citation(Some(citation));
self.push_element(None);
- let target = self.target();
- if !BibliographyElem::has(vt, &target.0) {
- if let Ok(elem) = vt.introspector.query_label(&target) {
+ let target = *self.target();
+ if !BibliographyElem::has(vt, target) {
+ if let Ok(elem) = vt.introspector.query_label(target) {
self.push_element(Some(elem.into_inner()));
return Ok(());
}
@@ -148,22 +149,22 @@ impl Show for RefElem {
#[tracing::instrument(name = "RefElem::show", skip_all)]
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
Ok(vt.delayed(|vt| {
- let target = self.target();
- let elem = vt.introspector.query_label(&self.target());
+ let target = *self.target();
+ let elem = vt.introspector.query_label(target);
let span = self.span();
- if BibliographyElem::has(vt, &target.0) {
+ if BibliographyElem::has(vt, target) {
if elem.is_ok() {
bail!(span, "label occurs in the document and its bibliography");
}
- return Ok(self.to_citation(vt, styles)?.pack().spanned(span));
+ return Ok(self.to_citation(vt, styles)?.spanned(span).pack());
}
let elem = elem.at(span)?;
if elem.func() == FootnoteElem::elem() {
- return Ok(FootnoteElem::with_label(target).pack().spanned(span));
+ return Ok(FootnoteElem::with_label(target).spanned(span).pack());
}
let refable = elem
@@ -204,7 +205,7 @@ impl Show for RefElem {
.at(vt, elem.location().unwrap())?
.display(vt, &numbering.trimmed())?;
- let supplement = match self.supplement(styles) {
+ let supplement = match self.supplement(styles).as_ref() {
Smart::Auto => refable.supplement(),
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(supplement)) => {
@@ -225,10 +226,10 @@ impl Show for RefElem {
impl RefElem {
/// Turn the reference into a citation.
pub fn to_citation(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<CiteElem> {
- let mut elem = CiteElem::new(self.target());
- elem.0.set_location(self.0.location().unwrap());
+ let mut elem = CiteElem::new(*self.target());
+ elem.set_location(self.location().unwrap());
elem.synthesize(vt, styles)?;
- elem.push_supplement(match self.supplement(styles) {
+ elem.push_supplement(match self.supplement(styles).clone() {
Smart::Custom(Some(Supplement::Content(content))) => Some(content),
_ => None,
});
@@ -238,6 +239,7 @@ impl RefElem {
}
/// Additional content for a reference.
+#[derive(Debug, Clone, PartialEq, Hash)]
pub enum Supplement {
Content(Content),
Func(Func),
diff --git a/crates/typst-library/src/meta/state.rs b/crates/typst-library/src/meta/state.rs
index 137b754e..4f04628f 100644
--- a/crates/typst-library/src/meta/state.rs
+++ b/crates/typst-library/src/meta/state.rs
@@ -233,7 +233,7 @@ impl State {
for elem in introspector.query(&self.selector()) {
let elem = elem.to::<UpdateElem>().unwrap();
match elem.update() {
- StateUpdate::Set(value) => state = value,
+ StateUpdate::Set(value) => state = value.clone(),
StateUpdate::Func(func) => state = func.call_vt(&mut vt, [state])?,
}
stops.push(state.clone());
@@ -244,7 +244,7 @@ impl State {
/// The selector for this state's updates.
fn selector(&self) -> Selector {
- Selector::Elem(UpdateElem::elem(), Some(dict! { "key" => self.key.clone() }))
+ select_where!(UpdateElem, Key => self.key.clone())
}
}
@@ -383,7 +383,7 @@ impl Show for DisplayElem {
#[tracing::instrument(name = "DisplayElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(vt.delayed(|vt| {
- let location = self.0.location().unwrap();
+ let location = self.location().unwrap();
let value = self.state().at(vt, location)?;
Ok(match self.func() {
Some(func) => func.call_vt(vt, [value])?.display(),