Fixed a bug where Delete / Insert can only have one Run (#73)

* fix: runs in insert / delete

* fix: json type

* fix: lint
main
bokuweb 2020-06-01 13:49:41 +09:00 committed by GitHub
parent 7556154bd5
commit 74e8b2d90a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 139 additions and 24 deletions

View File

@ -3,7 +3,7 @@ use std::fs::*;
use std::io::Read;
pub fn main() {
let mut file = File::open("./textbox.docx").unwrap();
let mut file = File::open("./6.docx").unwrap();
let mut buf = vec![];
file.read_to_end(&mut buf).unwrap();
dbg!(read_docx(&buf).unwrap().json());

View File

@ -7,7 +7,7 @@ use crate::xml_builder::*;
pub struct Delete {
pub author: String,
pub date: String,
pub run: Run,
pub runs: Vec<Run>,
}
impl Default for Delete {
@ -15,7 +15,7 @@ impl Default for Delete {
Delete {
author: "unnamed".to_owned(),
date: "1970-01-01T00:00:00Z".to_owned(),
run: Run::new(),
runs: vec![],
}
}
}
@ -23,12 +23,13 @@ impl Default for Delete {
impl Delete {
pub fn new(run: Run) -> Delete {
Self {
run,
runs: vec![run],
..Default::default()
}
}
pub fn run(mut self, run: Run) -> Delete {
self.run = run;
pub fn add_run(mut self, run: Run) -> Delete {
self.runs.push(run);
self
}
@ -49,7 +50,7 @@ impl BuildXML for Delete {
fn build(&self) -> Vec<u8> {
XMLBuilder::new()
.open_delete(&self.generate(), &self.author, &self.date)
.add_child(&self.run)
.add_children(&self.runs)
.close()
.build()
}

View File

@ -6,7 +6,7 @@ use crate::xml_builder::*;
#[derive(Serialize, Debug, Clone, PartialEq)]
pub struct Insert {
pub run: Run,
pub runs: Vec<Run>,
pub author: String,
pub date: String,
}
@ -16,7 +16,7 @@ impl Default for Insert {
Insert {
author: "unnamed".to_owned(),
date: "1970-01-01T00:00:00Z".to_owned(),
run: Run::new(),
runs: vec![],
}
}
}
@ -24,11 +24,16 @@ impl Default for Insert {
impl Insert {
pub fn new(run: Run) -> Insert {
Self {
run,
runs: vec![run],
..Default::default()
}
}
pub fn add_run(mut self, run: Run) -> Insert {
self.runs.push(run);
self
}
pub fn author(mut self, author: impl Into<String>) -> Insert {
self.author = author.into();
self
@ -46,7 +51,7 @@ impl BuildXML for Insert {
fn build(&self) -> Vec<u8> {
XMLBuilder::new()
.open_insert(&self.generate(), &self.author, &self.date)
.add_child(&self.run)
.add_children(&self.runs)
.close()
.build()
}

View File

@ -282,7 +282,7 @@ mod tests {
let p = Paragraph::new().add_insert(ins);
assert_eq!(
serde_json::to_string(&p).unwrap(),
r#"{"children":[{"type":"insert","data":{"run":{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"children":[{"type":"text","data":{"preserveSpace":true,"text":"Hello"}}]},"author":"unnamed","date":"1970-01-01T00:00:00Z"}}],"property":{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"style":null,"numberingProperty":null,"alignment":null,"indent":null},"hasNumbering":false,"attrs":[]}"#
r#"{"children":[{"type":"insert","data":{"runs":[{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"children":[{"type":"text","data":{"preserveSpace":true,"text":"Hello"}}]}],"author":"unnamed","date":"1970-01-01T00:00:00Z"}}],"property":{"runProperty":{"sz":null,"szCs":null,"color":null,"highlight":null,"underline":null,"bold":null,"boldCs":null,"italic":null,"italicCs":null,"vanish":null},"style":null,"numberingProperty":null,"alignment":null,"indent":null},"hasNumbering":false,"attrs":[]}"#
);
}
}

View File

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

@ -11,19 +11,24 @@ impl ElementReader for Insert {
r: &mut EventReader<R>,
attrs: &[OwnedAttribute],
) -> Result<Self, ReaderError> {
let mut run = Run::new();
let mut runs: Vec<Run> = vec![];
loop {
let e = r.next();
match e {
Ok(XmlEvent::StartElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::Run = e {
run = Run::read(r, attrs)?;
runs.push(Run::read(r, attrs)?);
}
}
Ok(XmlEvent::EndElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if e == XMLElement::Insert {
let run = if !runs.is_empty() {
std::mem::replace(&mut runs[0], Run::new())
} else {
Run::new()
};
let mut ins = Insert::new(run);
for attr in attrs {
let local_name = &attr.name.local_name;
@ -33,6 +38,11 @@ impl ElementReader for Insert {
ins = ins.date(&attr.value);
}
}
if runs.len() > 1 {
for r in runs.into_iter().skip(1) {
ins = ins.add_run(r);
}
}
return Ok(ins);
}
}

View File

@ -363,4 +363,92 @@ mod tests {
}
);
}
#[test]
fn test_read_two_insert() {
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:p>
<w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
<w:r>
<w:rPr></w:rPr>
<w:t>W</w:t>
</w:r>
</w:ins>
<w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
<w:r>
<w:rPr></w:rPr>
<w:t>H</w:t>
</w:r>
</w:ins>
</w:p>
</w:document>"#;
let mut parser = EventReader::new(c.as_bytes());
let p = Paragraph::read(&mut parser, &[]).unwrap();
assert_eq!(
p,
Paragraph {
children: vec![
ParagraphChild::Insert(
Insert::new(Run::new().add_text("W"))
.author("unknown")
.date("2019-11-15T14:19:04Z")
),
ParagraphChild::Insert(
Insert::new(Run::new().add_text("H"))
.author("unknown")
.date("2019-11-15T14:19:04Z")
)
],
property: ParagraphProperty {
run_property: RunProperty::new(),
style: None,
numbering_property: None,
alignment: None,
indent: None,
},
has_numbering: false,
attrs: vec![],
}
);
}
#[test]
fn test_read_two_run_in_insert() {
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:p>
<w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
<w:r>
<w:rPr></w:rPr>
<w:t>W</w:t>
</w:r>
<w:r>
<w:rPr></w:rPr>
<w:t>H</w:t>
</w:r>
</w:ins>
</w:p>
</w:document>"#;
let mut parser = EventReader::new(c.as_bytes());
let p = Paragraph::read(&mut parser, &[]).unwrap();
assert_eq!(
p,
Paragraph {
children: vec![ParagraphChild::Insert(
Insert::new(Run::new().add_text("W"))
.author("unknown")
.date("2019-11-15T14:19:04Z")
.add_run(Run::new().add_text("H")),
)],
property: ParagraphProperty {
run_property: RunProperty::new(),
style: None,
numbering_property: None,
alignment: None,
indent: None,
},
has_numbering: false,
attrs: vec![],
}
);
}
}

View File

@ -52,6 +52,7 @@ impl ElementReader for Run {
run = run.size(usize::from_str(&attributes[0].value)?)
}
XMLElement::Underline => {
dbg!(&attributes);
run = run.underline(&attributes[0].value.clone())
}
XMLElement::Italic => {

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

@ -32,10 +32,10 @@ export type ParagraphJSON = {
export type InsertJSON = {
type: "insert";
data: {
run: {
runs: {
runProperty: RunPropertyJSON;
children: RunChildJSON[];
};
}[];
author: string;
data: string;
};
@ -44,10 +44,10 @@ export type InsertJSON = {
export type DeleteJSON = {
type: "delete";
data: {
run: {
runs: {
runProperty: RunPropertyJSON;
children: RunChildJSON[];
};
}[];
author: string;
data: string;
};