From d4f08f9703a454f791696db314d990f55a2a1d9c Mon Sep 17 00:00:00 2001 From: bokuweb Date: Thu, 7 Nov 2019 16:08:59 +0900 Subject: [PATCH] feat: Add paragraph --- .../[Content_Types].xml | 0 .../{hello => hello_libre_oficce}/_rels/.rels | 0 .../docProps/app.xml | 0 .../docProps/core.xml | 0 .../{hello => hello_libre_oficce}/hello.docx | Bin .../word/_rels/document.xml.rels | 0 .../word/document.xml | 0 .../word/fontTable.xml | 0 .../word/styles.xml | 0 docx-core/src/documents/document.rs | 45 +++++++++++ docx-core/src/documents/elements/mod.rs | 6 ++ docx-core/src/documents/elements/paragraph.rs | 52 +++++++++++++ docx-core/src/documents/elements/run.rs | 54 +++++++++++++ docx-core/src/documents/elements/style.rs | 1 + docx-core/src/documents/elements/text.rs | 35 +++++++++ docx-core/src/documents/mod.rs | 22 +++--- docx-core/src/documents/styles.rs | 4 +- docx-core/src/documents/xml_document.rs | 6 +- docx-core/src/lib.rs | 4 +- docx-core/src/types/mod.rs | 3 + docx-core/src/types/style_type.rs | 16 ++++ docx-core/src/xml_builder/document.rs | 71 ++++++++++++++++++ docx-core/src/xml_builder/elements/body.rs | 7 ++ docx-core/src/xml_builder/elements/mod.rs | 41 ++++------ .../src/xml_builder/elements/paragraph.rs | 7 ++ docx-core/src/xml_builder/elements/run.rs | 7 ++ docx-core/src/xml_builder/elements/style.rs | 21 +----- docx-core/src/xml_builder/elements/text.rs | 7 ++ docx-core/src/xml_builder/mod.rs | 10 ++- docx-core/src/xml_builder/properties.rs | 2 +- docx-core/src/xml_builder/relationship.rs | 2 +- 31 files changed, 359 insertions(+), 64 deletions(-) rename docx-core/fixtures/{hello => hello_libre_oficce}/[Content_Types].xml (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/_rels/.rels (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/docProps/app.xml (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/docProps/core.xml (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/hello.docx (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/word/_rels/document.xml.rels (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/word/document.xml (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/word/fontTable.xml (100%) rename docx-core/fixtures/{hello => hello_libre_oficce}/word/styles.xml (100%) create mode 100644 docx-core/src/documents/document.rs create mode 100644 docx-core/src/documents/elements/paragraph.rs create mode 100644 docx-core/src/documents/elements/run.rs create mode 100644 docx-core/src/documents/elements/text.rs create mode 100644 docx-core/src/types/mod.rs create mode 100644 docx-core/src/types/style_type.rs create mode 100644 docx-core/src/xml_builder/document.rs create mode 100644 docx-core/src/xml_builder/elements/body.rs create mode 100644 docx-core/src/xml_builder/elements/paragraph.rs create mode 100644 docx-core/src/xml_builder/elements/run.rs create mode 100644 docx-core/src/xml_builder/elements/text.rs diff --git a/docx-core/fixtures/hello/[Content_Types].xml b/docx-core/fixtures/hello_libre_oficce/[Content_Types].xml similarity index 100% rename from docx-core/fixtures/hello/[Content_Types].xml rename to docx-core/fixtures/hello_libre_oficce/[Content_Types].xml diff --git a/docx-core/fixtures/hello/_rels/.rels b/docx-core/fixtures/hello_libre_oficce/_rels/.rels similarity index 100% rename from docx-core/fixtures/hello/_rels/.rels rename to docx-core/fixtures/hello_libre_oficce/_rels/.rels diff --git a/docx-core/fixtures/hello/docProps/app.xml b/docx-core/fixtures/hello_libre_oficce/docProps/app.xml similarity index 100% rename from docx-core/fixtures/hello/docProps/app.xml rename to docx-core/fixtures/hello_libre_oficce/docProps/app.xml diff --git a/docx-core/fixtures/hello/docProps/core.xml b/docx-core/fixtures/hello_libre_oficce/docProps/core.xml similarity index 100% rename from docx-core/fixtures/hello/docProps/core.xml rename to docx-core/fixtures/hello_libre_oficce/docProps/core.xml diff --git a/docx-core/fixtures/hello/hello.docx b/docx-core/fixtures/hello_libre_oficce/hello.docx similarity index 100% rename from docx-core/fixtures/hello/hello.docx rename to docx-core/fixtures/hello_libre_oficce/hello.docx diff --git a/docx-core/fixtures/hello/word/_rels/document.xml.rels b/docx-core/fixtures/hello_libre_oficce/word/_rels/document.xml.rels similarity index 100% rename from docx-core/fixtures/hello/word/_rels/document.xml.rels rename to docx-core/fixtures/hello_libre_oficce/word/_rels/document.xml.rels diff --git a/docx-core/fixtures/hello/word/document.xml b/docx-core/fixtures/hello_libre_oficce/word/document.xml similarity index 100% rename from docx-core/fixtures/hello/word/document.xml rename to docx-core/fixtures/hello_libre_oficce/word/document.xml diff --git a/docx-core/fixtures/hello/word/fontTable.xml b/docx-core/fixtures/hello_libre_oficce/word/fontTable.xml similarity index 100% rename from docx-core/fixtures/hello/word/fontTable.xml rename to docx-core/fixtures/hello_libre_oficce/word/fontTable.xml diff --git a/docx-core/fixtures/hello/word/styles.xml b/docx-core/fixtures/hello_libre_oficce/word/styles.xml similarity index 100% rename from docx-core/fixtures/hello/word/styles.xml rename to docx-core/fixtures/hello_libre_oficce/word/styles.xml diff --git a/docx-core/src/documents/document.rs b/docx-core/src/documents/document.rs new file mode 100644 index 0000000..05a8568 --- /dev/null +++ b/docx-core/src/documents/document.rs @@ -0,0 +1,45 @@ +use super::{DocDefaults, Style}; +use crate::documents::BuildXML; +use crate::xml_builder::*; +use crate::StyleType; + +pub struct Document {} + +impl Document { + pub fn new() -> Document { + Default::default() + } +} + +impl Default for Document { + fn default() -> Self { + Self {} + } +} + +impl BuildXML for Document { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.open_document().open_body().close().close().build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_document() { + let b = Document::new().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 45c41ce..74d4f71 100644 --- a/docx-core/src/documents/elements/mod.rs +++ b/docx-core/src/documents/elements/mod.rs @@ -3,21 +3,27 @@ mod color; mod doc_defaults; mod name; mod next; +mod paragraph; mod paragraph_property; mod q_format; +mod run; mod run_property; mod run_property_default; mod style; mod sz; +mod text; pub use based_on::*; pub use color::*; pub use doc_defaults::*; pub use name::*; pub use next::*; +pub use paragraph::*; pub use paragraph_property::*; pub use q_format::*; +pub use run::*; pub use run_property::*; pub use run_property_default::*; pub use style::*; pub use sz::*; +pub use text::*; diff --git a/docx-core/src/documents/elements/paragraph.rs b/docx-core/src/documents/elements/paragraph.rs new file mode 100644 index 0000000..ee955f2 --- /dev/null +++ b/docx-core/src/documents/elements/paragraph.rs @@ -0,0 +1,52 @@ +use super::{Run, RunProperty, Text}; +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct Paragraph { + runs: Vec, +} + +impl Default for Paragraph { + fn default() -> Self { + Self { runs: Vec::new() } + } +} + +impl Paragraph { + pub fn new() -> Paragraph { + Default::default() + } + + pub fn add_run(mut self, run: Run) -> Paragraph { + self.runs.push(run); + self + } +} + +impl BuildXML for Paragraph { + fn build(&self) -> Vec { + let mut b = XMLBuilder::new().open_paragraph(); + for r in self.runs.iter() { + b = b.add_child(r) + } + b.close().build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_paragraph() { + let b = Paragraph::new().add_run(Run::new("Hello")).build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#"Hello"# + ); + } +} diff --git a/docx-core/src/documents/elements/run.rs b/docx-core/src/documents/elements/run.rs new file mode 100644 index 0000000..d909d72 --- /dev/null +++ b/docx-core/src/documents/elements/run.rs @@ -0,0 +1,54 @@ +use super::{RunProperty, Text}; +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct Run { + run_property: RunProperty, + text: Text, +} + +impl Run { + pub fn new(text: impl Into) -> Run { + Run { + text: Text::new(text), + ..Default::default() + } + } +} + +impl Default for Run { + fn default() -> Self { + let run_property = RunProperty::new(); + let text = Text::new(""); + Self { run_property, text } + } +} + +impl BuildXML for Run { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.open_run() + .add_child(&self.run_property) + .add_child(&self.text) + .close() + .build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let b = Run::new("Hello").build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#"Hello"# + ); + } +} diff --git a/docx-core/src/documents/elements/style.rs b/docx-core/src/documents/elements/style.rs index f59eb4c..043d351 100644 --- a/docx-core/src/documents/elements/style.rs +++ b/docx-core/src/documents/elements/style.rs @@ -1,5 +1,6 @@ use crate::documents::BuildXML; use crate::xml_builder::*; +use crate::StyleType; use super::{BasedOn, Name, Next, ParagraphProperty, QFormat, RunProperty}; diff --git a/docx-core/src/documents/elements/text.rs b/docx-core/src/documents/elements/text.rs new file mode 100644 index 0000000..3149bbf --- /dev/null +++ b/docx-core/src/documents/elements/text.rs @@ -0,0 +1,35 @@ +use super::{RunProperty, Sz}; +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct Text { + text: String, +} + +impl Text { + pub fn new(text: impl Into) -> Text { + Text { text: text.into() } + } +} + +impl BuildXML for Text { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.text(&self.text).build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let b = Text::new("Hello").build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#"Hello"#); + } +} diff --git a/docx-core/src/documents/mod.rs b/docx-core/src/documents/mod.rs index 894d7d2..e8530e1 100644 --- a/docx-core/src/documents/mod.rs +++ b/docx-core/src/documents/mod.rs @@ -1,6 +1,7 @@ mod build_xml; mod content_types; mod doc_props; +mod document; mod elements; mod rels; mod styles; @@ -8,25 +9,26 @@ mod xml_document; pub(crate) use build_xml::*; -use crate::xml_builder::*; -use content_types::*; -use doc_props::*; -use elements::*; -use rels::*; -use styles::*; +pub use crate::xml_builder::*; +pub use content_types::*; +pub use doc_props::*; +pub use document::*; +pub use elements::*; +pub use rels::*; +pub use styles::*; -pub(crate) struct Document { +pub(crate) struct Docx { content_type: ContentTypes, rels: Rels, doc_props: DocProps, } -impl Document { - pub fn new() -> Document { +impl Docx { + pub fn new() -> Docx { let content_type = ContentTypes::new(); let rels = Rels::new(); let doc_props = DocProps::new(None, None /* TODO: */); - Document { + Docx { content_type, rels, doc_props, diff --git a/docx-core/src/documents/styles.rs b/docx-core/src/documents/styles.rs index 88d7aa5..df2b461 100644 --- a/docx-core/src/documents/styles.rs +++ b/docx-core/src/documents/styles.rs @@ -1,7 +1,7 @@ +use super::{DocDefaults, Style}; use crate::documents::BuildXML; use crate::xml_builder::*; - -use super::{DocDefaults, Style, StyleType}; +use crate::StyleType; pub struct Styles { doc_defaults: DocDefaults, diff --git a/docx-core/src/documents/xml_document.rs b/docx-core/src/documents/xml_document.rs index 97f129c..2020abf 100644 --- a/docx-core/src/documents/xml_document.rs +++ b/docx-core/src/documents/xml_document.rs @@ -1,4 +1,4 @@ -use super::Document; +use super::Docx; use crate::documents::BuildXML; pub(crate) struct XMLDocument { @@ -6,8 +6,8 @@ pub(crate) struct XMLDocument { rels: Vec, } -impl From for XMLDocument { - fn from(doc: Document) -> XMLDocument { +impl From for XMLDocument { + fn from(doc: Docx) -> XMLDocument { let content_type = doc.content_type.build(); XMLDocument { content_type, diff --git a/docx-core/src/lib.rs b/docx-core/src/lib.rs index c4806d9..d02c1c6 100644 --- a/docx-core/src/lib.rs +++ b/docx-core/src/lib.rs @@ -1,4 +1,5 @@ mod documents; +mod types; mod xml_builder; use documents::*; @@ -6,11 +7,12 @@ use xml_builder::*; use std::fs::File; use std::io::{self, Write}; +use types::*; use xml::writer::{EmitterConfig, EventWriter, Result, XmlEvent}; pub fn simple() { - let doc = Document::new(); + let doc = Docx::new(); let mut file = File::create("./dist/output.xml").unwrap(); // let mut b = Vec::new(); // let mut w = EmitterConfig::new() diff --git a/docx-core/src/types/mod.rs b/docx-core/src/types/mod.rs new file mode 100644 index 0000000..87172bb --- /dev/null +++ b/docx-core/src/types/mod.rs @@ -0,0 +1,3 @@ +pub mod style_type; + +pub use style_type::*; diff --git a/docx-core/src/types/style_type.rs b/docx-core/src/types/style_type.rs new file mode 100644 index 0000000..e19bc82 --- /dev/null +++ b/docx-core/src/types/style_type.rs @@ -0,0 +1,16 @@ +use std::fmt; + +#[derive(Copy, Clone, Debug)] +pub enum StyleType { + Paragraph, + Character, +} + +impl fmt::Display for StyleType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + StyleType::Paragraph => write!(f, "paragraph"), + StyleType::Character => write!(f, "character"), + } + } +} diff --git a/docx-core/src/xml_builder/document.rs b/docx-core/src/xml_builder/document.rs new file mode 100644 index 0000000..cc887e1 --- /dev/null +++ b/docx-core/src/xml_builder/document.rs @@ -0,0 +1,71 @@ +use std::fmt; + +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + pub(crate) fn open_document(mut self) -> Self { + self.writer + .write( + XmlEvent::start_element("w:document") + .attr("xmlns:o", "urn:schemas-microsoft-com:office:office") + .attr( + "xmlns:r", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + ) + .attr("xmlns:v", "urn:schemas-microsoft-com:vml") + .attr( + "xmlns:w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + ) + .attr("xmlns:w10", "urn:schemas-microsoft-com:office:word") + .attr( + "xmlns:wp", + "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", + ) + .attr( + "xmlns:wps", + "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", + ) + .attr( + "xmlns:wpg", + "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", + ) + .attr( + "xmlns:mc", + "http://schemas.openxmlformats.org/markup-compatibility/2006", + ) + .attr( + "xmlns:wp14", + "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", + ) + .attr( + "xmlns:w14", + "http://schemas.microsoft.com/office/word/2010/wordml", + ) + .attr("mc:Ignorable", "w14 wp14"), + ) + .expect("should write to buf"); + self + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_document() { + let b = XMLBuilder::new(); + let r = b.open_document().close().build(); + assert_eq!( + str::from_utf8(&r).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/xml_builder/elements/body.rs b/docx-core/src/xml_builder/elements/body.rs new file mode 100644 index 0000000..ba55518 --- /dev/null +++ b/docx-core/src/xml_builder/elements/body.rs @@ -0,0 +1,7 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + opened_el!(open_body, "w:body"); +} diff --git a/docx-core/src/xml_builder/elements/mod.rs b/docx-core/src/xml_builder/elements/mod.rs index 8744ef7..7a01cd7 100644 --- a/docx-core/src/xml_builder/elements/mod.rs +++ b/docx-core/src/xml_builder/elements/mod.rs @@ -1,29 +1,20 @@ #[macro_use] mod macros; -mod based_on; -mod color; -mod doc_defaults; -mod name; -mod next; -mod paragraph_property; -mod q_format; -mod run_property; -mod run_property_default; -mod style; -mod sz; +pub mod based_on; +pub mod body; +pub mod color; +pub mod doc_defaults; +pub mod name; +pub mod next; +pub mod paragraph; +pub mod paragraph_property; +pub mod q_format; +pub mod run; +pub mod run_property; +pub mod run_property_default; +pub mod style; +pub mod sz; +pub mod text; -pub use based_on::*; -pub use color::*; -pub use doc_defaults::*; -pub use name::*; -pub use next::*; -pub use paragraph_property::*; -pub use q_format::*; -pub use run_property::*; -pub use run_property_default::*; -pub use style::*; -pub use sz::*; - -use super::XMLBuilder; -use super::XmlEvent; +use super::{XMLBuilder, XmlEvent}; diff --git a/docx-core/src/xml_builder/elements/paragraph.rs b/docx-core/src/xml_builder/elements/paragraph.rs new file mode 100644 index 0000000..a801f41 --- /dev/null +++ b/docx-core/src/xml_builder/elements/paragraph.rs @@ -0,0 +1,7 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + opened_el!(open_paragraph, "w:p"); +} diff --git a/docx-core/src/xml_builder/elements/run.rs b/docx-core/src/xml_builder/elements/run.rs new file mode 100644 index 0000000..5fec490 --- /dev/null +++ b/docx-core/src/xml_builder/elements/run.rs @@ -0,0 +1,7 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + opened_el!(open_run, "w:r"); +} diff --git a/docx-core/src/xml_builder/elements/style.rs b/docx-core/src/xml_builder/elements/style.rs index bd84c15..6359256 100644 --- a/docx-core/src/xml_builder/elements/style.rs +++ b/docx-core/src/xml_builder/elements/style.rs @@ -1,22 +1,5 @@ -use std::fmt; - -use super::XMLBuilder; -use super::XmlEvent; - -#[derive(Copy, Clone, Debug)] -pub enum StyleType { - Paragraph, - Character, -} - -impl fmt::Display for StyleType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - StyleType::Paragraph => write!(f, "paragraph"), - StyleType::Character => write!(f, "character"), - } - } -} +use super::{XMLBuilder, XmlEvent}; +use crate::StyleType; impl XMLBuilder { // Build w:style element diff --git a/docx-core/src/xml_builder/elements/text.rs b/docx-core/src/xml_builder/elements/text.rs new file mode 100644 index 0000000..1bee6b5 --- /dev/null +++ b/docx-core/src/xml_builder/elements/text.rs @@ -0,0 +1,7 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + closed_el_with_child!(text, "w:t"); +} diff --git a/docx-core/src/xml_builder/mod.rs b/docx-core/src/xml_builder/mod.rs index e0254a0..5119a13 100644 --- a/docx-core/src/xml_builder/mod.rs +++ b/docx-core/src/xml_builder/mod.rs @@ -3,12 +3,14 @@ mod macros; mod core_properties; mod declaration; +mod document; mod elements; mod properties; mod relationship; mod styles; use crate::BuildXML; + use std::str; use xml::common::XmlVersion; use xml::writer::{EmitterConfig, EventWriter, XmlEvent}; @@ -91,7 +93,7 @@ impl XMLBuilder { } // Write plain text - pub(crate) fn text(mut self, t: &str) -> Self { + pub(crate) fn plain_text(mut self, t: &str) -> Self { self.writer.write(t).unwrap(); self } @@ -109,7 +111,11 @@ mod tests { #[test] fn test_open_types() { let b = XMLBuilder::new(); - let r = b.open_types("http://example").text("child").close().build(); + let r = b + .open_types("http://example") + .plain_text("child") + .close() + .build(); assert_eq!( str::from_utf8(&r).unwrap(), r#"child"# diff --git a/docx-core/src/xml_builder/properties.rs b/docx-core/src/xml_builder/properties.rs index 35f8bb5..c724d07 100644 --- a/docx-core/src/xml_builder/properties.rs +++ b/docx-core/src/xml_builder/properties.rs @@ -27,7 +27,7 @@ mod tests { let b = XMLBuilder::new(); let r = b .open_properties("http://example", "http://example2") - .text("child") + .plain_text("child") .close() .build(); assert_eq!( diff --git a/docx-core/src/xml_builder/relationship.rs b/docx-core/src/xml_builder/relationship.rs index 9b08b2c..1800177 100644 --- a/docx-core/src/xml_builder/relationship.rs +++ b/docx-core/src/xml_builder/relationship.rs @@ -21,7 +21,7 @@ mod tests { let b = XMLBuilder::new(); let r = b .open_relationships("http://example") - .text("child") + .plain_text("child") .close() .build(); assert_eq!(