//! Compound border lines of thin and thick strokes (`thinThickSmallGap` to //! `thinThickThinLargeGap`, ECMA-376 Part 1 ยง17.18.2 ST_Border) on paragraphs, table cells and //! pages: written back as read, not as a single line. Fixtures are hand-written from the spec. use std::io::{Read, Write}; use craft_wordmodel::props::BorderStyle; const LINES: [(&str, BorderStyle); 9] = [ ("thinThickSmallGap", BorderStyle::ThinThickSmallGap), ("thickThinSmallGap", BorderStyle::ThickThinSmallGap), ("thinThickThinSmallGap", BorderStyle::ThinThickThinSmallGap), ("thinThickMediumGap", BorderStyle::ThinThickMediumGap), ("thickThinMediumGap", BorderStyle::ThickThinMediumGap), ("thinThickThinMediumGap", BorderStyle::ThinThickThinMediumGap), ("thinThickLargeGap", BorderStyle::ThinThickLargeGap), ("thickThinLargeGap", BorderStyle::ThickThinLargeGap), ("thinThickThinLargeGap", BorderStyle::ThinThickThinLargeGap), ]; fn docx(body: &str) -> Vec { let root = r#""#; let doc = format!( r#"{body}"# ); let mut zw = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); for (name, bytes) in [("_rels/.rels", root.as_bytes()), ("word/document.xml", doc.as_bytes())] { zw.start_file(name, zip::write::SimpleFileOptions::default()).unwrap(); zw.write_all(bytes).unwrap(); } zw.finish().unwrap().into_inner() } fn document_xml(bytes: &[u8]) -> String { let mut z = zip::ZipArchive::new(std::io::Cursor::new(bytes)).unwrap(); let mut s = String::new(); z.by_name("word/document.xml").unwrap().read_to_string(&mut s).unwrap(); s } fn side(name: &str, val: &str) -> String { format!(r#""#) } #[test] fn compound_paragraph_borders_are_written_back_as_read() { let body: String = LINES .iter() .map(|(val, _)| { format!(r#"{}{}{val}"#, side("top", val), side("bottom", val)) }) .collect(); let d = craft_docx::read(&docx(&body)).unwrap(); let got: Vec> = d.body.iter().filter_map(|b| b.as_para()).map(|p| p.props.borders.and_then(|b| b.top).map(|t| t.style)).collect(); assert_eq!(got, LINES.iter().map(|(_, s)| Some(*s)).collect::>()); let xml = document_xml(&craft_docx::write(&d).unwrap()); for (val, _) in LINES { assert_eq!(xml.matches(&format!(r#"w:val="{val}""#)).count(), 2, "{val}: {xml}"); } assert!(!xml.contains(r#"w:val="single""#), "{xml}"); } #[test] fn compound_cell_and_page_borders_are_written_back_as_read() { let body = format!( r#"{}{}Cell{}"#, side("top", "thickThinLargeGap"), side("left", "thinThickSmallGap"), side("right", "thinThickThinMediumGap") ); let xml = document_xml(&craft_docx::write(&craft_docx::read(&docx(&body)).unwrap()).unwrap()); for val in ["thickThinLargeGap", "thinThickSmallGap", "thinThickThinMediumGap"] { assert_eq!(xml.matches(&format!(r#"w:val="{val}""#)).count(), 1, "{val}: {xml}"); } }