diff --git a/crates/wordmodel/src/props.rs b/crates/wordmodel/src/props.rs index 38feba083..65a59592c 100644 --- a/crates/wordmodel/src/props.rs +++ b/crates/wordmodel/src/props.rs @@ -93,6 +93,16 @@ mod tests { } } + #[test] + fn explicit_off_values_disable_underline() { + for value in ["off", "false", "0"] { + assert_eq!(Underline::from_ooxml(value), Underline::None, "{value}"); + } + assert_eq!(Underline::from_ooxml("none"), Underline::None); + assert_eq!(Underline::from_ooxml("single"), Underline::Single); + assert_eq!(Underline::from_ooxml("unknown"), Underline::Single); + } + /// The 16 `w14:ligatures` values of [MS-DOCX], each to its flags and back. #[test] fn ligature_names() { diff --git a/crates/wordmodel/src/props/char_props.rs b/crates/wordmodel/src/props/char_props.rs index 3cde0b132..db08ce2fe 100644 --- a/crates/wordmodel/src/props/char_props.rs +++ b/crates/wordmodel/src/props/char_props.rs @@ -51,6 +51,10 @@ impl Underline { } pub fn from_ooxml(s: &str) -> Underline { Underline::ALL.iter().copied().find(|u| u.ooxml() == s).unwrap_or(match s { + // Some Word producers serialize the generic on/off values here, although the + // underline simple type normally uses `none`. Honor an explicit disable rather + // than treating an unrecognized value as the default single underline. + "off" | "false" | "0" => Underline::None, "thickDash" | "dashLong" | "dashedHeavy" | "dashLongHeavy" => Underline::Dash, "dottedHeavy" => Underline::Dotted, "wavyHeavy" => Underline::Wave,