Documentation for citation, bibliography, and content

This commit is contained in:
Laurenz 2023-03-20 21:56:32 +01:00
parent 22bf0117a0
commit 2d16f9434f
17 changed files with 268 additions and 86 deletions

View File

@ -1,4 +1,4 @@
@article{stupid, @article{netwok,
title={At-scale impact of the {Net Wok}: A culinarically holistic investigation of distributed dumplings}, title={At-scale impact of the {Net Wok}: A culinarically holistic investigation of distributed dumplings},
author={Astley, Rick and Morris, Linda}, author={Astley, Rick and Morris, Linda},
journal={Armenian Journal of Proceedings}, journal={Armenian Journal of Proceedings},
@ -26,7 +26,7 @@
author={Leeson, Peter T.}, author={Leeson, Peter T.},
} }
@misc{cannonfodder, @misc{distress,
title={An Insight into Bibliographical Distress}, title={An Insight into Bibliographical Distress},
author={Aldrin, Buzz} author={Aldrin, Buzz}
} }

View File

@ -95,10 +95,17 @@ visualize: |
be in the future. be in the future.
meta: | meta: |
Document structuring and metadata setup. Document structuring, introspection, and metadata configuration.
Here, you can find functions to structure your document and configure its Here, you can find functions to structure your document and interact with that
metadata. structure. This includes section headings and figures, bibliography
management, cross-referencing and more.
Moreover, this category is home to Typst's introspection capabilities: With
the `counter` function, you can access and manipulate page, section, figure,
and equation counters or create custom ones. And the `query` function lets you
search for elements in the document to construct things like a list of
figures or headers which show the current chapter title.
symbols: | symbols: |
These two modules give names to symbols and emoji to make them easy to insert These two modules give names to symbols and emoji to make them easy to insert
@ -114,6 +121,8 @@ sym: |
[formulas]($category/math), these symbols can be used without the `#sym.` [formulas]($category/math), these symbols can be used without the `#sym.`
prefix. prefix.
The `d` in an integral's `dx` can be written as `[$dif x$]`.
emoji: | emoji: |
Named emoji. Named emoji.

View File

@ -178,8 +178,7 @@ can be either:
- a [dictionary]($type/dictionary) that has the specified key, - a [dictionary]($type/dictionary) that has the specified key,
- a [symbols]($type/symbol) that has the specified modifier, - a [symbols]($type/symbol) that has the specified modifier,
- a [module]($type/module) containing the specified definition, - a [module]($type/module) containing the specified definition,
- [content]($type/content) that exposes the specified field. Most elements - [content]($type/content) that has the specified field.
expose some or all of the non-settable arguments passed to them as fields.
```example ```example
#let dict = (greet: "Hello") #let dict = (greet: "Hello")

View File

@ -13,15 +13,17 @@ of elements.
## Set rules { #set-rules } ## Set rules { #set-rules }
With set rules, you can customize the appearance of elements. They are written With set rules, you can customize the appearance of elements. They are written
as a [function call]($type/function) to the respective function preceded by the as a [function call]($type/function) to the respective function preceded by the
`{set}` keyword (or `[#set]` in markup). Only settable parameters must be `{set}` keyword (or `[#set]` in markup). Only optional parameters of that
provided as arguments. Refer to each function's documentation for a list of function can be provided to the set rule. Refer to each function's documentation
settable parameters. In the example below, we use two set rules to change the to see which parameters are optional. In the example below, we use two set rules
[font family]($func/text.family) and to change the [font family]($func/text.family) and
[heading numbering]($func/heading.numbering) style. [heading numbering]($func/heading.numbering).
```example ```example
#set text(font: "New Computer Modern")
#set heading(numbering: "I.") #set heading(numbering: "I.")
#set text(
font: "New Computer Modern"
)
= Introduction = Introduction
With set rules, you can style With set rules, you can style
@ -35,9 +37,10 @@ your document. Below, we use a content block to scope the list styling to one
particular list. particular list.
```example ```example
This list is affected: This list is affected: #[
#[#set list(marker: [--]) #set list(marker: [--])
- Dash] - Dash
]
This one is not: This one is not:
- Bullet - Bullet
@ -87,8 +90,7 @@ fantasy encyclopedia.
#set align(center) #set align(center)
#set text(font: "Inria Serif") #set text(font: "Inria Serif")
\~ #emph(it.body) \~ #emph(it.body)
#(counter(heading) #counter(heading).display() \~
.display(it.numbering)) \~
] ]
= Dragon = Dragon

View File

@ -379,18 +379,16 @@ the resulting parts.
- returns: array - returns: array
# Content # Content
Representation of text, elements, and more. Representation of document content.
This type is at the heart of Typst. All markup you write and most This type is at the heart of Typst. All markup you write and most
[functions]($type/function) you call produce content values. You [functions]($type/function) you call produce content values. You can create a
can create a content value by enclosing markup in square brackets. This is also content value by enclosing markup in square brackets. This is also how you pass
how you pass content to functions. Typst does not allow you to peek into content to functions.
content, but you can affect its appearance in various ways using set and show
rules. See the chapter on [styling]($styling) for more details.
```example ```example
#type([*Hello!*]) \ Type of *Hello!* is
#strong[Hello!] #type([*Hello!*])
``` ```
Content can be added with the `+` operator, Content can be added with the `+` operator,
@ -398,21 +396,62 @@ Content can be added with the `+` operator,
integers. Wherever content is expected, you can also pass a integers. Wherever content is expected, you can also pass a
[string]($type/string) or `{none}`. [string]($type/string) or `{none}`.
### Reactivity ## Representation
Content is reactive to the styles that are active where it is inserted. Content consists of elements with fields. When constructing an element with
When you write a set or show rule, content that was _created_ before the show its _element function,_ you provide these fields as arguments and when you have
rule is stilled affected by the show rule if it is _inserted_ after the show a content value, you can access its fields with
rule. [field access syntax]($scripting/#field-access).
```example Some fields are required: These must be provided when constructing an element
// Content is created here. and as a consequence, they are always available through field access on content
#let mytext = [= A heading] of that type. Required fields are marked as such in the documentation.
// But still affected by the Most fields are optional: Like required fields, they can be passed to the
// styles that are active here. element function to configure them for a single element. However, these can also
#show heading: set text(green) be configured with [set rules]($styling/#set-rules) to apply them to all
#mytext elements within a scope. Optional fields are only available with field access
``` syntax when they are were explicitly passed to the element function, not when
they result from a set rule.
Each element has a default appearance. However, you can also completely
customize its appearance with a [show rule]($styling/#show-rules). The show rule
is passed the element. It can access the element's field and produce arbitrary
content from it.
In the web app, you can hover over a content variable to see exactly which
elements the content is composed of and what fields they have. Alternatively,
you can inspect the output of the [`repr`]($func/repr) function.
## Methods
### func()
The content's element function. This function can be used to create the element
contained in this content. It can be used in set and show rules for the element.
Can be compared with global functions to check whether you have a specific
kind of element.
- returns: function
### has()
Whether the content has the specified field.
- field: string (positional, required)
The field to look for.
- returns: boolean
### at()
Access the specified field on the content.
- field: string (positional, required)
The field to access.
- returns: any
### location()
The location of the content. This is only available on content returned by
[query]($func/query), for other content it will fail with an error. The
resulting location can be used with [counters]($func/counter),
[state]($func/state) and [queries]($func/query).
- returns: location
# Array # Array
A sequence of values. A sequence of values.

View File

@ -318,7 +318,7 @@ impl PageElem {
Numbering::Func(_) => true, Numbering::Func(_) => true,
}; };
Counter::new(CounterKey::Page) Counter::new(CounterKey::Page)
.display(numbering, both) .display(Some(numbering), both)
.aligned(self.number_align(styles)) .aligned(self.number_align(styles))
}) })
}); });

View File

@ -158,7 +158,7 @@ pub struct EquationElem {
} }
impl Synthesize for 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_block(self.block(styles));
self.push_numbering(self.numbering(styles)); self.push_numbering(self.numbering(styles));
} }
@ -216,7 +216,7 @@ impl Layout for EquationElem {
if let Some(numbering) = self.numbering(styles) { if let Some(numbering) = self.numbering(styles) {
let pod = Regions::one(regions.base(), Axes::splat(false)); let pod = Regions::one(regions.base(), Axes::splat(false));
let counter = Counter::of(Self::func()) let counter = Counter::of(Self::func())
.display(numbering, false) .display(Some(numbering), false)
.layout(vt, styles, pod)? .layout(vt, styles, pod)?
.into_frame(); .into_frame();

View File

@ -16,6 +16,31 @@ use crate::text::TextElem;
/// A bibliography / reference listing. /// 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 /// Display: Bibliography
/// Category: meta /// Category: meta
#[element(Locatable, Synthesize, Show, LocalName)] #[element(Locatable, Synthesize, Show, LocalName)]
@ -90,7 +115,7 @@ impl BibliographyElem {
} }
impl Synthesize for BibliographyElem { impl Synthesize for BibliographyElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) { fn synthesize(&mut self, styles: StyleChain) {
self.push_style(self.style(styles)); 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 /// Display: Citation
/// Category: meta /// Category: meta
#[element(Locatable, Synthesize, Show)] #[element(Locatable, Synthesize, Show)]
pub struct CiteElem { 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] #[variadic]
pub keys: Vec<EcoString>, pub keys: Vec<EcoString>,
/// A supplement for the citation such as page or chapter number. /// 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] #[positional]
pub supplement: Option<Content>, pub supplement: Option<Content>,
/// Whether the citation should include brackets. /// 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)] #[default(true)]
pub brackets: bool, pub brackets: bool,
@ -214,11 +282,19 @@ pub struct CiteElem {
/// ///
/// When set to `{auto}`, automatically picks the preferred citation style /// When set to `{auto}`, automatically picks the preferred citation style
/// for the bibliography's style. /// for the bibliography's style.
///
/// ```example
/// #set cite(style: "alphanumerical")
/// Alphanumerical references.
/// @netwok
///
/// #bibliography("works.bib")
/// ```
pub style: Smart<CitationStyle>, pub style: Smart<CitationStyle>,
} }
impl Synthesize for CiteElem { 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_supplement(self.supplement(styles));
self.push_brackets(self.brackets(styles)); self.push_brackets(self.brackets(styles));
self.push_style(self.style(styles)); self.push_style(self.style(styles));
@ -243,6 +319,11 @@ impl Show for CiteElem {
} }
} }
cast_from_value! {
CiteElem,
v: Content => v.to::<Self>().cloned().ok_or("expected citation")?,
}
/// A citation style. /// A citation style.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
pub enum CitationStyle { pub enum CitationStyle {
@ -261,6 +342,12 @@ pub enum CitationStyle {
Keys, Keys,
} }
impl CitationStyle {
fn is_short(self) -> bool {
matches!(self, Self::Numerical | Self::Alphanumerical | Self::Keys)
}
}
/// Fully formatted citations and references. /// Fully formatted citations and references.
#[derive(Default)] #[derive(Default)]
struct Works { struct Works {
@ -280,7 +367,7 @@ impl Works {
])) ]))
.into_iter() .into_iter()
.map(|elem| match elem.to::<RefElem>() { .map(|elem| match elem.to::<RefElem>() {
Some(reference) => reference.to_citation(StyleChain::default()), Some(reference) => reference.citation().unwrap(),
_ => elem.to::<CiteElem>().unwrap().clone(), _ => elem.to::<CiteElem>().unwrap().clone(),
}) })
.collect(); .collect();
@ -371,6 +458,10 @@ fn create(
) )
.display; .display;
if style.is_short() {
display.value = display.value.replace(' ', "\u{a0}");
}
if brackets && len == 1 { if brackets && len == 1 {
display = display.with_default_brackets(&*citation_style); display = display.with_default_brackets(&*citation_style);
} }

View File

@ -5,8 +5,9 @@ use ecow::{eco_vec, EcoVec};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use typst::eval::Tracer; use typst::eval::Tracer;
use super::{Numbering, NumberingPattern}; use super::{FigureElem, HeadingElem, Numbering, NumberingPattern};
use crate::layout::PageElem; use crate::layout::PageElem;
use crate::math::EquationElem;
use crate::prelude::*; use crate::prelude::*;
/// Count through pages, elements, and more. /// 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()`, /// which one doesn't matter. After the heading follow two calls to `step()`,
/// so the final value is `{(6,)}`. /// 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. /// The `counter` function is closely related to [state]($func/state) function.
/// Read its documentation for more details on state management in Typst and /// Read its documentation for more details on state management in Typst and
/// why it doesn't just use normal variables for counters. /// 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 /// varies, e.g. for the heading argument, you can use an
/// [argument sink]($type/arguments). /// [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 /// - returns: content
/// ///
/// ### step() /// ### step()
@ -275,14 +279,10 @@ impl Counter {
mut args: Args, mut args: Args,
span: Span, span: Span,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
let pattern = |s| NumberingPattern::from_str(s).unwrap().into();
let value = match method { let value = match method {
"display" => self "display" => {
.display( self.display(args.eat()?, args.named("both")?.unwrap_or(false)).into()
args.eat()?.unwrap_or_else(|| pattern("1.1")), }
args.named("both")?.unwrap_or(false),
)
.into(),
"step" => self "step" => self
.update(CounterUpdate::Step( .update(CounterUpdate::Step(
args.named("level")?.unwrap_or(NonZeroUsize::ONE), args.named("level")?.unwrap_or(NonZeroUsize::ONE),
@ -298,7 +298,7 @@ impl Counter {
} }
/// Display the current value of the counter. /// Display the current value of the counter.
pub fn display(self, numbering: Numbering, both: bool) -> Content { pub fn display(self, numbering: Option<Numbering>, both: bool) -> Content {
DisplayElem::new(self, numbering, both).pack() DisplayElem::new(self, numbering, both).pack()
} }
@ -574,7 +574,7 @@ struct DisplayElem {
/// The numbering to display the counter with. /// The numbering to display the counter with.
#[required] #[required]
numbering: Numbering, numbering: Option<Numbering>,
/// Whether to display both the current and final value. /// Whether to display both the current and final value.
#[required] #[required]
@ -582,10 +582,28 @@ struct DisplayElem {
} }
impl Show for DisplayElem { impl Show for DisplayElem {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> { fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let location = self.0.location().unwrap(); let location = self.0.location().unwrap();
let counter = self.counter(); 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() { let state = if self.both() {
counter.both(vt, location)? counter.both(vt, location)?
} else { } else {

View File

@ -10,7 +10,7 @@ use crate::text::TextElem;
/// ## Example /// ## Example
/// ```example /// ```example
/// = Pipeline /// = Pipeline
/// @fig-lab shows the central step of /// @lab shows the central step of
/// our molecular testing pipeline. /// our molecular testing pipeline.
/// ///
/// #figure( /// #figure(
@ -18,7 +18,7 @@ use crate::text::TextElem;
/// caption: [ /// caption: [
/// The molecular testing pipeline. /// The molecular testing pipeline.
/// ], /// ],
/// ) <fig-lab> /// ) <lab>
/// ``` /// ```
/// ///
/// Display: Figure /// Display: Figure
@ -43,7 +43,7 @@ pub struct FigureElem {
} }
impl Synthesize for FigureElem { impl Synthesize for FigureElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) { fn synthesize(&mut self, styles: StyleChain) {
self.push_numbering(self.numbering(styles)); self.push_numbering(self.numbering(styles));
} }
} }
@ -57,7 +57,7 @@ impl Show for FigureElem {
let name = self.local_name(TextElem::lang_in(styles)); let name = self.local_name(TextElem::lang_in(styles));
caption = TextElem::packed(eco_format!("{name}\u{a0}")) caption = TextElem::packed(eco_format!("{name}\u{a0}"))
+ Counter::of(Self::func()) + Counter::of(Self::func())
.display(numbering, false) .display(Some(numbering), false)
.spanned(self.span()) .spanned(self.span())
+ TextElem::packed(": ") + TextElem::packed(": ")
+ caption; + caption;

View File

@ -80,7 +80,7 @@ pub struct HeadingElem {
} }
impl Synthesize for 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_level(self.level(styles));
self.push_numbering(self.numbering(styles)); self.push_numbering(self.numbering(styles));
self.push_outlined(self.outlined(styles)); self.push_outlined(self.outlined(styles));
@ -92,7 +92,7 @@ impl Show for HeadingElem {
let mut realized = self.body(); let mut realized = self.body();
if let Some(numbering) = self.numbering(styles) { if let Some(numbering) = self.numbering(styles) {
realized = Counter::of(Self::func()) realized = Counter::of(Self::func())
.display(numbering, false) .display(Some(numbering), false)
.spanned(self.span()) .spanned(self.span())
+ HElem::new(Em::new(0.3).into()).with_weak(true).pack() + HElem::new(Em::new(0.3).into()).with_weak(true).pack()
+ realized; + realized;

View File

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use crate::text::{Hyphenate, TextElem}; 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 /// The link function makes its positional `body` argument clickable and links
/// it to the destination specified by the `dest` argument. By default, links /// it to the destination specified by the `dest` argument. By default, links

View File

@ -2,30 +2,37 @@ use super::{BibliographyElem, CiteElem, Counter, LocalName, Numbering};
use crate::prelude::*; use crate::prelude::*;
use crate::text::TextElem; 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, /// 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 /// 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 /// 1" for a reference to the first heading. The references are also links to
/// the respective element. /// the respective element.
/// ///
/// Reference syntax can also be used to [cite]($func/cite) from a bibliography.
///
/// # Example /// # Example
/// ```example /// ```example
/// #set heading(numbering: "1.") /// #set heading(numbering: "1.")
/// #set math.equation(numbering: "(1)")
/// ///
/// = Introduction <intro> /// = Introduction <intro>
/// Recent developments in typesetting /// Recent developments in
/// software have rekindled hope in /// typesetting software have
/// previously frustrated researchers. /// rekindled hope in previously
/// frustrated researchers. @distress
/// As shown in @results, we ... /// As shown in @results, we ...
/// ///
/// = Results <results> /// = Results <results>
/// We evaluate our method in a /// We discuss our approach in
/// series of tests. @perf discusses /// comparison with others.
/// the performance aspects of ...
/// ///
/// == Performance <perf> /// == Performance <perf>
/// As described in @intro, we ... /// @slow demonstrates what slow
/// software looks like.
/// $ O(n) = 2^n $ <slow>
///
/// #bibliography("works.bib")
/// ``` /// ```
/// ///
/// ## Syntax /// ## Syntax
@ -33,9 +40,12 @@ use crate::text::TextElem;
/// created by typing an `@` followed by the name of the label (e.g. /// created by typing an `@` followed by the name of the label (e.g.
/// `[= Introduction <intro>]` can be referenced by typing `[@intro]`). /// `[= Introduction <intro>]` can be referenced by typing `[@intro]`).
/// ///
/// To customize the supplement, add content in square brackets after the
/// reference: `[@intro[Chapter]]`.
///
/// Display: Reference /// Display: Reference
/// Category: meta /// Category: meta
#[element(Locatable, Show)] #[element(Synthesize, Locatable, Show)]
pub struct RefElem { pub struct RefElem {
/// The target label that should be referenced. /// The target label that should be referenced.
#[required] #[required]
@ -58,9 +68,22 @@ pub struct RefElem {
/// ///
/// = Introduction <intro> /// = Introduction <intro>
/// In @intro, we see how to turn /// In @intro, we see how to turn
/// Sections into Chapters. /// Sections into Chapters. And
/// in @intro[Part], it is done
/// manually.
/// ``` /// ```
pub supplement: Smart<Option<Supplement>>, pub supplement: Smart<Option<Supplement>>,
/// A synthesized citation.
#[synthesized]
pub citation: Option<CiteElem>,
}
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 { impl Show for RefElem {
@ -77,7 +100,7 @@ impl Show for RefElem {
bail!(self.span(), "label occurs in the document and its bibliography"); 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 { let [elem] = matches.as_slice() else {
@ -126,11 +149,12 @@ impl RefElem {
/// Turn the rference into a citation. /// Turn the rference into a citation.
pub fn to_citation(&self, styles: StyleChain) -> CiteElem { pub fn to_citation(&self, styles: StyleChain) -> CiteElem {
let mut elem = CiteElem::new(vec![self.target().0]); 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) { elem.push_supplement(match self.supplement(styles) {
Smart::Custom(Some(Supplement::Content(content))) => Some(content), Smart::Custom(Some(Supplement::Content(content))) => Some(content),
_ => None, _ => None,
}); });
elem.0.set_location(self.0.location().unwrap());
elem elem
} }
} }

View File

@ -121,7 +121,7 @@ impl RawElem {
} }
impl Synthesize for RawElem { impl Synthesize for RawElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) { fn synthesize(&mut self, styles: StyleChain) {
self.push_lang(self.lang(styles)); self.push_lang(self.lang(styles));
} }
} }

View File

@ -42,7 +42,7 @@ pub fn realize(
} }
if let Some(elem) = elem.with_mut::<dyn Synthesize>() { if let Some(elem) = elem.with_mut::<dyn Synthesize>() {
elem.synthesize(vt, styles); elem.synthesize(styles);
} }
elem.mark_prepared(); elem.mark_prepared();
@ -165,7 +165,7 @@ pub trait Locatable {}
/// rule. /// rule.
pub trait Synthesize { pub trait Synthesize {
/// Prepare the element for show rule application. /// Prepare the element for show rule application.
fn synthesize(&mut self, vt: &Vt, styles: StyleChain); fn synthesize(&mut self, styles: StyleChain);
} }
/// The base recipe for an element. /// The base recipe for an element.

View File

@ -14,7 +14,7 @@
--- ---
#set page(width: 200pt) #set page(width: 200pt)
= Details = Details
See also #cite("arrgh", "cannonfodder", [p. 22]), @arrgh[p. 4], and @cannonfodder[p. 5]. See also #cite("arrgh", "distress", [p. 22]), @arrgh[p. 4], and @distress[p. 5].
#bibliography("/works.bib") #bibliography("/works.bib")
--- ---
@ -22,7 +22,8 @@ See also #cite("arrgh", "cannonfodder", [p. 22]), @arrgh[p. 4], and @cannonfodde
#set page(width: 200pt) #set page(width: 200pt)
#bibliography("/works.bib", title: [Works to be cited], style: "author-date") #bibliography("/works.bib", title: [Works to be cited], style: "author-date")
#line(length: 100%) #line(length: 100%)
As described by #cite("stupid", brackets: false), #[#set cite(brackets: false)
As described by @netwok],
the net-work is a creature of its own. the net-work is a creature of its own.
This is close to piratery! @arrgh This is close to piratery! @arrgh
And quark! @quark And quark! @quark

View File

@ -31,8 +31,7 @@ Second: #mine.display("I")
#counter(heading).step() #counter(heading).step()
= Alpha = Alpha
In #counter(heading).display(). In #counter(heading).display()
== Beta == Beta
#set heading(numbering: none) #set heading(numbering: none)