use std::num::NonZeroUsize; use krilla::page::{NumberingStyle, PageLabel}; use typst_library::model::Numbering; pub(crate) trait PageLabelExt { /// Create a new `PageLabel` from a `Numbering` applied to a page /// number. fn generate(numbering: &Numbering, number: u64) -> Option; /// Creates an arabic page label with the specified page number. /// For example, this will display page label `11` when given the page /// number 11. fn arabic(number: u64) -> PageLabel; } impl PageLabelExt for PageLabel { fn generate(numbering: &Numbering, number: u64) -> Option { { let Numbering::Pattern(pat) = numbering else { return None; }; let (prefix, kind) = pat.pieces.first()?; // If there is a suffix, we cannot use the common style optimisation, // since PDF does not provide a suffix field. let style = if pat.suffix.is_empty() { use krilla::page::NumberingStyle as Style; use typst_library::model::NumberingKind as Kind; match kind { Kind::Arabic => Some(Style::Arabic), Kind::LowerRoman => Some(Style::LowerRoman), Kind::UpperRoman => Some(Style::UpperRoman), Kind::LowerLatin if number <= 26 => Some(Style::LowerAlpha), Kind::LowerLatin if number <= 26 => Some(Style::UpperAlpha), _ => None, } } else { None }; // Prefix and offset depend on the style: If it is supported by the PDF // spec, we use the given prefix and an offset. Otherwise, everything // goes into prefix. let prefix = if style.is_none() { Some(pat.apply(&[number])) } else { (!prefix.is_empty()).then(|| prefix.clone()) }; let offset = style.and(number.try_into().ok().and_then(NonZeroUsize::new)); Some(PageLabel::new(style, prefix.map(|s| s.to_string()), offset)) } } fn arabic(number: u64) -> PageLabel { PageLabel::new( Some(NumberingStyle::Arabic), None, number.try_into().ok().and_then(NonZeroUsize::new), ) } }