Cover repeated DOCX style replacement across saves (#2469)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Fin Warman
2026-10-25 10:43:03 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 0696c55698
commit a5526724aa
2 changed files with 38 additions and 1 deletions
+34
View File
@@ -48,6 +48,40 @@ fn read_body(body: &str) -> Document {
wordcraft_docx::read(&docx(body, &[], &[])).unwrap()
}
#[test]
fn repeated_style_ids_use_last() {
let styles = format!(
r#"<w:styles {W_NS}>
<w:style w:type="paragraph" w:styleId="Repeated"><w:name w:val="First"/>
<w:pPr><w:spacing w:after="240"/></w:pPr><w:rPr><w:b/><w:smallCaps/><w:sz w:val="28"/></w:rPr>
</w:style>
<w:style w:type="paragraph" w:styleId="Repeated"><w:name w:val="Last"/>
<w:pPr><w:spacing w:before="120"/></w:pPr><w:rPr><w:i/><w:caps/><w:sz w:val="20"/></w:rPr>
</w:style></w:styles>"#
);
let bytes = docx(
r#"<w:p><w:pPr><w:pStyle w:val="Repeated"/></w:pPr><w:r><w:t>Original style probe</w:t></w:r></w:p>"#,
&[("styles", "styles", "styles.xml")],
&[("word/styles.xml", &styles)],
);
let mut document = wordcraft_docx::read(&bytes).unwrap();
for round in 0..=2 {
let style = document.styles.get("Repeated").unwrap();
assert_eq!(style.name, "Last");
assert_eq!(style.chr.size, Some(10.0));
assert_eq!(style.chr.italic, Some(true));
assert_eq!(style.chr.bold, None);
assert_eq!(style.chr.caps, Some(true));
assert_eq!(style.chr.small_caps, None);
assert_eq!(style.para.space_before, Some(6.0));
assert_eq!(style.para.space_after, None);
assert_eq!(document.styles.styles.iter().filter(|style| style.id == "Repeated").count(), 1);
if round < 2 {
document = wordcraft_docx::read(&wordcraft_docx::write(&document).unwrap()).unwrap();
}
}
}
#[test]
fn paragraph_default_presence_survives_repeated_saves() {
// Omission leaves paragraph defaults application-defined (ISO 29500 pPrDefault).
File diff suppressed because one or more lines are too long