From 72c32378c5356743927e7b02684df1e20d2b1d34 Mon Sep 17 00:00:00 2001 From: Mark Charyk Date: Thu, 20 Jun 2019 15:59:43 -0700 Subject: [PATCH 1/7] Make prettified XML a Packer-wide configurable option The xml() function was being passed a flag for pretty printing the XML in word/document.xml. This was causing some parsers (not Word itself) to break when they didn't expect whitepsace. It was also causing some files to be prettified and others to be ugly. This ensures consistent prettification. --- src/export/packer/next-compiler.ts | 36 ++++++++++++++++-------------- src/export/packer/packer.ts | 4 ++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index 345d4db450..a2a09c3a8b 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -30,10 +30,12 @@ interface IXmlifyedFileMapping { export class Compiler { private readonly formatter: Formatter; private readonly imageReplacer: ImageReplacer; + private readonly prettifyXml?: boolean; - constructor() { + constructor(prettifyXml?: boolean) { this.formatter = new Formatter(); this.imageReplacer = new ImageReplacer(); + this.prettifyXml = prettifyXml; } public compile(file: File): JSZip { @@ -71,7 +73,7 @@ export class Compiler { return { Relationships: { data: (() => { - const xmlData = xml(this.formatter.format(file.Document)); + const xmlData = xml(this.formatter.format(file.Document), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -82,13 +84,13 @@ export class Compiler { ); }); - return xml(this.formatter.format(file.DocumentRelationships)); + return xml(this.formatter.format(file.DocumentRelationships), this.prettifyXml); })(), path: "word/_rels/document.xml.rels", }, Document: { data: (() => { - const tempXmlData = xml(this.formatter.format(file.Document), true); + const tempXmlData = xml(this.formatter.format(file.Document), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, documentRelationshipCount); @@ -97,7 +99,7 @@ export class Compiler { path: "word/document.xml", }, Styles: { - data: xml(this.formatter.format(file.Styles)), + data: xml(this.formatter.format(file.Styles), this.prettifyXml), path: "word/styles.xml", }, Properties: { @@ -110,15 +112,15 @@ export class Compiler { path: "docProps/core.xml", }, Numbering: { - data: xml(this.formatter.format(file.Numbering)), + data: xml(this.formatter.format(file.Numbering), this.prettifyXml), path: "word/numbering.xml", }, FileRelationships: { - data: xml(this.formatter.format(file.FileRelationships)), + data: xml(this.formatter.format(file.FileRelationships), this.prettifyXml), path: "_rels/.rels", }, HeaderRelationships: file.Headers.map((headerWrapper, index) => { - const xmlData = xml(this.formatter.format(headerWrapper.Header)); + const xmlData = xml(this.formatter.format(headerWrapper.Header), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -130,12 +132,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(headerWrapper.Relationships)), + data: xml(this.formatter.format(headerWrapper.Relationships), this.prettifyXml), path: `word/_rels/header${index + 1}.xml.rels`, }; }), FooterRelationships: file.Footers.map((footerWrapper, index) => { - const xmlData = xml(this.formatter.format(footerWrapper.Footer)); + const xmlData = xml(this.formatter.format(footerWrapper.Footer), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -147,12 +149,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(footerWrapper.Relationships)), + data: xml(this.formatter.format(footerWrapper.Relationships), this.prettifyXml), path: `word/_rels/footer${index + 1}.xml.rels`, }; }), Headers: file.Headers.map((headerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(headerWrapper.Header)); + const tempXmlData = xml(this.formatter.format(headerWrapper.Header), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -163,7 +165,7 @@ export class Compiler { }; }), Footers: file.Footers.map((footerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(footerWrapper.Footer)); + const tempXmlData = xml(this.formatter.format(footerWrapper.Footer), this.prettifyXml); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -174,19 +176,19 @@ export class Compiler { }; }), ContentTypes: { - data: xml(this.formatter.format(file.ContentTypes)), + data: xml(this.formatter.format(file.ContentTypes), this.prettifyXml), path: "[Content_Types].xml", }, AppProperties: { - data: xml(this.formatter.format(file.AppProperties)), + data: xml(this.formatter.format(file.AppProperties), this.prettifyXml), path: "docProps/app.xml", }, FootNotes: { - data: xml(this.formatter.format(file.FootNotes)), + data: xml(this.formatter.format(file.FootNotes), this.prettifyXml), path: "word/footnotes.xml", }, Settings: { - data: xml(this.formatter.format(file.Settings)), + data: xml(this.formatter.format(file.Settings), this.prettifyXml), path: "word/settings.xml", }, }; diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index 5f4c12c66f..a6c0f33cc4 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -4,8 +4,8 @@ import { Compiler } from "./next-compiler"; export class Packer { private readonly compiler: Compiler; - constructor() { - this.compiler = new Compiler(); + constructor(prettifyXml?: boolean) { + this.compiler = new Compiler(prettifyXml); } public async toBuffer(file: File): Promise { From 564a05531637da12ccec1f5952f5479bba45276f Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 26 Jun 2019 02:11:43 +0100 Subject: [PATCH 2/7] Remove jsonify method --- src/file/paragraph/run/underline.spec.ts | 179 ++++++++++++++---- src/file/xml-components/xml-component.spec.ts | 8 +- 2 files changed, 142 insertions(+), 45 deletions(-) diff --git a/src/file/paragraph/run/underline.spec.ts b/src/file/paragraph/run/underline.spec.ts index 346b4f7a93..b593b816dd 100644 --- a/src/file/paragraph/run/underline.spec.ts +++ b/src/file/paragraph/run/underline.spec.ts @@ -1,7 +1,6 @@ -import { assert, expect } from "chai"; +import { expect } from "chai"; import { Formatter } from "export/formatter"; -import { Utility } from "tests/utility"; import * as u from "./underline"; @@ -9,8 +8,14 @@ describe("Underline", () => { describe("#constructor()", () => { it("should create a new Underline object with u:u as the rootKey", () => { const underline = new u.Underline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.rootKey, "w:u"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "single", + }, + }, + }); }); it("should default to 'single' and no color", () => { @@ -33,16 +38,16 @@ describe("Underline", () => { describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { - it("should have u:u as the rootKey", () => { - const underline = new u.DashDotDotHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.rootKey, "w:u"); - }); - it("should put value in attribute", () => { const underline = new u.DashDotDotHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dashDotDotHeavy"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dashDotDotHeavy", + }, + }, + }); }); }); }); @@ -51,8 +56,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DashDotHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dashDotHeavy"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dashDotHeavy", + }, + }, + }); }); }); }); @@ -61,8 +72,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DashLongHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dashLongHeavy"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dashLongHeavy", + }, + }, + }); }); }); }); @@ -71,8 +88,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DashLongUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dashLong"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dashLong", + }, + }, + }); }); }); }); @@ -81,8 +104,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DashUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dash"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dash", + }, + }, + }); }); }); }); @@ -91,8 +120,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DotDashUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dotDash"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dotDash", + }, + }, + }); }); }); }); @@ -101,8 +136,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DotDotDashUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dotDotDash"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dotDotDash", + }, + }, + }); }); }); }); @@ -111,8 +152,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DottedHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dottedHeavy"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dottedHeavy", + }, + }, + }); }); }); }); @@ -121,8 +168,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DottedUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "dotted"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "dotted", + }, + }, + }); }); }); }); @@ -131,8 +184,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.DoubleUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "double"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "double", + }, + }, + }); }); }); }); @@ -141,8 +200,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.SingleUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "single"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "single", + }, + }, + }); }); }); }); @@ -151,8 +216,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.ThickUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "thick"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "thick", + }, + }, + }); }); }); }); @@ -161,8 +232,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.WaveUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "wave"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "wave", + }, + }, + }); }); }); }); @@ -171,8 +248,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.WavyDoubleUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "wavyDouble"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "wavyDouble", + }, + }, + }); }); }); }); @@ -181,8 +264,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.WavyHeavyUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "wavyHeavy"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "wavyHeavy", + }, + }, + }); }); }); }); @@ -191,8 +280,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { const underline = new u.WordsUnderline(); - const newJson = Utility.jsonify(underline); - assert.equal(newJson.root[0].root.val, "words"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": { + _attr: { + "w:val": "words", + }, + }, + }); }); }); }); diff --git a/src/file/xml-components/xml-component.spec.ts b/src/file/xml-components/xml-component.spec.ts index 0166daba18..b626289d99 100644 --- a/src/file/xml-components/xml-component.spec.ts +++ b/src/file/xml-components/xml-component.spec.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { EMPTY_OBJECT, XmlComponent } from "./"; class TestComponent extends XmlComponent {} @@ -14,8 +14,10 @@ describe("XmlComponent", () => { describe("#constructor()", () => { it("should create an Xml Component which has the correct rootKey", () => { - const newJson = Utility.jsonify(xmlComponent); - expect(newJson.rootKey).to.equal("w:test"); + const tree = new Formatter().format(xmlComponent); + expect(tree).to.deep.equal({ + "w:test": {}, + }); }); }); From a53171321442d1e455926b9bd877e6e1693819d8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 26 Jun 2019 22:12:18 +0100 Subject: [PATCH 3/7] Remove usage of Utility class --- src/file/drawing/floating/align.spec.ts | 11 +-- .../drawing/floating/position-offset.spec.ts | 11 +-- src/file/drawing/floating/simple-pos.spec.ts | 17 ++-- .../floating/vertical-position.spec.ts | 42 +++++---- src/file/paragraph/formatting/border.spec.ts | 27 +++--- src/file/paragraph/formatting/style.spec.ts | 24 ++++-- .../paragraph/links/outline-level.spec.ts | 20 ++--- src/file/paragraph/run/break.spec.ts | 10 ++- src/file/paragraph/run/run.spec.ts | 85 +++++++++++++------ src/file/paragraph/run/strike.spec.ts | 24 ++++-- src/file/paragraph/run/tab.spec.ts | 10 ++- 11 files changed, 182 insertions(+), 99 deletions(-) diff --git a/src/file/drawing/floating/align.spec.ts b/src/file/drawing/floating/align.spec.ts index a44ab7039b..906aa8732f 100644 --- a/src/file/drawing/floating/align.spec.ts +++ b/src/file/drawing/floating/align.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { Align } from "./align"; import { VerticalPositionAlign } from "./floating-position"; @@ -8,9 +8,10 @@ import { VerticalPositionAlign } from "./floating-position"; describe("Align", () => { describe("#constructor()", () => { it("should create a element with correct root key", () => { - const newJson = Utility.jsonify(new Align(VerticalPositionAlign.CENTER)); - assert.equal(newJson.rootKey, "wp:align"); - assert.include(newJson.root[0], VerticalPositionAlign.CENTER); + const tree = new Formatter().format(new Align(VerticalPositionAlign.CENTER)); + expect(tree).to.deep.equal({ + "wp:align": ["center"], + }); }); }); }); diff --git a/src/file/drawing/floating/position-offset.spec.ts b/src/file/drawing/floating/position-offset.spec.ts index 237490f9f2..f3fb6c35af 100644 --- a/src/file/drawing/floating/position-offset.spec.ts +++ b/src/file/drawing/floating/position-offset.spec.ts @@ -1,15 +1,16 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { PositionOffset } from "./position-offset"; describe("PositionOffset", () => { describe("#constructor()", () => { it("should create a element with correct root key", () => { - const newJson = Utility.jsonify(new PositionOffset(50)); - assert.equal(newJson.rootKey, "wp:posOffset"); - assert.equal(newJson.root[0], 50); + const tree = new Formatter().format(new PositionOffset(50)); + expect(tree).to.deep.equal({ + "wp:posOffset": ["50"], + }); }); }); }); diff --git a/src/file/drawing/floating/simple-pos.spec.ts b/src/file/drawing/floating/simple-pos.spec.ts index 32218b7a33..395781a358 100644 --- a/src/file/drawing/floating/simple-pos.spec.ts +++ b/src/file/drawing/floating/simple-pos.spec.ts @@ -1,17 +1,20 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { SimplePos } from "./simple-pos"; describe("SimplePos", () => { describe("#constructor()", () => { it("should create a element with correct root key", () => { - const newJson = Utility.jsonify(new SimplePos()); - assert.equal(newJson.rootKey, "wp:simplePos"); - assert.include(newJson.root[0].root, { - x: 0, - y: 0, + const tree = new Formatter().format(new SimplePos()); + expect(tree).to.deep.equal({ + "wp:simplePos": { + _attr: { + x: 0, + y: 0, + }, + }, }); }); }); diff --git a/src/file/drawing/floating/vertical-position.spec.ts b/src/file/drawing/floating/vertical-position.spec.ts index 42d70d7112..ff34f762ef 100644 --- a/src/file/drawing/floating/vertical-position.spec.ts +++ b/src/file/drawing/floating/vertical-position.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { VerticalPositionAlign, VerticalPositionRelativeFrom } from "./floating-position"; import { VerticalPosition } from "./vertical-position"; @@ -8,35 +8,45 @@ import { VerticalPosition } from "./vertical-position"; describe("VerticalPosition", () => { describe("#constructor()", () => { it("should create a element with position align", () => { - const newJson = Utility.jsonify( + const tree = new Formatter().format( new VerticalPosition({ relative: VerticalPositionRelativeFrom.MARGIN, align: VerticalPositionAlign.INSIDE, }), ); - assert.equal(newJson.rootKey, "wp:positionV"); - assert.include(newJson.root[0].root, { - relativeFrom: "margin", + expect(tree).to.deep.equal({ + "wp:positionV": [ + { + _attr: { + relativeFrom: "margin", + }, + }, + { + "wp:align": ["inside"], + }, + ], }); - - assert.equal(newJson.root[1].rootKey, "wp:align"); - assert.include(newJson.root[1].root, "inside"); }); it("should create a element with offset", () => { - const newJson = Utility.jsonify( + const tree = new Formatter().format( new VerticalPosition({ relative: VerticalPositionRelativeFrom.MARGIN, offset: 40, }), ); - assert.equal(newJson.rootKey, "wp:positionV"); - assert.include(newJson.root[0].root, { - relativeFrom: "margin", + expect(tree).to.deep.equal({ + "wp:positionV": [ + { + _attr: { + relativeFrom: "margin", + }, + }, + { + "wp:posOffset": ["40"], + }, + ], }); - - assert.equal(newJson.root[1].rootKey, "wp:posOffset"); - assert.include(newJson.root[1].root[0], 40); }); }); }); diff --git a/src/file/paragraph/formatting/border.spec.ts b/src/file/paragraph/formatting/border.spec.ts index d0fda56359..20b8e4309e 100644 --- a/src/file/paragraph/formatting/border.spec.ts +++ b/src/file/paragraph/formatting/border.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { assert, expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { ThematicBreak } from "./border"; @@ -28,14 +28,21 @@ describe("ThematicBreak", () => { }); it("should create a Thematic Break with correct border properties", () => { - const newJson = Utility.jsonify(thematicBreak); - const attributes = { - color: "auto", - space: "1", - val: "single", - sz: "6", - }; - assert.equal(JSON.stringify(newJson.root[0].root[0].root), JSON.stringify(attributes)); + const tree = new Formatter().format(thematicBreak); + expect(tree).to.deep.equal({ + "w:pBdr": [ + { + "w:bottom": { + _attr: { + "w:color": "auto", + "w:space": "1", + "w:sz": "6", + "w:val": "single", + }, + }, + }, + ], + }); }); }); }); diff --git a/src/file/paragraph/formatting/style.spec.ts b/src/file/paragraph/formatting/style.spec.ts index bf70dc35a4..af3fd9e3a7 100644 --- a/src/file/paragraph/formatting/style.spec.ts +++ b/src/file/paragraph/formatting/style.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { Style } from "./style"; @@ -10,14 +10,26 @@ describe("ParagraphStyle", () => { describe("#constructor()", () => { it("should create a style with given value", () => { style = new Style("test"); - const newJson = Utility.jsonify(style); - assert.equal(newJson.root[0].root.val, "test"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:pStyle": { + _attr: { + "w:val": "test", + }, + }, + }); }); it("should create a style with blank val", () => { style = new Style(""); - const newJson = Utility.jsonify(style); - assert.equal(newJson.root[0].root.val, ""); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:pStyle": { + _attr: { + "w:val": "", + }, + }, + }); }); }); }); diff --git a/src/file/paragraph/links/outline-level.spec.ts b/src/file/paragraph/links/outline-level.spec.ts index 6ba188fd9d..4b13ef03e2 100644 --- a/src/file/paragraph/links/outline-level.spec.ts +++ b/src/file/paragraph/links/outline-level.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { OutlineLevel } from "./outline-level"; @@ -10,14 +10,14 @@ describe("ParagraphOutlineLevel", () => { describe("#constructor()", () => { it("should create an outlineLevel with given value", () => { outlineLevel = new OutlineLevel("0"); - const newJson = Utility.jsonify(outlineLevel); - assert.equal(newJson.root[0].root.val, "0"); - }); - - it("should create an outlineLevel with blank val", () => { - outlineLevel = new OutlineLevel(""); - const newJson = Utility.jsonify(outlineLevel); - assert.equal(newJson.root[0].root.val, ""); + const tree = new Formatter().format(outlineLevel); + expect(tree).to.deep.equal({ + "w:outlineLvl": { + _attr: { + "w:val": "0", + }, + }, + }); }); }); }); diff --git a/src/file/paragraph/run/break.spec.ts b/src/file/paragraph/run/break.spec.ts index a07e1426bd..98e058937d 100644 --- a/src/file/paragraph/run/break.spec.ts +++ b/src/file/paragraph/run/break.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { Break } from "./break"; @@ -13,8 +13,10 @@ describe("Break", () => { describe("#constructor()", () => { it("should create a Break with correct root key", () => { - const newJson = Utility.jsonify(currentBreak); - assert.equal(newJson.rootKey, "w:br"); + const tree = new Formatter().format(currentBreak); + expect(tree).to.deep.equal({ + "w:br": {}, + }); }); }); }); diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index c30147d22f..ae6526a229 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -1,7 +1,6 @@ -import { assert, expect } from "chai"; +import { expect } from "chai"; import { Formatter } from "export/formatter"; -import { Utility } from "tests/utility"; import { Run } from "./"; @@ -15,28 +14,50 @@ describe("Run", () => { describe("#bold()", () => { it("it should add bold to the properties", () => { run.bold(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:b"); - assert.equal(newJson.root[0].root[1].rootKey, "w:bCs"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [ + { + "w:rPr": [ + { "w:b": { _attr: { "w:val": true } } }, + { + "w:bCs": { + _attr: { + "w:val": true, + }, + }, + }, + ], + }, + ], + }); }); }); describe("#italics()", () => { it("it should add italics to the properties", () => { run.italics(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:i"); - assert.equal(newJson.root[0].root[1].rootKey, "w:iCs"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [ + { + "w:rPr": [ + { "w:i": { _attr: { "w:val": true } } }, + { + "w:iCs": { + _attr: { + "w:val": true, + }, + }, + }, + ], + }, + ], + }); }); }); describe("#underline()", () => { - it("it should add underline to the properties", () => { - run.underline(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:u"); - }); - it("should default to 'single' and no color", () => { run.underline(); const tree = new Formatter().format(run); @@ -57,48 +78,60 @@ describe("Run", () => { describe("#smallCaps()", () => { it("it should add smallCaps to the properties", () => { run.smallCaps(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:smallCaps"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:rPr": [{ "w:smallCaps": {} }] }], + }); }); }); describe("#caps()", () => { it("it should add caps to the properties", () => { run.allCaps(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:caps"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:rPr": [{ "w:caps": {} }] }], + }); }); }); describe("#strike()", () => { it("it should add strike to the properties", () => { run.strike(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:strike"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }] }], + }); }); }); describe("#doubleStrike()", () => { it("it should add caps to the properties", () => { run.doubleStrike(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:dstrike"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }] }], + }); }); }); describe("#break()", () => { it("it should add break to the run", () => { run.break(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[1].rootKey, "w:br"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:br": {} }], + }); }); }); describe("#tab()", () => { it("it should add break to the run", () => { run.tab(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[1].rootKey, "w:tab"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [{ "w:tab": {} }], + }); }); }); diff --git a/src/file/paragraph/run/strike.spec.ts b/src/file/paragraph/run/strike.spec.ts index 3d4f83db43..73c7e853c8 100644 --- a/src/file/paragraph/run/strike.spec.ts +++ b/src/file/paragraph/run/strike.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { DoubleStrike, Strike } from "./formatting"; @@ -13,8 +13,14 @@ describe("Strike", () => { describe("#constructor()", () => { it("should create a Strike with correct root key", () => { - const newJson = Utility.jsonify(strike); - assert.equal(newJson.rootKey, "w:strike"); + const tree = new Formatter().format(strike); + expect(tree).to.deep.equal({ + "w:strike": { + _attr: { + "w:val": true, + }, + }, + }); }); }); }); @@ -28,8 +34,14 @@ describe("DoubleStrike", () => { describe("#constructor()", () => { it("should create a Double Strike with correct root key", () => { - const newJson = Utility.jsonify(strike); - assert.equal(newJson.rootKey, "w:dstrike"); + const tree = new Formatter().format(strike); + expect(tree).to.deep.equal({ + "w:dstrike": { + _attr: { + "w:val": true, + }, + }, + }); }); }); }); diff --git a/src/file/paragraph/run/tab.spec.ts b/src/file/paragraph/run/tab.spec.ts index 600b4778ac..04d3503521 100644 --- a/src/file/paragraph/run/tab.spec.ts +++ b/src/file/paragraph/run/tab.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { Tab } from "./tab"; @@ -13,8 +13,10 @@ describe("Tab", () => { describe("#constructor()", () => { it("should create a Tab with correct root key", () => { - const newJson = Utility.jsonify(tab); - assert.equal(newJson.rootKey, "w:tab"); + const tree = new Formatter().format(tab); + expect(tree).to.deep.equal({ + "w:tab": {}, + }); }); }); }); From 120d97bc64eabd0dc92725b2b314a5dfa07ee3b9 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 27 Jun 2019 01:10:39 +0100 Subject: [PATCH 4/7] Remove Utility --- src/file/drawing/drawing.spec.ts | 401 ++++++++++++++++++++++++++++++- 1 file changed, 389 insertions(+), 12 deletions(-) diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 5ab77f28d0..9ffda2add0 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { Drawing, IDrawingOptions } from "./drawing"; @@ -32,16 +32,181 @@ describe("Drawing", () => { let currentBreak: Drawing; describe("#constructor()", () => { - it("should create a Drawing with correct root key", () => { - currentBreak = createDrawing(); - const newJson = Utility.jsonify(currentBreak); - assert.equal(newJson.rootKey, "w:drawing"); - }); - it("should create a drawing with inline element when there are no options passed", () => { currentBreak = createDrawing(); - const newJson = Utility.jsonify(currentBreak); - assert.equal(newJson.root[0].rootKey, "wp:inline"); + const tree = new Formatter().format(currentBreak); + expect(tree).to.deep.equal({ + "w:drawing": [ + { + "wp:inline": [ + { + _attr: { + distB: 0, + distL: 0, + distR: 0, + distT: 0, + }, + }, + { + "wp:extent": { + _attr: { + cx: 952500, + cy: 952500, + }, + }, + }, + { + "wp:effectExtent": { + _attr: { + b: 0, + l: 0, + r: 0, + t: 0, + }, + }, + }, + { + "wp:docPr": { + _attr: { + descr: "", + id: 0, + name: "", + }, + }, + }, + { + "wp:cNvGraphicFramePr": [ + { + "a:graphicFrameLocks": { + _attr: { + // tslint:disable-next-line:object-literal-key-quotes + noChangeAspect: 1, + "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", + }, + }, + }, + ], + }, + { + "a:graphic": [ + { + _attr: { + "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", + }, + }, + { + "a:graphicData": [ + { + _attr: { + uri: "http://schemas.openxmlformats.org/drawingml/2006/picture", + }, + }, + { + "pic:pic": [ + { + _attr: { + "xmlns:pic": "http://schemas.openxmlformats.org/drawingml/2006/picture", + }, + }, + { + "pic:nvPicPr": [ + { + "pic:cNvPr": { + _attr: { + desc: "", + id: 0, + name: "", + }, + }, + }, + { + "pic:cNvPicPr": [ + { + "a:picLocks": { + _attr: { + noChangeArrowheads: 1, + noChangeAspect: 1, + }, + }, + }, + ], + }, + ], + }, + { + "pic:blipFill": [ + { + "a:blip": { + _attr: { + // tslint:disable-next-line:object-literal-key-quotes + cstate: "none", + "r:embed": "rId{test.jpg}", + }, + }, + }, + { + "a:srcRect": {}, + }, + { + "a:stretch": [ + { + "a:fillRect": {}, + }, + ], + }, + ], + }, + { + "pic:spPr": [ + { + _attr: { + bwMode: "auto", + }, + }, + { + "a:xfrm": [ + { + "a:ext": { + _attr: { + cx: 952500, + cy: 952500, + }, + }, + }, + { + "a:off": { + _attr: { + x: 0, + y: 0, + }, + }, + }, + ], + }, + { + "a:prstGeom": [ + { + _attr: { + prst: "rect", + }, + }, + { + "a:avLst": {}, + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }); }); it("should create a drawing with anchor element when there options are passed", () => { @@ -55,8 +220,220 @@ describe("Drawing", () => { }, }, }); - const newJson = Utility.jsonify(currentBreak); - assert.equal(newJson.root[0].rootKey, "wp:anchor"); + const tree = new Formatter().format(currentBreak); + expect(tree).to.deep.equal({ + "w:drawing": [ + { + "wp:anchor": [ + { + _attr: { + allowOverlap: "1", + behindDoc: "0", + distB: 0, + distL: 0, + distR: 0, + distT: 0, + layoutInCell: "1", + locked: "0", + relativeHeight: 952500, + simplePos: "0", + }, + }, + { + "wp:simplePos": { + _attr: { + x: 0, + y: 0, + }, + }, + }, + { + "wp:positionH": [ + { + _attr: { + relativeFrom: "page", + }, + }, + { + "wp:posOffset": ["0"], + }, + ], + }, + { + "wp:positionV": [ + { + _attr: { + relativeFrom: "page", + }, + }, + { + "wp:posOffset": ["0"], + }, + ], + }, + { + "wp:extent": { + _attr: { + cx: 952500, + cy: 952500, + }, + }, + }, + { + "wp:effectExtent": { + _attr: { + b: 0, + l: 0, + r: 0, + t: 0, + }, + }, + }, + { + "wp:wrapNone": {}, + }, + { + "wp:docPr": { + _attr: { + descr: "", + id: 0, + name: "", + }, + }, + }, + { + "wp:cNvGraphicFramePr": [ + { + "a:graphicFrameLocks": { + _attr: { + // tslint:disable-next-line:object-literal-key-quotes + noChangeAspect: 1, + "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", + }, + }, + }, + ], + }, + { + "a:graphic": [ + { + _attr: { + "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", + }, + }, + { + "a:graphicData": [ + { + _attr: { + uri: "http://schemas.openxmlformats.org/drawingml/2006/picture", + }, + }, + { + "pic:pic": [ + { + _attr: { + "xmlns:pic": "http://schemas.openxmlformats.org/drawingml/2006/picture", + }, + }, + { + "pic:nvPicPr": [ + { + "pic:cNvPr": { + _attr: { + desc: "", + id: 0, + name: "", + }, + }, + }, + { + "pic:cNvPicPr": [ + { + "a:picLocks": { + _attr: { + noChangeArrowheads: 1, + noChangeAspect: 1, + }, + }, + }, + ], + }, + ], + }, + { + "pic:blipFill": [ + { + "a:blip": { + _attr: { + // tslint:disable-next-line:object-literal-key-quotes + cstate: "none", + "r:embed": "rId{test.jpg}", + }, + }, + }, + { + "a:srcRect": {}, + }, + { + "a:stretch": [ + { + "a:fillRect": {}, + }, + ], + }, + ], + }, + { + "pic:spPr": [ + { + _attr: { + bwMode: "auto", + }, + }, + { + "a:xfrm": [ + { + "a:ext": { + _attr: { + cx: 952500, + cy: 952500, + }, + }, + }, + { + "a:off": { + _attr: { + x: 0, + y: 0, + }, + }, + }, + ], + }, + { + "a:prstGeom": [ + { + _attr: { + prst: "rect", + }, + }, + { + "a:avLst": {}, + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }); }); }); }); From 1f51fd7a312a2610127a6fcdb8fa68dd59d6091e Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 27 Jun 2019 01:35:58 +0100 Subject: [PATCH 5/7] Remove usage of Utility --- src/export/formatter.spec.ts | 37 ++++++----- .../floating/horizontal-position.spec.ts | 42 ++++++++----- .../paragraph/formatting/page-break.spec.ts | 37 ++++++----- .../formatting/unordered-list.spec.ts | 37 ++++++----- src/file/paragraph/links/hyperlink.spec.ts | 61 ++++++++++--------- 5 files changed, 115 insertions(+), 99 deletions(-) diff --git a/src/export/formatter.spec.ts b/src/export/formatter.spec.ts index 47d7773529..f8c1b457f0 100644 --- a/src/export/formatter.spec.ts +++ b/src/export/formatter.spec.ts @@ -1,10 +1,9 @@ -import { assert } from "chai"; +import { assert, expect } from "chai"; -import { Formatter } from "../export/formatter"; -import * as file from "../file"; -import { CoreProperties } from "../file/core-properties"; -import { Attributes } from "../file/xml-components"; -import { Utility } from "../tests/utility"; +import { Formatter } from "export/formatter"; +import * as file from "file"; +import { CoreProperties } from "file/core-properties"; +import { Attributes } from "file/xml-components"; describe("Formatter", () => { let formatter: Formatter; @@ -38,26 +37,24 @@ describe("Formatter", () => { const attributes = new Attributes({ rsidSect: "test2", }); - let newJson = formatter.format(attributes); - newJson = Utility.jsonify(newJson); - if (newJson._attr === undefined) { - assert.fail(); - return; - } - assert.isDefined(newJson._attr["w:rsidSect"]); + const tree = formatter.format(attributes); + expect(tree).to.deep.equal({ + _attr: { + "w:rsidSect": "test2", + }, + }); }); it("should format attributes (val)", () => { const attributes = new Attributes({ val: "test", }); - let newJson = formatter.format(attributes); - newJson = Utility.jsonify(newJson); - if (newJson._attr === undefined) { - assert.fail(); - return; - } - assert.isDefined(newJson._attr["w:val"]); + const tree = formatter.format(attributes); + expect(tree).to.deep.equal({ + _attr: { + "w:val": "test", + }, + }); }); it("should should change 'p' tag into 'w:p' tag", () => { diff --git a/src/file/drawing/floating/horizontal-position.spec.ts b/src/file/drawing/floating/horizontal-position.spec.ts index e04434e340..6faafb4f7e 100644 --- a/src/file/drawing/floating/horizontal-position.spec.ts +++ b/src/file/drawing/floating/horizontal-position.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from "./floating-position"; import { HorizontalPosition } from "./horizontal-position"; @@ -8,35 +8,45 @@ import { HorizontalPosition } from "./horizontal-position"; describe("HorizontalPosition", () => { describe("#constructor()", () => { it("should create a element with position align", () => { - const newJson = Utility.jsonify( + const tree = new Formatter().format( new HorizontalPosition({ relative: HorizontalPositionRelativeFrom.MARGIN, align: HorizontalPositionAlign.CENTER, }), ); - assert.equal(newJson.rootKey, "wp:positionH"); - assert.include(newJson.root[0].root, { - relativeFrom: "margin", + expect(tree).to.deep.equal({ + "wp:positionH": [ + { + _attr: { + relativeFrom: "margin", + }, + }, + { + "wp:align": ["center"], + }, + ], }); - - assert.equal(newJson.root[1].rootKey, "wp:align"); - assert.include(newJson.root[1].root, "center"); }); it("should create a element with offset", () => { - const newJson = Utility.jsonify( + const tree = new Formatter().format( new HorizontalPosition({ relative: HorizontalPositionRelativeFrom.MARGIN, offset: 40, }), ); - assert.equal(newJson.rootKey, "wp:positionH"); - assert.include(newJson.root[0].root, { - relativeFrom: "margin", + expect(tree).to.deep.equal({ + "wp:positionH": [ + { + _attr: { + relativeFrom: "margin", + }, + }, + { + "wp:posOffset": ["40"], + }, + ], }); - - assert.equal(newJson.root[1].rootKey, "wp:posOffset"); - assert.include(newJson.root[1].root[0], 40); }); }); }); diff --git a/src/file/paragraph/formatting/page-break.spec.ts b/src/file/paragraph/formatting/page-break.spec.ts index 9412da322b..412a8d3c54 100644 --- a/src/file/paragraph/formatting/page-break.spec.ts +++ b/src/file/paragraph/formatting/page-break.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { PageBreak, PageBreakBefore } from "./page-break"; @@ -13,21 +13,18 @@ describe("PageBreak", () => { describe("#constructor()", () => { it("should create a Page Break with correct attributes", () => { - const newJson = Utility.jsonify(pageBreak); - const attributes = { - type: "page", - }; - assert.equal(JSON.stringify(newJson.root[1].root[0].root), JSON.stringify(attributes)); - }); - - it("should create a Page Break with w:r", () => { - const newJson = Utility.jsonify(pageBreak); - assert.equal(newJson.rootKey, "w:r"); - }); - - it("should create a Page Break with a Break inside", () => { - const newJson = Utility.jsonify(pageBreak); - assert.equal(newJson.root[1].rootKey, "w:br"); + const tree = new Formatter().format(pageBreak); + expect(tree).to.deep.equal({ + "w:r": [ + { + "w:br": { + _attr: { + "w:type": "page", + }, + }, + }, + ], + }); }); }); }); @@ -35,7 +32,9 @@ describe("PageBreak", () => { describe("PageBreakBefore", () => { it("should create page break before", () => { const pageBreakBefore = new PageBreakBefore(); - const newJson = Utility.jsonify(pageBreakBefore); - assert.equal(newJson.rootKey, "w:pageBreakBefore"); + const tree = new Formatter().format(pageBreakBefore); + expect(tree).to.deep.equal({ + "w:pageBreakBefore": {}, + }); }); }); diff --git a/src/file/paragraph/formatting/unordered-list.spec.ts b/src/file/paragraph/formatting/unordered-list.spec.ts index 38b65c1ded..fb9fddb95d 100644 --- a/src/file/paragraph/formatting/unordered-list.spec.ts +++ b/src/file/paragraph/formatting/unordered-list.spec.ts @@ -1,6 +1,6 @@ -import { assert } from "chai"; +import { expect } from "chai"; -import { Utility } from "tests/utility"; +import { Formatter } from "export/formatter"; import { NumberProperties } from "./unordered-list"; @@ -13,20 +13,25 @@ describe("NumberProperties", () => { describe("#constructor()", () => { it("should create a Number Properties with correct root key", () => { - const newJson = Utility.jsonify(numberProperties); - assert.equal(newJson.rootKey, "w:numPr"); - }); - - it("should create a Page Break with a Indent Level inside", () => { - const newJson = Utility.jsonify(numberProperties); - assert.equal(newJson.root[0].rootKey, "w:ilvl"); - assert.equal(newJson.root[0].root[0].root.val, 10); - }); - - it("should create a Page Break with a Number Id inside", () => { - const newJson = Utility.jsonify(numberProperties); - assert.equal(newJson.root[1].rootKey, "w:numId"); - assert.equal(newJson.root[1].root[0].root.val, 5); + const tree = new Formatter().format(numberProperties); + expect(tree).to.deep.equal({ + "w:numPr": [ + { + "w:ilvl": { + _attr: { + "w:val": 10, + }, + }, + }, + { + "w:numId": { + _attr: { + "w:val": 5, + }, + }, + }, + ], + }); }); }); }); diff --git a/src/file/paragraph/links/hyperlink.spec.ts b/src/file/paragraph/links/hyperlink.spec.ts index 2cadcfcaca..09dd07b86f 100644 --- a/src/file/paragraph/links/hyperlink.spec.ts +++ b/src/file/paragraph/links/hyperlink.spec.ts @@ -1,7 +1,6 @@ -import { assert, expect } from "chai"; +import { expect } from "chai"; import { Formatter } from "export/formatter"; -import { Utility } from "tests/utility"; import { Hyperlink } from "./"; @@ -14,28 +13,23 @@ describe("Hyperlink", () => { describe("#constructor()", () => { it("should create a hyperlink with correct root key", () => { - const newJson = Utility.jsonify(hyperlink); - assert.equal(newJson.rootKey, "w:hyperlink"); - }); - - it("should create a hyperlink with right attributes", () => { - const newJson = Utility.jsonify(hyperlink); - const attributes = { - history: 1, - id: "rId1", - }; - assert.equal(JSON.stringify(newJson.root[0].root), JSON.stringify(attributes)); - }); - - it("should create a hyperlink with a run component", () => { const tree = new Formatter().format(hyperlink); - const runJson = { - "w:r": [ - { "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "Hyperlink" } } }] }, - { "w:t": [{ _attr: { "xml:space": "preserve" } }, "https://example.com"] }, + expect(tree).to.deep.equal({ + "w:hyperlink": [ + { + _attr: { + "w:history": 1, + "r:id": "rId1", + }, + }, + { + "w:r": [ + { "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "Hyperlink" } } }] }, + { "w:t": [{ _attr: { "xml:space": "preserve" } }, "https://example.com"] }, + ], + }, ], - }; - expect(tree["w:hyperlink"][1]).to.deep.equal(runJson); + }); }); describe("with optional anchor parameter", () => { @@ -44,12 +38,23 @@ describe("Hyperlink", () => { }); it("should create an internal link with anchor tag", () => { - const newJson = Utility.jsonify(hyperlink); - const attributes = { - history: 1, - anchor: "anchor", - }; - assert.equal(JSON.stringify(newJson.root[0].root), JSON.stringify(attributes)); + const tree = new Formatter().format(hyperlink); + expect(tree).to.deep.equal({ + "w:hyperlink": [ + { + _attr: { + "w:history": 1, + "w:anchor": "anchor", + }, + }, + { + "w:r": [ + { "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "Hyperlink" } } }] }, + { "w:t": [{ _attr: { "xml:space": "preserve" } }, "Anchor Text"] }, + ], + }, + ], + }); }); }); }); From cbbc4a80e78611fde8bd682f6bb4012661ffda0f Mon Sep 17 00:00:00 2001 From: Dolan Date: Fri, 28 Jun 2019 01:57:43 +0100 Subject: [PATCH 6/7] FIx up API for column count --- demo/demo44.ts | 20 ++++++++++++++----- .../section-properties.spec.ts | 6 ++++-- .../section-properties/section-properties.ts | 17 +++++++++------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/demo/demo44.ts b/demo/demo44.ts index e4553df05e..a64062222b 100644 --- a/demo/demo44.ts +++ b/demo/demo44.ts @@ -1,23 +1,33 @@ // Sections with multiple columns // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer} from "../build"; +import { Document, Packer } from "../build"; const doc = new Document(); doc.addSection({ - num: 2, + column: { + width: 708, + count: 2, + }, }); doc.createParagraph("This text will be split into 2 columns on a page."); -doc.createParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); +doc.createParagraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", +); doc.addSection({ - num: 3, + column: { + width: 708, + count: 2, + }, }); doc.createParagraph("This text will be split into 3 columns on a page."); -doc.createParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); +doc.createParagraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", +); const packer = new Packer(); diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts index 5b85f09c97..31828ff5f4 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -25,8 +25,10 @@ describe("SectionProperties", () => { footer: 708, gutter: 0, mirror: false, - space: 708, - num: 1, + column: { + space: 708, + count: 1, + }, linePitch: 360, headers: { default: new HeaderWrapper(media, 100), diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index ee5de8b45a..072f68acca 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -4,7 +4,6 @@ import { HeaderWrapper } from "file/header-wrapper"; import { XmlComponent } from "file/xml-components"; import { Columns } from "./columns/columns"; -import { IColumnsAttributes } from "./columns/columns-attributes"; import { DocumentGrid } from "./doc-grid/doc-grid"; import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes"; import { FooterReferenceType } from "./footer-reference"; @@ -40,19 +39,24 @@ interface ITitlePageOptions { export type SectionPropertiesOptions = IPageSizeAttributes & IPageMarginAttributes & - IColumnsAttributes & IDocGridAttributesProperties & IHeadersOptions & IFootersOptions & IPageNumberTypeAttributes & ILineNumberAttributes & IPageBordersOptions & - ITitlePageOptions; + ITitlePageOptions & { + readonly column?: { + readonly space?: number; + readonly count?: number; + }; + }; +// Need to decouple this from the attributes export class SectionProperties extends XmlComponent { private readonly options: SectionPropertiesOptions; - constructor(options: SectionPropertiesOptions = {}) { + constructor(options: SectionPropertiesOptions = { column: {} }) { super("w:sectPr"); const { @@ -66,8 +70,7 @@ export class SectionProperties extends XmlComponent { footer = 708, gutter = 0, mirror = false, - space = 708, - num = 1, + column = {}, linePitch = 360, orientation = PageOrientation.PORTRAIT, headers, @@ -89,7 +92,7 @@ export class SectionProperties extends XmlComponent { this.options = options; this.root.push(new PageSize(width, height, orientation)); this.root.push(new PageMargin(top, right, bottom, left, header, footer, gutter, mirror)); - this.root.push(new Columns(space, num)); + this.root.push(new Columns(column.space ? column.space : 708, column.count ? column.count : 1)); this.root.push(new DocumentGrid(linePitch)); this.addHeaders(headers); From 9e8d67c4a98d8702b7ad7f924c098a274f391fe8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Fri, 28 Jun 2019 01:59:18 +0100 Subject: [PATCH 7/7] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9044ecdeca..965a8b51e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx", - "version": "5.0.0-rc3", + "version": "5.0.0-rc4", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": {