//! Paragraph indents and spacing written as plain twips beyond 16 bits: Word keeps only the low //! 16 bits (ECMA-376 Part 1 §17.3.1.12 `w:ind`, §17.3.1.33 `w:spacing`). Measured in Word: a //! `w:left` of 66256 starts the text 36 pt in, a `w:right` of 66976 leaves a 72 pt right indent. //! Fixtures are hand-written. use craft_wordmodel::Document; use craft_wordmodel::props::ParaProps; use crate::fixtures::zip; /// A package whose body is `body`. fn docx(body: &str) -> Vec { let root = r#""#; let doc = format!( r#"{body}"# ); zip(&[("_rels/.rels", root.as_bytes()), ("word/document.xml", doc.as_bytes())]) } fn props(body: &str) -> Vec { let d: Document = craft_docx::read(&docx(body)).unwrap(); d.body.iter().filter_map(|b| b.as_para()).map(|p| p.props.clone()).collect() } #[test] fn indents_beyond_16_bits_wrap() { let p = props( r#"a b c d"#, ); assert_eq!(p[0].indent_left, Some(36.0)); assert_eq!(p[1].indent_right, Some(72.0)); // 65556 -> 20 twips; -65516 -> 20 twips. assert_eq!((p[2].indent_left, p[2].indent_right), (Some(1.0), Some(1.0))); // 98304 = 0x18000 -> 0x8000 = -32768 as a signed 16-bit value; hanging 65896 -> 360. assert_eq!((p[3].indent_left, p[3].indent_first), (Some(-1638.4), Some(-18.0))); } #[test] fn spacing_beyond_16_bits_wraps() { let p = props(r#"a"#); assert_eq!((p[0].space_before, p[0].space_after), (Some(0.05), Some(12.0))); } #[test] fn in_range_and_unit_values_are_unchanged() { let p = props( r#"a b"#, ); assert_eq!((p[0].indent_left, p[0].indent_right, p[0].space_before), (Some(1638.35), Some(-1638.4), Some(3276.75))); assert_eq!((p[1].indent_left, p[1].indent_right, p[1].space_before), (Some(72.0), Some(36.0), Some(12.0))); }