Fixed a bug where Delete / Insert can only have one Run (#73)
* fix: runs in insert / delete * fix: json type * fix: lintmain
parent
7556154bd5
commit
74e8b2d90a
|
@ -3,7 +3,7 @@ use std::fs::*;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut file = File::open("./textbox.docx").unwrap();
|
let mut file = File::open("./6.docx").unwrap();
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
file.read_to_end(&mut buf).unwrap();
|
file.read_to_end(&mut buf).unwrap();
|
||||||
dbg!(read_docx(&buf).unwrap().json());
|
dbg!(read_docx(&buf).unwrap().json());
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::xml_builder::*;
|
||||||
pub struct Delete {
|
pub struct Delete {
|
||||||
pub author: String,
|
pub author: String,
|
||||||
pub date: String,
|
pub date: String,
|
||||||
pub run: Run,
|
pub runs: Vec<Run>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Delete {
|
impl Default for Delete {
|
||||||
|
@ -15,7 +15,7 @@ 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(),
|
||||||
run: Run::new(),
|
runs: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,13 @@ impl Default for Delete {
|
||||||
impl Delete {
|
impl Delete {
|
||||||
pub fn new(run: Run) -> Delete {
|
pub fn new(run: Run) -> Delete {
|
||||||
Self {
|
Self {
|
||||||
run,
|
runs: vec![run],
|
||||||
..Default::default()
|
..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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ impl BuildXML for Delete {
|
||||||
fn build(&self) -> Vec<u8> {
|
fn build(&self) -> Vec<u8> {
|
||||||
XMLBuilder::new()
|
XMLBuilder::new()
|
||||||
.open_delete(&self.generate(), &self.author, &self.date)
|
.open_delete(&self.generate(), &self.author, &self.date)
|
||||||
.add_child(&self.run)
|
.add_children(&self.runs)
|
||||||
.close()
|
.close()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::xml_builder::*;
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||||
pub struct Insert {
|
pub struct Insert {
|
||||||
pub run: Run,
|
pub runs: Vec<Run>,
|
||||||
pub author: String,
|
pub author: String,
|
||||||
pub date: String,
|
pub date: String,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ impl Default for Insert {
|
||||||
Insert {
|
Insert {
|
||||||
author: "unnamed".to_owned(),
|
author: "unnamed".to_owned(),
|
||||||
date: "1970-01-01T00:00:00Z".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 {
|
impl Insert {
|
||||||
pub fn new(run: Run) -> Insert {
|
pub fn new(run: Run) -> Insert {
|
||||||
Self {
|
Self {
|
||||||
run,
|
runs: vec![run],
|
||||||
..Default::default()
|
..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 {
|
pub fn author(mut self, author: impl Into<String>) -> Insert {
|
||||||
self.author = author.into();
|
self.author = author.into();
|
||||||
self
|
self
|
||||||
|
@ -46,7 +51,7 @@ impl BuildXML for Insert {
|
||||||
fn build(&self) -> Vec<u8> {
|
fn build(&self) -> Vec<u8> {
|
||||||
XMLBuilder::new()
|
XMLBuilder::new()
|
||||||
.open_insert(&self.generate(), &self.author, &self.date)
|
.open_insert(&self.generate(), &self.author, &self.date)
|
||||||
.add_child(&self.run)
|
.add_children(&self.runs)
|
||||||
.close()
|
.close()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ mod tests {
|
||||||
let p = Paragraph::new().add_insert(ins);
|
let p = Paragraph::new().add_insert(ins);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_string(&p).unwrap(),
|
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":[]}"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ impl ElementReader for Delete {
|
||||||
r: &mut EventReader<R>,
|
r: &mut EventReader<R>,
|
||||||
attrs: &[OwnedAttribute],
|
attrs: &[OwnedAttribute],
|
||||||
) -> Result<Self, ReaderError> {
|
) -> Result<Self, ReaderError> {
|
||||||
let mut run = Run::new();
|
let mut runs: Vec<Run> = vec![];
|
||||||
loop {
|
loop {
|
||||||
let e = r.next();
|
let e = r.next();
|
||||||
match e {
|
match e {
|
||||||
|
@ -19,11 +19,16 @@ impl ElementReader for Delete {
|
||||||
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 {
|
if let XMLElement::Run = e {
|
||||||
run = Run::read(r, attrs)?;
|
runs.push(Run::read(r, attrs)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
let mut del = Delete::new(run);
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
|
@ -34,6 +39,11 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,24 @@ impl ElementReader for Insert {
|
||||||
r: &mut EventReader<R>,
|
r: &mut EventReader<R>,
|
||||||
attrs: &[OwnedAttribute],
|
attrs: &[OwnedAttribute],
|
||||||
) -> Result<Self, ReaderError> {
|
) -> Result<Self, ReaderError> {
|
||||||
let mut run = Run::new();
|
let mut runs: Vec<Run> = vec![];
|
||||||
loop {
|
loop {
|
||||||
let e = r.next();
|
let e = r.next();
|
||||||
match e {
|
match e {
|
||||||
Ok(XmlEvent::StartElement { name, .. }) => {
|
Ok(XmlEvent::StartElement { name, .. }) => {
|
||||||
let e = XMLElement::from_str(&name.local_name).unwrap();
|
let e = XMLElement::from_str(&name.local_name).unwrap();
|
||||||
if let XMLElement::Run = e {
|
if let XMLElement::Run = e {
|
||||||
run = Run::read(r, attrs)?;
|
runs.push(Run::read(r, attrs)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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();
|
||||||
if e == XMLElement::Insert {
|
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);
|
let mut ins = Insert::new(run);
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let local_name = &attr.name.local_name;
|
let local_name = &attr.name.local_name;
|
||||||
|
@ -33,6 +38,11 @@ impl ElementReader for Insert {
|
||||||
ins = ins.date(&attr.value);
|
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);
|
return Ok(ins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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![],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ impl ElementReader for Run {
|
||||||
run = run.size(usize::from_str(&attributes[0].value)?)
|
run = run.size(usize::from_str(&attributes[0].value)?)
|
||||||
}
|
}
|
||||||
XMLElement::Underline => {
|
XMLElement::Underline => {
|
||||||
|
dbg!(&attributes);
|
||||||
run = run.underline(&attributes[0].value.clone())
|
run = run.underline(&attributes[0].value.clone())
|
||||||
}
|
}
|
||||||
XMLElement::Italic => {
|
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
|
@ -32,10 +32,10 @@ export type ParagraphJSON = {
|
||||||
export type InsertJSON = {
|
export type InsertJSON = {
|
||||||
type: "insert";
|
type: "insert";
|
||||||
data: {
|
data: {
|
||||||
run: {
|
runs: {
|
||||||
runProperty: RunPropertyJSON;
|
runProperty: RunPropertyJSON;
|
||||||
children: RunChildJSON[];
|
children: RunChildJSON[];
|
||||||
};
|
}[];
|
||||||
author: string;
|
author: string;
|
||||||
data: string;
|
data: string;
|
||||||
};
|
};
|
||||||
|
@ -44,10 +44,10 @@ export type InsertJSON = {
|
||||||
export type DeleteJSON = {
|
export type DeleteJSON = {
|
||||||
type: "delete";
|
type: "delete";
|
||||||
data: {
|
data: {
|
||||||
run: {
|
runs: {
|
||||||
runProperty: RunPropertyJSON;
|
runProperty: RunPropertyJSON;
|
||||||
children: RunChildJSON[];
|
children: RunChildJSON[];
|
||||||
};
|
}[];
|
||||||
author: string;
|
author: string;
|
||||||
data: string;
|
data: string;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue