diff --git a/.nycrc b/.nycrc index 41a461385e..2c14e11a79 100644 --- a/.nycrc +++ b/.nycrc @@ -8,7 +8,8 @@ "src/**/*.ts" ], "exclude": [ - "src/**/*.spec.ts" + "src/**/*.spec.ts", + "src/import-dotx/import-dotx.ts" ], "reporter": [ "lcov", diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index a0b7c27a2c..ea0d24a448 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -45,7 +45,7 @@ export class Body extends XmlComponent { private createSectionParagraph(section: SectionProperties): Paragraph { const paragraph = new Paragraph({}); const properties = new ParagraphProperties({}); - properties.addChildElement(section); + properties.push(section); paragraph.addChildElement(properties); return paragraph; } diff --git a/src/file/numbering/abstract-numbering.spec.ts b/src/file/numbering/abstract-numbering.spec.ts index 6548a4436d..ef1df0de4c 100644 --- a/src/file/numbering/abstract-numbering.spec.ts +++ b/src/file/numbering/abstract-numbering.spec.ts @@ -7,6 +7,7 @@ import { AlignmentType, EmphasisMarkType, TabStopPosition } from "../paragraph"; import { UnderlineType } from "../paragraph/run/underline"; import { ShadingType } from "../table"; import { AbstractNumbering } from "./abstract-numbering"; +import { LevelSuffix } from "./level"; describe("AbstractNumbering", () => { it("stores its ID at its .id property", () => { @@ -48,6 +49,20 @@ describe("AbstractNumbering", () => { expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:lvlText": { _attr: { "w:val": "%1)" } } }); }); + it("has suffix", () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 3, + format: "lowerLetter", + text: "%1)", + alignment: AlignmentType.END, + suffix: LevelSuffix.SPACE, + }, + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:suff": { _attr: { "w:val": "space" } } }); + }); + describe("formatting methods: paragraph properties", () => { it("#indent", () => { const abstractNumbering = new AbstractNumbering(1, [ @@ -283,22 +298,41 @@ describe("AbstractNumbering", () => { }); describe("formatting methods: run properties", () => { - it("#size", () => { - const abstractNumbering = new AbstractNumbering(1, [ - { - level: 0, - format: "lowerRoman", - text: "%0.", - style: { - run: { - size: 24, + const sizeTests = [ + { + size: 24, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: true, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: false, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: 26, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 26 } } }], + }, + ]; + sizeTests.forEach(({ size, sizeComplexScript, expected }) => { + it(`#size ${size} cs ${sizeComplexScript}`, () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 0, + format: "lowerRoman", + text: "%0.", + style: { + run: { size, sizeComplexScript }, }, }, - }, - ]); - const tree = new Formatter().format(abstractNumbering); - expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ - "w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }], + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:rPr": expected }); }); }); @@ -478,83 +512,185 @@ describe("AbstractNumbering", () => { }); }); - it("#bold", () => { - const abstractNumbering = new AbstractNumbering(1, [ - { - level: 0, - format: "lowerRoman", - text: "%0.", - style: { - run: { - bold: true, + const boldTests = [ + { + bold: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: false, + expected: [{ "w:b": { _attr: { "w:val": true } } }], + }, + ]; + boldTests.forEach(({ bold, boldComplexScript, expected }) => { + it(`#bold ${bold} cs ${boldComplexScript}`, () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 0, + format: "lowerRoman", + text: "%0.", + style: { + run: { bold, boldComplexScript }, }, }, - }, - ]); - const tree = new Formatter().format(abstractNumbering); - expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ - "w:rPr": [{ "w:b": { _attr: { "w:val": true } } }], + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:rPr": expected }); }); }); - it("#italics", () => { - const abstractNumbering = new AbstractNumbering(1, [ - { - level: 0, - format: "lowerRoman", - text: "%0.", - style: { - run: { - italics: true, + const italicsTests = [ + { + italics: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: false, + expected: [{ "w:i": { _attr: { "w:val": true } } }], + }, + ]; + italicsTests.forEach(({ italics, italicsComplexScript, expected }) => { + it(`#italics ${italics} cs ${italicsComplexScript}`, () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 0, + format: "lowerRoman", + text: "%0.", + style: { + run: { italics, italicsComplexScript }, }, }, - }, - ]); - const tree = new Formatter().format(abstractNumbering); - expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ - "w:rPr": [{ "w:i": { _attr: { "w:val": true } } }], + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:rPr": expected }); }); }); - it("#highlight", () => { - const abstractNumbering = new AbstractNumbering(1, [ - { - level: 0, - format: "lowerRoman", - text: "%0.", - style: { - run: { - highlight: "005599", + const highlightTests = [ + { + highlight: "005599", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: true, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: false, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: "550099", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "550099" } } }], + }, + ]; + highlightTests.forEach(({ highlight, highlightComplexScript, expected }) => { + it(`#highlight ${highlight} cs ${highlightComplexScript}`, () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 0, + format: "lowerRoman", + text: "%0.", + style: { + run: { highlight, highlightComplexScript }, }, }, - }, - ]); - const tree = new Formatter().format(abstractNumbering); - expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ - "w:rPr": [{ "w:highlight": { _attr: { "w:val": "005599" } } }], + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:rPr": expected }); }); }); - it("#shadow", () => { - const abstractNumbering = new AbstractNumbering(1, [ - { - level: 0, - format: "lowerRoman", - text: "%0.", - style: { - run: { - shadow: { - type: ShadingType.PERCENT_10, - fill: "00FFFF", - color: "FF0000", - }, + const shadingTests = [ + { + shadow: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: true, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: false, + expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "00FF00", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "00FF00" } } }, + ], + }, + ]; + shadingTests.forEach(({ shadow, shading, shadingComplexScript, expected }) => { + it("#shadow correctly", () => { + const abstractNumbering = new AbstractNumbering(1, [ + { + level: 0, + format: "lowerRoman", + text: "%0.", + style: { + run: { shadow, shading, shadingComplexScript }, }, }, - }, - ]); - const tree = new Formatter().format(abstractNumbering); - expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ - "w:rPr": [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + ]); + const tree = new Formatter().format(abstractNumbering); + expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({ "w:rPr": expected }); }); }); diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index ddef2b2d78..6a68f0712f 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -1,19 +1,7 @@ import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-components"; -import { - Alignment, - AlignmentType, - Indent, - KeepLines, - KeepNext, - Spacing, - TabStop, - TabStopType, - ThematicBreak, -} from "../paragraph/formatting"; -import { ParagraphProperties } from "../paragraph/properties"; -import * as formatting from "../paragraph/run/formatting"; -import { RunProperties } from "../paragraph/run/properties"; -import { IParagraphStyleOptions2, IRunStyleOptions } from "../styles/style-options"; +import { AlignmentType } from "../paragraph/formatting"; +import { IParagraphStylePropertiesOptions, ParagraphProperties } from "../paragraph/properties"; +import { IRunStylePropertiesOptions, RunProperties } from "../paragraph/run/properties"; interface ILevelAttributesProperties { readonly ilvl?: number; @@ -85,8 +73,8 @@ export interface ILevelsOptions { readonly start?: number; readonly suffix?: LevelSuffix; readonly style?: { - readonly run?: IRunStyleOptions; - readonly paragraph?: IParagraphStyleOptions2; + readonly run?: IRunStylePropertiesOptions; + readonly paragraph?: IParagraphStylePropertiesOptions; }; } @@ -125,8 +113,8 @@ export class LevelBase extends XmlComponent { this.root.push(new LevelText(text)); } - this.paragraphProperties = new ParagraphProperties({}); - this.runProperties = new RunProperties(); + this.paragraphProperties = new ParagraphProperties(style && style.paragraph); + this.runProperties = new RunProperties(style && style.run); this.root.push(this.paragraphProperties); this.root.push(this.runProperties); @@ -134,104 +122,6 @@ export class LevelBase extends XmlComponent { if (suffix) { this.root.push(new Suffix(suffix)); } - - if (style) { - if (style.run) { - if (style.run.size) { - this.runProperties.push(new formatting.Size(style.run.size)); - } - - if (style.run.bold) { - this.runProperties.push(new formatting.Bold()); - } - - if (style.run.italics) { - this.runProperties.push(new formatting.Italics()); - } - - if (style.run.smallCaps) { - this.runProperties.push(new formatting.SmallCaps()); - } - - if (style.run.allCaps) { - this.runProperties.push(new formatting.Caps()); - } - - if (style.run.strike) { - this.runProperties.push(new formatting.Strike()); - } - - if (style.run.doubleStrike) { - this.runProperties.push(new formatting.DoubleStrike()); - } - - if (style.run.subScript) { - this.runProperties.push(new formatting.SubScript()); - } - - if (style.run.superScript) { - this.runProperties.push(new formatting.SuperScript()); - } - - if (style.run.underline) { - this.runProperties.push(new formatting.Underline(style.run.underline.type, style.run.underline.color)); - } - - if (style.run.emphasisMark) { - this.runProperties.push(new formatting.EmphasisMark(style.run.emphasisMark.type)); - } - - if (style.run.color) { - this.runProperties.push(new formatting.Color(style.run.color)); - } - - if (style.run.font) { - this.runProperties.push(new formatting.RunFonts(style.run.font)); - } - - if (style.run.highlight) { - this.runProperties.push(new formatting.Highlight(style.run.highlight)); - } - - if (style.run.shadow) { - this.runProperties.push(new formatting.Shading(style.run.shadow.type, style.run.shadow.fill, style.run.shadow.color)); - } - } - - if (style.paragraph) { - if (style.paragraph.alignment) { - this.paragraphProperties.push(new Alignment(style.paragraph.alignment)); - } - - if (style.paragraph.thematicBreak) { - this.paragraphProperties.push(new ThematicBreak()); - } - - if (style.paragraph.rightTabStop) { - this.paragraphProperties.push(new TabStop(TabStopType.RIGHT, style.paragraph.rightTabStop)); - } - - if (style.paragraph.leftTabStop) { - this.paragraphProperties.push(new TabStop(TabStopType.LEFT, style.paragraph.leftTabStop)); - } - - if (style.paragraph.indent) { - this.paragraphProperties.push(new Indent(style.paragraph.indent)); - } - - if (style.paragraph.spacing) { - this.paragraphProperties.push(new Spacing(style.paragraph.spacing)); - } - - if (style.paragraph.keepNext) { - this.paragraphProperties.push(new KeepNext()); - } - - if (style.paragraph.keepLines) { - this.paragraphProperties.push(new KeepLines()); - } - } - } } } diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index c97d8d34fd..a593f6f0ab 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -3,48 +3,13 @@ import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run" import { IXmlableObject, XmlComponent } from "file/xml-components"; import { File } from "../file"; -import { Alignment, AlignmentType } from "./formatting/alignment"; -import { Bidirectional } from "./formatting/bidirectional"; -import { IBorderOptions, ThematicBreak } from "./formatting/border"; -import { IIndentAttributesProperties, Indent } from "./formatting/indent"; -import { KeepLines, KeepNext } from "./formatting/keep"; -import { PageBreak, PageBreakBefore } from "./formatting/page-break"; -import { ContextualSpacing, ISpacingProperties, Spacing } from "./formatting/spacing"; -import { HeadingLevel, Style } from "./formatting/style"; -import { LeaderType, TabStop, TabStopPosition, TabStopType } from "./formatting/tab-stop"; -import { NumberProperties } from "./formatting/unordered-list"; -import { Bookmark, HyperlinkRef, OutlineLevel } from "./links"; -import { ParagraphProperties } from "./properties"; +import { PageBreak } from "./formatting/page-break"; +import { Bookmark, HyperlinkRef } from "./links"; +import { IParagraphPropertiesOptions, ParagraphProperties } from "./properties"; import { PictureRun, Run, SequentialIdentifier, SymbolRun, TextRun } from "./run"; -export interface IParagraphOptions { +export interface IParagraphOptions extends IParagraphPropertiesOptions { readonly text?: string; - readonly border?: IBorderOptions; - readonly spacing?: ISpacingProperties; - readonly outlineLevel?: number; - readonly alignment?: AlignmentType; - readonly heading?: HeadingLevel; - readonly bidirectional?: boolean; - readonly thematicBreak?: boolean; - readonly pageBreakBefore?: boolean; - readonly contextualSpacing?: boolean; - readonly indent?: IIndentAttributesProperties; - readonly keepLines?: boolean; - readonly keepNext?: boolean; - readonly tabStops?: Array<{ - readonly position: number | TabStopPosition; - readonly type: TabStopType; - readonly leader?: LeaderType; - }>; - readonly style?: string; - readonly bullet?: { - readonly level: number; - }; - readonly numbering?: { - readonly reference: string; - readonly level: number; - readonly custom?: boolean; - }; readonly children?: Array< TextRun | PictureRun | SymbolRun | Bookmark | PageBreak | SequentialIdentifier | FootnoteReferenceRun | HyperlinkRef >; @@ -70,9 +35,7 @@ export class Paragraph extends XmlComponent { return; } - this.properties = new ParagraphProperties({ - border: options.border, - }); + this.properties = new ParagraphProperties(options); this.root.push(this.properties); @@ -80,72 +43,6 @@ export class Paragraph extends XmlComponent { this.root.push(new TextRun(options.text)); } - if (options.spacing) { - this.properties.push(new Spacing(options.spacing)); - } - - if (options.outlineLevel !== undefined) { - this.properties.push(new OutlineLevel(options.outlineLevel)); - } - - if (options.alignment) { - this.properties.push(new Alignment(options.alignment)); - } - - if (options.heading) { - this.properties.push(new Style(options.heading)); - } - - if (options.bidirectional) { - this.properties.push(new Bidirectional()); - } - - if (options.thematicBreak) { - this.properties.push(new ThematicBreak()); - } - - if (options.pageBreakBefore) { - this.properties.push(new PageBreakBefore()); - } - - if (options.contextualSpacing) { - this.properties.push(new ContextualSpacing(options.contextualSpacing)); - } - - if (options.indent) { - this.properties.push(new Indent(options.indent)); - } - - if (options.keepLines) { - this.properties.push(new KeepLines()); - } - - if (options.keepNext) { - this.properties.push(new KeepNext()); - } - - if (options.tabStops) { - for (const tabStop of options.tabStops) { - this.properties.push(new TabStop(tabStop.type, tabStop.position, tabStop.leader)); - } - } - - if (options.style) { - this.properties.push(new Style(options.style)); - } - - if (options.bullet) { - this.properties.push(new Style("ListParagraph")); - this.properties.push(new NumberProperties(1, options.bullet.level)); - } - - if (options.numbering) { - if (!options.numbering.custom) { - this.properties.push(new Style("ListParagraph")); - } - this.properties.push(new NumberProperties(options.numbering.reference, options.numbering.level)); - } - if (options.children) { for (const child of options.children) { if (child instanceof Bookmark) { diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts index 35836ce30e..52afbd1dd8 100644 --- a/src/file/paragraph/properties.ts +++ b/src/file/paragraph/properties.ts @@ -1,19 +1,136 @@ // http://officeopenxml.com/WPparagraphProperties.php import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components"; +import { Alignment, AlignmentType } from "./formatting/alignment"; +import { Bidirectional } from "./formatting/bidirectional"; +import { Border, IBorderOptions, ThematicBreak } from "./formatting/border"; +import { IIndentAttributesProperties, Indent } from "./formatting/indent"; +import { KeepLines, KeepNext } from "./formatting/keep"; +import { PageBreakBefore } from "./formatting/page-break"; +import { ContextualSpacing, ISpacingProperties, Spacing } from "./formatting/spacing"; +import { HeadingLevel, Style } from "./formatting/style"; +import { LeaderType, TabStop, TabStopPosition, TabStopType } from "./formatting/tab-stop"; +import { NumberProperties } from "./formatting/unordered-list"; +import { OutlineLevel } from "./links"; -import { Border, IBorderOptions } from "./formatting/border"; +export interface IParagraphStylePropertiesOptions { + readonly alignment?: AlignmentType; + readonly thematicBreak?: boolean; + readonly contextualSpacing?: boolean; + readonly rightTabStop?: number; + readonly leftTabStop?: number; + readonly indent?: IIndentAttributesProperties; + readonly spacing?: ISpacingProperties; + readonly keepNext?: boolean; + readonly keepLines?: boolean; + readonly outlineLevel?: number; +} -interface IParagraphPropertiesOptions { +export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions { readonly border?: IBorderOptions; + readonly heading?: HeadingLevel; + readonly bidirectional?: boolean; + readonly pageBreakBefore?: boolean; + readonly tabStops?: Array<{ + readonly position: number | TabStopPosition; + readonly type: TabStopType; + readonly leader?: LeaderType; + }>; + readonly style?: string; + readonly bullet?: { + readonly level: number; + }; + readonly numbering?: { + readonly reference: string; + readonly level: number; + readonly custom?: boolean; + }; } export class ParagraphProperties extends IgnoreIfEmptyXmlComponent { - constructor(options: IParagraphPropertiesOptions) { + constructor(options?: IParagraphPropertiesOptions) { super("w:pPr"); + if (!options) { + return; + } + if (options.border) { this.push(new Border(options.border)); } + + if (options.spacing) { + this.push(new Spacing(options.spacing)); + } + + if (options.outlineLevel !== undefined) { + this.push(new OutlineLevel(options.outlineLevel)); + } + + if (options.alignment) { + this.push(new Alignment(options.alignment)); + } + + if (options.heading) { + this.push(new Style(options.heading)); + } + + if (options.bidirectional) { + this.push(new Bidirectional()); + } + + if (options.thematicBreak) { + this.push(new ThematicBreak()); + } + + if (options.pageBreakBefore) { + this.push(new PageBreakBefore()); + } + + if (options.contextualSpacing) { + this.push(new ContextualSpacing(options.contextualSpacing)); + } + + if (options.indent) { + this.push(new Indent(options.indent)); + } + + if (options.keepLines) { + this.push(new KeepLines()); + } + + if (options.keepNext) { + this.push(new KeepNext()); + } + + if (options.tabStops) { + for (const tabStop of options.tabStops) { + this.push(new TabStop(tabStop.type, tabStop.position, tabStop.leader)); + } + } + + if (options.style) { + this.push(new Style(options.style)); + } + + if (options.bullet) { + this.push(new Style("ListParagraph")); + this.push(new NumberProperties(1, options.bullet.level)); + } + + if (options.numbering) { + if (!options.numbering.custom) { + this.push(new Style("ListParagraph")); + } + this.push(new NumberProperties(options.numbering.reference, options.numbering.level)); + } + + if (options.rightTabStop) { + this.push(new TabStop(TabStopType.RIGHT, options.rightTabStop)); + } + + if (options.leftTabStop) { + this.push(new TabStop(TabStopType.LEFT, options.leftTabStop)); + } } public push(item: XmlComponent): void { diff --git a/src/file/paragraph/run/caps.ts b/src/file/paragraph/run/caps.ts deleted file mode 100644 index 0b9fb510be..0000000000 --- a/src/file/paragraph/run/caps.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { XmlComponent } from "file/xml-components"; - -export class SmallCaps extends XmlComponent { - constructor() { - super("w:smallCaps"); - } -} - -export class Caps extends XmlComponent { - constructor() { - super("w:caps"); - } -} diff --git a/src/file/paragraph/run/formatting.ts b/src/file/paragraph/run/formatting.ts index 51b14be5cf..3ef041d7d9 100644 --- a/src/file/paragraph/run/formatting.ts +++ b/src/file/paragraph/run/formatting.ts @@ -115,17 +115,6 @@ export class Imprint extends XmlComponent { } } -/* export class Shadow extends XmlComponent { - constructor() { - super("w:shadow"); - this.root.push( - new Attributes({ - val: true, - }), - ); - } -} */ - export class SmallCaps extends XmlComponent { constructor() { super("w:smallCaps"); diff --git a/src/file/paragraph/run/index.ts b/src/file/paragraph/run/index.ts index 745e33ea5a..3bf62d66cf 100644 --- a/src/file/paragraph/run/index.ts +++ b/src/file/paragraph/run/index.ts @@ -1,4 +1,5 @@ export * from "./run"; +export * from "./properties"; export * from "./text-run"; export * from "./symbol-run"; export * from "./picture-run"; diff --git a/src/file/paragraph/run/properties.ts b/src/file/paragraph/run/properties.ts index 903282b5a6..0bd082afc5 100644 --- a/src/file/paragraph/run/properties.ts +++ b/src/file/paragraph/run/properties.ts @@ -1,8 +1,183 @@ +import { ShadingType } from "file/table"; import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components"; +import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark"; +import { + Bold, + BoldComplexScript, + Caps, + CharacterSpacing, + Color, + DoubleStrike, + Highlight, + HighlightComplexScript, + Italics, + ItalicsComplexScript, + RightToLeft, + Shading, + ShadowComplexScript, + Size, + SizeComplexScript, + SmallCaps, + Strike, +} from "./formatting"; +import { IFontAttributesProperties, RunFonts } from "./run-fonts"; +import { SubScript, SuperScript } from "./script"; +import { Style } from "./style"; +import { Underline, UnderlineType } from "./underline"; + +interface IFontOptions { + readonly name: string; + readonly hint?: string; +} + +export interface IRunStylePropertiesOptions { + readonly bold?: boolean; + readonly boldComplexScript?: boolean; + readonly italics?: boolean; + readonly italicsComplexScript?: boolean; + readonly underline?: { + readonly color?: string; + readonly type?: UnderlineType; + }; + readonly emphasisMark?: { + readonly type?: EmphasisMarkType; + }; + readonly color?: string; + readonly size?: number; + readonly sizeComplexScript?: boolean | number; + readonly rightToLeft?: boolean; + readonly smallCaps?: boolean; + readonly allCaps?: boolean; + readonly strike?: boolean; + readonly doubleStrike?: boolean; + readonly subScript?: boolean; + readonly superScript?: boolean; + readonly font?: string | IFontOptions | IFontAttributesProperties; + readonly highlight?: string; + readonly highlightComplexScript?: boolean | string; + readonly characterSpacing?: number; + readonly shading?: { + readonly type: ShadingType; + readonly fill: string; + readonly color: string; + }; + readonly shadingComplexScript?: boolean | IRunStylePropertiesOptions["shading"]; + readonly shadow?: IRunStylePropertiesOptions["shading"]; +} + +export interface IRunPropertiesOptions extends IRunStylePropertiesOptions { + readonly style?: string; +} export class RunProperties extends IgnoreIfEmptyXmlComponent { - constructor() { + constructor(options?: IRunPropertiesOptions) { super("w:rPr"); + + if (!options) { + return; + } + + if (options.bold) { + this.push(new Bold()); + } + if ((options.boldComplexScript === undefined && options.bold) || options.boldComplexScript) { + this.push(new BoldComplexScript()); + } + + if (options.italics) { + this.push(new Italics()); + } + if ((options.italicsComplexScript === undefined && options.italics) || options.italicsComplexScript) { + this.push(new ItalicsComplexScript()); + } + + if (options.underline) { + this.push(new Underline(options.underline.type, options.underline.color)); + } + + if (options.emphasisMark) { + this.push(new EmphasisMark(options.emphasisMark.type)); + } + + if (options.color) { + this.push(new Color(options.color)); + } + + if (options.size) { + this.push(new Size(options.size)); + } + const szCs = + options.sizeComplexScript === undefined || options.sizeComplexScript === true ? options.size : options.sizeComplexScript; + if (szCs) { + this.push(new SizeComplexScript(szCs)); + } + + if (options.rightToLeft) { + this.push(new RightToLeft()); + } + + if (options.smallCaps) { + this.push(new SmallCaps()); + } + + if (options.allCaps) { + this.push(new Caps()); + } + + if (options.strike) { + this.push(new Strike()); + } + + if (options.doubleStrike) { + this.push(new DoubleStrike()); + } + + if (options.subScript) { + this.push(new SubScript()); + } + + if (options.superScript) { + this.push(new SuperScript()); + } + + if (options.style) { + this.push(new Style(options.style)); + } + + if (options.font) { + if (typeof options.font === "string") { + this.push(new RunFonts(options.font)); + } else if ("name" in options.font) { + this.push(new RunFonts(options.font.name, options.font.hint)); + } else { + this.push(new RunFonts(options.font)); + } + } + + if (options.highlight) { + this.push(new Highlight(options.highlight)); + } + const highlightCs = + options.highlightComplexScript === undefined || options.highlightComplexScript === true + ? options.highlight + : options.highlightComplexScript; + if (highlightCs) { + this.push(new HighlightComplexScript(highlightCs)); + } + + if (options.characterSpacing) { + this.push(new CharacterSpacing(options.characterSpacing)); + } + + const shading = options.shading || options.shadow; + if (shading) { + this.push(new Shading(shading.type, shading.fill, shading.color)); + } + const shdCs = + options.shadingComplexScript === undefined || options.shadingComplexScript === true ? shading : options.shadingComplexScript; + if (shdCs) { + this.push(new ShadowComplexScript(shdCs.type, shdCs.fill, shdCs.color)); + } } public push(item: XmlComponent): void { diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index 32904327d8..40cc7055cd 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -116,7 +116,7 @@ describe("Run", () => { }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ - "w:r": [{ "w:rPr": [{ "w:smallCaps": {} }] }], + "w:r": [{ "w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }] }], }); }); }); @@ -128,7 +128,7 @@ describe("Run", () => { }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ - "w:r": [{ "w:rPr": [{ "w:caps": {} }] }], + "w:r": [{ "w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }] }], }); }); }); diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index 5a26f3352c..8b5fb0ddd3 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -1,69 +1,15 @@ // http://officeopenxml.com/WPtext.php -import { ShadingType } from "file/table"; import { XmlComponent } from "file/xml-components"; import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"; import { FieldInstruction } from "file/table-of-contents/field-instruction"; import { Break } from "./break"; -import { Caps, SmallCaps } from "./caps"; -import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark"; import { Begin, End, Separate } from "./field"; -import { - Bold, - BoldComplexScript, - Color, - DoubleStrike, - Highlight, - HighlightComplexScript, - Italics, - ItalicsComplexScript, - RightToLeft, - Shading, - ShadowComplexScript, - Size, - SizeComplexScript, - Strike, -} from "./formatting"; import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number"; -import { RunProperties } from "./properties"; +import { IRunPropertiesOptions, RunProperties } from "./properties"; import { Text } from "./run-components/text"; -import { IFontAttributesProperties, RunFonts } from "./run-fonts"; -import { SubScript, SuperScript } from "./script"; -import { Style } from "./style"; -import { Underline, UnderlineType } from "./underline"; -interface IFontOptions { - readonly name: string; - readonly hint?: string; -} - -export interface IRunOptions { - readonly bold?: true; - readonly italics?: true; - readonly underline?: { - readonly color?: string; - readonly type?: UnderlineType; - }; - readonly emphasisMark?: { - readonly type?: EmphasisMarkType; - }; - readonly color?: string; - readonly size?: number; - readonly rightToLeft?: boolean; - readonly smallCaps?: boolean; - readonly allCaps?: boolean; - readonly strike?: boolean; - readonly doubleStrike?: boolean; - readonly subScript?: boolean; - readonly superScript?: boolean; - readonly style?: string; - readonly font?: IFontOptions | IFontAttributesProperties; - readonly highlight?: string; - readonly shading?: { - readonly type: ShadingType; - readonly fill: string; - readonly color: string; - }; +export interface IRunOptions extends IRunPropertiesOptions { readonly children?: Array; readonly text?: string; } @@ -79,86 +25,9 @@ export class Run extends XmlComponent { constructor(options: IRunOptions) { super("w:r"); - this.properties = new RunProperties(); + this.properties = new RunProperties(options); this.root.push(this.properties); - if (options.bold) { - this.properties.push(new Bold()); - this.properties.push(new BoldComplexScript()); - } - - if (options.italics) { - this.properties.push(new Italics()); - this.properties.push(new ItalicsComplexScript()); - } - - if (options.underline) { - this.properties.push(new Underline(options.underline.type, options.underline.color)); - } - - if (options.emphasisMark) { - this.properties.push(new EmphasisMark(options.emphasisMark.type)); - } - - if (options.color) { - this.properties.push(new Color(options.color)); - } - - if (options.size) { - this.properties.push(new Size(options.size)); - this.properties.push(new SizeComplexScript(options.size)); - } - - if (options.rightToLeft) { - this.properties.push(new RightToLeft()); - } - - if (options.smallCaps) { - this.properties.push(new SmallCaps()); - } - - if (options.allCaps) { - this.properties.push(new Caps()); - } - - if (options.strike) { - this.properties.push(new Strike()); - } - - if (options.doubleStrike) { - this.properties.push(new DoubleStrike()); - } - - if (options.subScript) { - this.properties.push(new SubScript()); - } - - if (options.superScript) { - this.properties.push(new SuperScript()); - } - - if (options.style) { - this.properties.push(new Style(options.style)); - } - - if (options.font) { - if ("name" in options.font) { - this.properties.push(new RunFonts(options.font.name, options.font.hint)); - } else { - this.properties.push(new RunFonts(options.font)); - } - } - - if (options.highlight) { - this.properties.push(new Highlight(options.highlight)); - this.properties.push(new HighlightComplexScript(options.highlight)); - } - - if (options.shading) { - this.properties.push(new Shading(options.shading.type, options.shading.fill, options.shading.color)); - this.properties.push(new ShadowComplexScript(options.shading.type, options.shading.fill, options.shading.color)); - } - if (options.children) { for (const child of options.children) { if (typeof child === "string") { diff --git a/src/file/styles/defaults/document-defaults.spec.ts b/src/file/styles/defaults/document-defaults.spec.ts new file mode 100644 index 0000000000..79ca9cccf7 --- /dev/null +++ b/src/file/styles/defaults/document-defaults.spec.ts @@ -0,0 +1,45 @@ +import { expect } from "chai"; + +import { DocumentDefaults } from "./document-defaults"; + +import { Formatter } from "export/formatter"; + +describe("DocumentDefaults", () => { + it("#constructor", () => { + const defaults = new DocumentDefaults({ + paragraph: { spacing: { line: 240 } }, + run: { color: "808080" }, + }); + const tree = new Formatter().format(defaults); + expect(tree).to.deep.equal({ + "w:docDefaults": [ + { + "w:rPrDefault": [ + { + "w:rPr": [ + { + "w:color": { _attr: { "w:val": "808080" } }, + }, + ], + }, + ], + }, + { + "w:pPrDefault": [ + { + "w:pPr": [ + { + "w:spacing": { + _attr: { + "w:line": 240, + }, + }, + }, + ], + }, + ], + }, + ], + }); + }); +}); diff --git a/src/file/styles/defaults/document-defaults.ts b/src/file/styles/defaults/document-defaults.ts new file mode 100644 index 0000000000..1f97bb2b07 --- /dev/null +++ b/src/file/styles/defaults/document-defaults.ts @@ -0,0 +1,25 @@ +import { IParagraphStylePropertiesOptions } from "file/paragraph/properties"; +import { IRunStylePropertiesOptions } from "file/paragraph/run/properties"; +import { XmlComponent } from "file/xml-components"; +import { ParagraphPropertiesDefaults } from "./paragraph-properties"; +import { RunPropertiesDefaults } from "./run-properties"; + +export interface IDocumentDefaultsOptions { + readonly paragraph?: IParagraphStylePropertiesOptions; + readonly run?: IRunStylePropertiesOptions; +} + +export class DocumentDefaults extends XmlComponent { + private readonly runPropertiesDefaults: RunPropertiesDefaults; + private readonly paragraphPropertiesDefaults: ParagraphPropertiesDefaults; + + constructor(options?: IDocumentDefaultsOptions) { + super("w:docDefaults"); + + this.runPropertiesDefaults = new RunPropertiesDefaults(options && options.run); + this.paragraphPropertiesDefaults = new ParagraphPropertiesDefaults(options && options.paragraph); + + this.root.push(this.runPropertiesDefaults); + this.root.push(this.paragraphPropertiesDefaults); + } +} diff --git a/src/file/styles/defaults/index.ts b/src/file/styles/defaults/index.ts index 2b6c49e299..986aa6194d 100644 --- a/src/file/styles/defaults/index.ts +++ b/src/file/styles/defaults/index.ts @@ -1,16 +1,3 @@ -import { XmlComponent } from "file/xml-components"; -import { ParagraphPropertiesDefaults } from "./paragraph-properties"; -import { RunPropertiesDefaults } from "./run-properties"; - -export class DocumentDefaults extends XmlComponent { - private readonly runPropertiesDefaults: RunPropertiesDefaults; - private readonly paragraphPropertiesDefaults: ParagraphPropertiesDefaults; - - constructor() { - super("w:docDefaults"); - this.runPropertiesDefaults = new RunPropertiesDefaults(); - this.paragraphPropertiesDefaults = new ParagraphPropertiesDefaults(); - this.root.push(this.runPropertiesDefaults); - this.root.push(this.paragraphPropertiesDefaults); - } -} +export * from "./paragraph-properties"; +export * from "./run-properties"; +export * from "./document-defaults"; diff --git a/src/file/styles/defaults/paragraph-properties.ts b/src/file/styles/defaults/paragraph-properties.ts index c5f2bee86c..cac92575a4 100644 --- a/src/file/styles/defaults/paragraph-properties.ts +++ b/src/file/styles/defaults/paragraph-properties.ts @@ -1,9 +1,9 @@ -import { ParagraphProperties } from "file/paragraph/properties"; +import { IParagraphStylePropertiesOptions, ParagraphProperties } from "file/paragraph/properties"; import { XmlComponent } from "file/xml-components"; export class ParagraphPropertiesDefaults extends XmlComponent { - constructor() { + constructor(options?: IParagraphStylePropertiesOptions) { super("w:pPrDefault"); - this.root.push(new ParagraphProperties({})); + this.root.push(new ParagraphProperties(options)); } } diff --git a/src/file/styles/defaults/run-properties.ts b/src/file/styles/defaults/run-properties.ts index 2228f84de6..f4e594ab99 100644 --- a/src/file/styles/defaults/run-properties.ts +++ b/src/file/styles/defaults/run-properties.ts @@ -1,25 +1,12 @@ -import { Size, SizeComplexScript } from "file/paragraph/run/formatting"; -import { RunProperties } from "file/paragraph/run/properties"; -import { IFontAttributesProperties, RunFonts } from "file/paragraph/run/run-fonts"; +import { IRunStylePropertiesOptions, RunProperties } from "file/paragraph/run/properties"; import { XmlComponent } from "file/xml-components"; export class RunPropertiesDefaults extends XmlComponent { private readonly properties: RunProperties; - constructor() { + constructor(options?: IRunStylePropertiesOptions) { super("w:rPrDefault"); - this.properties = new RunProperties(); + this.properties = new RunProperties(options); this.root.push(this.properties); } - - public size(size: number): RunPropertiesDefaults { - this.properties.push(new Size(size)); - this.properties.push(new SizeComplexScript(size)); - return this; - } - - public font(font: string | IFontAttributesProperties): RunPropertiesDefaults { - this.properties.push(new RunFonts(font)); - return this; - } } diff --git a/src/file/styles/index.ts b/src/file/styles/index.ts index 01ddf2d84e..e18813fbb8 100644 --- a/src/file/styles/index.ts +++ b/src/file/styles/index.ts @@ -1,4 +1,4 @@ export * from "./styles"; export * from "./style/character-style"; export * from "./style/paragraph-style"; -export * from "./style-options"; +export * from "./defaults"; diff --git a/src/file/styles/style-options.ts b/src/file/styles/style-options.ts deleted file mode 100644 index 8ce1e6460b..0000000000 --- a/src/file/styles/style-options.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - AlignmentType, - EmphasisMarkType, - IFontAttributesProperties, - IIndentAttributesProperties, - ISpacingProperties, - UnderlineType, -} from "../paragraph"; -import { ShadingType } from "../table"; - -export interface IRunStyleOptions { - readonly size?: number; - readonly bold?: boolean; - readonly italics?: boolean; - readonly smallCaps?: boolean; - readonly allCaps?: boolean; - readonly strike?: boolean; - readonly doubleStrike?: boolean; - readonly subScript?: boolean; - readonly superScript?: boolean; - readonly underline?: { - readonly type?: UnderlineType; - readonly color?: string; - }; - readonly emphasisMark?: { - readonly type?: EmphasisMarkType; - }; - readonly color?: string; - readonly font?: string | IFontAttributesProperties; - readonly characterSpacing?: number; - readonly highlight?: string; - readonly shadow?: { - readonly type: ShadingType; - readonly fill: string; - readonly color: string; - }; -} - -export interface IParagraphStyleOptions2 { - readonly alignment?: AlignmentType; - readonly thematicBreak?: boolean; - readonly contextualSpacing?: boolean; - readonly rightTabStop?: number; - readonly leftTabStop?: number; - readonly indent?: IIndentAttributesProperties; - readonly spacing?: ISpacingProperties; - readonly keepNext?: boolean; - readonly keepLines?: boolean; - readonly outlineLevel?: number; -} - -// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 -/** - * @ignore - */ -export const WORKAROUND4 = ""; diff --git a/src/file/styles/style/character-style.spec.ts b/src/file/styles/style/character-style.spec.ts index 64c866a8c8..2fddce1c1b 100644 --- a/src/file/styles/style/character-style.spec.ts +++ b/src/file/styles/style/character-style.spec.ts @@ -334,31 +334,52 @@ describe("CharacterStyle", () => { }); describe("formatting methods: run properties", () => { - it("#size", () => { - const style = new CharacterStyle({ - id: "myStyleId", - run: { - size: 24, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], - }, - { - "w:uiPriority": { - _attr: { - "w:val": 99, + const sizeTests = [ + { + size: 24, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: true, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: false, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: 26, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 26 } } }], + }, + ]; + sizeTests.forEach(({ size, sizeComplexScript, expected }) => { + it(`#size ${size} cs ${sizeComplexScript}`, () => { + const style = new CharacterStyle({ + id: "myStyleId", + run: { size, sizeComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, + { + "w:rPr": expected, + }, + { + "w:uiPriority": { + _attr: { + "w:val": 99, + }, }, }, - }, - { - "w:unhideWhenUsed": EMPTY_OBJECT, - }, - ], + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); }); }); @@ -577,59 +598,91 @@ describe("CharacterStyle", () => { }); }); - it("#bold", () => { - const style = new CharacterStyle({ - id: "myStyleId", - run: { - bold: true, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:b": { _attr: { "w:val": true } } }], - }, - { - "w:uiPriority": { - _attr: { - "w:val": 99, + const boldTests = [ + { + bold: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: false, + expected: [{ "w:b": { _attr: { "w:val": true } } }], + }, + ]; + boldTests.forEach(({ bold, boldComplexScript, expected }) => { + it(`#bold ${bold} cs ${boldComplexScript}`, () => { + const style = new CharacterStyle({ + id: "myStyleId", + run: { bold, boldComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, + { + "w:rPr": expected, + }, + { + "w:uiPriority": { + _attr: { + "w:val": 99, + }, }, }, - }, - { - "w:unhideWhenUsed": EMPTY_OBJECT, - }, - ], + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); }); }); - it("#italics", () => { - const style = new CharacterStyle({ - id: "myStyleId", - run: { - italics: true, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:i": { _attr: { "w:val": true } } }], - }, - { - "w:uiPriority": { - _attr: { - "w:val": 99, + const italicsTests = [ + { + italics: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: false, + expected: [{ "w:i": { _attr: { "w:val": true } } }], + }, + ]; + italicsTests.forEach(({ italics, italicsComplexScript, expected }) => { + it(`#italics ${italics} cs ${italicsComplexScript}`, () => { + const style = new CharacterStyle({ + id: "myStyleId", + run: { italics, italicsComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, + { + "w:rPr": expected, + }, + { + "w:uiPriority": { + _attr: { + "w:val": 99, + }, }, }, - }, - { - "w:unhideWhenUsed": EMPTY_OBJECT, - }, - ], + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); }); }); @@ -673,73 +726,141 @@ describe("CharacterStyle", () => { }); }); - it("#highlight", () => { - const style = new CharacterStyle({ - id: "myStyleId", - run: { - highlight: "005599", - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:highlight": { _attr: { "w:val": "005599" } } }], - }, - { - "w:uiPriority": { - _attr: { - "w:val": 99, + const highlightTests = [ + { + highlight: "005599", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: true, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: false, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: "550099", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "550099" } } }], + }, + ]; + highlightTests.forEach(({ highlight, highlightComplexScript, expected }) => { + it(`#highlight ${highlight} cs ${highlightComplexScript}`, () => { + const style = new CharacterStyle({ + id: "myStyleId", + run: { highlight, highlightComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, + { + "w:rPr": expected, + }, + { + "w:uiPriority": { + _attr: { + "w:val": 99, + }, }, }, - }, - { - "w:unhideWhenUsed": EMPTY_OBJECT, - }, - ], + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); }); }); - it("#shadow", () => { - const style = new CharacterStyle({ - id: "myStyleId", - run: { - shadow: { - type: ShadingType.PERCENT_10, - fill: "00FFFF", - color: "FF0000", - }, + const shadingTests = [ + { + shadow: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, - { - "w:rPr": [ - { - "w:shd": { - _attr: { - "w:val": "pct10", - "w:fill": "00FFFF", - "w:color": "FF0000", - }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: true, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: false, + expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "00FF00", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "00FF00" } } }, + ], + }, + ]; + shadingTests.forEach(({ shadow, shading, shadingComplexScript, expected }) => { + it("#shadow correctly", () => { + const style = new CharacterStyle({ + id: "myStyleId", + run: { shadow, shading, shadingComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [ + { _attr: { "w:type": "character", "w:styleId": "myStyleId" } }, + { + "w:rPr": expected, + }, + { + "w:uiPriority": { + _attr: { + "w:val": 99, }, }, - ], - }, - { - "w:uiPriority": { - _attr: { - "w:val": 99, - }, }, - }, - { - "w:unhideWhenUsed": EMPTY_OBJECT, - }, - ], + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); }); }); }); diff --git a/src/file/styles/style/character-style.ts b/src/file/styles/style/character-style.ts index f0d6c24639..0191a0460e 100644 --- a/src/file/styles/style/character-style.ts +++ b/src/file/styles/style/character-style.ts @@ -1,8 +1,4 @@ -import { EmphasisMarkType } from "file/paragraph/run/emphasis-mark"; -import * as formatting from "file/paragraph/run/formatting"; -import { RunProperties } from "file/paragraph/run/properties"; -import { IFontAttributesProperties } from "file/paragraph/run/run-fonts"; -import { UnderlineType } from "file/paragraph/run/underline"; +import { IRunStylePropertiesOptions, RunProperties } from "file/paragraph/run/properties"; import { BasedOn, Link, SemiHidden, UiPriority, UnhideWhenUsed } from "./components"; import { Style } from "./style"; @@ -11,33 +7,7 @@ export interface IBaseCharacterStyleOptions { readonly basedOn?: string; readonly link?: string; readonly semiHidden?: boolean; - readonly run?: { - readonly size?: number; - readonly bold?: boolean; - readonly italics?: boolean; - readonly smallCaps?: boolean; - readonly allCaps?: boolean; - readonly strike?: boolean; - readonly doubleStrike?: boolean; - readonly subScript?: boolean; - readonly superScript?: boolean; - readonly underline?: { - readonly type?: UnderlineType; - readonly color?: string; - }; - readonly emphasisMark?: { - readonly type?: EmphasisMarkType; - }; - readonly color?: string; - readonly font?: string | IFontAttributesProperties; - readonly characterSpacing?: number; - readonly highlight?: string; - readonly shadow?: { - readonly type: string; - readonly fill: string; - readonly color: string; - }; - }; + readonly run?: IRunStylePropertiesOptions; } export interface ICharacterStyleOptions extends IBaseCharacterStyleOptions { @@ -50,7 +20,9 @@ export class CharacterStyle extends Style { constructor(options: ICharacterStyleOptions) { super({ type: "character", styleId: options.id }, options.name); - this.runProperties = new RunProperties(); + + this.runProperties = new RunProperties(options.run); + this.root.push(this.runProperties); this.root.push(new UiPriority(99)); this.root.push(new UnhideWhenUsed()); @@ -66,72 +38,5 @@ export class CharacterStyle extends Style { if (options.semiHidden) { this.root.push(new SemiHidden()); } - - if (options.run) { - if (options.run.size) { - this.runProperties.push(new formatting.Size(options.run.size)); - this.runProperties.push(new formatting.SizeComplexScript(options.run.size)); - } - - if (options.run.bold) { - this.runProperties.push(new formatting.Bold()); - } - - if (options.run.italics) { - this.runProperties.push(new formatting.Italics()); - } - - if (options.run.smallCaps) { - this.runProperties.push(new formatting.SmallCaps()); - } - - if (options.run.allCaps) { - this.runProperties.push(new formatting.Caps()); - } - - if (options.run.strike) { - this.runProperties.push(new formatting.Strike()); - } - - if (options.run.doubleStrike) { - this.runProperties.push(new formatting.DoubleStrike()); - } - - if (options.run.subScript) { - this.runProperties.push(new formatting.SubScript()); - } - - if (options.run.superScript) { - this.runProperties.push(new formatting.SuperScript()); - } - - if (options.run.underline) { - this.runProperties.push(new formatting.Underline(options.run.underline.type, options.run.underline.color)); - } - - if (options.run.emphasisMark) { - this.runProperties.push(new formatting.EmphasisMark(options.run.emphasisMark.type)); - } - - if (options.run.color) { - this.runProperties.push(new formatting.Color(options.run.color)); - } - - if (options.run.font) { - this.runProperties.push(new formatting.RunFonts(options.run.font)); - } - - if (options.run.characterSpacing) { - this.runProperties.push(new formatting.CharacterSpacing(options.run.characterSpacing)); - } - - if (options.run.highlight) { - this.runProperties.push(new formatting.Highlight(options.run.highlight)); - } - - if (options.run.shadow) { - this.runProperties.push(new formatting.Shading(options.run.shadow.type, options.run.shadow.fill, options.run.shadow.color)); - } - } } } diff --git a/src/file/styles/style/paragraph-style.spec.ts b/src/file/styles/style/paragraph-style.spec.ts index 7d01ef87e7..92b798f862 100644 --- a/src/file/styles/style/paragraph-style.spec.ts +++ b/src/file/styles/style/paragraph-style.spec.ts @@ -358,21 +358,37 @@ describe("ParagraphStyle", () => { }); describe("formatting methods: run properties", () => { - it("#size", () => { - const style = new ParagraphStyle({ - id: "myStyleId", - run: { - size: 24, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], - }, - ], + const sizeTests = [ + { + size: 24, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: true, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: false, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }], + }, + { + size: 24, + sizeComplexScript: 26, + expected: [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 26 } } }], + }, + ]; + sizeTests.forEach(({ size, sizeComplexScript, expected }) => { + it(`#size ${size} cs ${sizeComplexScript}`, () => { + const style = new ParagraphStyle({ + id: "myStyleId", + run: { size, sizeComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:rPr": expected }], + }); }); }); @@ -543,89 +559,169 @@ describe("ParagraphStyle", () => { }); }); - it("#bold", () => { - const style = new ParagraphStyle({ - id: "myStyleId", - run: { - bold: true, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:b": { _attr: { "w:val": true } } }], - }, - ], + const boldTests = [ + { + bold: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: true, + expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }], + }, + { + bold: true, + boldComplexScript: false, + expected: [{ "w:b": { _attr: { "w:val": true } } }], + }, + ]; + boldTests.forEach(({ bold, boldComplexScript, expected }) => { + it(`#bold ${bold} cs ${boldComplexScript}`, () => { + const style = new ParagraphStyle({ + id: "myStyleId", + run: { bold, boldComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:rPr": expected }], + }); }); }); - it("#italics", () => { - const style = new ParagraphStyle({ - id: "myStyleId", - run: { - italics: true, - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:i": { _attr: { "w:val": true } } }], - }, - ], + const italicsTests = [ + { + italics: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: true, + expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }], + }, + { + italics: true, + italicsComplexScript: false, + expected: [{ "w:i": { _attr: { "w:val": true } } }], + }, + ]; + italicsTests.forEach(({ italics, italicsComplexScript, expected }) => { + it(`#italics ${italics} cs ${italicsComplexScript}`, () => { + const style = new ParagraphStyle({ + id: "myStyleId", + run: { italics, italicsComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:rPr": expected }], + }); }); }); - it("#highlight", () => { - const style = new ParagraphStyle({ - id: "myStyleId", - run: { - highlight: "005599", - }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { - "w:rPr": [{ "w:highlight": { _attr: { "w:val": "005599" } } }], - }, - ], + const highlightTests = [ + { + highlight: "005599", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: true, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: false, + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }], + }, + { + highlight: "005599", + highlightComplexScript: "550099", + expected: [{ "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { "w:val": "550099" } } }], + }, + ]; + highlightTests.forEach(({ highlight, highlightComplexScript, expected }) => { + it(`#highlight ${highlight} cs ${highlightComplexScript}`, () => { + const style = new ParagraphStyle({ + id: "myStyleId", + run: { highlight, highlightComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:rPr": expected }], + }); }); }); - it("#shadow", () => { - const style = new ParagraphStyle({ - id: "myStyleId", - run: { - shadow: { - type: ShadingType.PERCENT_10, - fill: "00FFFF", - color: "FF0000", - }, + const shadingTests = [ + { + shadow: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", }, - }); - const tree = new Formatter().format(style); - expect(tree).to.deep.equal({ - "w:style": [ - { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { - "w:rPr": [ - { - "w:shd": { - _attr: { - "w:val": "pct10", - "w:fill": "00FFFF", - "w:color": "FF0000", - }, - }, - }, - ], - }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: true, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + ], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: false, + expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + }, + { + shading: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + shadingComplexScript: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "00FF00", + }, + expected: [ + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shdCs": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "00FF00" } } }, + ], + }, + ]; + shadingTests.forEach(({ shadow, shading, shadingComplexScript, expected }) => { + it("#shadow correctly", () => { + const style = new ParagraphStyle({ + id: "myStyleId", + run: { shadow, shading, shadingComplexScript }, + }); + const tree = new Formatter().format(style); + expect(tree).to.deep.equal({ + "w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:rPr": expected }], + }); }); }); diff --git a/src/file/styles/style/paragraph-style.ts b/src/file/styles/style/paragraph-style.ts index 0a53c9251a..635e7b7e2f 100644 --- a/src/file/styles/style/paragraph-style.ts +++ b/src/file/styles/style/paragraph-style.ts @@ -1,19 +1,6 @@ -import { - Alignment, - ContextualSpacing, - Indent, - KeepLines, - KeepNext, - OutlineLevel, - ParagraphProperties, - Spacing, - ThematicBreak, -} from "file/paragraph"; -import { TabStop, TabStopType } from "file/paragraph/formatting"; -import * as formatting from "file/paragraph/run/formatting"; +import { IParagraphStylePropertiesOptions, IRunStylePropertiesOptions, ParagraphProperties } from "file/paragraph"; import { RunProperties } from "file/paragraph/run/properties"; -import { IParagraphStyleOptions2, IRunStyleOptions } from "../style-options"; import { BasedOn, Link, Next, QuickFormat, SemiHidden, UiPriority, UnhideWhenUsed } from "./components"; import { Style } from "./style"; @@ -25,22 +12,25 @@ export interface IBaseParagraphStyleOptions { readonly semiHidden?: boolean; readonly uiPriority?: number; readonly unhideWhenUsed?: boolean; - readonly run?: IRunStyleOptions; - readonly paragraph?: IParagraphStyleOptions2; + readonly paragraph?: IParagraphStylePropertiesOptions; + readonly run?: IRunStylePropertiesOptions; } export interface IParagraphStyleOptions extends IBaseParagraphStyleOptions { readonly id: string; readonly name?: string; } + export class ParagraphStyle extends Style { private readonly paragraphProperties: ParagraphProperties; private readonly runProperties: RunProperties; constructor(options: IParagraphStyleOptions) { super({ type: "paragraph", styleId: options.id }, options.name); - this.paragraphProperties = new ParagraphProperties({}); - this.runProperties = new RunProperties(); + + this.paragraphProperties = new ParagraphProperties(options.paragraph); + this.runProperties = new RunProperties(options.run); + this.root.push(this.paragraphProperties); this.root.push(this.runProperties); @@ -71,114 +61,5 @@ export class ParagraphStyle extends Style { if (options.unhideWhenUsed) { this.root.push(new UnhideWhenUsed()); } - - if (options.run) { - if (options.run.size) { - this.runProperties.push(new formatting.Size(options.run.size)); - this.runProperties.push(new formatting.SizeComplexScript(options.run.size)); - } - - if (options.run.bold) { - this.runProperties.push(new formatting.Bold()); - } - - if (options.run.italics) { - this.runProperties.push(new formatting.Italics()); - } - - if (options.run.smallCaps) { - this.runProperties.push(new formatting.SmallCaps()); - } - - if (options.run.allCaps) { - this.runProperties.push(new formatting.Caps()); - } - - if (options.run.strike) { - this.runProperties.push(new formatting.Strike()); - } - - if (options.run.doubleStrike) { - this.runProperties.push(new formatting.DoubleStrike()); - } - - if (options.run.subScript) { - this.runProperties.push(new formatting.SubScript()); - } - - if (options.run.superScript) { - this.runProperties.push(new formatting.SuperScript()); - } - - if (options.run.underline) { - this.runProperties.push(new formatting.Underline(options.run.underline.type, options.run.underline.color)); - } - - if (options.run.emphasisMark) { - this.runProperties.push(new formatting.EmphasisMark(options.run.emphasisMark.type)); - } - - if (options.run.color) { - this.runProperties.push(new formatting.Color(options.run.color)); - } - - if (options.run.font) { - this.runProperties.push(new formatting.RunFonts(options.run.font)); - } - - if (options.run.characterSpacing) { - this.runProperties.push(new formatting.CharacterSpacing(options.run.characterSpacing)); - } - - if (options.run.highlight) { - this.runProperties.push(new formatting.Highlight(options.run.highlight)); - } - - if (options.run.shadow) { - this.runProperties.push(new formatting.Shading(options.run.shadow.type, options.run.shadow.fill, options.run.shadow.color)); - } - } - - if (options.paragraph) { - if (options.paragraph.alignment) { - this.paragraphProperties.push(new Alignment(options.paragraph.alignment)); - } - - if (options.paragraph.thematicBreak) { - this.paragraphProperties.push(new ThematicBreak()); - } - - if (options.paragraph.contextualSpacing) { - this.paragraphProperties.push(new ContextualSpacing(options.paragraph.contextualSpacing)); - } - - if (options.paragraph.rightTabStop) { - this.paragraphProperties.push(new TabStop(TabStopType.RIGHT, options.paragraph.rightTabStop)); - } - - if (options.paragraph.leftTabStop) { - this.paragraphProperties.push(new TabStop(TabStopType.LEFT, options.paragraph.leftTabStop)); - } - - if (options.paragraph.indent) { - this.paragraphProperties.push(new Indent(options.paragraph.indent)); - } - - if (options.paragraph.spacing) { - this.paragraphProperties.push(new Spacing(options.paragraph.spacing)); - } - - if (options.paragraph.keepNext) { - this.paragraphProperties.push(new KeepNext()); - } - - if (options.paragraph.keepLines) { - this.paragraphProperties.push(new KeepLines()); - } - - if (options.paragraph.outlineLevel) { - this.paragraphProperties.push(new OutlineLevel(options.paragraph.outlineLevel)); - } - } } }