From 07c972a73ec5101fb36c437a0ce54e35055470da Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Sat, 24 May 2025 04:30:43 -0300 Subject: [PATCH] fix short lived headers with gutter We were checking after instead of before fixing up header indices due to gutter. --- .../typst-library/src/layout/grid/resolve.rs | 41 ++++++++++-------- ...alone-with-gutter-no-orphan-prevention.png | Bin 0 -> 254 bytes tests/suite/layout/grid/subheaders.typ | 16 +++++++ 3 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 tests/ref/grid-subheaders-alone-with-gutter-no-orphan-prevention.png diff --git a/crates/typst-library/src/layout/grid/resolve.rs b/crates/typst-library/src/layout/grid/resolve.rs index a8b5a2c9c..d659702fe 100644 --- a/crates/typst-library/src/layout/grid/resolve.rs +++ b/crates/typst-library/src/layout/grid/resolve.rs @@ -1827,6 +1827,28 @@ impl<'x> CellGridResolver<'_, '_, 'x> { row_amount: usize, at_least_one_cell: bool, ) -> SourceResult>> { + // Mark consecutive headers right before the end of the table, or the + // final footer, as short lived, given that there are no normal rows + // after them, so repeating them is pointless. + // + // It is important to do this BEFORE we update header and footer ranges + // due to gutter below as 'row_amount' doesn't consider gutter. + // + // TODO(subfooters): take the last footer if it is at the end and + // backtrack through consecutive footers until the first one in the + // sequence is found. If there is no footer at the end, there are no + // haeders to turn short-lived. + let mut consecutive_header_start = + footer.as_ref().map(|(_, _, f)| f.start).unwrap_or(row_amount); + for header_at_the_end in headers.iter_mut().rev().take_while(move |h| { + let at_the_end = h.end == consecutive_header_start; + + consecutive_header_start = h.start; + at_the_end + }) { + header_at_the_end.unwrap_mut().short_lived = true; + } + // Repeat the gutter below a header (hence why we don't // subtract 1 from the gutter case). // Don't do this if there are no rows under the header. @@ -1917,25 +1939,6 @@ impl<'x> CellGridResolver<'_, '_, 'x> { } }); - // Mark consecutive headers right before the end of the table, or the - // final footer, as short lived, given that there are no normal rows - // after them, so repeating them is pointless. - // - // TODO(subfooters): take the last footer if it is at the end and - // backtrack through consecutive footers until the first one in the - // sequence is found. If there is no footer at the end, there are no - // haeders to turn short-lived. - let mut consecutive_header_start = - footer.as_ref().map(|f| f.start).unwrap_or(row_amount); - for header_at_the_end in headers.iter_mut().rev().take_while(move |h| { - let at_the_end = h.end == consecutive_header_start; - - consecutive_header_start = h.start; - at_the_end - }) { - header_at_the_end.unwrap_mut().short_lived = true; - } - Ok(footer) } diff --git a/tests/ref/grid-subheaders-alone-with-gutter-no-orphan-prevention.png b/tests/ref/grid-subheaders-alone-with-gutter-no-orphan-prevention.png new file mode 100644 index 0000000000000000000000000000000000000000..17bf3fe4f5ff3f740c0251c94b008db961dde494 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^6+oQL0VEh^`bt^@siU4Qjv*Dd-rg|eI^-bYdQsTjvu%utTLj)*j)>gF?s!4Xdc&n-PB|t^Z)m(?YVnLS6MQ!L$v)mWNe>R+@o?*I zXhZ_pjQLg8p1bOt4!`mWy0xFRoqf`hANRC=