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")
.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()
.pack(file)?;

View File

@ -4,7 +4,7 @@ use std::fs::File;
use std::io::{Read, Write};
pub fn main() {
let mut file = File::open("./test.docx").unwrap();
let mut file = File::open("./commenta.docx").unwrap();
let mut buf = vec![];
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)]
mod tests {

View File

@ -1,13 +1,49 @@
use serde::ser::{SerializeStruct, Serializer};
use serde::Serialize;
use crate::documents::{BuildXML, HistoryId, Run};
use crate::documents::*;
use crate::xml_builder::*;
#[derive(Serialize, Debug, Clone, PartialEq)]
pub struct Delete {
pub author: 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 {
@ -15,21 +51,35 @@ impl Default for Delete {
Delete {
author: "unnamed".to_owned(),
date: "1970-01-01T00:00:00Z".to_owned(),
runs: vec![],
children: vec![],
}
}
}
impl Delete {
pub fn new(run: Run) -> Delete {
pub fn new() -> Delete {
Self {
runs: vec![run],
children: vec![],
..Default::default()
}
}
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
}
@ -48,11 +98,15 @@ impl HistoryId for Delete {}
impl BuildXML for Delete {
fn build(&self) -> Vec<u8> {
XMLBuilder::new()
.open_delete(&self.generate(), &self.author, &self.date)
.add_children(&self.runs)
.close()
.build()
let mut b = XMLBuilder::new().open_delete(&self.generate(), &self.author, &self.date);
for c in &self.children {
match c {
DeleteChild::Run(t) => b = b.add_child(t),
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]
fn test_delete_default() {
let b = Delete::new(Run::new()).build();
let b = Delete::new().add_run(Run::new()).build();
assert_eq!(
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>"#

View File

@ -30,6 +30,8 @@ pub enum RunChild {
Tab(Tab),
Break(Break),
Drawing(Box<Drawing>),
CommentStart(Box<CommentRangeStart>),
CommentEnd(CommentRangeEnd),
}
impl Serialize for RunChild {
@ -67,6 +69,18 @@ impl Serialize for RunChild {
t.serialize_field("data", s)?;
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::Break(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()

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) => {
@ -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>,
attrs: &[OwnedAttribute],
) -> Result<Self, ReaderError> {
let mut runs: Vec<Run> = vec![];
let mut del = Delete::new();
loop {
let e = r.next();
match e {
Ok(XmlEvent::StartElement { name, .. }) => {
Ok(XmlEvent::StartElement {
name, attributes, ..
}) => {
let e = XMLElement::from_str(&name.local_name)
.expect("should convert to XMLElement");
if let XMLElement::Run = e {
runs.push(Run::read(r, attrs)?);
match e {
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, .. }) => {
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 {
let mut del = Delete::new(run);
for attr in attrs {
let local_name = &attr.name.local_name;
if local_name == "author" {
@ -39,11 +53,6 @@ impl ElementReader for Delete {
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);
}
}

View File

@ -330,7 +330,8 @@ mod tests {
Paragraph {
id: "12345678".to_owned(),
children: vec![ParagraphChild::Delete(
Delete::new(Run::new().add_delete_text("Hello "))
Delete::new()
.add_run(Run::new().add_delete_text("Hello "))
.author("unknown")
.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]
pub fn hello() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/hello.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/hello.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.build()
.pack(file)?;
Ok(())
}
#[test]
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(
Some(840),
None,
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
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)?;
Ok(())
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(
Some(840),
None,
None,
None,
))
.add_paragraph(Paragraph::new())
.add_paragraph(Paragraph::new().add_run(Run::new().add_text(DUMMY)).indent(
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)?;
Ok(())
}
#[test]
pub fn size() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/size.docx");
let file = std::fs::File::create(&path).unwrap();
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(" Wor").size(50))
.add_run(Run::new().add_text("ld")),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/size.docx");
let file = std::fs::File::create(&path).unwrap();
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(" Wor").size(50))
.add_run(Run::new().add_text("ld")),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn alignment() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/alignment.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text(" World"))
.align(AlignmentType::Right),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/alignment.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text(" World"))
.align(AlignmentType::Right),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn table() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table.docx");
let file = std::fs::File::create(&path).unwrap();
let path = std::path::Path::new("./tests/output/table.docx");
let file = std::fs::File::create(&path).unwrap();
let table = Table::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("World"))),
]),
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("Bar"))),
]),
]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
let table = Table::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("World"))),
]),
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("Bar"))),
]),
]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
}
#[test]
pub fn table_with_grid() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table_with_grid.docx");
let file = std::fs::File::create(&path).unwrap();
let path = std::path::Path::new("./tests/output/table_with_grid.docx");
let file = std::fs::File::create(&path).unwrap();
let table = Table::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("World"))),
]),
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("Bar"))),
]),
])
.set_grid(vec![3000, 3000]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
let table = Table::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("World"))),
]),
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("Bar"))),
]),
])
.set_grid(vec![3000, 3000]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
}
#[test]
pub fn table_merged() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/table_merged.docx");
let file = std::fs::File::create(&path).unwrap();
let path = std::path::Path::new("./tests/output/table_merged.docx");
let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.grid_span(2),
TableCell::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.vertical_merge(VMergeType::Restart),
]),
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Restart),
TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
]),
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
]),
])
.set_grid(vec![2000, 2000, 2000]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
let table = Table::new(vec![
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.grid_span(2),
TableCell::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.vertical_merge(VMergeType::Restart),
]),
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Restart),
TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
]),
TableRow::new(vec![
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
TableCell::new().add_paragraph(Paragraph::new()),
TableCell::new()
.add_paragraph(Paragraph::new())
.vertical_merge(VMergeType::Continue),
]),
])
.set_grid(vec![2000, 2000, 2000]);
Docx::new().add_table(table).build().pack(file)?;
Ok(())
}
#[test]
pub fn decoration() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/decoration.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").bold()),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").highlight("yellow")),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").italic()),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").color("FF0000")),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/decoration.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").bold()),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").highlight("yellow")),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").italic()),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text(" World").color("FF0000")),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn tab_and_break() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/tab_and_break.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new().add_run(
Run::new()
.add_text("Hello")
.add_tab()
.add_text("World")
.add_break(BreakType::Page)
.add_text("Foo"),
),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/tab_and_break.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new().add_run(
Run::new()
.add_text("Hello")
.add_tab()
.add_text("World")
.add_break(BreakType::Page)
.add_text("Foo"),
),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn history() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/history.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_insert(
Insert::new(Run::new().add_text("Hello"))
.author("bokuweb")
.date("2019-01-01T00:00:00Z"),
let path = std::path::Path::new("./tests/output/history.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_insert(
Insert::new(Run::new().add_text("Hello"))
.author("bokuweb")
.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)?;
Ok(())
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn underline() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/underline.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").underline("single")))
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/underline.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello").underline("single")))
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn highlight() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/highlight.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_run(Run::new().add_text(" World!").highlight("yellow")),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/highlight.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_run(Run::new().add_text(" World!").highlight("yellow")),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn comments() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/comments.docx");
let file = std::fs::File::create(&path).unwrap();
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("Hello"))),
let path = std::path::Path::new("./tests/output/comments.docx");
let file = std::fs::File::create(&path).unwrap();
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("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"))
.add_run(Run::new().add_text(" World!").highlight("yellow"))
.add_comment_end(1),
)
.build()
.pack(file)?;
Ok(())
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn comments_to_table() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/comments_table.docx");
let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![TableRow::new(vec![
TableCell::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("Hello"))),
let path = std::path::Path::new("./tests/output/comments_table.docx");
let file = std::fs::File::create(&path).unwrap();
let table = Table::new(vec![TableRow::new(vec![
TableCell::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("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_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_table(table)
.build()
.pack(file)?;
Ok(())
.add_table(table)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn default_numbering() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/default_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(1), IndentLevel::new(0)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("World!"))
.numbering(NumberingId::new(1), IndentLevel::new(1)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Foooo!"))
.numbering(NumberingId::new(1), IndentLevel::new(2)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Bar!"))
.numbering(NumberingId::new(1), IndentLevel::new(3)),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/default_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(1), IndentLevel::new(0)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("World!"))
.numbering(NumberingId::new(1), IndentLevel::new(1)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Foooo!"))
.numbering(NumberingId::new(1), IndentLevel::new(2)),
)
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Bar!"))
.numbering(NumberingId::new(1), 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_abstract_numbering(
AbstractNumbering::new(2).add_level(
Level::new(
0,
Start::new(1),
NumberFormat::new("decimal"),
LevelText::new("Section %1."),
LevelJc::new("left"),
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)),
)
.indent(
Some(1620),
Some(SpecialIndentType::Hanging(320)),
None,
None,
),
),
)
.add_numbering(Numbering::new(2, 2))
.build()
.pack(file)?;
Ok(())
.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(
Some(1620),
Some(SpecialIndentType::Hanging(320)),
None,
None,
),
),
)
.add_numbering(Numbering::new(2, 2))
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn escape() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/escape.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("&&&>>><<"))
.numbering(NumberingId::new(2), IndentLevel::new(0)),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/escape.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("&&&>>><<"))
.numbering(NumberingId::new(2), IndentLevel::new(0)),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn vanish() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/vanish.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text("Hidden").vanish())
.add_run(Run::new().add_text(" World!!")),
)
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/vanish.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(
Paragraph::new()
.add_run(Run::new().add_text("Hello"))
.add_run(Run::new().add_text("Hidden").vanish())
.add_run(Run::new().add_text(" World!!")),
)
.build()
.pack(file)?;
Ok(())
}
#[test]
pub fn date() -> Result<(), DocxError> {
let path = std::path::Path::new("./tests/output/date.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.created_at("2019-01-01T00:00:00Z")
.updated_at("2019-01-02T10:00:00Z")
.build()
.pack(file)?;
Ok(())
let path = std::path::Path::new("./tests/output/date.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.created_at("2019-01-01T00:00:00Z")
.updated_at("2019-01-02T10:00:00Z")
.build()
.pack(file)?;
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 { CommentRangeStartJSON, CommentRangeEndJSON } from "..";
@ -51,15 +51,17 @@ export type InsertJSON = {
export type DeleteJSON = {
type: "delete";
data: {
runs: {
runProperty: RunPropertyJSON;
children: RunChildJSON[];
}[];
children: DeleteChildJSON[];
author: string;
data: string;
};
};
export type DeleteChildJSON =
| RunJSON
| CommentRangeStartJSON
| CommentRangeEndJSON;
export type BookmarkStartJSON = {
type: "bookmarkStart";
data: {

View File

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

View File

@ -7,7 +7,7 @@ pub struct Delete(docx_rs::Delete);
#[wasm_bindgen(js_name = createDelete)]
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 {