diff --git a/crates/typst-library/src/layout/mod.rs b/crates/typst-library/src/layout/mod.rs index ce728ccb7..3334d5aa3 100644 --- a/crates/typst-library/src/layout/mod.rs +++ b/crates/typst-library/src/layout/mod.rs @@ -467,7 +467,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { fn interrupt_page(&mut self, styles: Option>) -> SourceResult<()> { self.interrupt_par()?; let Some(doc) = &mut self.doc else { return Ok(()) }; - if !self.flow.0.is_empty() || (doc.keep_next && styles.is_some()) { + if !self.flow.0.is_basically_empty() || (doc.keep_next && styles.is_some()) { let (flow, shared) = mem::take(&mut self.flow).0.finish(); let styles = if shared == StyleChain::default() { styles.unwrap_or_default() diff --git a/crates/typst-library/src/layout/spacing.rs b/crates/typst-library/src/layout/spacing.rs index 950f024f8..69a5d952a 100644 --- a/crates/typst-library/src/layout/spacing.rs +++ b/crates/typst-library/src/layout/spacing.rs @@ -63,7 +63,7 @@ impl Behave for HElem { } else if self.weak(StyleChain::default()) { Behaviour::Weak(1) } else { - Behaviour::Ignorant + Behaviour::Invisible } } @@ -158,7 +158,7 @@ impl Behave for VElem { } else if self.weakness(StyleChain::default()) > 0 { Behaviour::Weak(self.weakness(StyleChain::default())) } else { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst-library/src/meta/metadata.rs b/crates/typst-library/src/meta/metadata.rs index ed0d19864..89d1409a9 100644 --- a/crates/typst-library/src/meta/metadata.rs +++ b/crates/typst-library/src/meta/metadata.rs @@ -38,6 +38,6 @@ impl Show for MetadataElem { impl Behave for MetadataElem { fn behaviour(&self) -> Behaviour { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst-library/src/shared/behave.rs b/crates/typst-library/src/shared/behave.rs index 6a1aa1274..471daa189 100644 --- a/crates/typst-library/src/shared/behave.rs +++ b/crates/typst-library/src/shared/behave.rs @@ -34,10 +34,9 @@ impl<'a> BehavedBuilder<'a> { /// probably collapse. pub fn is_basically_empty(&self) -> bool { self.builder.is_empty() - && self - .staged - .iter() - .all(|(_, behaviour, _)| matches!(behaviour, Behaviour::Weak(_))) + && self.staged.iter().all(|(_, behaviour, _)| { + matches!(behaviour, Behaviour::Weak(_) | Behaviour::Invisible) + }) } /// Push an item into the sequence. @@ -74,7 +73,7 @@ impl<'a> BehavedBuilder<'a> { self.builder.push(elem, styles); self.last = interaction; } - Behaviour::Ignorant => { + Behaviour::Ignorant | Behaviour::Invisible => { self.staged.push((elem, interaction, styles)); } } @@ -95,7 +94,10 @@ impl<'a> BehavedBuilder<'a> { /// false. fn flush(&mut self, supportive: bool) { for (item, interaction, styles) in self.staged.drain(..) { - if supportive || interaction == Behaviour::Ignorant { + if supportive + || interaction == Behaviour::Ignorant + || interaction == Behaviour::Invisible + { self.builder.push(item, styles); } } diff --git a/crates/typst/src/model/content.rs b/crates/typst/src/model/content.rs index f1600f251..6541ab6b4 100644 --- a/crates/typst/src/model/content.rs +++ b/crates/typst/src/model/content.rs @@ -610,7 +610,7 @@ pub struct MetaElem { impl Behave for MetaElem { fn behaviour(&self) -> Behaviour { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst/src/model/realize.rs b/crates/typst/src/model/realize.rs index 01c46b818..3e683d3e6 100644 --- a/crates/typst/src/model/realize.rs +++ b/crates/typst/src/model/realize.rs @@ -214,8 +214,10 @@ pub enum Behaviour { /// An element that destroys adjacent weak elements. Destructive, /// An element that does not interact at all with other elements, having the - /// same effect as if it didn't exist. + /// same effect as if it didn't exist, but has a visual representation. Ignorant, + /// An element that does not have a visual representation. + Invisible, } /// Guards content against being affected by the same show rule multiple times. diff --git a/tests/ref/layout/pagebreak-empty.png b/tests/ref/layout/pagebreak-empty.png new file mode 100644 index 000000000..412c4e8d6 Binary files /dev/null and b/tests/ref/layout/pagebreak-empty.png differ diff --git a/tests/typ/layout/pagebreak-empty.typ b/tests/typ/layout/pagebreak-empty.typ new file mode 100644 index 000000000..c228959e7 --- /dev/null +++ b/tests/typ/layout/pagebreak-empty.typ @@ -0,0 +1,30 @@ +// Test page breaks on basically empty pages. + +--- +// After place +// Should result in three pages. +First +#pagebreak(weak: true) +#place(right)[placed A] +#pagebreak(weak: true) +Third + +--- +// After only ignorables & invisibles +// Should result in two pages. +First +#pagebreak(weak: true) +#counter(page).update(1) +#metadata("Some") +#pagebreak(weak: true) +Second + +--- +// After only ignorables, but regular break +// Should result in three pages. +First +#pagebreak() +#counter(page).update(1) +#metadata("Some") +#pagebreak() +Third