fix: comment importing in delete (#226)

main
bokuweb 2021-01-27 19:44:29 +09:00 committed by GitHub
parent 17c669bdde
commit 9069f08791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 487 additions and 366 deletions

View File

@ -11,7 +11,7 @@ pub fn main() -> Result<(), DocxError> {
.author("bokuweb") .author("bokuweb")
.date("2019-01-01T00:00:00Z"), .date("2019-01-01T00:00:00Z"),
) )
.add_delete(Delete::new(Run::new().add_delete_text("World"))), .add_delete(Delete::new().add_run(Run::new().add_delete_text("World"))),
) )
.build() .build()
.pack(file)?; .pack(file)?;

View File

@ -4,7 +4,7 @@ use std::fs::File;
use std::io::{Read, Write}; use std::io::{Read, Write};
pub fn main() { pub fn main() {
let mut file = File::open("./test.docx").unwrap(); let mut file = File::open("./commenta.docx").unwrap();
let mut buf = vec![]; let mut buf = vec![];
file.read_to_end(&mut buf).unwrap(); file.read_to_end(&mut buf).unwrap();

View File

@ -38,6 +38,13 @@ impl BuildXML for CommentRangeStart {
} }
} }
impl BuildXML for Box<CommentRangeStart> {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
b.comment_range_start(&format!("{}", self.id)).build()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -1,13 +1,49 @@
use serde::ser::{SerializeStruct, Serializer};
use serde::Serialize; use serde::Serialize;
use crate::documents::{BuildXML, HistoryId, Run}; use crate::documents::*;
use crate::xml_builder::*; use crate::xml_builder::*;
#[derive(Serialize, Debug, Clone, PartialEq)] #[derive(Serialize, Debug, Clone, PartialEq)]
pub struct Delete { pub struct Delete {
pub author: String, pub author: String,
pub date: String, pub date: String,
pub runs: Vec<Run>, pub children: Vec<DeleteChild>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum DeleteChild {
Run(Run),
CommentStart(Box<CommentRangeStart>),
CommentEnd(CommentRangeEnd),
}
impl Serialize for DeleteChild {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
DeleteChild::Run(ref r) => {
let mut t = serializer.serialize_struct("Run", 2)?;
t.serialize_field("type", "run")?;
t.serialize_field("data", r)?;
t.end()
}
DeleteChild::CommentStart(ref r) => {
let mut t = serializer.serialize_struct("CommentRangeStart", 2)?;
t.serialize_field("type", "commentRangeStart")?;
t.serialize_field("data", r)?;
t.end()
}
DeleteChild::CommentEnd(ref r) => {
let mut t = serializer.serialize_struct("CommentRangeEnd", 2)?;
t.serialize_field("type", "commentRangeEnd")?;
t.serialize_field("data", r)?;
t.end()
}
}
}
} }
impl Default for Delete { impl Default for Delete {
@ -15,21 +51,35 @@ impl Default for Delete {
Delete { Delete {
author: "unnamed".to_owned(), author: "unnamed".to_owned(),
date: "1970-01-01T00:00:00Z".to_owned(), date: "1970-01-01T00:00:00Z".to_owned(),
runs: vec![], children: vec![],
} }
} }
} }
impl Delete { impl Delete {
pub fn new(run: Run) -> Delete { pub fn new() -> Delete {
Self { Self {
runs: vec![run], children: vec![],
..Default::default() ..Default::default()
} }
} }
pub fn add_run(mut self, run: Run) -> Delete { pub fn add_run(mut self, run: Run) -> Delete {
self.runs.push(run); self.children.push(DeleteChild::Run(run));
self
}
pub fn add_comment_start(mut self, comment: Comment) -> Delete {
self.children
.push(DeleteChild::CommentStart(Box::new(CommentRangeStart::new(
comment,
))));
self
}
pub fn add_comment_end(mut self, id: usize) -> Delete {
self.children
.push(DeleteChild::CommentEnd(CommentRangeEnd::new(id)));
self self
} }
@ -48,11 +98,15 @@ impl HistoryId for Delete {}
impl BuildXML for Delete { impl BuildXML for Delete {
fn build(&self) -> Vec<u8> { fn build(&self) -> Vec<u8> {
XMLBuilder::new() let mut b = XMLBuilder::new().open_delete(&self.generate(), &self.author, &self.date);
.open_delete(&self.generate(), &self.author, &self.date) for c in &self.children {
.add_children(&self.runs) match c {
.close() DeleteChild::Run(t) => b = b.add_child(t),
.build() DeleteChild::CommentStart(c) => b = b.add_child(c),
DeleteChild::CommentEnd(c) => b = b.add_child(c),
}
}
b.close().build()
} }
} }
@ -66,7 +120,7 @@ mod tests {
#[test] #[test]
fn test_delete_default() { fn test_delete_default() {
let b = Delete::new(Run::new()).build(); let b = Delete::new().add_run(Run::new()).build();
assert_eq!( assert_eq!(
str::from_utf8(&b).unwrap(), str::from_utf8(&b).unwrap(),
r#"<w:del w:id="123" w:author="unnamed" w:date="1970-01-01T00:00:00Z"><w:r><w:rPr /></w:r></w:del>"# r#"<w:del w:id="123" w:author="unnamed" w:date="1970-01-01T00:00:00Z"><w:r><w:rPr /></w:r></w:del>"#

View File

@ -30,6 +30,8 @@ pub enum RunChild {
Tab(Tab), Tab(Tab),
Break(Break), Break(Break),
Drawing(Box<Drawing>), Drawing(Box<Drawing>),
CommentStart(Box<CommentRangeStart>),
CommentEnd(CommentRangeEnd),
} }
impl Serialize for RunChild { impl Serialize for RunChild {
@ -67,6 +69,18 @@ impl Serialize for RunChild {
t.serialize_field("data", s)?; t.serialize_field("data", s)?;
t.end() t.end()
} }
RunChild::CommentStart(ref r) => {
let mut t = serializer.serialize_struct("CommentRangeStart", 2)?;
t.serialize_field("type", "commentRangeStart")?;
t.serialize_field("data", r)?;
t.end()
}
RunChild::CommentEnd(ref r) => {
let mut t = serializer.serialize_struct("CommentRangeEnd", 2)?;
t.serialize_field("type", "commentRangeEnd")?;
t.serialize_field("data", r)?;
t.end()
}
} }
} }
} }
@ -180,6 +194,8 @@ impl BuildXML for Run {
RunChild::Tab(t) => b = b.add_child(t), RunChild::Tab(t) => b = b.add_child(t),
RunChild::Break(t) => b = b.add_child(t), RunChild::Break(t) => b = b.add_child(t),
RunChild::Drawing(t) => b = b.add_child(t), RunChild::Drawing(t) => b = b.add_child(t),
RunChild::CommentStart(c) => b = b.add_child(c),
RunChild::CommentEnd(c) => b = b.add_child(c),
} }
} }
b.close().build() b.close().build()

View File

@ -444,6 +444,19 @@ impl Docx {
} }
} }
} }
if let ParagraphChild::Delete(ref mut delete) = child {
for child in &mut delete.children {
if let DeleteChild::CommentStart(ref mut c) = child {
let comment_id = c.get_id();
if let Some(comment) =
comments.iter().find(|c| c.id() == comment_id)
{
let comment = comment.clone();
c.as_mut().comment(comment);
}
}
}
}
} }
} }
DocumentChild::Table(table) => { DocumentChild::Table(table) => {
@ -478,6 +491,22 @@ impl Docx {
} }
} }
} }
if let ParagraphChild::Delete(ref mut delete) = child {
for child in &mut delete.children {
if let DeleteChild::CommentStart(ref mut c) =
child
{
let comment_id = c.get_id();
if let Some(comment) = comments
.iter()
.find(|c| c.id() == comment_id)
{
let comment = comment.clone();
c.as_mut().comment(comment);
}
}
}
}
} }
} }
} }

View File

@ -11,26 +11,40 @@ impl ElementReader for Delete {
r: &mut EventReader<R>, r: &mut EventReader<R>,
attrs: &[OwnedAttribute], attrs: &[OwnedAttribute],
) -> Result<Self, ReaderError> { ) -> Result<Self, ReaderError> {
let mut runs: Vec<Run> = vec![]; let mut del = Delete::new();
loop { loop {
let e = r.next(); let e = r.next();
match e { match e {
Ok(XmlEvent::StartElement { name, .. }) => { Ok(XmlEvent::StartElement {
name, attributes, ..
}) => {
let e = XMLElement::from_str(&name.local_name) let e = XMLElement::from_str(&name.local_name)
.expect("should convert to XMLElement"); .expect("should convert to XMLElement");
if let XMLElement::Run = e { match e {
runs.push(Run::read(r, attrs)?); XMLElement::Run => {
del = del.add_run(Run::read(r, attrs)?);
}
XMLElement::CommentRangeStart => {
if let Some(id) = read(&attributes, "id") {
if let Ok(id) = usize::from_str(&id) {
let comment = Comment::new(id);
del = del.add_comment_start(comment);
}
}
}
XMLElement::CommentRangeEnd => {
if let Some(id) = read(&attributes, "id") {
if let Ok(id) = usize::from_str(&id) {
del = del.add_comment_end(id);
}
}
}
_ => {}
} }
} }
Ok(XmlEvent::EndElement { name, .. }) => { Ok(XmlEvent::EndElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap(); let e = XMLElement::from_str(&name.local_name).unwrap();
let run = if !runs.is_empty() {
std::mem::replace(&mut runs[0], Run::new())
} else {
Run::new()
};
if e == XMLElement::Delete { if e == XMLElement::Delete {
let mut del = Delete::new(run);
for attr in attrs { for attr in attrs {
let local_name = &attr.name.local_name; let local_name = &attr.name.local_name;
if local_name == "author" { if local_name == "author" {
@ -39,11 +53,6 @@ impl ElementReader for Delete {
del = del.date(&attr.value); del = del.date(&attr.value);
} }
} }
if runs.len() > 1 {
for r in runs.into_iter().skip(1) {
del = del.add_run(r);
}
}
return Ok(del); return Ok(del);
} }
} }

View File

@ -330,7 +330,8 @@ mod tests {
Paragraph { Paragraph {
id: "12345678".to_owned(), id: "12345678".to_owned(),
children: vec![ParagraphChild::Delete( children: vec![ParagraphChild::Delete(
Delete::new(Run::new().add_delete_text("Hello ")) Delete::new()
.add_run(Run::new().add_delete_text("Hello "))
.author("unknown") .author("unknown")
.date("2019-11-15T14:19:04Z") .date("2019-11-15T14:19:04Z")
)], )],

View File

@ -8,410 +8,410 @@ pub const DUMMY: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit
#[test] #[test]
pub fn hello() -> Result<(), DocxError> { pub fn hello() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/hello.docx"); let path = std::path::Path::new("./tests/output/hello.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn indent() -> Result<(), DocxError> { pub fn indent() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/indent.docx"); let path = std::path::Path::new("./tests/output/indent.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent( .add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
Some(840), Some(840),
None, None,
None, None,
None, None,
)) ))
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent( .add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
Some(840), Some(840),
Some(SpecialIndentType::FirstLine(720)), Some(SpecialIndentType::FirstLine(720)),
None, None,
None, None,
)) ))
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent( .add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
Some(1560), Some(1560),
Some(SpecialIndentType::Hanging(720)), Some(SpecialIndentType::Hanging(720)),
None, None,
None, None,
)) ))
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn size() -> Result<(), DocxError> { pub fn size() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/size.docx"); let path = std::path::Path::new("./tests/output/size.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").size(60))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").size(60)))
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text(" Wor").size(50)) .add_run(Run::new().add_text(" Wor").size(50))
.add_run(Run::new().add_text("ld")), .add_run(Run::new().add_text("ld")),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn alignment() -> Result<(), DocxError> { pub fn alignment() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/alignment.docx"); let path = std::path::Path::new("./tests/output/alignment.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text(" World")) .add_run(Run::new().add_text(" World"))
.align(AlignmentType::Right), .align(AlignmentType::Right),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn table() -> Result<(), DocxError> { pub fn table() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table.docx"); let path = std::path::Path::new("./tests/output/table.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![ let table = Table::new(vec![
TableRow::new(vec![ TableRow::new(vec![
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
]), ]),
TableRow::new(vec![ TableRow::new(vec![
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Foo"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Foo"))),
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Bar"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Bar"))),
]), ]),
]); ]);
Docx::new().add_table(table).build().pack(file)?; Docx::new().add_table(table).build().pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn table_with_grid() -> Result<(), DocxError> { pub fn table_with_grid() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table_with_grid.docx"); let path = std::path::Path::new("./tests/output/table_with_grid.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![ let table = Table::new(vec![
TableRow::new(vec![ TableRow::new(vec![
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
]), ]),
TableRow::new(vec![ TableRow::new(vec![
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Foo"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Foo"))),
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Bar"))), TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("Bar"))),
]), ]),
]) ])
.set_grid(vec![3000, 3000]); .set_grid(vec![3000, 3000]);
Docx::new().add_table(table).build().pack(file)?; Docx::new().add_table(table).build().pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn table_merged() -> Result<(), DocxError> { pub fn table_merged() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table_merged.docx"); let path = std::path::Path::new("./tests/output/table_merged.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![ let table = Table::new(vec![
TableRow::new(vec![ TableRow::new(vec![
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.grid_span(2), .grid_span(2),
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.vertical_merge(VMergeType::Restart), .vertical_merge(VMergeType::Restart),
]), ]),
TableRow::new(vec![ TableRow::new(vec![
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Restart), .vertical_merge(VMergeType::Restart),
TableCell::new().add_paragraph(Paragraph::new()), TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue), .vertical_merge(VMergeType::Continue),
]), ]),
TableRow::new(vec![ TableRow::new(vec![
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue), .vertical_merge(VMergeType::Continue),
TableCell::new().add_paragraph(Paragraph::new()), TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new() TableCell::new()
.add_paragraph(Paragraph::new()) .add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue), .vertical_merge(VMergeType::Continue),
]), ]),
]) ])
.set_grid(vec![2000, 2000, 2000]); .set_grid(vec![2000, 2000, 2000]);
Docx::new().add_table(table).build().pack(file)?; Docx::new().add_table(table).build().pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn decoration() -> Result<(), DocxError> { pub fn decoration() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/decoration.docx"); let path = std::path::Path::new("./tests/output/decoration.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() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").bold()), .add_run(Run::new().add_text(" World").bold()),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").highlight("yellow")), .add_run(Run::new().add_text(" World").highlight("yellow")),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").italic()), .add_run(Run::new().add_text(" World").italic()),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").color("FF0000")), .add_run(Run::new().add_text(" World").color("FF0000")),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn tab_and_break() -> Result<(), DocxError> { pub fn tab_and_break() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/tab_and_break.docx"); let path = std::path::Path::new("./tests/output/tab_and_break.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( Paragraph::new().add_run(
Run::new() Run::new()
.add_text("Hello") .add_text("Hello")
.add_tab() .add_tab()
.add_text("World") .add_text("World")
.add_break(BreakType::Page) .add_break(BreakType::Page)
.add_text("Foo"), .add_text("Foo"),
), ),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn history() -> Result<(), DocxError> { pub fn history() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/history.docx"); let path = std::path::Path::new("./tests/output/history.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() Paragraph::new()
.add_insert( .add_insert(
Insert::new(Run::new().add_text("Hello")) Insert::new(Run::new().add_text("Hello"))
.author("bokuweb") .author("bokuweb")
.date("2019-01-01T00:00:00Z"), .date("2019-01-01T00:00:00Z"),
)
.add_delete(Delete::new().add_run(Run::new().add_delete_text("World"))),
) )
.add_delete(Delete::new(Run::new().add_delete_text("World"))), .build()
) .pack(file)?;
.build() Ok(())
.pack(file)?;
Ok(())
} }
#[test] #[test]
pub fn underline() -> Result<(), DocxError> { pub fn underline() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/underline.docx"); let path = std::path::Path::new("./tests/output/underline.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").underline("single"))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").underline("single")))
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn highlight() -> Result<(), DocxError> { pub fn highlight() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/highlight.docx"); let path = std::path::Path::new("./tests/output/highlight.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() Paragraph::new()
.add_run(Run::new().add_text("Hello").highlight("cyan")) .add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_run(Run::new().add_text(" World!").highlight("yellow")), .add_run(Run::new().add_text(" World!").highlight("yellow")),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn comments() -> Result<(), DocxError> { pub fn comments() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/comments.docx"); let path = std::path::Path::new("./tests/output/comments.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() Paragraph::new()
.add_comment_start( .add_comment_start(
Comment::new(1) Comment::new(1)
.author("bokuweb") .author("bokuweb")
.date("2019-01-01T00:00:00Z") .date("2019-01-01T00:00:00Z")
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))), .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
)
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_run(Run::new().add_text(" World!").highlight("yellow"))
.add_comment_end(1),
) )
.add_run(Run::new().add_text("Hello").highlight("cyan")) .build()
.add_run(Run::new().add_text(" World!").highlight("yellow")) .pack(file)?;
.add_comment_end(1), Ok(())
)
.build()
.pack(file)?;
Ok(())
} }
#[test] #[test]
pub fn comments_to_table() -> Result<(), DocxError> { pub fn comments_to_table() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/comments_table.docx"); let path = std::path::Path::new("./tests/output/comments_table.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![TableRow::new(vec![ let table = Table::new(vec![TableRow::new(vec![
TableCell::new().add_paragraph( TableCell::new().add_paragraph(
Paragraph::new() Paragraph::new()
.add_comment_start( .add_comment_start(
Comment::new(1) Comment::new(1)
.author("bokuweb") .author("bokuweb")
.date("2019-01-01T00:00:00Z") .date("2019-01-01T00:00:00Z")
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))), .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
)
.add_run(Run::new().add_text("Hello"))
.add_comment_end(1),
),
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
])]);
Docx::new()
.add_paragraph(
Paragraph::new()
.add_comment_start(
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Comment!!"))),
)
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_comment_end(1),
) )
.add_run(Run::new().add_text("Hello")) .add_table(table)
.add_comment_end(1), .build()
), .pack(file)?;
TableCell::new().add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))), Ok(())
])]);
Docx::new()
.add_paragraph(
Paragraph::new()
.add_comment_start(
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Comment!!"))),
)
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_comment_end(1),
)
.add_table(table)
.build()
.pack(file)?;
Ok(())
} }
#[test] #[test]
pub fn default_numbering() -> Result<(), DocxError> { pub fn default_numbering() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/default_numbering.docx"); let path = std::path::Path::new("./tests/output/default_numbering.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() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.numbering(NumberingId::new(1), IndentLevel::new(0)), .numbering(NumberingId::new(1), IndentLevel::new(0)),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("World!")) .add_run(Run::new().add_text("World!"))
.numbering(NumberingId::new(1), IndentLevel::new(1)), .numbering(NumberingId::new(1), IndentLevel::new(1)),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("Foooo!")) .add_run(Run::new().add_text("Foooo!"))
.numbering(NumberingId::new(1), IndentLevel::new(2)), .numbering(NumberingId::new(1), IndentLevel::new(2)),
) )
.add_paragraph( .add_paragraph(
Paragraph::new() Paragraph::new()
.add_run(Run::new().add_text("Bar!")) .add_run(Run::new().add_text("Bar!"))
.numbering(NumberingId::new(1), IndentLevel::new(3)), .numbering(NumberingId::new(1), IndentLevel::new(3)),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn user_numbering() -> Result<(), DocxError> { pub fn user_numbering() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/user_numbering.docx"); let path = std::path::Path::new("./tests/output/user_numbering.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() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.numbering(NumberingId::new(2), IndentLevel::new(0)), .numbering(NumberingId::new(2), IndentLevel::new(0)),
)
.add_abstract_numbering(
AbstractNumbering::new(2).add_level(
Level::new(
0,
Start::new(1),
NumberFormat::new("decimal"),
LevelText::new("Section %1."),
LevelJc::new("left"),
) )
.indent( .add_abstract_numbering(
Some(1620), AbstractNumbering::new(2).add_level(
Some(SpecialIndentType::Hanging(320)), Level::new(
None, 0,
None, Start::new(1),
), NumberFormat::new("decimal"),
), LevelText::new("Section %1."),
) LevelJc::new("left"),
.add_numbering(Numbering::new(2, 2)) )
.build() .indent(
.pack(file)?; Some(1620),
Ok(()) Some(SpecialIndentType::Hanging(320)),
None,
None,
),
),
)
.add_numbering(Numbering::new(2, 2))
.build()
.pack(file)?;
Ok(())
} }
#[test] #[test]
pub fn escape() -> Result<(), DocxError> { pub fn escape() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/escape.docx"); let path = std::path::Path::new("./tests/output/escape.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() Paragraph::new()
.add_run(Run::new().add_text("&&&>>><<")) .add_run(Run::new().add_text("&&&>>><<"))
.numbering(NumberingId::new(2), IndentLevel::new(0)), .numbering(NumberingId::new(2), IndentLevel::new(0)),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn vanish() -> Result<(), DocxError> { pub fn vanish() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/vanish.docx"); let path = std::path::Path::new("./tests/output/vanish.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() Paragraph::new()
.add_run(Run::new().add_text("Hello")) .add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text("Hidden").vanish()) .add_run(Run::new().add_text("Hidden").vanish())
.add_run(Run::new().add_text(" World!!")), .add_run(Run::new().add_text(" World!!")),
) )
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }
#[test] #[test]
pub fn date() -> Result<(), DocxError> { pub fn date() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/date.docx"); let path = std::path::Path::new("./tests/output/date.docx");
let file = std::fs::File::create(&path).unwrap(); let file = std::fs::File::create(&path).unwrap();
Docx::new() Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.created_at("2019-01-01T00:00:00Z") .created_at("2019-01-01T00:00:00Z")
.updated_at("2019-01-02T10:00:00Z") .updated_at("2019-01-02T10:00:00Z")
.build() .build()
.pack(file)?; .pack(file)?;
Ok(()) Ok(())
} }

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,4 +1,4 @@
import { RunJSON, RunChildJSON, RunPropertyJSON } from "./run"; import { RunJSON, RunPropertyJSON } from "./run";
import { IndentJSON } from "./indent"; import { IndentJSON } from "./indent";
import { CommentRangeStartJSON, CommentRangeEndJSON } from ".."; import { CommentRangeStartJSON, CommentRangeEndJSON } from "..";
@ -51,15 +51,17 @@ export type InsertJSON = {
export type DeleteJSON = { export type DeleteJSON = {
type: "delete"; type: "delete";
data: { data: {
runs: { children: DeleteChildJSON[];
runProperty: RunPropertyJSON;
children: RunChildJSON[];
}[];
author: string; author: string;
data: string; data: string;
}; };
}; };
export type DeleteChildJSON =
| RunJSON
| CommentRangeStartJSON
| CommentRangeEndJSON;
export type BookmarkStartJSON = { export type BookmarkStartJSON = {
type: "bookmarkStart"; type: "bookmarkStart";
data: { data: {

View File

@ -1,4 +1,5 @@
import { DrawingJSON } from "./drawing"; import { DrawingJSON } from "./drawing";
import { CommentRangeStartJSON, CommentRangeEndJSON } from "..";
export type RunPropertyJSON = { export type RunPropertyJSON = {
sz: number | null; sz: number | null;
@ -19,7 +20,9 @@ export type RunChildJSON =
| DeleteTextJSON | DeleteTextJSON
| TabJSON | TabJSON
| BreakJSON | BreakJSON
| DrawingJSON; | DrawingJSON
| CommentRangeStartJSON
| CommentRangeEndJSON;
export type TextJSON = { export type TextJSON = {
type: "text"; type: "text";

View File

@ -7,7 +7,7 @@ pub struct Delete(docx_rs::Delete);
#[wasm_bindgen(js_name = createDelete)] #[wasm_bindgen(js_name = createDelete)]
pub fn create_delete(run: Run) -> Delete { pub fn create_delete(run: Run) -> Delete {
Delete(docx_rs::Delete::new(run.take())) Delete(docx_rs::Delete::new().add_run(run.take()))
} }
impl Delete { impl Delete {