parent
9eec10e374
commit
d2c1417c98
|
@ -5,7 +5,7 @@ use crate::xml_builder::*;
|
|||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
pub struct BookmarkEnd {
|
||||
id: usize,
|
||||
pub id: usize,
|
||||
}
|
||||
|
||||
impl BookmarkEnd {
|
||||
|
|
|
@ -5,8 +5,8 @@ use crate::xml_builder::*;
|
|||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
pub struct BookmarkStart {
|
||||
id: usize,
|
||||
name: String,
|
||||
pub id: usize,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl BookmarkStart {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, Serializer};
|
||||
|
||||
use crate::documents::BuildXML;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
pub struct DocId {
|
||||
id: String,
|
||||
}
|
||||
|
@ -14,6 +14,15 @@ impl DocId {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serialize for DocId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for DocId {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
let b = XMLBuilder::new();
|
||||
|
|
|
@ -129,6 +129,11 @@ impl Docx {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn settings(mut self, s: Settings) -> Self {
|
||||
self.settings = s;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_paragraph(mut self, p: Paragraph) -> Docx {
|
||||
if p.has_numbering {
|
||||
// If this document has numbering, set numberings.xml to document_rels.
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
use std::io::Read;
|
||||
use std::str::FromStr;
|
||||
|
||||
use xml::attribute::OwnedAttribute;
|
||||
use xml::reader::EventReader;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl ElementReader for BookmarkEnd {
|
||||
fn read<R: Read>(
|
||||
_r: &mut EventReader<R>,
|
||||
attrs: &[OwnedAttribute],
|
||||
) -> Result<Self, ReaderError> {
|
||||
let mut id: Option<usize> = None;
|
||||
for a in attrs {
|
||||
let local_name = &a.name.local_name;
|
||||
if local_name == "id" {
|
||||
id = Some(usize::from_str(&a.value)?);
|
||||
}
|
||||
}
|
||||
if let Some(id) = id {
|
||||
Ok(BookmarkEnd::new(id))
|
||||
} else {
|
||||
Err(ReaderError::XMLReadError)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
use std::io::Read;
|
||||
use std::str::FromStr;
|
||||
|
||||
use xml::attribute::OwnedAttribute;
|
||||
use xml::reader::EventReader;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl ElementReader for BookmarkStart {
|
||||
fn read<R: Read>(
|
||||
_r: &mut EventReader<R>,
|
||||
attrs: &[OwnedAttribute],
|
||||
) -> Result<Self, ReaderError> {
|
||||
let mut id: Option<usize> = None;
|
||||
let mut name: Option<String> = None;
|
||||
|
||||
for a in attrs {
|
||||
let local_name = &a.name.local_name;
|
||||
if local_name == "id" {
|
||||
id = Some(usize::from_str(&a.value)?);
|
||||
} else if local_name == "name" {
|
||||
name = Some(a.value.clone());
|
||||
}
|
||||
}
|
||||
if id.is_none() || name.is_none() {
|
||||
return Err(ReaderError::XMLReadError);
|
||||
}
|
||||
Ok(BookmarkStart::new(id.unwrap(), name.unwrap()))
|
||||
}
|
||||
}
|
|
@ -28,6 +28,16 @@ impl FromXML for Document {
|
|||
doc = doc.add_table(t);
|
||||
continue;
|
||||
}
|
||||
XMLElement::BookmarkStart => {
|
||||
let s = BookmarkStart::read(&mut parser, &attributes)?;
|
||||
doc = doc.add_bookmark_start(s.id, s.name);
|
||||
continue;
|
||||
}
|
||||
XMLElement::BookmarkEnd => {
|
||||
let e = BookmarkEnd::read(&mut parser, &attributes)?;
|
||||
doc = doc.add_bookmark_end(e.id);
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
mod a_graphic;
|
||||
mod a_graphic_data;
|
||||
mod attributes;
|
||||
mod bookmark_end;
|
||||
mod bookmark_start;
|
||||
mod delete;
|
||||
mod document;
|
||||
mod document_rels;
|
||||
|
@ -19,6 +21,7 @@ mod read_zip;
|
|||
mod rels;
|
||||
mod run;
|
||||
mod run_property;
|
||||
mod settings;
|
||||
mod style;
|
||||
mod styles;
|
||||
mod table;
|
||||
|
@ -49,6 +52,8 @@ const STYLE_RELATIONSHIP_TYPE: &str =
|
|||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
||||
const NUMBERING_RELATIONSHIP_TYPE: &str =
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
|
||||
const SETTINGS_TYPE: &str =
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
|
||||
|
||||
pub fn read_docx(buf: &[u8]) -> Result<Docx, ReaderError> {
|
||||
let cur = Cursor::new(buf);
|
||||
|
@ -101,5 +106,16 @@ pub fn read_docx(buf: &[u8]) -> Result<Docx, ReaderError> {
|
|||
docx = docx.numberings(nums);
|
||||
}
|
||||
|
||||
// Read settings
|
||||
let settings_path = rels.find_target_path(SETTINGS_TYPE);
|
||||
if let Some(settings_path) = settings_path {
|
||||
let data = read_zip(
|
||||
&mut archive,
|
||||
settings_path.to_str().expect("should have settings"),
|
||||
)?;
|
||||
let settings = Settings::from_xml(&data[..])?;
|
||||
docx = docx.settings(settings);
|
||||
}
|
||||
|
||||
Ok(docx)
|
||||
}
|
||||
|
|
|
@ -42,36 +42,13 @@ impl ElementReader for Paragraph {
|
|||
continue;
|
||||
}
|
||||
XMLElement::BookmarkStart => {
|
||||
let mut id: Option<usize> = None;
|
||||
let mut name: Option<String> = None;
|
||||
|
||||
for a in attributes {
|
||||
let local_name = &a.name.local_name;
|
||||
if local_name == "id" {
|
||||
id = Some(usize::from_str(&a.value)?);
|
||||
} else if local_name == "name" {
|
||||
name = Some(a.value.clone());
|
||||
}
|
||||
}
|
||||
if id.is_none() || name.is_none() {
|
||||
return Err(ReaderError::XMLReadError);
|
||||
}
|
||||
p = p.add_bookmark_start(id.unwrap(), name.unwrap());
|
||||
let s = BookmarkStart::read(r, &attributes)?;
|
||||
p = p.add_bookmark_start(s.id, s.name);
|
||||
continue;
|
||||
}
|
||||
XMLElement::BookmarkEnd => {
|
||||
let mut id: Option<usize> = None;
|
||||
for a in attributes {
|
||||
let local_name = &a.name.local_name;
|
||||
if local_name == "id" {
|
||||
id = Some(usize::from_str(&a.value)?);
|
||||
}
|
||||
}
|
||||
if let Some(id) = id {
|
||||
p = p.add_bookmark_end(id);
|
||||
} else {
|
||||
return Err(ReaderError::XMLReadError);
|
||||
}
|
||||
let e = BookmarkEnd::read(r, &attributes)?;
|
||||
p = p.add_bookmark_end(e.id);
|
||||
continue;
|
||||
}
|
||||
XMLElement::CommentRangeStart => {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
use std::io::Read;
|
||||
use xml::reader::{EventReader, XmlEvent};
|
||||
|
||||
use super::*;
|
||||
use crate::reader::{FromXML, ReaderError};
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
impl FromXML for Settings {
|
||||
fn from_xml<R: Read>(reader: R) -> Result<Self, ReaderError> {
|
||||
let mut parser = EventReader::new(reader);
|
||||
let mut settings = Self::default();
|
||||
|
||||
loop {
|
||||
let e = parser.next();
|
||||
match e {
|
||||
Ok(XmlEvent::StartElement {
|
||||
attributes, name, ..
|
||||
}) => {
|
||||
let e = XMLElement::from_str(&name.local_name).unwrap();
|
||||
if let XMLElement::DocId = e {
|
||||
for a in attributes {
|
||||
if let Some(prefix) = a.name.prefix {
|
||||
let local_name = &a.name.local_name;
|
||||
// Ignore w14:val
|
||||
if local_name == "val" && prefix == "w15" {
|
||||
settings = settings.doc_id(
|
||||
&a.value.to_owned().replace("{", "").replace("}", ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::EndElement { name, .. }) => {
|
||||
let e = XMLElement::from_str(&name.local_name).unwrap();
|
||||
if let XMLElement::Settings = e {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::EndDocument { .. }) => break,
|
||||
Err(_) => return Err(ReaderError::XMLReadError),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(settings)
|
||||
}
|
||||
}
|
|
@ -83,6 +83,7 @@ pub enum XMLElement {
|
|||
StartOverride,
|
||||
Level,
|
||||
Numbering,
|
||||
Settings,
|
||||
Num,
|
||||
Start,
|
||||
NumberFormat,
|
||||
|
@ -94,6 +95,7 @@ pub enum XMLElement {
|
|||
Drawing,
|
||||
TxbxContent,
|
||||
Pict,
|
||||
DocId,
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
|
@ -226,6 +228,7 @@ impl FromStr for XMLElement {
|
|||
"abstractNumId" => Ok(XMLElement::AbstractNumberingId),
|
||||
"lvl" => Ok(XMLElement::Level),
|
||||
"numbering" => Ok(XMLElement::Numbering),
|
||||
"settings" => Ok(XMLElement::Settings),
|
||||
"num" => Ok(XMLElement::Num),
|
||||
"start" => Ok(XMLElement::Start),
|
||||
"numFmt" => Ok(XMLElement::NumberFormat),
|
||||
|
@ -240,6 +243,7 @@ impl FromStr for XMLElement {
|
|||
"pict" => Ok(XMLElement::Pict),
|
||||
"lvlOverride" => Ok(XMLElement::LvlOverride),
|
||||
"startOverride" => Ok(XMLElement::StartOverride),
|
||||
"docId" => Ok(XMLElement::DocId),
|
||||
_ => Ok(XMLElement::Unsupported),
|
||||
}
|
||||
}
|
||||
|
|
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
|
@ -1,7 +1,11 @@
|
|||
import { ParagraphJSON } from "./paragraph";
|
||||
import { ParagraphJSON, BookmarkStartJSON, BookmarkEndJSON } from "./paragraph";
|
||||
import { TableJSON } from "./table";
|
||||
|
||||
export type DocumentChildJSON = ParagraphJSON | TableJSON;
|
||||
export type DocumentChildJSON =
|
||||
| ParagraphJSON
|
||||
| TableJSON
|
||||
| BookmarkStartJSON
|
||||
| BookmarkEndJSON;
|
||||
|
||||
export type DocumentJSON = {
|
||||
children: DocumentChildJSON[];
|
||||
|
|
|
@ -35,6 +35,8 @@ export type DocxJSON = {
|
|||
};
|
||||
numberings: NumberingsJSON;
|
||||
settings: {
|
||||
// w15:docId
|
||||
docId: string | null;
|
||||
defaultTabStop: number;
|
||||
zoom: number;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue