fix: read sdt in cell (#601)
* fix: read sdt in cell * fix * fix: add without_sdt * fix * fix * fix * fixmain
parent
11c1618be8
commit
ccc6eda27d
|
@ -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(())
|
||||||
|
}
|
|
@ -147,10 +147,8 @@ impl StructuredDataTag {
|
||||||
self.property = self.property.alias(v);
|
self.property = self.property.alias(v);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BuildXML for StructuredDataTag {
|
fn inner_build(&self) -> Vec<u8> {
|
||||||
fn build(&self) -> Vec<u8> {
|
|
||||||
XMLBuilder::new()
|
XMLBuilder::new()
|
||||||
.open_structured_tag()
|
.open_structured_tag()
|
||||||
.add_child(&self.property)
|
.add_child(&self.property)
|
||||||
|
@ -162,6 +160,18 @@ impl BuildXML for StructuredDataTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BuildXML for StructuredDataTag {
|
||||||
|
fn build(&self) -> Vec<u8> {
|
||||||
|
self.inner_build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildXML for Box<StructuredDataTag> {
|
||||||
|
fn build(&self) -> Vec<u8> {
|
||||||
|
self.inner_build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ pub struct TableCell {
|
||||||
pub enum TableCellContent {
|
pub enum TableCellContent {
|
||||||
Paragraph(Paragraph),
|
Paragraph(Paragraph),
|
||||||
Table(Table),
|
Table(Table),
|
||||||
|
StructuredDataTag(Box<StructuredDataTag>),
|
||||||
|
TableOfContents(Box<TableOfContents>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for TableCellContent {
|
impl Serialize for TableCellContent {
|
||||||
|
@ -38,6 +40,18 @@ impl Serialize for TableCellContent {
|
||||||
t.serialize_field("data", s)?;
|
t.serialize_field("data", s)?;
|
||||||
t.end()
|
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
|
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 {
|
pub fn add_table(mut self, t: Table) -> TableCell {
|
||||||
if t.has_numbering {
|
if t.has_numbering {
|
||||||
self.has_numbering = true
|
self.has_numbering = true
|
||||||
|
@ -140,6 +166,8 @@ impl BuildXML for TableCell {
|
||||||
b = b.add_child(&Paragraph::new())
|
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.
|
// INFO: We need to add empty paragraph when parent cell includes only cell.
|
||||||
|
|
|
@ -39,8 +39,8 @@ pub struct TableOfContentsReviewData {
|
||||||
pub date: String,
|
pub date: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TOCTOC_topic_ID0ELZO1.html
|
/// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TOCTOC_topic_ID0ELZO1.html
|
||||||
// This struct is only used by writers
|
/// This struct is only used by writers
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq, Default)]
|
#[derive(Serialize, Debug, Clone, PartialEq, Default)]
|
||||||
pub struct TableOfContents {
|
pub struct TableOfContents {
|
||||||
pub instr: InstrToC,
|
pub instr: InstrToC,
|
||||||
|
@ -48,6 +48,8 @@ pub struct TableOfContents {
|
||||||
// don't use
|
// don't use
|
||||||
pub auto: bool,
|
pub auto: bool,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
|
/// Skip StructuredDataTag rendering
|
||||||
|
pub without_sdt: bool,
|
||||||
pub alias: Option<String>,
|
pub alias: Option<String>,
|
||||||
pub page_ref_placeholder: Option<String>,
|
pub page_ref_placeholder: Option<String>,
|
||||||
// it is inserted in before toc.
|
// it is inserted in before toc.
|
||||||
|
@ -141,19 +143,26 @@ impl TableOfContents {
|
||||||
self.after_contents.push(TocContent::Table(Box::new(t)));
|
self.after_contents.push(TocContent::Table(Box::new(t)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BuildXML for TableOfContents {
|
pub fn without_sdt(mut self) -> Self {
|
||||||
fn build(&self) -> Vec<u8> {
|
self.without_sdt = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner_build(&self) -> Vec<u8> {
|
||||||
let mut p = StructuredDataTagProperty::new();
|
let mut p = StructuredDataTagProperty::new();
|
||||||
if let Some(ref alias) = self.alias {
|
if let Some(ref alias) = self.alias {
|
||||||
p = p.alias(alias);
|
p = p.alias(alias);
|
||||||
}
|
}
|
||||||
if self.items.is_empty() {
|
if self.items.is_empty() {
|
||||||
let mut b = XMLBuilder::new()
|
let mut b = XMLBuilder::new();
|
||||||
.open_structured_tag()
|
|
||||||
.add_child(&p)
|
if !self.without_sdt {
|
||||||
.open_structured_tag_content();
|
b = b
|
||||||
|
.open_structured_tag()
|
||||||
|
.add_child(&p)
|
||||||
|
.open_structured_tag_content();
|
||||||
|
}
|
||||||
|
|
||||||
for c in self.before_contents.iter() {
|
for c in self.before_contents.iter() {
|
||||||
match c {
|
match c {
|
||||||
|
@ -207,13 +216,22 @@ impl BuildXML for TableOfContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TocContent::Table(t) => {
|
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 = b.add_child(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.close().close().build()
|
if !self.without_sdt {
|
||||||
|
b = b.close().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
b.build()
|
||||||
} else {
|
} else {
|
||||||
let items: Vec<TableOfContentsItem> = self
|
let items: Vec<TableOfContentsItem> = self
|
||||||
.items
|
.items
|
||||||
|
@ -229,10 +247,14 @@ impl BuildXML for TableOfContents {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut b = XMLBuilder::new()
|
let mut b = XMLBuilder::new();
|
||||||
.open_structured_tag()
|
|
||||||
.add_child(&p)
|
if !self.without_sdt {
|
||||||
.open_structured_tag_content();
|
b = b
|
||||||
|
.open_structured_tag()
|
||||||
|
.add_child(&p)
|
||||||
|
.open_structured_tag_content();
|
||||||
|
}
|
||||||
|
|
||||||
for c in self.before_contents.iter() {
|
for c in self.before_contents.iter() {
|
||||||
match c {
|
match c {
|
||||||
|
@ -247,22 +269,42 @@ impl BuildXML for TableOfContents {
|
||||||
|
|
||||||
b = b.add_child(&items);
|
b = b.add_child(&items);
|
||||||
|
|
||||||
for c in self.after_contents.iter() {
|
for (i, c) in self.after_contents.iter().enumerate() {
|
||||||
match c {
|
match c {
|
||||||
TocContent::Paragraph(p) => {
|
TocContent::Paragraph(p) => {
|
||||||
b = b.add_child(p);
|
b = b.add_child(p);
|
||||||
}
|
}
|
||||||
TocContent::Table(t) => {
|
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 = 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<u8> {
|
||||||
|
self.inner_build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildXML for Box<TableOfContents> {
|
||||||
|
fn build(&self) -> Vec<u8> {
|
||||||
|
self.inner_build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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#"<w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:fldChar w:fldCharType="begin" w:dirty="true" /><w:instrText>TOC \o "1-3"</w:instrText><w:fldChar w:fldCharType="separate" w:dirty="false" /></w:r></w:p><w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:fldChar w:fldCharType="end" w:dirty="false" /></w:r></w:p>"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#[test]
|
#[test]
|
||||||
fn test_toc_with_items() {
|
fn test_toc_with_items() {
|
||||||
|
|
|
@ -692,6 +692,85 @@ impl Docx {
|
||||||
&mut hyperlink_map,
|
&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,
|
&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<Comment>,
|
||||||
|
comments_extended: &mut Vec<CommentExtended>,
|
||||||
|
comment_map: &mut HashMap<usize, String>,
|
||||||
|
hyperlink_map: &mut HashMap<String, String>,
|
||||||
|
) {
|
||||||
|
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(
|
fn collect_dependencies_in_table(
|
||||||
table: &Table,
|
table: &Table,
|
||||||
comments: &mut Vec<Comment>,
|
comments: &mut Vec<Comment>,
|
||||||
|
@ -818,31 +976,13 @@ fn collect_dependencies_in_table(
|
||||||
for content in &cell.children {
|
for content in &cell.children {
|
||||||
match content {
|
match content {
|
||||||
TableCellContent::Paragraph(paragraph) => {
|
TableCellContent::Paragraph(paragraph) => {
|
||||||
for child in ¶graph.children {
|
collect_dependencies_in_paragraph(
|
||||||
if let ParagraphChild::CommentStart(c) = child {
|
paragraph,
|
||||||
push_comment_and_comment_extended(
|
comments,
|
||||||
comments,
|
comments_extended,
|
||||||
comments_extended,
|
comment_map,
|
||||||
comment_map,
|
hyperlink_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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TableCellContent::Table(table) => collect_dependencies_in_table(
|
TableCellContent::Table(table) => collect_dependencies_in_table(
|
||||||
table,
|
table,
|
||||||
|
@ -851,6 +991,105 @@ fn collect_dependencies_in_table(
|
||||||
comment_map,
|
comment_map,
|
||||||
hyperlink_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 {
|
for content in &mut cell.children {
|
||||||
match content {
|
match content {
|
||||||
TableCellContent::Paragraph(paragraph) => {
|
TableCellContent::Paragraph(paragraph) => {
|
||||||
for child in &mut paragraph.children {
|
store_comments_in_paragraph(paragraph, comments)
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TableCellContent::Table(ref mut table) => {
|
TableCellContent::Table(ref mut table) => {
|
||||||
store_comments_in_table(table, comments);
|
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) => {
|
TableCellContent::Table(table) => {
|
||||||
collect_images_from_table(table, images, image_bufs)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,12 @@ impl ElementReader for TableCell {
|
||||||
cell = cell.add_paragraph(p);
|
cell = cell.add_paragraph(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
XMLElement::StructuredDataTag => {
|
||||||
|
if let Ok(tag) = StructuredDataTag::read(r, &attributes) {
|
||||||
|
cell = cell.add_structured_data_tag(tag);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
XMLElement::TableCellProperty => {
|
XMLElement::TableCellProperty => {
|
||||||
if let Ok(p) = TableCellProperty::read(r, &attributes) {
|
if let Ok(p) = TableCellProperty::read(r, &attributes) {
|
||||||
cell.property = p;
|
cell.property = p;
|
||||||
|
|
|
@ -5,8 +5,9 @@ import { TextDirectionType } from "../table-cell";
|
||||||
import { ShadingJSON } from "./shading";
|
import { ShadingJSON } from "./shading";
|
||||||
import { TableLayoutType } from "../table";
|
import { TableLayoutType } from "../table";
|
||||||
import { DeleteJSONData, InsertJSONData } from "..";
|
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";
|
export type WidthType = "dxa" | "auto" | "pct" | "nil";
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { TableCellBorders, PositionKeys } from "./table-cell-borders";
|
||||||
import { TableCellBorderPosition, TableCellBorder } from "./table-cell-border";
|
import { TableCellBorderPosition, TableCellBorder } from "./table-cell-border";
|
||||||
import * as wasm from "./pkg";
|
import * as wasm from "./pkg";
|
||||||
import { convertBorderType } from "./run";
|
import { convertBorderType } from "./run";
|
||||||
|
import { TableOfContents } from "./table-of-contents";
|
||||||
import { build } from "./builder";
|
import { build } from "./builder";
|
||||||
|
|
||||||
export type VMergeType = "restart" | "continue";
|
export type VMergeType = "restart" | "continue";
|
||||||
|
@ -63,7 +64,7 @@ export type CellProperty = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class TableCell {
|
export class TableCell {
|
||||||
children: (Paragraph | Table)[] = [];
|
children: (Paragraph | Table | TableOfContents)[] = [];
|
||||||
hasNumberings = false;
|
hasNumberings = false;
|
||||||
property: CellProperty = {
|
property: CellProperty = {
|
||||||
borders: new TableCellBorders(),
|
borders: new TableCellBorders(),
|
||||||
|
@ -77,6 +78,11 @@ export class TableCell {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addTableOfContents(t: TableOfContents) {
|
||||||
|
this.children.push(t);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
addTable(t: Table) {
|
addTable(t: Table) {
|
||||||
if (t.hasNumberings) {
|
if (t.hasNumberings) {
|
||||||
this.hasNumberings = true;
|
this.hasNumberings = true;
|
||||||
|
@ -229,6 +235,12 @@ export class TableCell {
|
||||||
} else if (c instanceof Table) {
|
} else if (c instanceof Table) {
|
||||||
const table = c.build();
|
const table = c.build();
|
||||||
cell = cell.add_table(table);
|
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(_);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ export class TableOfContents {
|
||||||
_hyperlink = false;
|
_hyperlink = false;
|
||||||
_alias = "";
|
_alias = "";
|
||||||
_auto = false;
|
_auto = false;
|
||||||
|
_withoutSdt = false;
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
_items: TableOfContentsItem[] = [];
|
_items: TableOfContentsItem[] = [];
|
||||||
_pageRefPlaceholder = "";
|
_pageRefPlaceholder = "";
|
||||||
|
@ -77,6 +78,11 @@ export class TableOfContents {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
withoutSdt = () => {
|
||||||
|
this._withoutSdt = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
delete = (author: string, date: string) => {
|
delete = (author: string, date: string) => {
|
||||||
this._delete = { author, date };
|
this._delete = { author, date };
|
||||||
return this;
|
return this;
|
||||||
|
@ -114,6 +120,10 @@ export class TableOfContents {
|
||||||
toc = toc.dirty();
|
toc = toc.dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._withoutSdt) {
|
||||||
|
toc = toc.without_sdt();
|
||||||
|
}
|
||||||
|
|
||||||
if (this._pageRefPlaceholder) {
|
if (this._pageRefPlaceholder) {
|
||||||
toc = toc.page_ref_placeholder(this._pageRefPlaceholder);
|
toc = toc.page_ref_placeholder(this._pageRefPlaceholder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "docx-wasm",
|
"name": "docx-wasm",
|
||||||
"version": "0.0.277-rc4",
|
"version": "0.0.277-sdt5",
|
||||||
"main": "dist/node/index.js",
|
"main": "dist/node/index.js",
|
||||||
"browser": "dist/web/index.js",
|
"browser": "dist/web/index.js",
|
||||||
"author": "bokuweb <bokuweb12@gmail.com>",
|
"author": "bokuweb <bokuweb12@gmail.com>",
|
||||||
|
|
|
@ -35,6 +35,15 @@ impl TableCell {
|
||||||
self
|
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 {
|
pub fn vertical_merge(mut self, t: docx_rs::VMergeType) -> TableCell {
|
||||||
self.0.property = self.0.property.vertical_merge(t);
|
self.0.property = self.0.property.vertical_merge(t);
|
||||||
self
|
self
|
||||||
|
|
|
@ -67,6 +67,11 @@ impl TableOfContents {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn without_sdt(mut self) -> Self {
|
||||||
|
self.0.without_sdt = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn delete(mut self, author: &str, date: &str) -> Self {
|
pub fn delete(mut self, author: &str, date: &str) -> Self {
|
||||||
self.0 = self.0.delete(author, date);
|
self.0 = self.0.delete(author, date);
|
||||||
self
|
self
|
||||||
|
|
Loading…
Reference in New Issue