From 2d16f9434f46ab591cede54def23ae4bc477b668 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 20 Mar 2023 21:56:32 +0100 Subject: Documentation for citation, bibliography, and content --- library/src/layout/page.rs | 2 +- library/src/math/mod.rs | 4 +- library/src/meta/bibliography.rs | 101 +++++++++++++++++++++++++++++++++++++-- library/src/meta/counter.rs | 44 ++++++++++++----- library/src/meta/figure.rs | 8 ++-- library/src/meta/heading.rs | 4 +- library/src/meta/link.rs | 2 +- library/src/meta/reference.rs | 48 ++++++++++++++----- library/src/text/raw.rs | 2 +- 9 files changed, 174 insertions(+), 41 deletions(-) (limited to 'library/src') diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs index a8a806ad..61a1f9c4 100644 --- a/library/src/layout/page.rs +++ b/library/src/layout/page.rs @@ -318,7 +318,7 @@ impl PageElem { Numbering::Func(_) => true, }; Counter::new(CounterKey::Page) - .display(numbering, both) + .display(Some(numbering), both) .aligned(self.number_align(styles)) }) }); diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs index cf665203..4e91dd51 100644 --- a/library/src/math/mod.rs +++ b/library/src/math/mod.rs @@ -158,7 +158,7 @@ pub struct EquationElem { } impl Synthesize for EquationElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_block(self.block(styles)); self.push_numbering(self.numbering(styles)); } @@ -216,7 +216,7 @@ impl Layout for EquationElem { if let Some(numbering) = self.numbering(styles) { let pod = Regions::one(regions.base(), Axes::splat(false)); let counter = Counter::of(Self::func()) - .display(numbering, false) + .display(Some(numbering), false) .layout(vt, styles, pod)? .into_frame(); diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs index 5f244a8f..2223ce2a 100644 --- a/library/src/meta/bibliography.rs +++ b/library/src/meta/bibliography.rs @@ -16,6 +16,31 @@ use crate::text::TextElem; /// A bibliography / reference listing. /// +/// You can create a new bibliography by calling this function with a path +/// to a bibliography file in either one of two formats: +/// +/// - A Hayagriva `.yml` file. Hayagriva is a new bibliography file format +/// designed for use with Typst. Visit its +/// [documentation](https://github.com/typst/hayagriva/blob/main/docs/file-format.md) +/// for more details. +/// - A BibLaTeX `.bib` file. +/// +/// As soon as you add a bibliography somewhere in your document, you can start +/// citing things with reference syntax (`[@key]`) or explicit calls to the +/// [citation]($func/cite) function (`[#cite("key")]`). The bibliography will +/// only show entries for works that were referenced in the document. +/// +/// # Example +/// ```example +/// This was already noted by +/// pirates long ago. @arrgh +/// +/// Multiple sources say ... +/// #cite("arrgh", "netwok"). +/// +/// #bibliography("works.bib") +/// ``` +/// /// Display: Bibliography /// Category: meta #[element(Locatable, Synthesize, Show, LocalName)] @@ -90,7 +115,7 @@ impl BibliographyElem { } impl Synthesize for BibliographyElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_style(self.style(styles)); } } @@ -192,21 +217,64 @@ impl BibliographyStyle { } } -/// A citation of another work. +/// Cite a work from the bibliography. +/// +/// Before you starting citing, you need to add a +/// [bibliography]($func/bibliography) somewhere in your document. +/// +/// # Example +/// ```example +/// This was already noted by +/// pirates long ago. @arrgh +/// +/// Multiple sources say ... +/// #cite("arrgh", "netwok"). +/// +/// #bibliography("works.bib") +/// ``` +/// +/// # Syntax +/// This function indirectly has dedicated syntax. [References]($func/ref) +/// can be used to cite works from the bibliography. The label then +/// corresponds to the citation key. /// /// Display: Citation /// Category: meta #[element(Locatable, Synthesize, Show)] pub struct CiteElem { - /// The citation key. + /// The citation keys that identify the elements that shall be cited in + /// the bibliography. + /// + /// Reference syntax supports only a single key. #[variadic] pub keys: Vec, /// A supplement for the citation such as page or chapter number. + /// + /// In reference syntax, the supplement can be added in square brackets: + /// + /// ```example + /// This has been proven over and + /// over again. @distress[p.~7] + /// + /// #bibliography("works.bib") + /// ``` #[positional] pub supplement: Option, /// Whether the citation should include brackets. + /// + /// ```example + /// #set cite(brackets: false) + /// + /// @netwok follow these methods + /// in their work ... + /// + /// #bibliography( + /// "works.bib", + /// style: "author-date", + /// ) + /// ``` #[default(true)] pub brackets: bool, @@ -214,11 +282,19 @@ pub struct CiteElem { /// /// When set to `{auto}`, automatically picks the preferred citation style /// for the bibliography's style. + /// + /// ```example + /// #set cite(style: "alphanumerical") + /// Alphanumerical references. + /// @netwok + /// + /// #bibliography("works.bib") + /// ``` pub style: Smart, } impl Synthesize for CiteElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_supplement(self.supplement(styles)); self.push_brackets(self.brackets(styles)); self.push_style(self.style(styles)); @@ -243,6 +319,11 @@ impl Show for CiteElem { } } +cast_from_value! { + CiteElem, + v: Content => v.to::().cloned().ok_or("expected citation")?, +} + /// A citation style. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)] pub enum CitationStyle { @@ -261,6 +342,12 @@ pub enum CitationStyle { Keys, } +impl CitationStyle { + fn is_short(self) -> bool { + matches!(self, Self::Numerical | Self::Alphanumerical | Self::Keys) + } +} + /// Fully formatted citations and references. #[derive(Default)] struct Works { @@ -280,7 +367,7 @@ impl Works { ])) .into_iter() .map(|elem| match elem.to::() { - Some(reference) => reference.to_citation(StyleChain::default()), + Some(reference) => reference.citation().unwrap(), _ => elem.to::().unwrap().clone(), }) .collect(); @@ -371,6 +458,10 @@ fn create( ) .display; + if style.is_short() { + display.value = display.value.replace(' ', "\u{a0}"); + } + if brackets && len == 1 { display = display.with_default_brackets(&*citation_style); } diff --git a/library/src/meta/counter.rs b/library/src/meta/counter.rs index b93b8d15..c407219f 100644 --- a/library/src/meta/counter.rs +++ b/library/src/meta/counter.rs @@ -5,8 +5,9 @@ use ecow::{eco_vec, EcoVec}; use smallvec::{smallvec, SmallVec}; use typst::eval::Tracer; -use super::{Numbering, NumberingPattern}; +use super::{FigureElem, HeadingElem, Numbering, NumberingPattern}; use crate::layout::PageElem; +use crate::math::EquationElem; use crate::prelude::*; /// Count through pages, elements, and more. @@ -165,7 +166,7 @@ use crate::prelude::*; /// which one doesn't matter. After the heading follow two calls to `step()`, /// so the final value is `{(6,)}`. /// -/// ## Different kinds of state +/// ## Other kinds of state /// The `counter` function is closely related to [state]($func/state) function. /// Read its documentation for more details on state management in Typst and /// why it doesn't just use normal variables for counters. @@ -181,6 +182,9 @@ use crate::prelude::*; /// varies, e.g. for the heading argument, you can use an /// [argument sink]($type/arguments). /// +/// If this is omitted, displays the counter with the numbering style for the +/// counted element or with the pattern `{"1.1"}` if no such style exists. +/// /// - returns: content /// /// ### step() @@ -275,14 +279,10 @@ impl Counter { mut args: Args, span: Span, ) -> SourceResult { - let pattern = |s| NumberingPattern::from_str(s).unwrap().into(); let value = match method { - "display" => self - .display( - args.eat()?.unwrap_or_else(|| pattern("1.1")), - args.named("both")?.unwrap_or(false), - ) - .into(), + "display" => { + self.display(args.eat()?, args.named("both")?.unwrap_or(false)).into() + } "step" => self .update(CounterUpdate::Step( args.named("level")?.unwrap_or(NonZeroUsize::ONE), @@ -298,7 +298,7 @@ impl Counter { } /// Display the current value of the counter. - pub fn display(self, numbering: Numbering, both: bool) -> Content { + pub fn display(self, numbering: Option, both: bool) -> Content { DisplayElem::new(self, numbering, both).pack() } @@ -574,7 +574,7 @@ struct DisplayElem { /// The numbering to display the counter with. #[required] - numbering: Numbering, + numbering: Option, /// Whether to display both the current and final value. #[required] @@ -582,10 +582,28 @@ struct DisplayElem { } impl Show for DisplayElem { - fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult { + fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult { let location = self.0.location().unwrap(); let counter = self.counter(); - let numbering = self.numbering(); + let numbering = self + .numbering() + .or_else(|| { + let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else { + return None; + }; + + if func == HeadingElem::func() { + HeadingElem::numbering_in(styles) + } else if func == FigureElem::func() { + FigureElem::numbering_in(styles) + } else if func == EquationElem::func() { + EquationElem::numbering_in(styles) + } else { + None + } + }) + .unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into()); + let state = if self.both() { counter.both(vt, location)? } else { diff --git a/library/src/meta/figure.rs b/library/src/meta/figure.rs index 9251f3ef..73a8ef5b 100644 --- a/library/src/meta/figure.rs +++ b/library/src/meta/figure.rs @@ -10,7 +10,7 @@ use crate::text::TextElem; /// ## Example /// ```example /// = Pipeline -/// @fig-lab shows the central step of +/// @lab shows the central step of /// our molecular testing pipeline. /// /// #figure( @@ -18,7 +18,7 @@ use crate::text::TextElem; /// caption: [ /// The molecular testing pipeline. /// ], -/// ) +/// ) /// ``` /// /// Display: Figure @@ -43,7 +43,7 @@ pub struct FigureElem { } impl Synthesize for FigureElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_numbering(self.numbering(styles)); } } @@ -57,7 +57,7 @@ impl Show for FigureElem { let name = self.local_name(TextElem::lang_in(styles)); caption = TextElem::packed(eco_format!("{name}\u{a0}")) + Counter::of(Self::func()) - .display(numbering, false) + .display(Some(numbering), false) .spanned(self.span()) + TextElem::packed(": ") + caption; diff --git a/library/src/meta/heading.rs b/library/src/meta/heading.rs index 1eaca187..ca38d546 100644 --- a/library/src/meta/heading.rs +++ b/library/src/meta/heading.rs @@ -80,7 +80,7 @@ pub struct HeadingElem { } impl Synthesize for HeadingElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_level(self.level(styles)); self.push_numbering(self.numbering(styles)); self.push_outlined(self.outlined(styles)); @@ -92,7 +92,7 @@ impl Show for HeadingElem { let mut realized = self.body(); if let Some(numbering) = self.numbering(styles) { realized = Counter::of(Self::func()) - .display(numbering, false) + .display(Some(numbering), false) .spanned(self.span()) + HElem::new(Em::new(0.3).into()).with_weak(true).pack() + realized; diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs index c82a7443..d8cb779a 100644 --- a/library/src/meta/link.rs +++ b/library/src/meta/link.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::text::{Hyphenate, TextElem}; -/// Link to a URL or another location in the document. +/// Link to a URL or a location in the document. /// /// The link function makes its positional `body` argument clickable and links /// it to the destination specified by the `dest` argument. By default, links diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs index 6e794d2d..c103dd02 100644 --- a/library/src/meta/reference.rs +++ b/library/src/meta/reference.rs @@ -2,30 +2,37 @@ use super::{BibliographyElem, CiteElem, Counter, LocalName, Numbering}; use crate::prelude::*; use crate::text::TextElem; -/// A reference to a label. +/// A reference to a label or bibliography. /// /// The reference function produces a textual reference to a label. For example, /// a reference to a heading will yield an appropriate string such as "Section /// 1" for a reference to the first heading. The references are also links to /// the respective element. /// +/// Reference syntax can also be used to [cite]($func/cite) from a bibliography. +/// /// # Example /// ```example /// #set heading(numbering: "1.") +/// #set math.equation(numbering: "(1)") /// /// = Introduction -/// Recent developments in typesetting -/// software have rekindled hope in -/// previously frustrated researchers. +/// Recent developments in +/// typesetting software have +/// rekindled hope in previously +/// frustrated researchers. @distress /// As shown in @results, we ... /// /// = Results -/// We evaluate our method in a -/// series of tests. @perf discusses -/// the performance aspects of ... +/// We discuss our approach in +/// comparison with others. /// /// == Performance -/// As described in @intro, we ... +/// @slow demonstrates what slow +/// software looks like. +/// $ O(n) = 2^n $ +/// +/// #bibliography("works.bib") /// ``` /// /// ## Syntax @@ -33,9 +40,12 @@ use crate::text::TextElem; /// created by typing an `@` followed by the name of the label (e.g. /// `[= Introduction ]` can be referenced by typing `[@intro]`). /// +/// To customize the supplement, add content in square brackets after the +/// reference: `[@intro[Chapter]]`. +/// /// Display: Reference /// Category: meta -#[element(Locatable, Show)] +#[element(Synthesize, Locatable, Show)] pub struct RefElem { /// The target label that should be referenced. #[required] @@ -58,9 +68,22 @@ pub struct RefElem { /// /// = Introduction /// In @intro, we see how to turn - /// Sections into Chapters. + /// Sections into Chapters. And + /// in @intro[Part], it is done + /// manually. /// ``` pub supplement: Smart>, + + /// A synthesized citation. + #[synthesized] + pub citation: Option, +} + +impl Synthesize for RefElem { + fn synthesize(&mut self, styles: StyleChain) { + let citation = self.to_citation(styles); + self.push_citation(Some(citation)); + } } impl Show for RefElem { @@ -77,7 +100,7 @@ impl Show for RefElem { bail!(self.span(), "label occurs in the document and its bibliography"); } - return self.to_citation(styles).show(vt, styles); + return Ok(self.to_citation(styles).pack()); } let [elem] = matches.as_slice() else { @@ -126,11 +149,12 @@ impl RefElem { /// Turn the rference into a citation. pub fn to_citation(&self, styles: StyleChain) -> CiteElem { let mut elem = CiteElem::new(vec![self.target().0]); + elem.0.set_location(self.0.location().unwrap()); + elem.synthesize(styles); elem.push_supplement(match self.supplement(styles) { Smart::Custom(Some(Supplement::Content(content))) => Some(content), _ => None, }); - elem.0.set_location(self.0.location().unwrap()); elem } } diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs index d24254ed..c2630aef 100644 --- a/library/src/text/raw.rs +++ b/library/src/text/raw.rs @@ -121,7 +121,7 @@ impl RawElem { } impl Synthesize for RawElem { - fn synthesize(&mut self, _: &Vt, styles: StyleChain) { + fn synthesize(&mut self, styles: StyleChain) { self.push_lang(self.lang(styles)); } } -- cgit v1.2.3