From 6fcffc7cfd8e059a8eeebb79912282294f99836a Mon Sep 17 00:00:00 2001 From: bokuweb Date: Fri, 3 Jun 2022 01:03:16 +0900 Subject: [PATCH] fix: image writer with review (#486) Co-authored-by: bokuweb --- docx-core/src/documents/mod.rs | 124 +++++++++++++----- docx-core/src/reader/run.rs | 4 + docx-core/src/reader/xml_element.rs | 2 + .../test/__snapshots__/index.test.js.snap | 108 +++++++++++++++ docx-wasm/test/index.test.js | 42 ++++++ 5 files changed, 244 insertions(+), 36 deletions(-) diff --git a/docx-core/src/documents/mod.rs b/docx-core/src/documents/mod.rs index 65f8e39..5b147c7 100644 --- a/docx-core/src/documents/mod.rs +++ b/docx-core/src/documents/mod.rs @@ -849,23 +849,7 @@ impl Docx { for child in &mut self.document.children { match child { DocumentChild::Paragraph(paragraph) => { - for child in &mut paragraph.children { - if let ParagraphChild::Run(run) = child { - for child in &mut run.children { - if let RunChild::Drawing(d) = child { - if let Some(DrawingData::Pic(pic)) = &mut d.data { - images.push(( - pic.id.clone(), - // For now only png supported - format!("media/{}.png", pic.id), - )); - let b = std::mem::take(&mut pic.image); - image_bufs.push((pic.id.clone(), b)); - } - } - } - } - } + collect_images_from_paragraph(paragraph, &mut images, &mut image_bufs); } DocumentChild::Table(table) => { for TableChild::TableRow(row) in &mut table.rows { @@ -873,25 +857,11 @@ impl Docx { for content in &mut cell.children { match content { TableCellContent::Paragraph(paragraph) => { - for child in &mut paragraph.children { - if let ParagraphChild::Run(run) = child { - for child in &mut run.children { - if let RunChild::Drawing(d) = child { - if let Some(DrawingData::Pic(pic)) = - &mut d.data - { - images.push(( - pic.id.clone(), - // For now only png supported - format!("media/{}.png", pic.id), - )); - let b = std::mem::take(&mut pic.image); - image_bufs.push((pic.id.clone(), b)); - } - } - } - } - } + collect_images_from_paragraph( + paragraph, + &mut images, + &mut image_bufs, + ); } TableCellContent::Table(_) => { // TODO: support comment @@ -908,6 +878,88 @@ impl Docx { } } +fn collect_images_from_paragraph( + paragraph: &mut Paragraph, + images: &mut Vec<(String, String)>, + image_bufs: &mut Vec<(String, Vec)>, +) { + for child in &mut paragraph.children { + if let ParagraphChild::Run(run) = child { + for child in &mut run.children { + if let RunChild::Drawing(d) = child { + if let Some(DrawingData::Pic(pic)) = &mut d.data { + images.push(( + pic.id.clone(), + // For now only png supported + format!("media/{}.png", pic.id), + )); + let b = std::mem::take(&mut pic.image); + image_bufs.push((pic.id.clone(), b)); + } + } + } + } else if let ParagraphChild::Insert(ins) = child { + for child in &mut ins.children { + match child { + InsertChild::Run(run) => { + for child in &mut run.children { + if let RunChild::Drawing(d) = child { + if let Some(DrawingData::Pic(pic)) = &mut d.data { + images.push(( + pic.id.clone(), + // For now only png supported + format!("media/{}.png", pic.id), + )); + let b = std::mem::take(&mut pic.image); + image_bufs.push((pic.id.clone(), b)); + } + } + } + } + InsertChild::Delete(del) => { + for d in &mut del.children { + if let DeleteChild::Run(run) = d { + for child in &mut run.children { + if let RunChild::Drawing(d) = child { + if let Some(DrawingData::Pic(pic)) = &mut d.data { + images.push(( + pic.id.clone(), + // For now only png supported + format!("media/{}.png", pic.id), + )); + let b = std::mem::take(&mut pic.image); + image_bufs.push((pic.id.clone(), b)); + } + } + } + } + } + } + _ => {} + } + } + } else if let ParagraphChild::Delete(del) = child { + for d in &mut del.children { + if let DeleteChild::Run(run) = d { + for child in &mut run.children { + if let RunChild::Drawing(d) = child { + if let Some(DrawingData::Pic(pic)) = &mut d.data { + images.push(( + pic.id.clone(), + // For now only png supported + format!("media/{}.png", pic.id), + )); + let b = std::mem::take(&mut pic.image); + image_bufs.push((pic.id.clone(), b)); + } + } + } + } + } + } + } +} + fn update_document_by_toc( document_children: Vec, styles: &Styles, diff --git a/docx-core/src/reader/run.rs b/docx-core/src/reader/run.rs index 9362994..4757a3f 100644 --- a/docx-core/src/reader/run.rs +++ b/docx-core/src/reader/run.rs @@ -87,6 +87,10 @@ impl ElementReader for Run { if let Ok(drawing) = Drawing::read(r, &attributes) { run = run.add_drawing(drawing); } + } + // For now, we treat pict ad drawing + XMLElement::Pict => { + } XMLElement::FieldChar => { if let Ok(f) = read_field_char(&attributes) { diff --git a/docx-core/src/reader/xml_element.rs b/docx-core/src/reader/xml_element.rs index 3846926..c9e14b5 100644 --- a/docx-core/src/reader/xml_element.rs +++ b/docx-core/src/reader/xml_element.rs @@ -210,6 +210,7 @@ pub enum VXMLElement { Stroke, Fill, TextBox, + Shape, Unsupported, } @@ -450,6 +451,7 @@ impl FromStr for VXMLElement { "stroke" => Ok(VXMLElement::Stroke), "fill" => Ok(VXMLElement::Fill), "textbox" => Ok(VXMLElement::TextBox), + "shape" => Ok(VXMLElement::Shape), _ => Ok(VXMLElement::Unsupported), } } diff --git a/docx-wasm/test/__snapshots__/index.test.js.snap b/docx-wasm/test/__snapshots__/index.test.js.snap index 476b5ec..7e22265 100644 --- a/docx-wasm/test/__snapshots__/index.test.js.snap +++ b/docx-wasm/test/__snapshots__/index.test.js.snap @@ -69487,6 +69487,114 @@ exports[`writer should write inline jpeg image 2`] = ` " `; +exports[`writer should write jpeg image with del 1`] = ` +" + + + + + + +" +`; + +exports[`writer should write jpeg image with del 2`] = ` +" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" +`; + +exports[`writer should write jpeg image with ins 1`] = ` +" + + + + + + +" +`; + +exports[`writer should write jpeg image with ins 2`] = ` +" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" +`; + exports[`writer should write line spacing 1`] = ` " diff --git a/docx-wasm/test/index.test.js b/docx-wasm/test/index.test.js index 829ae41..af620a7 100644 --- a/docx-wasm/test/index.test.js +++ b/docx-wasm/test/index.test.js @@ -744,4 +744,46 @@ describe("writer", () => { } } }); + + test("should write jpeg image with ins", () => { + const buf = Buffer.from(require("./cat"), "base64"); + const image = new w.Image(buf).size(320 * 9525, 240 * 9525); + const p = new w.Paragraph().addInsert( + new w.Insert(new w.Run().addImage(image)) + .author("bokuweb") + .date("2021-12-23T18:16:00Z") + ); + + const buffer = new w.Docx().addParagraph(p).build(); + + writeFileSync("../output/js/image_with_ins.docx", buffer); + + const z = new Zip(Buffer.from(buffer)); + for (const e of z.getEntries()) { + if (e.entryName.match(/document.xml/)) { + expect(z.readAsText(e)).toMatchSnapshot(); + } + } + }); + + test("should write jpeg image with del", () => { + const buf = Buffer.from(require("./cat"), "base64"); + const image = new w.Image(buf).size(320 * 9525, 240 * 9525); + const p = new w.Paragraph().addDelete( + new w.Delete(new w.Run().addImage(image)) + .author("bokuweb") + .date("2021-12-23T18:16:00Z") + ); + + const buffer = new w.Docx().addParagraph(p).build(); + + writeFileSync("../output/js/image_with_del.docx", buffer); + + const z = new Zip(Buffer.from(buffer)); + for (const e of z.getEntries()) { + if (e.entryName.match(/document.xml/)) { + expect(z.readAsText(e)).toMatchSnapshot(); + } + } + }); });