mirror of
https://github.com/typst/typst
synced 2025-06-13 15:46:26 +08:00
repeatable figure captions
This commit is contained in:
parent
16736feb13
commit
84b66d43d6
@ -413,11 +413,17 @@ pub struct TrackSizings(pub SmallVec<[Sizing; 4]>);
|
|||||||
cast! {
|
cast! {
|
||||||
TrackSizings,
|
TrackSizings,
|
||||||
self => self.0.into_value(),
|
self => self.0.into_value(),
|
||||||
sizing: Sizing => Self(smallvec![sizing]),
|
sizing: Sizing => Self::from(sizing),
|
||||||
count: NonZeroUsize => Self(smallvec![Sizing::Auto; count.get()]),
|
count: NonZeroUsize => Self(smallvec![Sizing::Auto; count.get()]),
|
||||||
values: Array => Self(values.into_iter().map(Value::cast).collect::<HintedStrResult<_>>()?),
|
values: Array => Self(values.into_iter().map(Value::cast).collect::<HintedStrResult<_>>()?),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Sizing> for TrackSizings {
|
||||||
|
fn from(sizing: Sizing) -> Self {
|
||||||
|
Self(smallvec![sizing])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Any child of a grid element.
|
/// Any child of a grid element.
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
pub enum GridChild {
|
pub enum GridChild {
|
||||||
|
@ -14,8 +14,9 @@ use crate::introspection::{
|
|||||||
Count, Counter, CounterKey, CounterUpdate, Locatable, Location,
|
Count, Counter, CounterKey, CounterUpdate, Locatable, Location,
|
||||||
};
|
};
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
AlignElem, Alignment, BlockBody, BlockElem, Em, HAlignment, Length, OuterVAlignment,
|
AlignElem, Alignment, BlockBody, BlockElem, Em, GridCell, GridChild, GridElem,
|
||||||
PlaceElem, PlacementScope, VAlignment, VElem,
|
GridFooter, GridHeader, GridItem, HAlignment, Length, OuterVAlignment, PlaceElem,
|
||||||
|
PlacementScope, Sizing, TrackSizings, VAlignment, VElem,
|
||||||
};
|
};
|
||||||
use crate::model::{Numbering, NumberingPattern, Outlinable, Refable, Supplement};
|
use crate::model::{Numbering, NumberingPattern, Outlinable, Refable, Supplement};
|
||||||
use crate::text::{Lang, Region, TextElem};
|
use crate::text::{Lang, Region, TextElem};
|
||||||
@ -330,10 +331,27 @@ impl Show for Packed<FigureElem> {
|
|||||||
|
|
||||||
// Build the caption, if any.
|
// Build the caption, if any.
|
||||||
if let Some(caption) = self.caption(styles) {
|
if let Some(caption) = self.caption(styles) {
|
||||||
let v = VElem::new(self.gap(styles).into()).with_weak(true).pack();
|
let gap = self.gap(styles);
|
||||||
realized = match caption.position(styles) {
|
let v = || VElem::new(gap.into()).with_weak(true).pack();
|
||||||
OuterVAlignment::Top => caption.pack() + v + realized,
|
realized = match (caption.repeat(styles), caption.position(styles)) {
|
||||||
OuterVAlignment::Bottom => realized + v + caption.pack(),
|
(true, OuterVAlignment::Top) => GridElem::new(vec![
|
||||||
|
GridChild::Header(Packed::new(GridHeader::new(vec![
|
||||||
|
GridItem::Cell(Packed::new(GridCell::new(caption.pack()))),
|
||||||
|
]))),
|
||||||
|
GridChild::Item(GridItem::Cell(Packed::new(GridCell::new(realized)))),
|
||||||
|
])
|
||||||
|
.with_row_gutter(TrackSizings::from(Sizing::from(gap)))
|
||||||
|
.pack(),
|
||||||
|
(true, OuterVAlignment::Bottom) => GridElem::new(vec![
|
||||||
|
GridChild::Item(GridItem::Cell(Packed::new(GridCell::new(realized)))),
|
||||||
|
GridChild::Footer(Packed::new(GridFooter::new(vec![
|
||||||
|
GridItem::Cell(Packed::new(GridCell::new(caption.pack()))),
|
||||||
|
]))),
|
||||||
|
])
|
||||||
|
.with_row_gutter(TrackSizings::from(Sizing::from(gap)))
|
||||||
|
.pack(),
|
||||||
|
(false, OuterVAlignment::Top) => caption.pack() + v() + realized,
|
||||||
|
(false, OuterVAlignment::Bottom) => realized + v() + caption.pack(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,6 +515,25 @@ pub struct FigureCaption {
|
|||||||
#[default(OuterVAlignment::Bottom)]
|
#[default(OuterVAlignment::Bottom)]
|
||||||
pub position: OuterVAlignment,
|
pub position: OuterVAlignment,
|
||||||
|
|
||||||
|
/// Whether the figure caption should be repeated if the figure breaks.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #show figure.where(kind: table): set block(breakable: true)
|
||||||
|
/// #set page(height: 7em)
|
||||||
|
/// #figure(
|
||||||
|
/// table(
|
||||||
|
/// columns: 3,
|
||||||
|
/// [A], [B], [C],
|
||||||
|
/// [D], [E], [F],
|
||||||
|
/// [G], [H], [I],
|
||||||
|
/// [J], [K], [L]
|
||||||
|
/// ),
|
||||||
|
/// caption: figure.caption(repeat: true)[A nice table.]
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
#[default(false)]
|
||||||
|
pub repeat: bool,
|
||||||
|
|
||||||
/// The separator which will appear between the number and body.
|
/// The separator which will appear between the number and body.
|
||||||
///
|
///
|
||||||
/// If set to `{auto}`, the separator will be adapted to the current
|
/// If set to `{auto}`, the separator will be adapted to the current
|
||||||
|
BIN
tests/ref/figure-caption-repeat-bottom.png
Normal file
BIN
tests/ref/figure-caption-repeat-bottom.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
tests/ref/figure-caption-repeat-top.png
Normal file
BIN
tests/ref/figure-caption-repeat-top.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
@ -219,6 +219,34 @@ We can clearly see that @fig-cylinder and
|
|||||||
// Error: 31-38 expected `top` or `bottom`, found horizon
|
// Error: 31-38 expected `top` or `bottom`, found horizon
|
||||||
#set figure.caption(position: horizon)
|
#set figure.caption(position: horizon)
|
||||||
|
|
||||||
|
--- figure-caption-repeat-bottom ---
|
||||||
|
#show figure.where(kind: table): set block(breakable: true)
|
||||||
|
#set page(height: 7em)
|
||||||
|
#figure(
|
||||||
|
table(
|
||||||
|
columns: 3,
|
||||||
|
[A], [B], [C],
|
||||||
|
[D], [E], [F],
|
||||||
|
[G], [H], [I],
|
||||||
|
[J], [K], [L]
|
||||||
|
),
|
||||||
|
caption: figure.caption(repeat: true)[A nice table.]
|
||||||
|
)
|
||||||
|
|
||||||
|
--- figure-caption-repeat-top ---
|
||||||
|
#show figure.where(kind: table): set block(breakable: true)
|
||||||
|
#set page(height: 7em)
|
||||||
|
#figure(
|
||||||
|
table(
|
||||||
|
columns: 3,
|
||||||
|
[A], [B], [C],
|
||||||
|
[D], [E], [F],
|
||||||
|
[G], [H], [I],
|
||||||
|
[J], [K], [L]
|
||||||
|
),
|
||||||
|
caption: figure.caption(position: top, repeat: true)[A nice table.]
|
||||||
|
)
|
||||||
|
|
||||||
--- figure-localization-fr ---
|
--- figure-localization-fr ---
|
||||||
// Test French
|
// Test French
|
||||||
#set text(lang: "fr")
|
#set text(lang: "fr")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user