use super::XMLBuilder; use super::XmlEvent; use crate::types::line_spacing_type::LineSpacingType; use crate::types::*; const EXPECT_MESSAGE: &str = "should write buf"; impl XMLBuilder { // i.e. open!(open_body, "w:body"); // i.e. closed_with_str!(based_on, "w:basedOn"); // i.e. pub(crate) fn text(mut self, text: &str, preserve_space: bool) -> Self { let space = if preserve_space { "preserve" } else { "default" }; self.writer .write(XmlEvent::start_element("w:t").attr("xml:space", space)) .expect(EXPECT_MESSAGE); self.writer.write(text).expect(EXPECT_MESSAGE); self.close() } pub(crate) fn run_fonts( mut self, ascii: Option<&String>, hi_ansi: Option<&String>, cs: Option<&String>, east_asia: Option<&String>, ) -> Self { let mut w = XmlEvent::start_element("w:rFonts"); if let Some(ascii) = ascii { w = w.attr("w:ascii", ascii); } if let Some(hi_ansi) = hi_ansi { w = w.attr("w:hAnsi", hi_ansi); } if let Some(cs) = cs { w = w.attr("w:cs", cs); } if let Some(east_asia) = east_asia { w = w.attr("w:eastAsia", east_asia); } self.writer.write(w).expect(EXPECT_MESSAGE); self.close() } // i.e. pub(crate) fn delete_text(mut self, text: &str, preserve_space: bool) -> Self { let space = if preserve_space { "preserve" } else { "default" }; self.writer .write(XmlEvent::start_element("w:delText").attr("xml:space", space)) .expect(EXPECT_MESSAGE); self.writer.write(text).expect(EXPECT_MESSAGE); self.close() } pub(crate) fn data_binding( mut self, xpath: Option<&String>, prefix_mappings: Option<&String>, store_item_id: Option<&String>, ) -> Self { let mut e = XmlEvent::start_element("w:dataBinding"); if let Some(xpath) = xpath { e = e.attr("w:xpath", xpath); } if let Some(prefix_mappings) = prefix_mappings { e = e.attr("w:prefixMappings", prefix_mappings); } if let Some(store_item_id) = store_item_id { e = e.attr("w:storeItemID", store_item_id); } self.writer.write(e).expect(EXPECT_MESSAGE); self.close() } // i.e. open!(open_run, "w:r"); open!(open_run_property, "w:rPr"); open!(open_run_property_default, "w:rPrDefault"); // i.e. closed!(q_format, "w:qFormat"); // i.e. // open!(open_paragraph, "w:p"); open!(open_paragraph, "w:p", "w14:paraId"); open!(open_paragraph_property, "w:pPr"); open!(open_doc_defaults, "w:docDefaults"); open!(open_structured_tag, "w:sdt"); open!(open_structured_tag_content, "w:sdtContent"); open!(open_structured_tag_property, "w:sdtPr"); // i.e. closed_with_usize!(outline_lvl, "w:outlineLvl"); // i.e. closed_with_str!(name, "w:name"); // i.e. closed_with_str!(justification, "w:jc"); // i.e. closed_with_str!(vert_align, "w:vertAlign"); // i.e. closed_with_str!(paragraph_style, "w:pStyle"); // i.e. closed_with_usize!(sz, "w:sz"); // i.e. closed_with_usize!(sz_cs, "w:szCs"); closed!(field_character, "w:fldChar", "w:fldCharType", "w:dirty"); open!(open_instr_text, "w:instrText"); closed_with_str!(text_direction, "w:textDirection"); closed!(b, "w:b"); closed!(b_cs, "w:bCs"); closed!(i, "w:i"); closed!(i_cs, "w:iCs"); // Build w:style element // i.e. pub(crate) fn open_style(mut self, style_type: StyleType, id: &str) -> Self { self.writer .write( XmlEvent::start_element("w:style") .attr("w:type", &style_type.to_string()) .attr("w:styleId", id), ) .expect(EXPECT_MESSAGE); self } // i.e. closed_with_str!(next, "w:next"); // i.e. closed_with_str!(color, "w:color"); // i.e. closed_with_str!(highlight, "w:highlight"); // i.e. closed_with_str!(underline, "w:u"); closed_with_str!(suffix, "w:suff"); // i.e. pub(crate) fn indent( mut self, start: Option, special_indent: Option, end: i32, start_chars: Option, ) -> Self { let start = &format!("{}", start.unwrap_or(0)); let end = &format!("{}", end); let start_chars_value = format!("{}", start_chars.unwrap_or(0)); let mut base = XmlEvent::start_element("w:ind") .attr("w:left", start) .attr("w:right", end); if start_chars.is_some() { base = base.attr("w:leftChars", &start_chars_value); } match special_indent { Some(SpecialIndentType::FirstLine(v)) => self .writer .write(base.attr("w:firstLine", &format!("{}", v))) .expect(EXPECT_MESSAGE), Some(SpecialIndentType::Hanging(v)) => self .writer .write(base.attr("w:hanging", &format!("{}", v))) .expect(EXPECT_MESSAGE), _ => self.writer.write(base).expect(EXPECT_MESSAGE), }; self.close() } // i.e. pub(crate) fn spacing(mut self, s: i32) -> Self { self.writer .write(XmlEvent::start_element("w:spacing").attr("w:val", &format!("{}", s))) .expect(EXPECT_MESSAGE); self.close() } // i.e. pub(crate) fn line_spacing( mut self, before: Option, after: Option, line: Option, before_lines: Option, after_lines: Option, spacing: Option, ) -> Self { let mut xml_event = XmlEvent::start_element("w:spacing"); let before_val: String; let after_val: String; let before_lines_val: String; let after_lines_val: String; let line_val: String; if let Some(before) = before { before_val = format!("{}", before); xml_event = xml_event.attr("w:before", &before_val) } if let Some(after) = after { after_val = format!("{}", after); xml_event = xml_event.attr("w:after", &after_val) } if let Some(before_lines) = before_lines { before_lines_val = format!("{}", before_lines); xml_event = xml_event.attr("w:beforeLines", &before_lines_val) } if let Some(after_lines) = after_lines { after_lines_val = format!("{}", after_lines); xml_event = xml_event.attr("w:afterLines", &after_lines_val) } if let Some(line) = line { line_val = format!("{}", line); xml_event = xml_event.attr("w:line", &line_val) } if let Some(spacing_type) = spacing { match spacing_type { LineSpacingType::Auto => { xml_event = xml_event.attr("w:lineRule", "auto"); } LineSpacingType::AtLeast => { xml_event = xml_event.attr("w:lineRule", "atLeast"); } LineSpacingType::Exact => { xml_event = xml_event.attr("w:lineRule", "exact"); } } } self.writer.write(xml_event).expect(EXPECT_MESSAGE); self.close() } // // Table elements // open!(open_table, "w:tbl"); open!(open_table_property, "w:tblPr"); open!(open_table_grid, "w:tblGrid"); open!(open_table_row, "w:tr"); open!(open_table_row_property, "w:trPr"); open!(open_table_cell, "w:tc"); open!(open_table_cell_property, "w:tcPr"); open!(open_table_cell_borders, "w:tcBorders"); open!(open_table_borders, "w:tblBorders"); open!(open_table_cell_margins, "w:tblCellMar"); closed!(table_layout, "w:tblLayout", "w:type"); closed_with_str!(table_style, "w:tblStyle"); closed_w_with_type_el!(table_width, "w:tblW"); closed_w_with_type_el!(table_indent, "w:tblInd"); closed_w_with_type_el!(grid_column, "w:gridCol"); closed_w_with_type_el!(table_cell_width, "w:tcW"); closed!(table_row_height, "w:trHeight", "w:val", "w:hRule"); closed_with_usize!(grid_span, "w:gridSpan"); closed_with_str!(vertical_merge, "w:vMerge"); closed_with_str!(vertical_align, "w:vAlign"); closed_w_with_type_el!(margin_top, "w:top"); closed_w_with_type_el!(margin_left, "w:left"); closed_w_with_type_el!(margin_bottom, "w:bottom"); closed_w_with_type_el!(margin_right, "w:right"); closed_border_el!(border_top, "w:top"); closed_border_el!(border_left, "w:left"); closed_border_el!(border_bottom, "w:bottom"); closed_border_el!(border_right, "w:right"); closed_border_el!(border_inside_h, "w:insideH"); closed_border_el!(border_inside_v, "w:insideV"); closed_border_el!(border_tl2br, "w:tl2br"); closed_border_el!(border_tr2bl, "w:tr2bl"); closed_border_el!(text_border, "w:bdr"); closed!(shd, "w:shd", "w:val", "w:color", "w:fill"); closed!(tab, "w:tab"); closed!(tab_with_pos, "w:tab", "w:val", "w:pos"); closed!(br, "w:br", "w:type"); closed!(zoom, "w:zoom", "w:percent"); closed_with_usize!(default_tab_stop, "w:defaultTabStop"); open!(open_font, "w:font", "w:name"); closed_with_str!(pitch, "w:pitch"); closed_with_str!(family, "w:family"); closed_with_str!(charset, "w:charset"); open!(open_section_property, "w:sectPr"); closed!(header_reference, "w:headerReference", "w:type", "r:id"); closed!(footer_reference, "w:footerReference", "w:type", "r:id"); closed_with_str!(type_tag, "w:type"); closed!(title_pg, "w:titlePg"); closed!(even_and_odd_headers, "w:evenAndOddHeaders"); closed!(page_size, "w:pgSz", "w:w", "w:h"); closed!(page_size_with_orient, "w:pgSz", "w:w", "w:h", "w:orient"); closed!( page_margin, "w:pgMar", "w:top", "w:right", "w:bottom", "w:left", "w:header", "w:footer", "w:gutter" ); closed!(columns, "w:cols", "w:space"); closed!(document_grid, "w:docGrid", "w:type", "w:linePitch"); open!(open_insert, "w:ins", "w:id", "w:author", "w:date"); open!(open_delete, "w:del", "w:id", "w:author", "w:date"); closed!(bookmark_start, "w:bookmarkStart", "w:id", "w:name"); closed!(bookmark_end, "w:bookmarkEnd", "w:id"); closed!(comment_range_start, "w:commentRangeStart", "w:id"); closed!(comment_range_end, "w:commentRangeEnd", "w:id"); closed!(comment_reference, "w:commentReference", "w:id"); open!( open_comment, "w:comment", "w:id", "w:author", "w:date", "w:initials" ); open!(open_abstract_num, "w:abstractNum", "w:abstractNumId"); open!(open_level, "w:lvl", "w:ilvl"); open!(open_tabs, "w:tabs"); open!(open_num, "w:num", "w:numId"); open!(open_numbering_property, "w:numPr"); closed_with_usize!(indent_level, "w:ilvl"); closed_with_usize!(num_id, "w:numId"); closed_with_usize!(start, "w:start"); closed_with_str!(number_format, "w:numFmt"); closed_with_str!(level_text, "w:lvlText"); closed_with_str!(level_restart, "w:lvlRestart"); closed_with_str!(level_justification, "w:lvlJc"); closed_with_str!(abstract_num_id, "w:abstractNumId"); closed!(vanish, "w:vanish"); open!(open_drawing, "w:drawing"); open!(open_anchor, "wp:anchor"); open!(open_graphic, "a:graphic", "xmlns:a"); open!(open_graphic_data, "a:graphicData", "uri"); // shape open!(open_wp_shape, "wps:wsp"); open!(open_wp_text_box, "wps:txbx"); open!(open_text_box_content, "w:txbxContent"); // compat open!(open_compat, "w:compat"); closed!(space_for_ul, "w:spaceForUL"); closed!( balance_single_byte_double_byte_width, "w:balanceSingleByteDoubleByteWidth" ); closed!(do_not_leave_backslash_alone, "w:doNotLeaveBackslashAlone"); closed!(ul_trail_space, "w:ulTrailSpace"); closed!(do_not_expand_shift_return, "w:doNotExpandShiftReturn"); closed!(adjust_line_height_table, "w:adjustLineHeightInTable"); closed!(use_fe_layout, "w:useFELayout"); closed!( compat_setting, "w:compatSetting", "w:name", "w:uri", "w:val" ); closed!(keep_next, "w:keepNext"); closed!(keep_lines, "w:keepLines"); closed!(page_break_before, "w:pageBreakBefore"); closed!(window_control, "w:windowControl"); /* */ open!(open_level_override, "w:lvlOverride", "w:ilvl"); closed_with_str!(start_override, "w:startOverride"); closed!(doc_id, "w15:docId", "w15:val"); open!(open_doc_vars, "w:docVars"); closed!(doc_var, "w:docVar", "w:name", "w:val"); // webextension open!(open_webextension, "we:webextension", "xmlns:we", "id"); closed!( webextension_reference, "we:reference", "id", "version", "store", "storeType" ); closed!(webextension_alternate_references, "we:alternateReferences"); open!(open_webextension_properties, "we:properties"); closed!(webextension_property, "we:property", "name", "value"); closed!(webextension_bindings, "we:bindings"); closed!(webextension_snapshot, "we:snapshot", "xmlns:r"); // taskpanes open!(open_taskpanes, "wetp:taskpanes", "xmlns:wetp"); open!( open_taskpane, "wetp:taskpane", "dockstate", "visibility", "width", "row" ); closed!(webextensionref, "wetp:webextensionref", "xmlns:r", "r:id"); // customXML open!( open_data_store_item, "ds:datastoreItem", "xmlns:ds", "ds:itemID" ); open!(open_data_store_schema_refs, "ds:schemaRefs"); // CommentExtended // w15:commentEx w15:paraId="00000001" w15:paraIdParent="57D1BD7C" w15:done="0" pub(crate) fn comment_extended( mut self, paragraph_id: &str, done: bool, parent_paragraph_id: &Option, ) -> Self { if let Some(parent_paragraph_id) = parent_paragraph_id { self.writer .write( XmlEvent::start_element("w15:commentEx") .attr("w15:paraId", paragraph_id) .attr("w15:paraIdParent", parent_paragraph_id) .attr("w15:done", &format!("{}", done as usize)), ) .expect(EXPECT_MESSAGE); return self.close(); } self.writer .write( XmlEvent::start_element("w15:commentEx") .attr("w15:paraId", paragraph_id) .attr("w15:done", &format!("{}", done as usize)), ) .expect(EXPECT_MESSAGE); self.close() } // docGrid pub(crate) fn doc_grid( mut self, t: &DocGridType, line_pitch: Option, char_space: Option, ) -> Self { let t = t.to_string(); let line_pitch_string = format!("{}", line_pitch.unwrap_or_default()); let char_space_string = format!("{}", char_space.unwrap_or_default()); let mut w = XmlEvent::start_element("w:docGrid").attr("w:type", &t); if line_pitch.is_some() { w = w.attr("w:linePitch", &line_pitch_string); } if char_space.is_some() { w = w.attr("w:charSpace", &char_space_string); } self.writer.write(w).expect(EXPECT_MESSAGE); self.close() } } #[cfg(test)] mod tests { use super::*; #[cfg(test)] use pretty_assertions::assert_eq; use std::str; #[test] fn test_sz() { let b = XMLBuilder::new(); let r = b.sz(20).build(); assert_eq!(str::from_utf8(&r).unwrap(), r#""#); } #[test] fn test_declaration() { let b = XMLBuilder::new(); let r = b .open_style(StyleType::Paragraph, "Heading") .close() .build(); assert_eq!( str::from_utf8(&r).unwrap(), r#""# ); } #[test] fn test_next() { let b = XMLBuilder::new(); let r = b.next("Normal").build(); assert_eq!(str::from_utf8(&r).unwrap(), r#""#); } #[test] fn test_name() { let b = XMLBuilder::new(); let r = b.name("Heading").build(); assert_eq!(str::from_utf8(&r).unwrap(), r#""#); } #[test] fn test_color() { let b = XMLBuilder::new(); let r = b.color("2E74B5").build(); assert_eq!(str::from_utf8(&r).unwrap(), r#""#); } #[test] fn test_based_on() { let b = XMLBuilder::new(); let r = b.based_on("Normal").build(); assert_eq!( str::from_utf8(&r).unwrap(), r#""# ); } }