mirror of
https://github.com/typst/typst
synced 2025-05-19 03:25:27 +08:00
Fixed page numbering (#594)
This commit is contained in:
parent
d569f6b33b
commit
70a909b8ba
@ -324,8 +324,14 @@ impl PageElem {
|
||||
});
|
||||
let footer_descent = self.footer_descent(styles);
|
||||
|
||||
let numbering_meta = FrameItem::Meta(
|
||||
Meta::PageNumbering(self.numbering(styles).into()),
|
||||
Size::zero(),
|
||||
);
|
||||
|
||||
// Realize overlays.
|
||||
for frame in &mut fragment {
|
||||
frame.prepend(Point::zero(), numbering_meta.clone());
|
||||
let size = frame.size();
|
||||
let pad = padding.resolve(styles).relative_to(size);
|
||||
let pw = size.x - pad.left - pad.right;
|
||||
|
@ -35,6 +35,15 @@ use crate::prelude::*;
|
||||
///
|
||||
/// - returns: dictionary
|
||||
///
|
||||
/// ### page-numbering()
|
||||
/// Returns the page numbering pattern of the page at this location. This can be
|
||||
/// used when displaying the page counter in order to obtain the local numbering.
|
||||
/// This is useful if you are building custom indices or outlines.
|
||||
///
|
||||
/// If the page numbering is set to `none` at that location, this function returns `none`.
|
||||
///
|
||||
/// - returns: string or function or none
|
||||
///
|
||||
/// Display: Locate
|
||||
/// Category: meta
|
||||
/// Returns: content
|
||||
|
@ -1,4 +1,8 @@
|
||||
use super::{Counter, CounterKey, HeadingElem, LocalName, Refable};
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::{
|
||||
Counter, CounterKey, HeadingElem, LocalName, Numbering, NumberingPattern, Refable,
|
||||
};
|
||||
use crate::layout::{BoxElem, HElem, HideElem, ParbreakElem, RepeatElem};
|
||||
use crate::prelude::*;
|
||||
use crate::text::{LinebreakElem, SpaceElem, TextElem};
|
||||
@ -205,6 +209,15 @@ impl Show for OutlineElem {
|
||||
// Add the outline of the element.
|
||||
seq.push(outline.linked(Destination::Location(location)));
|
||||
|
||||
let page_numbering = vt
|
||||
.introspector
|
||||
.page_numbering(location)
|
||||
.cast::<Option<Numbering>>()
|
||||
.unwrap()
|
||||
.unwrap_or_else(|| {
|
||||
Numbering::Pattern(NumberingPattern::from_str("1").unwrap())
|
||||
});
|
||||
|
||||
// Add filler symbols between the section name and page number.
|
||||
if let Some(filler) = self.fill(styles) {
|
||||
seq.push(SpaceElem::new().pack());
|
||||
@ -221,11 +234,10 @@ impl Show for OutlineElem {
|
||||
|
||||
// Add the page number and linebreak.
|
||||
let page = Counter::new(CounterKey::Page)
|
||||
// query the page counter state at location of heading
|
||||
.at(vt, location)?
|
||||
.first();
|
||||
let end = TextElem::packed(eco_format!("{page}"));
|
||||
seq.push(end.linked(Destination::Location(location)));
|
||||
.display(vt, &page_numbering)?;
|
||||
|
||||
seq.push(page.linked(Destination::Location(location)));
|
||||
seq.push(LinebreakElem::new().pack());
|
||||
|
||||
ancestors.push(elem);
|
||||
|
@ -609,6 +609,8 @@ pub enum Meta {
|
||||
/// An identifiable element that produces something within the area this
|
||||
/// metadata is attached to.
|
||||
Elem(Content),
|
||||
/// The numbering of the current page.
|
||||
PageNumbering(Value),
|
||||
/// Indicates that content should be hidden. This variant doesn't appear
|
||||
/// in the final frames as it is removed alongside the content that should
|
||||
/// be hidden.
|
||||
|
@ -154,6 +154,7 @@ pub fn call(
|
||||
match method {
|
||||
"page" => vm.vt.introspector.page(location).into(),
|
||||
"position" => vm.vt.introspector.position(location).into(),
|
||||
"page-numbering" => vm.vt.introspector.page_numbering(location),
|
||||
_ => return missing(),
|
||||
}
|
||||
} else {
|
||||
@ -308,7 +309,7 @@ pub fn methods_on(type_name: &str) -> &[(&'static str, bool)] {
|
||||
],
|
||||
"function" => &[("where", true), ("with", true)],
|
||||
"arguments" => &[("named", false), ("pos", false)],
|
||||
"location" => &[("page", false), ("position", false)],
|
||||
"location" => &[("page", false), ("position", false), ("page-numbering", false)],
|
||||
"counter" => &[
|
||||
("display", true),
|
||||
("at", true),
|
||||
|
@ -298,6 +298,7 @@ fn write_frame(ctx: &mut PageContext, frame: &Frame) {
|
||||
Meta::Link(dest) => write_link(ctx, pos, dest, *size),
|
||||
Meta::Elem(_) => {}
|
||||
Meta::Hide => {}
|
||||
Meta::PageNumbering(_) => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ fn render_frame(
|
||||
FrameItem::Meta(meta, _) => match meta {
|
||||
Meta::Link(_) => {}
|
||||
Meta::Elem(_) => {}
|
||||
Meta::PageNumbering(_) => {}
|
||||
Meta::Hide => {}
|
||||
},
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::num::NonZeroUsize;
|
||||
use super::{Content, Selector};
|
||||
use crate::diag::StrResult;
|
||||
use crate::doc::{Frame, FrameItem, Meta, Position};
|
||||
use crate::eval::cast_from_value;
|
||||
use crate::eval::{cast_from_value, Value};
|
||||
use crate::geom::{Point, Transform};
|
||||
use crate::model::Label;
|
||||
use crate::util::NonZeroExt;
|
||||
@ -84,12 +84,18 @@ impl StabilityProvider {
|
||||
pub struct Introspector {
|
||||
pages: usize,
|
||||
elems: Vec<(Content, Position)>,
|
||||
// Indexed by page number.
|
||||
page_numberings: Vec<Value>,
|
||||
}
|
||||
|
||||
impl Introspector {
|
||||
/// Create a new introspector.
|
||||
pub fn new(frames: &[Frame]) -> Self {
|
||||
let mut introspector = Self { pages: frames.len(), elems: vec![] };
|
||||
let mut introspector = Self {
|
||||
pages: frames.len(),
|
||||
elems: vec![],
|
||||
page_numberings: vec![],
|
||||
};
|
||||
for (i, frame) in frames.iter().enumerate() {
|
||||
let page = NonZeroUsize::new(1 + i).unwrap();
|
||||
introspector.extract(frame, page, Transform::identity());
|
||||
@ -121,6 +127,9 @@ impl Introspector {
|
||||
let pos = pos.transform(ts);
|
||||
self.elems.push((content.clone(), Position { page, point: pos }));
|
||||
}
|
||||
FrameItem::Meta(Meta::PageNumbering(numbering), _) => {
|
||||
self.page_numberings.push(numbering.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -184,6 +193,12 @@ impl Introspector {
|
||||
self.position(location).page
|
||||
}
|
||||
|
||||
/// Gets the page numbering for the given location, if any.
|
||||
pub fn page_numbering(&self, location: Location) -> Value {
|
||||
let page = self.page(location);
|
||||
self.page_numberings.get(page.get() - 1).cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Find the position for the given location.
|
||||
pub fn position(&self, location: Location) -> Position {
|
||||
self.elems
|
||||
|
Loading…
x
Reference in New Issue
Block a user