feat: Support space:preserve
parent
37d4a157d5
commit
517c3b0b9f
|
@ -5,18 +5,21 @@ use crate::xml_builder::*;
|
|||
#[derive(Debug)]
|
||||
pub struct Text {
|
||||
text: String,
|
||||
preserve_space: bool,
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn new(text: impl Into<String>) -> Text {
|
||||
Text { text: text.into() }
|
||||
Text {
|
||||
text: text.into(),
|
||||
preserve_space: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for Text {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
let b = XMLBuilder::new();
|
||||
b.text(&self.text).build()
|
||||
XMLBuilder::new().text(&self.text, true).build()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,11 @@ pub fn simple() {
|
|||
let path = std::path::Path::new("./test.docx");
|
||||
let file = std::fs::File::create(&path).unwrap();
|
||||
Docx::new()
|
||||
.add_paragraph(Paragraph::new().add_run(Run::new("Hello")))
|
||||
.add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(Run::new("Hello"))
|
||||
.add_run(Run::new(" World")),
|
||||
)
|
||||
.build()
|
||||
.pack(file);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
use crate::types::*;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:body... >
|
||||
opened_el!(open_body, "w:body");
|
||||
// i.e. <w:basedOn ... >
|
||||
only_str_val_el!(based_on, "w:basedOn");
|
||||
// i.e. <w:t ... >
|
||||
// i.e. <w:sz ... >
|
||||
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("should write to buf");
|
||||
self.writer.write(text).expect("should write to buf");
|
||||
self.close()
|
||||
}
|
||||
// i.e. <w:r ... >
|
||||
opened_el!(open_run, "w:r");
|
||||
opened_el!(open_run_property, "w:rPr");
|
||||
opened_el!(open_run_property_default, "w:rPrDefault");
|
||||
// i.e. <w:qFormat ... >
|
||||
closed_el!(q_format, "w:qFormat");
|
||||
// i.e. <w:p ... >
|
||||
opened_el!(open_paragraph, "w:p");
|
||||
opened_el!(open_paragraph_property, "w:pPr");
|
||||
opened_el!(open_doc_defaults, "w:docDefaults");
|
||||
// i.e. <w:name ... >
|
||||
only_str_val_el!(name, "w:name");
|
||||
// i.e. <w:sz ... >
|
||||
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()
|
||||
}
|
||||
// Build w:style element
|
||||
// i.e. <w:style ... >
|
||||
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
|
||||
}
|
||||
// i.e. <w:next ... >
|
||||
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()
|
||||
}
|
||||
|
||||
// i.e. <w:color ... >
|
||||
pub(crate) fn color(mut self, val: &str) -> Self {
|
||||
self.writer
|
||||
.write(XmlEvent::start_element("w:color").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_sz() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.sz(20).build();
|
||||
assert_eq!(str::from_utf8(&r).unwrap(), r#"<w:sz w:val="20" />"#);
|
||||
}
|
||||
|
||||
#[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#"<w:style w:type="paragraph" w:styleId="Heading" />"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_next() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.next("Normal").build();
|
||||
assert_eq!(str::from_utf8(&r).unwrap(), r#"<w:next w:val="Normal" />"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_name() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.name("Heading").build();
|
||||
assert_eq!(str::from_utf8(&r).unwrap(), r#"<w:name w:val="Heading" />"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_color() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.color("2E74B5").build();
|
||||
assert_eq!(str::from_utf8(&r).unwrap(), r#"<w:color w:val="2E74B5" />"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_based_on() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.based_on("Normal").build();
|
||||
assert_eq!(
|
||||
str::from_utf8(&r).unwrap(),
|
||||
r#"<w:basedOn w:val="Normal" />"#
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:basedOn ... >
|
||||
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#"<w:basedOn w:val="Normal" />"#
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:body... >
|
||||
opened_el!(open_body, "w:body");
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:color ... >
|
||||
pub(crate) fn color(mut self, val: &str) -> Self {
|
||||
self.writer
|
||||
.write(XmlEvent::start_element("w:color").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_color() {
|
||||
let b = XMLBuilder::new();
|
||||
let r = b.color("2E74B5").build();
|
||||
assert_eq!(str::from_utf8(&r).unwrap(), r#"<w:color w:val="2E74B5" />"#);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
use super::super::XmlEvent;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
impl XMLBuilder {
|
||||
opened_el!(open_doc_defaults, "w:docDefaults");
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
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()
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
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;
|
||||
|
||||
use super::{XMLBuilder, XmlEvent};
|
|
@ -1,25 +0,0 @@
|
|||
use std::fmt;
|
||||
|
||||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:name ... >
|
||||
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#"<w:name w:val="Heading" />"#);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:next ... >
|
||||
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#"<w:next w:val="Normal" />"#);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:p ... >
|
||||
opened_el!(open_paragraph, "w:p");
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
use super::super::XmlEvent;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
impl XMLBuilder {
|
||||
opened_el!(open_paragraph_property, "w:pPr");
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:qFormat ... >
|
||||
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#"<w:qFormat />"#);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:r ... >
|
||||
opened_el!(open_run, "w:r");
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
use super::super::XmlEvent;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
impl XMLBuilder {
|
||||
opened_el!(open_run_property, "w:rPr");
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
use super::super::XmlEvent;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
impl XMLBuilder {
|
||||
opened_el!(open_run_property_default, "w:rPrDefault");
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
use super::{XMLBuilder, XmlEvent};
|
||||
use crate::StyleType;
|
||||
|
||||
impl XMLBuilder {
|
||||
// Build w:style element
|
||||
// i.e. <w:style ... >
|
||||
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#"<w:style w:type="paragraph" w:styleId="Heading" />"#
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:sz ... >
|
||||
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#"<w:sz w:val="20" />"#);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use super::XMLBuilder;
|
||||
use super::XmlEvent;
|
||||
|
||||
impl XMLBuilder {
|
||||
// i.e. <w:t ... >
|
||||
closed_el_with_child!(text, "w:t");
|
||||
}
|
|
@ -130,3 +130,25 @@ macro_rules! closed_el {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue