From 886113515b917019e5112639daf2ac4bc09438df Mon Sep 17 00:00:00 2001 From: bokuweb Date: Wed, 16 Mar 2022 12:24:12 +0900 Subject: [PATCH] feat: Support run style (#447) * feat: Support run style * update snaps --- docx-core/src/documents/elements/mod.rs | 2 + docx-core/src/documents/elements/run.rs | 5 + .../src/documents/elements/run_property.rs | 33 +- docx-core/src/documents/elements/run_style.rs | 57 + docx-core/src/reader/run_property.rs | 5 + docx-core/src/reader/xml_element.rs | 2 + docx-core/src/xml_builder/elements.rs | 2 + .../test/__snapshots__/index.test.js.snap | 1454 ++++++++++++++++- docx-wasm/test/index.test.js | 6 + fixtures/font/font.docx | Bin 0 -> 12922 bytes 10 files changed, 1530 insertions(+), 36 deletions(-) create mode 100644 docx-core/src/documents/elements/run_style.rs create mode 100644 fixtures/font/font.docx diff --git a/docx-core/src/documents/elements/mod.rs b/docx-core/src/documents/elements/mod.rs index 071ffa8..0462cf5 100644 --- a/docx-core/src/documents/elements/mod.rs +++ b/docx-core/src/documents/elements/mod.rs @@ -9,6 +9,7 @@ mod bookmark_start; mod br; mod character_spacing; mod color; +mod run_style; mod comment; mod comment_extended; mod comment_range_end; @@ -136,6 +137,7 @@ pub use doc_var::*; pub use drawing::*; pub use fld_char::*; pub use font::*; +pub use run_style::*; pub use font_scheme::*; pub use footer_reference::*; pub use grid_span::*; diff --git a/docx-core/src/documents/elements/run.rs b/docx-core/src/documents/elements/run.rs index 1c91ac8..6af7b1d 100644 --- a/docx-core/src/documents/elements/run.rs +++ b/docx-core/src/documents/elements/run.rs @@ -165,6 +165,11 @@ impl Run { self } + pub fn style(mut self, style_id: &str) -> Self { + self.run_property = self.run_property.style(style_id); + self + } + pub fn size(mut self, size: usize) -> Run { self.run_property = self.run_property.size(size); self diff --git a/docx-core/src/documents/elements/run_property.rs b/docx-core/src/documents/elements/run_property.rs index b9a9ab5..2b75902 100644 --- a/docx-core/src/documents/elements/run_property.rs +++ b/docx-core/src/documents/elements/run_property.rs @@ -5,9 +5,11 @@ use crate::documents::BuildXML; use crate::types::*; use crate::xml_builder::*; -#[derive(Debug, Clone, Serialize, PartialEq)] +#[derive(Debug, Clone, Serialize, PartialEq, Default)] #[serde(rename_all = "camelCase")] pub struct RunProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub style: Option, #[serde(skip_serializing_if = "Option::is_none")] pub sz: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -49,6 +51,11 @@ impl RunProperty { Default::default() } + pub fn style(mut self, style_id: &str) -> Self { + self.style = Some(RunStyle::new(style_id)); + self + } + pub fn size(mut self, size: usize) -> RunProperty { self.sz = Some(Sz::new(size)); self.sz_cs = Some(SzCs::new(size)); @@ -135,30 +142,6 @@ impl RunProperty { } } -impl Default for RunProperty { - fn default() -> Self { - Self { - color: None, - sz: None, - sz_cs: None, - highlight: None, - vert_align: None, - underline: None, - bold: None, - bold_cs: None, - italic: None, - italic_cs: None, - vanish: None, - fonts: None, - character_spacing: None, - text_border: None, - del: None, - ins: None, - strike: None, - } - } -} - impl BuildXML for RunProperty { fn build(&self) -> Vec { let b = XMLBuilder::new(); diff --git a/docx-core/src/documents/elements/run_style.rs b/docx-core/src/documents/elements/run_style.rs new file mode 100644 index 0000000..0f69c05 --- /dev/null +++ b/docx-core/src/documents/elements/run_style.rs @@ -0,0 +1,57 @@ +use serde::{Serialize, Serializer}; + +use crate::documents::BuildXML; +use crate::xml_builder::*; + +#[derive(Debug, Clone, PartialEq)] +pub struct RunStyle { + pub val: String, +} + +impl Default for RunStyle { + fn default() -> Self { + RunStyle { + val: "Normal".to_owned(), + } + } +} + +impl RunStyle { + pub fn new(val: impl Into) -> RunStyle { + RunStyle { val: val.into() } + } +} + +impl BuildXML for RunStyle { + fn build(&self) -> Vec { + XMLBuilder::new().run_style(&self.val).build() + } +} + +impl Serialize for RunStyle { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.val) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[cfg(test)] + use pretty_assertions::assert_eq; + use std::str; + + #[test] + fn test_r_style() { + let c = RunStyle::new("Heading"); + let b = c.build(); + assert_eq!( + str::from_utf8(&b).unwrap(), + r#""# + ); + } +} diff --git a/docx-core/src/reader/run_property.rs b/docx-core/src/reader/run_property.rs index 1f6eb64..df8af7b 100644 --- a/docx-core/src/reader/run_property.rs +++ b/docx-core/src/reader/run_property.rs @@ -60,6 +60,11 @@ impl ElementReader for RunProperty { }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { + XMLElement::RunStyle => { + if let Some(v) = read_val(&attributes) { + rp = rp.style(&v); + } + } XMLElement::Bold => { if !read_bool(&attributes) { rp = rp.disable_bold(); diff --git a/docx-core/src/reader/xml_element.rs b/docx-core/src/reader/xml_element.rs index c7292dd..8b436a1 100644 --- a/docx-core/src/reader/xml_element.rs +++ b/docx-core/src/reader/xml_element.rs @@ -29,6 +29,7 @@ pub enum XMLElement { Highlight, VertAlign, Bold, + RunStyle, BoldCs, Break, Tab, @@ -235,6 +236,7 @@ impl FromStr for XMLElement { "pStyle" => Ok(XMLElement::ParagraphStyle), "pPrChange" => Ok(XMLElement::ParagraphPropertyChange), "highlight" => Ok(XMLElement::Highlight), + "rStyle" => Ok(XMLElement::RunStyle), "b" => Ok(XMLElement::Bold), "bCs" => Ok(XMLElement::BoldCs), "i" => Ok(XMLElement::Italic), diff --git a/docx-core/src/xml_builder/elements.rs b/docx-core/src/xml_builder/elements.rs index c9e7d58..cfa87ec 100644 --- a/docx-core/src/xml_builder/elements.rs +++ b/docx-core/src/xml_builder/elements.rs @@ -149,6 +149,8 @@ impl XMLBuilder { closed_with_str!(vert_align, "w:vertAlign"); // i.e. closed_with_str!(paragraph_style, "w:pStyle"); + // i.e. + closed_with_str!(run_style, "w:rStyle"); // i.e. closed_with_usize!(sz, "w:sz"); // i.e. diff --git a/docx-wasm/test/__snapshots__/index.test.js.snap b/docx-wasm/test/__snapshots__/index.test.js.snap index b2af19c..edbe463 100644 --- a/docx-wasm/test/__snapshots__/index.test.js.snap +++ b/docx-wasm/test/__snapshots__/index.test.js.snap @@ -5956,6 +5956,1411 @@ Object { } `; +exports[`reader should read font docx 1`] = ` +Object { + "comments": Object { + "comments": Array [], + }, + "commentsExtended": Object { + "children": Array [], + }, + "contentType": Object { + "custom_xml_count": 1, + "footer_count": 0, + "header_count": 0, + "types": Object { + "/_rels/.rels": "application/vnd.openxmlformats-package.relationships+xml", + "/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml", + "/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml", + "/docProps/custom.xml": "application/vnd.openxmlformats-officedocument.custom-properties+xml", + "/word/_rels/document.xml.rels": "application/vnd.openxmlformats-package.relationships+xml", + "/word/comments.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", + "/word/commentsExtended.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", + "/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", + "/word/fontTable.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", + "/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", + "/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", + "/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", + }, + "web_extension_count": 1, + }, + "customItemProps": Array [], + "customItemRels": Array [], + "customItems": Array [], + "docProps": Object { + "app": Object {}, + "core": Object { + "config": Object { + "created": null, + "creator": null, + "description": null, + "language": null, + "lastModifiedBy": null, + "modified": null, + "revision": null, + "subject": null, + "title": null, + }, + }, + "custom": Object { + "properties": Object {}, + }, + }, + "document": Object { + "children": Array [ + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "preserveSpace": true, + "text": "こんにちは", + }, + "type": "text", + }, + ], + "runProperty": Object { + "fonts": Object { + "ascii": "筑紫B丸ゴシック レギュラー", + "eastAsia": "筑紫B丸ゴシック レギュラー", + "hiAnsi": "筑紫B丸ゴシック レギュラー", + "hint": "eastAsia", + }, + }, + }, + "type": "run", + }, + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "preserveSpace": true, + "text": " ", + }, + "type": "text", + }, + ], + "runProperty": Object { + "fonts": Object { + "hint": "eastAsia", + }, + }, + }, + "type": "run", + }, + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "preserveSpace": true, + "text": "世界", + }, + "type": "text", + }, + ], + "runProperty": Object { + "fonts": Object { + "ascii": "ヒラギノ丸ゴ ProN W4", + "eastAsia": "ヒラギノ丸ゴ ProN W4", + "hiAnsi": "ヒラギノ丸ゴ ProN W4", + "hint": "eastAsia", + }, + }, + }, + "type": "run", + }, + ], + "hasNumbering": false, + "id": "18937B0B", + "property": Object { + "runProperty": Object { + "fonts": Object { + "ascii": "ヒラギノ丸ゴ ProN W4", + "eastAsia": "ヒラギノ丸ゴ ProN W4", + "hiAnsi": "ヒラギノ丸ゴ ProN W4", + }, + }, + "tabs": Array [], + }, + }, + "type": "paragraph", + }, + Object { + "data": Object { + "children": Array [], + "hasNumbering": false, + "id": "4866A1EA", + "property": Object { + "runProperty": Object { + "fonts": Object { + "ascii": "ヒラギノ丸ゴ ProN W4", + "eastAsia": "ヒラギノ丸ゴ ProN W4", + "hiAnsi": "ヒラギノ丸ゴ ProN W4", + }, + }, + "tabs": Array [], + }, + }, + "type": "paragraph", + }, + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "children": Array [ + Object { + "data": Object { + "preserveSpace": true, + "text": "こんにちは世界", + }, + "type": "text", + }, + ], + "runProperty": Object { + "fonts": Object { + "hint": "eastAsia", + }, + "style": "test", + }, + }, + "type": "run", + }, + ], + "hasNumbering": false, + "id": "558ED852", + "property": Object { + "runProperty": Object { + "style": "test", + }, + "style": "a4", + "tabs": Array [], + }, + }, + "type": "paragraph", + }, + ], + "hasNumbering": false, + "sectionProperty": Object { + "columns": 425, + "docGrid": Object { + "charSpace": null, + "gridType": "lines", + "linePitch": 360, + }, + "pageMargin": Object { + "bottom": 1701, + "footer": 992, + "gutter": 0, + "header": 851, + "left": 1701, + "right": 1701, + "top": 1985, + }, + "pageSize": Object { + "h": 16840, + "orient": null, + "w": 11900, + }, + "titlePg": false, + }, + }, + "documentRels": Object { + "customXmlCount": 0, + "footerCount": 0, + "hasComments": false, + "hasNumberings": false, + "headerCount": 0, + "imageIds": Array [], + }, + "fontTable": Object {}, + "media": Array [], + "numberings": Object { + "abstractNums": Array [], + "numberings": Array [], + }, + "rels": Object { + "rels": Array [ + Array [ + "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", + "rId1", + "docProps/core.xml", + ], + Array [ + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", + "rId2", + "docProps/app.xml", + ], + Array [ + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + "rId3", + "word/document.xml", + ], + Array [ + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties", + "rId4", + "docProps/custom.xml", + ], + ], + }, + "settings": Object { + "defaultTabStop": 840, + "docId": "4A9883C0-7AEC-574E-926D-DA6DB000DD90", + "docVars": Array [], + "evenAndOddHeaders": false, + "zoom": 100, + }, + "styles": Object { + "docDefaults": Object { + "runPropertyDefault": Object { + "runProperty": Object { + "fonts": Object { + "asciiTheme": "minorHAnsi", + "csTheme": "minorBidi", + "eastAsiaTheme": "minorEastAsia", + "hiAnsiTheme": "minorHAnsi", + }, + "sz": 21, + "szCs": 21, + }, + }, + }, + "styles": Array [ + Object { + "basedOn": null, + "name": "Normal", + "paragraphProperty": Object { + "alignment": "both", + "runProperty": Object {}, + "tabs": Array [], + "widowControl": true, + }, + "runProperty": Object {}, + "styleId": "a", + "styleType": "paragraph", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": null, + "name": "Default Paragraph Font", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object {}, + "styleId": "a0", + "styleType": "character", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": null, + "name": "Normal Table", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object {}, + "styleId": "a1", + "styleType": "table", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": null, + "insideH": null, + "insideV": null, + "left": null, + "right": null, + "top": null, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": null, + "name": "No List", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object {}, + "styleId": "a2", + "styleType": "numbering", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": "a0", + "name": "Subtle Emphasis", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object { + "color": "404040", + "italic": true, + "italicCs": true, + }, + "styleId": "a3", + "styleType": "character", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": "a", + "name": "Subtitle", + "paragraphProperty": Object { + "alignment": "center", + "outlineLvl": 1, + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object { + "sz": 24, + "szCs": 24, + }, + "styleId": "a4", + "styleType": "paragraph", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": "a0", + "name": "副題 (文字)", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object { + "sz": 24, + "szCs": 24, + }, + "styleId": "a5", + "styleType": "character", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + Object { + "basedOn": "a3", + "name": "test", + "paragraphProperty": Object { + "runProperty": Object {}, + "tabs": Array [], + }, + "runProperty": Object { + "color": "404040", + "fonts": Object { + "eastAsia": "MS Pゴシック", + }, + "italic": true, + "italicCs": true, + }, + "styleId": "test", + "styleType": "character", + "tableCellProperty": Object { + "borders": null, + "gridSpan": null, + "shading": null, + "textDirection": null, + "verticalAlign": null, + "verticalMerge": null, + "width": null, + }, + "tableProperty": Object { + "borders": Object { + "bottom": Object { + "borderType": "single", + "color": "000000", + "position": "bottom", + "size": 2, + "space": 0, + }, + "insideH": Object { + "borderType": "single", + "color": "000000", + "position": "insideH", + "size": 2, + "space": 0, + }, + "insideV": Object { + "borderType": "single", + "color": "000000", + "position": "insideV", + "size": 2, + "space": 0, + }, + "left": Object { + "borderType": "single", + "color": "000000", + "position": "left", + "size": 2, + "space": 0, + }, + "right": Object { + "borderType": "single", + "color": "000000", + "position": "right", + "size": 2, + "space": 0, + }, + "top": Object { + "borderType": "single", + "color": "000000", + "position": "top", + "size": 2, + "space": 0, + }, + }, + "indent": null, + "justification": "left", + "layout": null, + "margins": Object { + "bottom": Object { + "val": 0, + "widthType": "DXA", + }, + "left": Object { + "val": 55, + "widthType": "DXA", + }, + "right": Object { + "val": 55, + "widthType": "DXA", + }, + "top": Object { + "val": 0, + "widthType": "DXA", + }, + }, + "style": null, + "width": Object { + "width": 0, + "widthType": "Auto", + }, + }, + }, + ], + }, + "taskpanes": null, + "taskpanesRels": Object { + "rels": Array [], + }, + "themes": Array [ + Object { + "fontSchema": Object { + "majorFont": Object { + "cs": "", + "ea": "", + "fonts": Array [ + Object { + "script": "Jpan", + "typeface": "游ゴシック Light", + }, + Object { + "script": "Hang", + "typeface": "맑은 고딕", + }, + Object { + "script": "Hans", + "typeface": "等线 Light", + }, + Object { + "script": "Hant", + "typeface": "新細明體", + }, + Object { + "script": "Arab", + "typeface": "Times New Roman", + }, + Object { + "script": "Hebr", + "typeface": "Times New Roman", + }, + Object { + "script": "Thai", + "typeface": "Angsana New", + }, + Object { + "script": "Ethi", + "typeface": "Nyala", + }, + Object { + "script": "Beng", + "typeface": "Vrinda", + }, + Object { + "script": "Gujr", + "typeface": "Shruti", + }, + Object { + "script": "Khmr", + "typeface": "MoolBoran", + }, + Object { + "script": "Knda", + "typeface": "Tunga", + }, + Object { + "script": "Guru", + "typeface": "Raavi", + }, + Object { + "script": "Cans", + "typeface": "Euphemia", + }, + Object { + "script": "Cher", + "typeface": "Plantagenet Cherokee", + }, + Object { + "script": "Yiii", + "typeface": "Microsoft Yi Baiti", + }, + Object { + "script": "Tibt", + "typeface": "Microsoft Himalaya", + }, + Object { + "script": "Thaa", + "typeface": "MV Boli", + }, + Object { + "script": "Deva", + "typeface": "Mangal", + }, + Object { + "script": "Telu", + "typeface": "Gautami", + }, + Object { + "script": "Taml", + "typeface": "Latha", + }, + Object { + "script": "Syrc", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Orya", + "typeface": "Kalinga", + }, + Object { + "script": "Mlym", + "typeface": "Kartika", + }, + Object { + "script": "Laoo", + "typeface": "DokChampa", + }, + Object { + "script": "Sinh", + "typeface": "Iskoola Pota", + }, + Object { + "script": "Mong", + "typeface": "Mongolian Baiti", + }, + Object { + "script": "Viet", + "typeface": "Times New Roman", + }, + Object { + "script": "Uigh", + "typeface": "Microsoft Uighur", + }, + Object { + "script": "Geor", + "typeface": "Sylfaen", + }, + Object { + "script": "Armn", + "typeface": "Arial", + }, + Object { + "script": "Bugi", + "typeface": "Leelawadee UI", + }, + Object { + "script": "Bopo", + "typeface": "Microsoft JhengHei", + }, + Object { + "script": "Java", + "typeface": "Javanese Text", + }, + Object { + "script": "Lisu", + "typeface": "Segoe UI", + }, + Object { + "script": "Mymr", + "typeface": "Myanmar Text", + }, + Object { + "script": "Nkoo", + "typeface": "Ebrima", + }, + Object { + "script": "Olck", + "typeface": "Nirmala UI", + }, + Object { + "script": "Osma", + "typeface": "Ebrima", + }, + Object { + "script": "Phag", + "typeface": "Phagspa", + }, + Object { + "script": "Syrn", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Syrj", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Syre", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Sora", + "typeface": "Nirmala UI", + }, + Object { + "script": "Tale", + "typeface": "Microsoft Tai Le", + }, + Object { + "script": "Talu", + "typeface": "Microsoft New Tai Lue", + }, + Object { + "script": "Tfng", + "typeface": "Ebrima", + }, + ], + "latin": "游ゴシック Light", + }, + "minorFont": Object { + "cs": "", + "ea": "", + "fonts": Array [ + Object { + "script": "Jpan", + "typeface": "游明朝", + }, + Object { + "script": "Hang", + "typeface": "맑은 고딕", + }, + Object { + "script": "Hans", + "typeface": "等线", + }, + Object { + "script": "Hant", + "typeface": "新細明體", + }, + Object { + "script": "Arab", + "typeface": "Arial", + }, + Object { + "script": "Hebr", + "typeface": "Arial", + }, + Object { + "script": "Thai", + "typeface": "Cordia New", + }, + Object { + "script": "Ethi", + "typeface": "Nyala", + }, + Object { + "script": "Beng", + "typeface": "Vrinda", + }, + Object { + "script": "Gujr", + "typeface": "Shruti", + }, + Object { + "script": "Khmr", + "typeface": "DaunPenh", + }, + Object { + "script": "Knda", + "typeface": "Tunga", + }, + Object { + "script": "Guru", + "typeface": "Raavi", + }, + Object { + "script": "Cans", + "typeface": "Euphemia", + }, + Object { + "script": "Cher", + "typeface": "Plantagenet Cherokee", + }, + Object { + "script": "Yiii", + "typeface": "Microsoft Yi Baiti", + }, + Object { + "script": "Tibt", + "typeface": "Microsoft Himalaya", + }, + Object { + "script": "Thaa", + "typeface": "MV Boli", + }, + Object { + "script": "Deva", + "typeface": "Mangal", + }, + Object { + "script": "Telu", + "typeface": "Gautami", + }, + Object { + "script": "Taml", + "typeface": "Latha", + }, + Object { + "script": "Syrc", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Orya", + "typeface": "Kalinga", + }, + Object { + "script": "Mlym", + "typeface": "Kartika", + }, + Object { + "script": "Laoo", + "typeface": "DokChampa", + }, + Object { + "script": "Sinh", + "typeface": "Iskoola Pota", + }, + Object { + "script": "Mong", + "typeface": "Mongolian Baiti", + }, + Object { + "script": "Viet", + "typeface": "Arial", + }, + Object { + "script": "Uigh", + "typeface": "Microsoft Uighur", + }, + Object { + "script": "Geor", + "typeface": "Sylfaen", + }, + Object { + "script": "Armn", + "typeface": "Arial", + }, + Object { + "script": "Bugi", + "typeface": "Leelawadee UI", + }, + Object { + "script": "Bopo", + "typeface": "Microsoft JhengHei", + }, + Object { + "script": "Java", + "typeface": "Javanese Text", + }, + Object { + "script": "Lisu", + "typeface": "Segoe UI", + }, + Object { + "script": "Mymr", + "typeface": "Myanmar Text", + }, + Object { + "script": "Nkoo", + "typeface": "Ebrima", + }, + Object { + "script": "Olck", + "typeface": "Nirmala UI", + }, + Object { + "script": "Osma", + "typeface": "Ebrima", + }, + Object { + "script": "Phag", + "typeface": "Phagspa", + }, + Object { + "script": "Syrn", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Syrj", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Syre", + "typeface": "Estrangelo Edessa", + }, + Object { + "script": "Sora", + "typeface": "Nirmala UI", + }, + Object { + "script": "Tale", + "typeface": "Microsoft Tai Le", + }, + Object { + "script": "Talu", + "typeface": "Microsoft New Tai Lue", + }, + Object { + "script": "Tfng", + "typeface": "Ebrima", + }, + ], + "latin": "游明朝", + }, + }, + }, + ], + "webExtensions": Array [], + "webSettings": Object { + "divs": Array [], + }, +} +`; + exports[`reader should read footer docx 1`] = ` Object { "comments": Object { @@ -12558,7 +13963,9 @@ Object { Object { "data": Object { "children": Array [], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -13103,7 +14510,9 @@ Object { Object { "data": Object { "children": Array [], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -13339,7 +14748,9 @@ Object { Object { "data": Object { "children": Array [], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -23468,6 +24879,7 @@ Object { "ascii": "Arial", "hiAnsi": "Arial", }, + "style": "a9", "sz": 20, "szCs": 20, }, @@ -23491,6 +24903,7 @@ Object { "ascii": "Arial", "hiAnsi": "Arial", }, + "style": "a9", "sz": 20, "szCs": 20, }, @@ -23514,6 +24927,7 @@ Object { "ascii": "Arial", "hiAnsi": "Arial", }, + "style": "a9", "sz": 20, "szCs": 20, }, @@ -23537,6 +24951,7 @@ Object { "ascii": "Arial", "hiAnsi": "Arial", }, + "style": "a9", "sz": 20, "szCs": 20, }, @@ -23560,6 +24975,7 @@ Object { "ascii": "Arial", "hiAnsi": "Arial", }, + "style": "a9", "sz": 20, "szCs": 20, }, @@ -43653,7 +45069,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -43689,7 +45107,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -43825,7 +45245,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -43859,7 +45281,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -43993,7 +45417,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -44029,7 +45455,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -44165,7 +45593,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, @@ -44199,7 +45629,9 @@ Object { "type": "text", }, ], - "runProperty": Object {}, + "runProperty": Object { + "style": "a5", + }, }, "type": "run", }, diff --git a/docx-wasm/test/index.test.js b/docx-wasm/test/index.test.js index 94b3b91..1147d8d 100644 --- a/docx-wasm/test/index.test.js +++ b/docx-wasm/test/index.test.js @@ -118,6 +118,12 @@ describe("reader", () => { const json = w.readDocx(buffer); expect(json).toMatchSnapshot(); }); + + test("should read font docx", () => { + const buffer = readFileSync("../fixtures/font/font.docx"); + const json = w.readDocx(buffer); + expect(json).toMatchSnapshot(); + }); }); describe("writer", () => { diff --git a/fixtures/font/font.docx b/fixtures/font/font.docx new file mode 100644 index 0000000000000000000000000000000000000000..a8d6ad29555a7b19281f849706e457d25d08945d GIT binary patch literal 12922 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 v#DDbvKg7