diff --git a/package.json b/package.json index c623ceac56..9574cc3ac4 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,8 @@ "@types/app-root-path": "^1.2.4", "@types/archiver": "^0.15.37", "@types/express": "^4.0.35", - "@types/lodash": "^4.14.54", "app-root-path": "^2.0.1", "archiver": "^1.3.0", - "install": "^0.8.7", - "lodash": "^4.6.1", - "npm": "^4.3.0", "xml": "^1.0.1" }, "author": "Dolan Miu", diff --git a/ts/docx/document/document-attributes.ts b/ts/docx/document/document-attributes.ts index 8c1572f632..bdd3dff089 100644 --- a/ts/docx/document/document-attributes.ts +++ b/ts/docx/document/document-attributes.ts @@ -26,39 +26,30 @@ interface IDocumentAttributesProperties { type?: string; } -export class DocumentAttributes extends XmlAttributeComponent { - - constructor(properties?: IDocumentAttributesProperties) { - super({ - wpc: "xmlns:wpc", - mc: "xmlns:mc", - o: "xmlns:o", - r: "xmlns:r", - m: "xmlns:m", - v: "xmlns:v", - wp14: "xmlns:wp14", - wp: "xmlns:wp", - w10: "xmlns:w10", - w: "xmlns:w", - w14: "xmlns:w14", - w15: "xmlns:w15", - wpg: "xmlns:wpg", - wpi: "xmlns:wpi", - wne: "xmlns:wne", - wps: "xmlns:wps", - Ignorable: "mc:Ignorable", - cp: "xmlns:cp", - dc: "xmlns:dc", - dcterms: "xmlns:dcterms", - dcmitype: "xmlns:dcmitype", - xsi: "xmlns:xsi", - type: "xsi:type", - }, properties); - - this.root = properties; - - if (!properties) { - this.root = {}; - } - } +export class DocumentAttributes extends XmlAttributeComponent { + protected xmlKeys = { + wpc: "xmlns:wpc", + mc: "xmlns:mc", + o: "xmlns:o", + r: "xmlns:r", + m: "xmlns:m", + v: "xmlns:v", + wp14: "xmlns:wp14", + wp: "xmlns:wp", + w10: "xmlns:w10", + w: "xmlns:w", + w14: "xmlns:w14", + w15: "xmlns:w15", + wpg: "xmlns:wpg", + wpi: "xmlns:wpi", + wne: "xmlns:wne", + wps: "xmlns:wps", + Ignorable: "mc:Ignorable", + cp: "xmlns:cp", + dc: "xmlns:dc", + dcterms: "xmlns:dcterms", + dcmitype: "xmlns:dcmitype", + xsi: "xmlns:xsi", + type: "xsi:type", + }; } diff --git a/ts/docx/document/index.ts b/ts/docx/document/index.ts index de8f3f0053..555ebf55bf 100644 --- a/ts/docx/document/index.ts +++ b/ts/docx/document/index.ts @@ -33,4 +33,10 @@ export class Document extends XmlComponent { public addParagraph(paragraph: Paragraph): void { this.body.push(paragraph); } + + public createParagraph(text?: string): Paragraph { + const para = new Paragraph(text); + this.addParagraph(para); + return para; + } } diff --git a/ts/docx/paragraph/indent.ts b/ts/docx/paragraph/indent.ts index c98b3570a1..c2136dada0 100644 --- a/ts/docx/paragraph/indent.ts +++ b/ts/docx/paragraph/indent.ts @@ -1,18 +1,15 @@ import { XmlAttributeComponent, XmlComponent } from "../xml-components"; -interface IndentAttributesProperties { - left: number; - hanging: number; +interface IIndentAttributesProperties { + left?: number; + hanging?: number; } -class IndentAttributes extends XmlAttributeComponent { - - constructor(properties: IndentAttributesProperties) { - super({ - left: "w:left", - hanging: "w:hanging", - }, properties); - } +class IndentAttributes extends XmlAttributeComponent { + protected xmlKeys = { + left: "w:left", + hanging: "w:hanging", + }; } export class Indent extends XmlComponent { diff --git a/ts/docx/paragraph/index.ts b/ts/docx/paragraph/index.ts index c2b3c5ef37..5bf0912d03 100644 --- a/ts/docx/paragraph/index.ts +++ b/ts/docx/paragraph/index.ts @@ -38,6 +38,12 @@ export class Paragraph extends XmlComponent { return this; } + public createTextRun(text: string): TextRun { + const run = new TextRun(text); + this.addText(run); + return run; + } + public heading1(): Paragraph { this.properties.push(new Style("Heading1")); return this; diff --git a/ts/docx/paragraph/spacing.ts b/ts/docx/paragraph/spacing.ts index 527d62c6d3..af4c4e8f79 100644 --- a/ts/docx/paragraph/spacing.ts +++ b/ts/docx/paragraph/spacing.ts @@ -6,14 +6,12 @@ export interface ISpacingProperties { line?: number; } -class SpacingAttributes extends XmlAttributeComponent { - constructor(properties: ISpacingProperties) { - super({ - after: "w:after", - before: "w:before", - line: "w:line", - }, properties); - } +class SpacingAttributes extends XmlAttributeComponent { + protected xmlKeys = { + after: "w:after", + before: "w:before", + line: "w:line", + }; } export class Spacing extends XmlComponent { diff --git a/ts/docx/run/run-fonts.ts b/ts/docx/run/run-fonts.ts index cc542934ae..674f1395b9 100644 --- a/ts/docx/run/run-fonts.ts +++ b/ts/docx/run/run-fonts.ts @@ -6,15 +6,12 @@ interface IRunFontAttributesProperties { hint?: string; } -class RunFontAttributes extends XmlAttributeComponent { - - constructor(properties: IRunFontAttributesProperties) { - super({ - ascii: "w:ascii", - hAnsi: "w:hAnsi", - hint: "w:hint", - }, properties); - } +class RunFontAttributes extends XmlAttributeComponent { + protected xmlKeys = { + ascii: "w:ascii", + hAnsi: "w:hAnsi", + hint: "w:hint", + }; } export class RunFonts extends XmlComponent { diff --git a/ts/docx/xml-components/attributes.ts b/ts/docx/xml-components/attributes.ts index 126a040699..33cbbc1f7b 100644 --- a/ts/docx/xml-components/attributes.ts +++ b/ts/docx/xml-components/attributes.ts @@ -22,29 +22,26 @@ interface IAttributesProperties { pos?: string | number; // Little strange. Perhaps it is normal. Need to clarify in the spec. } -export class Attributes extends XmlAttributeComponent { - - constructor(properties?: IAttributesProperties) { - super({ - val: "w:val", - color: "w:color", - space: "w:space", - sz: "w:sz", - type: "w:type", - rsidR: "w:rsidR", - rsidRPr: "w:rsidRPr", - rsidSect: "w:rsidSect", - w: "w:w", - h: "w:h", - top: "w:top", - right: "w:right", - bottom: "w:bottom", - left: "w:left", - header: "w:header", - footer: "w:footer", - gutter: "w:gutter", - linePitch: "w:linePitch", - pos: "w:pos", - }, properties); - } +export class Attributes extends XmlAttributeComponent { + protected xmlKeys = { + val: "w:val", + color: "w:color", + space: "w:space", + sz: "w:sz", + type: "w:type", + rsidR: "w:rsidR", + rsidRPr: "w:rsidRPr", + rsidSect: "w:rsidSect", + w: "w:w", + h: "w:h", + top: "w:top", + right: "w:right", + bottom: "w:bottom", + left: "w:left", + header: "w:header", + footer: "w:footer", + gutter: "w:gutter", + linePitch: "w:linePitch", + pos: "w:pos", + }; } diff --git a/ts/docx/xml-components/default-attributes.ts b/ts/docx/xml-components/default-attributes.ts index 7559f9fead..7c56a96e63 100644 --- a/ts/docx/xml-components/default-attributes.ts +++ b/ts/docx/xml-components/default-attributes.ts @@ -1,31 +1,25 @@ -import * as _ from "lodash"; import { BaseXmlComponent } from "./base"; -export abstract class XmlAttributeComponent extends BaseXmlComponent { - protected root: object; - private xmlKeys: object; +type AttributeMap = {[P in keyof T]: string}; - constructor(xmlKeys: object, properties: object) { +export abstract class XmlAttributeComponent extends BaseXmlComponent { + protected root: T; + protected xmlKeys: AttributeMap; + + constructor(properties: T) { super("_attr"); - this.xmlKeys = xmlKeys; - this.root = properties; - - if (!properties) { - this.root = {}; - } } public prepForXml(): {_attr: {[key: string]: (string | number | boolean)}} { const attrs = {}; - if (this.root !== undefined) { - _.forOwn(this.root, (value, key) => { - if (value !== undefined) { - const newKey = this.xmlKeys[key]; - attrs[newKey] = value; - } - }); - } + Object.keys(this.root).forEach((key) => { + const value = this.root[key]; + if (value !== undefined) { + const newKey = this.xmlKeys[key]; + attrs[newKey] = value; + } + }); return {_attr: attrs}; } } diff --git a/ts/export/index.ts b/ts/export/index.ts index e9db28839a..111dddfc60 100644 --- a/ts/export/index.ts +++ b/ts/export/index.ts @@ -1,2 +1,3 @@ export { LocalPacker } from "./packer/local"; export { ExpressPacker } from "./packer/express"; +export { Packer } from "./packer/packer"; diff --git a/ts/export/packer/packer.ts b/ts/export/packer/packer.ts index b7838c5ba3..a09f494ded 100644 --- a/ts/export/packer/packer.ts +++ b/ts/export/packer/packer.ts @@ -20,17 +20,18 @@ export abstract class Packer { constructor(document: Document, style?: Styles, properties?: Properties, numbering?: Numbering) { this.formatter = new Formatter(); this.document = document; - this.style = style; - this.properties = properties; - this.numbering = numbering; this.archive = archiver.create("zip", {}); - if (!style) { + if (style) { + this.style = style; + } else { const stylesFactory = new DefaultStylesFactory(); this.style = stylesFactory.newInstance(); } - if (!properties) { + if (properties) { + this.properties = properties; + } else { this.properties = new Properties({ creator: "Un-named", revision: "1", @@ -38,7 +39,9 @@ export abstract class Packer { }); } - if (!numbering) { + if (numbering) { + this.numbering = numbering; + } else { this.numbering = new Numbering(); } diff --git a/ts/index.ts b/ts/index.ts index 5177ddce40..230983a268 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -2,3 +2,4 @@ export * from "./docx"; export * from "./export"; export { Numbering } from "./numbering"; export { Styles } from "./styles"; +export * from './export'; diff --git a/ts/numbering/abstract-numbering.ts b/ts/numbering/abstract-numbering.ts index 5aaaf7a20d..3491ec6426 100644 --- a/ts/numbering/abstract-numbering.ts +++ b/ts/numbering/abstract-numbering.ts @@ -7,14 +7,11 @@ interface IAbstractNumberingAttributesProperties { restartNumberingAfterBreak?: number; } -class AbstractNumberingAttributes extends XmlAttributeComponent { - - constructor(properties: IAbstractNumberingAttributesProperties) { - super({ - abstractNumId: "w:abstractNumId", - restartNumberingAfterBreak: "w15:restartNumberingAfterBreak", - }, properties); - } +class AbstractNumberingAttributes extends XmlAttributeComponent { + protected xmlKeys = { + abstractNumId: "w:abstractNumId", + restartNumberingAfterBreak: "w15:restartNumberingAfterBreak", + }; } export class AbstractNumbering extends XmlComponent { diff --git a/ts/numbering/level.ts b/ts/numbering/level.ts index 2882c20589..02f0896f21 100644 --- a/ts/numbering/level.ts +++ b/ts/numbering/level.ts @@ -7,14 +7,11 @@ interface ILevelAttributesProperties { tentative?: number; } -class LevelAttributes extends XmlAttributeComponent { - - constructor(properties: ILevelAttributesProperties) { - super({ - ilvl: "w:ilvl", - tentative: "w15:tentative", - }, properties); - } +class LevelAttributes extends XmlAttributeComponent { + protected xmlKeys = { + ilvl: "w:ilvl", + tentative: "w15:tentative", + }; } class Start extends XmlComponent { diff --git a/ts/numbering/num.ts b/ts/numbering/num.ts index 1958b989ac..ef7281dc78 100644 --- a/ts/numbering/num.ts +++ b/ts/numbering/num.ts @@ -14,13 +14,8 @@ interface INumAttributesProperties { numId: number; } -class NumAttributes extends XmlAttributeComponent { - - constructor(properties: INumAttributesProperties) { - super({ - numId: "w:numId", - }, properties); - } +class NumAttributes extends XmlAttributeComponent { + protected xmlKeys = {numId: "w:numId"}; } export class Num extends XmlComponent { diff --git a/ts/styles/index.ts b/ts/styles/index.ts index c0114c1c54..da19782366 100644 --- a/ts/styles/index.ts +++ b/ts/styles/index.ts @@ -3,7 +3,6 @@ import { XmlComponent } from "../docx/xml-components"; import { DocumentDefaults } from "./defaults"; import { LatentStyles } from "./latent-styles"; import { LatentStyleException } from "./latent-styles/exceptions"; -import { LatentStyleExceptionAttributes } from "./latent-styles/exceptions/attributes"; import { ParagraphStyle } from "./style"; export class Styles extends XmlComponent { diff --git a/ts/styles/latent-styles/exceptions.ts b/ts/styles/latent-styles/exceptions.ts new file mode 100644 index 0000000000..83995b0902 --- /dev/null +++ b/ts/styles/latent-styles/exceptions.ts @@ -0,0 +1,27 @@ +import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; + +interface ILatentStyleExceptionAttributesProperties { + name?: string; + uiPriority?: string; + qFormat?: string; + semiHidden?: string; + unhideWhenUsed?: string; +} + +class LatentStyleExceptionAttributes extends XmlAttributeComponent { + protected xmlKeys = { + name: "w:name", + uiPriority: "w:uiPriority", + qFormat: "w:qFormat", + semiHidden: "w:semiHidden", + unhideWhenUsed: "w:unhideWhenUsed", + }; +} + +export class LatentStyleException extends XmlComponent { + + constructor(attributes: ILatentStyleExceptionAttributesProperties) { + super("w:lsdException"); + this.root.push(new LatentStyleExceptionAttributes(attributes)); + } +} diff --git a/ts/styles/latent-styles/exceptions/attributes.ts b/ts/styles/latent-styles/exceptions/attributes.ts deleted file mode 100644 index 37e1d8abc6..0000000000 --- a/ts/styles/latent-styles/exceptions/attributes.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {XmlComponent} from "../../../docx/xml-components"; - -interface ILatentStyleExceptionAttributesProperties { - name?: string; - uiPriority?: string; - qFormat?: string; - semiHidden?: string; - unhideWhenUsed?: string; -} - -export class LatentStyleExceptionAttributes extends XmlComponent { - /* tslint:disable */ - private _attr: ILatentStyleExceptionAttributesProperties; - /* tslint:enable */ - - private xmlKeys = { - name: "w:name", - uiPriority: "w:uiPriority", - qFormat: "w:qFormat", - semiHidden: "w:semiHidden", - unhideWhenUsed: "w:unhideWhenUsed", - }; - - constructor(properties?: ILatentStyleExceptionAttributesProperties) { - super("_attr"); - this._attr = properties; - - if (!properties) { - this._attr = {}; - } - // this._attr.xmlKeys = this.xmlKeys; - } -} diff --git a/ts/styles/latent-styles/exceptions/index.ts b/ts/styles/latent-styles/exceptions/index.ts deleted file mode 100644 index 227ed93318..0000000000 --- a/ts/styles/latent-styles/exceptions/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { XmlComponent } from "../../../docx/xml-components"; -import { LatentStyleExceptionAttributes } from "./attributes"; - -export class LatentStyleException extends XmlComponent { - - constructor(attributes: LatentStyleExceptionAttributes) { - super("w:lsdException"); - this.root.push(attributes); - } -} diff --git a/ts/styles/style/components.ts b/ts/styles/style/components.ts index 080ce00162..8980ee8a58 100644 --- a/ts/styles/style/components.ts +++ b/ts/styles/style/components.ts @@ -4,10 +4,8 @@ interface IComponentAttributes { val: string; } -class ComponentAttributes extends XmlAttributeComponent { - constructor(properties: IComponentAttributes) { - super({val: "w:val"}, properties); - } +class ComponentAttributes extends XmlAttributeComponent { + protected xmlKeys = {val: "w:val"}; } export class Name extends XmlComponent { diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index 9a486abbdc..e5e3561eef 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -14,15 +14,13 @@ export interface IStyleAttributes { customStyle?: string; } -class StyleAttributes extends XmlAttributeComponent { - constructor(properties: IStyleAttributes) { - super({ - type: "w:type", - styleId: "w:styleId", - default: "w:default", - customStyle: "w:customStyle", - }, properties); - } +class StyleAttributes extends XmlAttributeComponent { + protected xmlKeys = { + type: "w:type", + styleId: "w:styleId", + default: "w:default", + customStyle: "w:customStyle", + }; } export class Style extends XmlComponent { diff --git a/ts/tests/docx/document/documentTest.ts b/ts/tests/docx/document/documentTest.ts index 43b352a1a7..98b9a9cf97 100644 --- a/ts/tests/docx/document/documentTest.ts +++ b/ts/tests/docx/document/documentTest.ts @@ -1,5 +1,6 @@ -import { assert } from "chai"; +import { assert, expect } from "chai"; import * as docx from "../../../docx"; +import { Formatter } from "../../../export/formatter"; describe("Document", () => { let document: docx.Document; @@ -22,4 +23,27 @@ describe("Document", () => { assert.isTrue(true); }); }); + + describe("#createParagraph", () => { + it("should create a new paragraph and append it to body", () => { + const para = document.createParagraph(); + expect(para).to.be.an.instanceof(docx.Paragraph); + const body = new Formatter().format(document)["w:document"][1]["w:body"]; + expect(body).to.be.an("array").which.has.length.at.least(1); + expect(body[0]).to.have.property("w:p"); + }); + + it("should use the text given to create a run in the paragraph", () => { + const para = document.createParagraph("sample paragraph text"); + expect(para).to.be.an.instanceof(docx.Paragraph); + const body = new Formatter().format(document)["w:document"][1]["w:body"]; + expect(body).to.be.an("array").which.has.length.at.least(1); + expect(body[0]).to.have.property("w:p").which.includes({ + "w:r": [ + {"w:rPr": []}, + {"w:t": ["sample paragraph text"]}, + ], + }); + }); + }); }); diff --git a/ts/tests/docx/paragraph/paragraphTests.ts b/ts/tests/docx/paragraph/paragraphTests.ts index 4866246361..3f8ae4bb56 100644 --- a/ts/tests/docx/paragraph/paragraphTests.ts +++ b/ts/tests/docx/paragraph/paragraphTests.ts @@ -32,6 +32,20 @@ describe("Paragraph", () => { }); }); + describe("#createTextRun", () => { + it("should add a new run to the paragraph and return it", () => { + const run = paragraph.createTextRun("this is a test run"); + expect(run).to.be.instanceof(docx.TextRun); + const tree = new Formatter().format(paragraph)["w:p"]; + expect(tree).to.be.an("array").which.includes({ + "w:r": [ + {"w:rPr": []}, + {"w:t": ["this is a test run"]}, + ], + }); + }); + }); + describe("#heading1()", () => { it("should add heading style to JSON", () => { paragraph.heading1(); diff --git a/ts/tests/docx/xml-components/attributeTest.ts b/ts/tests/docx/xml-components/attributeTest.ts index 002a6bb82c..928164e051 100644 --- a/ts/tests/docx/xml-components/attributeTest.ts +++ b/ts/tests/docx/xml-components/attributeTest.ts @@ -2,21 +2,8 @@ import { assert } from "chai"; import { Attributes } from "../../../docx/xml-components"; describe("Attribute", () => { - let attributes: Attributes; - - beforeEach(() => { - attributes = new Attributes(); - }); - describe("#constructor()", () => { - it("should not add val with empty constructor", () => { - const newAttrs = new Attributes(); - const stringifiedJson = JSON.stringify(newAttrs); - const newJson = JSON.parse(stringifiedJson); - assert.isUndefined(newJson.root.val); - }); - it("should have val as defined with populated constructor", () => { const newAttrs = new Attributes({ val: "test",