Add some instr text (#385)

* feat: Add tc instr

* feat: Add pageref
main
bokuweb 2021-12-15 02:23:12 +09:00 committed by GitHub
parent b8ad56daab
commit a4ddb3a5ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 243 additions and 16 deletions

View File

@ -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);
}
}
}
}

View File

@ -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("&quot;", "").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("&quot;", "").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);
}
}
}
}

View File

@ -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 &quot;1-3&quot;</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>"#
);
}
}

View File

@ -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::*;

View File

@ -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()));
}

View File

@ -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",
},