From 2684f16579b139e62796da7d9f5b026f8c7a83f6 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 09:18:17 +0100 Subject: [PATCH 01/13] move indent.ts over to paragraph and add a #indent method --- ts/{numbering => docx/paragraph}/indent.ts | 2 +- ts/docx/paragraph/index.ts | 7 +++++++ ts/numbering/index.ts | 2 +- ts/tests/docx/paragraph/paragraphTests.ts | 18 +++++++++++++++++- 4 files changed, 26 insertions(+), 3 deletions(-) rename ts/{numbering => docx/paragraph}/indent.ts (91%) diff --git a/ts/numbering/indent.ts b/ts/docx/paragraph/indent.ts similarity index 91% rename from ts/numbering/indent.ts rename to ts/docx/paragraph/indent.ts index b5bdac02b0..24a73cb3e8 100644 --- a/ts/numbering/indent.ts +++ b/ts/docx/paragraph/indent.ts @@ -17,7 +17,7 @@ class IndentAttributes extends XmlAttributeComponent { export class Indent extends XmlComponent { - constructor(left: number, hanging: number) { + constructor(left: number, hanging?: number) { super("w:ind"); this.root.push(new IndentAttributes({ left: left, diff --git a/ts/docx/paragraph/index.ts b/ts/docx/paragraph/index.ts index 368cdc1f5a..e22badcba5 100644 --- a/ts/docx/paragraph/index.ts +++ b/ts/docx/paragraph/index.ts @@ -1,7 +1,9 @@ import { Num } from "../../numbering/num"; import { TextRun } from "../run/text-run"; import { Attributes, XmlComponent } from "../xml-components"; + import { ThematicBreak } from "./border"; +import { Indent } from "./indent"; import { PageBreak } from "./page-break"; import { ParagraphProperties } from "./properties"; import { Style } from "./style"; @@ -116,4 +118,9 @@ export class Paragraph extends XmlComponent { this.properties.push(new NumberProperties(numbering.id, indentLevel)); return this; } + + public indent(start: number, hanging?: number): Paragraph { + this.properties.push(new Indent(start, hanging)); + return this; + } } diff --git a/ts/numbering/index.ts b/ts/numbering/index.ts index 39bfda0867..828933ae90 100644 --- a/ts/numbering/index.ts +++ b/ts/numbering/index.ts @@ -1,9 +1,9 @@ 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 { AbstractNumbering } from "./abstract-numbering"; -import { Indent } from "./indent"; import { Level } from "./level"; import { Num } from "./num"; diff --git a/ts/tests/docx/paragraph/paragraphTests.ts b/ts/tests/docx/paragraph/paragraphTests.ts index 81fb18564d..e581bf11f9 100644 --- a/ts/tests/docx/paragraph/paragraphTests.ts +++ b/ts/tests/docx/paragraph/paragraphTests.ts @@ -136,7 +136,6 @@ describe("Paragraph", () => { paragraph.setNumbering(letterNumbering, 0); const tree = new Formatter().format(paragraph); - console.log(JSON.stringify(tree, null, 2)); expect(tree).to.deep.equal({ "w:p": [ { @@ -155,4 +154,21 @@ describe("Paragraph", () => { }) }); }); + + describe("#indent", () => { + it("should set the paragraph indent to the given values", () => { + paragraph.indent(720); + const tree = new Formatter().format(paragraph); + expect(tree).to.deep.equal({ + "w:p": [ + { + "w:pPr": [ + {"_attr": {}}, + {"w:ind": [{"_attr": {"w:left": 720}}]}, + ], + }, + ] + }) + }); + }); }); From f5144e6d729a5aecd2d1ded35294c746975b021f Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 09:45:01 +0100 Subject: [PATCH 02/13] ts/styles linter warnings --- ts/styles/defaults/index.ts | 10 ++--- ts/styles/defaults/paragraph-properties.ts | 6 +-- ts/styles/defaults/run-properties.ts | 6 +-- ts/styles/factory.ts | 44 ++++++++++--------- ts/styles/index.ts | 23 +++++----- .../latent-styles/exceptions/attributes.ts | 14 +++--- ts/styles/latent-styles/exceptions/index.ts | 6 +-- ts/styles/latent-styles/index.ts | 8 ++-- ts/styles/style/attributes.ts | 13 +++--- ts/styles/style/components.ts | 16 +++---- ts/styles/style/index.ts | 25 ++++++----- ts/tests/stylesTest.ts | 9 ++-- 12 files changed, 91 insertions(+), 89 deletions(-) diff --git a/ts/styles/defaults/index.ts b/ts/styles/defaults/index.ts index 7b74e1d311..65737fcc52 100644 --- a/ts/styles/defaults/index.ts +++ b/ts/styles/defaults/index.ts @@ -1,6 +1,6 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {ParagraphPropertiesDefaults} from "./paragraph-properties"; -import {RunPropertiesDefaults} from "./run-properties"; +import { XmlComponent } from "../../docx/xml-components"; +import { ParagraphPropertiesDefaults } from "./paragraph-properties"; +import { RunPropertiesDefaults } from "./run-properties"; export class DocumentDefaults extends XmlComponent { @@ -15,10 +15,10 @@ export class DocumentDefaults extends XmlComponent { this.root.push(this.paragraphPropertiesDefaults); } - clearVariables(): void { + public clearVariables(): void { this.runPropertiesDefaults.clearVariables(); this.paragraphPropertiesDefaults.clearVariables(); delete this.runPropertiesDefaults; delete this.paragraphPropertiesDefaults; } -} \ No newline at end of file +} diff --git a/ts/styles/defaults/paragraph-properties.ts b/ts/styles/defaults/paragraph-properties.ts index 43d1d4c4cf..bac85aa796 100644 --- a/ts/styles/defaults/paragraph-properties.ts +++ b/ts/styles/defaults/paragraph-properties.ts @@ -1,5 +1,5 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {ParagraphProperties} from "../../docx/paragraph/properties"; +import { ParagraphProperties } from "../../docx/paragraph/properties"; +import { XmlComponent } from "../../docx/xml-components"; export class ParagraphPropertiesDefaults extends XmlComponent { @@ -7,4 +7,4 @@ export class ParagraphPropertiesDefaults extends XmlComponent { super("w:pPrDefault"); this.root.push(new ParagraphProperties()); } -} \ No newline at end of file +} diff --git a/ts/styles/defaults/run-properties.ts b/ts/styles/defaults/run-properties.ts index e3c14a20a1..388d7a2e88 100644 --- a/ts/styles/defaults/run-properties.ts +++ b/ts/styles/defaults/run-properties.ts @@ -1,5 +1,5 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {RunProperties} from "../../docx/run/properties"; +import { RunProperties } from "../../docx/run/properties"; +import { XmlComponent } from "../../docx/xml-components"; export class RunPropertiesDefaults extends XmlComponent { @@ -7,4 +7,4 @@ export class RunPropertiesDefaults extends XmlComponent { super("w:rPrDefault"); this.root.push(new RunProperties()); } -} \ No newline at end of file +} diff --git a/ts/styles/factory.ts b/ts/styles/factory.ts index 9907157dd3..d44e4c3b09 100644 --- a/ts/styles/factory.ts +++ b/ts/styles/factory.ts @@ -1,56 +1,60 @@ -import {Styles} from "./"; -import {DocumentDefaults} from "./defaults"; -import {ParagraphPropertiesDefaults} from "./defaults/paragraph-properties"; -import {RunPropertiesDefaults} from "./defaults/run-properties"; -import {Heading1Style, Heading2Style, TitleStyle, Heading3Style, Heading4Style, Heading5Style, Heading6Style, ListParagraph} from "./style"; -// import {StyleAttributes} from "./style/attributes"; -import {ParagraphProperties} from "../docx/paragraph/properties"; -import {RunProperties} from "../docx/run/properties"; -import {Color, Size, Italics} from "../docx/run/formatting"; +import { ParagraphProperties } from "../docx/paragraph/properties"; +import { Color, Italics, Size } from "../docx/run/formatting"; +import { RunProperties } from "../docx/run/properties"; + +import { Styles } from "./"; +import { DocumentDefaults } from "./defaults"; +import { ParagraphPropertiesDefaults } from "./defaults/paragraph-properties"; +import { RunPropertiesDefaults } from "./defaults/run-properties"; +import { + Heading1Style, Heading2Style, Heading3Style, Heading4Style, Heading5Style, Heading6Style, + ListParagraph, TitleStyle, +} from "./style"; +// import { StyleAttributes } from "./style/attributes"; export class DefaultStylesFactory { - newInstance(): Styles { - let styles = new Styles(); + public newInstance(): Styles { + const styles = new Styles(); styles.push(new DocumentDefaults()); - let titleStyle = new TitleStyle(); + const titleStyle = new TitleStyle(); titleStyle.addRunProperty(new Size(56)); styles.push(titleStyle); - let heading1Style = new Heading1Style(); + const heading1Style = new Heading1Style(); heading1Style.addRunProperty(new Color("2E74B5")); heading1Style.addRunProperty(new Size(32)); styles.push(heading1Style); - let heading2Style = new Heading2Style(); + const heading2Style = new Heading2Style(); heading2Style.addRunProperty(new Color("2E74B5")); heading2Style.addRunProperty(new Size(26)); styles.push(heading2Style); - let heading3Style = new Heading3Style(); + const heading3Style = new Heading3Style(); heading3Style.addRunProperty(new Color("1F4D78")); heading3Style.addRunProperty(new Size(24)); styles.push(heading3Style); - let heading4Style = new Heading4Style(); + const heading4Style = new Heading4Style(); heading4Style.addRunProperty(new Color("2E74B5")); heading4Style.addRunProperty(new Italics()); styles.push(heading4Style); - let heading5Style = new Heading5Style(); + const heading5Style = new Heading5Style(); heading5Style.addRunProperty(new Color("2E74B5")); styles.push(heading5Style); - let heading6Style = new Heading6Style(); + const heading6Style = new Heading6Style(); heading6Style.addRunProperty(new Color("1F4D78")); styles.push(heading6Style); - let listParagraph = new ListParagraph(); + const listParagraph = new ListParagraph(); // listParagraph.addParagraphProperty(); styles.push(listParagraph); // console.log(JSON.stringify(styles, null, " ")); return styles; } -} \ No newline at end of file +} diff --git a/ts/styles/index.ts b/ts/styles/index.ts index ebf66dd56b..ee9f2bc784 100644 --- a/ts/styles/index.ts +++ b/ts/styles/index.ts @@ -1,9 +1,9 @@ -import {XmlComponent} from "../docx/xml-components"; -import {DocumentAttributes} from "../docx/document/document-attributes"; -import {DocumentDefaults} from "./defaults"; -import {LatentStyles} from "./latent-styles"; -import {LatentStyleException} from "./latent-styles/exceptions"; -import {LatentStyleExceptionAttributes} from "./latent-styles/exceptions/attributes"; +import { DocumentAttributes } from "../docx/document/document-attributes"; +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"; export class Styles extends XmlComponent { @@ -15,7 +15,7 @@ export class Styles extends XmlComponent { w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", w14: "http://schemas.microsoft.com/office/word/2010/wordml", w15: "http://schemas.microsoft.com/office/word/2012/wordml", - Ignorable: "w14 w15" + Ignorable: "w14 w15", })); // let latentStyles = new LatentStyles(); // latentStyles.push(new LatentStyleException(new LatentStyleExceptionAttributes({ @@ -24,13 +24,14 @@ export class Styles extends XmlComponent { // this.root.push(latentStyles); } - push(style: XmlComponent): void { + public push(style: XmlComponent): Styles { this.root.push(style); + return this; } - clearVariables() { - this.root.forEach(element => { + public clearVariables(): void { + this.root.forEach((element) => { element.clearVariables(); }); } -} \ No newline at end of file +} diff --git a/ts/styles/latent-styles/exceptions/attributes.ts b/ts/styles/latent-styles/exceptions/attributes.ts index 4c2eaa2786..359852bceb 100644 --- a/ts/styles/latent-styles/exceptions/attributes.ts +++ b/ts/styles/latent-styles/exceptions/attributes.ts @@ -1,6 +1,6 @@ import {XmlComponent} from "../../../docx/xml-components"; -interface LatentStyleExceptionAttributesProperties { +interface ILatentStyleExceptionAttributesProperties { name?: string; uiPriority?: string; qFormat?: string; @@ -9,23 +9,23 @@ interface LatentStyleExceptionAttributesProperties { } export class LatentStyleExceptionAttributes extends XmlComponent { - private _attr: Object; + private _attr: ILatentStyleExceptionAttributesProperties; - xmlKeys = { + private xmlKeys = { name: "w:name", uiPriority: "w:uiPriority", qFormat: "w:qFormat", semiHidden: "w:semiHidden", - unhideWhenUsed: "w:unhideWhenUsed" + unhideWhenUsed: "w:unhideWhenUsed", }; - constructor(properties?: LatentStyleExceptionAttributesProperties) { + constructor(properties?: ILatentStyleExceptionAttributesProperties) { super("_attr"); this._attr = properties; if (!properties) { this._attr = {}; } - this._attr["xmlKeys"] = this.xmlKeys; + //this._attr.xmlKeys = this.xmlKeys; } -} \ No newline at end of file +} diff --git a/ts/styles/latent-styles/exceptions/index.ts b/ts/styles/latent-styles/exceptions/index.ts index 685440b3ee..227ed93318 100644 --- a/ts/styles/latent-styles/exceptions/index.ts +++ b/ts/styles/latent-styles/exceptions/index.ts @@ -1,5 +1,5 @@ -import {XmlComponent} from "../../../docx/xml-components"; -import {LatentStyleExceptionAttributes} from "./attributes"; +import { XmlComponent } from "../../../docx/xml-components"; +import { LatentStyleExceptionAttributes } from "./attributes"; export class LatentStyleException extends XmlComponent { @@ -7,4 +7,4 @@ export class LatentStyleException extends XmlComponent { super("w:lsdException"); this.root.push(attributes); } -} \ No newline at end of file +} diff --git a/ts/styles/latent-styles/index.ts b/ts/styles/latent-styles/index.ts index fe75c11e37..583ab1e0e0 100644 --- a/ts/styles/latent-styles/index.ts +++ b/ts/styles/latent-styles/index.ts @@ -1,5 +1,5 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {LatentStyleException} from "./exceptions"; +import { XmlComponent } from "../../docx/xml-components"; +import { LatentStyleException } from "./exceptions"; export class LatentStyles extends XmlComponent { @@ -7,7 +7,7 @@ export class LatentStyles extends XmlComponent { super("w:latentStyles"); } - push(latentException: LatentStyleException): void { + public push(latentException: LatentStyleException): void { this.root.push(latentException); } -} \ No newline at end of file +} diff --git a/ts/styles/style/attributes.ts b/ts/styles/style/attributes.ts index a227979cb4..c6ec627404 100644 --- a/ts/styles/style/attributes.ts +++ b/ts/styles/style/attributes.ts @@ -1,7 +1,6 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {XmlAttributeComponent} from "../../docx/xml-components"; +import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; -interface StyleAttributesProperties { +interface IStyleAttributesProperties { type?: string; styleId?: string; default?: string; @@ -10,15 +9,15 @@ interface StyleAttributesProperties { } export class StyleAttributes extends XmlAttributeComponent { - private _attr: Object; + private _attr: IStyleAttributesProperties; - constructor(properties: StyleAttributesProperties) { + constructor(properties: IStyleAttributesProperties) { super({ type: "w:type", styleId: "w:styleId", default: "w:default", customStyle: "w:customStyle", - val: "w:val" + val: "w:val", }, properties); } -} \ No newline at end of file +} diff --git a/ts/styles/style/components.ts b/ts/styles/style/components.ts index f7853169d1..17751bb32a 100644 --- a/ts/styles/style/components.ts +++ b/ts/styles/style/components.ts @@ -1,12 +1,12 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {StyleAttributes} from "./attributes"; +import { XmlComponent } from "../../docx/xml-components"; +import { StyleAttributes } from "./attributes"; export class Name extends XmlComponent { constructor(value: string) { super("w:name"); this.root.push(new StyleAttributes({ - val: value + val: value, })); } } @@ -16,7 +16,7 @@ export class BasedOn extends XmlComponent { constructor(value: string) { super("w:basedOn"); this.root.push(new StyleAttributes({ - val: value + val: value, })); } } @@ -27,7 +27,7 @@ export class Next extends XmlComponent { super("w:next"); this.root.push(new StyleAttributes({ styleId: "1", - val: value + val: value, })); } } @@ -37,7 +37,7 @@ export class Link extends XmlComponent { constructor(value: string) { super("w:link"); this.root.push(new StyleAttributes({ - val: value + val: value, })); } } @@ -47,7 +47,7 @@ export class UiPriority extends XmlComponent { constructor(value: string) { super("w:uiPriority"); this.root.push(new StyleAttributes({ - val: value + val: value, })); } } @@ -73,4 +73,4 @@ export class RsId extends XmlComponent { export class SemiHidden extends XmlComponent { -} \ No newline at end of file +} diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index 412667ea81..6d916a1507 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -1,8 +1,9 @@ -import {XmlComponent} from "../../docx/xml-components"; -import {StyleAttributes} from "./attributes"; -import {ParagraphProperties} from "../../docx/paragraph/properties"; -import {RunProperties} from "../../docx/run/properties"; -import {Name, BasedOn, Next, QuickFormat} from "./components"; +import { ParagraphProperties } from "../../docx/paragraph/properties"; +import { RunProperties } from "../../docx/run/properties"; +import { XmlComponent } from "../../docx/xml-components"; + +import { StyleAttributes } from "./attributes"; +import { BasedOn, Name, Next, QuickFormat } from "./components"; export class Style extends XmlComponent { @@ -11,7 +12,7 @@ export class Style extends XmlComponent { this.root.push(attributes); } - push(styleSegment: XmlComponent): void { + public push(styleSegment: XmlComponent): void { this.root.push(styleSegment); } } @@ -23,9 +24,9 @@ export class ParagraphStyle extends Style { constructor(styleId: string) { - let attributes = new StyleAttributes({ + const attributes = new StyleAttributes({ type: "paragraph", - styleId: styleId + styleId: styleId, }); super(attributes); this.paragraphProperties = new ParagraphProperties(); @@ -34,18 +35,18 @@ export class ParagraphStyle extends Style { this.root.push(this.runProperties); } - clearVariables(): void { + public clearVariables(): void { this.paragraphProperties.clearVariables(); this.runProperties.clearVariables(); delete this.paragraphProperties; delete this.runProperties; } - addParagraphProperty(property: XmlComponent): void { + public addParagraphProperty(property: XmlComponent): void { this.paragraphProperties.push(property); } - addRunProperty(property: XmlComponent): void { + public addRunProperty(property: XmlComponent): void { this.runProperties.push(property); } } @@ -118,4 +119,4 @@ export class ListParagraph extends ParagraphStyle { this.root.push(new BasedOn("Normal")); this.root.push(new QuickFormat()); } -} \ No newline at end of file +} diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index bc3015c009..06fc29e645 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -1,5 +1,5 @@ -import { Styles } from "../styles"; import { assert } from "chai"; +import { Styles } from "../styles"; describe("Styles", () => { let styles: Styles; @@ -11,11 +11,8 @@ describe("Styles", () => { describe("#constructor()", () => { it("should create styles with correct rootKey", () => { - let styles = new Styles(); - let stringifiedJson = JSON.stringify(styles); - let newJson = JSON.parse(stringifiedJson); - + const newJson = JSON.parse(JSON.stringify(styles)); assert.equal(newJson.rootKey, "w:styles"); }); }); -}); \ No newline at end of file +}); From 18ca93e50a2d9e3a4342bc675f8b68dc21613b4d Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 09:46:12 +0100 Subject: [PATCH 03/13] add paragraph#style method to quickly set the style --- ts/docx/paragraph/indent.ts | 2 +- ts/docx/paragraph/index.ts | 5 +++++ ts/tests/docx/paragraph/paragraphTests.ts | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ts/docx/paragraph/indent.ts b/ts/docx/paragraph/indent.ts index 24a73cb3e8..c98b3570a1 100644 --- a/ts/docx/paragraph/indent.ts +++ b/ts/docx/paragraph/indent.ts @@ -1,4 +1,4 @@ -import { XmlAttributeComponent, XmlComponent } from "../docx/xml-components"; +import { XmlAttributeComponent, XmlComponent } from "../xml-components"; interface IndentAttributesProperties { left: number; diff --git a/ts/docx/paragraph/index.ts b/ts/docx/paragraph/index.ts index e22badcba5..7b82b63434 100644 --- a/ts/docx/paragraph/index.ts +++ b/ts/docx/paragraph/index.ts @@ -119,6 +119,11 @@ export class Paragraph extends XmlComponent { return this; } + public style(styleId: string): Paragraph { + this.properties.push(new Style(styleId)); + return this; + } + public indent(start: number, hanging?: number): Paragraph { this.properties.push(new Indent(start, hanging)); return this; diff --git a/ts/tests/docx/paragraph/paragraphTests.ts b/ts/tests/docx/paragraph/paragraphTests.ts index e581bf11f9..96b23ac8bd 100644 --- a/ts/tests/docx/paragraph/paragraphTests.ts +++ b/ts/tests/docx/paragraph/paragraphTests.ts @@ -155,6 +155,23 @@ describe("Paragraph", () => { }); }); + describe("#style", () => { + it("should set the paragraph style to the given styleId", () => { + paragraph.style('myFancyStyle'); + const tree = new Formatter().format(paragraph); + expect(tree).to.deep.equal({ + "w:p": [ + { + "w:pPr": [ + {"_attr": {}}, + {"w:pStyle": [{"_attr": {"w:val": "myFancyStyle"}}]}, + ], + }, + ] + }) + }); + }); + describe("#indent", () => { it("should set the paragraph indent to the given values", () => { paragraph.indent(720); From e6e06588122319fd23e5d629bbc6d3b937e3a848 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 10:54:40 +0100 Subject: [PATCH 04/13] clean up style & components attributes --- ts/styles/style/attributes.ts | 23 -------------- ts/styles/style/components.ts | 37 ++++++++++++----------- ts/styles/style/index.ts | 34 ++++++++++++++------- ts/tests/stylesTest.ts | 56 +++++++++++++++++++++++++++++++++-- 4 files changed, 97 insertions(+), 53 deletions(-) delete mode 100644 ts/styles/style/attributes.ts diff --git a/ts/styles/style/attributes.ts b/ts/styles/style/attributes.ts deleted file mode 100644 index c6ec627404..0000000000 --- a/ts/styles/style/attributes.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; - -interface IStyleAttributesProperties { - type?: string; - styleId?: string; - default?: string; - customStyle?: string; - val?: string; -} - -export class StyleAttributes extends XmlAttributeComponent { - private _attr: IStyleAttributesProperties; - - constructor(properties: IStyleAttributesProperties) { - super({ - type: "w:type", - styleId: "w:styleId", - default: "w:default", - customStyle: "w:customStyle", - val: "w:val", - }, properties); - } -} diff --git a/ts/styles/style/components.ts b/ts/styles/style/components.ts index 17751bb32a..596a112852 100644 --- a/ts/styles/style/components.ts +++ b/ts/styles/style/components.ts @@ -1,13 +1,22 @@ -import { XmlComponent } from "../../docx/xml-components"; -import { StyleAttributes } from "./attributes"; +import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; + +interface IComponentAttributes { + val: string; +} + +class ComponentAttributes extends XmlAttributeComponent { + private _attr: IComponentAttributes; + + constructor(properties: IComponentAttributes) { + super({val: "w:val"}, properties); + } +} export class Name extends XmlComponent { constructor(value: string) { super("w:name"); - this.root.push(new StyleAttributes({ - val: value, - })); + this.root.push(new ComponentAttributes({val: value})); } } @@ -15,9 +24,7 @@ export class BasedOn extends XmlComponent { constructor(value: string) { super("w:basedOn"); - this.root.push(new StyleAttributes({ - val: value, - })); + this.root.push(new ComponentAttributes({val: value})); } } @@ -25,10 +32,7 @@ export class Next extends XmlComponent { constructor(value: string) { super("w:next"); - this.root.push(new StyleAttributes({ - styleId: "1", - val: value, - })); + this.root.push(new ComponentAttributes({val: value})); } } @@ -36,9 +40,7 @@ export class Link extends XmlComponent { constructor(value: string) { super("w:link"); - this.root.push(new StyleAttributes({ - val: value, - })); + this.root.push(new ComponentAttributes({val: value})); } } @@ -46,9 +48,8 @@ export class UiPriority extends XmlComponent { constructor(value: string) { super("w:uiPriority"); - this.root.push(new StyleAttributes({ - val: value, - })); + // TODO: this value should be a ST_DecimalNumber + this.root.push(new ComponentAttributes({val: value})); } } diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index 6d916a1507..7730c039e3 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -1,15 +1,34 @@ import { ParagraphProperties } from "../../docx/paragraph/properties"; import { RunProperties } from "../../docx/run/properties"; -import { XmlComponent } from "../../docx/xml-components"; +import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; -import { StyleAttributes } from "./attributes"; import { BasedOn, Name, Next, QuickFormat } from "./components"; +export interface IStyleAttributes { + type?: string; + styleId?: string; + default?: boolean; + customStyle?: string; +} + +class StyleAttributes extends XmlAttributeComponent { + private _attr: IStyleAttributes; + + constructor(properties: IStyleAttributes) { + super({ + type: "w:type", + styleId: "w:styleId", + default: "w:default", + customStyle: "w:customStyle", + }, properties); + } +} + export class Style extends XmlComponent { - constructor(attributes: StyleAttributes) { + constructor(attributes: IStyleAttributes) { super("w:style"); - this.root.push(attributes); + this.root.push(new StyleAttributes(attributes)); } public push(styleSegment: XmlComponent): void { @@ -23,12 +42,7 @@ export class ParagraphStyle extends Style { private runProperties: RunProperties; constructor(styleId: string) { - - const attributes = new StyleAttributes({ - type: "paragraph", - styleId: styleId, - }); - super(attributes); + super({type: "paragraph", styleId: styleId}); this.paragraphProperties = new ParagraphProperties(); this.runProperties = new RunProperties(); this.root.push(this.paragraphProperties); diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index 06fc29e645..e448b3e2a1 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -1,5 +1,8 @@ -import { assert } from "chai"; +import { assert, expect } from "chai"; +import { Formatter } from "../export/formatter"; import { Styles } from "../styles"; +import { Style } from "../styles/style"; +import * as components from "../styles/style/components"; describe("Styles", () => { let styles: Styles; @@ -9,10 +12,59 @@ describe("Styles", () => { }); describe("#constructor()", () => { - it("should create styles with correct rootKey", () => { const newJson = JSON.parse(JSON.stringify(styles)); assert.equal(newJson.rootKey, "w:styles"); }); }); }); + +describe("Style", () => { + describe("#constructor()", () => { + it("should set the given properties", () => { + const style = new Style({ + type: "paragraph", + styleId: "myStyleId", + default: true, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId", "w:default": true}}, + ], + }); + }); + }); +}); + +describe("Style components", () => { + it("Name#constructor", () => { + const style = new components.Name("Style Name"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({"w:name": [{_attr: {"w:val": "Style Name"}}]}); + }); + + it("BasedOn#constructor", () => { + const style = new components.BasedOn("otherId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({"w:basedOn": [{_attr: {"w:val": "otherId"}}]}); + }); + + it("Next#constructor", () => { + const style = new components.Next("otherId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({"w:next": [{_attr: {"w:val": "otherId"}}]}); + }); + + it("Link#constructor", () => { + const style = new components.Link("otherId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({"w:link": [{_attr: {"w:val": "otherId"}}]}); + }); + + it("UiPriority#constructor", () => { + const style = new components.UiPriority("123"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({"w:uiPriority": [{_attr: {"w:val": "123"}}]}); + }); +}); From b4dca79d722f6deceb6cabb595366a43a8dc09ff Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 11:09:08 +0100 Subject: [PATCH 05/13] added optional name parameter to style constructor --- ts/styles/style/index.ts | 9 +++++--- ts/tests/stylesTest.ts | 46 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index 7730c039e3..f8e1974374 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -26,9 +26,12 @@ class StyleAttributes extends XmlAttributeComponent { export class Style extends XmlComponent { - constructor(attributes: IStyleAttributes) { + constructor(attributes: IStyleAttributes, name?: string) { super("w:style"); this.root.push(new StyleAttributes(attributes)); + if (name) { + this.root.push(new Name(name)); + } } public push(styleSegment: XmlComponent): void { @@ -41,8 +44,8 @@ export class ParagraphStyle extends Style { private paragraphProperties: ParagraphProperties; private runProperties: RunProperties; - constructor(styleId: string) { - super({type: "paragraph", styleId: styleId}); + constructor(styleId: string, name?: string) { + super({type: "paragraph", styleId: styleId}, name); this.paragraphProperties = new ParagraphProperties(); this.runProperties = new RunProperties(); this.root.push(this.paragraphProperties); diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index e448b3e2a1..562f655d42 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -1,7 +1,7 @@ import { assert, expect } from "chai"; import { Formatter } from "../export/formatter"; import { Styles } from "../styles"; -import { Style } from "../styles/style"; +import { ParagraphStyle, Style } from "../styles/style"; import * as components from "../styles/style/components"; describe("Styles", () => { @@ -34,6 +34,20 @@ describe("Style", () => { ], }); }); + + it("should set the name of the style, if given", () => { + const style = new Style({ + type: "paragraph", + styleId: "myStyleId", + }, "Style Name"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:name": [{_attr: {"w:val": "Style Name"}}]}, + ], + }); + }); }); }); @@ -68,3 +82,33 @@ describe("Style components", () => { expect(tree).to.deep.equal({"w:uiPriority": [{_attr: {"w:val": "123"}}]}); }); }); + + +describe("ParagraphStyle", () => { + describe("#constructor", () => { + it("should set the style type to paragraph and use the given style id", () => { + const style = new ParagraphStyle("myStyleId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + ], + }); + }); + + it("should set the name of the style, if given", () => { + const style = new ParagraphStyle("myStyleId", "Style Name"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:name": [{_attr: {"w:val": "Style Name"}}]}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + ], + }); + }); + }); +}); From 449d1bc2c3294d2147d810af2f8c7f94f9af9542 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 11:23:24 +0100 Subject: [PATCH 06/13] added fluent formatting methods to ParagraphStyle --- ts/styles/style/index.ts | 51 ++++++++++++++-- ts/tests/stylesTest.ts | 125 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 170 insertions(+), 6 deletions(-) diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index f8e1974374..b72b070522 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -1,4 +1,6 @@ +import { Indent } from "../../docx/paragraph/indent"; import { ParagraphProperties } from "../../docx/paragraph/properties"; +import * as formatting from "../../docx/run/formatting"; import { RunProperties } from "../../docx/run/properties"; import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; @@ -66,16 +68,55 @@ export class ParagraphStyle extends Style { public addRunProperty(property: XmlComponent): void { this.runProperties.push(property); } + + public basedOn(parentId: string): ParagraphStyle { + this.root.push(new BasedOn(parentId)); + return this; + } + + public quickFormat(): ParagraphStyle { + this.root.push(new QuickFormat()); + return this; + } + + public next(nextId: string): ParagraphStyle { + this.root.push(new Next(nextId)); + return this; + } + + public size(twips: number): ParagraphStyle { + this.addRunProperty(new formatting.Size(twips)); + return this; + } + + public bold(): ParagraphStyle { + this.addRunProperty(new formatting.Bold()); + return this; + } + + public italics(): ParagraphStyle { + this.addRunProperty(new formatting.Italics()); + return this; + } + + public color(color: string): ParagraphStyle { + this.addRunProperty(new formatting.Color(color)); + return this; + } + + public indent(left: number, hanging?: number): ParagraphStyle { + this.addParagraphProperty(new Indent(left, hanging)); + return this; + } } export class HeadingStyle extends ParagraphStyle { constructor(styleId: string, name: string) { - super(styleId); - this.root.push(new Name(name)); - this.root.push(new BasedOn("Normal")); - this.root.push(new Next("Normal")); - this.root.push(new QuickFormat()); + super(styleId, name); + this.basedOn("Normal"); + this.next("Normal"); + this.quickFormat(); } } diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index 562f655d42..d2fd979b13 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -83,7 +83,6 @@ describe("Style components", () => { }); }); - describe("ParagraphStyle", () => { describe("#constructor", () => { it("should set the style type to paragraph and use the given style id", () => { @@ -111,4 +110,128 @@ describe("ParagraphStyle", () => { }); }); }); + + describe("formatting methods: style attributes", () => { + it("#basedOn", () => { + const style = new ParagraphStyle("myStyleId") + .basedOn("otherId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + {"w:basedOn": [{_attr: {"w:val": "otherId"}}]}, + ], + }); + }); + + it("#quickFormat", () => { + const style = new ParagraphStyle("myStyleId") + .quickFormat(); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + {"w:qFormat": []}, + ], + }); + }); + + it("#next", () => { + const style = new ParagraphStyle("myStyleId") + .next("otherId"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + {"w:next": [{_attr: {"w:val": "otherId"}}]}, + ], + }); + }); + }); + + describe("formatting methods: paragraph properties", () => { + it("#indent", () => { + const style = new ParagraphStyle("myStyleId") + .indent(720); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [ + {_attr: {}}, + {"w:ind": [{_attr: {"w:left": 720}}]}, + ]}, + {"w:rPr": []}, + ], + }); + }); + }); + + describe("formatting methods: run properties", () => { + it("#size", () => { + const style = new ParagraphStyle("myStyleId") + .size(24); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:sz": [{_attr: {"w:val": 24}}]}, + ]}, + ], + }); + }); + + it("#bold", () => { + const style = new ParagraphStyle("myStyleId") + .bold(); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:b": [{_attr: {"w:val": true}}]}, + ]}, + ], + }); + }); + + it("#italics", () => { + const style = new ParagraphStyle("myStyleId") + .italics(); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:i": [{_attr: {"w:val": true}}]}, + ]}, + ], + }); + }); + + it("#color", () => { + const style = new ParagraphStyle("myStyleId") + .color("123456"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:color": [{_attr: {"w:val": "123456"}}]}, + ]}, + ], + }); + }); + }); }); From 20ec9b679ef66b33530258b97bcef4ff18b4aef5 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 12:12:33 +0100 Subject: [PATCH 07/13] added Spacing for paragraphs and ParagraphStyle --- ts/docx/paragraph/index.ts | 6 ++++++ ts/docx/paragraph/spacing.ts | 24 +++++++++++++++++++++++ ts/styles/style/index.ts | 6 ++++++ ts/tests/docx/paragraph/paragraphTests.ts | 17 ++++++++++++++++ ts/tests/docx/paragraph/spacingTest.ts | 24 +++++++++++++++++++++++ ts/tests/stylesTest.ts | 16 +++++++++++++++ 6 files changed, 93 insertions(+) create mode 100644 ts/docx/paragraph/spacing.ts create mode 100644 ts/tests/docx/paragraph/spacingTest.ts diff --git a/ts/docx/paragraph/index.ts b/ts/docx/paragraph/index.ts index 7b82b63434..c2b3c5ef37 100644 --- a/ts/docx/paragraph/index.ts +++ b/ts/docx/paragraph/index.ts @@ -6,6 +6,7 @@ import { ThematicBreak } from "./border"; import { Indent } from "./indent"; import { PageBreak } from "./page-break"; import { ParagraphProperties } from "./properties"; +import { ISpacingProperties, Spacing } from "./spacing"; import { Style } from "./style"; import { LeftTabStop, MaxRightTabStop } from "./tab-stop"; import { NumberProperties } from "./unordered-list"; @@ -128,4 +129,9 @@ export class Paragraph extends XmlComponent { this.properties.push(new Indent(start, hanging)); return this; } + + public spacing(params: ISpacingProperties): Paragraph { + this.properties.push(new Spacing(params)); + return this; + }; } diff --git a/ts/docx/paragraph/spacing.ts b/ts/docx/paragraph/spacing.ts new file mode 100644 index 0000000000..527d62c6d3 --- /dev/null +++ b/ts/docx/paragraph/spacing.ts @@ -0,0 +1,24 @@ +import { XmlAttributeComponent, XmlComponent } from "../xml-components"; + +export interface ISpacingProperties { + after?: number; + before?: number; + line?: number; +} + +class SpacingAttributes extends XmlAttributeComponent { + constructor(properties: ISpacingProperties) { + super({ + after: "w:after", + before: "w:before", + line: "w:line", + }, properties); + } +} + +export class Spacing extends XmlComponent { + constructor(opts: ISpacingProperties) { + super("w:spacing"); + this.root.push(new SpacingAttributes(opts)); + } +} diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index b72b070522..ececdfe6bd 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -1,5 +1,6 @@ import { Indent } from "../../docx/paragraph/indent"; import { ParagraphProperties } from "../../docx/paragraph/properties"; +import { ISpacingProperties, Spacing } from "../../docx/paragraph/spacing"; import * as formatting from "../../docx/run/formatting"; import { RunProperties } from "../../docx/run/properties"; import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; @@ -108,6 +109,11 @@ export class ParagraphStyle extends Style { this.addParagraphProperty(new Indent(left, hanging)); return this; } + + public spacing(params: ISpacingProperties): ParagraphStyle { + this.addParagraphProperty(new Spacing(params)); + return this; + }; } export class HeadingStyle extends ParagraphStyle { diff --git a/ts/tests/docx/paragraph/paragraphTests.ts b/ts/tests/docx/paragraph/paragraphTests.ts index 96b23ac8bd..ad7578abe3 100644 --- a/ts/tests/docx/paragraph/paragraphTests.ts +++ b/ts/tests/docx/paragraph/paragraphTests.ts @@ -188,4 +188,21 @@ describe("Paragraph", () => { }) }); }); + + describe("#spacing", () => { + it("should set the paragraph spacing to the given values", () => { + paragraph.spacing({before: 90, line: 50}); + const tree = new Formatter().format(paragraph); + expect(tree).to.deep.equal({ + "w:p": [ + { + "w:pPr": [ + {"_attr": {}}, + {"w:spacing": [{"_attr": {"w:before": 90, "w:line": 50}}]}, + ], + }, + ] + }) + }); + }); }); diff --git a/ts/tests/docx/paragraph/spacingTest.ts b/ts/tests/docx/paragraph/spacingTest.ts new file mode 100644 index 0000000000..e09e9e9042 --- /dev/null +++ b/ts/tests/docx/paragraph/spacingTest.ts @@ -0,0 +1,24 @@ +import { expect } from "chai"; + +import { Spacing } from "../../../docx/paragraph/spacing"; +import { Formatter } from "../../../export/formatter"; + +describe("Spacing", () => { + describe("#constructor", () => { + it("should set the properties given", () => { + const spacing = new Spacing({before: 100, after: 120, line: 150}); + const tree = new Formatter().format(spacing); + expect(tree).to.deep.equal({ + "w:spacing": [{_attr: {"w:after": 120, "w:before": 100, "w:line": 150}}], + }); + }); + + it("should only set the given properties", () => { + const spacing = new Spacing({before: 100}); + const tree = new Formatter().format(spacing); + expect(tree).to.deep.equal({ + "w:spacing": [{_attr: {"w:before": 100}}], + }); + }); + }); +}); diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index d2fd979b13..9035e1c030 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -171,6 +171,22 @@ describe("ParagraphStyle", () => { ], }); }); + + it("#spacing", () => { + const style = new ParagraphStyle("myStyleId") + .spacing({before: 50, after: 150}); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [ + {_attr: {}}, + {"w:spacing": [{_attr: {"w:before": 50, "w:after": 150}}]}, + ]}, + {"w:rPr": []}, + ], + }); + }); }); describe("formatting methods: run properties", () => { From 3b18b8267a1a2826d40d03d7796003f6fe691564 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 12:25:59 +0100 Subject: [PATCH 08/13] fix paragraphTests.ts linter warnings --- ts/tests/docx/paragraph/paragraphTests.ts | 75 ++++++++++++----------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/ts/tests/docx/paragraph/paragraphTests.ts b/ts/tests/docx/paragraph/paragraphTests.ts index ad7578abe3..fbab274f26 100644 --- a/ts/tests/docx/paragraph/paragraphTests.ts +++ b/ts/tests/docx/paragraph/paragraphTests.ts @@ -1,10 +1,11 @@ +import { assert, expect } from "chai"; + import * as docx from "../../../docx"; import { Formatter } from "../../../export/formatter"; import { Numbering } from "../../../numbering"; -import { assert, expect } from "chai"; -function jsonify(obj: Object) { - let stringifiedJson = JSON.stringify(obj); +function jsonify(obj: object) { + const stringifiedJson = JSON.stringify(obj); return JSON.parse(stringifiedJson); } @@ -18,7 +19,7 @@ describe("Paragraph", () => { describe("#constructor()", () => { it("should create valid JSON", () => { - let stringifiedJson = JSON.stringify(paragraph); + const stringifiedJson = JSON.stringify(paragraph); let newJson; try { @@ -30,8 +31,8 @@ describe("Paragraph", () => { }); it("should create have valid properties", () => { - let stringifiedJson = JSON.stringify(paragraph); - let newJson = JSON.parse(stringifiedJson); + const stringifiedJson = JSON.stringify(paragraph); + const newJson = JSON.parse(stringifiedJson); assert.equal(newJson.root[0].rootKey, "w:pPr"); }); }); @@ -39,7 +40,7 @@ describe("Paragraph", () => { describe("#heading1()", () => { it("should add heading style to JSON", () => { paragraph.heading1(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "Heading1"); }); }); @@ -47,7 +48,7 @@ describe("Paragraph", () => { describe("#heading2()", () => { it("should add heading style to JSON", () => { paragraph.heading2(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "Heading2"); }); @@ -56,7 +57,7 @@ describe("Paragraph", () => { describe("#heading3()", () => { it("should add heading style to JSON", () => { paragraph.heading3(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "Heading3"); }); @@ -65,7 +66,7 @@ describe("Paragraph", () => { describe("#title()", () => { it("should add title style to JSON", () => { paragraph.title(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "Title"); }); @@ -74,7 +75,7 @@ describe("Paragraph", () => { describe("#center()", () => { it("should add center alignment to JSON", () => { paragraph.center(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "center"); }); @@ -83,7 +84,7 @@ describe("Paragraph", () => { describe("#thematicBreak()", () => { it("should add thematic break to JSON", () => { paragraph.thematicBreak(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].rootKey, "w:pBdr"); }); }); @@ -91,13 +92,13 @@ describe("Paragraph", () => { describe("#pageBreak()", () => { it("should add page break to JSON", () => { paragraph.pageBreak(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[1].rootKey, "w:br"); }); it("should add page break with 'page' type", () => { paragraph.pageBreak(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[1].root[0].root.type, "page"); }); }); @@ -105,13 +106,13 @@ describe("Paragraph", () => { describe("#bullet()", () => { it("should add list paragraph style to JSON", () => { paragraph.bullet(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "ListParagraph"); }); it("it should add numbered properties", () => { paragraph.bullet(); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.isDefined(newJson.root[0].root[2]); }); }); @@ -124,7 +125,7 @@ describe("Paragraph", () => { const letterNumbering = numbering.createConcreteNumbering(numberedAbstract); paragraph.setNumbering(letterNumbering, 0); - let newJson = jsonify(paragraph); + const newJson = jsonify(paragraph); assert.equal(newJson.root[0].root[1].root[0].root.val, "ListParagraph"); }); @@ -140,35 +141,35 @@ describe("Paragraph", () => { "w:p": [ { "w:pPr": [ - {"_attr": {}}, - {"w:pStyle": [{"_attr": {"w:val": "ListParagraph"}}]}, + {_attr: {}}, + {"w:pStyle": [{_attr: {"w:val": "ListParagraph"}}]}, { "w:numPr": [ - {"w:ilvl": [{"_attr": {"w:val": 0}}]}, - {"w:numId": [{"_attr": {"w:val": letterNumbering.id}}]} - ] + {"w:ilvl": [{_attr: {"w:val": 0}}]}, + {"w:numId": [{_attr: {"w:val": letterNumbering.id}}]}, + ], }, ], }, - ] - }) + ], + }); }); }); describe("#style", () => { it("should set the paragraph style to the given styleId", () => { - paragraph.style('myFancyStyle'); + paragraph.style("myFancyStyle"); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ { "w:pPr": [ - {"_attr": {}}, - {"w:pStyle": [{"_attr": {"w:val": "myFancyStyle"}}]}, + {_attr: {}}, + {"w:pStyle": [{_attr: {"w:val": "myFancyStyle"}}]}, ], }, - ] - }) + ], + }); }); }); @@ -180,12 +181,12 @@ describe("Paragraph", () => { "w:p": [ { "w:pPr": [ - {"_attr": {}}, - {"w:ind": [{"_attr": {"w:left": 720}}]}, + {_attr: {}}, + {"w:ind": [{_attr: {"w:left": 720}}]}, ], }, - ] - }) + ], + }); }); }); @@ -197,12 +198,12 @@ describe("Paragraph", () => { "w:p": [ { "w:pPr": [ - {"_attr": {}}, - {"w:spacing": [{"_attr": {"w:before": 90, "w:line": 50}}]}, + {_attr: {}}, + {"w:spacing": [{_attr: {"w:before": 90, "w:line": 50}}]}, ], }, - ] - }) + ], + }); }); }); }); From f06094c91d9fbd36db180ac73603b9670c24324c Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 12:36:33 +0100 Subject: [PATCH 09/13] clean up underlineTests linter warnings --- ts/tests/docx/run/underlineTests.ts | 83 +++++++++++++++-------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/ts/tests/docx/run/underlineTests.ts b/ts/tests/docx/run/underlineTests.ts index 4a6e931598..fa40923306 100644 --- a/ts/tests/docx/run/underlineTests.ts +++ b/ts/tests/docx/run/underlineTests.ts @@ -1,9 +1,10 @@ -import * as u from "../../../docx/run/underline"; -import { TextRun } from "../../../docx/run/text-run"; import { assert } from "chai"; -function jsonify(obj: Object) { - let stringifiedJson = JSON.stringify(obj); +import { TextRun } from "../../../docx/run/text-run"; +import * as u from "../../../docx/run/underline"; + +function jsonify(obj: object) { + const stringifiedJson = JSON.stringify(obj); return JSON.parse(stringifiedJson); } @@ -12,8 +13,8 @@ describe("Underline", () => { describe("#constructor()", () => { it("should create a new Underline object with u:u as the rootKey", () => { - let underline = new u.Underline(); - let newJson = jsonify(underline); + const underline = new u.Underline(); + const newJson = jsonify(underline); assert.equal(newJson.rootKey, "w:u"); }); }); @@ -23,14 +24,14 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should have u:u as the rootKey", () => { - let underline = new u.DashDotDotHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashDotDotHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.rootKey, "w:u"); }); it("should put value in attribute", () => { - let underline = new u.DashDotDotHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashDotDotHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dashDotDotHeavy"); }); }); @@ -40,8 +41,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DashDotHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashDotHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dashDotHeavy"); }); }); @@ -51,8 +52,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DashLongHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashLongHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dashLongHeavy"); }); }); @@ -62,8 +63,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DashLongUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashLongUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dashLong"); }); }); @@ -73,8 +74,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DashUnderline(); - let newJson = jsonify(underline); + const underline = new u.DashUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dash"); }); }); @@ -84,8 +85,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DotDashUnderline(); - let newJson = jsonify(underline); + const underline = new u.DotDashUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dotDash"); }); }); @@ -95,8 +96,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DotDotDashUnderline(); - let newJson = jsonify(underline); + const underline = new u.DotDotDashUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dotDotDash"); }); }); @@ -106,8 +107,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DottedHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.DottedHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dottedHeavy"); }); }); @@ -117,8 +118,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DottedUnderline(); - let newJson = jsonify(underline); + const underline = new u.DottedUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "dotted"); }); }); @@ -128,8 +129,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.DoubleUnderline(); - let newJson = jsonify(underline); + const underline = new u.DoubleUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "double"); }); }); @@ -139,8 +140,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.SingleUnderline(); - let newJson = jsonify(underline); + const underline = new u.SingleUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "single"); }); }); @@ -150,8 +151,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.ThickUnderline(); - let newJson = jsonify(underline); + const underline = new u.ThickUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "thick"); }); }); @@ -161,8 +162,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.WaveUnderline(); - let newJson = jsonify(underline); + const underline = new u.WaveUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "wave"); }); }); @@ -172,8 +173,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.WavyDoubleUnderline(); - let newJson = jsonify(underline); + const underline = new u.WavyDoubleUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "wavyDouble"); }); }); @@ -183,8 +184,8 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.WavyHeavyUnderline(); - let newJson = jsonify(underline); + const underline = new u.WavyHeavyUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "wavyHeavy"); }); }); @@ -194,9 +195,9 @@ describe("DashDotDotHeavyUnderline", () => { describe("#constructor()", () => { it("should put value in attribute", () => { - let underline = new u.WordsUnderline(); - let newJson = jsonify(underline); + const underline = new u.WordsUnderline(); + const newJson = jsonify(underline); assert.equal(newJson.root[0].root.val, "words"); }); }); -}); \ No newline at end of file +}); From 766bcabcb8e6ad5ed58f04f24f4bca33ee94819d Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 12:42:19 +0100 Subject: [PATCH 10/13] allow Underline to be called with type and color; fix default --- ts/docx/run/formatting.ts | 1 + ts/docx/run/underline.ts | 4 ++-- ts/tests/docx/run/underlineTests.ts | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ts/docx/run/formatting.ts b/ts/docx/run/formatting.ts index 2471b359cd..ccad4cc349 100644 --- a/ts/docx/run/formatting.ts +++ b/ts/docx/run/formatting.ts @@ -1,4 +1,5 @@ import { Attributes, XmlComponent } from "../xml-components"; +export { Underline } from './underline'; export class Bold extends XmlComponent { diff --git a/ts/docx/run/underline.ts b/ts/docx/run/underline.ts index cac9538a6b..1a6fda2334 100644 --- a/ts/docx/run/underline.ts +++ b/ts/docx/run/underline.ts @@ -13,8 +13,8 @@ abstract class BaseUnderline extends XmlComponent { export class Underline extends BaseUnderline { - constructor() { - super(""); + constructor(underlineType: string = "single", color?: string) { + super(underlineType, color); } } diff --git a/ts/tests/docx/run/underlineTests.ts b/ts/tests/docx/run/underlineTests.ts index fa40923306..2fb34172f5 100644 --- a/ts/tests/docx/run/underlineTests.ts +++ b/ts/tests/docx/run/underlineTests.ts @@ -1,7 +1,8 @@ -import { assert } from "chai"; +import { assert, expect } from "chai"; import { TextRun } from "../../../docx/run/text-run"; import * as u from "../../../docx/run/underline"; +import { Formatter } from "../../../export/formatter"; function jsonify(obj: object) { const stringifiedJson = JSON.stringify(obj); @@ -17,6 +18,22 @@ describe("Underline", () => { const newJson = jsonify(underline); assert.equal(newJson.rootKey, "w:u"); }); + + it("should default to 'single' and no color", () => { + const underline = new u.Underline(); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": [{_attr: {"w:val": "single"}}], + }); + }); + + it("should use the given style type and color", () => { + const underline = new u.Underline("double", "FF00CC"); + const tree = new Formatter().format(underline); + expect(tree).to.deep.equal({ + "w:u": [{_attr: {"w:val": "double", "w:color": "FF00CC"}}], + }); + }); }); }); From ac7799a875d7bb303b32482a32324f7119d00e3a Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 13:19:50 +0100 Subject: [PATCH 11/13] add an #underline method to ParagraphStyle --- ts/styles/style/index.ts | 5 +++++ ts/tests/stylesTest.ts | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/ts/styles/style/index.ts b/ts/styles/style/index.ts index ececdfe6bd..840e55b317 100644 --- a/ts/styles/style/index.ts +++ b/ts/styles/style/index.ts @@ -100,6 +100,11 @@ export class ParagraphStyle extends Style { return this; } + public underline(underlineType?: string, color?: string): ParagraphStyle { + this.addRunProperty(new formatting.Underline(underlineType, color)); + return this; + } + public color(color: string): ParagraphStyle { this.addRunProperty(new formatting.Color(color)); return this; diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index 9035e1c030..22441ec769 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -235,6 +235,53 @@ describe("ParagraphStyle", () => { }); }); + describe("#underline", () => { + it("should set underline to 'single' if no arguments are given", () => { + const style = new ParagraphStyle("myStyleId") + .underline(); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:u": [{_attr: {"w:val": "single"}}]}, + ]}, + ], + }); + }); + + it("should set the style if given", () => { + const style = new ParagraphStyle("myStyleId") + .underline("double"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:u": [{_attr: {"w:val": "double"}}]}, + ]}, + ], + }); + }); + + it("should set the style and color if given", () => { + const style = new ParagraphStyle("myStyleId") + .underline("double", "005599"); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": [ + {"w:u": [{_attr: {"w:val": "double", "w:color": "005599"}}]}, + ]}, + ], + }); + }); + }); + it("#color", () => { const style = new ParagraphStyle("myStyleId") .color("123456"); From d93432678b47435808a24753cf60d2b45e705c71 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 13:27:40 +0100 Subject: [PATCH 12/13] added #createParagraphStyle method to Styles --- ts/styles/index.ts | 7 +++++++ ts/tests/stylesTest.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/ts/styles/index.ts b/ts/styles/index.ts index ee9f2bc784..519ad925e2 100644 --- a/ts/styles/index.ts +++ b/ts/styles/index.ts @@ -4,6 +4,7 @@ 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 { @@ -34,4 +35,10 @@ export class Styles extends XmlComponent { element.clearVariables(); }); } + + public createParagraphStyle(styleId: string, name?: string): ParagraphStyle { + const para = new ParagraphStyle(styleId, name); + this.push(para); + return para; + } } diff --git a/ts/tests/stylesTest.ts b/ts/tests/stylesTest.ts index 22441ec769..0922627528 100644 --- a/ts/tests/stylesTest.ts +++ b/ts/tests/stylesTest.ts @@ -17,6 +17,33 @@ describe("Styles", () => { assert.equal(newJson.rootKey, "w:styles"); }); }); + + describe("#createParagraphStyle", () => { + it("should create a new paragraph style and push it onto this collection", () => { + const ps = styles.createParagraphStyle("pStyleId"); + const tree = new Formatter().format(styles)["w:styles"].filter((x) => !x._attr); + expect(tree).to.deep.equal([{ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "pStyleId"}}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + ], + }]); + }); + + it("should set the paragraph name if given", () => { + const ps = styles.createParagraphStyle("pStyleId", "Paragraph Style"); + const tree = new Formatter().format(styles)["w:styles"].filter((x) => !x._attr); + expect(tree).to.deep.equal([{ + "w:style": [ + {_attr: {"w:type": "paragraph", "w:styleId": "pStyleId"}}, + {"w:name": [{_attr: {"w:val": "Paragraph Style"}}]}, + {"w:pPr": [{_attr: {}}]}, + {"w:rPr": []}, + ], + }]); + }); + }); }); describe("Style", () => { From aac81ffa128e068823be1b83ebe51e8ad5e8db6e Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 9 Mar 2017 13:27:53 +0100 Subject: [PATCH 13/13] add Styles to top-level exports --- ts/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/index.ts b/ts/index.ts index ee4bf88498..5177ddce40 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -1,3 +1,4 @@ export * from "./docx"; export * from "./export"; export { Numbering } from "./numbering"; +export { Styles } from "./styles";