feat: Support custom numbering

main
bokuweb 2019-12-07 02:15:21 +09:00
parent 7dff9e771d
commit 182f82e9a0
12 changed files with 78 additions and 54 deletions

View File

@ -9,7 +9,7 @@ pub struct Level<'a> {
format: NumberFormat<'a>,
text: LevelText<'a>,
jc: LevelJc<'a>,
paragraph_property: ParagraphProperty<'a>,
paragraph_property: ParagraphProperty,
}
impl<'a> Level<'a> {

View File

@ -3,12 +3,12 @@ use crate::xml_builder::*;
#[derive(Debug, Clone)]
pub struct Numbering<'a> {
id: &'a str,
id: usize,
levels: Vec<Level<'a>>,
}
impl<'a> Numbering<'a> {
pub fn new(id: &'a str) -> Self {
pub fn new(id: usize) -> Self {
Self { id, levels: vec![] }
}
@ -20,16 +20,13 @@ impl<'a> Numbering<'a> {
impl<'a> BuildXML for Numbering<'a> {
fn build(&self) -> Vec<u8> {
let id = format!("{}", self.id);
let mut b = XMLBuilder::new();
b = b.open_abstract_num(self.id);
b = b.open_abstract_num(&id);
for l in &self.levels {
b = b.add_child(l);
}
b.close()
.open_num(self.id)
.abstract_num_id(self.id)
.close()
.build()
b.close().open_num(&id).abstract_num_id(&id).close().build()
}
}
@ -44,7 +41,7 @@ mod tests {
#[test]
fn test_numbering() {
let mut c = Numbering::new("0");
let mut c = Numbering::new(0);
c = c.add_level(Level::new(
1,
Start::new(1),

View File

@ -2,17 +2,17 @@ use crate::documents::BuildXML;
use crate::xml_builder::*;
#[derive(Debug, Clone)]
pub struct NumberingId<'a> {
id: &'a str,
pub struct NumberingId {
id: usize,
}
impl<'a> NumberingId<'a> {
pub fn new(id: &'a str) -> NumberingId<'a> {
impl NumberingId {
pub fn new(id: usize) -> NumberingId {
NumberingId { id }
}
}
impl<'a> BuildXML for NumberingId<'a> {
impl BuildXML for NumberingId {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
b.num_id(self.id).build()
@ -29,8 +29,8 @@ mod tests {
#[test]
fn test_num_id() {
let c = NumberingId::new("abc");
let c = NumberingId::new(0);
let b = c.build();
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:numId w:val="abc" />"#);
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:numId w:val="0" />"#);
}
}

View File

@ -3,18 +3,18 @@ use crate::documents::BuildXML;
use crate::xml_builder::*;
#[derive(Debug, Clone)]
pub struct NumberingProperty<'a> {
id: NumberingId<'a>,
pub struct NumberingProperty {
id: NumberingId,
level: IndentLevel,
}
impl<'a> NumberingProperty<'a> {
pub fn new(id: NumberingId<'a>, level: IndentLevel) -> NumberingProperty {
impl NumberingProperty {
pub fn new(id: NumberingId, level: IndentLevel) -> NumberingProperty {
Self { id, level }
}
}
impl<'a> BuildXML for NumberingProperty<'a> {
impl BuildXML for NumberingProperty {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
b.open_numbering_property()
@ -35,11 +35,11 @@ mod tests {
#[test]
fn test_num_property() {
let c = NumberingProperty::new(NumberingId::new("abc"), IndentLevel::new(3));
let c = NumberingProperty::new(NumberingId::new(0), IndentLevel::new(3));
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:numPr><w:numId w:val="abc" /><w:ilvl w:val="3" /></w:numPr>"#
r#"<w:numPr><w:numId w:val="0" /><w:ilvl w:val="3" /></w:numPr>"#
);
}
}

View File

@ -6,7 +6,7 @@ use crate::xml_builder::*;
#[derive(Debug, Clone)]
pub struct Paragraph<'a> {
pub(crate) children: Vec<ParagraphChild<'a>>,
property: ParagraphProperty<'a>,
property: ParagraphProperty,
attrs: Vec<(String, String)>,
}
@ -119,7 +119,7 @@ impl<'a> Paragraph<'a> {
self
}
pub fn numbering(mut self, id: NumberingId<'a>, level: IndentLevel) -> Self {
pub fn numbering(mut self, id: NumberingId, level: IndentLevel) -> Self {
self.property = self.property.numbering(id, level);
self
}
@ -205,11 +205,11 @@ mod tests {
fn test_numbering() {
let b = Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.numbering(NumberingId::new("abc"), IndentLevel::new(1))
.numbering(NumberingId::new(0), IndentLevel::new(1))
.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:p><w:pPr><w:pStyle w:val="Normal" /><w:rPr /><w:numPr><w:numId w:val="abc" /><w:ilvl w:val="1" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space="preserve">Hello</w:t></w:r></w:p>"#
r#"<w:p><w:pPr><w:pStyle w:val="Normal" /><w:rPr /><w:numPr><w:numId w:val="0" /><w:ilvl w:val="1" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space="preserve">Hello</w:t></w:r></w:p>"#
);
}
}

View File

@ -6,15 +6,15 @@ use crate::types::{AlignmentType, SpecialIndentType};
use crate::xml_builder::*;
#[derive(Debug, Clone)]
pub struct ParagraphProperty<'a> {
pub struct ParagraphProperty {
run_property: RunProperty,
style: ParagraphStyle,
numbering_property: Option<NumberingProperty<'a>>,
numbering_property: Option<NumberingProperty>,
alignment: Option<Justification>,
indent: Option<Indent>,
}
impl<'a> Default for ParagraphProperty<'a> {
impl Default for ParagraphProperty {
fn default() -> Self {
let s: Option<&str> = None;
ParagraphProperty {
@ -32,8 +32,8 @@ impl<'a> Default for ParagraphProperty<'a> {
// 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<'a> ParagraphProperty<'a> {
pub fn new() -> ParagraphProperty<'a> {
impl ParagraphProperty {
pub fn new() -> ParagraphProperty {
Default::default()
}
@ -52,13 +52,13 @@ impl<'a> ParagraphProperty<'a> {
self
}
pub fn numbering(mut self, id: NumberingId<'a>, level: IndentLevel) -> Self {
pub fn numbering(mut self, id: NumberingId, level: IndentLevel) -> Self {
self.numbering_property = Some(NumberingProperty::new(id, level));
self
}
}
impl<'a> BuildXML for ParagraphProperty<'a> {
impl BuildXML for ParagraphProperty {
fn build(&self) -> Vec<u8> {
XMLBuilder::new()
.open_paragraph_property()

View File

@ -5,15 +5,15 @@ use crate::StyleType;
use super::{BasedOn, Name, Next, ParagraphProperty, QFormat, RunProperty};
#[derive(Debug)]
pub struct Style<'a> {
pub struct Style {
style_id: String,
name: Name,
style_type: StyleType,
run_property: RunProperty,
paragraph_property: ParagraphProperty<'a>,
paragraph_property: ParagraphProperty,
}
impl<'a> Default for Style<'a> {
impl Default for Style {
fn default() -> Self {
let name = Name::new("");
let rpr = RunProperty::new();
@ -28,7 +28,7 @@ impl<'a> Default for Style<'a> {
}
}
impl<'a> Style<'a> {
impl Style {
pub fn new(
style_id: impl Into<String>,
name: impl Into<String>,
@ -65,7 +65,7 @@ impl<'a> Style<'a> {
}
}
impl<'a> BuildXML for Style<'a> {
impl BuildXML for Style {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
// Set "Normal" as default if you need change these values please fix it

View File

@ -35,7 +35,7 @@ pub struct Docx<'a> {
rels: Rels,
document_rels: DocumentRels,
doc_props: DocProps<'a>,
styles: Styles<'a>,
styles: Styles,
document: Document<'a>,
comments: Comments<'a>,
numberings: Numberings<'a>,

View File

@ -37,7 +37,7 @@ impl<'a> BuildXML for Numberings<'a> {
}
fn create_default_numbering() -> Numbering<'static> {
Numbering::new("0")
Numbering::new(0)
.add_level(
Level::new(
0,

View File

@ -4,23 +4,23 @@ use crate::types::*;
use crate::xml_builder::*;
#[derive(Debug)]
pub struct Styles<'a> {
pub struct Styles {
doc_defaults: DocDefaults,
styles: Vec<Style<'a>>,
styles: Vec<Style>,
}
impl<'a> Styles<'a> {
pub fn new() -> Styles<'a> {
impl Styles {
pub fn new() -> Styles {
Default::default()
}
pub fn add_style(mut self, style: Style<'a>) -> Self {
pub fn add_style(mut self, style: Style) -> Self {
self.styles.push(style);
self
}
}
impl<'a> Default for Styles<'a> {
impl Default for Styles {
fn default() -> Self {
Self {
doc_defaults: DocDefaults::new(),
@ -29,7 +29,7 @@ impl<'a> Default for Styles<'a> {
}
}
impl<'a> BuildXML for Styles<'a> {
impl BuildXML for Styles {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
let normal = Style::new("Normal", "Normal", StyleType::Paragraph);

View File

@ -191,7 +191,7 @@ impl XMLBuilder {
opened_el!(open_num, "w:num", "w:numId");
opened_el!(open_numbering_property, "w:numPr");
only_usize_val_el!(indent_level, "w:ilvl");
only_str_val_el!(num_id, "w:numId");
only_usize_val_el!(num_id, "w:numId");
only_usize_val_el!(start, "w:start");
only_str_val_el!(number_format, "w:numFmt");
only_str_val_el!(level_text, "w:lvlText");

View File

@ -323,22 +323,49 @@ pub fn default_numbering() -> Result<(), DocxError> {
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.numbering(NumberingId::new("0"), IndentLevel::new(0)),
.numbering(NumberingId::new(0), IndentLevel::new(0)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("World!"))
.numbering(NumberingId::new("0"), IndentLevel::new(1)),
.numbering(NumberingId::new(0), IndentLevel::new(1)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Foooo!"))
.numbering(NumberingId::new("0"), IndentLevel::new(2)),
.numbering(NumberingId::new(0), IndentLevel::new(2)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Bar!"))
.numbering(NumberingId::new("0"), IndentLevel::new(3)),
.numbering(NumberingId::new(0), IndentLevel::new(3)),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn user_numbering() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/user_numbering.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.numbering(NumberingId::new(2), IndentLevel::new(0)),
)
.add_numbering(
Numbering::new(2).add_level(
Level::new(
0,
Start::new(1),
NumberFormat::new("decimal"),
LevelText::new("Section %1."),
LevelJc::new("left"),
)
.indent(1620, Some(SpecialIndentType::Hanging(320))),
),
)
.build()
.pack(file)?;