Skip to content

Commit

Permalink
fix: read levelOverride (#61)
Browse files Browse the repository at this point in the history
* fix: read levelOverride

* spec: update snaps
  • Loading branch information
bokuweb authored Apr 21, 2020
1 parent 83d7dc2 commit 6336859
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 10 deletions.
33 changes: 33 additions & 0 deletions docx-core/src/documents/elements/level_override.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::documents::BuildXML;
// use crate::xml_builder::*;

use serde::Serialize;

/*
17.9.8 lvlOverride (Numbering Level Definition Override)
This element specifies an optional override which shall be applied in place of zero or more levels from the abstract numbering definition for a given numbering definition instance. Each instance of this element is used to override the appearance and behavior of a given numbering level definition within the given abstract numbering definition.
*/
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LevelOverride {
pub level: usize,
pub start: Option<usize>,
}

impl LevelOverride {
pub fn new(level: usize) -> LevelOverride {
LevelOverride { level, start: None }
}

pub fn start(mut self, start: usize) -> LevelOverride {
self.start = Some(start);
self
}
}

// TODO: Now read only
impl BuildXML for LevelOverride {
fn build(&self) -> Vec<u8> {
vec![]
}
}
2 changes: 2 additions & 0 deletions docx-core/src/documents/elements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod italic_cs;
mod justification;
mod level;
mod level_jc;
mod level_override;
mod level_text;
mod mc_fallback;
mod name;
Expand Down Expand Up @@ -103,6 +104,7 @@ pub use italic_cs::*;
pub use justification::*;
pub use level::*;
pub use level_jc::*;
pub use level_override::*;
pub use level_text::*;
pub use mc_fallback::*;
pub use name::*;
Expand Down
44 changes: 44 additions & 0 deletions docx-core/src/documents/elements/numbering.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use crate::documents::BuildXML;
use crate::xml_builder::*;

use super::*;
use serde::Serialize;

#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Numbering {
id: usize,
abstract_num_id: usize,
level_overrides: Vec<LevelOverride>,
}

impl Numbering {
pub fn new(id: usize, abstract_num_id: usize) -> Self {
Self {
id,
abstract_num_id,
level_overrides: vec![],
}
}

pub fn overrides(mut self, overrides: Vec<LevelOverride>) -> Self {
self.level_overrides = overrides;
self
}
}

impl BuildXML for Numbering {
Expand Down Expand Up @@ -47,4 +55,40 @@ mod tests {
</w:num>"#
);
}
/* TODO: enable when builder implemented
#[test]
fn test_numbering_override() {
let c = Numbering::new(0, 2);
let overrides = vec![
LevelOverride::new(0).start(1),
LevelOverride::new(1).start(1),
];
let b = c.overrides(overrides).build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:num w:numId="0">
<w:abstractNumId w:val="2" />
<w:lvlOverride w:ilvl="0">
<w:startOverride w:val="1"/>
</w:lvlOverride>
<w:lvlOverride w:ilvl="1">
<w:startOverride w:val="1"/>
</w:lvlOverride>
</w:num>"#
);
}
*/

#[test]
fn test_numbering_override_json() {
let c = Numbering::new(0, 2);
let overrides = vec![
LevelOverride::new(0).start(1),
LevelOverride::new(1).start(1),
];
assert_eq!(
serde_json::to_string(&c.overrides(overrides)).unwrap(),
r#"{"id":0,"abstractNumId":2,"levelOverrides":[{"level":0,"start":1},{"level":1,"start":1}]}"#
);
}
}
4 changes: 3 additions & 1 deletion docx-core/src/documents/elements/numbering_id.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::documents::BuildXML;
use crate::xml_builder::*;

#[derive(Debug, Clone, PartialEq)]
use serde::Serialize;

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct NumberingId {
pub id: usize,
}
Expand Down
39 changes: 39 additions & 0 deletions docx-core/src/reader/level_override.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::io::Read;
use std::str::FromStr;

use xml::attribute::OwnedAttribute;
use xml::reader::{EventReader, XmlEvent};

use super::*;

impl ElementReader for LevelOverride {
fn read<R: Read>(
r: &mut EventReader<R>,
attrs: &[OwnedAttribute],
) -> Result<Self, ReaderError> {
let mut o = LevelOverride::new(usize::from_str(&attrs[0].value)?);
loop {
let e = r.next();
match e {
Ok(XmlEvent::StartElement {
attributes, name, ..
}) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::StartOverride = e {
let val = usize::from_str(&attributes[0].value)?;
o = o.start(val);
continue;
}
}
Ok(XmlEvent::EndElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if e == XMLElement::LvlOverride {
return Ok(o);
}
}
Err(_) => return Err(ReaderError::XMLReadError),
_ => {}
}
}
}
}
1 change: 1 addition & 0 deletions docx-core/src/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod wp_anchor;
mod wps_shape;
mod wps_text_box;
mod xml_element;
mod level_override;

use std::io::Cursor;
use zip;
Expand Down
48 changes: 45 additions & 3 deletions docx-core/src/reader/numberings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,33 @@ impl FromXML for Numberings {
}
}
let mut abs_num_id = 0;
let mut level_overrides = vec![];

loop {
let e = parser.next();
match e {
Ok(XmlEvent::StartElement {
attributes, name, ..
}) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::AbstractNumberingId = e {
abs_num_id = usize::from_str(&attributes[0].value)?;
match e {
XMLElement::AbstractNumberingId => {
abs_num_id = usize::from_str(&attributes[0].value)?
}
XMLElement::LvlOverride => {
let o =
LevelOverride::read(&mut parser, &attributes)?;
level_overrides.push(o);
}
_ => {}
}
}
Ok(XmlEvent::EndElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::Num = e {
let num = Numbering::new(id, abs_num_id);
nums =
nums.add_numbering(Numbering::new(id, abs_num_id));
nums.add_numbering(num.overrides(level_overrides));
break;
}
}
Expand Down Expand Up @@ -204,4 +215,35 @@ mod tests {
.add_numbering(Numbering::new(1, 0));
assert_eq!(n, nums)
}

#[test]
fn test_numberings_from_xml_with_override() {
let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
<w:abstractNum w:abstractNumId="0">
<w:multiLevelType w:val="hybridMultilevel"/>
</w:abstractNum>
<w:num w:numId="1">
<w:abstractNumId w:val="0"></w:abstractNumId>
<w:lvlOverride w:ilvl="0">
<w:startOverride w:val="1"/>
</w:lvlOverride>
<w:lvlOverride w:ilvl="1">
<w:startOverride w:val="1"/>
</w:lvlOverride>
</w:num>
</w:numbering>"#;
let n = Numberings::from_xml(xml.as_bytes()).unwrap();
let mut nums = Numberings::new();
let overrides = vec![
LevelOverride::new(0).start(1),
LevelOverride::new(1).start(1),
];
let num = Numbering::new(1, 0).overrides(overrides);
dbg!(&num);
nums = nums
.add_abstract_numbering(AbstractNumbering::new(0))
.add_numbering(num);
assert_eq!(n, nums)
}
}
4 changes: 4 additions & 0 deletions docx-core/src/reader/xml_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pub enum XMLElement {
Relationships,
AbstractNumbering,
AbstractNumberingId,
LvlOverride,
StartOverride,
Level,
Numbering,
Num,
Expand Down Expand Up @@ -217,6 +219,8 @@ impl FromStr for XMLElement {
"drawing" => Ok(XMLElement::Drawing),
"txbxContent" => Ok(XMLElement::TxbxContent),
"pict" => Ok(XMLElement::Pict),
"lvlOverride" => Ok(XMLElement::LvlOverride),
"startOverride" => Ok(XMLElement::StartOverride),
_ => Ok(XMLElement::Unsupported),
}
}
Expand Down
2 changes: 1 addition & 1 deletion docx-core/tests/snapshots/lib__reader__read_hello.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docx-core/tests/snapshots/lib__reader__read_numbering.snap

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docx-core/tests/snapshots/reader__read_hello.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docx-core/tests/snapshots/reader__read_numbering.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docx-core/tests/snapshots/reader__read_table_docx.snap

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docx-wasm/js/json/numbering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export type AbstractNumberingJSON = {
export type NumberingJSON = {
id: number;
abstractNumId: number;
LevelOverrides: LevelOverrideJSON[];
};

export type LevelOverrideJSON = {
level: number;
start: number;
};

export type NumberingsJSON = {
Expand Down

0 comments on commit 6336859

Please sign in to comment.