From a9eb8f96b266c0a8a02428b4dd6bf43ca0c0e9f7 Mon Sep 17 00:00:00 2001 From: bokuweb Date: Thu, 14 Nov 2019 19:21:45 +0900 Subject: [PATCH] feat: Add style --- docx-core/src/documents/document_rels.rs | 6 -- docx-core/src/documents/elements/font.rs | 57 +++++++++++ docx-core/src/documents/elements/mod.rs | 2 + docx-core/src/documents/elements/style.rs | 20 ++++ docx-core/src/documents/font_table.rs | 67 +++++++++++++ docx-core/src/documents/mod.rs | 6 ++ docx-core/src/documents/styles.rs | 5 +- docx-core/src/documents/xml_docx.rs | 1 + docx-core/src/types/font_pitch_type.rs | 20 ++++ docx-core/src/types/mod.rs | 2 + docx-core/src/xml_builder/elements.rs | 5 + docx-core/src/xml_builder/fonts.rs | 21 +++++ docx-core/src/xml_builder/mod.rs | 1 + docx-core/src/zipper/mod.rs | 2 + docx-core/tests/lib.rs | 11 +++ .../word/_rels/document.xml.rels | 5 +- fixtures/hello_libre_office/word/styles.xml | 94 ++++++++++++++++++- 17 files changed, 316 insertions(+), 9 deletions(-) create mode 100644 docx-core/src/documents/elements/font.rs create mode 100644 docx-core/src/documents/font_table.rs create mode 100644 docx-core/src/types/font_pitch_type.rs create mode 100644 docx-core/src/xml_builder/fonts.rs diff --git a/docx-core/src/documents/document_rels.rs b/docx-core/src/documents/document_rels.rs index 98109d0..dc873e8 100644 --- a/docx-core/src/documents/document_rels.rs +++ b/docx-core/src/documents/document_rels.rs @@ -30,11 +30,6 @@ impl BuildXML for DocumentRels { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", "settings.xml", ) - .relationship( - "rId4", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tag", - "tag.xml", - ) .close() .build() } @@ -59,7 +54,6 @@ mod tests { - "# ); } diff --git a/docx-core/src/documents/elements/font.rs b/docx-core/src/documents/elements/font.rs new file mode 100644 index 0000000..8a0e607 --- /dev/null +++ b/docx-core/src/documents/elements/font.rs @@ -0,0 +1,57 @@ +use crate::documents::BuildXML; +use crate::types::*; +use crate::xml_builder::*; + +#[derive(Debug)] +pub struct Font<'a> { + name: &'a str, + charset: &'a str, + family: &'a str, + pitch: FontPitchType, +} + +impl<'a> Font<'a> { + pub fn new(name: &'a str, charset: &'a str, family: &'a str, pitch: FontPitchType) -> Font<'a> { + Font { + name, + charset, + family, + pitch, + } + } +} + +impl<'a> BuildXML for Font<'a> { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.open_font(self.name) + .charset(self.charset) + .family(self.family) + .pitch(&self.pitch.to_string()) + .close() + .build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = Font::new("Arial", "00", "swiss", FontPitchType::Variable); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#" + + + +"# + ); + } +} diff --git a/docx-core/src/documents/elements/mod.rs b/docx-core/src/documents/elements/mod.rs index 20b12af..489ce4e 100644 --- a/docx-core/src/documents/elements/mod.rs +++ b/docx-core/src/documents/elements/mod.rs @@ -5,6 +5,7 @@ mod br; mod color; mod default_tab_stop; mod doc_defaults; +mod font; mod grid_span; mod highlight; mod indent; @@ -48,6 +49,7 @@ pub use br::*; pub use color::*; pub use default_tab_stop::*; pub use doc_defaults::*; +pub use font::*; pub use grid_span::*; pub use highlight::*; pub use indent::*; diff --git a/docx-core/src/documents/elements/style.rs b/docx-core/src/documents/elements/style.rs index 9ffd107..9bd8917 100644 --- a/docx-core/src/documents/elements/style.rs +++ b/docx-core/src/documents/elements/style.rs @@ -43,6 +43,26 @@ impl Style { ..default } } + + pub fn size(mut self, size: usize) -> Self { + self.run_property = self.run_property.size(size); + self + } + + pub fn color(mut self, color: &str) -> Self { + self.run_property = self.run_property.color(color); + self + } + + pub fn bold(mut self) -> Self { + self.run_property = self.run_property.bold(); + self + } + + pub fn italic(mut self) -> Self { + self.run_property = self.run_property.italic(); + self + } } impl BuildXML for Style { diff --git a/docx-core/src/documents/font_table.rs b/docx-core/src/documents/font_table.rs new file mode 100644 index 0000000..dd5accc --- /dev/null +++ b/docx-core/src/documents/font_table.rs @@ -0,0 +1,67 @@ +use super::Font; +use crate::documents::BuildXML; +use crate::types::FontPitchType; +use crate::xml_builder::*; + +#[derive(Debug)] +pub struct FontTable {} + +impl FontTable { + pub fn new() -> FontTable { + Default::default() + } +} + +impl Default for FontTable { + fn default() -> Self { + Self {} + } +} + +impl BuildXML for FontTable { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + let times = Font::new("Times New Roman", "00", "roman", FontPitchType::Variable); + let symbol = Font::new("Symbol", "02", "roman", FontPitchType::Variable); + let arial = Font::new("Arial", "00", "swiss", FontPitchType::Variable); + b.declaration(Some(true)) + .open_fonts() + .add_child(×) + .add_child(&symbol) + .add_child(&arial) + .close() + .build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_settings() { + let c = FontTable::new(); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#" + + + + + + + + + + + + +"# + ); + } +} diff --git a/docx-core/src/documents/mod.rs b/docx-core/src/documents/mod.rs index 2104df4..a7b757b 100644 --- a/docx-core/src/documents/mod.rs +++ b/docx-core/src/documents/mod.rs @@ -4,6 +4,7 @@ mod doc_props; mod document; mod document_rels; mod elements; +mod font_table; mod rels; mod settings; mod styles; @@ -16,6 +17,7 @@ pub use doc_props::*; pub use document::*; pub use document_rels::*; pub use elements::*; +pub use font_table::*; pub use rels::*; pub use settings::*; pub use styles::*; @@ -30,6 +32,7 @@ pub struct Docx { styles: Styles, document: Document, settings: Settings, + font_table: FontTable, } impl Default for Docx { @@ -41,6 +44,7 @@ impl Default for Docx { let document = Document::new(); let document_rels = DocumentRels::new(); let settings = Settings::new(); + let font_table = FontTable::new(); Docx { content_type, rels, @@ -49,6 +53,7 @@ impl Default for Docx { document, document_rels, settings, + font_table, } } } @@ -77,6 +82,7 @@ impl Docx { document: self.document.build(), document_rels: self.document_rels.build(), settings: self.settings.build(), + font_table: self.font_table.build(), } } } diff --git a/docx-core/src/documents/styles.rs b/docx-core/src/documents/styles.rs index f1e8cfe..66edbdc 100644 --- a/docx-core/src/documents/styles.rs +++ b/docx-core/src/documents/styles.rs @@ -1,5 +1,6 @@ use super::{DocDefaults, Style}; use crate::documents::BuildXML; +use crate::types::*; use crate::xml_builder::*; #[derive(Debug)] @@ -31,8 +32,10 @@ impl Default for Styles { impl BuildXML for Styles { fn build(&self) -> Vec { let b = XMLBuilder::new(); + let normal = Style::new("Normal", "Normal", StyleType::Paragraph); b.open_styles() .add_child(&self.doc_defaults) + .add_child(&normal) .add_children(&self.styles) .close() .build() @@ -54,7 +57,7 @@ mod tests { let b = c.build(); assert_eq!( str::from_utf8(&b).unwrap(), - r#""# + r#""# ); } } diff --git a/docx-core/src/documents/xml_docx.rs b/docx-core/src/documents/xml_docx.rs index 613eefd..3b256d9 100644 --- a/docx-core/src/documents/xml_docx.rs +++ b/docx-core/src/documents/xml_docx.rs @@ -13,6 +13,7 @@ pub struct XMLDocx { pub document: Vec, pub document_rels: Vec, pub settings: Vec, + pub font_table: Vec, } impl XMLDocx { diff --git a/docx-core/src/types/font_pitch_type.rs b/docx-core/src/types/font_pitch_type.rs new file mode 100644 index 0000000..325f7e1 --- /dev/null +++ b/docx-core/src/types/font_pitch_type.rs @@ -0,0 +1,20 @@ +use std::fmt; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Copy, Clone, Debug)] +pub enum FontPitchType { + Default, + Fixed, + Variable, +} + +impl fmt::Display for FontPitchType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + FontPitchType::Default => write!(f, "default"), + FontPitchType::Fixed => write!(f, "fixed"), + FontPitchType::Variable => write!(f, "variable"), + } + } +} diff --git a/docx-core/src/types/mod.rs b/docx-core/src/types/mod.rs index 48bec73..4bbe005 100644 --- a/docx-core/src/types/mod.rs +++ b/docx-core/src/types/mod.rs @@ -2,6 +2,7 @@ pub mod alignment_type; pub mod border_position; pub mod border_type; pub mod break_type; +pub mod font_pitch_type; pub mod special_indent_type; pub mod style_type; pub mod table_alignment_type; @@ -12,6 +13,7 @@ pub use alignment_type::*; pub use border_position::*; pub use border_type::*; pub use break_type::*; +pub use font_pitch_type::*; pub use special_indent_type::*; pub use style_type::*; pub use table_alignment_type::*; diff --git a/docx-core/src/xml_builder/elements.rs b/docx-core/src/xml_builder/elements.rs index dd2a1c4..48d25f2 100644 --- a/docx-core/src/xml_builder/elements.rs +++ b/docx-core/src/xml_builder/elements.rs @@ -128,6 +128,11 @@ impl XMLBuilder { closed_el!(br, "w:br", "w:type"); closed_el!(zoom, "w:zoom", "w:percent"); only_usize_val_el!(default_tab_stop, "w:defaultTabStop"); + + opened_el!(open_font, "w:font", "w:name"); + only_str_val_el!(pitch, "w:pitch"); + only_str_val_el!(family, "w:family"); + only_str_val_el!(charset, "w:charset"); } #[cfg(test)] diff --git a/docx-core/src/xml_builder/fonts.rs b/docx-core/src/xml_builder/fonts.rs new file mode 100644 index 0000000..df508de --- /dev/null +++ b/docx-core/src/xml_builder/fonts.rs @@ -0,0 +1,21 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + pub(crate) fn open_fonts(mut self) -> Self { + self.writer + .write( + XmlEvent::start_element("w:fonts") + .attr( + "xmlns:w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + ) + .attr( + "xmlns:r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + ), + ) + .expect("should write to buf"); + self + } +} diff --git a/docx-core/src/xml_builder/mod.rs b/docx-core/src/xml_builder/mod.rs index d684a69..936ea57 100644 --- a/docx-core/src/xml_builder/mod.rs +++ b/docx-core/src/xml_builder/mod.rs @@ -5,6 +5,7 @@ mod core_properties; mod declaration; mod document; mod elements; +mod fonts; mod properties; mod relationship; mod settings; diff --git a/docx-core/src/zipper/mod.rs b/docx-core/src/zipper/mod.rs index ec51f30..6ee606f 100644 --- a/docx-core/src/zipper/mod.rs +++ b/docx-core/src/zipper/mod.rs @@ -35,6 +35,8 @@ where zip.write_all(&xml.styles)?; zip.start_file("word/settings.xml", options)?; zip.write_all(&xml.settings)?; + zip.start_file("word/fontTable.xml", options)?; + zip.write_all(&xml.font_table)?; zip.finish()?; Ok(()) } diff --git a/docx-core/tests/lib.rs b/docx-core/tests/lib.rs index 79822fe..c8372b7 100644 --- a/docx-core/tests/lib.rs +++ b/docx-core/tests/lib.rs @@ -4,6 +4,17 @@ use docx_core::*; pub const DUMMY: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; +#[test] +pub fn hello() -> Result<(), DocxError> { + let path = std::path::Path::new("./tests/output/hello.docx"); + let file = std::fs::File::create(&path).unwrap(); + Docx::new() + .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) + .build() + .pack(file)?; + Ok(()) +} + #[test] pub fn indent() -> Result<(), DocxError> { let path = std::path::Path::new("./tests/output/indent.docx"); diff --git a/fixtures/hello_libre_office/word/_rels/document.xml.rels b/fixtures/hello_libre_office/word/_rels/document.xml.rels index 8a2db8a..6ac87fd 100644 --- a/fixtures/hello_libre_office/word/_rels/document.xml.rels +++ b/fixtures/hello_libre_office/word/_rels/document.xml.rels @@ -1,3 +1,6 @@ - + + + + \ No newline at end of file diff --git a/fixtures/hello_libre_office/word/styles.xml b/fixtures/hello_libre_office/word/styles.xml index 72e6f53..d8d8049 100644 --- a/fixtures/hello_libre_office/word/styles.xml +++ b/fixtures/hello_libre_office/word/styles.xml @@ -1,2 +1,94 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file