Support start chars (#51)

* feat: suport start char for writer

* support start char and add option to indent start

* fix:lint error

* fix: lint
main
bokuweb 2020-03-10 11:56:12 +09:00 committed by GitHub
parent 4378de2ecc
commit 6f54e5e493
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 211 additions and 76 deletions

View File

@ -6,22 +6,25 @@ pub fn main() -> Result<(), DocxError> {
let path = std::path::Path::new("./output/indent.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text(DUMMY))
.indent(840, None, None),
)
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
840,
Some(SpecialIndentType::FirstLine(720)),
Some(840),
None,
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
1560,
Some(840),
Some(SpecialIndentType::FirstLine(720)),
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
Some(1560),
Some(SpecialIndentType::Hanging(720)),
None,
None,
))
.build()
.pack(file)?;

View File

@ -18,7 +18,12 @@ pub fn main() -> Result<(), DocxError> {
LevelText::new("Section %1."),
LevelJc::new("left"),
)
.indent(1620, Some(SpecialIndentType::Hanging(320)), None),
.indent(
Some(1620),
Some(SpecialIndentType::Hanging(320)),
None,
None,
),
),
)
.add_numbering(Numbering::new(2, 2))

View File

@ -7,15 +7,22 @@ use crate::xml_builder::*;
#[derive(Debug, Clone, PartialEq)]
pub struct Indent {
start: i32,
start: Option<i32>,
end: Option<i32>,
special_indent: Option<SpecialIndentType>,
start_chars: Option<i32>,
}
impl Indent {
pub fn new(start: i32, special_indent: Option<SpecialIndentType>, end: Option<i32>) -> Indent {
pub fn new(
start: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: Option<i32>,
start_chars: Option<i32>,
) -> Indent {
Indent {
start,
start_chars,
end,
special_indent,
}
@ -34,6 +41,7 @@ impl BuildXML for Indent {
self.start,
self.special_indent,
self.end.unwrap_or_default(),
self.start_chars,
)
.build()
}
@ -46,6 +54,7 @@ impl Serialize for Indent {
{
let mut t = serializer.serialize_struct("Indent", 3)?;
t.serialize_field("start", &self.start)?;
t.serialize_field("startChars", &self.start_chars)?;
t.serialize_field("end", &self.end)?;
t.serialize_field("specialIndent", &self.special_indent)?;
t.end()
@ -62,7 +71,7 @@ mod tests {
#[test]
fn test_left() {
let b = Indent::new(20, None, None).build();
let b = Indent::new(Some(20), None, None, None).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:ind w:left="20" w:right="0" />"#
@ -71,7 +80,7 @@ mod tests {
#[test]
fn test_first_line() {
let b = Indent::new(20, Some(SpecialIndentType::FirstLine(40)), None).build();
let b = Indent::new(Some(20), Some(SpecialIndentType::FirstLine(40)), None, None).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:ind w:left="20" w:right="0" w:firstLine="40" />"#
@ -80,7 +89,7 @@ mod tests {
#[test]
fn test_hanging() {
let b = Indent::new(20, Some(SpecialIndentType::Hanging(50)), None).build();
let b = Indent::new(Some(20), Some(SpecialIndentType::Hanging(50)), None, None).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:ind w:left="20" w:right="0" w:hanging="50" />"#

View File

@ -37,11 +37,14 @@ impl Level {
pub fn indent(
mut self,
left: i32,
left: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: Option<i32>,
start_chars: Option<i32>,
) -> Self {
self.paragraph_property = self.paragraph_property.indent(left, special_indent, end);
self.paragraph_property =
self.paragraph_property
.indent(left, special_indent, end, start_chars);
self
}
@ -98,7 +101,7 @@ mod tests {
LevelText::new("%4."),
LevelJc::new("left"),
)
.indent(320, Some(SpecialIndentType::Hanging(200)), None)
.indent(Some(320), Some(SpecialIndentType::Hanging(200)), None, None)
.build();
assert_eq!(
str::from_utf8(&b).unwrap(),

View File

@ -163,11 +163,12 @@ impl Paragraph {
pub fn indent(
mut self,
left: i32,
left: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: Option<i32>,
start_chars: Option<i32>,
) -> Paragraph {
self.property = self.property.indent(left, special_indent, end);
self.property = self.property.indent(left, special_indent, end, start_chars);
self
}

View File

@ -50,11 +50,12 @@ impl ParagraphProperty {
pub fn indent(
mut self,
left: i32,
left: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: Option<i32>,
start_chars: Option<i32>,
) -> Self {
self.indent = Some(Indent::new(left, special_indent, end));
self.indent = Some(Indent::new(left, special_indent, end, start_chars));
self
}
@ -109,7 +110,7 @@ mod tests {
#[test]
fn test_indent() {
let c = ParagraphProperty::new();
let b = c.indent(20, None, None).build();
let b = c.indent(Some(20), None, None, None).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:pPr><w:pStyle w:val="Normal" /><w:rPr /><w:ind w:left="20" w:right="0" /></w:pPr>"#
@ -119,10 +120,10 @@ mod tests {
#[test]
fn test_indent_json() {
let c = ParagraphProperty::new();
let b = c.indent(20, Some(SpecialIndentType::FirstLine(10)), None);
let b = c.indent(Some(20), Some(SpecialIndentType::FirstLine(10)), None, None);
assert_eq!(
serde_json::to_string(&b).unwrap(),
r#"{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"style":"Normal","numberingProperty":null,"alignment":null,"indent":{"start":20,"end":null,"specialIndent":{"type":"firstLine","val":10}}}"#
r#"{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"style":"Normal","numberingProperty":null,"alignment":null,"indent":{"start":20,"startChars":null,"end":null,"specialIndent":{"type":"firstLine","val":10}}}"#
);
}
}

View File

@ -89,11 +89,14 @@ impl Style {
pub fn indent(
mut self,
left: i32,
left: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: Option<i32>,
start_chars: Option<i32>,
) -> Self {
self.paragraph_property = self.paragraph_property.indent(left, special_indent, end);
self.paragraph_property =
self.paragraph_property
.indent(left, special_indent, end, start_chars);
self
}
}

View File

@ -62,7 +62,7 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%1."),
LevelJc::new("left"),
)
.indent(420, Some(SpecialIndentType::Hanging(420)), None),
.indent(Some(420), Some(SpecialIndentType::Hanging(420)), None, None),
)
.add_level(
Level::new(
@ -72,7 +72,7 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("(%2)"),
LevelJc::new("left"),
)
.indent(840, Some(SpecialIndentType::Hanging(420)), None),
.indent(Some(840), Some(SpecialIndentType::Hanging(420)), None, None),
)
.add_level(
Level::new(
@ -82,7 +82,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%3"),
LevelJc::new("left"),
)
.indent(1260, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(1260),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -92,7 +97,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%4."),
LevelJc::new("left"),
)
.indent(1680, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(1680),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -102,7 +112,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("(%5)"),
LevelJc::new("left"),
)
.indent(2100, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(2100),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -112,7 +127,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%6"),
LevelJc::new("left"),
)
.indent(2520, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(2520),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -122,7 +142,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%7."),
LevelJc::new("left"),
)
.indent(2940, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(2940),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -132,7 +157,12 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("(%8)"),
LevelJc::new("left"),
)
.indent(3360, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(3360),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
.add_level(
Level::new(
@ -142,6 +172,11 @@ fn create_default_numbering() -> AbstractNumbering {
LevelText::new("%9"),
LevelJc::new("left"),
)
.indent(3780, Some(SpecialIndentType::Hanging(420)), None),
.indent(
Some(3780),
Some(SpecialIndentType::Hanging(420)),
None,
None,
),
)
}

View File

@ -6,17 +6,28 @@ use crate::types::*;
use super::super::errors::*;
pub fn read_indent(
attrs: &[OwnedAttribute],
) -> Result<(i32, Option<i32>, Option<SpecialIndentType>), ReaderError> {
let mut start = 0;
pub type ReadIndentResult = Result<
(
Option<i32>,
Option<i32>,
Option<SpecialIndentType>,
Option<i32>,
),
ReaderError,
>;
pub fn read_indent(attrs: &[OwnedAttribute]) -> ReadIndentResult {
let mut start: Option<i32> = None;
let mut start_chars: Option<i32> = None;
let mut end: Option<i32> = None;
let mut special: Option<SpecialIndentType> = None;
for a in attrs {
let local_name = &a.name.local_name;
if local_name == "left" || local_name == "start" {
start = i32::from_str(&a.value)?;
start = Some(i32::from_str(&a.value)?);
} else if local_name == "leftChars" || local_name == "startChars" {
start_chars = Some(i32::from_str(&a.value)?);
} else if local_name == "end" || local_name == "right" {
end = Some(i32::from_str(&a.value)?);
} else if local_name == "hanging" {
@ -26,5 +37,5 @@ pub fn read_indent(
}
}
Ok((start, end, special))
Ok((start, end, special, start_chars))
}

View File

@ -18,9 +18,10 @@ impl ElementReader for Level {
let mut level_text = LevelText::new("");
let mut jc = LevelJc::new("left");
let mut indent_start = 0;
let mut indent_start = None;
let mut special_indent = None;
let mut indent_end = None;
let mut start_chars = None;
let mut has_indent = false;
loop {
@ -52,6 +53,7 @@ impl ElementReader for Level {
indent_start = i.0;
indent_end = i.1;
special_indent = i.2;
start_chars = i.3;
has_indent = true;
}
_ => {}
@ -65,7 +67,7 @@ impl ElementReader for Level {
l = l.paragraph_style(style_id);
}
if has_indent {
l = l.indent(indent_start, special_indent, indent_end);
l = l.indent(indent_start, special_indent, indent_end, start_chars);
}
return Ok(l);
}

View File

@ -153,7 +153,12 @@ mod tests {
LevelText::new(""),
LevelJc::new("left"),
)
.indent(720, Some(SpecialIndentType::Hanging(360)), None),
.indent(
Some(720),
Some(SpecialIndentType::Hanging(360)),
None,
None,
),
),
)
.add_numbering(Numbering::new(1, 0));

View File

@ -80,8 +80,8 @@ impl ElementReader for Paragraph {
continue;
}
XMLElement::Indent => {
let (start, end, special) = read_indent(&attributes)?;
p = p.indent(start, special, end);
let (start, end, special, start_chars) = read_indent(&attributes)?;
p = p.indent(start, special, end, start_chars);
continue;
}
XMLElement::Justification => {
@ -147,9 +147,10 @@ mod tests {
numbering_property: None,
alignment: None,
indent: Some(Indent::new(
1470,
Some(1470),
Some(SpecialIndentType::Hanging(0)),
Some(1270)
Some(1270),
None,
)),
},
has_numbering: false,
@ -158,6 +159,40 @@ mod tests {
);
}
#[test]
fn test_read_indent_start_chars() {
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:p>
<w:pPr>
<w:ind w:startChars="100" />
<w:rPr></w:rPr>
</w:pPr>
<w:r>
<w:rPr></w:rPr>
<w:t>a</w:t>
</w:r>
</w:p>
</w:document>"#;
let mut parser = EventReader::new(c.as_bytes());
let p = Paragraph::read(&mut parser, &[]).unwrap();
let s: Option<&str> = None;
assert_eq!(
p,
Paragraph {
children: vec![ParagraphChild::Run(Run::new().add_text("a"))],
property: ParagraphProperty {
run_property: RunProperty::new(),
style: ParagraphStyle::new(s),
numbering_property: None,
alignment: None,
indent: Some(Indent::new(None, None, None, Some(100))),
},
has_numbering: false,
attrs: Vec::new(),
}
);
}
#[test]
fn test_read_jc() {
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

View File

@ -38,8 +38,8 @@ impl ElementReader for Style {
}
// pPr
XMLElement::Indent => {
let (start, end, special) = read_indent(&attributes)?;
style = style.indent(start, special, end);
let (start, end, special, start_chars) = read_indent(&attributes)?;
style = style.indent(start, special, end, start_chars);
continue;
}
XMLElement::Justification => {

View File

@ -89,16 +89,22 @@ impl XMLBuilder {
// i.e. <w:ind ... >
pub(crate) fn indent(
mut self,
start: i32,
start: Option<i32>,
special_indent: Option<SpecialIndentType>,
end: i32,
start_chars: Option<i32>,
) -> Self {
let start = &format!("{}", start);
let start = &format!("{}", start.unwrap_or(0));
let end = &format!("{}", end);
let base = XmlEvent::start_element("w:ind")
let start_chars_value = format!("{}", start_chars.unwrap_or(0));
let mut base = XmlEvent::start_element("w:ind")
.attr("w:left", start)
.attr("w:right", end);
if start_chars.is_some() {
base = base.attr("w:leftChars", &start_chars_value);
}
match special_indent {
Some(SpecialIndentType::FirstLine(v)) => self
.writer

View File

@ -22,22 +22,25 @@ pub fn indent() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/indent.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text(DUMMY))
.indent(840, None, None),
)
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
840,
Some(SpecialIndentType::FirstLine(720)),
Some(840),
None,
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
1560,
Some(840),
Some(SpecialIndentType::FirstLine(720)),
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
Some(1560),
Some(SpecialIndentType::Hanging(720)),
None,
None,
))
.build()
.pack(file)?;
@ -370,7 +373,12 @@ pub fn user_numbering() -> Result<(), DocxError> {
LevelText::new("Section %1."),
LevelJc::new("left"),
)
.indent(1620, Some(SpecialIndentType::Hanging(320)), None),
.indent(
Some(1620),
Some(SpecialIndentType::Hanging(320)),
None,
None,
),
),
)
.add_numbering(Numbering::new(2, 2))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,9 @@
export type IndentJSON = {
start: number;
start: number | null;
end: number | null;
specialIndent: {
type: "firstLine" | "hanging";
val: number;
} | null;
startChars: number | null;
};

View File

@ -1,6 +1,6 @@
{
"name": "docx-wasm",
"version": "0.0.47",
"version": "0.0.48",
"main": "dist/node/index.js",
"browser": "dist/web/index.js",
"author": "bokuweb <bokuweb12@gmail.com>",

View File

@ -30,7 +30,11 @@ impl Level {
special_indent_size: Option<i32>,
) -> Self {
let special_indent = create_special_indent(special_indent_kind, special_indent_size);
self.0.paragraph_property = self.0.paragraph_property.indent(left, special_indent, None);
// end and start_chars is not supported fro wasm for now.
self.0.paragraph_property =
self.0
.paragraph_property
.indent(Some(left), special_indent, None, None);
self
}
}

View File

@ -79,7 +79,10 @@ impl Paragraph {
special_indent_size: Option<i32>,
) -> Paragraph {
let special_indent = create_special_indent(special_indent_kind, special_indent_size);
self.0.property = self.0.property.indent(left, special_indent, None);
self.0.property = self
.0
.property
.indent(Some(left), special_indent, None, None);
self
}