diff options
Diffstat (limited to 'crates/typst-library/src/meta')
| -rw-r--r-- | crates/typst-library/src/meta/bibliography.rs | 66 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/cite.rs | 2 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/context.rs | 2 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/counter.rs | 18 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/document.rs | 10 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/figure.rs | 78 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/footnote.rs | 22 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/heading.rs | 26 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/link.rs | 8 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/mod.rs | 18 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/outline.rs | 35 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/reference.rs | 26 | ||||
| -rw-r--r-- | crates/typst-library/src/meta/state.rs | 6 |
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(), |
