parent
b8ad56daab
commit
a4ddb3a5ee
|
@ -0,0 +1,67 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::documents::*;
|
||||
|
||||
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_PAGEREFPAGEREF_topic_ID0EHXK1.html
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Default)]
|
||||
pub struct InstrPAGEREF {
|
||||
pub page_ref: String,
|
||||
pub hyperlink: bool,
|
||||
pub relative_position: bool,
|
||||
}
|
||||
|
||||
impl InstrPAGEREF {
|
||||
pub fn new(r: impl Into<String>) -> Self {
|
||||
Self {
|
||||
page_ref: r.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hyperlink(mut self) -> Self {
|
||||
self.hyperlink = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn relative_position(mut self) -> Self {
|
||||
self.relative_position = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for InstrPAGEREF {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
let mut instr = format!("PAGEREF {}", self.page_ref);
|
||||
|
||||
if self.relative_position {
|
||||
instr = format!("{} \\p", instr);
|
||||
}
|
||||
|
||||
if self.hyperlink {
|
||||
instr = format!("{} \\h", instr);
|
||||
}
|
||||
|
||||
instr.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for InstrPAGEREF {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(instr: &str) -> Result<Self, Self::Err> {
|
||||
let mut s = instr.split(' ');
|
||||
let text = s.next();
|
||||
let mut page_ref = InstrPAGEREF::new(text.unwrap_or_default());
|
||||
loop {
|
||||
if let Some(i) = s.next() {
|
||||
match i {
|
||||
"\\h" => page_ref = page_ref.hyperlink(),
|
||||
"\\p" => page_ref = page_ref.relative_position(),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
return Ok(page_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::documents::*;
|
||||
|
||||
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TCTC_topic_ID0EU2N1.html
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Default)]
|
||||
pub struct InstrTC {
|
||||
pub text: String,
|
||||
// \n Omits the page number for the entry.
|
||||
pub omits_page_number: bool,
|
||||
pub level: Option<usize>,
|
||||
// \f
|
||||
pub item_type_identifier: Option<String>,
|
||||
}
|
||||
|
||||
impl InstrTC {
|
||||
pub fn new(text: impl Into<String>) -> Self {
|
||||
Self {
|
||||
text: text.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn omits_page_number(mut self) -> Self {
|
||||
self.omits_page_number = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn level(mut self, level: usize) -> Self {
|
||||
self.level = Some(level);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn item_type_identifier(mut self, t: impl Into<String>) -> Self {
|
||||
self.item_type_identifier = Some(t.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for InstrTC {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
let mut instr = format!("TC {}", self.text);
|
||||
|
||||
if let Some(ref t) = self.item_type_identifier {
|
||||
instr = format!("{} \\f {}", instr, t);
|
||||
}
|
||||
|
||||
if let Some(level) = self.level {
|
||||
instr = format!("{} \\l {}", instr, level);
|
||||
}
|
||||
|
||||
if self.omits_page_number {
|
||||
instr = format!("{} \\n", instr);
|
||||
}
|
||||
|
||||
instr.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_level(i: &str) -> Option<usize> {
|
||||
let r = i.replace(""", "").replace("\"", "");
|
||||
if let Ok(l) = usize::from_str(&r) {
|
||||
return Some(l);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl std::str::FromStr for InstrTC {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(instr: &str) -> Result<Self, Self::Err> {
|
||||
let mut s = instr.split(' ');
|
||||
let text = s.next();
|
||||
let mut tc = InstrTC::new(text.unwrap_or_default());
|
||||
loop {
|
||||
if let Some(i) = s.next() {
|
||||
match i {
|
||||
"\\f" => {
|
||||
if let Some(r) = s.next() {
|
||||
let r = r.replace(""", "").replace("\"", "");
|
||||
tc = tc.item_type_identifier(r);
|
||||
}
|
||||
}
|
||||
"\\l" => {
|
||||
if let Some(r) = s.next() {
|
||||
if let Some(l) = parse_level(r) {
|
||||
tc = tc.level(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
"\\n" => tc = tc.omits_page_number(),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
return Ok(tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ use crate::xml_builder::*;
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InstrText {
|
||||
TOC(InstrToC),
|
||||
TC(InstrTC),
|
||||
PAGEREF(InstrPAGEREF),
|
||||
Unsupported(String),
|
||||
}
|
||||
|
||||
|
@ -14,6 +16,8 @@ impl BuildXML for Box<InstrText> {
|
|||
fn build(&self) -> Vec<u8> {
|
||||
let instr = match self.as_ref() {
|
||||
InstrText::TOC(toc) => toc.build(),
|
||||
InstrText::TC(tc) => tc.build(),
|
||||
InstrText::PAGEREF(page_ref) => page_ref.build(),
|
||||
InstrText::Unsupported(s) => s.as_bytes().to_vec(),
|
||||
};
|
||||
XMLBuilder::new()
|
||||
|
@ -36,6 +40,18 @@ impl Serialize for InstrText {
|
|||
t.serialize_field("data", s)?;
|
||||
t.end()
|
||||
}
|
||||
InstrText::TC(ref s) => {
|
||||
let mut t = serializer.serialize_struct("TC", 2)?;
|
||||
t.serialize_field("type", "tc")?;
|
||||
t.serialize_field("data", s)?;
|
||||
t.end()
|
||||
}
|
||||
InstrText::PAGEREF(ref s) => {
|
||||
let mut t = serializer.serialize_struct("PAGEREF", 2)?;
|
||||
t.serialize_field("type", "pageref")?;
|
||||
t.serialize_field("data", s)?;
|
||||
t.end()
|
||||
}
|
||||
InstrText::Unsupported(ref s) => {
|
||||
let mut t = serializer.serialize_struct("Unsupported", 2)?;
|
||||
t.serialize_field("type", "unsupported")?;
|
||||
|
@ -62,4 +78,16 @@ mod tests {
|
|||
r#"<w:instrText>TOC \o "1-3"</w:instrText>"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pageref_instr() {
|
||||
let b = Box::new(InstrText::PAGEREF(
|
||||
InstrPAGEREF::new("_Toc90425847").hyperlink(),
|
||||
))
|
||||
.build();
|
||||
assert_eq!(
|
||||
str::from_utf8(&b).unwrap(),
|
||||
r#"<w:instrText>PAGEREF _Toc90425847 \h</w:instrText>"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ mod default_tab_stop;
|
|||
mod delete;
|
||||
mod delete_text;
|
||||
mod div;
|
||||
mod instr_toc;
|
||||
mod doc_defaults;
|
||||
mod doc_grid;
|
||||
mod doc_id;
|
||||
|
@ -33,7 +32,10 @@ mod highlight;
|
|||
mod indent;
|
||||
mod indent_level;
|
||||
mod insert;
|
||||
mod instr_pageref;
|
||||
mod instr_tc;
|
||||
mod instr_text;
|
||||
mod instr_toc;
|
||||
mod italic;
|
||||
mod italic_cs;
|
||||
mod justification;
|
||||
|
@ -136,7 +138,10 @@ pub use highlight::*;
|
|||
pub use indent::*;
|
||||
pub use indent_level::*;
|
||||
pub use insert::*;
|
||||
pub use instr_pageref::*;
|
||||
pub use instr_tc::*;
|
||||
pub use instr_text::*;
|
||||
pub use instr_toc::*;
|
||||
pub use italic::*;
|
||||
pub use italic_cs::*;
|
||||
pub use justification::*;
|
||||
|
@ -204,4 +209,3 @@ pub use wp_anchor::*;
|
|||
pub use wps_shape::*;
|
||||
pub use wps_text_box::*;
|
||||
pub use zoom::*;
|
||||
pub use instr_toc::*;
|
||||
|
|
|
@ -29,10 +29,19 @@ impl ElementReader for InstrText {
|
|||
return Err(ReaderError::XMLReadError);
|
||||
} else {
|
||||
if instr.starts_with("TOC") {
|
||||
for i in instr.split(' ') {
|
||||
dbg!(i);
|
||||
if let Ok(instr) = InstrToC::from_str(instr) {
|
||||
return Ok(InstrText::TOC(instr));
|
||||
}
|
||||
}
|
||||
if instr.starts_with("TC") {
|
||||
if let Ok(instr) = InstrTC::from_str(instr) {
|
||||
return Ok(InstrText::TC(instr));
|
||||
}
|
||||
}
|
||||
if instr.starts_with("PAGEREF") {
|
||||
if let Ok(instr) = InstrPAGEREF::from_str(instr) {
|
||||
return Ok(InstrText::PAGEREF(instr));
|
||||
}
|
||||
return Ok(InstrText::TOC(InstrToC::new()));
|
||||
}
|
||||
return Ok(InstrText::Unsupported(instr.to_string()));
|
||||
}
|
||||
|
|
|
@ -23126,15 +23126,19 @@ Object {
|
|||
"caption_label_including_numbers": null,
|
||||
"entry_and_page_number_separator": null,
|
||||
"entry_bookmark_name": null,
|
||||
"hide_tab_and_page_numbers_in_webview": false,
|
||||
"hyperlink": false,
|
||||
"heading_styles_range": Array [
|
||||
1,
|
||||
3,
|
||||
],
|
||||
"hide_tab_and_page_numbers_in_webview": true,
|
||||
"hyperlink": true,
|
||||
"preserve_new_line": false,
|
||||
"preserve_tab": false,
|
||||
"seq_field_identifier_for_prefix": null,
|
||||
"sequence_and_page_numbers_separator": null,
|
||||
"styles_with_levels": Array [],
|
||||
"tc_field_identifier": null,
|
||||
"use_applied_paragraph_line_level": false,
|
||||
"use_applied_paragraph_line_level": true,
|
||||
},
|
||||
"type": "toc",
|
||||
},
|
||||
|
@ -23351,8 +23355,12 @@ Object {
|
|||
"children": Array [
|
||||
Object {
|
||||
"data": Object {
|
||||
"data": "PAGEREF _Toc89816785 \\\\h",
|
||||
"type": "unsupported",
|
||||
"data": Object {
|
||||
"hyperlink": true,
|
||||
"page_ref": "PAGEREF",
|
||||
"relative_position": false,
|
||||
},
|
||||
"type": "pageref",
|
||||
},
|
||||
"type": "instrText",
|
||||
},
|
||||
|
@ -23695,8 +23703,12 @@ Object {
|
|||
"children": Array [
|
||||
Object {
|
||||
"data": Object {
|
||||
"data": "PAGEREF _Toc89816786 \\\\h",
|
||||
"type": "unsupported",
|
||||
"data": Object {
|
||||
"hyperlink": true,
|
||||
"page_ref": "PAGEREF",
|
||||
"relative_position": false,
|
||||
},
|
||||
"type": "pageref",
|
||||
},
|
||||
"type": "instrText",
|
||||
},
|
||||
|
@ -24039,8 +24051,12 @@ Object {
|
|||
"children": Array [
|
||||
Object {
|
||||
"data": Object {
|
||||
"data": "PAGEREF _Toc89816787 \\\\h",
|
||||
"type": "unsupported",
|
||||
"data": Object {
|
||||
"hyperlink": true,
|
||||
"page_ref": "PAGEREF",
|
||||
"relative_position": false,
|
||||
},
|
||||
"type": "pageref",
|
||||
},
|
||||
"type": "instrText",
|
||||
},
|
||||
|
@ -24383,8 +24399,12 @@ Object {
|
|||
"children": Array [
|
||||
Object {
|
||||
"data": Object {
|
||||
"data": "PAGEREF _Toc89816788 \\\\h",
|
||||
"type": "unsupported",
|
||||
"data": Object {
|
||||
"hyperlink": true,
|
||||
"page_ref": "PAGEREF",
|
||||
"relative_position": false,
|
||||
},
|
||||
"type": "pageref",
|
||||
},
|
||||
"type": "instrText",
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue