fix: comment importing in delete (#226)
parent
17c669bdde
commit
9069f08791
|
@ -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)?;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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>"#
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
)],
|
||||
|
|
|
@ -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
|
@ -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: {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue