diff --git a/crates/typst/src/layout/page.rs b/crates/typst/src/layout/page.rs index f62218873..c354dc81a 100644 --- a/crates/typst/src/layout/page.rs +++ b/crates/typst/src/layout/page.rs @@ -228,6 +228,11 @@ pub struct PageElem { /// The page's header. Fills the top margin of each page. /// + /// - Content: Shows the content as the header. + /// - `{auto}`: Shows the page number if a `numbering` is set and + /// `number-align` is `top`. + /// - `{none}`: Suppresses the header. + /// /// ```example /// #set par(justify: true) /// #set page( @@ -242,7 +247,7 @@ pub struct PageElem { /// #lorem(19) /// ``` #[borrowed] - pub header: Option, + pub header: Smart>, /// The amount the header is raised into the top margin. #[resolve] @@ -251,8 +256,13 @@ pub struct PageElem { /// The page's footer. Fills the bottom margin of each page. /// - /// For just a page number, the `numbering` property, typically suffices. If - /// you want to create a custom footer, but still display the page number, + /// - Content: Shows the content as the footer. + /// - `{auto}`: Shows the page number if a `numbering` is set and + /// `number-align` is `bottom`. + /// - `{none}`: Suppresses the footer. + /// + /// For just a page number, the `numbering` property typically suffices. If + /// you want to create a custom footer but still display the page number, /// you can directly access the [page counter]($counter). /// /// ```example @@ -273,7 +283,7 @@ pub struct PageElem { /// #lorem(48) /// ``` #[borrowed] - pub footer: Option, + pub footer: Smart>, /// The amount the footer is lowered into the bottom margin. #[resolve] @@ -402,17 +412,15 @@ impl Packed { } let fill = self.fill(styles); - let foreground = Cow::Borrowed(self.foreground(styles)); - let background = Cow::Borrowed(self.background(styles)); + let foreground = self.foreground(styles); + let background = self.background(styles); let header_ascent = self.header_ascent(styles); let footer_descent = self.footer_descent(styles); let numbering = self.numbering(styles); let number_align = self.number_align(styles); - let mut header = Cow::Borrowed(self.header(styles)); - let mut footer = Cow::Borrowed(self.footer(styles)); // Construct the numbering (for header or footer). - let numbering_marginal = Cow::Owned(numbering.as_ref().map(|numbering| { + let numbering_marginal = numbering.as_ref().map(|numbering| { let both = match numbering { Numbering::Pattern(pattern) => pattern.pieces() >= 2, Numbering::Func(_) => true, @@ -433,13 +441,21 @@ impl Packed { } counter - })); + }); - if matches!(number_align.y(), Some(OuterVAlignment::Top)) { - header = if header.is_some() { header } else { numbering_marginal }; + let header = self.header(styles); + let footer = self.footer(styles); + let (header, footer) = if matches!(number_align.y(), Some(OuterVAlignment::Top)) { + ( + header.as_ref().unwrap_or(&numbering_marginal), + footer.as_ref().unwrap_or(&None), + ) } else { - footer = if footer.is_some() { footer } else { numbering_marginal }; - } + ( + header.as_ref().unwrap_or(&None), + footer.as_ref().unwrap_or(&numbering_marginal), + ) + }; // Post-process pages. let mut pages = Vec::with_capacity(frames.len()); @@ -463,16 +479,16 @@ impl Packed { let size = frame.size(); // Realize overlays. - for marginal in [&header, &footer, &background, &foreground] { - let Some(content) = &**marginal else { continue }; + for marginal in [header, footer, background, foreground] { + let Some(content) = marginal.as_ref() else { continue }; let (pos, area, align); - if ptr::eq(marginal, &header) { + if ptr::eq(marginal, header) { let ascent = header_ascent.relative_to(margin.top); pos = Point::with_x(margin.left); area = Size::new(pw, margin.top - ascent); align = Alignment::BOTTOM; - } else if ptr::eq(marginal, &footer) { + } else if ptr::eq(marginal, footer) { let descent = footer_descent.relative_to(margin.bottom); pos = Point::new(margin.left, size.y - margin.bottom + descent); area = Size::new(pw, margin.bottom - descent); @@ -490,7 +506,7 @@ impl Packed { .layout(engine, styles, pod)? .into_frame(); - if ptr::eq(marginal, &header) || ptr::eq(marginal, &background) { + if ptr::eq(marginal, header) || ptr::eq(marginal, background) { frame.prepend_frame(pos, sub); } else { frame.push_frame(pos, sub); diff --git a/tests/ref/page-suppress-headers-and-footers.png b/tests/ref/page-suppress-headers-and-footers.png new file mode 100644 index 000000000..6ce4f7214 Binary files /dev/null and b/tests/ref/page-suppress-headers-and-footers.png differ diff --git a/tests/suite/layout/page.typ b/tests/suite/layout/page.typ index a529b4297..e881bc470 100644 --- a/tests/suite/layout/page.typ +++ b/tests/suite/layout/page.typ @@ -229,3 +229,12 @@ The END. #pagebreak() #counter(page).update(53) #filler + +--- page-suppress-headers-and-footers --- +#set page(header: none, footer: none, numbering: "1") +Look, ma, no page numbers! + +#pagebreak() + +#set page(header: auto, footer: auto) +Default page numbers now.