feat: Support alignment
parent
517c3b0b9f
commit
879189da3c
|
@ -4,4 +4,5 @@ dist
|
||||||
node_modules
|
node_modules
|
||||||
pkg
|
pkg
|
||||||
*.docx#
|
*.docx#
|
||||||
test.docx
|
test.docx
|
||||||
|
output/*.docx
|
|
@ -0,0 +1,15 @@
|
||||||
|
use docx_core::*;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let path = std::path::Path::new("./output/alignment.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(" World"))
|
||||||
|
.align(AlignmentType::Right),
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
.pack(file);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
use crate::documents::BuildXML;
|
||||||
|
use crate::xml_builder::*;
|
||||||
|
|
||||||
|
// 22.1.2.51
|
||||||
|
// jc (Justification)
|
||||||
|
// This element specifies justification of the math paragraph (a series of adjacent instances of mathematical text
|
||||||
|
// within the same paragraph). A math paragraph can be Left Justified, Right Justified, Centered, or Centered as
|
||||||
|
// Group. If this element is omitted, the math paragraph is Centered as Group. Whether the element is absent or
|
||||||
|
// present without the val attribute, the default of the val attribute is centerGroup . This means that the instances
|
||||||
|
// of mathematical text can be aligned with respect to each other, but the entire group of mathematical text is
|
||||||
|
// centered as a whole.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Justification {
|
||||||
|
val: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Justification {
|
||||||
|
pub fn new(val: impl Into<String>) -> Justification {
|
||||||
|
Justification { val: val.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildXML for Justification {
|
||||||
|
fn build(&self) -> Vec<u8> {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
b.justification(&self.val).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[cfg(test)]
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_justification() {
|
||||||
|
let c = Justification::new("start");
|
||||||
|
let b = c.build();
|
||||||
|
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:jc w:val="start" />"#);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
mod based_on;
|
mod based_on;
|
||||||
mod color;
|
mod color;
|
||||||
mod doc_defaults;
|
mod doc_defaults;
|
||||||
|
mod justification;
|
||||||
mod name;
|
mod name;
|
||||||
mod next;
|
mod next;
|
||||||
mod paragraph;
|
mod paragraph;
|
||||||
|
@ -16,6 +17,7 @@ mod text;
|
||||||
pub use based_on::*;
|
pub use based_on::*;
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
pub use doc_defaults::*;
|
pub use doc_defaults::*;
|
||||||
|
pub use justification::*;
|
||||||
pub use name::*;
|
pub use name::*;
|
||||||
pub use next::*;
|
pub use next::*;
|
||||||
pub use paragraph::*;
|
pub use paragraph::*;
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
use super::{Run, RunProperty, Text};
|
use super::{ParagraphProperty, Run, RunProperty, Text};
|
||||||
use crate::documents::BuildXML;
|
use crate::documents::BuildXML;
|
||||||
|
use crate::types::*;
|
||||||
use crate::xml_builder::*;
|
use crate::xml_builder::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Paragraph {
|
pub struct Paragraph {
|
||||||
runs: Vec<Run>,
|
runs: Vec<Run>,
|
||||||
|
property: ParagraphProperty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Paragraph {
|
impl Default for Paragraph {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { runs: Vec::new() }
|
Self {
|
||||||
|
runs: Vec::new(),
|
||||||
|
property: ParagraphProperty::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +27,18 @@ impl Paragraph {
|
||||||
self.runs.push(run);
|
self.runs.push(run);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn align(mut self, alignment_type: AlignmentType) -> Paragraph {
|
||||||
|
self.property = self.property.align(alignment_type);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildXML for Paragraph {
|
impl BuildXML for Paragraph {
|
||||||
fn build(&self) -> Vec<u8> {
|
fn build(&self) -> Vec<u8> {
|
||||||
XMLBuilder::new()
|
XMLBuilder::new()
|
||||||
.open_paragraph()
|
.open_paragraph()
|
||||||
|
.add_child(&self.property)
|
||||||
.add_children(&self.runs)
|
.add_children(&self.runs)
|
||||||
.close()
|
.close()
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
|
use super::Justification;
|
||||||
use crate::documents::BuildXML;
|
use crate::documents::BuildXML;
|
||||||
|
use crate::types::AlignmentType;
|
||||||
use crate::xml_builder::*;
|
use crate::xml_builder::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParagraphProperty {}
|
pub struct ParagraphProperty {
|
||||||
|
alignment: Option<Justification>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ParagraphProperty {
|
||||||
|
fn default() -> Self {
|
||||||
|
ParagraphProperty { alignment: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 17.3.1.26
|
// 17.3.1.26
|
||||||
// pPr (Paragraph Properties)
|
// pPr (Paragraph Properties)
|
||||||
|
@ -11,14 +21,22 @@ pub struct ParagraphProperty {}
|
||||||
// as direct formatting, since they are directly applied to the paragraph and supersede any formatting from styles.
|
// as direct formatting, since they are directly applied to the paragraph and supersede any formatting from styles.
|
||||||
impl ParagraphProperty {
|
impl ParagraphProperty {
|
||||||
pub fn new() -> ParagraphProperty {
|
pub fn new() -> ParagraphProperty {
|
||||||
ParagraphProperty {}
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align(mut self, alignment_type: AlignmentType) -> ParagraphProperty {
|
||||||
|
self.alignment = Some(Justification::new(alignment_type.to_string()));
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildXML for ParagraphProperty {
|
impl BuildXML for ParagraphProperty {
|
||||||
fn build(&self) -> Vec<u8> {
|
fn build(&self) -> Vec<u8> {
|
||||||
let b = XMLBuilder::new();
|
let b = XMLBuilder::new();
|
||||||
b.open_paragraph_property().close().build()
|
let p = b
|
||||||
|
.open_paragraph_property()
|
||||||
|
.add_optional_child(&self.alignment);
|
||||||
|
p.close().build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ mod tests {
|
||||||
let b = Run::new("Hello").build();
|
let b = Run::new("Hello").build();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
str::from_utf8(&b).unwrap(),
|
str::from_utf8(&b).unwrap(),
|
||||||
r#"<w:r><w:rPr /><w:t>Hello</w:t></w:r>"#
|
r#"<w:r><w:rPr /><w:t xml:space="preserve">Hello</w:t></w:r>"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build() {
|
fn test_build() {
|
||||||
let b = Text::new("Hello").build();
|
let b = Text::new("Hello").build();
|
||||||
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:t>Hello</w:t>"#);
|
assert_eq!(
|
||||||
|
str::from_utf8(&b).unwrap(),
|
||||||
|
r#"<w:t xml:space="preserve">Hello</w:t>"#
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,8 @@ pub fn simple() {
|
||||||
let path = std::path::Path::new("./test.docx");
|
let path = std::path::Path::new("./test.docx");
|
||||||
let file = std::fs::File::create(&path).unwrap();
|
let file = std::fs::File::create(&path).unwrap();
|
||||||
Docx::new()
|
Docx::new()
|
||||||
.add_paragraph(
|
.add_paragraph(Paragraph::new().add_run(Run::new("Hello")))
|
||||||
Paragraph::new()
|
.add_paragraph(Paragraph::new().add_run(Run::new(" World")))
|
||||||
.add_run(Run::new("Hello"))
|
|
||||||
.add_run(Run::new(" World")),
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
.pack(file);
|
.pack(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
use std::fmt;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum AlignmentType {
|
||||||
|
Center,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Justified,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AlignmentType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
AlignmentType::Center => write!(f, "center"),
|
||||||
|
AlignmentType::Left => write!(f, "left"),
|
||||||
|
AlignmentType::Right => write!(f, "right"),
|
||||||
|
AlignmentType::Justified => write!(f, "justified"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub mod alignment_type;
|
||||||
pub mod style_type;
|
pub mod style_type;
|
||||||
|
|
||||||
|
pub use alignment_type::*;
|
||||||
pub use style_type::*;
|
pub use style_type::*;
|
||||||
|
|
|
@ -33,6 +33,10 @@ impl XMLBuilder {
|
||||||
opened_el!(open_doc_defaults, "w:docDefaults");
|
opened_el!(open_doc_defaults, "w:docDefaults");
|
||||||
// i.e. <w:name ... >
|
// i.e. <w:name ... >
|
||||||
only_str_val_el!(name, "w:name");
|
only_str_val_el!(name, "w:name");
|
||||||
|
// i.e. <w:jc ... >
|
||||||
|
only_str_val_el!(justification, "w:jc");
|
||||||
|
// i.e. <w:pStyle ... >
|
||||||
|
only_str_val_el!(p_style, "w:pStyle");
|
||||||
// i.e. <w:sz ... >
|
// i.e. <w:sz ... >
|
||||||
pub(crate) fn sz(mut self, val: usize) -> Self {
|
pub(crate) fn sz(mut self, val: usize) -> Self {
|
||||||
self.writer
|
self.writer
|
||||||
|
|
Loading…
Reference in New Issue