From ccc6eda27dadfc518278599431c8d57434467851 Mon Sep 17 00:00:00 2001 From: bokuweb Date: Thu, 16 Mar 2023 18:48:24 +0900 Subject: [PATCH] fix: read sdt in cell (#601) * fix: read sdt in cell * fix * fix: add without_sdt * fix * fix * fix * fix --- docx-core/examples/toc_with_comment.rs | 38 ++ .../documents/elements/structured_data_tag.rs | 16 +- .../src/documents/elements/table_cell.rs | 28 ++ .../documents/elements/table_of_contents.rs | 86 +++- docx-core/src/documents/mod.rs | 385 +++++++++++++++--- docx-core/src/reader/table_cell.rs | 6 + docx-wasm/js/json/table.ts | 3 +- docx-wasm/js/table-cell.ts | 14 +- docx-wasm/js/table-of-contents.ts | 10 + docx-wasm/package.json | 2 +- docx-wasm/src/table_cell.rs | 9 + docx-wasm/src/table_of_contents.rs | 5 + 12 files changed, 518 insertions(+), 84 deletions(-) create mode 100644 docx-core/examples/toc_with_comment.rs diff --git a/docx-core/examples/toc_with_comment.rs b/docx-core/examples/toc_with_comment.rs new file mode 100644 index 0000000..09496f0 --- /dev/null +++ b/docx-core/examples/toc_with_comment.rs @@ -0,0 +1,38 @@ +use docx_rs::*; + +pub fn main() -> Result<(), DocxError> { + let path = std::path::Path::new("./output/examples/toc_with_comment.docx"); + let file = std::fs::File::create(&path).unwrap(); + let p1 = Paragraph::new() + .add_run(Run::new().add_text("!!Hello")) + .style("Heading1") + .page_break_before(true); + let style1 = Style::new("Heading1", StyleType::Paragraph).name("Heading 1"); + let p2 = Paragraph::new() + .add_run(Run::new().add_text("World")) + .style("Heading2") + .page_break_before(true); + let p3 = Paragraph::new() + .add_comment_start( + Comment::new(1) + .author("bokuweb") + .date("2019-01-01T00:00:00Z") + .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Comment"))), + ) + .add_run(Run::new().add_text("CommentTarget")) + .add_comment_end(1); + + Docx::new() + .add_style(style1) + .add_table_of_contents( + TableOfContents::new() + .heading_styles_range(1, 3) + .alias("Table of contents") + .add_before_paragraph(p3), + ) + .add_paragraph(p1) + .add_paragraph(p2) + .build() + .pack(file)?; + Ok(()) +} diff --git a/docx-core/src/documents/elements/structured_data_tag.rs b/docx-core/src/documents/elements/structured_data_tag.rs index dc8e5bb..11dc089 100644 --- a/docx-core/src/documents/elements/structured_data_tag.rs +++ b/docx-core/src/documents/elements/structured_data_tag.rs @@ -147,10 +147,8 @@ impl StructuredDataTag { self.property = self.property.alias(v); self } -} -impl BuildXML for StructuredDataTag { - fn build(&self) -> Vec { + fn inner_build(&self) -> Vec { XMLBuilder::new() .open_structured_tag() .add_child(&self.property) @@ -162,6 +160,18 @@ impl BuildXML for StructuredDataTag { } } +impl BuildXML for StructuredDataTag { + fn build(&self) -> Vec { + self.inner_build() + } +} + +impl BuildXML for Box { + fn build(&self) -> Vec { + self.inner_build() + } +} + #[cfg(test)] mod tests { diff --git a/docx-core/src/documents/elements/table_cell.rs b/docx-core/src/documents/elements/table_cell.rs index ac43d37..c757112 100644 --- a/docx-core/src/documents/elements/table_cell.rs +++ b/docx-core/src/documents/elements/table_cell.rs @@ -18,6 +18,8 @@ pub struct TableCell { pub enum TableCellContent { Paragraph(Paragraph), Table(Table), + StructuredDataTag(Box), + TableOfContents(Box), } impl Serialize for TableCellContent { @@ -38,6 +40,18 @@ impl Serialize for TableCellContent { t.serialize_field("data", s)?; t.end() } + TableCellContent::StructuredDataTag(ref r) => { + let mut t = serializer.serialize_struct("StructuredDataTag", 2)?; + t.serialize_field("type", "structuredDataTag")?; + t.serialize_field("data", r)?; + t.end() + } + TableCellContent::TableOfContents(ref r) => { + let mut t = serializer.serialize_struct("TableOfContents", 2)?; + t.serialize_field("type", "tableOfContents")?; + t.serialize_field("data", r)?; + t.end() + } } } } @@ -55,6 +69,18 @@ impl TableCell { self } + pub fn add_table_of_contents(mut self, t: TableOfContents) -> Self { + self.children + .push(TableCellContent::TableOfContents(Box::new(t))); + self + } + + pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Self { + self.children + .push(TableCellContent::StructuredDataTag(Box::new(t))); + self + } + pub fn add_table(mut self, t: Table) -> TableCell { if t.has_numbering { self.has_numbering = true @@ -140,6 +166,8 @@ impl BuildXML for TableCell { b = b.add_child(&Paragraph::new()) } } + TableCellContent::StructuredDataTag(t) => b = b.add_child(t), + TableCellContent::TableOfContents(t) => b = b.add_child(t), } } // INFO: We need to add empty paragraph when parent cell includes only cell. diff --git a/docx-core/src/documents/elements/table_of_contents.rs b/docx-core/src/documents/elements/table_of_contents.rs index ebe1a53..49b66de 100644 --- a/docx-core/src/documents/elements/table_of_contents.rs +++ b/docx-core/src/documents/elements/table_of_contents.rs @@ -39,8 +39,8 @@ pub struct TableOfContentsReviewData { pub date: String, } -// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TOCTOC_topic_ID0ELZO1.html -// This struct is only used by writers +/// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TOCTOC_topic_ID0ELZO1.html +/// This struct is only used by writers #[derive(Serialize, Debug, Clone, PartialEq, Default)] pub struct TableOfContents { pub instr: InstrToC, @@ -48,6 +48,8 @@ pub struct TableOfContents { // don't use pub auto: bool, pub dirty: bool, + /// Skip StructuredDataTag rendering + pub without_sdt: bool, pub alias: Option, pub page_ref_placeholder: Option, // it is inserted in before toc. @@ -141,19 +143,26 @@ impl TableOfContents { self.after_contents.push(TocContent::Table(Box::new(t))); self } -} -impl BuildXML for TableOfContents { - fn build(&self) -> Vec { + pub fn without_sdt(mut self) -> Self { + self.without_sdt = true; + self + } + + fn inner_build(&self) -> Vec { let mut p = StructuredDataTagProperty::new(); if let Some(ref alias) = self.alias { p = p.alias(alias); } if self.items.is_empty() { - let mut b = XMLBuilder::new() - .open_structured_tag() - .add_child(&p) - .open_structured_tag_content(); + let mut b = XMLBuilder::new(); + + if !self.without_sdt { + b = b + .open_structured_tag() + .add_child(&p) + .open_structured_tag_content(); + } for c in self.before_contents.iter() { match c { @@ -207,13 +216,22 @@ impl BuildXML for TableOfContents { } } TocContent::Table(t) => { + // insert empty line for table + // because it causes docx error if table is added after TOC + if i == 0 { + b = b.add_child(&Paragraph::new().add_run(Run::new().add_text(""))); + } b = b.add_child(t); } } } } - b.close().close().build() + if !self.without_sdt { + b = b.close().close(); + } + + b.build() } else { let items: Vec = self .items @@ -229,10 +247,14 @@ impl BuildXML for TableOfContents { }) .collect(); - let mut b = XMLBuilder::new() - .open_structured_tag() - .add_child(&p) - .open_structured_tag_content(); + let mut b = XMLBuilder::new(); + + if !self.without_sdt { + b = b + .open_structured_tag() + .add_child(&p) + .open_structured_tag_content(); + } for c in self.before_contents.iter() { match c { @@ -247,22 +269,42 @@ impl BuildXML for TableOfContents { b = b.add_child(&items); - for c in self.after_contents.iter() { + for (i, c) in self.after_contents.iter().enumerate() { match c { TocContent::Paragraph(p) => { b = b.add_child(p); } TocContent::Table(t) => { + // insert empty line for table + // because it causes docx error if table is added after TOC + if i == 0 { + b = b.add_child(&Paragraph::new().add_run(Run::new().add_text(""))); + } b = b.add_child(t); } } } - b.close().close().build() + if !self.without_sdt { + b = b.close().close(); + } + b.build() } } } +impl BuildXML for TableOfContents { + fn build(&self) -> Vec { + self.inner_build() + } +} + +impl BuildXML for Box { + fn build(&self) -> Vec { + self.inner_build() + } +} + #[cfg(test)] mod tests { @@ -281,6 +323,18 @@ mod tests { ); } + #[test] + fn test_toc_without_sdt() { + let b = TableOfContents::new() + .without_sdt() + .heading_styles_range(1, 3) + .build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#"TOC \o "1-3""# + ); + } + /* #[test] fn test_toc_with_items() { diff --git a/docx-core/src/documents/mod.rs b/docx-core/src/documents/mod.rs index c348487..2feefaf 100644 --- a/docx-core/src/documents/mod.rs +++ b/docx-core/src/documents/mod.rs @@ -692,6 +692,85 @@ impl Docx { &mut hyperlink_map, ); } + DocumentChild::TableOfContents(toc) => { + // TODO:refine later + for child in &toc.before_contents { + if let TocContent::Paragraph(paragraph) = child { + for child in ¶graph.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended( + &mut comments, + &mut comments_extended, + &comment_map, + c, + ); + } + if let ParagraphChild::Hyperlink(h) = child { + if let HyperlinkData::External { rid, path } = h.link.clone() { + hyperlink_map.insert(rid, path); + }; + for child in &h.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended( + &mut comments, + &mut comments_extended, + &comment_map, + c, + ); + } + } + } + } + } + if let TocContent::Table(table) = child { + collect_dependencies_in_table( + table, + &mut comments, + &mut comments_extended, + &mut comment_map, + &mut hyperlink_map, + ); + } + } + for child in &toc.after_contents { + if let TocContent::Paragraph(paragraph) = child { + for child in ¶graph.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended( + &mut comments, + &mut comments_extended, + &comment_map, + c, + ); + } + if let ParagraphChild::Hyperlink(h) = child { + if let HyperlinkData::External { rid, path } = h.link.clone() { + hyperlink_map.insert(rid, path); + }; + for child in &h.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended( + &mut comments, + &mut comments_extended, + &comment_map, + c, + ); + } + } + } + } + } + if let TocContent::Table(table) = child { + collect_dependencies_in_table( + table, + &mut comments, + &mut comments_extended, + &mut comment_map, + &mut hyperlink_map, + ); + } + } + } _ => {} } } @@ -794,6 +873,61 @@ impl Docx { &mut image_bufs, ); } + TableCellContent::StructuredDataTag(tag) => { + for child in &mut tag.children { + if let StructuredDataTagChild::Paragraph(paragraph) = + child + { + collect_images_from_paragraph( + paragraph, + &mut images, + &mut image_bufs, + ); + } + if let StructuredDataTagChild::Table(table) = child { + collect_images_from_table( + table, + &mut images, + &mut image_bufs, + ); + } + } + } + TableCellContent::TableOfContents(t) => { + for child in &mut t.before_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_images_from_paragraph( + paragraph, + &mut images, + &mut image_bufs, + ); + } + if let TocContent::Table(table) = child { + collect_images_from_table( + table, + &mut images, + &mut image_bufs, + ); + } + } + + for child in &mut t.after_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_images_from_paragraph( + paragraph, + &mut images, + &mut image_bufs, + ); + } + if let TocContent::Table(table) = child { + collect_images_from_table( + table, + &mut images, + &mut image_bufs, + ); + } + } + } } } } @@ -806,6 +940,30 @@ impl Docx { } } +fn collect_dependencies_in_paragraph( + paragraph: &Paragraph, + comments: &mut Vec, + comments_extended: &mut Vec, + comment_map: &mut HashMap, + hyperlink_map: &mut HashMap, +) { + for child in ¶graph.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended(comments, comments_extended, comment_map, c); + } + if let ParagraphChild::Hyperlink(h) = child { + if let HyperlinkData::External { rid, path } = h.link.clone() { + hyperlink_map.insert(rid, path); + }; + for child in &h.children { + if let ParagraphChild::CommentStart(c) = child { + push_comment_and_comment_extended(comments, comments_extended, comment_map, c); + } + } + } + } +} + fn collect_dependencies_in_table( table: &Table, comments: &mut Vec, @@ -818,31 +976,13 @@ fn collect_dependencies_in_table( for content in &cell.children { match content { TableCellContent::Paragraph(paragraph) => { - for child in ¶graph.children { - if let ParagraphChild::CommentStart(c) = child { - push_comment_and_comment_extended( - comments, - comments_extended, - comment_map, - c, - ); - } - if let ParagraphChild::Hyperlink(h) = child { - if let HyperlinkData::External { rid, path } = h.link.clone() { - hyperlink_map.insert(rid, path); - }; - for child in &h.children { - if let ParagraphChild::CommentStart(c) = child { - push_comment_and_comment_extended( - comments, - comments_extended, - comment_map, - c, - ); - } - } - } - } + collect_dependencies_in_paragraph( + paragraph, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); } TableCellContent::Table(table) => collect_dependencies_in_table( table, @@ -851,6 +991,105 @@ fn collect_dependencies_in_table( comment_map, hyperlink_map, ), + TableCellContent::StructuredDataTag(tag) => { + for child in &tag.children { + if let StructuredDataTagChild::Paragraph(paragraph) = child { + collect_dependencies_in_paragraph( + paragraph, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + if let StructuredDataTagChild::Table(table) = child { + collect_dependencies_in_table( + table, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + } + } + TableCellContent::TableOfContents(t) => { + for child in &t.before_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_dependencies_in_paragraph( + paragraph, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + if let TocContent::Table(table) = child { + collect_dependencies_in_table( + table, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + } + + for child in &t.after_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_dependencies_in_paragraph( + paragraph, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + if let TocContent::Table(table) = child { + collect_dependencies_in_table( + table, + comments, + comments_extended, + comment_map, + hyperlink_map, + ); + } + } + } + } + } + } + } +} + +fn store_comments_in_paragraph(paragraph: &mut Paragraph, comments: &[Comment]) { + for child in &mut paragraph.children { + if let ParagraphChild::CommentStart(ref mut c) = child { + let comment_id = c.get_id(); + if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) { + let comment = comment.clone(); + c.as_mut().comment(comment); + } + } + if let ParagraphChild::Insert(ref mut insert) = child { + for child in &mut insert.children { + if let InsertChild::CommentStart(ref mut c) = child { + let comment_id = c.get_id(); + if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) { + let comment = comment.clone(); + c.as_mut().comment(comment); + } + } + } + } + if let ParagraphChild::Delete(ref mut delete) = child { + for child in &mut delete.children { + if let DeleteChild::CommentStart(ref mut c) = child { + let comment_id = c.get_id(); + if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) { + let comment = comment.clone(); + c.as_mut().comment(comment); + } } } } @@ -863,47 +1102,40 @@ fn store_comments_in_table(table: &mut Table, comments: &[Comment]) { for content in &mut cell.children { match content { TableCellContent::Paragraph(paragraph) => { - for child in &mut paragraph.children { - if let ParagraphChild::CommentStart(ref mut c) = child { - let comment_id = c.get_id(); - if let Some(comment) = - comments.iter().find(|c| c.id() == comment_id) - { - let comment = comment.clone(); - c.as_mut().comment(comment); - } - } - if let ParagraphChild::Insert(ref mut insert) = child { - for child in &mut insert.children { - if let InsertChild::CommentStart(ref mut c) = child { - let comment_id = c.get_id(); - if let Some(comment) = - comments.iter().find(|c| c.id() == comment_id) - { - let comment = comment.clone(); - c.as_mut().comment(comment); - } - } - } - } - if let ParagraphChild::Delete(ref mut delete) = child { - for child in &mut delete.children { - if let DeleteChild::CommentStart(ref mut c) = child { - let comment_id = c.get_id(); - if let Some(comment) = - comments.iter().find(|c| c.id() == comment_id) - { - let comment = comment.clone(); - c.as_mut().comment(comment); - } - } - } - } - } + store_comments_in_paragraph(paragraph, comments) } TableCellContent::Table(ref mut table) => { store_comments_in_table(table, comments); } + TableCellContent::StructuredDataTag(ref mut tag) => { + for child in &mut tag.children { + if let StructuredDataTagChild::Paragraph(paragraph) = child { + store_comments_in_paragraph(paragraph, comments); + } + if let StructuredDataTagChild::Table(table) = child { + store_comments_in_table(table, comments); + } + } + } + TableCellContent::TableOfContents(ref mut t) => { + for child in &mut t.before_contents { + if let TocContent::Paragraph(paragraph) = child { + store_comments_in_paragraph(paragraph, comments); + } + if let TocContent::Table(table) = child { + store_comments_in_table(table, comments); + } + } + + for child in &mut t.after_contents { + if let TocContent::Paragraph(paragraph) = child { + store_comments_in_paragraph(paragraph, comments); + } + if let TocContent::Table(table) = child { + store_comments_in_table(table, comments); + } + } + } } } } @@ -1039,6 +1271,35 @@ fn collect_images_from_table( TableCellContent::Table(table) => { collect_images_from_table(table, images, image_bufs) } + TableCellContent::StructuredDataTag(tag) => { + for child in &mut tag.children { + if let StructuredDataTagChild::Paragraph(paragraph) = child { + collect_images_from_paragraph(paragraph, images, image_bufs); + } + if let StructuredDataTagChild::Table(table) = child { + collect_images_from_table(table, images, image_bufs); + } + } + } + TableCellContent::TableOfContents(t) => { + for child in &mut t.before_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_images_from_paragraph(paragraph, images, image_bufs); + } + if let TocContent::Table(table) = child { + collect_images_from_table(table, images, image_bufs); + } + } + + for child in &mut t.after_contents { + if let TocContent::Paragraph(paragraph) = child { + collect_images_from_paragraph(paragraph, images, image_bufs); + } + if let TocContent::Table(table) = child { + collect_images_from_table(table, images, image_bufs); + } + } + } } } } diff --git a/docx-core/src/reader/table_cell.rs b/docx-core/src/reader/table_cell.rs index a7c66f6..bfd4fef 100644 --- a/docx-core/src/reader/table_cell.rs +++ b/docx-core/src/reader/table_cell.rs @@ -23,6 +23,12 @@ impl ElementReader for TableCell { cell = cell.add_paragraph(p); continue; } + XMLElement::StructuredDataTag => { + if let Ok(tag) = StructuredDataTag::read(r, &attributes) { + cell = cell.add_structured_data_tag(tag); + } + continue; + } XMLElement::TableCellProperty => { if let Ok(p) = TableCellProperty::read(r, &attributes) { cell.property = p; diff --git a/docx-wasm/js/json/table.ts b/docx-wasm/js/json/table.ts index d932e34..73d00c0 100644 --- a/docx-wasm/js/json/table.ts +++ b/docx-wasm/js/json/table.ts @@ -5,8 +5,9 @@ import { TextDirectionType } from "../table-cell"; import { ShadingJSON } from "./shading"; import { TableLayoutType } from "../table"; import { DeleteJSONData, InsertJSONData } from ".."; +import { StructuredTagJSON } from "./structured-data-tag"; -export type TableCellChildJSON = ParagraphJSON | TableJSON; +export type TableCellChildJSON = ParagraphJSON | TableJSON | StructuredTagJSON; export type WidthType = "dxa" | "auto" | "pct" | "nil"; diff --git a/docx-wasm/js/table-cell.ts b/docx-wasm/js/table-cell.ts index 5bc4a11..8e3c4f5 100644 --- a/docx-wasm/js/table-cell.ts +++ b/docx-wasm/js/table-cell.ts @@ -5,6 +5,7 @@ import { TableCellBorders, PositionKeys } from "./table-cell-borders"; import { TableCellBorderPosition, TableCellBorder } from "./table-cell-border"; import * as wasm from "./pkg"; import { convertBorderType } from "./run"; +import { TableOfContents } from "./table-of-contents"; import { build } from "./builder"; export type VMergeType = "restart" | "continue"; @@ -63,7 +64,7 @@ export type CellProperty = { }; export class TableCell { - children: (Paragraph | Table)[] = []; + children: (Paragraph | Table | TableOfContents)[] = []; hasNumberings = false; property: CellProperty = { borders: new TableCellBorders(), @@ -77,6 +78,11 @@ export class TableCell { return this; } + addTableOfContents(t: TableOfContents) { + this.children.push(t); + return this; + } + addTable(t: Table) { if (t.hasNumberings) { this.hasNumberings = true; @@ -229,6 +235,12 @@ export class TableCell { } else if (c instanceof Table) { const table = c.build(); cell = cell.add_table(table); + } else if (c instanceof TableOfContents) { + cell = cell.add_table_of_contents(c.buildWasmObject()); + } else { + // eslint-disable-next-line + const _: never = c; + console.error(_); } }); diff --git a/docx-wasm/js/table-of-contents.ts b/docx-wasm/js/table-of-contents.ts index ff65986..947f45d 100644 --- a/docx-wasm/js/table-of-contents.ts +++ b/docx-wasm/js/table-of-contents.ts @@ -11,6 +11,7 @@ export class TableOfContents { _hyperlink = false; _alias = ""; _auto = false; + _withoutSdt = false; _dirty = false; _items: TableOfContentsItem[] = []; _pageRefPlaceholder = ""; @@ -77,6 +78,11 @@ export class TableOfContents { return this; }; + withoutSdt = () => { + this._withoutSdt = true; + return this; + }; + delete = (author: string, date: string) => { this._delete = { author, date }; return this; @@ -114,6 +120,10 @@ export class TableOfContents { toc = toc.dirty(); } + if (this._withoutSdt) { + toc = toc.without_sdt(); + } + if (this._pageRefPlaceholder) { toc = toc.page_ref_placeholder(this._pageRefPlaceholder); } diff --git a/docx-wasm/package.json b/docx-wasm/package.json index 95b4550..ae5b3e9 100644 --- a/docx-wasm/package.json +++ b/docx-wasm/package.json @@ -1,6 +1,6 @@ { "name": "docx-wasm", - "version": "0.0.277-rc4", + "version": "0.0.277-sdt5", "main": "dist/node/index.js", "browser": "dist/web/index.js", "author": "bokuweb ", diff --git a/docx-wasm/src/table_cell.rs b/docx-wasm/src/table_cell.rs index aef3662..aade4f1 100644 --- a/docx-wasm/src/table_cell.rs +++ b/docx-wasm/src/table_cell.rs @@ -35,6 +35,15 @@ impl TableCell { self } + pub fn add_table_of_contents(mut self, t: TableOfContents) -> TableCell { + self.0 + .children + .push(docx_rs::TableCellContent::TableOfContents(Box::new( + t.take(), + ))); + self + } + pub fn vertical_merge(mut self, t: docx_rs::VMergeType) -> TableCell { self.0.property = self.0.property.vertical_merge(t); self diff --git a/docx-wasm/src/table_of_contents.rs b/docx-wasm/src/table_of_contents.rs index c7d472b..a4a59c1 100644 --- a/docx-wasm/src/table_of_contents.rs +++ b/docx-wasm/src/table_of_contents.rs @@ -67,6 +67,11 @@ impl TableOfContents { self } + pub fn without_sdt(mut self) -> Self { + self.0.without_sdt = true; + self + } + pub fn delete(mut self, author: &str, date: &str) -> Self { self.0 = self.0.delete(author, date); self