diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-03-14 22:33:22 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-03-14 22:34:43 +0100 |
| commit | 2a86e4db0bb3894d1cc3b94e1a1af31a6cd87b80 (patch) | |
| tree | d5c0954ef779689c40eb9b2f58d477869546ea89 /library/src | |
| parent | e50189cfa75d83ea1b74b1dc2cf1fc9c01f8c825 (diff) | |
Reference supplements
Diffstat (limited to 'library/src')
| -rw-r--r-- | library/src/lib.rs | 18 | ||||
| -rw-r--r-- | library/src/meta/mod.rs | 8 | ||||
| -rw-r--r-- | library/src/meta/reference.rs | 46 |
3 files changed, 53 insertions, 19 deletions
diff --git a/library/src/lib.rs b/library/src/lib.rs index 19539ccf..5b114d9b 100644 --- a/library/src/lib.rs +++ b/library/src/lib.rs @@ -11,7 +11,7 @@ pub mod text; pub mod visualize; use typst::eval::{LangItems, Library, Module, Scope}; -use typst::geom::{Align, Color, Dir, GenAlign}; +use typst::geom::{Align, Color, Dir, GenAlign, Smart}; use typst::model::{Node, NodeId, StyleMap}; use self::layout::LayoutRoot; @@ -185,13 +185,21 @@ fn items() -> LangItems { }, raw_languages: text::RawNode::languages, link: |url| meta::LinkNode::from_url(url).pack(), - ref_: |target| meta::RefNode::new(target).pack(), + reference: |target, supplement| { + let mut node = meta::RefNode::new(target); + if let Some(supplement) = supplement { + node.push_supplement(Smart::Custom(Some(meta::Supplement::Content( + supplement, + )))); + } + node.pack() + }, heading: |level, title| meta::HeadingNode::new(title).with_level(level).pack(), list_item: |body| layout::ListItem::new(body).pack(), enum_item: |number, body| { let mut node = layout::EnumItem::new(body); if let Some(number) = number { - node = node.with_number(Some(number)); + node.push_number(Some(number)); } node.pack() }, @@ -202,10 +210,10 @@ fn items() -> LangItems { math_attach: |base, bottom, top| { let mut node = math::AttachNode::new(base); if let Some(bottom) = bottom { - node = node.with_bottom(Some(bottom)); + node.push_bottom(Some(bottom)); } if let Some(top) = top { - node = node.with_top(Some(top)); + node.push_top(Some(top)); } node.pack() }, diff --git a/library/src/meta/mod.rs b/library/src/meta/mod.rs index f5b9bf2f..3cde2b8e 100644 --- a/library/src/meta/mod.rs +++ b/library/src/meta/mod.rs @@ -15,3 +15,11 @@ pub use self::link::*; pub use self::numbering::*; pub use self::outline::*; pub use self::reference::*; + +use typst::doc::Lang; + +/// The named with which an element is referenced. +pub trait LocalName { + /// Get the name in the given language. + fn local_name(&self, lang: Lang) -> &'static str; +} diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs index 18f0aa3f..f63c7e4c 100644 --- a/library/src/meta/reference.rs +++ b/library/src/meta/reference.rs @@ -1,4 +1,4 @@ -use super::{FigureNode, HeadingNode, Numbering}; +use super::{FigureNode, HeadingNode, LocalName, Numbering}; use crate::prelude::*; use crate::text::TextNode; @@ -41,11 +41,14 @@ pub struct RefNode { #[required] pub target: Label, - /// The prefix before the referenced number. + /// A supplement for the reference. + /// + /// For references to headings or figures, this is added before the + /// referenced number. For citations, this can be used to add a page number. /// /// ```example /// #set heading(numbering: "1.") - /// #set ref(prefix: it => { + /// #set ref(supplement: it => { /// if it.func() == heading { /// "Chapter" /// } else { @@ -57,11 +60,11 @@ pub struct RefNode { /// In @intro, we see how to turn /// Sections into Chapters. /// ``` - pub prefix: Smart<Option<Func>>, /// All elements with the target label in the document. #[synthesized] pub matches: Vec<Content>, + pub supplement: Smart<Option<Supplement>>, } impl Synthesize for RefNode { @@ -90,34 +93,36 @@ impl Show for RefNode { } }; - let mut prefix = match self.prefix(styles) { + let supplement = self.supplement(styles); + let mut supplement = match supplement { Smart::Auto => target .with::<dyn LocalName>() .map(|node| node.local_name(TextNode::lang_in(styles))) .map(TextNode::packed) .unwrap_or_default(), Smart::Custom(None) => Content::empty(), - Smart::Custom(Some(func)) => { + Smart::Custom(Some(Supplement::Content(content))) => content.clone(), + Smart::Custom(Some(Supplement::Func(func))) => { let args = Args::new(func.span(), [target.clone().into()]); func.call_detached(vt.world(), args)?.display() } }; - if !prefix.is_empty() { - prefix += TextNode::packed('\u{a0}'); + if !supplement.is_empty() { + supplement += TextNode::packed('\u{a0}'); } let formatted = if let Some(heading) = target.to::<HeadingNode>() { if let Some(numbering) = heading.numbering(StyleChain::default()) { let numbers = heading.numbers().unwrap(); - numbered(vt, prefix, &numbering, &numbers)? + numbered(vt, supplement, &numbering, &numbers)? } else { bail!(self.span(), "cannot reference unnumbered heading"); } } else if let Some(figure) = target.to::<FigureNode>() { if let Some(numbering) = figure.numbering(StyleChain::default()) { let number = figure.number().unwrap(); - numbered(vt, prefix, &numbering, &[number])? + numbered(vt, supplement, &numbering, &[number])? } else { bail!(self.span(), "cannot reference unnumbered figure"); } @@ -146,8 +151,21 @@ fn numbered( }) } -/// The named with which an element is referenced. -pub trait LocalName { - /// Get the name in the given language. - fn local_name(&self, lang: Lang) -> &'static str; +/// Additional content for a reference. +pub enum Supplement { + Content(Content), + Func(Func), +} + +cast_from_value! { + Supplement, + v: Content => Self::Content(v), + v: Func => Self::Func(v), +} + +cast_to_value! { + v: Supplement => match v { + Supplement::Content(v) => v.into(), + Supplement::Func(v) => v.into(), + } } |
