From 8711f5cfd1e6a30a79a67b91fcebcbc325108425 Mon Sep 17 00:00:00 2001 From: Divyanshu Gupta Date: Fri, 16 Oct 2026 03:05:52 +0530 Subject: [PATCH] fix(docx): inspect textbox style for v-text-anchor and handle case-insensitivity --- crates/docx/src/read/story.rs | 16 ++++++++++------ crates/docx/tests/fixtures.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/crates/docx/src/read/story.rs b/crates/docx/src/read/story.rs index 9a39f6406..39617bd36 100644 --- a/crates/docx/src/read/story.rs +++ b/crates/docx/src/read/story.rs @@ -1437,14 +1437,18 @@ impl Reader<'_> { } part.body.inset = (inset != wordcraft_doc::TEXT_BOX_INSET).then_some(inset); // Resize shape to fit text (DrawingML's `a:spAutoFit`). - let fit = vml_style(tb.attr("style").unwrap_or(""), "mso-fit-shape-to-text"); + let fit = vml_style(tb.attr("style").unwrap_or(""), "mso-fit-shape-to-text") + .or_else(|| vml_style(style, "mso-fit-shape-to-text")); part.body.auto_fit = fit.is_some_and(|v| v.eq_ignore_ascii_case("t") || v.eq_ignore_ascii_case("true")); // Where the text sits between the box's top and bottom (DrawingML's `anchor`). - if let Some(a) = vml_style(style, "v-text-anchor") { - part.body.anchor = match a { - a if a.starts_with("middle") => wordcraft_doc::props::VAlign::Center, - a if a.starts_with("bottom") => wordcraft_doc::props::VAlign::Bottom, - _ => wordcraft_doc::props::VAlign::Top, + if let Some(a) = vml_style(tb.attr("style").unwrap_or(""), "v-text-anchor").or_else(|| vml_style(style, "v-text-anchor")) { + let al = a.trim().to_ascii_lowercase(); + part.body.anchor = if al.starts_with("middle") || al == "center" { + wordcraft_doc::props::VAlign::Center + } else if al.starts_with("bottom") { + wordcraft_doc::props::VAlign::Bottom + } else { + wordcraft_doc::props::VAlign::Top }; } } diff --git a/crates/docx/tests/fixtures.rs b/crates/docx/tests/fixtures.rs index 2c36a3bb4..96cbcba62 100644 --- a/crates/docx/tests/fixtures.rs +++ b/crates/docx/tests/fixtures.rs @@ -2830,3 +2830,29 @@ fn row_table_borders_round_trip() { let again = wordcraft_docx::read(&saved).unwrap(); assert_eq!(d.body, again.body); } + +#[test] +fn vml_textbox_style_anchor_and_fit() { + let body = r#" + + + + + + Centered text + + + + + + "#; + let doc = wordcraft_docx::read(&docx(body, &[], &[])).unwrap(); + let p = doc.body.first().unwrap().as_para().unwrap(); + let story_id = match p.objects.first() { + Some(InlineObject::Shape { story: Some(id), .. }) => *id, + o => panic!("expected shape with story, got {o:?}"), + }; + let tb = doc.parts.get(&story_id).unwrap(); + assert_eq!(tb.body.anchor, wordcraft_doc::props::VAlign::Center); + assert!(tb.body.auto_fit); +}