diff --git a/Cargo.lock b/Cargo.lock index 493ec46..c53a4d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,120 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "docx-core" version = "0.1.0" dependencies = [ + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "output_vt100" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pretty_assertions" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "xml-rs" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" +"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" diff --git a/docx-core/Cargo.toml b/docx-core/Cargo.toml index 95cfdd6..c4f0004 100644 --- a/docx-core/Cargo.toml +++ b/docx-core/Cargo.toml @@ -7,4 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -xml-rs = "0.8.0" \ No newline at end of file +xml-rs = "0.8.0" + +[dev-dependencies] +pretty_assertions = "*" \ No newline at end of file diff --git a/docx-core/src/documents/elements/based_on.rs b/docx-core/src/documents/elements/based_on.rs new file mode 100644 index 0000000..745f603 --- /dev/null +++ b/docx-core/src/documents/elements/based_on.rs @@ -0,0 +1,38 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct BasedOn { + val: String, +} + +impl BasedOn { + pub fn new(val: impl Into) -> BasedOn { + BasedOn { val: val.into() } + } +} + +impl BuildXML for BasedOn { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.based_on(&self.val).build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = BasedOn::new("Normal"); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/documents/elements/doc_defaults.rs b/docx-core/src/documents/elements/doc_defaults.rs index 4a0efcd..c8334c6 100644 --- a/docx-core/src/documents/elements/doc_defaults.rs +++ b/docx-core/src/documents/elements/doc_defaults.rs @@ -31,6 +31,8 @@ impl BuildXML for DocDefaults { mod tests { use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; use std::str; #[test] @@ -39,7 +41,7 @@ mod tests { let b = c.build(); assert_eq!( str::from_utf8(&b).unwrap(), - r#""# + r#""# ); } } diff --git a/docx-core/src/documents/elements/mod.rs b/docx-core/src/documents/elements/mod.rs index 33ad843..363f96b 100644 --- a/docx-core/src/documents/elements/mod.rs +++ b/docx-core/src/documents/elements/mod.rs @@ -1,5 +1,21 @@ +mod based_on; 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 use based_on::*; 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::*; diff --git a/docx-core/src/documents/elements/name.rs b/docx-core/src/documents/elements/name.rs new file mode 100644 index 0000000..efe5e5c --- /dev/null +++ b/docx-core/src/documents/elements/name.rs @@ -0,0 +1,35 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct Name { + name: String, +} + +impl Name { + pub fn new(name: impl Into) -> Name { + Name { name: name.into() } + } +} + +impl BuildXML for Name { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.name(&self.name).build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = Name::new("Heading"); + let b = c.build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + } +} diff --git a/docx-core/src/documents/elements/next.rs b/docx-core/src/documents/elements/next.rs new file mode 100644 index 0000000..2de586f --- /dev/null +++ b/docx-core/src/documents/elements/next.rs @@ -0,0 +1,35 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct Next { + val: String, +} + +impl Next { + pub fn new(val: impl Into) -> Next { + Next { val: val.into() } + } +} + +impl BuildXML for Next { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.next(&self.val).build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_next() { + let c = Next::new("Normal"); + let b = c.build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + } +} diff --git a/docx-core/src/documents/elements/paragraph_property.rs b/docx-core/src/documents/elements/paragraph_property.rs new file mode 100644 index 0000000..29071ac --- /dev/null +++ b/docx-core/src/documents/elements/paragraph_property.rs @@ -0,0 +1,36 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct ParagraphProperty {} + +// 17.3.1.26 +// pPr (Paragraph Properties) +// This element specifies a set of paragraph properties which shall be applied to the contents of the parent +// paragraph after all style/numbering/table properties have been applied to the text. These properties are defined +// as direct formatting, since they are directly applied to the paragraph and supersede any formatting from styles. +impl ParagraphProperty { + pub fn new() -> ParagraphProperty { + ParagraphProperty {} + } +} + +impl BuildXML for ParagraphProperty { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.open_paragraph_property().close().build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use std::str; + + #[test] + fn test_build() { + let c = ParagraphProperty::new(); + let b = c.build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + } +} diff --git a/docx-core/src/documents/elements/q_format.rs b/docx-core/src/documents/elements/q_format.rs new file mode 100644 index 0000000..3e1c8b4 --- /dev/null +++ b/docx-core/src/documents/elements/q_format.rs @@ -0,0 +1,39 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +//17.7.4.14 +// qFormat (Primary Style) +// This element specifies whether this style shall be treated as a primary style when this document is loaded by an +// application. If this element is set, then this style has been designated as being particularly important for the +// current document, and this information can be used by an application in any means desired. [Note: This setting +// 637ECMA-376 Part 1 does not imply any behavior for the style, only that the style is of particular significance for this document. end note] +pub struct QFormat {} + +impl QFormat { + pub fn new() -> QFormat { + QFormat {} + } +} + +impl BuildXML for QFormat { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.q_format().build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_q_format() { + let c = QFormat::new(); + let b = c.build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + } +} diff --git a/docx-core/src/documents/elements/run_property.rs b/docx-core/src/documents/elements/run_property.rs new file mode 100644 index 0000000..3b704ff --- /dev/null +++ b/docx-core/src/documents/elements/run_property.rs @@ -0,0 +1,50 @@ +use super::Sz; +use crate::documents::BuildXML; +use crate::xml_builder::*; + +pub struct RunProperty { + sz: Option, +} + +impl RunProperty { + pub fn new() -> RunProperty { + RunProperty { sz: None } + } + + pub fn add_sz(mut self, sz: Sz) -> RunProperty { + self.sz = Some(sz); + self + } +} + +impl BuildXML for RunProperty { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + let b = b.open_run_property(); + let b = if let Some(sz) = &self.sz { + b.add_child_buffer(&sz.build()) + } else { + b + }; + b.close().build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = RunProperty::new().add_sz(Sz::new(10)); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/documents/elements/run_property_default.rs b/docx-core/src/documents/elements/run_property_default.rs index 7b9fedb..4d90e7d 100644 --- a/docx-core/src/documents/elements/run_property_default.rs +++ b/docx-core/src/documents/elements/run_property_default.rs @@ -1,18 +1,26 @@ +use super::RunProperty; use crate::documents::BuildXML; use crate::xml_builder::*; -pub struct RunPropertyDefault {} +pub struct RunPropertyDefault { + run_property: RunProperty, +} impl RunPropertyDefault { pub fn new() -> RunPropertyDefault { - RunPropertyDefault {} + let run_property = RunProperty::new(); + RunPropertyDefault { run_property } } } impl BuildXML for RunPropertyDefault { fn build(&self) -> Vec { let b = XMLBuilder::new(); - b.open_run_property_default().close().build() + let run_property = self.run_property.build(); + b.open_run_property_default() + .add_child_buffer(&run_property) + .close() + .build() } } @@ -26,6 +34,9 @@ mod tests { fn test_build() { let c = RunPropertyDefault::new(); let b = c.build(); - assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#""# + ); } } diff --git a/docx-core/src/documents/elements/style.rs b/docx-core/src/documents/elements/style.rs new file mode 100644 index 0000000..9e1acb6 --- /dev/null +++ b/docx-core/src/documents/elements/style.rs @@ -0,0 +1,71 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +use super::{BasedOn, Name, Next, ParagraphProperty, QFormat, RunProperty}; + +pub struct Style { + style_id: String, + name: Name, + style_type: StyleType, + run_property: RunProperty, + paragraph_property: ParagraphProperty, +} + +impl Style { + pub fn new( + style_id: impl Into, + name: impl Into, + style_type: StyleType, + ) -> Style { + let name = Name::new(name.into()); + let rpr = RunProperty::new(); + let ppr = ParagraphProperty::new(); + Style { + style_id: style_id.into(), + style_type, + name, + run_property: rpr, + paragraph_property: ppr, + } + } +} + +impl BuildXML for Style { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + let name = self.name.build(); + let rpr = self.run_property.build(); + let ppr = self.paragraph_property.build(); + let based_on = BasedOn::new("Normal").build(); + let next = Next::new("Normal").build(); + let q_format = QFormat::new().build(); + b.open_style(self.style_type, &self.style_id) + .add_child_buffer(&name) + .add_child_buffer(&rpr) + .add_child_buffer(&ppr) + .add_child_buffer(&based_on) + .add_child_buffer(&next) + .add_child_buffer(&q_format) + .close() + .build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = Style::new("Heading", "Heading1", StyleType::Paragraph); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/documents/elements/sz.rs b/docx-core/src/documents/elements/sz.rs new file mode 100644 index 0000000..35f7505 --- /dev/null +++ b/docx-core/src/documents/elements/sz.rs @@ -0,0 +1,37 @@ +use crate::documents::BuildXML; +use crate::xml_builder::*; + +use super::Name; + +pub struct Sz { + val: usize, +} + +impl Sz { + pub fn new(val: usize) -> Sz { + Sz { val } + } +} + +impl BuildXML for Sz { + fn build(&self) -> Vec { + let b = XMLBuilder::new(); + b.sz(self.val).build() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_build() { + let c = Sz::new(20); + let b = c.build(); + assert_eq!(str::from_utf8(&b).unwrap(), r#""#); + } +} diff --git a/docx-core/src/xml_builder/elements/based_on.rs b/docx-core/src/xml_builder/elements/based_on.rs new file mode 100644 index 0000000..6147bb7 --- /dev/null +++ b/docx-core/src/xml_builder/elements/based_on.rs @@ -0,0 +1,26 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + only_str_val_el!(based_on, "w:basedOn"); +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_based_on() { + let b = XMLBuilder::new(); + let r = b.based_on("Normal").build(); + assert_eq!( + str::from_utf8(&r).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/xml_builder/elements/macros.rs b/docx-core/src/xml_builder/elements/macros.rs new file mode 100644 index 0000000..3aed0cf --- /dev/null +++ b/docx-core/src/xml_builder/elements/macros.rs @@ -0,0 +1,21 @@ +macro_rules! only_str_val_el { + ($name: ident, $el_name: expr) => { + pub(crate) fn $name(mut self, val: &str) -> Self { + self.writer + .write(XmlEvent::start_element($el_name).attr("w:val", val)) + .expect("should write to buf"); + self.close() + } + }; +} + +macro_rules! only_usize_val_el { + ($name: ident, $el_name: expr) => { + pub(crate) fn $name(mut self, val: usize) -> Self { + self.writer + .write(XmlEvent::start_element($el_name).attr("w:val", val)) + .expect("should write to buf"); + self.close() + } + }; +} diff --git a/docx-core/src/xml_builder/elements/mod.rs b/docx-core/src/xml_builder/elements/mod.rs index 33ad843..7d69ea5 100644 --- a/docx-core/src/xml_builder/elements/mod.rs +++ b/docx-core/src/xml_builder/elements/mod.rs @@ -1,5 +1,27 @@ -mod doc_defaults; -mod run_property_default; +#[macro_use] +mod macros; +mod based_on; +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 use based_on::*; 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; diff --git a/docx-core/src/xml_builder/elements/name.rs b/docx-core/src/xml_builder/elements/name.rs new file mode 100644 index 0000000..ff04b9d --- /dev/null +++ b/docx-core/src/xml_builder/elements/name.rs @@ -0,0 +1,25 @@ +use std::fmt; + +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + only_str_val_el!(name, "w:name"); +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_name() { + let b = XMLBuilder::new(); + let r = b.name("Heading").build(); + assert_eq!(str::from_utf8(&r).unwrap(), r#""#); + } +} diff --git a/docx-core/src/xml_builder/elements/next.rs b/docx-core/src/xml_builder/elements/next.rs new file mode 100644 index 0000000..6cd8c42 --- /dev/null +++ b/docx-core/src/xml_builder/elements/next.rs @@ -0,0 +1,28 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + pub(crate) fn next(mut self, val: &str) -> Self { + self.writer + .write(XmlEvent::start_element("w:next").attr("w:val", val)) + .expect("should write to buf"); + self.close() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_next() { + let b = XMLBuilder::new(); + let r = b.next("Normal").build(); + assert_eq!(str::from_utf8(&r).unwrap(), r#""#); + } +} diff --git a/docx-core/src/xml_builder/elements/paragraph_property.rs b/docx-core/src/xml_builder/elements/paragraph_property.rs new file mode 100644 index 0000000..bc8bff3 --- /dev/null +++ b/docx-core/src/xml_builder/elements/paragraph_property.rs @@ -0,0 +1,6 @@ +use super::super::XmlEvent; +use crate::xml_builder::*; + +impl XMLBuilder { + opened_el!(open_paragraph_property, "w:pPr"); +} diff --git a/docx-core/src/xml_builder/elements/q_format.rs b/docx-core/src/xml_builder/elements/q_format.rs new file mode 100644 index 0000000..5100997 --- /dev/null +++ b/docx-core/src/xml_builder/elements/q_format.rs @@ -0,0 +1,23 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + closed_el!(q_format, "w:qFormat"); +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_q_format() { + let b = XMLBuilder::new(); + let r = b.q_format().build(); + assert_eq!(str::from_utf8(&r).unwrap(), r#""#); + } +} diff --git a/docx-core/src/xml_builder/elements/run_property.rs b/docx-core/src/xml_builder/elements/run_property.rs new file mode 100644 index 0000000..f50a7ed --- /dev/null +++ b/docx-core/src/xml_builder/elements/run_property.rs @@ -0,0 +1,6 @@ +use super::super::XmlEvent; +use crate::xml_builder::*; + +impl XMLBuilder { + opened_el!(open_run_property, "w:rPr"); +} diff --git a/docx-core/src/xml_builder/elements/style.rs b/docx-core/src/xml_builder/elements/style.rs new file mode 100644 index 0000000..bd84c15 --- /dev/null +++ b/docx-core/src/xml_builder/elements/style.rs @@ -0,0 +1,56 @@ +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"), + } + } +} + +impl XMLBuilder { + // 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("should write to buf"); + self + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[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#""# + ); + } +} diff --git a/docx-core/src/xml_builder/elements/sz.rs b/docx-core/src/xml_builder/elements/sz.rs new file mode 100644 index 0000000..806f883 --- /dev/null +++ b/docx-core/src/xml_builder/elements/sz.rs @@ -0,0 +1,28 @@ +use super::XMLBuilder; +use super::XmlEvent; + +impl XMLBuilder { + // i.e. + pub(crate) fn sz(mut self, val: usize) -> Self { + self.writer + .write(XmlEvent::start_element("w:sz").attr("w:val", &format!("{}", val))) + .expect("should write to buf"); + self.close() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_name() { + let b = XMLBuilder::new(); + let r = b.sz(20).build(); + assert_eq!(str::from_utf8(&r).unwrap(), r#""#); + } +} diff --git a/docx-core/src/xml_builder/macros.rs b/docx-core/src/xml_builder/macros.rs index f0a0da5..1a1caff 100644 --- a/docx-core/src/xml_builder/macros.rs +++ b/docx-core/src/xml_builder/macros.rs @@ -97,6 +97,14 @@ macro_rules! closed_el_with_child { } macro_rules! closed_el { + ($name: ident, $el_name: expr) => { + pub(crate) fn $name(mut self) -> Self { + self.writer + .write(XmlEvent::start_element($el_name)) + .expect("should write to buf"); + self.close() + } + }; ($name: ident, $el_name: expr, $attr0: expr) => { pub(crate) fn $name(mut self, arg0: &str) -> Self { self.writer diff --git a/docx-core/src/xml_builder/mod.rs b/docx-core/src/xml_builder/mod.rs index 5453463..3d6474c 100644 --- a/docx-core/src/xml_builder/mod.rs +++ b/docx-core/src/xml_builder/mod.rs @@ -1,17 +1,17 @@ #[macro_use] mod macros; + mod core_properties; mod declaration; mod elements; mod properties; mod relationship; -use std::io::BufReader; use std::str; use xml::common::XmlVersion; use xml::writer::{EmitterConfig, EventWriter, XmlEvent}; -use xml::reader::EventReader; +pub use elements::*; pub struct XMLBuilder { writer: EventWriter>,