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