From f36684bfb07774c11ea0eef4786460f778f59c4b Mon Sep 17 00:00:00 2001 From: Sen-CaPoo Date: Sun, 4 Oct 2026 14:28:45 +0800 Subject: [PATCH 1/2] fix(rust): honor pageBreakBefore on/off value in docx paragraphs Rust docx rendering inserted a page break whenever a paragraph contained a pageBreakBefore element, ignoring w:val="0" or w:val="false". Documents that explicitly disable the property on every paragraph rendered one paragraph per page (Issue79 fixtures produced 20 pages instead of 1). Read only the direct pPr child and gate it on the existing on/off helper, matching the OOXML CT_OnOff semantics implemented by LibreOffice writerfilter and by the .NET DocxReader. Co-Authored-By: Claude Fable 5.1 --- minipdf-rs/crates/minipdf/src/docx.rs | 33 ++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/minipdf-rs/crates/minipdf/src/docx.rs b/minipdf-rs/crates/minipdf/src/docx.rs index ee014ed8..5c7bfaa9 100644 --- a/minipdf-rs/crates/minipdf/src/docx.rs +++ b/minipdf-rs/crates/minipdf/src/docx.rs @@ -679,9 +679,9 @@ fn read_paragraph( relationships: &HashMap, archive: &mut ZipArchive>, ) -> Result<()> { - if paragraph - .descendants() - .any(|node| node.has_tag_name("pageBreakBefore")) + if child(paragraph, "pPr") + .and_then(|properties| child(properties, "pageBreakBefore")) + .is_some_and(property_enabled) { blocks.push(DocxBlock::PageBreak); } @@ -2400,6 +2400,33 @@ mod tests { ); } + #[test] + fn ignores_disabled_page_break_before() { + let input = create_docx( + r#"FirstSecondThirdFourth"#, + ); + + let document = read_docx_document(&input).unwrap(); + + assert_eq!( + document.blocks, + vec![ + DocxBlock::Paragraph(plain_paragraph("First".to_owned())), + DocxBlock::Paragraph(plain_paragraph("Second".to_owned())), + DocxBlock::Paragraph(plain_paragraph("Third".to_owned())), + DocxBlock::PageBreak, + DocxBlock::Paragraph(plain_paragraph("Fourth".to_owned())), + ] + ); + let pdf = convert_docx_bytes(&input, &ConversionOptions::default()).unwrap(); + assert_eq!( + pdf.windows(b"/Type /Page /Parent".len()) + .filter(|chunk| *chunk == b"/Type /Page /Parent") + .count(), + 2 + ); + } + #[test] fn reads_and_renders_basic_table() { let input = create_docx( From c6ae6c8ce25d77c4485cf6673467806ccac6a2ee Mon Sep 17 00:00:00 2001 From: Wei Lin Date: Sun, 4 Oct 2026 21:59:22 +0800 Subject: [PATCH 2/2] test(rust): ignore page break in DOCX change history Cover nested pageBreakBefore in pPrChange so historic properties cannot trigger a live page break. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- minipdf-rs/crates/minipdf/src/docx.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/minipdf-rs/crates/minipdf/src/docx.rs b/minipdf-rs/crates/minipdf/src/docx.rs index 5c7bfaa9..5a8aa2fe 100644 --- a/minipdf-rs/crates/minipdf/src/docx.rs +++ b/minipdf-rs/crates/minipdf/src/docx.rs @@ -2427,6 +2427,23 @@ mod tests { ); } + #[test] + fn ignores_page_break_before_in_change_history() { + let input = create_docx( + r#"FirstSecond"#, + ); + + let document = read_docx_document(&input).unwrap(); + + assert_eq!( + document.blocks, + vec![ + DocxBlock::Paragraph(plain_paragraph("First".to_owned())), + DocxBlock::Paragraph(plain_paragraph("Second".to_owned())), + ] + ); + } + #[test] fn reads_and_renders_basic_table() { let input = create_docx(