diff --git a/ts/docx/document/index.ts b/ts/docx/document/index.ts index cffa5f17d2..de8f3f0053 100644 --- a/ts/docx/document/index.ts +++ b/ts/docx/document/index.ts @@ -33,9 +33,4 @@ export class Document extends XmlComponent { public addParagraph(paragraph: Paragraph): void { this.body.push(paragraph); } - - public clearVariables(): void { - this.body.clearVariables(); - delete this.body; - } } diff --git a/ts/docx/run/text.ts b/ts/docx/run/text.ts index 68019098d4..745c605094 100644 --- a/ts/docx/run/text.ts +++ b/ts/docx/run/text.ts @@ -1,9 +1,11 @@ -import { XmlUnitComponent } from "../xml-components"; +import { XmlComponent } from "../xml-components"; -export class Text extends XmlUnitComponent { +export class Text extends XmlComponent { constructor(text: string) { super("w:t"); - this.root = text; + if (text) { + this.root.push(text); + } } } diff --git a/ts/docx/xml-components/base.ts b/ts/docx/xml-components/base.ts index 0fb1811bf4..cc20f27cb2 100644 --- a/ts/docx/xml-components/base.ts +++ b/ts/docx/xml-components/base.ts @@ -5,9 +5,5 @@ export abstract class BaseXmlComponent { this.rootKey = rootKey; } - public abstract replaceKey(): void; - - public clearVariables(): void { - // Do Nothing - } + public abstract toXml(): object; } diff --git a/ts/docx/xml-components/default-attributes.ts b/ts/docx/xml-components/default-attributes.ts index 02b873f8f1..ec2641fb66 100644 --- a/ts/docx/xml-components/default-attributes.ts +++ b/ts/docx/xml-components/default-attributes.ts @@ -2,10 +2,10 @@ import * as _ from "lodash"; import { BaseXmlComponent } from "./base"; export abstract class XmlAttributeComponent extends BaseXmlComponent { - protected root: Object; - private xmlKeys: Object; + protected root: object; + private xmlKeys: object; - constructor(xmlKeys: Object, properties: Object) { + constructor(xmlKeys: object, properties: object) { super("_attr"); this.xmlKeys = xmlKeys; @@ -16,15 +16,18 @@ export abstract class XmlAttributeComponent extends BaseXmlComponent { } } - public replaceKey(): void { - if (this.root !== undefined) { + public toXml(): object { + const attrs = {}; + if (this.root != undefined) { _.forOwn(this.root, (value, key) => { - const newKey = this.xmlKeys[key]; - this.root[newKey] = value; - delete this.root[key]; + if (value != undefined) { + const newKey = this.xmlKeys[key]; + attrs[newKey] = value; + } }); - this[this.rootKey] = this.root; - delete this.root; } + const ret = {}; + ret[this.rootKey] = attrs; + return ret; } } diff --git a/ts/docx/xml-components/index.ts b/ts/docx/xml-components/index.ts index 07ef8f7363..7e049df6a7 100644 --- a/ts/docx/xml-components/index.ts +++ b/ts/docx/xml-components/index.ts @@ -1,30 +1,27 @@ import * as _ from "lodash"; import { BaseXmlComponent } from "./base"; +export { BaseXmlComponent }; export abstract class XmlComponent extends BaseXmlComponent { - protected root: BaseXmlComponent[]; + protected root: Array; constructor(rootKey: string) { super(rootKey); this.root = new Array(); } - public replaceKey(): void { - // console.log(this.rootKey); - // console.log(this.root); - if (this.root !== undefined) { - this.root.forEach((root) => { - if (root && root instanceof BaseXmlComponent) { - root.replaceKey(); - } - }); - this[this.rootKey] = this.root; - delete this.root; + public toXml(): object { + const ret = this.root.map((comp) => { + if (comp instanceof BaseXmlComponent) { + return comp.toXml(); + } + return comp + }).filter((comp) => comp); // Exclude null, undefined, and empty strings + return { + [this.rootKey]: ret, } } } export * from "./attributes" export * from "./default-attributes"; -export * from "./unit"; -export * from "./property"; diff --git a/ts/docx/xml-components/property.ts b/ts/docx/xml-components/property.ts deleted file mode 100644 index bfc0cab717..0000000000 --- a/ts/docx/xml-components/property.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ParagraphProperties } from "../paragraph/properties"; -import { RunProperties } from "../run/properties"; -import { XmlComponent } from "./"; - -export class ParagraphPropertyXmlComponent extends XmlComponent { - private paragraphProperties: ParagraphProperties; - - constructor(rootKey: string) { - super(rootKey); - this.paragraphProperties = new ParagraphProperties(); - this.root.push(this.paragraphProperties); - } - - public clearVariables(): void { - this.paragraphProperties.clearVariables(); - - delete this.paragraphProperties; - } -} - -export class RunPropertyXmlComponent extends XmlComponent { - private runProperties: RunProperties; - - constructor(rootKey: string) { - super(rootKey); - this.runProperties = new RunProperties(); - this.root.push(this.runProperties); - } - - public clearVariables(): void { - this.runProperties.clearVariables(); - - delete this.runProperties; - } -} - -export class MultiPropertyXmlComponent extends XmlComponent { - private runProperties: RunProperties; - private paragraphProperties: ParagraphProperties; - - constructor(rootKey: string) { - super(rootKey); - this.runProperties = new RunProperties(); - this.root.push(this.runProperties); - - this.paragraphProperties = new ParagraphProperties(); - this.root.push(this.paragraphProperties); - } - - public clearVariables(): void { - this.runProperties.clearVariables(); - this.paragraphProperties.clearVariables(); - - delete this.runProperties; - delete this.paragraphProperties; - } -} diff --git a/ts/docx/xml-components/unit.ts b/ts/docx/xml-components/unit.ts deleted file mode 100644 index 604655d230..0000000000 --- a/ts/docx/xml-components/unit.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {BaseXmlComponent} from "./base"; - -export abstract class XmlUnitComponent extends BaseXmlComponent { - protected root: string; - - constructor(rootKey: string) { - super(rootKey); - } - - public replaceKey(): void { - if (this.root !== undefined) { - this[this.rootKey] = this.root; - delete this.root; - } - } -} diff --git a/ts/export/formatter.ts b/ts/export/formatter.ts index 163e059148..9020e0b293 100644 --- a/ts/export/formatter.ts +++ b/ts/export/formatter.ts @@ -1,52 +1,7 @@ -import * as _ from "lodash"; -import {XmlComponent} from "../docx/xml-components"; +import { BaseXmlComponent } from "../docx/xml-components"; export class Formatter { - - public format(input: any): Object { - input.clearVariables(); - this.replaceKeys(input); - const newJson = this.clense(input); - // console.log(JSON.stringify(newJson, null, " ")); - return newJson; + public format(input: BaseXmlComponent): any { + return input.toXml(); } - - private replaceKeys(input: XmlComponent): Object { - input.replaceKey(); - - return input; - } - - private clense(input: any): Object { - const newJson = this.jsonify(input); - - this.deepTraverseJson(newJson, (parent, value, key) => { - if (key === "properties") { - delete parent[key]; - } - if (key === "xmlKeys") { - delete parent[key]; - } - if (key === "rootKey") { - delete parent[key]; - } - }); - - return newJson; - } - - private jsonify(obj: Object): Object { - let stringifiedJson = JSON.stringify(obj); - return JSON.parse(stringifiedJson); - } - - private deepTraverseJson(json: Object, lambda: (json: any, value: any, key: any) => void): void { - _.forOwn(json, (value, key) => { - if (_.isObject(value) && key !== "xmlKeys" && key !== "rootKey") { - this.deepTraverseJson(value, lambda); - } - lambda(json, value, key); - }); - } - -} \ No newline at end of file +} diff --git a/ts/numbering/abstract-numbering.ts b/ts/numbering/abstract-numbering.ts index 1a5b4bfffb..f8c3822658 100644 --- a/ts/numbering/abstract-numbering.ts +++ b/ts/numbering/abstract-numbering.ts @@ -40,11 +40,4 @@ export class AbstractNumbering extends XmlComponent { this.addLevel(level); return level; } - - public clearVariables(): void { - _.forEach(this.root, (element) => { - element.clearVariables(); - }); - delete this.id; - } } diff --git a/ts/numbering/index.ts b/ts/numbering/index.ts index 828933ae90..06b32b1ab2 100644 --- a/ts/numbering/index.ts +++ b/ts/numbering/index.ts @@ -2,12 +2,12 @@ import * as _ from "lodash"; import { DocumentAttributes } from "../docx/document/document-attributes"; import { Indent } from "../docx/paragraph/indent"; import { RunFonts } from "../docx/run/run-fonts"; -import { MultiPropertyXmlComponent } from "../docx/xml-components"; +import { XmlComponent } from "../docx/xml-components"; import { AbstractNumbering } from "./abstract-numbering"; import { Level } from "./level"; import { Num } from "./num"; -export class Numbering extends MultiPropertyXmlComponent { +export class Numbering extends XmlComponent { private nextId: number; constructor() { @@ -86,12 +86,4 @@ export class Numbering extends MultiPropertyXmlComponent { this.root.push(num); return num; } - - public clearVariables(): void { - super.clearVariables(); - _.forEach(this.root, (element) => { - element.clearVariables(); - }); - delete this.nextId; - } } diff --git a/ts/numbering/level.ts b/ts/numbering/level.ts index 54937cbf63..2882c20589 100644 --- a/ts/numbering/level.ts +++ b/ts/numbering/level.ts @@ -1,6 +1,6 @@ import { ParagraphProperties } from "../docx/paragraph/properties"; import { RunProperties } from "../docx/run/properties"; -import { Attributes, MultiPropertyXmlComponent, XmlAttributeComponent, XmlComponent } from "../docx/xml-components"; +import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components"; interface ILevelAttributesProperties { ilvl?: number; @@ -80,14 +80,6 @@ export class Level extends XmlComponent { this.root.push(this.runProperties); } - public clearVariables(): void { - this.paragraphProperties.clearVariables(); - this.runProperties.clearVariables(); - - delete this.paragraphProperties; - delete this.runProperties; - } - public addParagraphProperty(property: XmlComponent): Level { this.paragraphProperties.push(property); return this; diff --git a/ts/numbering/num.ts b/ts/numbering/num.ts index f127817654..1958b989ac 100644 --- a/ts/numbering/num.ts +++ b/ts/numbering/num.ts @@ -34,9 +34,4 @@ export class Num extends XmlComponent { this.root.push(new AbstractNumId(abstractNumId)); this.id = numId; } - - public clearVariables(): void { - super.clearVariables(); - delete this.id; - } } diff --git a/ts/properties/components.ts b/ts/properties/components.ts index 5f25767a96..d5e1b7fc01 100644 --- a/ts/properties/components.ts +++ b/ts/properties/components.ts @@ -1,66 +1,64 @@ import { DocumentAttributes } from "../docx/document/document-attributes"; -import { XmlUnitComponent } from "../docx/xml-components"; import { XmlComponent } from "../docx/xml-components"; -export class Title extends XmlUnitComponent { +export class Title extends XmlComponent { constructor(value: string) { super("dc:title"); - this.root = value; + this.root.push(value); } } -export class Subject extends XmlUnitComponent { +export class Subject extends XmlComponent { constructor(value: string) { super("dc:subject"); - this.root = value; + this.root.push(value); } } -export class Creator extends XmlUnitComponent { +export class Creator extends XmlComponent { constructor(value: string) { super("dc:creator"); - this.root = value; + this.root.push(value); } } -export class Keywords extends XmlUnitComponent { +export class Keywords extends XmlComponent { constructor(value: string) { super("cp:keywords"); - this.root = value; + this.root.push(value); } } -export class Description extends XmlUnitComponent { +export class Description extends XmlComponent { constructor(value: string) { super("dc:description"); - this.root = value; + this.root.push(value); } } -export class LastModifiedBy extends XmlUnitComponent { +export class LastModifiedBy extends XmlComponent { constructor(value: string) { super("cp:lastModifiedBy"); - this.root = value; + this.root.push(value); } } -export class Revision extends XmlUnitComponent { +export class Revision extends XmlComponent { constructor(value: string) { super("cp:revision"); - const revision = value; - this.root = value; + this.root.push(value); } } abstract class DateComponent extends XmlComponent { - protected getCurrentDate(): any { + protected getCurrentDate(): string { const date = new Date(); const year = date.getFullYear(); const month = ("0" + (date.getMonth() + 1)).slice(-2); diff --git a/ts/properties/index.ts b/ts/properties/index.ts index cbda98a13d..22067d1caa 100644 --- a/ts/properties/index.ts +++ b/ts/properties/index.ts @@ -23,13 +23,27 @@ export class Properties extends XmlComponent { dcmitype: "http://purl.org/dc/dcmitype/", xsi: "http://www.w3.org/2001/XMLSchema-instance", })); - this.root.push(new Title(options.title)); - this.root.push(new Subject(options.subject)); - this.root.push(new Creator(options.creator)); - this.root.push(new Keywords(options.keywords)); - this.root.push(new Description(options.description)); - this.root.push(new LastModifiedBy(options.lastModifiedBy)); - this.root.push(new Revision(options.revision)); + if (options.title) { + this.root.push(new Title(options.title)); + } + if (options.subject) { + this.root.push(new Subject(options.subject)); + } + if (options.creator) { + this.root.push(new Creator(options.creator)); + } + if (options.keywords) { + this.root.push(new Keywords(options.keywords)); + } + if (options.description) { + this.root.push(new Description(options.description)); + } + if (options.lastModifiedBy) { + this.root.push(new LastModifiedBy(options.lastModifiedBy)); + } + if (options.revision) { + this.root.push(new Revision(options.revision)); + } this.root.push(new Created()); this.root.push(new Modified()); } diff --git a/ts/styles/defaults/index.ts b/ts/styles/defaults/index.ts index 65737fcc52..065ed785bd 100644 --- a/ts/styles/defaults/index.ts +++ b/ts/styles/defaults/index.ts @@ -14,11 +14,4 @@ export class DocumentDefaults extends XmlComponent { this.root.push(this.runPropertiesDefaults); this.root.push(this.paragraphPropertiesDefaults); } - - public clearVariables(): void { - this.runPropertiesDefaults.clearVariables(); - this.paragraphPropertiesDefaults.clearVariables(); - delete this.runPropertiesDefaults; - delete this.paragraphPropertiesDefaults; - } } diff --git a/ts/styles/index.ts b/ts/styles/index.ts index 519ad925e2..c0114c1c54 100644 --- a/ts/styles/index.ts +++ b/ts/styles/index.ts @@ -30,12 +30,6 @@ export class Styles extends XmlComponent { return this; } - public clearVariables(): void { - this.root.forEach((element) => { - element.clearVariables(); - }); - } - public createParagraphStyle(styleId: string, name?: string): ParagraphStyle { const para = new ParagraphStyle(styleId, name); this.push(para); diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index 840e55b317..e2fae80a75 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -55,13 +55,6 @@ export class ParagraphStyle extends Style { this.root.push(this.runProperties); } - public clearVariables(): void { - this.paragraphProperties.clearVariables(); - this.runProperties.clearVariables(); - delete this.paragraphProperties; - delete this.runProperties; - } - public addParagraphProperty(property: XmlComponent): void { this.paragraphProperties.push(property); } diff --git a/ts/tests/docx/xml-components/xmlComponentTests.ts b/ts/tests/docx/xml-components/xmlComponentTests.ts index 28f389e4f4..578a5dc2a4 100644 --- a/ts/tests/docx/xml-components/xmlComponentTests.ts +++ b/ts/tests/docx/xml-components/xmlComponentTests.ts @@ -24,13 +24,4 @@ describe("XmlComponent", () => { assert.equal(newJson.rootKey, "w:test"); }); }); - - describe("#replaceKey", () => { - - it("should replace the key to the specified root key", () => { - xmlComponent.replaceKey(); - let newJson = jsonify(xmlComponent); - assert.isDefined(newJson["w:test"]); - }); - }); -}); \ No newline at end of file +}); diff --git a/ts/tests/docx/xml-components/xmlUnitTests.ts b/ts/tests/docx/xml-components/xmlUnitTests.ts deleted file mode 100644 index 313d8916d2..0000000000 --- a/ts/tests/docx/xml-components/xmlUnitTests.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { XmlUnitComponent } from "../../../docx/xml-components"; -import { assert } from "chai"; - -function jsonify(obj: Object) { - let stringifiedJson = JSON.stringify(obj); - return JSON.parse(stringifiedJson); -} - -class TestComponent extends XmlUnitComponent { - -} - -describe("XmlUnitComponent", () => { - let xmlComponent: TestComponent; - - beforeEach(() => { - xmlComponent = new TestComponent("w:test"); - }); - - describe("#constructor()", () => { - - it("should create an Xml Component which has the correct rootKey", () => { - let newJson = jsonify(xmlComponent); - assert.equal(newJson.rootKey, "w:test"); - }); - }); - - describe("#replaceKey", () => { - - it("should not replace the key to the specified root key as root is null", () => { - xmlComponent.replaceKey(); - let newJson = jsonify(xmlComponent); - assert.isUndefined(newJson["w:test"]); - }); - }); -}); \ No newline at end of file diff --git a/ts/tests/export/formatterTest.ts b/ts/tests/export/formatterTest.ts index 8986c2472c..ce7714050b 100644 --- a/ts/tests/export/formatterTest.ts +++ b/ts/tests/export/formatterTest.ts @@ -1,11 +1,12 @@ -import { Formatter } from "../../export/formatter"; -import * as docx from "../../docx"; -import { Attributes } from "../../docx/xml-components"; -import { Properties } from "../../properties"; import { assert } from "chai"; -function jsonify(obj: Object) { - let stringifiedJson = JSON.stringify(obj); +import * as docx from "../../docx"; +import { Attributes } from "../../docx/xml-components"; +import { Formatter } from "../../export/formatter"; +import { Properties } from "../../properties"; + +function jsonify(obj: object): any { + const stringifiedJson = JSON.stringify(obj); return JSON.parse(stringifiedJson); } @@ -18,59 +19,56 @@ describe("Formatter", () => { describe("#format()", () => { it("should format simple paragraph", () => { - let paragraph = new docx.Paragraph(); - let newJson = formatter.format(paragraph); - newJson = jsonify(newJson); + const paragraph = new docx.Paragraph(); + const newJson = formatter.format(paragraph); assert.isDefined(newJson["w:p"]); }); it("should remove xmlKeys", () => { - let paragraph = new docx.Paragraph(); - let newJson = formatter.format(paragraph); - let stringifiedJson = JSON.stringify(newJson); + const paragraph = new docx.Paragraph(); + const newJson = formatter.format(paragraph); + const stringifiedJson = JSON.stringify(newJson); assert(stringifiedJson.indexOf("xmlKeys") < 0); }); it("should format simple paragraph with bold text", () => { - let paragraph = new docx.Paragraph(); + const paragraph = new docx.Paragraph(); paragraph.addText(new docx.TextRun("test").bold()); - let newJson = formatter.format(paragraph); - newJson = jsonify(newJson); - assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]["_attr"]["w:val"]); + const newJson = formatter.format(paragraph); + assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]._attr["w:val"]); }); it("should format attributes (rsidSect)", () => { - let attributes = new Attributes({ - rsidSect: "test2" + const attributes = new Attributes({ + rsidSect: "test2", }); let newJson = formatter.format(attributes); newJson = jsonify(newJson); - assert.isDefined(newJson["_attr"]["w:rsidSect"]); + assert.isDefined(newJson._attr["w:rsidSect"]); }); it("should format attributes (val)", () => { - let attributes = new Attributes({ - val: "test" + const attributes = new Attributes({ + val: "test", }); let newJson = formatter.format(attributes); newJson = jsonify(newJson); - assert.isDefined(newJson["_attr"]["w:val"]); + assert.isDefined(newJson._attr["w:val"]); }); it("should should change 'p' tag into 'w:p' tag", () => { - let paragraph = new docx.Paragraph(); - let newJson = formatter.format(paragraph); + const paragraph = new docx.Paragraph(); + const newJson = formatter.format(paragraph); assert.isDefined(newJson["w:p"]); }); it("should format Properties object correctly", () => { - let properties = new Properties({ + const properties = new Properties({ title: "test document", - creator: "Dolan" + creator: "Dolan", }); - let newJson = formatter.format(properties); - newJson = jsonify(newJson); + const newJson = formatter.format(properties); assert.isDefined(newJson["cp:coreProperties"]); }); }); -}); \ No newline at end of file +}); diff --git a/ts/tests/numberingTest.ts b/ts/tests/numberingTest.ts index 7b562567a8..1d79475b17 100644 --- a/ts/tests/numberingTest.ts +++ b/ts/tests/numberingTest.ts @@ -65,7 +65,10 @@ describe("Numbering", () => { const n = numbering.createConcreteNumbering(a2); expect(n).to.be.instanceof(Num); const tree = new Formatter().format(numbering); - expect(n.id).to.equal(a2.id); + const serializedN = tree["w:numbering"].find( + (obj) => obj["w:num"] && obj["w:num"][0]._attr["w:numId"] === n.id + ); + expect(serializedN["w:num"][1]["w:abstractNumId"][0]._attr["w:val"]).to.equal(a2.id); }); it("assigns a unique ID to each concrete numbering it creates", () => { diff --git a/ts/tests/propertiesTest.ts b/ts/tests/propertiesTest.ts index 0c56ccd13c..c11505381d 100644 --- a/ts/tests/propertiesTest.ts +++ b/ts/tests/propertiesTest.ts @@ -1,25 +1,74 @@ -import { Properties } from "../properties"; -import { assert } from "chai"; +import { expect } from "chai"; -function jsonify(obj: Object) { - let stringifiedJson = JSON.stringify(obj); - return JSON.parse(stringifiedJson); -} +import { Formatter } from "../export/formatter"; +import { Properties } from "../properties"; describe("Properties", () => { - let properties: Properties; - - beforeEach(() => { - - }); describe("#constructor()", () => { - it("should create properties with a title", () => { - properties = new Properties({ - title: "test document" + it("sets the appropriate attributes on the top-level", () => { + const properties = new Properties({}); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]); + expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array); + expect(tree["cp:coreProperties"][0]).to.deep.equal({ + _attr: { + "xmlns:cp": "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", + "xmlns:dc": "http://purl.org/dc/elements/1.1/", + "xmlns:dcmitype": "http://purl.org/dc/dcmitype/", + "xmlns:dcterms": "http://purl.org/dc/terms/", + "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", + }, }); - let newJson = jsonify(properties); - assert(newJson.root[1].root === "test document"); + }); + + it("should create properties with a title", () => { + const properties = new Properties({title: "test document"}); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]); + expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array); + expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]); + expect(tree["cp:coreProperties"][1]).to.deep.equal( + {"dc:title": ["test document"]}, + ); + }); + + it("should create properties with all the attributes given", () => { + const properties = new Properties({ + title: "test document", + subject: "test subject", + creator: "me", + keywords: "test docx", + description: "testing document", + lastModifiedBy: "the author", + revision: "123", + }); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]); + expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array); + const key = (obj) => Object.keys(obj)[0]; + const props = tree["cp:coreProperties"].map(key).sort(); + expect(props).to.deep.equal([ + "_attr", + "cp:keywords", + "cp:lastModifiedBy", + "cp:revision", + "dc:creator", + "dc:description", + "dc:subject", + "dc:title", + "dcterms:created", + "dcterms:modified", + ]); + expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => key(a) < key(b) ? -1 : 1)).to.deep.equal([ + {"cp:keywords": ["test docx"]}, + {"cp:lastModifiedBy": ["the author"]}, + {"cp:revision": ["123"]}, + {"dc:creator": ["me"]}, + {"dc:description": ["testing document"]}, + {"dc:subject": ["test subject"]}, + {"dc:title": ["test document"]}, + ]); }); }); -}); \ No newline at end of file +});