Fix heading supplement

Fixes #730
This commit is contained in:
Laurenz 2023-04-11 16:59:38 +02:00
parent 9720424884
commit 2606034ac7
5 changed files with 69 additions and 70 deletions

View File

@ -298,13 +298,12 @@ impl Refable for EquationElem {
fn reference(
&self,
vt: &mut Vt,
styles: StyleChain,
supplement: Option<Content>,
lang: Lang,
) -> SourceResult<Content> {
// first we create the supplement of the heading
let mut supplement = supplement.unwrap_or_else(|| {
TextElem::packed(self.local_name(TextElem::lang_in(styles)))
});
let mut supplement =
supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang)));
// we append a space if the supplement is not empty
if !supplement.is_empty() {
@ -312,7 +311,7 @@ impl Refable for EquationElem {
};
// we check for a numbering
let Some(numbering) = self.numbering(styles) else {
let Some(numbering) = self.numbering(StyleChain::default()) else {
bail!(self.span(), "only numbered equations can be referenced");
};
@ -324,11 +323,11 @@ impl Refable for EquationElem {
Ok(supplement + numbers)
}
fn numbering(&self, styles: StyleChain) -> Option<Numbering> {
self.numbering(styles)
fn numbering(&self) -> Option<Numbering> {
self.numbering(StyleChain::default())
}
fn counter(&self, _: StyleChain) -> Counter {
fn counter(&self) -> Counter {
Counter::of(Self::func())
}
}

View File

@ -223,12 +223,14 @@ impl Synthesize for FigureElem {
}),
)));
self.push_caption(self.caption(styles));
self.push_kind(Smart::Custom(kind));
self.push_numbering(numbering);
self.push_counter(Some(counter));
self.push_supplement(Smart::Custom(Supplement::Content(
supplement.unwrap_or_default(),
)));
self.push_numbering(numbering);
self.push_outlined(self.outlined(styles));
self.push_counter(Some(counter));
Ok(())
}
@ -242,7 +244,7 @@ impl Show for FigureElem {
// We build the caption, if any.
if self.caption(styles).is_some() {
realized += VElem::weak(self.gap(styles).into()).pack();
realized += self.show_caption(vt, styles)?;
realized += self.show_caption(vt)?;
}
// We wrap the contents in a block.
@ -268,32 +270,32 @@ impl Refable for FigureElem {
fn reference(
&self,
vt: &mut Vt,
styles: StyleChain,
supplement: Option<Content>,
_: Lang,
) -> SourceResult<Content> {
// If the figure is not numbered, we cannot reference it.
// Otherwise we build the supplement and numbering scheme.
let Some(desc) = self.show_supplement_and_numbering(vt, styles, supplement)? else {
let Some(desc) = self.show_supplement_and_numbering(vt, supplement)? else {
bail!(self.span(), "cannot reference unnumbered figure")
};
Ok(desc)
}
fn outline(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Option<Content>> {
fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult<Option<Content>> {
// If the figure is not outlined, it is not referenced.
if !self.outlined(styles) {
if !self.outlined(StyleChain::default()) {
return Ok(None);
}
self.show_caption(vt, styles).map(Some)
self.show_caption(vt).map(Some)
}
fn numbering(&self, styles: StyleChain) -> Option<Numbering> {
self.numbering(styles)
fn numbering(&self) -> Option<Numbering> {
self.numbering(StyleChain::default())
}
fn counter(&self, _: StyleChain) -> Counter {
fn counter(&self) -> Counter {
self.counter().unwrap_or_else(|| Counter::of(Self::func()))
}
}
@ -327,12 +329,13 @@ impl FigureElem {
pub fn show_supplement_and_numbering(
&self,
vt: &mut Vt,
styles: StyleChain,
external_supplement: Option<Content>,
) -> SourceResult<Option<Content>> {
if let (Some(numbering), Some(supplement), Some(counter)) = (
self.numbering(styles),
self.supplement(styles).as_custom().and_then(|s| s.as_content()),
self.numbering(StyleChain::default()),
self.supplement(StyleChain::default())
.as_custom()
.and_then(|s| s.as_content()),
self.counter(),
) {
let mut name = external_supplement.unwrap_or(supplement);
@ -356,12 +359,12 @@ impl FigureElem {
///
/// # Errors
/// If a numbering is specified but the [`Self::element`] is `None`.
pub fn show_caption(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let Some(mut caption) = self.caption(styles) else {
pub fn show_caption(&self, vt: &mut Vt) -> SourceResult<Content> {
let Some(mut caption) = self.caption(StyleChain::default()) else {
return Ok(Content::empty());
};
if let Some(sup_and_num) = self.show_supplement_and_numbering(vt, styles, None)? {
if let Some(sup_and_num) = self.show_supplement_and_numbering(vt, None)? {
caption = sup_and_num + TextElem::packed(": ") + caption;
}

View File

@ -59,21 +59,6 @@ pub struct HeadingElem {
/// ```
pub numbering: Option<Numbering>,
/// Whether the heading should appear in the outline.
///
/// ```example
/// #outline()
///
/// #heading[Normal]
/// This is a normal heading.
///
/// #heading(outlined: false)[Hidden]
/// This heading does not appear
/// in the outline.
/// ```
#[default(true)]
pub outlined: bool,
/// A supplement for the heading.
///
/// For references to headings, this is added before the
@ -91,6 +76,21 @@ pub struct HeadingElem {
#[default(Smart::Auto)]
pub supplement: Smart<Option<Supplement>>,
/// Whether the heading should appear in the outline.
///
/// ```example
/// #outline()
///
/// #heading[Normal]
/// This is a normal heading.
///
/// #heading(outlined: false)[Hidden]
/// This heading does not appear
/// in the outline.
/// ```
#[default(true)]
pub outlined: bool,
/// The heading's title.
#[required]
pub body: Content,
@ -100,6 +100,7 @@ impl Synthesize for HeadingElem {
fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
self.push_level(self.level(styles));
self.push_numbering(self.numbering(styles));
self.push_supplement(self.supplement(styles));
self.push_outlined(self.outlined(styles));
Ok(())
}
@ -159,17 +160,15 @@ impl Refable for HeadingElem {
fn reference(
&self,
vt: &mut Vt,
styles: StyleChain,
supplement: Option<Content>,
lang: Lang,
) -> SourceResult<Content> {
// Create the supplement of the heading.
let mut supplement = if let Some(supplement) = supplement {
supplement
} else {
match self.supplement(styles) {
Smart::Auto => {
TextElem::packed(self.local_name(TextElem::lang_in(styles)))
}
match self.supplement(StyleChain::default()) {
Smart::Auto => TextElem::packed(self.local_name(lang)),
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(supplement)) => {
supplement.resolve(vt, std::iter::once(Value::from(self.clone())))?
@ -183,7 +182,7 @@ impl Refable for HeadingElem {
};
// Check for a numbering.
let Some(numbering) = self.numbering(styles) else {
let Some(numbering) = self.numbering(StyleChain::default()) else {
bail!(self.span(), "only numbered headings can be referenced");
};
@ -195,21 +194,21 @@ impl Refable for HeadingElem {
Ok(supplement + numbers)
}
fn level(&self, styles: StyleChain) -> usize {
self.level(styles).get()
fn level(&self) -> usize {
self.level(StyleChain::default()).get()
}
fn numbering(&self, styles: StyleChain) -> Option<Numbering> {
self.numbering(styles)
fn numbering(&self) -> Option<Numbering> {
self.numbering(StyleChain::default())
}
fn counter(&self, _: StyleChain) -> Counter {
fn counter(&self) -> Counter {
Counter::of(Self::func())
}
fn outline(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Option<Content>> {
fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult<Option<Content>> {
// Check whether the heading is outlined.
if !self.outlined(styles) {
if !self.outlined(StyleChain::default()) {
return Ok(None);
}

View File

@ -151,6 +151,7 @@ impl Show for OutlineElem {
let indent = self.indent(styles);
let depth = self.depth(styles).map_or(usize::MAX, NonZeroUsize::get);
let lang = TextElem::lang_in(styles);
let mut ancestors: Vec<&Content> = vec![];
let elems = vt.introspector.query(self.target(styles));
@ -161,11 +162,11 @@ impl Show for OutlineElem {
};
let location = elem.location().expect("missing location");
if depth < refable.level(StyleChain::default()) {
if depth < refable.level() {
continue;
}
let Some(outline) = refable.outline(vt, StyleChain::default())? else {
let Some(outline) = refable.outline(vt, lang)? else {
continue;
};
@ -174,10 +175,7 @@ impl Show for OutlineElem {
while ancestors
.last()
.and_then(|ancestor| ancestor.with::<dyn Refable>())
.map_or(false, |last| {
last.level(StyleChain::default())
>= refable.level(StyleChain::default())
})
.map_or(false, |last| last.level() >= refable.level())
{
ancestors.pop();
}
@ -188,11 +186,9 @@ impl Show for OutlineElem {
for ancestor in &ancestors {
let ancestor_refable = ancestor.with::<dyn Refable>().unwrap();
if let Some(numbering) =
ancestor_refable.numbering(StyleChain::default())
{
if let Some(numbering) = ancestor_refable.numbering() {
let numbers = ancestor_refable
.counter(StyleChain::default())
.counter()
.at(vt, ancestor.location().unwrap())?
.display(vt, &numbering)?;

View File

@ -1,5 +1,6 @@
use super::{BibliographyElem, CiteElem, Counter, Figurable, Numbering};
use crate::prelude::*;
use crate::text::TextElem;
/// A reference to a label or bibliography.
///
@ -131,10 +132,11 @@ impl Show for RefElem {
}
};
let lang = TextElem::lang_in(styles);
let reference = elem
.with::<dyn Refable>()
.expect("element should be refable")
.reference(vt, styles, supplement)?;
.reference(vt, supplement, lang)?;
Ok(reference.linked(Destination::Location(elem.location().unwrap())))
}
@ -212,27 +214,27 @@ pub trait Refable {
fn reference(
&self,
vt: &mut Vt,
styles: StyleChain,
supplement: Option<Content>,
lang: Lang,
) -> SourceResult<Content>;
/// Tries to build an outline element for this element.
/// If this returns `None`, the outline will not include this element.
/// By default this just calls [`Refable::reference`].
fn outline(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Option<Content>> {
self.reference(vt, styles, None).map(Some)
fn outline(&self, vt: &mut Vt, lang: Lang) -> SourceResult<Option<Content>> {
self.reference(vt, None, lang).map(Some)
}
/// Returns the level of this element.
/// This is used to determine the level of the outline.
/// By default this returns `0`.
fn level(&self, _styles: StyleChain) -> usize {
fn level(&self) -> usize {
0
}
/// Returns the numbering of this element.
fn numbering(&self, styles: StyleChain) -> Option<Numbering>;
fn numbering(&self) -> Option<Numbering>;
/// Returns the counter of this element.
fn counter(&self, styles: StyleChain) -> Counter;
fn counter(&self) -> Counter;
}