diff --git a/ROADMAP.md b/ROADMAP.md index d60a6bf49..d1c2872e0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -347,6 +347,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m Newest first. +- **2026-10-15** · In a facing-pages document, two odd-numbered pages in a row after a section restart (page 2 starting at 1) each get their own spread and stay right pages, instead of sharing a spread with an odd page on the left. No readiness percentage change. - **2026-10-14** · The Type tool draws a new text frame over a locked empty frame, as InDesign does, instead of turning the locked frame into a text frame. No readiness percentage change. - **2026-10-14** · 100% black shows as pure black on screen by default, as InDesign's Appearance of Black does out of the box (Display All Blacks as Rich Black); Preferences › Appearance of Black › Display All Blacks Accurately still shows it as the dark grey it prints, and a saved choice is kept. No readiness percentage change. - **2026-10-14** · Pathfinder keeps the frontmost object, as InDesign does: a photo placed over shapes and intersected with them shows through the shapes (it was dropped, and the shapes kept their black fill); Add, Exclude Overlap and Minus Back take the front object's fill too, Subtract still keeps the back one. No readiness percentage change. diff --git a/crates/doc/src/build.rs b/crates/doc/src/build.rs index 9fb075553..aa6cebac7 100644 --- a/crates/doc/src/build.rs +++ b/crates/doc/src/build.rs @@ -346,7 +346,10 @@ impl Document { let odd = parity.get(i).copied().unwrap_or(i % 2 == 0); p.side = if odd != rtl { PageSide::Right } else { PageSide::Left }; let starts = if rtl { PageSide::Right } else { PageSide::Left }; - if p.side == starts && !cur.is_empty() { + // A right page closes its spread, so two right pages in a row (a section restart + // at an even position) never share one. + let after_ending = cur.last().is_some_and(|(q, _)| q.side != starts); + if (p.side == starts || after_ending) && !cur.is_empty() { let id = SpreadId(self.alloc()); flush(&mut cur, &mut spreads, id); } diff --git a/crates/doc/src/tests.rs b/crates/doc/src/tests.rs index 8af281d3b..a602cca25 100644 --- a/crates/doc/src/tests.rs +++ b/crates/doc/src/tests.rs @@ -262,6 +262,29 @@ fn page_names_follow_sections() { assert_eq!(d.page_name(5), "4"); } +/// A section restarting at 1 on page 2 leaves two odd (right) pages in a row; each gets its own +/// spread instead of sharing one with the odd page on the left. +#[test] +fn consecutive_right_pages_get_separate_spreads() { + let mut d = Document::new(&NewDocument { pages: 4, ..Default::default() }); + d.sections.push(Section { + start: 1, + start_number: Some(1), + style: NumberStyle::Arabic, + prefix: String::new(), + marker: String::new(), + include_prefix: false, + }); + d.repaginate(); + let sides: Vec> = d.spreads.iter().map(|s| s.pages.iter().map(|p| p.side).collect()).collect(); + assert_eq!(sides, vec![vec![PageSide::Right], vec![PageSide::Right], vec![PageSide::Left, PageSide::Right]]); + let flat: Vec = sides.into_iter().flatten().collect(); + for (i, side) in flat.iter().enumerate() { + assert_eq!(*side == PageSide::Right, d.page_number(i) % 2 == 1, "page {i}"); + } + d.check().unwrap(); +} + #[test] fn document_serde_roundtrip() { let mut d = doc();