Fix comment structure (#216)

* fix: Add comment children

* feat: Update snaps

* fix: specs

* spec: Add spec

* fix: js if
main
bokuweb 2020-12-21 17:30:42 +09:00 committed by GitHub
parent e45e0431e9
commit 2e5a22fc53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 3952 additions and 249 deletions

View File

@ -10,7 +10,7 @@ pub fn main() -> Result<(), DocxError> {
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
)
.add_comment_end(1),
)

View File

@ -10,7 +10,8 @@ pub fn main() -> Result<(), DocxError> {
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))),
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
)
.add_comment_end(1)
.add_comment_start(
@ -18,7 +19,7 @@ pub fn main() -> Result<(), DocxError> {
.author("bokuweb")
.date("2019-01-02T00:00:00Z")
.parent_comment_id(1)
.paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("World"))),
)
.add_comment_end(2)
.add_comment_start(
@ -26,7 +27,8 @@ pub fn main() -> Result<(), DocxError> {
.author("bokuweb")
.date("2019-01-02T00:00:00Z")
.parent_comment_id(1)
.paragraph(Paragraph::new().add_run(Run::new().add_text("!!!!!"))),
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("!!!!!")))
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("!!!!!"))),
)
.add_comment_end(3),
)

View File

@ -1,6 +1,7 @@
use serde::ser::{SerializeStruct, Serializer};
use serde::Serialize;
use crate::documents::{BuildXML, Paragraph};
use crate::documents::*;
use crate::xml_builder::*;
#[derive(Serialize, Debug, Clone, PartialEq)]
@ -9,17 +10,45 @@ pub struct Comment {
pub id: usize,
pub author: String,
pub date: String,
pub paragraph: Paragraph,
pub children: Vec<CommentChild>,
pub parent_comment_id: Option<usize>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CommentChild {
Paragraph(Paragraph),
Table(Table),
}
impl Serialize for CommentChild {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
CommentChild::Paragraph(ref p) => {
let mut t = serializer.serialize_struct("Paragraph", 2)?;
t.serialize_field("type", "paragraph")?;
t.serialize_field("data", p)?;
t.end()
}
CommentChild::Table(ref c) => {
let mut t = serializer.serialize_struct("Table", 2)?;
t.serialize_field("type", "table")?;
t.serialize_field("data", c)?;
t.end()
}
}
}
}
impl Default for Comment {
fn default() -> Comment {
Comment {
id: 1,
author: "unnamed".to_owned(),
date: "1970-01-01T00:00:00Z".to_owned(),
paragraph: Paragraph::new(),
children: vec![],
parent_comment_id: None,
}
}
@ -43,8 +72,13 @@ impl Comment {
self
}
pub fn paragraph(mut self, p: Paragraph) -> Comment {
self.paragraph = p;
pub fn add_paragraph(mut self, p: Paragraph) -> Self {
self.children.push(CommentChild::Paragraph(p));
self
}
pub fn add_table(mut self, t: Table) -> Self {
self.children.push(CommentChild::Table(t));
self
}
@ -58,11 +92,20 @@ impl Comment {
}
}
impl BuildXML for CommentChild {
fn build(&self) -> Vec<u8> {
match self {
CommentChild::Paragraph(v) => v.build(),
CommentChild::Table(v) => v.build(),
}
}
}
impl BuildXML for Comment {
fn build(&self) -> Vec<u8> {
XMLBuilder::new()
.open_comment(&format!("{}", self.id), &self.author, &self.date, "")
.add_child(&self.paragraph)
.add_children(&self.children)
.close()
.build()
}
@ -77,8 +120,17 @@ mod tests {
use std::str;
#[test]
fn test_ins_default() {
fn test_comment_default() {
let b = Comment::new(1).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:comment w:id="1" w:author="unnamed" w:date="1970-01-01T00:00:00Z" w:initials="" />"#
);
}
#[test]
fn test_comment_with_default_paragraph() {
let b = Comment::new(1).add_paragraph(Paragraph::new()).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:comment w:id="1" w:author="unnamed" w:date="1970-01-01T00:00:00Z" w:initials=""><w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr></w:p></w:comment>"#

View File

@ -278,8 +278,14 @@ impl Docx {
for child in &paragraph.children {
if let ParagraphChild::CommentStart(c) = child {
let comment = c.get_comment();
let para_id = comment.paragraph.id.clone();
comment_map.insert(comment.id(), para_id.clone());
let comment_id = comment.id();
for child in comment.children {
if let CommentChild::Paragraph(child) = child {
let para_id = child.id.clone();
comment_map.insert(comment_id, para_id.clone());
}
// TODO: Support table
}
}
}
}
@ -292,8 +298,15 @@ impl Docx {
for child in &paragraph.children {
if let ParagraphChild::CommentStart(c) = child {
let comment = c.get_comment();
let para_id = comment.paragraph.id.clone();
comment_map.insert(comment.id(), para_id.clone());
let comment_id = comment.id();
for child in comment.children {
if let CommentChild::Paragraph(child) = child {
let para_id = child.id.clone();
comment_map
.insert(comment_id, para_id.clone());
}
// TODO: Support table
}
}
}
}
@ -312,18 +325,24 @@ impl Docx {
for child in &paragraph.children {
if let ParagraphChild::CommentStart(c) = child {
let comment = c.get_comment();
let para_id = comment.paragraph.id.clone();
for child in comment.children {
if let CommentChild::Paragraph(child) = child {
let para_id = child.id.clone();
comments.push(c.get_comment());
let comment_extended = CommentExtended::new(para_id);
if let Some(parent_comment_id) = comment.parent_comment_id {
let parent_para_id =
comment_map.get(&parent_comment_id).unwrap().clone();
comments_extended
.push(comment_extended.parent_paragraph_id(parent_para_id));
comments_extended.push(
comment_extended.parent_paragraph_id(parent_para_id),
);
} else {
comments_extended.push(comment_extended);
}
}
// TODO: Support table
}
}
}
}
DocumentChild::Table(table) => {
@ -335,7 +354,9 @@ impl Docx {
for child in &paragraph.children {
if let ParagraphChild::CommentStart(c) = child {
let comment = c.get_comment();
let para_id = comment.paragraph.id.clone();
for child in comment.children {
if let CommentChild::Paragraph(child) = child {
let para_id = child.id.clone();
comments.push(c.get_comment());
let comment_extended =
CommentExtended::new(para_id);
@ -348,10 +369,15 @@ impl Docx {
.clone();
comments_extended.push(
comment_extended
.parent_paragraph_id(parent_para_id),
.parent_paragraph_id(
parent_para_id,
),
);
} else {
comments_extended.push(comment_extended);
comments_extended
.push(comment_extended);
}
}
}
}
}

View File

@ -29,7 +29,7 @@ impl ElementReader for Comment {
.expect("should convert to XMLElement");
if let XMLElement::Paragraph = e {
let p = Paragraph::read(r, &attributes)?;
comment = comment.paragraph(p);
comment = comment.add_paragraph(p);
}
}
Ok(XmlEvent::EndElement { name, .. }) => {

View File

@ -126,19 +126,31 @@ pub fn read_docx(buf: &[u8]) -> Result<Docx, ReaderError> {
let mut comments = Comments::from_xml(&data[..])?.into_inner();
for i in 0..comments.len() {
let c = &comments[i];
let extended = comments_extended
.children
.iter()
.find(|ex| ex.paragraph_id == c.paragraph.id);
let extended = comments_extended.children.iter().find(|ex| {
for child in &c.children {
if let CommentChild::Paragraph(p) = child {
if ex.paragraph_id == p.id {
return true;
}
}
}
false
});
if let Some(CommentExtended {
parent_paragraph_id: Some(parent_paragraph_id),
..
}) = extended
{
if let Some(parent_comment) = comments
.iter()
.find(|c| &c.paragraph.id == parent_paragraph_id)
{
if let Some(parent_comment) = comments.iter().find(|c| {
for child in &c.children {
if let CommentChild::Paragraph(p) = child {
if &p.id == parent_paragraph_id {
return true;
}
}
}
false
}) {
comments[i].parent_comment_id = Some(parent_comment.id);
}
}

View File

@ -262,7 +262,7 @@ pub fn comments() -> Result<(), DocxError> {
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.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"))
@ -284,7 +284,7 @@ pub fn comments_to_table() -> Result<(), DocxError> {
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.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),
@ -298,7 +298,7 @@ pub fn comments_to_table() -> Result<(), DocxError> {
Comment::new(1)
.author("bokuweb")
.date("2019-01-01T00:00:00Z")
.paragraph(Paragraph::new().add_run(Run::new().add_text("Comment!!"))),
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Comment!!"))),
)
.add_run(Run::new().add_text("Hello").highlight("cyan"))
.add_comment_end(1),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
import { Paragraph } from "./paragraph";
import { Table } from "./table";
export class Comment {
id: number;
_author: string;
_date: string;
_paragraph: Paragraph;
children: (Paragraph | Table)[] = [];
_parentCommentId: number;
constructor(id: number) {
@ -21,8 +22,8 @@ export class Comment {
return this;
}
paragraph(p: Paragraph) {
this._paragraph = p;
addParagraph(p: Paragraph) {
this.children.push(p);
return this;
}

View File

@ -231,9 +231,13 @@ export class Docx {
buildComment(c: Comment) {
let comment = wasm.createComment(c.id);
if (c._paragraph) {
comment = comment.paragraph(this.buildParagraph(c._paragraph));
c.children.forEach((child) => {
if (child instanceof Paragraph) {
comment = comment.add_paragraph(this.buildParagraph(child));
} else if (child instanceof Table) {
// TODO:
}
});
if (c._author) {
comment = comment.author(c._author);
}

View File

@ -1,10 +1,12 @@
import { ParagraphJSON } from "../";
import { ParagraphJSON, TableJSON } from "../";
export type CommentChildJSON = ParagraphJSON | TableJSON;
export type CommentJSON = {
id: number;
author: string;
date: string;
paragraph: ParagraphJSON;
children: CommentChildJSON[];
parentCommentId: number | null;
};

View File

@ -28,8 +28,8 @@ impl Comment {
self
}
pub fn paragraph(mut self, p: Paragraph) -> Comment {
self.0.paragraph = p.take();
pub fn add_paragraph(mut self, p: Paragraph) -> Comment {
self.0 = self.0.add_paragraph(p.take());
self
}

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,14 @@ describe("reader", () => {
const json = w.readDocx(buf);
expect(json).toMatchSnapshot();
});
test("should read multi paragraph comments docx", () => {
const buf = readFileSync(
"../fixtures/multi_paragraph_comment/multi_paragraph_comment.docx"
);
const json = w.readDocx(buf);
expect(json).toMatchSnapshot();
});
});
describe("writer", () => {