diff --git a/crates/typst-library/src/layout/mod.rs b/crates/typst-library/src/layout/mod.rs index d9e8ec9aa..018cf1a69 100644 --- a/crates/typst-library/src/layout/mod.rs +++ b/crates/typst-library/src/layout/mod.rs @@ -250,7 +250,7 @@ fn realize_root<'a>( let mut builder = Builder::new(vt, scratch, true); builder.accept(content, styles)?; - builder.interrupt_page(Some(styles))?; + builder.interrupt_page(Some(styles), true)?; let (pages, shared) = builder.doc.unwrap().pages.finish(); Ok((DocumentElem::new(pages.to_vec()).pack(), shared)) } @@ -375,7 +375,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { .to::() .map_or(false, |pagebreak| !pagebreak.weak(styles)); - self.interrupt_page(keep.then_some(styles))?; + self.interrupt_page(keep.then_some(styles), false)?; if let Some(doc) = &mut self.doc { if doc.accept(content, styles) { @@ -424,7 +424,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { if self.doc.is_none() { bail!(span, "page configuration is not allowed inside of containers"); } - self.interrupt_page(outer)?; + self.interrupt_page(outer, false)?; } else if local.interruption::().is_some() || local.interruption::().is_some() { @@ -462,10 +462,14 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { Ok(()) } - fn interrupt_page(&mut self, styles: Option>) -> SourceResult<()> { + fn interrupt_page( + &mut self, + styles: Option>, + last: bool, + ) -> SourceResult<()> { self.interrupt_par()?; let Some(doc) = &mut self.doc else { return Ok(()) }; - if !self.flow.0.is_basically_empty() || (doc.keep_next && styles.is_some()) { + if (doc.keep_next && styles.is_some()) || self.flow.0.has_strong_elements(last) { let (flow, shared) = mem::take(&mut self.flow).0.finish(); let styles = if shared == StyleChain::default() { styles.unwrap_or_default() @@ -588,7 +592,7 @@ struct ParBuilder<'a>(BehavedBuilder<'a>); impl<'a> ParBuilder<'a> { fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool { if content.is::() { - if !self.0.is_basically_empty() { + if self.0.has_strong_elements(false) { self.0.push(content.clone(), styles); return true; } diff --git a/crates/typst-library/src/shared/behave.rs b/crates/typst-library/src/shared/behave.rs index 471daa189..ed7a2593b 100644 --- a/crates/typst-library/src/shared/behave.rs +++ b/crates/typst-library/src/shared/behave.rs @@ -32,10 +32,11 @@ impl<'a> BehavedBuilder<'a> { /// Whether the builder is empty except for some weak elements that will /// probably collapse. - pub fn is_basically_empty(&self) -> bool { - self.builder.is_empty() - && self.staged.iter().all(|(_, behaviour, _)| { - matches!(behaviour, Behaviour::Weak(_) | Behaviour::Invisible) + pub fn has_strong_elements(&self, last: bool) -> bool { + !self.builder.is_empty() + || self.staged.iter().any(|(_, behaviour, _)| { + !matches!(behaviour, Behaviour::Weak(_) | Behaviour::Invisible) + || (last && *behaviour == Behaviour::Invisible) }) } diff --git a/tests/ref/bugs/pagebreak-bibliography.png b/tests/ref/bugs/pagebreak-bibliography.png new file mode 100644 index 000000000..43de15744 Binary files /dev/null and b/tests/ref/bugs/pagebreak-bibliography.png differ diff --git a/tests/typ/bugs/pagebreak-bibliography.typ b/tests/typ/bugs/pagebreak-bibliography.typ new file mode 100644 index 000000000..bfc782501 --- /dev/null +++ b/tests/typ/bugs/pagebreak-bibliography.typ @@ -0,0 +1,5 @@ +// Test weak pagebreak before bibliography. + +--- +#pagebreak(weak: true) +#bibliography("/files/works.bib")