feat: impl sdt writer (#380)
parent
ad229e91ad
commit
caa61e9947
|
@ -0,0 +1,16 @@
|
|||
use docx_rs::*;
|
||||
|
||||
pub fn main() -> Result<(), DocxError> {
|
||||
let path = std::path::Path::new("./output/sdt.docx");
|
||||
let file = std::fs::File::create(&path).unwrap();
|
||||
let p = Paragraph::new().add_run(
|
||||
Run::new()
|
||||
.add_text("Hello")
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
);
|
||||
Docx::new()
|
||||
.add_structured_data_tag(StructuredDataTag::new().add_paragraph(p))
|
||||
.build()
|
||||
.pack(file)?;
|
||||
Ok(())
|
||||
}
|
|
@ -21,6 +21,7 @@ pub enum DocumentChild {
|
|||
BookmarkEnd(BookmarkEnd),
|
||||
CommentStart(Box<CommentRangeStart>),
|
||||
CommentEnd(CommentRangeEnd),
|
||||
StructuredDataTag(StructuredDataTag),
|
||||
}
|
||||
|
||||
impl Serialize for DocumentChild {
|
||||
|
@ -65,6 +66,12 @@ impl Serialize for DocumentChild {
|
|||
t.serialize_field("data", r)?;
|
||||
t.end()
|
||||
}
|
||||
DocumentChild::StructuredDataTag(ref r) => {
|
||||
let mut t = serializer.serialize_struct("StructuredDataTag", 2)?;
|
||||
t.serialize_field("type", "structuredDataTag")?;
|
||||
t.serialize_field("data", r)?;
|
||||
t.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,6 +186,14 @@ impl Document {
|
|||
self.section_property = self.section_property.even_footer(h, rid);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Self {
|
||||
if t.has_numbering {
|
||||
self.has_numbering = true
|
||||
}
|
||||
self.children.push(DocumentChild::StructuredDataTag(t));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for DocumentChild {
|
||||
|
@ -190,6 +205,7 @@ impl BuildXML for DocumentChild {
|
|||
DocumentChild::BookmarkEnd(v) => v.build(),
|
||||
DocumentChild::CommentStart(v) => v.build(),
|
||||
DocumentChild::CommentEnd(v) => v.build(),
|
||||
DocumentChild::StructuredDataTag(v) => v.build(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ mod doc_id;
|
|||
mod doc_var;
|
||||
mod drawing;
|
||||
mod font;
|
||||
mod footer_reference;
|
||||
mod grid_span;
|
||||
mod header_reference;
|
||||
mod footer_reference;
|
||||
mod highlight;
|
||||
mod indent;
|
||||
mod indent_level;
|
||||
|
@ -62,6 +62,7 @@ mod section;
|
|||
mod section_property;
|
||||
mod shading;
|
||||
mod start;
|
||||
mod structured_data_tag;
|
||||
mod style;
|
||||
mod sz;
|
||||
mod sz_cs;
|
||||
|
@ -120,9 +121,9 @@ pub use doc_id::*;
|
|||
pub use doc_var::*;
|
||||
pub use drawing::*;
|
||||
pub use font::*;
|
||||
pub use footer_reference::*;
|
||||
pub use grid_span::*;
|
||||
pub use header_reference::*;
|
||||
pub use footer_reference::*;
|
||||
pub use highlight::*;
|
||||
pub use indent::*;
|
||||
pub use indent_level::*;
|
||||
|
@ -159,6 +160,7 @@ pub use section::*;
|
|||
pub use section_property::*;
|
||||
pub use shading::*;
|
||||
pub use start::*;
|
||||
pub use structured_data_tag::*;
|
||||
pub use style::*;
|
||||
pub use sz::*;
|
||||
pub use sz_cs::*;
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
use serde::ser::{SerializeStruct, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use super::*;
|
||||
use crate::documents::BuildXML;
|
||||
// use crate::types::*;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StructuredDataTag {
|
||||
pub children: Vec<StructuredDataTagChild>,
|
||||
pub has_numbering: bool,
|
||||
}
|
||||
|
||||
impl Default for StructuredDataTag {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
children: Vec::new(),
|
||||
has_numbering: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum StructuredDataTagChild {
|
||||
Run(Box<Run>),
|
||||
Paragraph(Box<Paragraph>),
|
||||
}
|
||||
|
||||
impl BuildXML for StructuredDataTagChild {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
match self {
|
||||
StructuredDataTagChild::Run(v) => v.build(),
|
||||
StructuredDataTagChild::Paragraph(v) => v.build(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for StructuredDataTagChild {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
StructuredDataTagChild::Run(ref r) => {
|
||||
let mut t = serializer.serialize_struct("Run", 2)?;
|
||||
t.serialize_field("type", "run")?;
|
||||
t.serialize_field("data", r)?;
|
||||
t.end()
|
||||
}
|
||||
StructuredDataTagChild::Paragraph(ref r) => {
|
||||
let mut t = serializer.serialize_struct("Paragraph", 2)?;
|
||||
t.serialize_field("type", "paragraph")?;
|
||||
t.serialize_field("data", r)?;
|
||||
t.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StructuredDataTag {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn add_run(mut self, run: Run) -> Self {
|
||||
self.children
|
||||
.push(StructuredDataTagChild::Run(Box::new(run)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_paragraph(mut self, p: Paragraph) -> Self {
|
||||
if p.has_numbering {
|
||||
self.has_numbering = true
|
||||
}
|
||||
self.children
|
||||
.push(StructuredDataTagChild::Paragraph(Box::new(p)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for StructuredDataTag {
|
||||
fn build(&self) -> Vec<u8> {
|
||||
XMLBuilder::new()
|
||||
.open_structured_tag()
|
||||
.open_structured_tag_property()
|
||||
.close()
|
||||
.open_structured_tag_content()
|
||||
.add_children(&self.children)
|
||||
.close()
|
||||
.close()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
#[cfg(test)]
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::str;
|
||||
|
||||
#[test]
|
||||
fn test_sdt() {
|
||||
let b = StructuredDataTag::new()
|
||||
.add_run(Run::new().add_text("Hello"))
|
||||
.build();
|
||||
assert_eq!(
|
||||
str::from_utf8(&b).unwrap(),
|
||||
r#"<w:sdt>
|
||||
<w:sdtPr />
|
||||
<w:sdtContent><w:r><w:rPr /><w:t xml:space="preserve">Hello</w:t></w:r></w:sdtContent>
|
||||
</w:sdt>"#
|
||||
);
|
||||
}
|
||||
}
|
|
@ -191,6 +191,16 @@ impl Docx {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Docx {
|
||||
if t.has_numbering {
|
||||
// If this document has numbering, set numberings.xml to document_rels.
|
||||
// This is because numberings.xml without numbering cause an error on word online.
|
||||
self.document_rels.has_numberings = true;
|
||||
}
|
||||
self.document = self.document.add_structured_data_tag(t);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bookmark_start(mut self, id: usize, name: impl Into<String>) -> Docx {
|
||||
self.document = self.document.add_bookmark_start(id, name);
|
||||
self
|
||||
|
|
|
@ -72,6 +72,11 @@ impl XMLBuilder {
|
|||
open!(open_paragraph, "w:p", "w14:paraId");
|
||||
open!(open_paragraph_property, "w:pPr");
|
||||
open!(open_doc_defaults, "w:docDefaults");
|
||||
|
||||
open!(open_structured_tag, "w:sdt");
|
||||
open!(open_structured_tag_content, "w:sdtContent");
|
||||
open!(open_structured_tag_property, "w:sdtPr");
|
||||
|
||||
// i.e. <w:outlineLvl ...>
|
||||
closed_with_usize!(outline_lvl, "w:outlineLvl");
|
||||
// i.e. <w:name ... >
|
||||
|
|
Loading…
Reference in New Issue