From cb42c74a8d865d67a329af978e36aba52ef3a424 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 12 Jun 2019 01:03:36 +0100 Subject: [PATCH 01/38] Make Paragraph declaritive --- src/export/formatter.spec.ts | 10 +- src/export/packer/packer.spec.ts | 21 +- src/file/document/body/body.ts | 4 +- src/file/document/document.spec.ts | 27 -- src/file/document/document.ts | 6 - src/file/file.spec.ts | 12 +- src/file/file.ts | 4 - src/file/footer-wrapper.spec.ts | 12 +- src/file/footer-wrapper.ts | 6 - src/file/footer/footer.ts | 6 - src/file/footnotes/footnotes.ts | 16 +- src/file/header-wrapper.spec.ts | 12 +- src/file/header-wrapper.ts | 6 - src/file/header/header.ts | 6 - src/file/numbering/level.ts | 12 +- src/file/numbering/numbering.spec.ts | 4 +- src/file/paragraph/formatting/alignment.ts | 7 +- .../paragraph/formatting/border-attributes.ts | 17 + src/file/paragraph/formatting/border.spec.ts | 4 +- src/file/paragraph/formatting/border.ts | 85 ++--- src/file/paragraph/formatting/style.ts | 10 + src/file/paragraph/image.ts | 2 +- .../paragraph/links/outline-level.spec.ts | 8 +- src/file/paragraph/links/outline-level.ts | 6 +- src/file/paragraph/paragraph.spec.ts | 237 ++++++++----- src/file/paragraph/paragraph.ts | 321 ++++++++---------- src/file/paragraph/properties.ts | 18 +- .../styles/defaults/paragraph-properties.ts | 2 +- src/file/styles/style/paragraph-style.spec.ts | 8 +- src/file/styles/style/paragraph-style.ts | 14 +- .../table-of-contents/table-of-contents.ts | 4 +- src/file/table/table-cell/table-cell.ts | 10 +- src/file/table/table.spec.ts | 31 -- 33 files changed, 451 insertions(+), 497 deletions(-) create mode 100644 src/file/paragraph/formatting/border-attributes.ts diff --git a/src/export/formatter.spec.ts b/src/export/formatter.spec.ts index 47d7773529..a76bad29c0 100644 --- a/src/export/formatter.spec.ts +++ b/src/export/formatter.spec.ts @@ -15,23 +15,23 @@ describe("Formatter", () => { describe("#format()", () => { it("should format simple paragraph", () => { - const paragraph = new file.Paragraph(); + const paragraph = new file.Paragraph(""); const newJson = formatter.format(paragraph); assert.isDefined(newJson["w:p"]); }); it("should remove xmlKeys", () => { - const paragraph = new file.Paragraph(); + const paragraph = new file.Paragraph(""); const newJson = formatter.format(paragraph); const stringifiedJson = JSON.stringify(newJson); assert(stringifiedJson.indexOf("xmlKeys") < 0); }); it("should format simple paragraph with bold text", () => { - const paragraph = new file.Paragraph(); + const paragraph = new file.Paragraph(""); paragraph.addRun(new file.TextRun("test").bold()); const newJson = formatter.format(paragraph); - assert.isDefined(newJson["w:p"][0]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]); + assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]); }); it("should format attributes (rsidSect)", () => { @@ -61,7 +61,7 @@ describe("Formatter", () => { }); it("should should change 'p' tag into 'w:p' tag", () => { - const paragraph = new file.Paragraph(); + const paragraph = new file.Paragraph(""); const newJson = formatter.format(paragraph); assert.isDefined(newJson["w:p"]); }); diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index b61165ab46..944b5892e2 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { stub } from "sinon"; -import { File, Paragraph } from "file"; +import { File, HeadingLevel, Paragraph } from "file"; import { Packer } from "./packer"; @@ -17,11 +17,24 @@ describe("Packer", () => { lastModifiedBy: "Dolan Miu", }); const paragraph = new Paragraph("test text"); - const heading = new Paragraph("Hello world").heading1(); + const heading = new Paragraph({ + text: "Hello world", + heading: HeadingLevel.HEADING_1, + }); - file.addParagraph(new Paragraph("title").title()); + file.addParagraph( + new Paragraph({ + text: "title", + heading: HeadingLevel.TITLE, + }), + ); file.addParagraph(heading); - file.addParagraph(new Paragraph("heading 2").heading2()); + file.addParagraph( + new Paragraph({ + text: "heading 2", + heading: HeadingLevel.HEADING_2, + }), + ); file.addParagraph(paragraph); packer = new Packer(); diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index fb8a187645..54d08ef9c5 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -60,8 +60,8 @@ export class Body extends XmlComponent { } private createSectionParagraph(section: SectionProperties): Paragraph { - const paragraph = new Paragraph(); - const properties = new ParagraphProperties(); + const paragraph = new Paragraph({}); + const properties = new ParagraphProperties({}); properties.addChildElement(section); paragraph.addChildElement(properties); return paragraph; diff --git a/src/file/document/document.spec.ts b/src/file/document/document.spec.ts index 111d42efdf..6b20515138 100644 --- a/src/file/document/document.spec.ts +++ b/src/file/document/document.spec.ts @@ -2,7 +2,6 @@ import { assert, expect } from "chai"; import { Formatter } from "export/formatter"; -import { Paragraph } from "../paragraph"; import { Table } from "../table"; import { Document } from "./document"; @@ -31,32 +30,6 @@ describe("Document", () => { }); }); - describe("#createParagraph", () => { - it("should create a new paragraph and append it to body", () => { - const para = document.createParagraph(); - expect(para).to.be.an.instanceof(Paragraph); - const body = new Formatter().format(document)["w:document"][1]["w:body"]; - expect(body) - .to.be.an("array") - .which.has.length.at.least(1); - expect(body[0]).to.have.property("w:p"); - }); - - it("should use the text given to create a run in the paragraph", () => { - const para = document.createParagraph("sample paragraph text"); - expect(para).to.be.an.instanceof(Paragraph); - const body = new Formatter().format(document)["w:document"][1]["w:body"]; - expect(body) - .to.be.an("array") - .which.has.length.at.least(1); - expect(body[0]) - .to.have.property("w:p") - .which.includes({ - "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "sample paragraph text"] }], - }); - }); - }); - describe("#createTable", () => { it("should create a new table and append it to body", () => { const table = document.createTable({ diff --git a/src/file/document/document.ts b/src/file/document/document.ts index e9a0e71c27..8c36c70a84 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -47,12 +47,6 @@ export class Document extends XmlComponent { return this; } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - return para; - } - public addTable(table: Table): Document { this.body.push(table); return this; diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 1ceb87cd85..33a2c09432 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -83,7 +83,7 @@ describe("File", () => { it("should call the underlying document's addParagraph", () => { const file = new File(); const spy = sinon.spy(file.Document, "addParagraph"); - file.addParagraph(new Paragraph()); + file.addParagraph(new Paragraph({})); expect(spy.called).to.equal(true); }); @@ -128,16 +128,6 @@ describe("File", () => { }); }); - describe("#createParagraph", () => { - it("should call the underlying document's createParagraph", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "createParagraph"); - wrapper.createParagraph("test"); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addImage", () => { it("should call the underlying document's addImage", () => { const wrapper = new File(); diff --git a/src/file/file.ts b/src/file/file.ts index f6cf109b94..747077bd36 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -122,10 +122,6 @@ export class File { return this; } - public createParagraph(text?: string): Paragraph { - return this.document.createParagraph(text); - } - public addTable(table: Table): File { this.document.addTable(table); return this; diff --git a/src/file/footer-wrapper.spec.ts b/src/file/footer-wrapper.spec.ts index c7bc5564fa..90f9e71865 100644 --- a/src/file/footer-wrapper.spec.ts +++ b/src/file/footer-wrapper.spec.ts @@ -11,7 +11,7 @@ describe("FooterWrapper", () => { it("should call the underlying footer's addParagraph", () => { const file = new FooterWrapper(new Media(), 1); const spy = sinon.spy(file.Footer, "addParagraph"); - file.addParagraph(new Paragraph()); + file.addParagraph(new Paragraph({})); expect(spy.called).to.equal(true); }); @@ -42,16 +42,6 @@ describe("FooterWrapper", () => { }); }); - describe("#createParagraph", () => { - it("should call the underlying footer's createParagraph", () => { - const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(file.Footer, "addParagraph"); - file.createParagraph(); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addImage", () => { it("should call the underlying footer's addImage", () => { const file = new FooterWrapper(new Media(), 1); diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index 6b55730f9f..b8302dc5ca 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -25,12 +25,6 @@ export class FooterWrapper { this.footer.addParagraph(paragraph); } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - return para; - } - public addTable(table: Table): void { this.footer.addTable(table); } diff --git a/src/file/footer/footer.ts b/src/file/footer/footer.ts index 6934447d83..cbd69a8a3d 100644 --- a/src/file/footer/footer.ts +++ b/src/file/footer/footer.ts @@ -42,12 +42,6 @@ export class Footer extends InitializableXmlComponent { return this; } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - return para; - } - public addTable(table: Table): void { this.root.push(table); } diff --git a/src/file/footnotes/footnotes.ts b/src/file/footnotes/footnotes.ts index 7877eea9a0..1681928afb 100644 --- a/src/file/footnotes/footnotes.ts +++ b/src/file/footnotes/footnotes.ts @@ -38,25 +38,25 @@ export class FootNotes extends XmlComponent { const begin = new Footnote(-1, FootnoteType.SEPERATOR); begin.addParagraph( - new Paragraph() - .spacing({ + new Paragraph({ + spacing: { after: 0, line: 240, lineRule: "auto", - }) - .addRun(new SeperatorRun()), + }, + }).addRun(new SeperatorRun()), ); this.root.push(begin); const spacing = new Footnote(0, FootnoteType.CONTINUATION_SEPERATOR); spacing.addParagraph( - new Paragraph() - .spacing({ + new Paragraph({ + spacing: { after: 0, line: 240, lineRule: "auto", - }) - .addRun(new ContinuationSeperatorRun()), + }, + }).addRun(new ContinuationSeperatorRun()), ); this.root.push(spacing); } diff --git a/src/file/header-wrapper.spec.ts b/src/file/header-wrapper.spec.ts index c457753ced..01e54847ca 100644 --- a/src/file/header-wrapper.spec.ts +++ b/src/file/header-wrapper.spec.ts @@ -11,7 +11,7 @@ describe("HeaderWrapper", () => { it("should call the underlying header's addParagraph", () => { const wrapper = new HeaderWrapper(new Media(), 1); const spy = sinon.spy(wrapper.Header, "addParagraph"); - wrapper.addParagraph(new Paragraph()); + wrapper.addParagraph(new Paragraph({})); expect(spy.called).to.equal(true); }); @@ -42,16 +42,6 @@ describe("HeaderWrapper", () => { }); }); - describe("#createParagraph", () => { - it("should call the underlying header's createParagraph", () => { - const file = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(file.Header, "addParagraph"); - file.createParagraph(); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addImage", () => { it("should call the underlying header's addImage", () => { const file = new HeaderWrapper(new Media(), 1); diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index 878d23bc9e..b06dbb4933 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -25,12 +25,6 @@ export class HeaderWrapper { this.header.addParagraph(paragraph); } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - return para; - } - public addTable(table: Table): void { this.header.addTable(table); } diff --git a/src/file/header/header.ts b/src/file/header/header.ts index a812b1b453..65a89e4943 100644 --- a/src/file/header/header.ts +++ b/src/file/header/header.ts @@ -53,12 +53,6 @@ export class Header extends InitializableXmlComponent { this.root.push(paragraph); } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - return para; - } - public addTable(table: Table): void { this.root.push(table); } diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index 716f313104..bd213cfa6c 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -1,7 +1,7 @@ import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-components"; import { Alignment, - AlignmentOptions, + AlignmentType, Indent, ISpacingProperties, KeepLines, @@ -114,7 +114,7 @@ export class LevelBase extends XmlComponent { this.root.push(new LevelJc(lvlJc)); } - this.paragraphProperties = new ParagraphProperties(); + this.paragraphProperties = new ParagraphProperties({}); this.runProperties = new RunProperties(); this.root.push(this.paragraphProperties); @@ -201,22 +201,22 @@ export class LevelBase extends XmlComponent { // --------------------- Paragraph formatting ------------------------ // public center(): Level { - this.addParagraphProperty(new Alignment(AlignmentOptions.CENTER)); + this.addParagraphProperty(new Alignment(AlignmentType.CENTER)); return this; } public left(): Level { - this.addParagraphProperty(new Alignment(AlignmentOptions.LEFT)); + this.addParagraphProperty(new Alignment(AlignmentType.LEFT)); return this; } public right(): Level { - this.addParagraphProperty(new Alignment(AlignmentOptions.RIGHT)); + this.addParagraphProperty(new Alignment(AlignmentType.RIGHT)); return this; } public justified(): Level { - this.addParagraphProperty(new Alignment(AlignmentOptions.BOTH)); + this.addParagraphProperty(new Alignment(AlignmentType.BOTH)); return this; } diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 3ba39b15f6..ab74e1c39c 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -175,9 +175,9 @@ describe("AbstractNumbering", () => { "w:bottom": { _attr: { "w:color": "auto", - "w:space": "1", + "w:space": 1, "w:val": "single", - "w:sz": "6", + "w:sz": 6, }, }, }, diff --git a/src/file/paragraph/formatting/alignment.ts b/src/file/paragraph/formatting/alignment.ts index 838c1dc700..8acf41ee4b 100644 --- a/src/file/paragraph/formatting/alignment.ts +++ b/src/file/paragraph/formatting/alignment.ts @@ -1,22 +1,23 @@ // http://officeopenxml.com/WPalignment.php import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; -export enum AlignmentOptions { +export enum AlignmentType { START = "start", END = "end", CENTER = "center", BOTH = "both", + JUSTIFIED = "both", DISTRIBUTE = "distribute", LEFT = "left", RIGHT = "right", } -export class AlignmentAttributes extends XmlAttributeComponent<{ readonly val: AlignmentOptions }> { +export class AlignmentAttributes extends XmlAttributeComponent<{ readonly val: AlignmentType }> { protected readonly xmlKeys = { val: "w:val" }; } export class Alignment extends XmlComponent { - constructor(type: AlignmentOptions) { + constructor(type: AlignmentType) { super("w:jc"); this.root.push(new AlignmentAttributes({ val: type })); } diff --git a/src/file/paragraph/formatting/border-attributes.ts b/src/file/paragraph/formatting/border-attributes.ts new file mode 100644 index 0000000000..d389f7adc7 --- /dev/null +++ b/src/file/paragraph/formatting/border-attributes.ts @@ -0,0 +1,17 @@ +import { XmlAttributeComponent } from "file/xml-components"; + +export interface IBorderAttributesProperties { + readonly color: string; + readonly space: number; + readonly val: string; + readonly sz: number; +} + +export class BorderAttributes extends XmlAttributeComponent { + protected readonly xmlKeys = { + val: "w:val", + color: "w:color", + space: "w:space", + sz: "w:sz", + }; +} diff --git a/src/file/paragraph/formatting/border.spec.ts b/src/file/paragraph/formatting/border.spec.ts index d0fda56359..45c65cc620 100644 --- a/src/file/paragraph/formatting/border.spec.ts +++ b/src/file/paragraph/formatting/border.spec.ts @@ -31,9 +31,9 @@ describe("ThematicBreak", () => { const newJson = Utility.jsonify(thematicBreak); const attributes = { color: "auto", - space: "1", + space: 1, val: "single", - sz: "6", + sz: 6, }; assert.equal(JSON.stringify(newJson.root[0].root[0].root), JSON.stringify(attributes)); }); diff --git a/src/file/paragraph/formatting/border.ts b/src/file/paragraph/formatting/border.ts index f37854a3c7..d44bc51c06 100644 --- a/src/file/paragraph/formatting/border.ts +++ b/src/file/paragraph/formatting/border.ts @@ -1,13 +1,30 @@ // http://officeopenxml.com/WPborders.php -import { Attributes, XmlComponent } from "file/xml-components"; +import { XmlComponent } from "file/xml-components"; +import { BorderAttributes } from "./border-attributes"; + +interface IBorderPropertyOptions { + readonly color: string; + readonly space: number; + readonly value: string; + readonly size: number; +} + +export interface IBorderOptions { + readonly top?: IBorderPropertyOptions; + readonly bottom?: IBorderPropertyOptions; + readonly left?: IBorderPropertyOptions; + readonly right?: IBorderPropertyOptions; +} class BorderProperty extends XmlComponent { - public setProperties(color: string, space: string, value: string, size: string): XmlComponent { - const attrs = new Attributes({ - color: color, - space: space, - val: value, - sz: size, + constructor(rootKey: string, options: IBorderPropertyOptions = { color: "auto", space: 1, value: "single", size: 6 }) { + super(rootKey); + + const attrs = new BorderAttributes({ + color: options.color, + space: options.space, + val: options.value, + sz: options.size, }); this.root.push(attrs); @@ -16,48 +33,40 @@ class BorderProperty extends XmlComponent { } export class Border extends XmlComponent { - constructor() { + constructor(options: IBorderOptions) { super("w:pBdr"); - } - public addTopBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { - const top = new BorderProperty("w:top"); - top.setProperties(color, space, value, size); - this.root.push(top); + if (options.top !== undefined) { + const borderProperty = new BorderProperty("w:top", options.top); + this.root.push(borderProperty); + } - return this; - } + if (options.bottom !== undefined) { + const borderProperty = new BorderProperty("w:bottom", options.bottom); + this.root.push(borderProperty); + } - public addBottomBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { - const bottom = new BorderProperty("w:bottom"); - bottom.setProperties(color, space, value, size); - this.root.push(bottom); + if (options.left !== undefined) { + const borderProperty = new BorderProperty("w:left", options.left); + this.root.push(borderProperty); + } - return this; - } - - public addLeftBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { - const left = new BorderProperty("w:left"); - left.setProperties(color, space, value, size); - this.root.push(left); - - return this; - } - - public addRightBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { - const right = new BorderProperty("w:right"); - right.setProperties(color, space, value, size); - this.root.push(right); - - return this; + if (options.right !== undefined) { + const borderProperty = new BorderProperty("w:right", options.right); + this.root.push(borderProperty); + } } } export class ThematicBreak extends XmlComponent { constructor() { super("w:pBdr"); - const bottom = new BorderProperty("w:bottom"); - bottom.setProperties("auto", "1", "single", "6"); + const bottom = new BorderProperty("w:bottom", { + color: "auto", + space: 1, + value: "single", + size: 6, + }); this.root.push(bottom); } } diff --git a/src/file/paragraph/formatting/style.ts b/src/file/paragraph/formatting/style.ts index 30d57eb997..a493e4b025 100644 --- a/src/file/paragraph/formatting/style.ts +++ b/src/file/paragraph/formatting/style.ts @@ -1,5 +1,15 @@ import { Attributes, XmlComponent } from "file/xml-components"; +export enum HeadingLevel { + HEADING_1 = "Heading1", + HEADING_2 = "Heading2", + HEADING_3 = "Heading3", + HEADING_4 = "Heading4", + HEADING_5 = "Heading5", + HEADING_6 = "Heading6", + TITLE = "Title", +} + export class Style extends XmlComponent { public readonly styleId: string; diff --git a/src/file/paragraph/image.ts b/src/file/paragraph/image.ts index 634f76e517..f4adffbdd4 100644 --- a/src/file/paragraph/image.ts +++ b/src/file/paragraph/image.ts @@ -7,7 +7,7 @@ export class ImageParagraph extends Paragraph { private readonly pictureRun: PictureRun; constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { - super(); + super({}); this.pictureRun = new PictureRun(imageData, drawingOptions); this.root.push(this.pictureRun); } diff --git a/src/file/paragraph/links/outline-level.spec.ts b/src/file/paragraph/links/outline-level.spec.ts index 6ba188fd9d..1b7873ea47 100644 --- a/src/file/paragraph/links/outline-level.spec.ts +++ b/src/file/paragraph/links/outline-level.spec.ts @@ -9,15 +9,9 @@ describe("ParagraphOutlineLevel", () => { describe("#constructor()", () => { it("should create an outlineLevel with given value", () => { - outlineLevel = new OutlineLevel("0"); + outlineLevel = new OutlineLevel(0); const newJson = Utility.jsonify(outlineLevel); assert.equal(newJson.root[0].root.val, "0"); }); - - it("should create an outlineLevel with blank val", () => { - outlineLevel = new OutlineLevel(""); - const newJson = Utility.jsonify(outlineLevel); - assert.equal(newJson.root[0].root.val, ""); - }); }); }); diff --git a/src/file/paragraph/links/outline-level.ts b/src/file/paragraph/links/outline-level.ts index 512638bcc7..bb3258a02b 100644 --- a/src/file/paragraph/links/outline-level.ts +++ b/src/file/paragraph/links/outline-level.ts @@ -2,11 +2,9 @@ import { Attributes, XmlComponent } from "file/xml-components"; export class OutlineLevel extends XmlComponent { - public readonly level: string; - - constructor(level: string) { + constructor(public readonly level: number) { super("w:outlineLvl"); - this.level = level; + this.root.push( new Attributes({ val: level, diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index ed9dfbe6c4..91ee616a4e 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -1,22 +1,16 @@ import { assert, expect } from "chai"; import { Formatter } from "export/formatter"; -import * as file from "file"; - -import { Numbering } from "../numbering"; -import { LeaderType } from "./formatting"; - import { EMPTY_OBJECT } from "file/xml-components"; +import { Numbering } from "../numbering"; +import { AlignmentType, HeadingLevel, LeaderType } from "./formatting"; +import { Paragraph } from "./paragraph"; + describe("Paragraph", () => { - let paragraph: file.Paragraph; - - beforeEach(() => { - paragraph = new file.Paragraph(); - }); - describe("#constructor()", () => { it("should create valid JSON", () => { + const paragraph = new Paragraph(""); const stringifiedJson = JSON.stringify(paragraph); try { @@ -28,28 +22,18 @@ describe("Paragraph", () => { }); it("should create have valid properties", () => { + const paragraph = new Paragraph(""); const stringifiedJson = JSON.stringify(paragraph); const newJson = JSON.parse(stringifiedJson); assert.equal(newJson.root[0].rootKey, "w:pPr"); }); }); - describe("#createTextRun", () => { - it("should add a new run to the paragraph and return it", () => { - const run = paragraph.createTextRun("this is a test run"); - expect(run).to.be.instanceof(file.TextRun); - const tree = new Formatter().format(paragraph)["w:p"]; - expect(tree) - .to.be.an("array") - .which.includes({ - "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "this is a test run"] }], - }); - }); - }); - describe("#heading1()", () => { it("should add heading style to JSON", () => { - paragraph.heading1(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_1, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -63,7 +47,9 @@ describe("Paragraph", () => { describe("#heading2()", () => { it("should add heading style to JSON", () => { - paragraph.heading2(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_2, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -77,7 +63,9 @@ describe("Paragraph", () => { describe("#heading3()", () => { it("should add heading style to JSON", () => { - paragraph.heading3(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_3, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -91,7 +79,9 @@ describe("Paragraph", () => { describe("#heading4()", () => { it("should add heading style to JSON", () => { - paragraph.heading4(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_4, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -105,7 +95,9 @@ describe("Paragraph", () => { describe("#heading5()", () => { it("should add heading style to JSON", () => { - paragraph.heading5(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_5, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -119,7 +111,9 @@ describe("Paragraph", () => { describe("#heading6()", () => { it("should add heading style to JSON", () => { - paragraph.heading6(); + const paragraph = new Paragraph({ + heading: HeadingLevel.HEADING_6, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -133,7 +127,9 @@ describe("Paragraph", () => { describe("#title()", () => { it("should add title style to JSON", () => { - paragraph.title(); + const paragraph = new Paragraph({ + heading: HeadingLevel.TITLE, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -147,7 +143,9 @@ describe("Paragraph", () => { describe("#center()", () => { it("should add center alignment to JSON", () => { - paragraph.center(); + const paragraph = new Paragraph({ + alignment: AlignmentType.CENTER, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -161,7 +159,9 @@ describe("Paragraph", () => { describe("#left()", () => { it("should add left alignment to JSON", () => { - paragraph.left(); + const paragraph = new Paragraph({ + alignment: AlignmentType.LEFT, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -175,7 +175,9 @@ describe("Paragraph", () => { describe("#right()", () => { it("should add right alignment to JSON", () => { - paragraph.right(); + const paragraph = new Paragraph({ + alignment: AlignmentType.RIGHT, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -189,7 +191,9 @@ describe("Paragraph", () => { describe("#start()", () => { it("should add start alignment to JSON", () => { - paragraph.start(); + const paragraph = new Paragraph({ + alignment: AlignmentType.START, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -203,7 +207,9 @@ describe("Paragraph", () => { describe("#end()", () => { it("should add end alignment to JSON", () => { - paragraph.end(); + const paragraph = new Paragraph({ + alignment: AlignmentType.END, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -217,7 +223,9 @@ describe("Paragraph", () => { describe("#distribute()", () => { it("should add distribute alignment to JSON", () => { - paragraph.distribute(); + const paragraph = new Paragraph({ + alignment: AlignmentType.DISTRIBUTE, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -231,7 +239,9 @@ describe("Paragraph", () => { describe("#justified()", () => { it("should add justified alignment to JSON", () => { - paragraph.justified(); + const paragraph = new Paragraph({ + alignment: AlignmentType.JUSTIFIED, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -245,7 +255,11 @@ describe("Paragraph", () => { describe("#maxRightTabStop()", () => { it("should add maxRightTabStop to JSON", () => { - paragraph.maxRightTabStop(); + const paragraph = new Paragraph({ + tabStop: { + maxRight: {}, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -272,7 +286,14 @@ describe("Paragraph", () => { describe("#leftTabStop()", () => { it("should add leftTabStop to JSON", () => { - paragraph.leftTabStop(100, LeaderType.HYPHEN); + const paragraph = new Paragraph({ + tabStop: { + left: { + position: 100, + leader: LeaderType.HYPHEN, + }, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -300,7 +321,14 @@ describe("Paragraph", () => { describe("#rightTabStop()", () => { it("should add rightTabStop to JSON", () => { - paragraph.rightTabStop(100, LeaderType.DOT); + const paragraph = new Paragraph({ + tabStop: { + right: { + position: 100, + leader: LeaderType.DOT, + }, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -328,7 +356,14 @@ describe("Paragraph", () => { describe("#centerTabStop()", () => { it("should add centerTabStop to JSON", () => { - paragraph.centerTabStop(100, LeaderType.MIDDLE_DOT); + const paragraph = new Paragraph({ + tabStop: { + center: { + position: 100, + leader: LeaderType.MIDDLE_DOT, + }, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -356,7 +391,9 @@ describe("Paragraph", () => { describe("#contextualSpacing()", () => { it("should add contextualSpacing to JSON, and set 1 if true", () => { - paragraph.contextualSpacing(true); + const paragraph = new Paragraph({ + contextualSpacing: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -366,23 +403,13 @@ describe("Paragraph", () => { ], }); }); - - it("should add contextualSpacing to JSON, and set 0 if false", () => { - paragraph.contextualSpacing(false); - const tree = new Formatter().format(paragraph); - expect(tree).to.deep.equal({ - "w:p": [ - { - "w:pPr": [{ "w:contextualSpacing": { _attr: { "w:val": 0 } } }], - }, - ], - }); - }); }); describe("#thematicBreak()", () => { it("should add thematic break to JSON", () => { - paragraph.thematicBreak(); + const paragraph = new Paragraph({ + thematicBreak: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -395,8 +422,8 @@ describe("Paragraph", () => { _attr: { "w:val": "single", "w:color": "auto", - "w:space": "1", - "w:sz": "6", + "w:space": 1, + "w:sz": 6, }, }, }, @@ -411,9 +438,22 @@ describe("Paragraph", () => { describe("#paragraphBorders()", () => { it("should add a left and right border to a paragraph", () => { - paragraph.createBorder(); - paragraph.Borders.addLeftBorder(); - paragraph.Borders.addRightBorder(); + const paragraph = new Paragraph({ + border: { + left: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + right: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -425,8 +465,8 @@ describe("Paragraph", () => { "w:left": { _attr: { "w:color": "auto", - "w:space": "1", - "w:sz": "6", + "w:space": 1, + "w:sz": 6, "w:val": "single", }, }, @@ -435,8 +475,8 @@ describe("Paragraph", () => { "w:right": { _attr: { "w:color": "auto", - "w:space": "1", - "w:sz": "6", + "w:space": 1, + "w:sz": 6, "w:val": "single", }, }, @@ -452,6 +492,7 @@ describe("Paragraph", () => { describe("#pageBreak()", () => { it("should add page break to JSON", () => { + const paragraph = new Paragraph({}); paragraph.pageBreak(); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ @@ -466,7 +507,9 @@ describe("Paragraph", () => { describe("#pageBreakBefore()", () => { it("should add page break before to JSON", () => { - paragraph.pageBreakBefore(); + const paragraph = new Paragraph({ + pageBreakBefore: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -484,7 +527,11 @@ describe("Paragraph", () => { describe("#bullet()", () => { it("should default to 0 indent level if no bullet was specified", () => { - paragraph.bullet(); + const paragraph = new Paragraph({ + bullet: { + level: 0, + }, + }); const tree = new Formatter().format(paragraph); expect(tree) .to.have.property("w:p") @@ -500,7 +547,11 @@ describe("Paragraph", () => { }); it("should add list paragraph style to JSON", () => { - paragraph.bullet(0); + const paragraph = new Paragraph({ + bullet: { + level: 0, + }, + }); const tree = new Formatter().format(paragraph); expect(tree) .to.have.property("w:p") @@ -516,7 +567,11 @@ describe("Paragraph", () => { }); it("it should add numbered properties", () => { - paragraph.bullet(1); + const paragraph = new Paragraph({ + bullet: { + level: 1, + }, + }); const tree = new Formatter().format(paragraph); expect(tree) .to.have.property("w:p") @@ -539,7 +594,12 @@ describe("Paragraph", () => { numberedAbstract.createLevel(0, "lowerLetter", "%1)", "start"); const letterNumbering = numbering.createConcreteNumbering(numberedAbstract); - paragraph.setNumbering(letterNumbering, 0); + const paragraph = new Paragraph({ + numbering: { + num: letterNumbering, + level: 0, + }, + }); const tree = new Formatter().format(paragraph); expect(tree) .to.have.property("w:p") @@ -560,7 +620,12 @@ describe("Paragraph", () => { numberedAbstract.createLevel(0, "lowerLetter", "%1)", "start"); const letterNumbering = numbering.createConcreteNumbering(numberedAbstract); - paragraph.setNumbering(letterNumbering, 0); + const paragraph = new Paragraph({ + numbering: { + num: letterNumbering, + level: 0, + }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -582,7 +647,9 @@ describe("Paragraph", () => { describe("#style", () => { it("should set the paragraph style to the given styleId", () => { - paragraph.style("myFancyStyle"); + const paragraph = new Paragraph({ + style: "myFancyStyle", + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -596,7 +663,9 @@ describe("Paragraph", () => { describe("#indent", () => { it("should set the paragraph indent to the given values", () => { - paragraph.indent({ left: 720 }); + const paragraph = new Paragraph({ + indent: { left: 720 }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -610,7 +679,9 @@ describe("Paragraph", () => { describe("#spacing", () => { it("should set the paragraph spacing to the given values", () => { - paragraph.spacing({ before: 90, line: 50 }); + const paragraph = new Paragraph({ + spacing: { before: 90, line: 50 }, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ @@ -624,7 +695,9 @@ describe("Paragraph", () => { describe("#keepLines", () => { it("should set the paragraph keepLines sub-component", () => { - paragraph.keepLines(); + const paragraph = new Paragraph({ + keepLines: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [{ "w:pPr": [{ "w:keepLines": EMPTY_OBJECT }] }], @@ -634,7 +707,9 @@ describe("Paragraph", () => { describe("#keepNext", () => { it("should set the paragraph keepNext sub-component", () => { - paragraph.keepNext(); + const paragraph = new Paragraph({ + keepNext: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [{ "w:pPr": [{ "w:keepNext": EMPTY_OBJECT }] }], @@ -644,7 +719,9 @@ describe("Paragraph", () => { describe("#bidirectional", () => { it("set paragraph right to left layout", () => { - paragraph.bidirectional(); + const paragraph = new Paragraph({ + bidirectional: true, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [{ "w:pPr": [{ "w:bidi": EMPTY_OBJECT }] }], @@ -654,12 +731,14 @@ describe("Paragraph", () => { describe("#outlineLevel", () => { it("should set paragraph outline level to the given value", () => { - paragraph.outlineLevel("0"); + const paragraph = new Paragraph({ + outlineLevel: 0, + }); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [ { - "w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": "0" } } }], + "w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": 0 } } }], }, ], }); diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index cfd32322c2..51940a6373 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -4,43 +4,165 @@ import { Image } from "file/media"; import { Num } from "file/numbering/num"; import { XmlComponent } from "file/xml-components"; -import { Alignment, AlignmentOptions } from "./formatting/alignment"; +import { Alignment, AlignmentType } from "./formatting/alignment"; import { Bidirectional } from "./formatting/bidirectional"; -import { Border, ThematicBreak } from "./formatting/border"; +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 { Style } from "./formatting/style"; +import { HeadingLevel, Style } from "./formatting/style"; import { CenterTabStop, LeaderType, LeftTabStop, MaxRightTabStop, RightTabStop } from "./formatting/tab-stop"; import { NumberProperties } from "./formatting/unordered-list"; import { Bookmark, Hyperlink, OutlineLevel } from "./links"; import { ParagraphProperties } from "./properties"; import { PictureRun, Run, SequentialIdentifier, TextRun } from "./run"; +interface ITabStopOptions { + readonly position: number; + readonly leader?: LeaderType; +} + +export interface IParagraphOptions { + readonly text?: string; + readonly border?: IBorderOptions; + readonly spacing?: ISpacingProperties; + readonly runs?: Run[]; + 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 tabStop?: { + readonly left?: ITabStopOptions; + readonly right?: ITabStopOptions; + readonly maxRight?: { + readonly leader?: LeaderType; + }; + readonly center?: ITabStopOptions; + }; + readonly style?: string; + readonly bullet?: { + readonly level: number; + }; + readonly numbering?: { + readonly num: Num; + readonly level: number; + readonly custom?: boolean; + }; +} + export class Paragraph extends XmlComponent { private readonly properties: ParagraphProperties; - constructor(text?: string) { + constructor(options: string | IParagraphOptions) { super("w:p"); - this.properties = new ParagraphProperties(); - this.root.push(this.properties); - if (text !== undefined) { - this.root.push(new TextRun(text)); + + if (typeof options === "string") { + this.properties = new ParagraphProperties({}); + this.root.push(this.properties); + this.root.push(new TextRun(options)); + return; } - } - public get paragraphProperties(): ParagraphProperties { - return this.properties; - } + this.properties = new ParagraphProperties({ + border: options.border, + }); - public get Borders(): Border { - return this.properties.paragraphBorder; - } + this.root.push(this.properties); - public createBorder(): Paragraph { - this.properties.createBorder(); - return this; + if (options.text) { + 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.tabStop) { + if (options.tabStop.left) { + this.properties.push(new LeftTabStop(options.tabStop.left.position, options.tabStop.left.leader)); + } + + if (options.tabStop.right) { + this.properties.push(new RightTabStop(options.tabStop.right.position, options.tabStop.right.leader)); + } + + if (options.tabStop.maxRight) { + this.properties.push(new MaxRightTabStop(options.tabStop.maxRight.leader)); + } + + if (options.tabStop.center) { + this.properties.push(new CenterTabStop(options.tabStop.center.position, options.tabStop.center.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.num.id, options.numbering.level)); + } + + if (options.runs) { + for (const run of options.runs) { + this.root.push(run); + } + } } public addRun(run: Run): Paragraph { @@ -61,12 +183,6 @@ export class Paragraph extends XmlComponent { return this; } - public createTextRun(text: string): TextRun { - const run = new TextRun(text); - this.addRun(run); - return run; - } - public addImage(image: Image): PictureRun { const run = image.Run; this.addRun(run); @@ -74,158 +190,11 @@ export class Paragraph extends XmlComponent { return run; } - public heading1(): Paragraph { - this.properties.push(new Style("Heading1")); - return this; - } - - public heading2(): Paragraph { - this.properties.push(new Style("Heading2")); - return this; - } - - public heading3(): Paragraph { - this.properties.push(new Style("Heading3")); - return this; - } - - public heading4(): Paragraph { - this.properties.push(new Style("Heading4")); - return this; - } - - public heading5(): Paragraph { - this.properties.push(new Style("Heading5")); - return this; - } - - public heading6(): Paragraph { - this.properties.push(new Style("Heading6")); - return this; - } - - public title(): Paragraph { - this.properties.push(new Style("Title")); - return this; - } - - public center(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.CENTER)); - return this; - } - - public left(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.LEFT)); - return this; - } - - public right(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.RIGHT)); - return this; - } - - public start(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.START)); - return this; - } - - public end(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.END)); - return this; - } - - public distribute(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.DISTRIBUTE)); - return this; - } - - public justified(): Paragraph { - this.properties.push(new Alignment(AlignmentOptions.BOTH)); - return this; - } - - public thematicBreak(): Paragraph { - this.properties.push(new ThematicBreak()); - return this; - } - public pageBreak(): Paragraph { this.root.push(new PageBreak()); return this; } - public pageBreakBefore(): Paragraph { - this.properties.push(new PageBreakBefore()); - return this; - } - - public maxRightTabStop(leader?: LeaderType): Paragraph { - this.properties.push(new MaxRightTabStop(leader)); - return this; - } - - public leftTabStop(position: number, leader?: LeaderType): Paragraph { - this.properties.push(new LeftTabStop(position, leader)); - return this; - } - - public rightTabStop(position: number, leader?: LeaderType): Paragraph { - this.properties.push(new RightTabStop(position, leader)); - return this; - } - - public centerTabStop(position: number, leader?: LeaderType): Paragraph { - this.properties.push(new CenterTabStop(position, leader)); - return this; - } - - public bullet(indentLevel: number = 0): Paragraph { - this.properties.push(new Style("ListParagraph")); - this.properties.push(new NumberProperties(1, indentLevel)); - return this; - } - - public setNumbering(numbering: Num, indentLevel: number): Paragraph { - this.properties.push(new Style("ListParagraph")); - this.properties.push(new NumberProperties(numbering.id, indentLevel)); - return this; - } - - public setCustomNumbering(numberId: number, indentLevel: number): Paragraph { - this.properties.push(new NumberProperties(numberId, indentLevel)); - return this; - } - - public style(styleId: string): Paragraph { - this.properties.push(new Style(styleId)); - return this; - } - - public indent(attrs: IIndentAttributesProperties): Paragraph { - this.properties.push(new Indent(attrs)); - return this; - } - - public spacing(params: ISpacingProperties): Paragraph { - this.properties.push(new Spacing(params)); - return this; - } - - public contextualSpacing(value: boolean): Paragraph { - this.properties.push(new ContextualSpacing(value)); - return this; - } - - public keepNext(): Paragraph { - this.properties.push(new KeepNext()); - return this; - } - - public keepLines(): Paragraph { - this.properties.push(new KeepLines()); - return this; - } - public referenceFootnote(id: number): Paragraph { this.root.push(new FootnoteReferenceRun(id)); return this; @@ -236,18 +205,8 @@ export class Paragraph extends XmlComponent { return this; } - public bidirectional(): Paragraph { - this.properties.push(new Bidirectional()); - return this; - } - public addSequentialIdentifier(identifier: string): Paragraph { this.root.push(new SequentialIdentifier(identifier)); return this; } - - public outlineLevel(level: string): Paragraph { - this.properties.push(new OutlineLevel(level)); - return this; - } } diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts index 188960145c..35836ce30e 100644 --- a/src/file/paragraph/properties.ts +++ b/src/file/paragraph/properties.ts @@ -1,17 +1,19 @@ // http://officeopenxml.com/WPparagraphProperties.php import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components"; -import { Border } from "./formatting/border"; + +import { Border, IBorderOptions } from "./formatting/border"; + +interface IParagraphPropertiesOptions { + readonly border?: IBorderOptions; +} export class ParagraphProperties extends IgnoreIfEmptyXmlComponent { - public readonly paragraphBorder: Border; - - constructor() { + constructor(options: IParagraphPropertiesOptions) { super("w:pPr"); - this.paragraphBorder = new Border(); - } - public createBorder(): void { - this.push(this.paragraphBorder); + if (options.border) { + this.push(new Border(options.border)); + } } public push(item: XmlComponent): void { diff --git a/src/file/styles/defaults/paragraph-properties.ts b/src/file/styles/defaults/paragraph-properties.ts index 1ab3b623d6..c5f2bee86c 100644 --- a/src/file/styles/defaults/paragraph-properties.ts +++ b/src/file/styles/defaults/paragraph-properties.ts @@ -4,6 +4,6 @@ import { XmlComponent } from "file/xml-components"; export class ParagraphPropertiesDefaults extends XmlComponent { constructor() { super("w:pPrDefault"); - this.root.push(new ParagraphProperties()); + this.root.push(new ParagraphProperties({})); } } diff --git a/src/file/styles/style/paragraph-style.spec.ts b/src/file/styles/style/paragraph-style.spec.ts index 41ef0fddab..47e447abfd 100644 --- a/src/file/styles/style/paragraph-style.spec.ts +++ b/src/file/styles/style/paragraph-style.spec.ts @@ -166,9 +166,9 @@ describe("ParagraphStyle", () => { "w:bottom": { _attr: { "w:color": "auto", - "w:space": "1", + "w:space": 1, "w:val": "single", - "w:sz": "6", + "w:sz": 6, }, }, }, @@ -231,12 +231,12 @@ describe("ParagraphStyle", () => { }); it("#outlineLevel", () => { - const style = new ParagraphStyle("myStyleId").outlineLevel("1"); + const style = new ParagraphStyle("myStyleId").outlineLevel(1); const tree = new Formatter().format(style); expect(tree).to.deep.equal({ "w:style": [ { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, - { "w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": "1" } } }] }, + { "w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": 1 } } }] }, ], }); }); diff --git a/src/file/styles/style/paragraph-style.ts b/src/file/styles/style/paragraph-style.ts index d231c58f33..46e02155be 100644 --- a/src/file/styles/style/paragraph-style.ts +++ b/src/file/styles/style/paragraph-style.ts @@ -1,6 +1,6 @@ import { Alignment, - AlignmentOptions, + AlignmentType, Indent, ISpacingProperties, KeepLines, @@ -24,7 +24,7 @@ export class ParagraphStyle extends Style { constructor(styleId: string, name?: string) { super({ type: "paragraph", styleId: styleId }, name); - this.paragraphProperties = new ParagraphProperties(); + this.paragraphProperties = new ParagraphProperties({}); this.runProperties = new RunProperties(); this.root.push(this.paragraphProperties); this.root.push(this.runProperties); @@ -35,7 +35,7 @@ export class ParagraphStyle extends Style { return this; } - public outlineLevel(level: string): ParagraphStyle { + public outlineLevel(level: number): ParagraphStyle { this.paragraphProperties.push(new OutlineLevel(level)); return this; } @@ -117,19 +117,19 @@ export class ParagraphStyle extends Style { // --------------------- Paragraph formatting ------------------------ // public center(): ParagraphStyle { - return this.addParagraphProperty(new Alignment(AlignmentOptions.CENTER)); + return this.addParagraphProperty(new Alignment(AlignmentType.CENTER)); } public left(): ParagraphStyle { - return this.addParagraphProperty(new Alignment(AlignmentOptions.LEFT)); + return this.addParagraphProperty(new Alignment(AlignmentType.LEFT)); } public right(): ParagraphStyle { - return this.addParagraphProperty(new Alignment(AlignmentOptions.RIGHT)); + return this.addParagraphProperty(new Alignment(AlignmentType.RIGHT)); } public justified(): ParagraphStyle { - return this.addParagraphProperty(new Alignment(AlignmentOptions.BOTH)); + return this.addParagraphProperty(new Alignment(AlignmentType.BOTH)); } public thematicBreak(): ParagraphStyle { diff --git a/src/file/table-of-contents/table-of-contents.ts b/src/file/table-of-contents/table-of-contents.ts index 7b1ff0f66d..6b2c69e1bf 100644 --- a/src/file/table-of-contents/table-of-contents.ts +++ b/src/file/table-of-contents/table-of-contents.ts @@ -16,7 +16,7 @@ export class TableOfContents extends XmlComponent { const content = new StructuredDocumentTagContent(); - const beginParagraph = new Paragraph(); + const beginParagraph = new Paragraph({}); const beginRun = new Run(); beginRun.addChildElement(new Begin(true)); beginRun.addChildElement(new FieldInstruction(properties)); @@ -24,7 +24,7 @@ export class TableOfContents extends XmlComponent { beginParagraph.addRun(beginRun); content.addChildElement(beginParagraph); - const endParagraph = new Paragraph(); + const endParagraph = new Paragraph({}); const endRun = new Run(); endRun.addChildElement(new End()); endParagraph.addRun(endRun); diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts index a3c8b427e1..99acef0b31 100644 --- a/src/file/table/table-cell/table-cell.ts +++ b/src/file/table/table-cell/table-cell.ts @@ -31,18 +31,12 @@ export class TableCell extends XmlComponent { public prepForXml(): IXmlableObject | undefined { // Cells must end with a paragraph if (!(this.root[this.root.length - 1] instanceof Paragraph)) { - this.createParagraph(); + const para = new Paragraph({}); + this.addParagraph(para); } return super.prepForXml(); } - public createParagraph(text?: string): Paragraph { - const para = new Paragraph(text); - this.addParagraph(para); - - return para; - } - public setVerticalAlign(type: VerticalAlign): TableCell { this.properties.setVerticalAlign(type); diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index 0407b85718..de814ace20 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -341,37 +341,6 @@ describe("Table", () => { }); }); }); - - describe("#createParagraph", () => { - it("inserts a new paragraph in the cell", () => { - const table = new Table({ - rows: 1, - columns: 1, - }); - const para = table.getCell(0, 0).createParagraph("Test paragraph"); - expect(para).to.be.an.instanceof(Paragraph); - const tree = new Formatter().format(table); - expect(tree) - .to.have.property("w:tbl") - .which.is.an("array"); - const row = tree["w:tbl"].find((x) => x["w:tr"]); - expect(row).not.to.be.undefined; - expect(row["w:tr"]) - .to.be.an("array") - .which.has.length.at.least(1); - expect(row["w:tr"].find((x) => x["w:tc"])).to.deep.equal({ - "w:tc": [ - { - "w:p": [ - { - "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "Test paragraph"] }], - }, - ], - }, - ], - }); - }); - }); }); describe("#float", () => { From 5497dabaf957c2a801ac16b390c7cda1b94febb7 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 13 Jun 2019 01:07:00 +0100 Subject: [PATCH 02/38] Deprecate createParagraph in all demos --- demo/demo10.ts | 57 ++++++++++++++++++++++++--------- demo/demo11.ts | 85 ++++++++++++++++++++++++++++++++++++++++---------- demo/demo13.ts | 22 ++++++++----- demo/demo14.ts | 20 +++++++++--- demo/demo15.ts | 5 ++- demo/demo16.ts | 18 +++++------ demo/demo2.ts | 62 +++++++++++++++++++++++++----------- demo/demo21.ts | 20 ++++++------ demo/demo27.ts | 30 ++++++++++++------ demo/demo32.ts | 18 ++++++++--- demo/demo36.ts | 1 - demo/demo37.ts | 4 +-- demo/demo38.ts | 14 ++++----- demo/demo39.ts | 30 ++++++++++-------- demo/demo6.ts | 11 ++++--- demo/demo8.ts | 8 ++--- demo/demo9.ts | 4 +-- 17 files changed, 284 insertions(+), 125 deletions(-) diff --git a/demo/demo10.ts b/demo/demo10.ts index 7dcc1befab..5cb04d1cdb 100644 --- a/demo/demo10.ts +++ b/demo/demo10.ts @@ -1,7 +1,7 @@ // Generate a CV // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build"; // tslint:disable:no-shadowed-variable @@ -135,7 +135,12 @@ class DocumentCreator { const skills = data[2] as object[]; const achivements = data[3] as object[]; const document = new Document(); - document.addParagraph(new Paragraph("Dolan Miu").title()); + document.addParagraph( + new Paragraph({ + text: "Dolan Miu", + heading: HeadingLevel.TITLE, + }), + ); document.addParagraph(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); document.addParagraph(this.createHeading("Education")); @@ -194,15 +199,18 @@ class DocumentCreator { ); document.addParagraph(new Paragraph("More references upon request")); document.addParagraph( - new Paragraph( - "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", - ).center(), + new Paragraph({ + text: "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", + alignment: AlignmentType.CENTER, + }), ); return document; } public createContactInfo(phoneNumber: string, profileUrl: string, email: string): Paragraph { - const paragraph = new Paragraph().center(); + const paragraph = new Paragraph({ + alignment: AlignmentType.CENTER, + }); const contactInfo = new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`); const address = new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(); @@ -213,15 +221,26 @@ class DocumentCreator { } public createHeading(text: string): Paragraph { - return new Paragraph(text).heading1().thematicBreak(); + return new Paragraph({ + text: text, + heading: HeadingLevel.HEADING_1, + thematicBreak: true, + }); } public createSubHeading(text: string): Paragraph { - return new Paragraph(text).heading2(); + return new Paragraph({ + text: text, + heading: HeadingLevel.HEADING_2, + }); } public createInstitutionHeader(institutionName: string, dateText: string): Paragraph { - const paragraph = new Paragraph().maxRightTabStop(); + const paragraph = new Paragraph({ + tabStop: { + maxRight: {}, + }, + }); const institution = new TextRun(institutionName).bold(); const date = new TextRun(dateText).tab().bold(); @@ -232,7 +251,7 @@ class DocumentCreator { } public createRoleText(roleText: string): Paragraph { - const paragraph = new Paragraph(); + const paragraph = new Paragraph({}); const role = new TextRun(roleText).italics(); paragraph.addRun(role); @@ -241,12 +260,17 @@ class DocumentCreator { } public createBullet(text: string): Paragraph { - return new Paragraph(text).bullet(); + return new Paragraph({ + text: text, + bullet: { + level: 0, + }, + }); } // tslint:disable-next-line:no-any public createSkillList(skills: any[]): Paragraph { - const paragraph = new Paragraph(); + const paragraph = new Paragraph({}); const skillConcat = skills.map((skill) => skill.name).join(", ") + "."; paragraph.addRun(new TextRun(skillConcat)); @@ -259,7 +283,12 @@ class DocumentCreator { const arr: Paragraph[] = []; for (const achievement of achivements) { - const paragraph = new Paragraph(achievement.name).bullet(); + const paragraph = new Paragraph({ + text: achievement.name, + bullet: { + level: 0, + }, + }); arr.push(paragraph); } @@ -267,7 +296,7 @@ class DocumentCreator { } public createInterests(interests: string): Paragraph { - const paragraph = new Paragraph(); + const paragraph = new Paragraph({}); paragraph.addRun(new TextRun(interests)); return paragraph; diff --git a/demo/demo11.ts b/demo/demo11.ts index 2b2e183c32..40c7fe5380 100644 --- a/demo/demo11.ts +++ b/demo/demo11.ts @@ -1,7 +1,7 @@ // Setting styles with JavaScript configuration // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, Table } from "../build"; +import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, Table } from "../build"; const doc = new Document(undefined, { top: 700, @@ -84,27 +84,75 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") .basedOn("Normal"); doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.createParagraph("HEADING") - .heading1() - .center(); +doc.addParagraph( + new Paragraph({ + text: "HEADING", + heading: HeadingLevel.HEADING_1, + alignment: AlignmentType.CENTER, + }), +); -doc.Footer.createParagraph("1") - .style("normalPara") - .right(); +doc.Footer.addParagraph( + new Paragraph({ + text: "1", + style: "normalPara", + alignment: AlignmentType.RIGHT, + }), +); -doc.createParagraph("Ref. :").style("normalPara"); -doc.createParagraph("Date :").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "Ref. :", + style: "normalPara", + }), +); +doc.addParagraph( + new Paragraph({ + text: "Date :", + style: "normalPara", + }), +); -doc.createParagraph("To,").style("normalPara"); -doc.createParagraph("The Superindenting Engineer,(O &M)").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "To,", + style: "normalPara", + }), +); +doc.addParagraph( + new Paragraph({ + text: "The Superindenting Engineer,(O &M)", + style: "normalPara", + }), +); -doc.createParagraph("Sub : ").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "Sub : ", + style: "normalPara", + }), +); -doc.createParagraph("Ref. : ").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "Ref. : ", + style: "normalPara", + }), +); -doc.createParagraph("Sir,").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "Sir,", + style: "normalPara", + }), +); -doc.createParagraph("BRIEF DESCRIPTION").style("normalPara"); +doc.addParagraph( + new Paragraph({ + text: "BRIEF DESCRIPTION", + style: "normalPara", + }), +); const table = new Table({ rows: 4, @@ -130,7 +178,12 @@ const arrboth = [ arrboth.forEach((item) => { doc.createImage(fs.readFileSync(item.image)); - doc.createParagraph(item.comment).style("normalPara2"); + doc.addParagraph( + new Paragraph({ + text: item.comment, + style: "normalPara2", + }), + ); }); const packer = new Packer(); diff --git a/demo/demo13.ts b/demo/demo13.ts index b80b9fdc22..cd0111deb4 100644 --- a/demo/demo13.ts +++ b/demo/demo13.ts @@ -1,7 +1,7 @@ // This example shows 3 styles using XML styles // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph } from "../build"; const styles = fs.readFileSync("./demo/assets/custom-styles.xml", "utf-8"); const doc = new Document({ @@ -9,16 +9,24 @@ const doc = new Document({ externalStyles: styles, }); -doc.createParagraph("Cool Heading Text").heading1(); +doc.addParagraph(new Paragraph({ + text: "Cool Heading Text", + heading: HeadingLevel.HEADING_1, +})); -const paragraph = new Paragraph('This is a custom named style from the template "MyFancyStyle"'); -paragraph.style("MyFancyStyle"); +const paragraph = new Paragraph({ + text: 'This is a custom named style from the template "MyFancyStyle"', + style: "MyFancyStyle", +}); doc.addParagraph(paragraph); -doc.createParagraph("Some normal text"); +doc.addParagraph(new Paragraph("Some normal text")); + +doc.addParagraph(new Paragraph({ + text: "MyFancyStyle again", + style: "MyFancyStyle", +})); -doc.createParagraph("MyFancyStyle again").style("MyFancyStyle"); -paragraph.style("MyFancyStyle"); doc.addParagraph(paragraph); const packer = new Packer(); diff --git a/demo/demo14.ts b/demo/demo14.ts index 94d45a66a6..ca3e56ac78 100644 --- a/demo/demo14.ts +++ b/demo/demo14.ts @@ -1,22 +1,32 @@ // Page numbers // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -doc.createParagraph("First Page").pageBreak(); -doc.createParagraph("Second Page"); +doc.addParagraph( + new Paragraph({ + text: "First Page", + }).pageBreak(), +); +doc.addParagraph(new Paragraph("Second Page")); const pageNumber = new TextRun("Page ").pageNumber(); -const pageoneheader = new Paragraph("First Page Header ").right(); +const pageoneheader = new Paragraph({ + text: "First Page Header ", + alignment: AlignmentType.RIGHT, +}); pageoneheader.addRun(pageNumber); const firstPageHeader = doc.createFirstPageHeader(); firstPageHeader.addParagraph(pageoneheader); -const pagetwoheader = new Paragraph("My Title ").right(); +const pagetwoheader = new Paragraph({ + text: "My Title ", + alignment: AlignmentType.RIGHT, +}); pagetwoheader.addRun(pageNumber); doc.Header.addParagraph(pagetwoheader); diff --git a/demo/demo15.ts b/demo/demo15.ts index 5da6c826b5..966d2b9e19 100644 --- a/demo/demo15.ts +++ b/demo/demo15.ts @@ -6,7 +6,10 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); const paragraph = new Paragraph("Hello World"); -const paragraph2 = new Paragraph("Hello World on another page").pageBreakBefore(); +const paragraph2 = new Paragraph({ + text: "Hello World on another page", + pageBreakBefore: true, +}); doc.addParagraph(paragraph); doc.addParagraph(paragraph2); diff --git a/demo/demo16.ts b/demo/demo16.ts index 786b7bf081..161334c626 100644 --- a/demo/demo16.ts +++ b/demo/demo16.ts @@ -10,9 +10,9 @@ const paragraph = new Paragraph("Hello World").pageBreak(); doc.addParagraph(paragraph); const header = doc.createHeader(); -header.createParagraph("Header on another page"); +header.addParagraph(new Paragraph("Header on another page")); const footer = doc.createFooter(); -footer.createParagraph("Footer on another page"); +footer.addParagraph(new Paragraph("Footer on another page")); doc.addSection({ headers: { @@ -25,7 +25,7 @@ doc.addSection({ pageNumberFormatType: PageNumberFormat.DECIMAL, }); -doc.createParagraph("hello"); +doc.addParagraph(new Paragraph("hello")); doc.addSection({ headers: { @@ -39,11 +39,11 @@ doc.addSection({ orientation: PageOrientation.LANDSCAPE, }); -doc.createParagraph("hello in landscape"); +doc.addParagraph(new Paragraph("hello in landscape")); const header2 = doc.createHeader(); const pageNumber = new TextRun("Page number: ").pageNumber(); -header2.createParagraph().addRun(pageNumber); +header2.addParagraph(new Paragraph({}).addRun(pageNumber)); doc.addSection({ headers: { @@ -52,7 +52,7 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.createParagraph("Page number in the header must be 2, because it continues from the previous section."); +doc.addParagraph(new Paragraph("Page number in the header must be 2, because it continues from the previous section.")); doc.addSection({ headers: { @@ -62,9 +62,9 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.createParagraph( +doc.addParagraph(new Paragraph( "Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.", -); +)); doc.addSection({ headers: { @@ -75,7 +75,7 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.createParagraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section."); +doc.addParagraph(new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section.")); const packer = new Packer(); diff --git a/demo/demo2.ts b/demo/demo2.ts index f32779fa06..def1f69ca0 100644 --- a/demo/demo2.ts +++ b/demo/demo2.ts @@ -1,7 +1,7 @@ // Example on how to customise the look at feel using Styles // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, Packer, Paragraph, TextRun, HeadingLevel } from "../build"; const doc = new Document({ creator: "Clippy", @@ -46,30 +46,56 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") const numberedAbstract = doc.Numbering.createAbstractNumbering(); numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left"); -doc.createParagraph("Test heading1, bold and italicized").heading1(); -doc.createParagraph("Some simple content"); -doc.createParagraph("Test heading2 with double red underline").heading2(); +doc.addParagraph( + new Paragraph({ + text: "Test heading1, bold and italicized", + heading: HeadingLevel.HEADING_1, + }), +); +doc.addParagraph(new Paragraph("Some simple content")); +doc.addParagraph( + new Paragraph({ + text: "Test heading2 with double red underline", + heading: HeadingLevel.HEADING_2, + }), +); const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract); const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract); letterNumbering5.overrideLevel(0, 5); -doc.createParagraph("Option1").setNumbering(letterNumbering, 0); -doc.createParagraph("Option5 -- override 2 to 5").setNumbering(letterNumbering5, 0); -doc.createParagraph("Option3").setNumbering(letterNumbering, 0); +doc.addParagraph( + new Paragraph({ + text: "Option1", + numbering: { + num: letterNumbering, + level: 0, + }, + }), +); +doc.addParagraph(new Paragraph("Option5 -- override 2 to 5").setNumbering(letterNumbering5, 0)); +doc.addParagraph(new Paragraph("Option3").setNumbering(letterNumbering, 0)); -doc - .createParagraph() - .createTextRun("Some monospaced content") - .font("Monospace"); +doc.addParagraph(new Paragraph({}).addRun(new TextRun("Some monospaced content").font("Monospace"))); -doc.createParagraph("An aside, in light gray italics and indented").style("aside"); -doc.createParagraph("This is normal, but well-spaced text").style("wellSpaced"); -const para = doc.createParagraph(); -para.createTextRun("This is a bold run,").bold(); -para.createTextRun(" switching to normal "); -para.createTextRun("and then underlined ").underline(); -para.createTextRun("and back to normal."); +doc.addParagraph( + new Paragraph({ + text: "An aside, in light gray italics and indented", + style: "aside", + }), +); +doc.addParagraph( + new Paragraph({ + text: "This is normal, but well-spaced text", + style: "wellSpaced", + }), +); +const para = new Paragraph({}); +doc.addParagraph(para); +para.addRun(new TextRun("This is a bold run,").bold()); +para.addRun(new TextRun(" switching to normal ")); +para.addRun(new TextRun("and then underlined ").underline()); +para.addRun(new TextRun("and back to normal.")); const packer = new Packer(); diff --git a/demo/demo21.ts b/demo/demo21.ts index b02da56065..8e2136c813 100644 --- a/demo/demo21.ts +++ b/demo/demo21.ts @@ -1,7 +1,7 @@ // This demo shows how to create bookmarks then link to them with internal hyperlinks // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph } from "../build"; const loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante."; @@ -17,18 +17,20 @@ const anchorId = "anchorID"; // First create the bookmark const bookmark = doc.createBookmark(anchorId, "Lorem Ipsum"); // That has header styling -doc - .createParagraph() - .addBookmark(bookmark) - .heading1(); -doc.createParagraph("\n"); +doc.addParagraph( + new Paragraph({ + heading: HeadingLevel.HEADING_1, + }).addBookmark(bookmark), +); -doc.createParagraph(loremIpsum); -doc.createParagraph().pageBreak(); +doc.addParagraph(new Paragraph("\n")); + +doc.addParagraph(new Paragraph(loremIpsum)); +doc.addParagraph(new Paragraph({}).pageBreak()); // Now the link back up to the bookmark const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); -doc.createParagraph().addHyperLink(hyperlink); +doc.addParagraph(new Paragraph({}).addHyperLink(hyperlink)); const packer = new Packer(); diff --git a/demo/demo27.ts b/demo/demo27.ts index a5022a1d18..09651dee9e 100644 --- a/demo/demo27.ts +++ b/demo/demo27.ts @@ -1,32 +1,44 @@ // Custom styles using JavaScript configuration // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph } from "../build"; const doc = new Document(); const myStyles = doc.Styles; // The first argument is an ID you use to apply the style to paragraphs // The second argument is a human-friendly name to show in the UI -myStyles.createParagraphStyle("myWonkyStyle", "My Wonky Style") +myStyles + .createParagraphStyle("myWonkyStyle", "My Wonky Style") .basedOn("Normal") .next("Normal") .color("990000") .italics() - .indent({left: 720}) // 720 TWIP === 720 / 20 pt === .5 in - .spacing({line: 276}); // 276 / 240 = 1.15x line spacing + .indent({ left: 720 }) // 720 TWIP === 720 / 20 pt === .5 in + .spacing({ line: 276 }); // 276 / 240 = 1.15x line spacing -myStyles.createParagraphStyle("Heading2", "Heading 2") +myStyles + .createParagraphStyle("Heading2", "Heading 2") .basedOn("Normal") .next("Normal") .quickFormat() - .size(26) // 26 half-points === 13pt font + .size(26) // 26 half-points === 13pt font .bold() .underline("double", "FF0000") - .spacing({before: 240, after: 120}); // TWIP for both + .spacing({ before: 240, after: 120 }); // TWIP for both -doc.createParagraph("Hello").style("myWonkyStyle"); -doc.createParagraph("World").heading2(); // Uses the Heading2 style +doc.addParagraph( + new Paragraph({ + text: "Hello", + style: "myWonkyStyle", + }), +); +doc.addParagraph( + new Paragraph({ + text: "World", + heading: HeadingLevel.HEADING_2, + }), +); // Uses the Heading2 style const packer = new Packer(); diff --git a/demo/demo32.ts b/demo/demo32.ts index 7196058ec0..421838afa9 100644 --- a/demo/demo32.ts +++ b/demo/demo32.ts @@ -1,7 +1,7 @@ // Example of how you would merge cells together // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, ShadingType, WidthType } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, ShadingType, WidthType } from "../build"; const doc = new Document(); @@ -13,7 +13,12 @@ let table = doc.createTable({ table.getCell(0, 0).addParagraph(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); -doc.createParagraph("Another table").heading2(); +doc.addParagraph( + new Paragraph({ + text: "Another table", + heading: HeadingLevel.HEADING_2, + }), +); table = doc.createTable({ rows: 2, @@ -33,7 +38,12 @@ table }); table.getRow(0).mergeCells(0, 2); -doc.createParagraph("Another table").heading2(); +doc.addParagraph( + new Paragraph({ + text: "Another table", + heading: HeadingLevel.HEADING_2, + }), +); table = doc.createTable({ rows: 2, @@ -85,7 +95,7 @@ table table.getRow(0).mergeCells(0, 3); -doc.createParagraph("hi"); +doc.addParagraph(new Paragraph("hi")); doc.createTable({ rows: 2, diff --git a/demo/demo36.ts b/demo/demo36.ts index 5baa5086c3..f40d0e4e3e 100644 --- a/demo/demo36.ts +++ b/demo/demo36.ts @@ -12,7 +12,6 @@ const table = new Table({ }); table.getCell(1, 1).addParagraph(image.Paragraph); -// doc.createParagraph("Hello World"); doc.addTable(table); // doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); diff --git a/demo/demo37.ts b/demo/demo37.ts index 0aaf380d51..8b9e04a12e 100644 --- a/demo/demo37.ts +++ b/demo/demo37.ts @@ -1,11 +1,11 @@ // Add images to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer } from "../build"; +import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -doc.createParagraph("Hello World"); +doc.addParagraph(new Paragraph("Hello World")); doc.Header.addImage(image); doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); diff --git a/demo/demo38.ts b/demo/demo38.ts index d3e5fb2688..dfc9a50091 100644 --- a/demo/demo38.ts +++ b/demo/demo38.ts @@ -2,21 +2,21 @@ // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; // import { Document, Packer, Paragraph } from "../build"; -import { Document, Packer, TextWrappingSide, TextWrappingType } from "../build"; +import { Document, Packer, Paragraph, TextWrappingSide, TextWrappingType } from "../build"; const doc = new Document(); -doc.createParagraph( +doc.addParagraph(new Paragraph( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.", -); +)); -doc.createParagraph( +doc.addParagraph(new Paragraph( "Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.", -); +)); -doc.createParagraph( +doc.addParagraph(new Paragraph( "Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.", -); +)); doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { diff --git a/demo/demo39.ts b/demo/demo39.ts index cd87bc4bcb..1768ce3074 100644 --- a/demo/demo39.ts +++ b/demo/demo39.ts @@ -1,7 +1,7 @@ // Example how to display page numbers // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, PageNumberFormat, TextRun } from "../build"; +import { AlignmentType, Document, Packer, PageNumberFormat, Paragraph, TextRun } from "../build"; const doc = new Document( {}, @@ -11,20 +11,24 @@ const doc = new Document( }, ); -doc.Header.createParagraph("Foo Bar corp. ") - .addRun(new TextRun("Page Number ").pageNumber()) - .addRun(new TextRun(" to ").numberOfTotalPages()); +doc.Header.addParagraph( + new Paragraph("Foo Bar corp. ").addRun(new TextRun("Page Number ").pageNumber()).addRun(new TextRun(" to ").numberOfTotalPages()), +); -doc.Footer.createParagraph("Foo Bar corp. ") - .center() - .addRun(new TextRun("Page Number: ").pageNumber()) - .addRun(new TextRun(" to ").numberOfTotalPages()); +doc.Footer.addParagraph( + new Paragraph({ + text: "Foo Bar corp. ", + alignment: AlignmentType.CENTER, + }) + .addRun(new TextRun("Page Number: ").pageNumber()) + .addRun(new TextRun(" to ").numberOfTotalPages()), +); -doc.createParagraph("Hello World 1").pageBreak(); -doc.createParagraph("Hello World 2").pageBreak(); -doc.createParagraph("Hello World 3").pageBreak(); -doc.createParagraph("Hello World 4").pageBreak(); -doc.createParagraph("Hello World 5").pageBreak(); +doc.addParagraph(new Paragraph("Hello World 1").pageBreak()); +doc.addParagraph(new Paragraph("Hello World 2").pageBreak()); +doc.addParagraph(new Paragraph("Hello World 3").pageBreak()); +doc.addParagraph(new Paragraph("Hello World 4").pageBreak()); +doc.addParagraph(new Paragraph("Hello World 5").pageBreak()); const packer = new Packer(); diff --git a/demo/demo6.ts b/demo/demo6.ts index 5c9ff2798f..524a801d8a 100644 --- a/demo/demo6.ts +++ b/demo/demo6.ts @@ -1,7 +1,7 @@ // Example of how to change page borders // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(undefined, { top: 0, @@ -18,9 +18,12 @@ paragraph.addRun(dateText); doc.addParagraph(paragraph); -doc.createParagraph("Hello World").heading1(); -doc.createParagraph("Foo bar"); -doc.createParagraph("Github is the best"); +doc.addParagraph(new Paragraph({ + text: "Hello World", + heading: HeadingLevel.HEADING_1, +})); +doc.addParagraph(new Paragraph("Foo bar")); +doc.addParagraph(new Paragraph("Github is the best")); const packer = new Packer(); diff --git a/demo/demo8.ts b/demo/demo8.ts index c4fb96a78c..89d474568d 100644 --- a/demo/demo8.ts +++ b/demo/demo8.ts @@ -1,14 +1,14 @@ // Add text to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.createParagraph("Hello World"); +doc.addParagraph(new Paragraph("Hello World")); -doc.Header.createParagraph("Header text"); -doc.Footer.createParagraph("Footer text"); +doc.Header.addParagraph(new Paragraph("Header text")); +doc.Footer.addParagraph(new Paragraph("Footer text")); const packer = new Packer(); diff --git a/demo/demo9.ts b/demo/demo9.ts index 87fe9b5192..71b8b25a77 100644 --- a/demo/demo9.ts +++ b/demo/demo9.ts @@ -1,11 +1,11 @@ // Add images to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.createParagraph("Hello World"); +doc.addParagraph(new Paragraph("Hello World")); doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); From a1cd5e9573a44ae2f5647c62f9cfc50274f4afd9 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 13 Jun 2019 22:36:42 +0100 Subject: [PATCH 03/38] Use new Paragraph API --- demo/demo2.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/demo/demo2.ts b/demo/demo2.ts index def1f69ca0..9960234dc7 100644 --- a/demo/demo2.ts +++ b/demo/demo2.ts @@ -1,7 +1,7 @@ // Example on how to customise the look at feel using Styles // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun, HeadingLevel } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build"; const doc = new Document({ creator: "Clippy", @@ -73,8 +73,24 @@ doc.addParagraph( }, }), ); -doc.addParagraph(new Paragraph("Option5 -- override 2 to 5").setNumbering(letterNumbering5, 0)); -doc.addParagraph(new Paragraph("Option3").setNumbering(letterNumbering, 0)); +doc.addParagraph( + new Paragraph({ + text: "Option5 -- override 2 to 5", + numbering: { + num: letterNumbering, + level: 0, + }, + }), +); +doc.addParagraph( + new Paragraph({ + text: "Option3", + numbering: { + num: letterNumbering, + level: 0, + }, + }), +); doc.addParagraph(new Paragraph({}).addRun(new TextRun("Some monospaced content").font("Monospace"))); From fb65bb4207ce9b94f4d248ae05337a2b7eb3e3e8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Mon, 17 Jun 2019 01:51:57 +0100 Subject: [PATCH 04/38] Turn Run into a declaritive API --- demo/demo1.ts | 10 +- demo/demo10.ts | 15 +- demo/demo19.ts | 10 +- demo/demo2.ts | 32 +++- demo/demo22.ts | 29 +++- demo/demo26.ts | 20 ++- demo/demo28.ts | 25 ++- demo/demo29.ts | 65 +++++--- demo/demo3.ts | 65 ++++++-- demo/demo31.ts | 10 +- demo/demo35.ts | 3 +- demo/demo6.ts | 10 +- src/export/formatter.spec.ts | 7 +- src/file/file.ts | 4 +- .../run/continuation-seperator-run.ts | 2 +- .../footnote/run/footnote-ref-run.ts | 5 +- .../footnotes/footnote/run/reference-run.ts | 2 +- .../footnotes/footnote/run/seperator-run.ts | 2 +- src/file/paragraph/formatting/page-break.ts | 2 +- src/file/paragraph/links/hyperlink.ts | 5 +- src/file/paragraph/run/picture-run.ts | 2 +- src/file/paragraph/run/run.spec.ts | 78 ++++++---- src/file/paragraph/run/run.ts | 147 ++++++++++-------- .../paragraph/run/sequential-identifier.ts | 2 +- src/file/paragraph/run/text-run.ts | 18 ++- src/file/paragraph/run/underline.ts | 20 +++ .../table-of-contents/table-of-contents.ts | 4 +- 27 files changed, 411 insertions(+), 183 deletions(-) diff --git a/demo/demo1.ts b/demo/demo1.ts index ba3a0bcc2f..83a9a3abd8 100644 --- a/demo/demo1.ts +++ b/demo/demo1.ts @@ -6,8 +6,14 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun("Foo Bar").bold(); -const dateText = new TextRun("Github is the best").tab().bold(); +const institutionText = new TextRun({ + text: "Foo Bar", + bold: true, +}); +const dateText = new TextRun({ + text: "Github is the best", + bold: true, +}).tab(); paragraph.addRun(institutionText); paragraph.addRun(dateText); diff --git a/demo/demo10.ts b/demo/demo10.ts index 5cb04d1cdb..8f312af128 100644 --- a/demo/demo10.ts +++ b/demo/demo10.ts @@ -241,8 +241,14 @@ class DocumentCreator { maxRight: {}, }, }); - const institution = new TextRun(institutionName).bold(); - const date = new TextRun(dateText).tab().bold(); + const institution = new TextRun({ + text: institutionName, + bold: true, + }); + const date = new TextRun({ + text: dateText, + bold: true, + }).tab(); paragraph.addRun(institution); paragraph.addRun(date); @@ -252,7 +258,10 @@ class DocumentCreator { public createRoleText(roleText: string): Paragraph { const paragraph = new Paragraph({}); - const role = new TextRun(roleText).italics(); + const role = new TextRun({ + text: roleText, + italics: true, + }); paragraph.addRun(role); diff --git a/demo/demo19.ts b/demo/demo19.ts index 52b5fd6694..819de0bd74 100644 --- a/demo/demo19.ts +++ b/demo/demo19.ts @@ -6,8 +6,14 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun("Foo").bold(); -const dateText = new TextRun("Bar").tab().bold(); +const institutionText = new TextRun({ + text: "Foo", + bold: true, +}); +const dateText = new TextRun({ + text: "Bar", + bold: true, +}).tab(); paragraph.addRun(institutionText); paragraph.addRun(dateText); diff --git a/demo/demo2.ts b/demo/demo2.ts index 9960234dc7..c15942db5b 100644 --- a/demo/demo2.ts +++ b/demo/demo2.ts @@ -92,7 +92,16 @@ doc.addParagraph( }), ); -doc.addParagraph(new Paragraph({}).addRun(new TextRun("Some monospaced content").font("Monospace"))); +doc.addParagraph( + new Paragraph({}).addRun( + new TextRun({ + text: "Some monospaced content", + font: { + name: "Monospace", + }, + }), + ), +); doc.addParagraph( new Paragraph({ @@ -108,10 +117,25 @@ doc.addParagraph( ); const para = new Paragraph({}); doc.addParagraph(para); -para.addRun(new TextRun("This is a bold run,").bold()); +// Showing the different ways to create a TextRun +para.addRun( + new TextRun({ + text: "This is a bold run,", + bold: true, + }), +); para.addRun(new TextRun(" switching to normal ")); -para.addRun(new TextRun("and then underlined ").underline()); -para.addRun(new TextRun("and back to normal.")); +para.addRun( + new TextRun({ + text: "and then underlined ", + underline: {}, + }), +); +para.addRun( + new TextRun({ + text: "and back to normal.", + }), +); const packer = new Packer(); diff --git a/demo/demo22.ts b/demo/demo22.ts index 6f5baa970c..c13d867f5d 100644 --- a/demo/demo22.ts +++ b/demo/demo22.ts @@ -5,18 +5,35 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph1 = new Paragraph().bidirectional(); -const textRun1 = new TextRun("שלום עולם").rightToLeft(); +const paragraph1 = new Paragraph({ + bidirectional: true, +}); +const textRun1 = new TextRun({ + text: "שלום עולם", + rightToLeft: true, +}); paragraph1.addRun(textRun1); doc.addParagraph(paragraph1); -const paragraph2 = new Paragraph().bidirectional(); -const textRun2 = new TextRun("שלום עולם").bold().rightToLeft(); +const paragraph2 = new Paragraph({ + bidirectional: true, +}); +const textRun2 = new TextRun({ + text: "שלום עולם", + bold: true, + rightToLeft: true, +}); paragraph2.addRun(textRun2); doc.addParagraph(paragraph2); -const paragraph3 = new Paragraph().bidirectional(); -const textRun3 = new TextRun("שלום עולם").italics().rightToLeft(); +const paragraph3 = new Paragraph({ + bidirectional: true, +}); +const textRun3 = new TextRun({ + text: "שלום עולם", + italics: true, + rightToLeft: true, +}); paragraph3.addRun(textRun3); doc.addParagraph(paragraph3); diff --git a/demo/demo26.ts b/demo/demo26.ts index 9fa560d260..613d624091 100644 --- a/demo/demo26.ts +++ b/demo/demo26.ts @@ -9,9 +9,23 @@ const paragraph = new Paragraph("No border!"); doc.addParagraph(paragraph); -const borderParagraph = new Paragraph("I have borders on my top and bottom sides!").createBorder(); -borderParagraph.Borders.addTopBorder(); -borderParagraph.Borders.addBottomBorder(); +const borderParagraph = new Paragraph({ + text: "I have borders on my top and bottom sides!", + border: { + top: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + bottom: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + }, +}); doc.addParagraph(borderParagraph); diff --git a/demo/demo28.ts b/demo/demo28.ts index aec36f5bfd..20e4a50026 100644 --- a/demo/demo28.ts +++ b/demo/demo28.ts @@ -1,7 +1,7 @@ // Table of contents // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { File, Packer, Paragraph, StyleLevel, TableOfContents } from "../build"; +import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } from "../build"; const doc = new File(); @@ -26,15 +26,30 @@ const toc = new TableOfContents("Summary", { doc.addTableOfContents(toc); -doc.addParagraph(new Paragraph("Header #1").heading1().pageBreakBefore()); +doc.addParagraph(new Paragraph({ + text: "Header #1", + heading: HeadingLevel.HEADING_1, + pageBreakBefore: true, +})); doc.addParagraph(new Paragraph("I'm a little text very nicely written.'")); -doc.addParagraph(new Paragraph("Header #2").heading1().pageBreakBefore()); +doc.addParagraph(new Paragraph({ + text: "Header #2", + heading: HeadingLevel.HEADING_1, + pageBreakBefore: true, +})); doc.addParagraph(new Paragraph("I'm a other text very nicely written.'")); -doc.addParagraph(new Paragraph("Header #2.1").heading2()); +doc.addParagraph(new Paragraph({ + text: "Header #2.1", + heading: HeadingLevel.HEADING_2, +})); doc.addParagraph(new Paragraph("I'm a another text very nicely written.'")); -doc.addParagraph(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore()); +doc.addParagraph(new Paragraph({ + text: "My Spectacular Style #1", + style: "MySpectacularStyle", + pageBreakBefore: true, +})); const packer = new Packer(); diff --git a/demo/demo29.ts b/demo/demo29.ts index 0439d372d7..bbf6b8d125 100644 --- a/demo/demo29.ts +++ b/demo/demo29.ts @@ -12,27 +12,50 @@ abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new const concrete = numbering.createConcreteNumbering(abstractNum); -const item1 = new Paragraph("line with contextual spacing"); -const item2 = new Paragraph("line with contextual spacing"); -const item3 = new Paragraph("line without contextual spacing"); -const item4 = new Paragraph("line without contextual spacing"); - -item1 - .setNumbering(concrete, 0) - .spacing({ before: 200 }) - .contextualSpacing(true); -item2 - .setNumbering(concrete, 0) - .spacing({ before: 200 }) - .contextualSpacing(true); -item3 - .setNumbering(concrete, 0) - .spacing({ before: 200 }) - .contextualSpacing(false); -item4 - .setNumbering(concrete, 0) - .spacing({ before: 200 }) - .contextualSpacing(false); +const item1 = new Paragraph({ + text: "line with contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: true, + spacing: { + before: 200, + }, +}); +const item2 = new Paragraph({ + text: "line with contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: true, + spacing: { + before: 200, + }, +}); +const item3 = new Paragraph({ + text: "line without contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: false, + spacing: { + before: 200, + }, +}); +const item4 = new Paragraph({ + text: "line without contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: false, + spacing: { + before: 200, + }, +}); doc.addParagraph(item1); doc.addParagraph(item2); diff --git a/demo/demo3.ts b/demo/demo3.ts index ac3680ef32..e526b8e523 100644 --- a/demo/demo3.ts +++ b/demo/demo3.ts @@ -14,25 +14,64 @@ abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(n const concrete = numbering.createConcreteNumbering(abstractNum); -const topLevelP = new Paragraph("Hey you"); -const subP = new Paragraph("What's up fam"); -const secondSubP = new Paragraph("Hello World 2"); -const subSubP = new Paragraph("Yeah boi"); - -topLevelP.setNumbering(concrete, 0); -subP.setNumbering(concrete, 1); -secondSubP.setNumbering(concrete, 1); -subSubP.setNumbering(concrete, 2); +const topLevelP = new Paragraph({ + text: "Hey you", + numbering: { + num: concrete, + level: 0, + }, +}); +const subP = new Paragraph({ + text: "What's up fam", + numbering: { + num: concrete, + level: 1, + }, +}); +const secondSubP = new Paragraph({ + text: "Hello World 2", + numbering: { + num: concrete, + level: 1, + }, +}); +const subSubP = new Paragraph({ + text: "Yeah boi", + numbering: { + num: concrete, + level: 2, + }, +}); doc.addParagraph(topLevelP); doc.addParagraph(subP); doc.addParagraph(secondSubP); doc.addParagraph(subSubP); -const bullet1 = new Paragraph("Hey you").bullet(); -const bullet2 = new Paragraph("What's up fam").bullet(1); -const bullet3 = new Paragraph("Hello World 2").bullet(2); -const bullet4 = new Paragraph("Yeah boi").bullet(3); +const bullet1 = new Paragraph({ + text: "Hey you", + bullet: { + level: 0, + }, +}); +const bullet2 = new Paragraph({ + text: "What's up fam", + bullet: { + level: 1, + }, +}); +const bullet3 = new Paragraph({ + text: "Hello World 2", + bullet: { + level: 2, + }, +}); +const bullet4 = new Paragraph({ + text: "Yeah boi", + bullet: { + level: 3, + }, +}); doc.addParagraph(bullet1); doc.addParagraph(bullet2); diff --git a/demo/demo31.ts b/demo/demo31.ts index e05a20f454..a17f18b94c 100644 --- a/demo/demo31.ts +++ b/demo/demo31.ts @@ -1,7 +1,7 @@ // Example of how you would create a table and add data to it // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, VerticalAlign } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, VerticalAlign } from "../build"; const doc = new Document(); @@ -17,9 +17,11 @@ table table .getCell(1, 0) .addParagraph( - new Paragraph( - "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", - ).heading1(), + new Paragraph({ + text: + "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", + heading: HeadingLevel.HEADING_1, + }), ); const packer = new Packer(); diff --git a/demo/demo35.ts b/demo/demo35.ts index 05ef010c1a..04573edc1e 100644 --- a/demo/demo35.ts +++ b/demo/demo35.ts @@ -4,10 +4,9 @@ import * as fs from "fs"; import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -const paragraph = new Paragraph(); +const paragraph = new Paragraph({}); const link = doc.createHyperlink("http://www.example.com", "Hyperlink"); -link.bold(); paragraph.addHyperLink(link); doc.addParagraph(paragraph); diff --git a/demo/demo6.ts b/demo/demo6.ts index 524a801d8a..042f6d7d94 100644 --- a/demo/demo6.ts +++ b/demo/demo6.ts @@ -11,8 +11,14 @@ const doc = new Document(undefined, { }); const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun("Foo bar").bold(); -const dateText = new TextRun("Github is the best").tab().bold(); +const institutionText = new TextRun({ + text: "Foo bar", + bold: true, +}); +const dateText = new TextRun({ + text: "Github is the best", + bold: true, +}).tab(); paragraph.addRun(institutionText); paragraph.addRun(dateText); diff --git a/src/export/formatter.spec.ts b/src/export/formatter.spec.ts index a76bad29c0..a2f0c971ab 100644 --- a/src/export/formatter.spec.ts +++ b/src/export/formatter.spec.ts @@ -29,7 +29,12 @@ describe("Formatter", () => { it("should format simple paragraph with bold text", () => { const paragraph = new file.Paragraph(""); - paragraph.addRun(new file.TextRun("test").bold()); + paragraph.addRun( + new file.TextRun({ + text: "test", + bold: true, + }), + ); const newJson = formatter.format(paragraph); assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]); }); diff --git a/src/file/file.ts b/src/file/file.ts index 747077bd36..50f4ff9613 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -30,6 +30,8 @@ import { TableOfContents } from "./table-of-contents"; export class File { // tslint:disable-next-line:readonly-keyword private currentRelationshipId: number = 1; + // tslint:disable-next-line:readonly-keyword + private styles: Styles; private readonly document: Document; private readonly headers: IDocumentHeader[] = []; @@ -43,8 +45,6 @@ export class File { private readonly settings: Settings; private readonly contentTypes: ContentTypes; private readonly appProperties: AppProperties; - // tslint:disable-next-line:readonly-keyword - private styles: Styles; constructor( options: IPropertiesOptions = { diff --git a/src/file/footnotes/footnote/run/continuation-seperator-run.ts b/src/file/footnotes/footnote/run/continuation-seperator-run.ts index 4cf3ad2d21..8e55b9bb7f 100644 --- a/src/file/footnotes/footnote/run/continuation-seperator-run.ts +++ b/src/file/footnotes/footnote/run/continuation-seperator-run.ts @@ -3,7 +3,7 @@ import { ContinuationSeperator } from "./continuation-seperator"; export class ContinuationSeperatorRun extends Run { constructor() { - super(); + super({}); this.root.push(new ContinuationSeperator()); } diff --git a/src/file/footnotes/footnote/run/footnote-ref-run.ts b/src/file/footnotes/footnote/run/footnote-ref-run.ts index 65ef0b697a..4be3493b33 100644 --- a/src/file/footnotes/footnote/run/footnote-ref-run.ts +++ b/src/file/footnotes/footnote/run/footnote-ref-run.ts @@ -3,9 +3,10 @@ import { FootnoteRef } from "./footnote-ref"; export class FootnoteRefRun extends Run { constructor() { - super(); + super({ + style: "FootnoteReference", + }); - this.style("FootnoteReference"); this.root.push(new FootnoteRef()); } } diff --git a/src/file/footnotes/footnote/run/reference-run.ts b/src/file/footnotes/footnote/run/reference-run.ts index 278120ed70..7dec91473d 100644 --- a/src/file/footnotes/footnote/run/reference-run.ts +++ b/src/file/footnotes/footnote/run/reference-run.ts @@ -26,7 +26,7 @@ export class FootnoteReference extends XmlComponent { export class FootnoteReferenceRun extends Run { constructor(id: number) { - super(); + super({}); this.properties.push(new Style("FootnoteReference")); diff --git a/src/file/footnotes/footnote/run/seperator-run.ts b/src/file/footnotes/footnote/run/seperator-run.ts index 17cc69d8ec..c5a0f9b252 100644 --- a/src/file/footnotes/footnote/run/seperator-run.ts +++ b/src/file/footnotes/footnote/run/seperator-run.ts @@ -3,7 +3,7 @@ import { Seperator } from "./seperator"; export class SeperatorRun extends Run { constructor() { - super(); + super({}); this.root.push(new Seperator()); } diff --git a/src/file/paragraph/formatting/page-break.ts b/src/file/paragraph/formatting/page-break.ts index 13556d12e2..af08f766d3 100644 --- a/src/file/paragraph/formatting/page-break.ts +++ b/src/file/paragraph/formatting/page-break.ts @@ -15,7 +15,7 @@ class Break extends XmlComponent { export class PageBreak extends Run { constructor() { - super(); + super({}); this.root.push(new Break()); } } diff --git a/src/file/paragraph/links/hyperlink.ts b/src/file/paragraph/links/hyperlink.ts index 3ed33f44ad..b41980ed77 100644 --- a/src/file/paragraph/links/hyperlink.ts +++ b/src/file/paragraph/links/hyperlink.ts @@ -20,7 +20,10 @@ export class Hyperlink extends XmlComponent { const attributes = new HyperlinkAttributes(props); this.root.push(attributes); - this.textRun = new TextRun(text).style("Hyperlink"); + this.textRun = new TextRun({ + text: text, + style: "Hyperlink", + }); this.root.push(this.textRun); } diff --git a/src/file/paragraph/run/picture-run.ts b/src/file/paragraph/run/picture-run.ts index 15da74eb56..9f8cd7393c 100644 --- a/src/file/paragraph/run/picture-run.ts +++ b/src/file/paragraph/run/picture-run.ts @@ -7,7 +7,7 @@ export class PictureRun extends Run { private readonly drawing: Drawing; constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { - super(); + super({}); if (imageData === undefined) { throw new Error("imageData cannot be undefined"); diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index c30147d22f..bb72e65b3a 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -4,17 +4,14 @@ import { Formatter } from "export/formatter"; import { Utility } from "tests/utility"; import { Run } from "./"; +import { UnderlineType } from "./underline"; describe("Run", () => { - let run: Run; - - beforeEach(() => { - run = new Run(); - }); - describe("#bold()", () => { it("it should add bold to the properties", () => { - run.bold(); + const run = new Run({ + bold: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:b"); assert.equal(newJson.root[0].root[1].rootKey, "w:bCs"); @@ -23,7 +20,9 @@ describe("Run", () => { describe("#italics()", () => { it("it should add italics to the properties", () => { - run.italics(); + const run = new Run({ + italics: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:i"); assert.equal(newJson.root[0].root[1].rootKey, "w:iCs"); @@ -31,14 +30,10 @@ describe("Run", () => { }); describe("#underline()", () => { - it("it should add underline to the properties", () => { - run.underline(); - const newJson = Utility.jsonify(run); - assert.equal(newJson.root[0].root[0].rootKey, "w:u"); - }); - it("should default to 'single' and no color", () => { - run.underline(); + const run = new Run({ + underline: {}, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }] }], @@ -46,7 +41,12 @@ describe("Run", () => { }); it("should set the style type and color if given", () => { - run.underline("double", "990011"); + const run = new Run({ + underline: { + type: UnderlineType.DOUBLE, + color: "990011", + }, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "990011" } } }] }], @@ -56,7 +56,9 @@ describe("Run", () => { describe("#smallCaps()", () => { it("it should add smallCaps to the properties", () => { - run.smallCaps(); + const run = new Run({ + smallCaps: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:smallCaps"); }); @@ -64,7 +66,9 @@ describe("Run", () => { describe("#caps()", () => { it("it should add caps to the properties", () => { - run.allCaps(); + const run = new Run({ + allCaps: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:caps"); }); @@ -72,7 +76,9 @@ describe("Run", () => { describe("#strike()", () => { it("it should add strike to the properties", () => { - run.strike(); + const run = new Run({ + strike: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:strike"); }); @@ -80,7 +86,9 @@ describe("Run", () => { describe("#doubleStrike()", () => { it("it should add caps to the properties", () => { - run.doubleStrike(); + const run = new Run({ + doubleStrike: true, + }); const newJson = Utility.jsonify(run); assert.equal(newJson.root[0].root[0].rootKey, "w:dstrike"); }); @@ -88,6 +96,7 @@ describe("Run", () => { describe("#break()", () => { it("it should add break to the run", () => { + const run = new Run({}); run.break(); const newJson = Utility.jsonify(run); assert.equal(newJson.root[1].rootKey, "w:br"); @@ -96,6 +105,7 @@ describe("Run", () => { describe("#tab()", () => { it("it should add break to the run", () => { + const run = new Run({}); run.tab(); const newJson = Utility.jsonify(run); assert.equal(newJson.root[1].rootKey, "w:tab"); @@ -103,12 +113,12 @@ describe("Run", () => { }); describe("#font()", () => { - it("should allow chaining calls", () => { - expect(run.font("Times")).to.equal(run); - }); - it("should set the font as named", () => { - run.font("Times"); + const run = new Run({ + font: { + name: "Times", + }, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [ @@ -124,7 +134,9 @@ describe("Run", () => { describe("#color", () => { it("should set the run to the color given", () => { - run.color("001122"); + const run = new Run({ + color: "001122", + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:color": { _attr: { "w:val": "001122" } } }] }], @@ -134,7 +146,9 @@ describe("Run", () => { describe("#size", () => { it("should set the run to the given size", () => { - run.size(24); + const run = new Run({ + size: 24, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [ @@ -148,7 +162,9 @@ describe("Run", () => { describe("#rtl", () => { it("should set the run to the RTL mode", () => { - run.rightToLeft(); + const run = new Run({ + rightToLeft: true, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:rtl": { _attr: { "w:val": true } } }] }], @@ -158,6 +174,7 @@ describe("Run", () => { describe("#numberOfTotalPages", () => { it("should set the run to the RTL mode", () => { + const run = new Run({}); run.numberOfTotalPages(); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ @@ -173,6 +190,7 @@ describe("Run", () => { describe("#pageNumber", () => { it("should set the run to the RTL mode", () => { + const run = new Run({}); run.pageNumber(); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ @@ -188,7 +206,9 @@ describe("Run", () => { describe("#style", () => { it("should set the style to the given styleId", () => { - run.style("myRunStyle"); + const run = new Run({ + style: "myRunStyle", + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "myRunStyle" } } }] }], diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index 32777cd31d..8909fe66bf 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -20,50 +20,99 @@ import { RunFonts } from "./run-fonts"; import { SubScript, SuperScript } from "./script"; import { Style } from "./style"; import { Tab } from "./tab"; -import { Underline } from "./underline"; +import { Underline, UnderlineType } from "./underline"; import { XmlComponent } from "file/xml-components"; +export interface IRunOptions { + readonly bold?: true; + readonly italics?: true; + readonly underline?: { + readonly color?: string; + readonly type?: UnderlineType; + }; + 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?: { + readonly name: string; + readonly hint?: string; + }; +} + export class Run extends XmlComponent { protected readonly properties: RunProperties; - constructor() { + constructor(options: IRunOptions) { super("w:r"); this.properties = new RunProperties(); this.root.push(this.properties); - } - public bold(): Run { - this.properties.push(new Bold()); - this.properties.push(new BoldComplexScript()); - return this; - } + if (options.bold) { + this.properties.push(new Bold()); + this.properties.push(new BoldComplexScript()); + } - public italics(): Run { - this.properties.push(new Italics()); - this.properties.push(new ItalicsComplexScript()); - return this; - } + if (options.italics) { + this.properties.push(new Italics()); + this.properties.push(new ItalicsComplexScript()); + } - public underline(underlineType?: string, color?: string): Run { - this.properties.push(new Underline(underlineType, color)); - return this; - } + if (options.underline) { + this.properties.push(new Underline(options.underline.type, options.underline.color)); + } - public color(color: string): Run { - this.properties.push(new Color(color)); - return this; - } + if (options.color) { + this.properties.push(new Color(options.color)); + } - public size(size: number): Run { - this.properties.push(new Size(size)); - this.properties.push(new SizeComplexScript(size)); - return this; - } + if (options.size) { + this.properties.push(new Size(options.size)); + this.properties.push(new SizeComplexScript(options.size)); + } - public rightToLeft(): Run { - this.properties.push(new RightToLeft()); - return this; + 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) { + this.properties.push(new RunFonts(options.font.name, options.font.hint)); + } } public break(): Run { @@ -91,44 +140,4 @@ export class Run extends XmlComponent { this.root.push(new End()); return this; } - - public smallCaps(): Run { - this.properties.push(new SmallCaps()); - return this; - } - - public allCaps(): Run { - this.properties.push(new Caps()); - return this; - } - - public strike(): Run { - this.properties.push(new Strike()); - return this; - } - - public doubleStrike(): Run { - this.properties.push(new DoubleStrike()); - return this; - } - - public subScript(): Run { - this.properties.push(new SubScript()); - return this; - } - - public superScript(): Run { - this.properties.push(new SuperScript()); - return this; - } - - public font(fontName: string, hint?: string | undefined): Run { - this.properties.push(new RunFonts(fontName, hint)); - return this; - } - - public style(styleId: string): Run { - this.properties.push(new Style(styleId)); - return this; - } } diff --git a/src/file/paragraph/run/sequential-identifier.ts b/src/file/paragraph/run/sequential-identifier.ts index 5536eca4ae..e193307e83 100644 --- a/src/file/paragraph/run/sequential-identifier.ts +++ b/src/file/paragraph/run/sequential-identifier.ts @@ -4,7 +4,7 @@ import { SequentialIdentifierInstruction } from "./sequential-identifier-instruc export class SequentialIdentifier extends Run { constructor(identifier: string) { - super(); + super({}); this.root.push(new Begin(true)); this.root.push(new SequentialIdentifierInstruction(identifier)); this.root.push(new Separate()); diff --git a/src/file/paragraph/run/text-run.ts b/src/file/paragraph/run/text-run.ts index 4b0474edc6..eeacf2dfd5 100644 --- a/src/file/paragraph/run/text-run.ts +++ b/src/file/paragraph/run/text-run.ts @@ -1,9 +1,19 @@ -import { Run } from "../run"; +import { IRunOptions, Run } from "./run"; import { Text } from "./run-components/text"; +export interface ITextRunOptions extends IRunOptions { + readonly text: string; +} + export class TextRun extends Run { - constructor(text: string) { - super(); - this.root.push(new Text(text)); + constructor(options: ITextRunOptions | string) { + if (typeof options === "string") { + super({}); + this.root.push(new Text(options)); + return; + } + + super(options); + this.root.push(new Text(options.text)); } } diff --git a/src/file/paragraph/run/underline.ts b/src/file/paragraph/run/underline.ts index bb994e040b..7d4a1c98d1 100644 --- a/src/file/paragraph/run/underline.ts +++ b/src/file/paragraph/run/underline.ts @@ -1,5 +1,25 @@ import { Attributes, XmlComponent } from "file/xml-components"; +export enum UnderlineType { + SINGLE = "single", + WORDS = "words", + DOUBLE = "double", + THICK = "thick", + DOTTED = "dotted", + DOTTEDHEAVY = "dottedHeavy", + DASH = "dash", + DASHEDHEAVY = "dashedHeavy", + DASHLONG = "dashLong", + DASHLONGHEAVY = "dashLongHeavy", + DOTDASH = "dotDash", + DASHDOTHEAVY = "dashDotHeavy", + DOTDOTDASH = "dotDotDash", + DASHDOTDOTHEAVY = "dashDotDotHeavy", + WAVE = "wave", + WAVYHEAVY = "wavyHeavy", + WAVYDOUBLE = "wavyDouble", +} + export abstract class BaseUnderline extends XmlComponent { constructor(underlineType: string, color?: string) { super("w:u"); diff --git a/src/file/table-of-contents/table-of-contents.ts b/src/file/table-of-contents/table-of-contents.ts index 6b2c69e1bf..57acbb3ace 100644 --- a/src/file/table-of-contents/table-of-contents.ts +++ b/src/file/table-of-contents/table-of-contents.ts @@ -17,7 +17,7 @@ export class TableOfContents extends XmlComponent { const content = new StructuredDocumentTagContent(); const beginParagraph = new Paragraph({}); - const beginRun = new Run(); + const beginRun = new Run({}); beginRun.addChildElement(new Begin(true)); beginRun.addChildElement(new FieldInstruction(properties)); beginRun.addChildElement(new Separate()); @@ -25,7 +25,7 @@ export class TableOfContents extends XmlComponent { content.addChildElement(beginParagraph); const endParagraph = new Paragraph({}); - const endRun = new Run(); + const endRun = new Run({}); endRun.addChildElement(new End()); endParagraph.addRun(endRun); content.addChildElement(endParagraph); From 427dc869151603c326e1b3dc4a1ce1920f456dac Mon Sep 17 00:00:00 2001 From: Dolan Date: Mon, 17 Jun 2019 01:54:48 +0100 Subject: [PATCH 05/38] Fix demos --- demo/demo40.ts | 21 +++++++++++++++------ demo/demo41.ts | 40 ++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/demo/demo40.ts b/demo/demo40.ts index b9213d76a1..ed0e0fe278 100644 --- a/demo/demo40.ts +++ b/demo/demo40.ts @@ -1,7 +1,7 @@ // Example demonstrating line numbers. // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, LineNumberRestartFormat, Packer, Paragraph } from "../build"; +import { Document, HeadingLevel, LineNumberRestartFormat, Packer, Paragraph } from "../build"; const doc = new Document( {}, @@ -11,12 +11,21 @@ const doc = new Document( }, ); -doc.addParagraph(new Paragraph("Hello").heading1()); -doc.createParagraph( - "Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.", +doc.addParagraph( + new Paragraph({ + text: "Hello", + heading: HeadingLevel.HEADING_1, + }), ); -doc.createParagraph( - "Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.", +doc.addParagraph( + new Paragraph( + "Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.", + ), +); +doc.addParagraph( + new Paragraph( + "Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.", + ), ); const packer = new Packer(); diff --git a/demo/demo41.ts b/demo/demo41.ts index a7094784ca..3fc387a1c7 100644 --- a/demo/demo41.ts +++ b/demo/demo41.ts @@ -10,38 +10,38 @@ const table = doc.createTable({ columns: 6, }); let row = 0; -table.getCell(row, 0).addContent(new Paragraph("0,0")); -table.getCell(row, 1).addContent(new Paragraph("0,1")); -table.getCell(row, 3).addContent(new Paragraph("0,3")); -table.getCell(row, 4).addContent(new Paragraph("0,4")); +table.getCell(row, 0).addParagraph(new Paragraph("0,0")); +table.getCell(row, 1).addParagraph(new Paragraph("0,1")); +table.getCell(row, 3).addParagraph(new Paragraph("0,3")); +table.getCell(row, 4).addParagraph(new Paragraph("0,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(1, 2); row = 1; -table.getCell(row, 0).addContent(new Paragraph("1,0")); -table.getCell(row, 2).addContent(new Paragraph("1,2")); -table.getCell(row, 4).addContent(new Paragraph("1,4")); +table.getCell(row, 0).addParagraph(new Paragraph("1,0")); +table.getCell(row, 2).addParagraph(new Paragraph("1,2")); +table.getCell(row, 4).addParagraph(new Paragraph("1,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(2, 3); table.getRow(row).mergeCells(0, 1); row = 2; -table.getCell(row, 0).addContent(new Paragraph("2,0")); -table.getCell(row, 1).addContent(new Paragraph("2,1")); -table.getCell(row, 2).addContent(new Paragraph("2,2")); -table.getCell(row, 3).addContent(new Paragraph("2,3")); -table.getCell(row, 4).addContent(new Paragraph("2,4")); +table.getCell(row, 0).addParagraph(new Paragraph("2,0")); +table.getCell(row, 1).addParagraph(new Paragraph("2,1")); +table.getCell(row, 2).addParagraph(new Paragraph("2,2")); +table.getCell(row, 3).addParagraph(new Paragraph("2,3")); +table.getCell(row, 4).addParagraph(new Paragraph("2,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(1, 2); row = 3; -table.getCell(row, 0).addContent(new Paragraph("3,0")); -table.getCell(row, 1).addContent(new Paragraph("3,1")); -table.getCell(row, 2).addContent(new Paragraph("3,2")); -table.getCell(row, 3).addContent(new Paragraph("3,3")); -table.getCell(row, 4).addContent(new Paragraph("3,4")); -table.getCell(row, 5).addContent(new Paragraph("3,5")); +table.getCell(row, 0).addParagraph(new Paragraph("3,0")); +table.getCell(row, 1).addParagraph(new Paragraph("3,1")); +table.getCell(row, 2).addParagraph(new Paragraph("3,2")); +table.getCell(row, 3).addParagraph(new Paragraph("3,3")); +table.getCell(row, 4).addParagraph(new Paragraph("3,4")); +table.getCell(row, 5).addParagraph(new Paragraph("3,5")); row = 4; -table.getCell(row, 0).addContent(new Paragraph("4,0")); -table.getCell(row, 5).addContent(new Paragraph("4,5")); +table.getCell(row, 0).addParagraph(new Paragraph("4,0")); +table.getCell(row, 5).addParagraph(new Paragraph("4,5")); table.getRow(row).mergeCells(0, 4); const packer = new Packer(); From dfe986331d9102e5368f9cb719cb74a7c0cf3330 Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 23 Jun 2019 22:36:01 +0100 Subject: [PATCH 06/38] Make media return a picture run instead --- demo/demo24.ts | 2 +- demo/demo36.ts | 4 ++-- src/file/file.ts | 7 ++++--- src/file/media/media.spec.ts | 9 +++++---- src/file/media/media.ts | 8 ++++---- src/file/paragraph/paragraph.ts | 16 +++++++++++++++- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/demo/demo24.ts b/demo/demo24.ts index 831a4c29a8..ed84acf727 100644 --- a/demo/demo24.ts +++ b/demo/demo24.ts @@ -12,7 +12,7 @@ const table = doc.createTable({ table.getCell(2, 2).addParagraph(new Paragraph("Hello")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -table.getCell(1, 1).addParagraph(image.Paragraph); +table.getCell(1, 1).addParagraph(new Paragraph(image)); const packer = new Packer(); diff --git a/demo/demo36.ts b/demo/demo36.ts index f40d0e4e3e..655410b56e 100644 --- a/demo/demo36.ts +++ b/demo/demo36.ts @@ -1,7 +1,7 @@ // Add image to table cell // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer, Table } from "../build"; +import { Document, Media, Packer, Paragraph, Table } from "../build"; const doc = new Document(); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); @@ -10,7 +10,7 @@ const table = new Table({ rows: 2, columns: 2, }); -table.getCell(1, 1).addParagraph(image.Paragraph); +table.getCell(1, 1).addParagraph(new Paragraph(image)); doc.addTable(table); diff --git a/src/file/file.ts b/src/file/file.ts index 50f4ff9613..bb27abb411 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -141,11 +141,12 @@ export class File { width?: number, height?: number, drawingOptions?: IDrawingOptions, - ): Image { + ): Paragraph { const image = Media.addImage(this, buffer, width, height, drawingOptions); - this.document.addParagraph(image.Paragraph); + const paragraph = new Paragraph(image); + this.document.addParagraph(paragraph); - return image; + return paragraph; } public createHyperlink(link: string, text?: string): Hyperlink { diff --git a/src/file/media/media.spec.ts b/src/file/media/media.spec.ts index 9c53f1910d..b7ce0c106c 100644 --- a/src/file/media/media.spec.ts +++ b/src/file/media/media.spec.ts @@ -5,6 +5,7 @@ import { stub } from "sinon"; import { Formatter } from "export/formatter"; import { File } from "../file"; +import { Paragraph } from "../paragraph"; import { Media } from "./media"; describe("Media", () => { @@ -13,10 +14,10 @@ describe("Media", () => { const file = new File(); const image = Media.addImage(file, ""); - let tree = new Formatter().format(image.Paragraph); + let tree = new Formatter().format(new Paragraph(image)); expect(tree["w:p"]).to.be.an.instanceof(Array); - tree = new Formatter().format(image.Run); + tree = new Formatter().format(image); expect(tree["w:r"]).to.be.an.instanceof(Array); }); @@ -26,7 +27,7 @@ describe("Media", () => { const file = new File(); const image1 = Media.addImage(file, "test"); - const tree = new Formatter().format(image1.Paragraph); + const tree = new Formatter().format(new Paragraph(image1)); const inlineElements = tree["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"]; const graphicData = inlineElements.find((x) => x["a:graphic"]); @@ -38,7 +39,7 @@ describe("Media", () => { }); const image2 = Media.addImage(file, "test"); - const tree2 = new Formatter().format(image2.Paragraph); + const tree2 = new Formatter().format(new Paragraph(image2)); const inlineElements2 = tree2["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"]; const graphicData2 = inlineElements2.find((x) => x["a:graphic"]); diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 8a160291ca..75087a66ab 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,8 +1,8 @@ import { IDrawingOptions } from "../drawing"; import { File } from "../file"; -import { ImageParagraph } from "../paragraph"; +import { PictureRun } from "../paragraph"; import { IMediaData } from "./data"; -import { Image } from "./image"; +// import { Image } from "./image"; export class Media { public static addImage( @@ -11,10 +11,10 @@ export class Media { width?: number, height?: number, drawingOptions?: IDrawingOptions, - ): Image { + ): PictureRun { // Workaround to expose id without exposing to API const mediaData = file.Media.addMedia(buffer, width, height); - return new Image(new ImageParagraph(mediaData, drawingOptions)); + return new PictureRun(mediaData, drawingOptions); } private static generateId(): string { diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 51940a6373..74aff05bf5 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -55,12 +55,13 @@ export interface IParagraphOptions { readonly level: number; readonly custom?: boolean; }; + readonly children?: Array; } export class Paragraph extends XmlComponent { private readonly properties: ParagraphProperties; - constructor(options: string | IParagraphOptions) { + constructor(options: string | PictureRun | IParagraphOptions) { super("w:p"); if (typeof options === "string") { @@ -70,6 +71,13 @@ export class Paragraph extends XmlComponent { return; } + if (options instanceof PictureRun) { + this.properties = new ParagraphProperties({}); + this.root.push(this.properties); + this.root.push(options); + return; + } + this.properties = new ParagraphProperties({ border: options.border, }); @@ -163,6 +171,12 @@ export class Paragraph extends XmlComponent { this.root.push(run); } } + + if (options.children) { + for (const child of options.children) { + this.root.push(child); + } + } } public addRun(run: Run): Paragraph { From c97d15cb9f813956882332e110d7ca443267610b Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 25 Jun 2019 01:21:28 +0100 Subject: [PATCH 07/38] Remove create table helper function --- demo/demo20.ts | 6 +- demo/demo24.ts | 7 +- demo/demo31.ts | 23 +-- demo/demo32.ts | 20 +- demo/demo34.ts | 15 +- demo/demo4.ts | 7 +- demo/demo41.ts | 7 +- demo/demo43.ts | 7 +- docs/usage/tables.md | 49 ++--- src/file/document/document.spec.ts | 37 ---- src/file/document/document.ts | 8 +- src/file/file.spec.ts | 13 -- src/file/file.ts | 6 +- src/file/footer-wrapper.spec.ts | 15 +- src/file/footer-wrapper.ts | 25 ++- src/file/footer/footer.ts | 9 - src/file/header-wrapper.spec.ts | 15 +- src/file/header-wrapper.ts | 25 ++- src/file/header/header.ts | 9 - src/file/media/media.ts | 4 +- src/file/paragraph/paragraph.ts.orig | 243 ------------------------ src/file/table/table-cell/table-cell.ts | 4 + 22 files changed, 132 insertions(+), 422 deletions(-) delete mode 100644 src/file/paragraph/paragraph.ts.orig diff --git a/demo/demo20.ts b/demo/demo20.ts index d80d23913b..8038944ed0 100644 --- a/demo/demo20.ts +++ b/demo/demo20.ts @@ -1,14 +1,16 @@ // Add custom borders to table cell // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { BorderStyle, Document, Packer, Paragraph } from "../build"; +import { BorderStyle, Document, Packer, Paragraph, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 4, columns: 4, }); + +doc.addTable(table); table .getCell(2, 2) .addParagraph(new Paragraph("Hello")) diff --git a/demo/demo24.ts b/demo/demo24.ts index ed84acf727..7a50a911b4 100644 --- a/demo/demo24.ts +++ b/demo/demo24.ts @@ -1,14 +1,17 @@ // Add image to table cell // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer, Paragraph } from "../build"; +import { Document, Media, Packer, Paragraph, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 4, columns: 4, }); + +doc.addTable(table); + table.getCell(2, 2).addParagraph(new Paragraph("Hello")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); diff --git a/demo/demo31.ts b/demo/demo31.ts index a17f18b94c..15f6de5a64 100644 --- a/demo/demo31.ts +++ b/demo/demo31.ts @@ -1,28 +1,29 @@ // Example of how you would create a table and add data to it // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, HeadingLevel, Packer, Paragraph, VerticalAlign } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, VerticalAlign, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 2, columns: 2, }); + +doc.addTable(table); + table .getCell(1, 1) .addParagraph(new Paragraph("This text should be in the middle of the cell")) .setVerticalAlign(VerticalAlign.CENTER); -table - .getCell(1, 0) - .addParagraph( - new Paragraph({ - text: - "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", - heading: HeadingLevel.HEADING_1, - }), - ); +table.getCell(1, 0).addParagraph( + new Paragraph({ + text: + "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", + heading: HeadingLevel.HEADING_1, + }), +); const packer = new Packer(); diff --git a/demo/demo32.ts b/demo/demo32.ts index 421838afa9..2591a72174 100644 --- a/demo/demo32.ts +++ b/demo/demo32.ts @@ -1,15 +1,17 @@ // Example of how you would merge cells together // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, HeadingLevel, Packer, Paragraph, ShadingType, WidthType } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, ShadingType, Table, WidthType } from "../build"; const doc = new Document(); -let table = doc.createTable({ +let table = new Table({ rows: 2, columns: 2, }); +doc.addTable(table); + table.getCell(0, 0).addParagraph(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); @@ -20,13 +22,16 @@ doc.addParagraph( }), ); -table = doc.createTable({ +table = new Table({ rows: 2, columns: 3, width: 100, widthUnitType: WidthType.AUTO, columnWidths: [1000, 1000, 1000], }); + +doc.addTable(table); + table .getCell(0, 0) .addParagraph(new Paragraph("World")) @@ -45,7 +50,7 @@ doc.addParagraph( }), ); -table = doc.createTable({ +table = new Table({ rows: 2, columns: 4, width: 7000, @@ -57,6 +62,9 @@ table = doc.createTable({ left: 400, }, }); + +doc.addTable(table); + table.getCell(0, 0).addParagraph(new Paragraph("Foo")); table.getCell(0, 1).addParagraph(new Paragraph("v")); @@ -97,13 +105,15 @@ table.getRow(0).mergeCells(0, 3); doc.addParagraph(new Paragraph("hi")); -doc.createTable({ +table = new Table({ rows: 2, columns: 2, width: 100, widthUnitType: WidthType.PERCENTAGE, }); +doc.addTable(table); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo34.ts b/demo/demo34.ts index 0899f26bfe..678094988f 100644 --- a/demo/demo34.ts +++ b/demo/demo34.ts @@ -1,11 +1,20 @@ // Example of how you would create a table with float positions // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph, RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType, WidthType } from "../build"; +import { + Document, + Packer, + Paragraph, + RelativeHorizontalPosition, + RelativeVerticalPosition, + Table, + TableAnchorType, + WidthType, +} from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 2, columns: 2, float: { @@ -17,6 +26,8 @@ const table = doc.createTable({ width: 4535, widthUnitType: WidthType.DXA, }); + +doc.addTable(table); table.setFixedWidthLayout(); table.getCell(0, 0).addParagraph(new Paragraph("Hello")); diff --git a/demo/demo4.ts b/demo/demo4.ts index 805e7ed33f..19242b1a71 100644 --- a/demo/demo4.ts +++ b/demo/demo4.ts @@ -1,14 +1,17 @@ // Example of how you would create a table and add data to it // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Packer, Paragraph, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 4, columns: 4, }); + +doc.addTable(table); + table.getCell(2, 2).addParagraph(new Paragraph("Hello")); const packer = new Packer(); diff --git a/demo/demo41.ts b/demo/demo41.ts index 3fc387a1c7..2d3192bdf2 100644 --- a/demo/demo41.ts +++ b/demo/demo41.ts @@ -1,14 +1,17 @@ // Multiple cells merging in the same table // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Packer, Paragraph, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 13, columns: 6, }); + +doc.addTable(table); + let row = 0; table.getCell(row, 0).addParagraph(new Paragraph("0,0")); table.getCell(row, 1).addParagraph(new Paragraph("0,1")); diff --git a/demo/demo43.ts b/demo/demo43.ts index 65d34355aa..65ce2d443a 100644 --- a/demo/demo43.ts +++ b/demo/demo43.ts @@ -1,14 +1,17 @@ // Add image to table cell // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Packer, Paragraph, Table } from "../build"; const doc = new Document(); -const table = doc.createTable({ +const table = new Table({ rows: 4, columns: 4, }); + +doc.addTable(table); + table.getCell(2, 2).addParagraph(new Paragraph("Hello")); table.getColumn(3).mergeCells(1, 2); // table.getCell(3, 2).addParagraph(new Paragraph("Hello")); diff --git a/docs/usage/tables.md b/docs/usage/tables.md index ed669cfd18..437d579b8f 100644 --- a/docs/usage/tables.md +++ b/docs/usage/tables.md @@ -4,10 +4,13 @@ You can create tables with `docx`. More information can be found [here](http://o ## Create Table -To create a table, simply use the `createTable()` method on a `document`. +To create a table, simply create one with `new Table()`, then add it to the document: `doc.addTable()`. ```ts -const table = doc.createTable([NUMBER OF ROWS], [NUMBER OF COLUMNS]); +const table = doc.addTable(new Table({ + rows: [NUMBER OF ROWS], + columns: [NUMBER OF COLUMNS] +}); ``` Alternatively, you can create a table object directly, and then add it in the `document` @@ -20,11 +23,10 @@ doc.addTable(table); The snippet below creates a table of 2 rows and 4 columns. ```ts -const table = doc.createTable(2, 4); - -// Or - -const table = new Table(2, 4); +const table = new Table({ + rows: 2, + columns: 4, +}); doc.addTable(table); ``` @@ -70,7 +72,7 @@ column.getCell(index); ## Cells -The `createTable()` method created a table with cells. To access the cell, use the `getCell()` method. +To access the cell, use the `getCell()` method. ```ts const cell = table.getCell([ROW INDEX], [COLUMN INDEX]); @@ -103,10 +105,11 @@ You can specify the width of a cell using: `cell.Properties.setWidth(width, format)` format can be: -* WidthType.AUTO -* WidthType.DXA: value is in twentieths of a point -* WidthType.NIL: is considered as zero -* WidthType.PCT: percent of table width + +- WidthType.AUTO +- WidthType.DXA: value is in twentieths of a point +- WidthType.NIL: is considered as zero +- WidthType.PCT: percent of table width ### Example @@ -115,7 +118,7 @@ cell.Properties.setWidth(100, WidthType.DXA); ``` ```ts -cell.Properties.setWidth('50%', WidthType.PCT); +cell.Properties.setWidth("50%", WidthType.PCT); ``` ## Borders @@ -241,11 +244,10 @@ If a table is paginated on multiple pages, it is possible to repeat a row at the ```ts table.getRow(0).setTableHeader(); ``` - ## Examples -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_ @@ -253,7 +255,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_ Example showing how to add colourful borders to tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_ @@ -261,11 +263,11 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_ Example showing how to add images to tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo24.ts_ -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo36.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo36.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo36.ts_ @@ -273,7 +275,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo36.ts_ Example showing how align text in a table cell -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo31.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo31.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo31.ts_ @@ -281,11 +283,11 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo31.ts_ Example showing merging of `rows` -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo32.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo32.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo32.ts_ -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo41.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo41.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo41.ts_ @@ -293,13 +295,12 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo41.ts_ Example showing merging of `columns` -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo43.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo43.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo43.ts_ ### Floating tables -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo34.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo34.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo34.ts_ - diff --git a/src/file/document/document.spec.ts b/src/file/document/document.spec.ts index 6b20515138..780dca0f27 100644 --- a/src/file/document/document.spec.ts +++ b/src/file/document/document.spec.ts @@ -2,7 +2,6 @@ import { assert, expect } from "chai"; import { Formatter } from "export/formatter"; -import { Table } from "../table"; import { Document } from "./document"; describe("Document", () => { @@ -29,40 +28,4 @@ describe("Document", () => { expect(body[0]).to.have.property("w:sectPr"); }); }); - - describe("#createTable", () => { - it("should create a new table and append it to body", () => { - const table = document.createTable({ - rows: 2, - columns: 3, - }); - expect(table).to.be.an.instanceof(Table); - const body = new Formatter().format(document)["w:document"][1]["w:body"]; - expect(body) - .to.be.an("array") - .which.has.length.at.least(1); - expect(body[0]).to.have.property("w:tbl"); - }); - - it("should create a table with the correct dimensions", () => { - document.createTable({ - rows: 2, - columns: 3, - }); - const body = new Formatter().format(document)["w:document"][1]["w:body"]; - expect(body) - .to.be.an("array") - .which.has.length.at.least(1); - expect(body[0]) - .to.have.property("w:tbl") - .which.includes({ - "w:tblGrid": [ - { "w:gridCol": { _attr: { "w:w": 100 } } }, - { "w:gridCol": { _attr: { "w:w": 100 } } }, - { "w:gridCol": { _attr: { "w:w": 100 } } }, - ], - }); - expect(body[0]["w:tbl"].filter((x) => x["w:tr"])).to.have.length(2); - }); - }); }); diff --git a/src/file/document/document.ts b/src/file/document/document.ts index 8c36c70a84..c517124ef3 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -1,7 +1,7 @@ // http://officeopenxml.com/WPdocument.php import { XmlComponent } from "file/xml-components"; import { Paragraph } from "../paragraph"; -import { ITableOptions, Table } from "../table"; +import { Table } from "../table"; import { TableOfContents } from "../table-of-contents"; import { Body } from "./body"; import { SectionPropertiesOptions } from "./body/section-properties"; @@ -52,12 +52,6 @@ export class Document extends XmlComponent { return this; } - public createTable(options: ITableOptions): Table { - const table = new Table(options); - this.addTable(table); - return table; - } - public get Body(): Body { return this.body; } diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 33a2c09432..d406070443 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -104,19 +104,6 @@ describe("File", () => { }); }); - describe("#createTable", () => { - it("should call the underlying document's createTable", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "createTable"); - wrapper.createTable({ - rows: 1, - columns: 1, - }); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addTableOfContents", () => { it("should call the underlying document's addTableOfContents", () => { const wrapper = new File(); diff --git a/src/file/file.ts b/src/file/file.ts index bb27abb411..4b9fa58514 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -24,7 +24,7 @@ import { Settings } from "./settings"; import { Styles } from "./styles"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; import { DefaultStylesFactory } from "./styles/factory"; -import { ITableOptions, Table } from "./table"; +import { Table } from "./table"; import { TableOfContents } from "./table-of-contents"; export class File { @@ -127,10 +127,6 @@ export class File { return this; } - public createTable(options: ITableOptions): Table { - return this.document.createTable(options); - } - public addImage(image: Image): File { this.document.addParagraph(image.Paragraph); return this; diff --git a/src/file/footer-wrapper.spec.ts b/src/file/footer-wrapper.spec.ts index 90f9e71865..37121f0813 100644 --- a/src/file/footer-wrapper.spec.ts +++ b/src/file/footer-wrapper.spec.ts @@ -32,16 +32,6 @@ describe("FooterWrapper", () => { }); }); - describe("#createTable", () => { - it("should call the underlying footer's createTable", () => { - const wrapper = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Footer, "createTable"); - wrapper.createTable(1, 1); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addImage", () => { it("should call the underlying footer's addImage", () => { const file = new FooterWrapper(new Media(), 1); @@ -56,12 +46,11 @@ describe("FooterWrapper", () => { describe("#createImage", () => { it("should call the underlying footer's createImage", () => { const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(file.Media, "addMedia"); - const fileSpy = sinon.spy(file, "addImage"); + const spy = sinon.spy(Media, "addImage"); file.createImage(""); expect(spy.called).to.equal(true); - expect(fileSpy.called).to.equal(true); + spy.restore(); }); }); diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index b8302dc5ca..b2d5e503f4 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -1,9 +1,10 @@ import { XmlComponent } from "file/xml-components"; import { FooterReferenceType } from "./document"; +import { IDrawingOptions } from "./drawing"; import { Footer } from "./footer/footer"; import { Image, Media } from "./media"; -import { ImageParagraph, Paragraph } from "./paragraph"; +import { Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Table } from "./table"; @@ -29,22 +30,26 @@ export class FooterWrapper { this.footer.addTable(table); } - public createTable(rows: number, cols: number): Table { - return this.footer.createTable(rows, cols); + public addImage(image: Image): FooterWrapper { + this.footer.addParagraph(image.Paragraph); + return this; } public addChildElement(childElement: XmlComponent): void { this.footer.addChildElement(childElement); } - public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void { - const mediaData = this.media.addMedia(image, width, height); - this.addImage(new Image(new ImageParagraph(mediaData))); - } + public createImage( + buffer: Buffer | string | Uint8Array | ArrayBuffer, + width?: number, + height?: number, + drawingOptions?: IDrawingOptions, + ): Paragraph { + const image = Media.addImage(this, buffer, width, height, drawingOptions); + const paragraph = new Paragraph(image); + this.addParagraph(paragraph); - public addImage(image: Image): FooterWrapper { - this.footer.addParagraph(image.Paragraph); - return this; + return paragraph; } public get Footer(): Footer { diff --git a/src/file/footer/footer.ts b/src/file/footer/footer.ts index cbd69a8a3d..bd2a76bd96 100644 --- a/src/file/footer/footer.ts +++ b/src/file/footer/footer.ts @@ -45,13 +45,4 @@ export class Footer extends InitializableXmlComponent { public addTable(table: Table): void { this.root.push(table); } - - public createTable(rows: number, cols: number): Table { - const table = new Table({ - rows: rows, - columns: cols, - }); - this.addTable(table); - return table; - } } diff --git a/src/file/header-wrapper.spec.ts b/src/file/header-wrapper.spec.ts index 01e54847ca..202f034f13 100644 --- a/src/file/header-wrapper.spec.ts +++ b/src/file/header-wrapper.spec.ts @@ -32,16 +32,6 @@ describe("HeaderWrapper", () => { }); }); - describe("#createTable", () => { - it("should call the underlying header's createTable", () => { - const wrapper = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Header, "createTable"); - wrapper.createTable(1, 1); - - expect(spy.called).to.equal(true); - }); - }); - describe("#addImage", () => { it("should call the underlying header's addImage", () => { const file = new HeaderWrapper(new Media(), 1); @@ -56,12 +46,11 @@ describe("HeaderWrapper", () => { describe("#createImage", () => { it("should call the underlying header's createImage", () => { const file = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(file.Media, "addMedia"); - const fileSpy = sinon.spy(file, "addImage"); + const spy = sinon.spy(Media, "addImage"); file.createImage(""); expect(spy.called).to.equal(true); - expect(fileSpy.called).to.equal(true); + spy.restore(); }); }); diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index b06dbb4933..4bc4134f08 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -1,9 +1,10 @@ import { XmlComponent } from "file/xml-components"; import { HeaderReferenceType } from "./document"; +import { IDrawingOptions } from "./drawing"; import { Header } from "./header/header"; import { Image, Media } from "./media"; -import { ImageParagraph, Paragraph } from "./paragraph"; +import { Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Table } from "./table"; @@ -29,22 +30,26 @@ export class HeaderWrapper { this.header.addTable(table); } - public createTable(rows: number, cols: number): Table { - return this.header.createTable(rows, cols); + public addImage(image: Image): HeaderWrapper { + this.header.addParagraph(image.Paragraph); + return this; } public addChildElement(childElement: XmlComponent | string): void { this.header.addChildElement(childElement); } - public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void { - const mediaData = this.media.addMedia(image, width, height); - this.addImage(new Image(new ImageParagraph(mediaData))); - } + public createImage( + buffer: Buffer | string | Uint8Array | ArrayBuffer, + width?: number, + height?: number, + drawingOptions?: IDrawingOptions, + ): Paragraph { + const image = Media.addImage(this, buffer, width, height, drawingOptions); + const paragraph = new Paragraph(image); + this.addParagraph(paragraph); - public addImage(image: Image): HeaderWrapper { - this.header.addParagraph(image.Paragraph); - return this; + return paragraph; } public get Header(): Header { diff --git a/src/file/header/header.ts b/src/file/header/header.ts index 65a89e4943..67c889446d 100644 --- a/src/file/header/header.ts +++ b/src/file/header/header.ts @@ -56,13 +56,4 @@ export class Header extends InitializableXmlComponent { public addTable(table: Table): void { this.root.push(table); } - - public createTable(rows: number, cols: number): Table { - const table = new Table({ - rows: rows, - columns: cols, - }); - this.addTable(table); - return table; - } } diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 75087a66ab..0d062c6d64 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,12 +1,14 @@ import { IDrawingOptions } from "../drawing"; import { File } from "../file"; +import { FooterWrapper } from "../footer-wrapper"; +import { HeaderWrapper } from "../header-wrapper"; import { PictureRun } from "../paragraph"; import { IMediaData } from "./data"; // import { Image } from "./image"; export class Media { public static addImage( - file: File, + file: File | HeaderWrapper | FooterWrapper, buffer: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number, diff --git a/src/file/paragraph/paragraph.ts.orig b/src/file/paragraph/paragraph.ts.orig deleted file mode 100644 index 7ffbeca43d..0000000000 --- a/src/file/paragraph/paragraph.ts.orig +++ /dev/null @@ -1,243 +0,0 @@ -// http://officeopenxml.com/WPparagraph.php -import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"; -import { Image } from "file/media"; -import { Num } from "file/numbering/num"; -import { XmlComponent } from "file/xml-components"; - -import { Alignment } from "./formatting/alignment"; -import { Bidirectional } from "./formatting/bidirectional"; -<<<<<<< HEAD -import { Border, ThematicBreak } from "./formatting/border"; -import { Indent } from "./formatting/indent"; -======= -import { ThematicBreak } from "./formatting/border"; -import { IIndentAttributesProperties, Indent } from "./formatting/indent"; ->>>>>>> a53818754a1c76b9930ee2ecc642570170fa3c06 -import { KeepLines, KeepNext } from "./formatting/keep"; -import { PageBreak, PageBreakBefore } from "./formatting/page-break"; -import { ISpacingProperties, Spacing } from "./formatting/spacing"; -import { Style } from "./formatting/style"; -import { CenterTabStop, LeftTabStop, MaxRightTabStop, RightTabStop } from "./formatting/tab-stop"; -import { NumberProperties } from "./formatting/unordered-list"; -import { Bookmark, Hyperlink } from "./links"; -import { ParagraphProperties } from "./properties"; -import { PictureRun, Run, TextRun } from "./run"; - -export class Paragraph extends XmlComponent { - private readonly properties: ParagraphProperties; - - constructor(text?: string) { - super("w:p"); - this.properties = new ParagraphProperties(); - this.root.push(this.properties); - if (text !== undefined) { - this.root.push(new TextRun(text)); - } - } - - public get Borders(): Border { - return this.properties.paragraphBorder; - } - - public createBorder(): Paragraph { - this.properties.createBorder(); - return this; - } - - public addRun(run: Run): Paragraph { - this.root.push(run); - return this; - } - - public addHyperLink(hyperlink: Hyperlink): Paragraph { - this.root.push(hyperlink); - return this; - } - - public addBookmark(bookmark: Bookmark): Paragraph { - // Bookmarks by spec have three components, a start, text, and end - this.root.push(bookmark.start); - this.root.push(bookmark.text); - this.root.push(bookmark.end); - return this; - } - - public createTextRun(text: string): TextRun { - const run = new TextRun(text); - this.addRun(run); - return run; - } - - public addImage(image: Image): PictureRun { - const run = image.Run; - this.addRun(run); - - return run; - } - - public heading1(): Paragraph { - this.properties.push(new Style("Heading1")); - return this; - } - - public heading2(): Paragraph { - this.properties.push(new Style("Heading2")); - return this; - } - - public heading3(): Paragraph { - this.properties.push(new Style("Heading3")); - return this; - } - - public heading4(): Paragraph { - this.properties.push(new Style("Heading4")); - return this; - } - - public heading5(): Paragraph { - this.properties.push(new Style("Heading5")); - return this; - } - - public heading6(): Paragraph { - this.properties.push(new Style("Heading6")); - return this; - } - - public title(): Paragraph { - this.properties.push(new Style("Title")); - return this; - } - - public center(): Paragraph { - this.properties.push(new Alignment("center")); - return this; - } - - public left(): Paragraph { - this.properties.push(new Alignment("left")); - return this; - } - - public right(): Paragraph { - this.properties.push(new Alignment("right")); - return this; - } - - public start(): Paragraph { - this.properties.push(new Alignment("start")); - return this; - } - - public end(): Paragraph { - this.properties.push(new Alignment("end")); - return this; - } - - public distribute(): Paragraph { - this.properties.push(new Alignment("distribute")); - return this; - } - - public justified(): Paragraph { - this.properties.push(new Alignment("both")); - return this; - } - - public thematicBreak(): Paragraph { - this.properties.push(new ThematicBreak()); - return this; - } - - public pageBreak(): Paragraph { - this.root.push(new PageBreak()); - return this; - } - - public pageBreakBefore(): Paragraph { - this.properties.push(new PageBreakBefore()); - return this; - } - - public maxRightTabStop(): Paragraph { - this.properties.push(new MaxRightTabStop()); - return this; - } - - public leftTabStop(position: number): Paragraph { - this.properties.push(new LeftTabStop(position)); - return this; - } - - public rightTabStop(position: number): Paragraph { - this.properties.push(new RightTabStop(position)); - return this; - } - - public centerTabStop(position: number): Paragraph { - this.properties.push(new CenterTabStop(position)); - return this; - } - - public bullet(indentLevel: number = 0): Paragraph { - this.properties.push(new Style("ListParagraph")); - this.properties.push(new NumberProperties(1, indentLevel)); - return this; - } - - public setNumbering(numbering: Num, indentLevel: number): Paragraph { - this.properties.push(new Style("ListParagraph")); - this.properties.push(new NumberProperties(numbering.id, indentLevel)); - return this; - } - - public setCustomNumbering(numberId: number, indentLevel: number): Paragraph { - this.properties.push(new NumberProperties(numberId, indentLevel)); - return this; - } - - public style(styleId: string): Paragraph { - this.properties.push(new Style(styleId)); - return this; - } - - public indent(attrs: IIndentAttributesProperties): Paragraph { - this.properties.push(new Indent(attrs)); - return this; - } - - public spacing(params: ISpacingProperties): Paragraph { - this.properties.push(new Spacing(params)); - return this; - } - - public keepNext(): Paragraph { - this.properties.push(new KeepNext()); - return this; - } - - public keepLines(): Paragraph { - this.properties.push(new KeepLines()); - return this; - } - - public referenceFootnote(id: number): Paragraph { - this.root.push(new FootnoteReferenceRun(id)); - return this; - } - - public addRunToFront(run: Run): Paragraph { - this.root.splice(1, 0, run); - return this; - } - - public bidirectional(): Paragraph { - this.properties.push(new Bidirectional()); - return this; - } - - public get Properties(): ParagraphProperties { - return this.properties; - } -} diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts index 99acef0b31..830797dbed 100644 --- a/src/file/table/table-cell/table-cell.ts +++ b/src/file/table/table-cell/table-cell.ts @@ -8,6 +8,10 @@ import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins"; import { TableCellBorders, VerticalAlign, VMergeType } from "./table-cell-components"; import { TableCellProperties } from "./table-cell-properties"; +export interface ITableCellOptions { + readonly shading?: ITableShadingAttributesProperties; +} + export class TableCell extends XmlComponent { private readonly properties: TableCellProperties; From 384d144a857b5a4e2a598c57235c015ae4652391 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 25 Jun 2019 01:52:02 +0100 Subject: [PATCH 08/38] Simplify multiple addXXX methods into a single add method --- src/export/packer/packer.spec.ts | 8 ++++---- src/file/file.spec.ts | 16 ++++++---------- src/file/file.ts | 26 +++++++++++--------------- src/file/header-wrapper.spec.ts | 18 ++++++++---------- src/file/header-wrapper.ts | 12 +++++------- src/file/header/header.ts | 8 ++------ 6 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index 944b5892e2..201f5eb38d 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -22,20 +22,20 @@ describe("Packer", () => { heading: HeadingLevel.HEADING_1, }); - file.addParagraph( + file.add( new Paragraph({ text: "title", heading: HeadingLevel.TITLE, }), ); - file.addParagraph(heading); - file.addParagraph( + file.add(heading); + file.add( new Paragraph({ text: "heading 2", heading: HeadingLevel.HEADING_2, }), ); - file.addParagraph(paragraph); + file.add(paragraph); packer = new Packer(); }); diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index d406070443..6b0b7aa251 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -6,6 +6,7 @@ import { Formatter } from "export/formatter"; import { File } from "./file"; import { Paragraph } from "./paragraph"; import { Table } from "./table"; +import { TableOfContents } from "./table-of-contents"; describe("File", () => { describe("#constructor", () => { @@ -83,17 +84,17 @@ describe("File", () => { it("should call the underlying document's addParagraph", () => { const file = new File(); const spy = sinon.spy(file.Document, "addParagraph"); - file.addParagraph(new Paragraph({})); + file.add(new Paragraph({})); expect(spy.called).to.equal(true); }); }); - describe("#addTable", () => { + describe("#add", () => { it("should call the underlying document's addTable", () => { const wrapper = new File(); const spy = sinon.spy(wrapper.Document, "addTable"); - wrapper.addTable( + wrapper.add( new Table({ rows: 1, columns: 1, @@ -102,25 +103,20 @@ describe("File", () => { expect(spy.called).to.equal(true); }); - }); - describe("#addTableOfContents", () => { it("should call the underlying document's addTableOfContents", () => { const wrapper = new File(); const spy = sinon.spy(wrapper.Document, "addTableOfContents"); - // tslint:disable-next-line:no-any - wrapper.addTableOfContents({} as any); + wrapper.add(new TableOfContents()); expect(spy.called).to.equal(true); }); - }); - describe("#addImage", () => { it("should call the underlying document's addImage", () => { const wrapper = new File(); const spy = sinon.spy(wrapper.Document, "addParagraph"); // tslint:disable-next-line:no-any - wrapper.addImage({} as any); + wrapper.add(new Paragraph("")); expect(spy.called).to.equal(true); }); diff --git a/src/file/file.ts b/src/file/file.ts index 4b9fa58514..26848c8e5b 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -15,7 +15,7 @@ import { IFileProperties } from "./file-properties"; import { FooterWrapper, IDocumentFooter } from "./footer-wrapper"; import { FootNotes } from "./footnotes"; import { HeaderWrapper, IDocumentHeader } from "./header-wrapper"; -import { Image, Media } from "./media"; +import { Media } from "./media"; import { Numbering } from "./numbering"; import { Bookmark, Hyperlink, Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; @@ -112,23 +112,19 @@ export class File { this.settings = new Settings(); } - public addTableOfContents(toc: TableOfContents): File { - this.document.addTableOfContents(toc); - return this; - } + public add(item: Paragraph | Table | TableOfContents): File { + if (item instanceof Paragraph) { + this.document.addParagraph(item); + } - public addParagraph(paragraph: Paragraph): File { - this.document.addParagraph(paragraph); - return this; - } + if (item instanceof Table) { + this.document.addTable(item); + } - public addTable(table: Table): File { - this.document.addTable(table); - return this; - } + if (item instanceof TableOfContents) { + this.document.addTableOfContents(item); + } - public addImage(image: Image): File { - this.document.addParagraph(image.Paragraph); return this; } diff --git a/src/file/header-wrapper.spec.ts b/src/file/header-wrapper.spec.ts index 202f034f13..0640ca41f5 100644 --- a/src/file/header-wrapper.spec.ts +++ b/src/file/header-wrapper.spec.ts @@ -7,21 +7,19 @@ import { Paragraph } from "./paragraph"; import { Table } from "./table"; describe("HeaderWrapper", () => { - describe("#addParagraph", () => { - it("should call the underlying header's addParagraph", () => { + describe("#add", () => { + it("should call the underlying header's addChildElement for Paragraph", () => { const wrapper = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Header, "addParagraph"); - wrapper.addParagraph(new Paragraph({})); + const spy = sinon.spy(wrapper.Header, "addChildElement"); + wrapper.add(new Paragraph({})); expect(spy.called).to.equal(true); }); - }); - describe("#addTable", () => { - it("should call the underlying header's addTable", () => { + it("should call the underlying header's addChildElement for Table", () => { const wrapper = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Header, "addTable"); - wrapper.addTable( + const spy = sinon.spy(wrapper.Header, "addChildElement"); + wrapper.add( new Table({ rows: 1, columns: 1, @@ -35,7 +33,7 @@ describe("HeaderWrapper", () => { describe("#addImage", () => { it("should call the underlying header's addImage", () => { const file = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(file.Header, "addParagraph"); + const spy = sinon.spy(file.Header, "add"); // tslint:disable-next-line:no-any file.addImage({} as any); diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index 4bc4134f08..bd445dbe9f 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -22,16 +22,14 @@ export class HeaderWrapper { this.relationships = new Relationships(); } - public addParagraph(paragraph: Paragraph): void { - this.header.addParagraph(paragraph); - } + public add(item: Paragraph | Table): HeaderWrapper { + this.header.addChildElement(item); - public addTable(table: Table): void { - this.header.addTable(table); + return this; } public addImage(image: Image): HeaderWrapper { - this.header.addParagraph(image.Paragraph); + this.header.add(image.Paragraph); return this; } @@ -47,7 +45,7 @@ export class HeaderWrapper { ): Paragraph { const image = Media.addImage(this, buffer, width, height, drawingOptions); const paragraph = new Paragraph(image); - this.addParagraph(paragraph); + this.add(paragraph); return paragraph; } diff --git a/src/file/header/header.ts b/src/file/header/header.ts index 67c889446d..8c63a6723c 100644 --- a/src/file/header/header.ts +++ b/src/file/header/header.ts @@ -49,11 +49,7 @@ export class Header extends InitializableXmlComponent { return this.refId; } - public addParagraph(paragraph: Paragraph): void { - this.root.push(paragraph); - } - - public addTable(table: Table): void { - this.root.push(table); + public add(item: Paragraph | Table): void { + this.root.push(item); } } From b566b0f76514edba113cac1245bea4136aa33f07 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 25 Jun 2019 01:58:09 +0100 Subject: [PATCH 09/38] Simplify multiple addXXX methods into a single add method for Footer --- src/file/footer-wrapper.spec.ts | 16 ++++++---------- src/file/footer-wrapper.ts | 12 ++++-------- src/file/footer/footer.ts | 10 ++-------- src/file/header-wrapper.spec.ts | 4 ++-- src/file/header-wrapper.ts | 2 +- 5 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/file/footer-wrapper.spec.ts b/src/file/footer-wrapper.spec.ts index 37121f0813..882e47fadf 100644 --- a/src/file/footer-wrapper.spec.ts +++ b/src/file/footer-wrapper.spec.ts @@ -7,21 +7,19 @@ import { Paragraph } from "./paragraph"; import { Table } from "./table"; describe("FooterWrapper", () => { - describe("#addParagraph", () => { + describe("#add", () => { it("should call the underlying footer's addParagraph", () => { const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(file.Footer, "addParagraph"); - file.addParagraph(new Paragraph({})); + const spy = sinon.spy(file.Footer, "add"); + file.add(new Paragraph({})); expect(spy.called).to.equal(true); }); - }); - describe("#addTable", () => { it("should call the underlying footer's addParagraph", () => { const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(file.Footer, "addTable"); - file.addTable( + const spy = sinon.spy(file.Footer, "add"); + file.add( new Table({ rows: 1, columns: 1, @@ -30,12 +28,10 @@ describe("FooterWrapper", () => { expect(spy.called).to.equal(true); }); - }); - describe("#addImage", () => { it("should call the underlying footer's addImage", () => { const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(file.Footer, "addParagraph"); + const spy = sinon.spy(file.Footer, "add"); // tslint:disable-next-line:no-any file.addImage({} as any); diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index b2d5e503f4..ebd0610a23 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -22,16 +22,12 @@ export class FooterWrapper { this.relationships = new Relationships(); } - public addParagraph(paragraph: Paragraph): void { - this.footer.addParagraph(paragraph); - } - - public addTable(table: Table): void { - this.footer.addTable(table); + public add(item: Paragraph | Table): void { + this.footer.add(item); } public addImage(image: Image): FooterWrapper { - this.footer.addParagraph(image.Paragraph); + this.footer.add(image.Paragraph); return this; } @@ -47,7 +43,7 @@ export class FooterWrapper { ): Paragraph { const image = Media.addImage(this, buffer, width, height, drawingOptions); const paragraph = new Paragraph(image); - this.addParagraph(paragraph); + this.add(paragraph); return paragraph; } diff --git a/src/file/footer/footer.ts b/src/file/footer/footer.ts index bd2a76bd96..cfac9b8d9a 100644 --- a/src/file/footer/footer.ts +++ b/src/file/footer/footer.ts @@ -36,13 +36,7 @@ export class Footer extends InitializableXmlComponent { return this.refId; } - public addParagraph(paragraph: Paragraph): Footer { - this.root.push(paragraph); - - return this; - } - - public addTable(table: Table): void { - this.root.push(table); + public add(item: Paragraph | Table): void { + this.root.push(item); } } diff --git a/src/file/header-wrapper.spec.ts b/src/file/header-wrapper.spec.ts index 0640ca41f5..0d10b5818a 100644 --- a/src/file/header-wrapper.spec.ts +++ b/src/file/header-wrapper.spec.ts @@ -10,7 +10,7 @@ describe("HeaderWrapper", () => { describe("#add", () => { it("should call the underlying header's addChildElement for Paragraph", () => { const wrapper = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Header, "addChildElement"); + const spy = sinon.spy(wrapper.Header, "add"); wrapper.add(new Paragraph({})); expect(spy.called).to.equal(true); @@ -18,7 +18,7 @@ describe("HeaderWrapper", () => { it("should call the underlying header's addChildElement for Table", () => { const wrapper = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(wrapper.Header, "addChildElement"); + const spy = sinon.spy(wrapper.Header, "add"); wrapper.add( new Table({ rows: 1, diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index bd445dbe9f..58826ec03b 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -23,7 +23,7 @@ export class HeaderWrapper { } public add(item: Paragraph | Table): HeaderWrapper { - this.header.addChildElement(item); + this.header.add(item); return this; } From 3ef8f5311d69ac713cdfbb2c4f52fdca8c755ec2 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 25 Jun 2019 20:57:46 +0100 Subject: [PATCH 10/38] Make fixed layout declaritive --- demo/demo34.ts | 5 +-- src/file/paragraph/formatting/border.ts | 2 -- src/file/table/table-properties/index.ts | 1 + .../table-properties/table-properties.spec.ts | 6 ++-- .../table-properties/table-properties.ts | 5 ++- src/file/table/table.spec.ts | 34 +++++++++---------- src/file/table/table.ts | 12 ++++--- 7 files changed, 34 insertions(+), 31 deletions(-) diff --git a/demo/demo34.ts b/demo/demo34.ts index 678094988f..365fc00845 100644 --- a/demo/demo34.ts +++ b/demo/demo34.ts @@ -9,6 +9,7 @@ import { RelativeVerticalPosition, Table, TableAnchorType, + TableLayoutType, WidthType, } from "../build"; @@ -25,10 +26,10 @@ const table = new Table({ }, width: 4535, widthUnitType: WidthType.DXA, + layout: TableLayoutType.FIXED, }); -doc.addTable(table); -table.setFixedWidthLayout(); +doc.add(table); table.getCell(0, 0).addParagraph(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); diff --git a/src/file/paragraph/formatting/border.ts b/src/file/paragraph/formatting/border.ts index d44bc51c06..9fdb9b65c3 100644 --- a/src/file/paragraph/formatting/border.ts +++ b/src/file/paragraph/formatting/border.ts @@ -27,8 +27,6 @@ class BorderProperty extends XmlComponent { sz: options.size, }); this.root.push(attrs); - - return this; } } diff --git a/src/file/table/table-properties/index.ts b/src/file/table/table-properties/index.ts index 913c3a7839..dde973ee7a 100644 --- a/src/file/table/table-properties/index.ts +++ b/src/file/table/table-properties/index.ts @@ -1,2 +1,3 @@ export * from "./table-properties"; export * from "./table-float-properties"; +export * from "./table-layout"; diff --git a/src/file/table/table-properties/table-properties.spec.ts b/src/file/table/table-properties/table-properties.spec.ts index c5bc54d2b9..dbd1c6b371 100644 --- a/src/file/table/table-properties/table-properties.spec.ts +++ b/src/file/table/table-properties/table-properties.spec.ts @@ -3,6 +3,7 @@ import { expect } from "chai"; import { Formatter } from "export/formatter"; import { WidthType } from "../table-cell"; +import { TableLayoutType } from "./table-layout"; import { TableProperties } from "./table-properties"; describe("TableProperties", () => { @@ -35,9 +36,10 @@ describe("TableProperties", () => { }); }); - describe("#setFixedWidthLayout", () => { + describe("#setLayout", () => { it("sets the table to fixed width layout", () => { - const tp = new TableProperties().setFixedWidthLayout(); + const tp = new TableProperties(); + tp.setLayout(TableLayoutType.FIXED); const tree = new Formatter().format(tp); expect(tree).to.deep.equal({ "w:tblPr": [{ "w:tblLayout": { _attr: { "w:type": "fixed" } } }], diff --git a/src/file/table/table-properties/table-properties.ts b/src/file/table/table-properties/table-properties.ts index 4067b2b3dc..fd1f844978 100644 --- a/src/file/table/table-properties/table-properties.ts +++ b/src/file/table/table-properties/table-properties.ts @@ -23,9 +23,8 @@ export class TableProperties extends IgnoreIfEmptyXmlComponent { return this; } - public setFixedWidthLayout(): TableProperties { - this.root.push(new TableLayout(TableLayoutType.FIXED)); - return this; + public setLayout(type: TableLayoutType): void { + this.root.push(new TableLayout(type)); } public setBorder(): TableProperties { diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index de814ace20..70fc2db165 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -9,6 +9,7 @@ import { Table } from "./table"; import { RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType } from "./table-properties"; import { EMPTY_OBJECT } from "file/xml-components"; +import { TableLayoutType } from "./table-properties/table-layout"; const DEFAULT_TABLE_PROPERTIES = { "w:tblCellMar": [ @@ -134,6 +135,22 @@ describe("Table", () => { ], }); }); + + it("sets the table to fixed width layout", () => { + const table = new Table({ + rows: 1, + columns: 1, + layout: TableLayoutType.FIXED, + }); + const tree = new Formatter().format(table); + expect(tree) + .to.have.property("w:tbl") + .which.is.an("array") + .with.has.length.at.least(1); + expect(tree["w:tbl"][0]).to.deep.equal({ + "w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS, { "w:tblLayout": { _attr: { "w:type": "fixed" } } }], + }); + }); }); describe("#getRow and Row#getCell", () => { @@ -252,23 +269,6 @@ describe("Table", () => { // }); // }); - describe("#setFixedWidthLayout", () => { - it("sets the table to fixed width layout", () => { - const table = new Table({ - rows: 1, - columns: 1, - }).setFixedWidthLayout(); - const tree = new Formatter().format(table); - expect(tree) - .to.have.property("w:tbl") - .which.is.an("array") - .with.has.length.at.least(1); - expect(tree["w:tbl"][0]).to.deep.equal({ - "w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS, { "w:tblLayout": { _attr: { "w:type": "fixed" } } }], - }); - }); - }); - describe("Cell", () => { describe("#prepForXml", () => { it("inserts a paragraph at the end of the cell if it is empty", () => { diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 9a99ce0408..c56bc4d62c 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -5,6 +5,7 @@ import { TableGrid } from "./grid"; import { TableCell, WidthType } from "./table-cell"; import { TableColumn } from "./table-column"; import { ITableFloatOptions, TableProperties } from "./table-properties"; +import { TableLayoutType } from "./table-properties/table-layout"; import { TableRow } from "./table-row"; /* 0-width columns don't get rendered correctly, so we need @@ -30,6 +31,7 @@ export interface ITableOptions { readonly left?: number; }; readonly float?: ITableFloatOptions; + readonly layout?: TableLayoutType; } export class Table extends XmlComponent { @@ -44,6 +46,7 @@ export class Table extends XmlComponent { columnWidths = Array(columns).fill(100), margins: { marginUnitType, top, bottom, right, left } = { marginUnitType: WidthType.AUTO, top: 0, bottom: 0, right: 0, left: 0 }, float, + layout, }: ITableOptions) { super("w:tbl"); this.properties = new TableProperties(); @@ -73,6 +76,10 @@ export class Table extends XmlComponent { if (float) { this.properties.setTableFloatProperties(float); } + + if (layout) { + this.properties.setLayout(layout); + } } public getRow(index: number): TableRow { @@ -94,9 +101,4 @@ export class Table extends XmlComponent { public getCell(row: number, col: number): TableCell { return this.getRow(row).getCell(col); } - - public setFixedWidthLayout(): Table { - this.properties.setFixedWidthLayout(); - return this; - } } From e2574ec23bd828c342cde61f3c02e5c800302486 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 25 Jun 2019 23:17:56 +0100 Subject: [PATCH 11/38] Turn methods into "add()" --- demo/browser-demo.html | 2 +- demo/demo1.ts | 2 +- demo/demo10.ts | 42 ++++++++++++------------- demo/demo11.ts | 26 +++++++-------- demo/demo12.ts | 2 +- demo/demo13.ts | 10 +++--- demo/demo14.ts | 8 ++--- demo/demo15.ts | 4 +-- demo/demo16.ts | 18 +++++------ demo/demo17.ts | 4 +-- demo/demo19.ts | 2 +- demo/demo2.ts | 20 ++++++------ demo/demo20.ts | 4 +-- demo/demo21.ts | 10 +++--- demo/demo22.ts | 6 ++-- demo/demo23.ts | 14 ++++----- demo/demo24.ts | 6 ++-- demo/demo26.ts | 4 +-- demo/demo27.ts | 4 +-- demo/demo28.ts | 14 ++++----- demo/demo29.ts | 10 +++--- demo/demo3.ts | 22 ++++++------- demo/demo30.ts | 2 +- demo/demo31.ts | 6 ++-- demo/demo32.ts | 30 +++++++++--------- demo/demo33.ts | 8 ++--- demo/demo34.ts | 2 +- demo/demo35.ts | 2 +- demo/demo36.ts | 6 ++-- demo/demo37.ts | 2 +- demo/demo38.ts | 6 ++-- demo/demo39.ts | 14 ++++----- demo/demo4.ts | 4 +-- demo/demo40.ts | 6 ++-- demo/demo41.ts | 42 ++++++++++++------------- demo/demo43.ts | 6 ++-- demo/demo5.ts | 2 +- demo/demo6.ts | 8 ++--- demo/demo7.ts | 2 +- demo/demo8.ts | 6 ++-- demo/demo9.ts | 2 +- docs/README.md | 2 +- docs/contribution-guidelines.md | 2 +- docs/usage/bullet-points.md | 4 +-- docs/usage/paragraph.md | 2 +- docs/usage/styling-with-xml.md | 2 +- docs/usage/table-of-contents.md | 14 ++++----- docs/usage/tables.md | 14 ++++----- src/file/document/document.ts | 7 +---- src/file/file.spec.ts | 34 ++++++++++---------- src/file/file.ts | 6 ++-- src/file/footnotes/footnote/footnote.ts | 2 +- src/file/footnotes/footnotes.ts | 6 ++-- src/file/table/table-cell/table-cell.ts | 10 ++---- src/file/table/table.spec.ts | 20 ++++++------ 55 files changed, 253 insertions(+), 262 deletions(-) diff --git a/demo/browser-demo.html b/demo/browser-demo.html index fff5dc7989..535b55beea 100644 --- a/demo/browser-demo.html +++ b/demo/browser-demo.html @@ -22,7 +22,7 @@ paragraph.addRun(institutionText); paragraph.addRun(dateText); - doc.addParagraph(paragraph); + doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo1.ts b/demo/demo1.ts index 83a9a3abd8..c8ed2e4781 100644 --- a/demo/demo1.ts +++ b/demo/demo1.ts @@ -17,7 +17,7 @@ const dateText = new TextRun({ paragraph.addRun(institutionText); paragraph.addRun(dateText); -doc.addParagraph(paragraph); +doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo10.ts b/demo/demo10.ts index 8f312af128..62077cf4c4 100644 --- a/demo/demo10.ts +++ b/demo/demo10.ts @@ -135,70 +135,70 @@ class DocumentCreator { const skills = data[2] as object[]; const achivements = data[3] as object[]; const document = new Document(); - document.addParagraph( + document.add( new Paragraph({ text: "Dolan Miu", heading: HeadingLevel.TITLE, }), ); - document.addParagraph(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); - document.addParagraph(this.createHeading("Education")); + document.add(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); + document.add(this.createHeading("Education")); for (const education of educations) { - document.addParagraph( + document.add( this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`), ); - document.addParagraph(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`)); + document.add(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`)); const bulletPoints = this.splitParagraphIntoBullets(education.notes); bulletPoints.forEach((bulletPoint) => { - document.addParagraph(this.createBullet(bulletPoint)); + document.add(this.createBullet(bulletPoint)); }); } - document.addParagraph(this.createHeading("Experience")); + document.add(this.createHeading("Experience")); for (const position of experiences) { - document.addParagraph( + document.add( this.createInstitutionHeader( position.company.name, this.createPositionDateText(position.startDate, position.endDate, position.isCurrent), ), ); - document.addParagraph(this.createRoleText(position.title)); + document.add(this.createRoleText(position.title)); const bulletPoints = this.splitParagraphIntoBullets(position.summary); bulletPoints.forEach((bulletPoint) => { - document.addParagraph(this.createBullet(bulletPoint)); + document.add(this.createBullet(bulletPoint)); }); } - document.addParagraph(this.createHeading("Skills, Achievements and Interests")); + document.add(this.createHeading("Skills, Achievements and Interests")); - document.addParagraph(this.createSubHeading("Skills")); - document.addParagraph(this.createSkillList(skills)); + document.add(this.createSubHeading("Skills")); + document.add(this.createSkillList(skills)); - document.addParagraph(this.createSubHeading("Achievements")); + document.add(this.createSubHeading("Achievements")); for (const achievementParagraph of this.createAchivementsList(achivements)) { - document.addParagraph(achievementParagraph); + document.add(achievementParagraph); } - document.addParagraph(this.createSubHeading("Interests")); + document.add(this.createSubHeading("Interests")); - document.addParagraph(this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing.")); + document.add(this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing.")); - document.addParagraph(this.createHeading("References")); + document.add(this.createHeading("References")); - document.addParagraph( + document.add( new Paragraph( "Dr. Dean Mohamedally Director of Postgraduate Studies Department of Computer Science, University College London Malet Place, Bloomsbury, London WC1E d.mohamedally@ucl.ac.uk", ), ); - document.addParagraph(new Paragraph("More references upon request")); - document.addParagraph( + document.add(new Paragraph("More references upon request")); + document.add( new Paragraph({ text: "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", alignment: AlignmentType.CENTER, diff --git a/demo/demo11.ts b/demo/demo11.ts index 40c7fe5380..3861447df9 100644 --- a/demo/demo11.ts +++ b/demo/demo11.ts @@ -84,7 +84,7 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") .basedOn("Normal"); doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.addParagraph( +doc.add( new Paragraph({ text: "HEADING", heading: HeadingLevel.HEADING_1, @@ -92,7 +92,7 @@ doc.addParagraph( }), ); -doc.Footer.addParagraph( +doc.Footer.add( new Paragraph({ text: "1", style: "normalPara", @@ -100,54 +100,54 @@ doc.Footer.addParagraph( }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Ref. :", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Date :", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "To,", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "The Superindenting Engineer,(O &M)", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Sub : ", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Ref. : ", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Sir,", style: "normalPara", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "BRIEF DESCRIPTION", style: "normalPara", @@ -161,9 +161,9 @@ const table = new Table({ table .getRow(0) .getCell(0) - .addParagraph(new Paragraph("Pole No.")); + .add(new Paragraph("Pole No.")); -doc.addTable(table); +doc.add(table); const arrboth = [ { @@ -178,7 +178,7 @@ const arrboth = [ arrboth.forEach((item) => { doc.createImage(fs.readFileSync(item.image)); - doc.addParagraph( + doc.add( new Paragraph({ text: item.comment, style: "normalPara2", diff --git a/demo/demo12.ts b/demo/demo12.ts index a3479c3cbf..f27aee4968 100644 --- a/demo/demo12.ts +++ b/demo/demo12.ts @@ -6,7 +6,7 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); const paragraph = new Paragraph("Hello World"); -doc.addParagraph(paragraph); +doc.add(paragraph); const image = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); const image2 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); diff --git a/demo/demo13.ts b/demo/demo13.ts index cd0111deb4..53287c2e1a 100644 --- a/demo/demo13.ts +++ b/demo/demo13.ts @@ -9,7 +9,7 @@ const doc = new Document({ externalStyles: styles, }); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "Cool Heading Text", heading: HeadingLevel.HEADING_1, })); @@ -18,16 +18,16 @@ const paragraph = new Paragraph({ text: 'This is a custom named style from the template "MyFancyStyle"', style: "MyFancyStyle", }); -doc.addParagraph(paragraph); +doc.add(paragraph); -doc.addParagraph(new Paragraph("Some normal text")); +doc.add(new Paragraph("Some normal text")); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "MyFancyStyle again", style: "MyFancyStyle", })); -doc.addParagraph(paragraph); +doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo14.ts b/demo/demo14.ts index ca3e56ac78..310f854301 100644 --- a/demo/demo14.ts +++ b/demo/demo14.ts @@ -5,12 +5,12 @@ import { AlignmentType, Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -doc.addParagraph( +doc.add( new Paragraph({ text: "First Page", }).pageBreak(), ); -doc.addParagraph(new Paragraph("Second Page")); +doc.add(new Paragraph("Second Page")); const pageNumber = new TextRun("Page ").pageNumber(); @@ -21,7 +21,7 @@ const pageoneheader = new Paragraph({ pageoneheader.addRun(pageNumber); const firstPageHeader = doc.createFirstPageHeader(); -firstPageHeader.addParagraph(pageoneheader); +firstPageHeader.add(pageoneheader); const pagetwoheader = new Paragraph({ text: "My Title ", @@ -29,7 +29,7 @@ const pagetwoheader = new Paragraph({ }); pagetwoheader.addRun(pageNumber); -doc.Header.addParagraph(pagetwoheader); +doc.Header.add(pagetwoheader); const packer = new Packer(); diff --git a/demo/demo15.ts b/demo/demo15.ts index 966d2b9e19..f25639bf2f 100644 --- a/demo/demo15.ts +++ b/demo/demo15.ts @@ -11,8 +11,8 @@ const paragraph2 = new Paragraph({ pageBreakBefore: true, }); -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); +doc.add(paragraph); +doc.add(paragraph2); const packer = new Packer(); diff --git a/demo/demo16.ts b/demo/demo16.ts index 161334c626..cd1507d747 100644 --- a/demo/demo16.ts +++ b/demo/demo16.ts @@ -7,12 +7,12 @@ const doc = new Document(); const paragraph = new Paragraph("Hello World").pageBreak(); -doc.addParagraph(paragraph); +doc.add(paragraph); const header = doc.createHeader(); -header.addParagraph(new Paragraph("Header on another page")); +header.add(new Paragraph("Header on another page")); const footer = doc.createFooter(); -footer.addParagraph(new Paragraph("Footer on another page")); +footer.add(new Paragraph("Footer on another page")); doc.addSection({ headers: { @@ -25,7 +25,7 @@ doc.addSection({ pageNumberFormatType: PageNumberFormat.DECIMAL, }); -doc.addParagraph(new Paragraph("hello")); +doc.add(new Paragraph("hello")); doc.addSection({ headers: { @@ -39,11 +39,11 @@ doc.addSection({ orientation: PageOrientation.LANDSCAPE, }); -doc.addParagraph(new Paragraph("hello in landscape")); +doc.add(new Paragraph("hello in landscape")); const header2 = doc.createHeader(); const pageNumber = new TextRun("Page number: ").pageNumber(); -header2.addParagraph(new Paragraph({}).addRun(pageNumber)); +header2.add(new Paragraph({}).addRun(pageNumber)); doc.addSection({ headers: { @@ -52,7 +52,7 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.addParagraph(new Paragraph("Page number in the header must be 2, because it continues from the previous section.")); +doc.add(new Paragraph("Page number in the header must be 2, because it continues from the previous section.")); doc.addSection({ headers: { @@ -62,7 +62,7 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.addParagraph(new Paragraph( +doc.add(new Paragraph( "Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.", )); @@ -75,7 +75,7 @@ doc.addSection({ orientation: PageOrientation.PORTRAIT, }); -doc.addParagraph(new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section.")); +doc.add(new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section.")); const packer = new Packer(); diff --git a/demo/demo17.ts b/demo/demo17.ts index c48a2e67e8..1d928b60b5 100644 --- a/demo/demo17.ts +++ b/demo/demo17.ts @@ -8,8 +8,8 @@ const doc = new Document(); const paragraph = new Paragraph("Hello World").referenceFootnote(1); const paragraph2 = new Paragraph("Hello World").referenceFootnote(2); -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); +doc.add(paragraph); +doc.add(paragraph2); doc.createFootnote(new Paragraph("Test")); doc.createFootnote(new Paragraph("My amazing reference")); diff --git a/demo/demo19.ts b/demo/demo19.ts index 819de0bd74..f8930db836 100644 --- a/demo/demo19.ts +++ b/demo/demo19.ts @@ -17,7 +17,7 @@ const dateText = new TextRun({ paragraph.addRun(institutionText); paragraph.addRun(dateText); -doc.addParagraph(paragraph); +doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo2.ts b/demo/demo2.ts index c15942db5b..5764f40f91 100644 --- a/demo/demo2.ts +++ b/demo/demo2.ts @@ -46,14 +46,14 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") const numberedAbstract = doc.Numbering.createAbstractNumbering(); numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left"); -doc.addParagraph( +doc.add( new Paragraph({ text: "Test heading1, bold and italicized", heading: HeadingLevel.HEADING_1, }), ); -doc.addParagraph(new Paragraph("Some simple content")); -doc.addParagraph( +doc.add(new Paragraph("Some simple content")); +doc.add( new Paragraph({ text: "Test heading2 with double red underline", heading: HeadingLevel.HEADING_2, @@ -64,7 +64,7 @@ const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract); const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract); letterNumbering5.overrideLevel(0, 5); -doc.addParagraph( +doc.add( new Paragraph({ text: "Option1", numbering: { @@ -73,7 +73,7 @@ doc.addParagraph( }, }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Option5 -- override 2 to 5", numbering: { @@ -82,7 +82,7 @@ doc.addParagraph( }, }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Option3", numbering: { @@ -92,7 +92,7 @@ doc.addParagraph( }), ); -doc.addParagraph( +doc.add( new Paragraph({}).addRun( new TextRun({ text: "Some monospaced content", @@ -103,20 +103,20 @@ doc.addParagraph( ), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "An aside, in light gray italics and indented", style: "aside", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "This is normal, but well-spaced text", style: "wellSpaced", }), ); const para = new Paragraph({}); -doc.addParagraph(para); +doc.add(para); // Showing the different ways to create a TextRun para.addRun( new TextRun({ diff --git a/demo/demo20.ts b/demo/demo20.ts index 8038944ed0..b861a10cfa 100644 --- a/demo/demo20.ts +++ b/demo/demo20.ts @@ -10,10 +10,10 @@ const table = new Table({ columns: 4, }); -doc.addTable(table); +doc.add(table); table .getCell(2, 2) - .addParagraph(new Paragraph("Hello")) + .add(new Paragraph("Hello")) .Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red") .addBottomBorder(BorderStyle.DOUBLE, 3, "blue") .addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green") diff --git a/demo/demo21.ts b/demo/demo21.ts index 8e2136c813..5ce3bc2930 100644 --- a/demo/demo21.ts +++ b/demo/demo21.ts @@ -17,20 +17,20 @@ const anchorId = "anchorID"; // First create the bookmark const bookmark = doc.createBookmark(anchorId, "Lorem Ipsum"); // That has header styling -doc.addParagraph( +doc.add( new Paragraph({ heading: HeadingLevel.HEADING_1, }).addBookmark(bookmark), ); -doc.addParagraph(new Paragraph("\n")); +doc.add(new Paragraph("\n")); -doc.addParagraph(new Paragraph(loremIpsum)); -doc.addParagraph(new Paragraph({}).pageBreak()); +doc.add(new Paragraph(loremIpsum)); +doc.add(new Paragraph({}).pageBreak()); // Now the link back up to the bookmark const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); -doc.addParagraph(new Paragraph({}).addHyperLink(hyperlink)); +doc.add(new Paragraph({}).addHyperLink(hyperlink)); const packer = new Packer(); diff --git a/demo/demo22.ts b/demo/demo22.ts index c13d867f5d..c92406071e 100644 --- a/demo/demo22.ts +++ b/demo/demo22.ts @@ -13,7 +13,7 @@ const textRun1 = new TextRun({ rightToLeft: true, }); paragraph1.addRun(textRun1); -doc.addParagraph(paragraph1); +doc.add(paragraph1); const paragraph2 = new Paragraph({ bidirectional: true, @@ -24,7 +24,7 @@ const textRun2 = new TextRun({ rightToLeft: true, }); paragraph2.addRun(textRun2); -doc.addParagraph(paragraph2); +doc.add(paragraph2); const paragraph3 = new Paragraph({ bidirectional: true, @@ -35,7 +35,7 @@ const textRun3 = new TextRun({ rightToLeft: true, }); paragraph3.addRun(textRun3); -doc.addParagraph(paragraph3); +doc.add(paragraph3); const packer = new Packer(); diff --git a/demo/demo23.ts b/demo/demo23.ts index 2e230e0cb7..8cbdac292c 100644 --- a/demo/demo23.ts +++ b/demo/demo23.ts @@ -6,7 +6,7 @@ import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); const paragraph = new Paragraph("Hello World"); -doc.addParagraph(paragraph); +doc.add(paragraph); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png")); @@ -20,12 +20,12 @@ const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, // I am adding an image to the paragraph rather than the document to make the image inline paragraph.addImage(image5); -doc.addImage(image); -doc.addImage(image2); -doc.addImage(image3); -doc.addImage(image4); -doc.addImage(image5); -doc.addImage(image6); +doc.add(image); +doc.add(image2); +doc.add(image3); +doc.add(image4); +doc.add(image5); +doc.add(image6); const packer = new Packer(); diff --git a/demo/demo24.ts b/demo/demo24.ts index 7a50a911b4..fc940eed1d 100644 --- a/demo/demo24.ts +++ b/demo/demo24.ts @@ -10,12 +10,12 @@ const table = new Table({ columns: 4, }); -doc.addTable(table); +doc.add(table); -table.getCell(2, 2).addParagraph(new Paragraph("Hello")); +table.getCell(2, 2).add(new Paragraph("Hello")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -table.getCell(1, 1).addParagraph(new Paragraph(image)); +table.getCell(1, 1).add(new Paragraph(image)); const packer = new Packer(); diff --git a/demo/demo26.ts b/demo/demo26.ts index 613d624091..ef914e9465 100644 --- a/demo/demo26.ts +++ b/demo/demo26.ts @@ -7,7 +7,7 @@ const doc = new Document(); const paragraph = new Paragraph("No border!"); -doc.addParagraph(paragraph); +doc.add(paragraph); const borderParagraph = new Paragraph({ text: "I have borders on my top and bottom sides!", @@ -27,7 +27,7 @@ const borderParagraph = new Paragraph({ }, }); -doc.addParagraph(borderParagraph); +doc.add(borderParagraph); const packer = new Packer(); diff --git a/demo/demo27.ts b/demo/demo27.ts index 09651dee9e..28d2ba5d09 100644 --- a/demo/demo27.ts +++ b/demo/demo27.ts @@ -27,13 +27,13 @@ myStyles .underline("double", "FF0000") .spacing({ before: 240, after: 120 }); // TWIP for both -doc.addParagraph( +doc.add( new Paragraph({ text: "Hello", style: "myWonkyStyle", }), ); -doc.addParagraph( +doc.add( new Paragraph({ text: "World", heading: HeadingLevel.HEADING_2, diff --git a/demo/demo28.ts b/demo/demo28.ts index 20e4a50026..0bef4470bc 100644 --- a/demo/demo28.ts +++ b/demo/demo28.ts @@ -26,26 +26,26 @@ const toc = new TableOfContents("Summary", { doc.addTableOfContents(toc); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "Header #1", heading: HeadingLevel.HEADING_1, pageBreakBefore: true, })); -doc.addParagraph(new Paragraph("I'm a little text very nicely written.'")); +doc.add(new Paragraph("I'm a little text very nicely written.'")); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "Header #2", heading: HeadingLevel.HEADING_1, pageBreakBefore: true, })); -doc.addParagraph(new Paragraph("I'm a other text very nicely written.'")); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph("I'm a other text very nicely written.'")); +doc.add(new Paragraph({ text: "Header #2.1", heading: HeadingLevel.HEADING_2, })); -doc.addParagraph(new Paragraph("I'm a another text very nicely written.'")); +doc.add(new Paragraph("I'm a another text very nicely written.'")); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "My Spectacular Style #1", style: "MySpectacularStyle", pageBreakBefore: true, diff --git a/demo/demo29.ts b/demo/demo29.ts index bbf6b8d125..f8982e425d 100644 --- a/demo/demo29.ts +++ b/demo/demo29.ts @@ -8,7 +8,7 @@ const doc = new Document(); const numbering = new Numbering(); const abstractNum = numbering.createAbstractNumbering(); -abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent({ left: 720, hanging: 260 })); +abstractNum.createLevel(0, "upperRoman", "%1", "start").addProperty(new Indent({ left: 720, hanging: 260 })); const concrete = numbering.createConcreteNumbering(abstractNum); @@ -57,10 +57,10 @@ const item4 = new Paragraph({ }, }); -doc.addParagraph(item1); -doc.addParagraph(item2); -doc.addParagraph(item3); -doc.addParagraph(item4); +doc.add(item1); +doc.add(item2); +doc.add(item3); +doc.add(item4); const packer = new Packer(); diff --git a/demo/demo3.ts b/demo/demo3.ts index e526b8e523..e901049ec9 100644 --- a/demo/demo3.ts +++ b/demo/demo3.ts @@ -8,9 +8,9 @@ const doc = new Document(); const numbering = new Numbering(); const abstractNum = numbering.createAbstractNumbering(); -abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent({ left: 720, hanging: 260 })); -abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent({ left: 1440, hanging: 980 })); -abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent({ left: 14402160, hanging: 1700 })); +abstractNum.createLevel(0, "upperRoman", "%1", "start").addProperty(new Indent({ left: 720, hanging: 260 })); +abstractNum.createLevel(1, "decimal", "%2.", "start").addProperty(new Indent({ left: 1440, hanging: 980 })); +abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addProperty(new Indent({ left: 14402160, hanging: 1700 })); const concrete = numbering.createConcreteNumbering(abstractNum); @@ -43,10 +43,10 @@ const subSubP = new Paragraph({ }, }); -doc.addParagraph(topLevelP); -doc.addParagraph(subP); -doc.addParagraph(secondSubP); -doc.addParagraph(subSubP); +doc.add(topLevelP); +doc.add(subP); +doc.add(secondSubP); +doc.add(subSubP); const bullet1 = new Paragraph({ text: "Hey you", @@ -73,10 +73,10 @@ const bullet4 = new Paragraph({ }, }); -doc.addParagraph(bullet1); -doc.addParagraph(bullet2); -doc.addParagraph(bullet3); -doc.addParagraph(bullet4); +doc.add(bullet1); +doc.add(bullet2); +doc.add(bullet3); +doc.add(bullet4); const packer = new Packer(); diff --git a/demo/demo30.ts b/demo/demo30.ts index ad7867a9c0..92b929bd30 100644 --- a/demo/demo30.ts +++ b/demo/demo30.ts @@ -21,7 +21,7 @@ fs.readFile(filePath, (err, data) => { template: templateDocument, }); const paragraph = new Paragraph("Hello World"); - doc.addParagraph(paragraph); + doc.add(paragraph); const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo31.ts b/demo/demo31.ts index 15f6de5a64..32c8cd755a 100644 --- a/demo/demo31.ts +++ b/demo/demo31.ts @@ -10,14 +10,14 @@ const table = new Table({ columns: 2, }); -doc.addTable(table); +doc.add(table); table .getCell(1, 1) - .addParagraph(new Paragraph("This text should be in the middle of the cell")) + .add(new Paragraph("This text should be in the middle of the cell")) .setVerticalAlign(VerticalAlign.CENTER); -table.getCell(1, 0).addParagraph( +table.getCell(1, 0).add( new Paragraph({ text: "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", diff --git a/demo/demo32.ts b/demo/demo32.ts index 2591a72174..c2fd76ebf6 100644 --- a/demo/demo32.ts +++ b/demo/demo32.ts @@ -10,12 +10,12 @@ let table = new Table({ columns: 2, }); -doc.addTable(table); +doc.add(table); -table.getCell(0, 0).addParagraph(new Paragraph("Hello")); +table.getCell(0, 0).add(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); -doc.addParagraph( +doc.add( new Paragraph({ text: "Another table", heading: HeadingLevel.HEADING_2, @@ -30,11 +30,11 @@ table = new Table({ columnWidths: [1000, 1000, 1000], }); -doc.addTable(table); +doc.add(table); table .getCell(0, 0) - .addParagraph(new Paragraph("World")) + .add(new Paragraph("World")) .setMargins({ top: 1000, bottom: 1000, @@ -43,7 +43,7 @@ table }); table.getRow(0).mergeCells(0, 2); -doc.addParagraph( +doc.add( new Paragraph({ text: "Another table", heading: HeadingLevel.HEADING_2, @@ -63,14 +63,14 @@ table = new Table({ }, }); -doc.addTable(table); +doc.add(table); -table.getCell(0, 0).addParagraph(new Paragraph("Foo")); -table.getCell(0, 1).addParagraph(new Paragraph("v")); +table.getCell(0, 0).add(new Paragraph("Foo")); +table.getCell(0, 1).add(new Paragraph("v")); table .getCell(1, 0) - .addParagraph(new Paragraph("Bar1")) + .add(new Paragraph("Bar1")) .setShading({ fill: "b79c2f", val: ShadingType.REVERSE_DIAGONAL_STRIPE, @@ -78,7 +78,7 @@ table }); table .getCell(1, 1) - .addParagraph(new Paragraph("Bar2")) + .add(new Paragraph("Bar2")) .setShading({ fill: "42c5f4", val: ShadingType.PERCENT_95, @@ -86,7 +86,7 @@ table }); table .getCell(1, 2) - .addParagraph(new Paragraph("Bar3")) + .add(new Paragraph("Bar3")) .setShading({ fill: "880aa8", val: ShadingType.PERCENT_10, @@ -94,7 +94,7 @@ table }); table .getCell(1, 3) - .addParagraph(new Paragraph("Bar4")) + .add(new Paragraph("Bar4")) .setShading({ fill: "FF0000", val: ShadingType.CLEAR, @@ -103,7 +103,7 @@ table table.getRow(0).mergeCells(0, 3); -doc.addParagraph(new Paragraph("hi")); +doc.add(new Paragraph("hi")); table = new Table({ rows: 2, @@ -112,7 +112,7 @@ table = new Table({ widthUnitType: WidthType.PERCENTAGE, }); -doc.addTable(table); +doc.add(table); const packer = new Packer(); diff --git a/demo/demo33.ts b/demo/demo33.ts index c6efe2ed0f..b4831d849b 100644 --- a/demo/demo33.ts +++ b/demo/demo33.ts @@ -10,10 +10,10 @@ const paragraph2 = new Paragraph("Hello World 1->").addSequentialIdentifier("Lab const paragraph3 = new Paragraph("Hello World 1->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 3->")).addSequentialIdentifier("Label"); const paragraph4 = new Paragraph("Hello World 2->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 4->")).addSequentialIdentifier("Label"); -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); -doc.addParagraph(paragraph3); -doc.addParagraph(paragraph4); +doc.add(paragraph); +doc.add(paragraph2); +doc.add(paragraph3); +doc.add(paragraph4); const packer = new Packer(); diff --git a/demo/demo34.ts b/demo/demo34.ts index 365fc00845..007be8efdb 100644 --- a/demo/demo34.ts +++ b/demo/demo34.ts @@ -31,7 +31,7 @@ const table = new Table({ doc.add(table); -table.getCell(0, 0).addParagraph(new Paragraph("Hello")); +table.getCell(0, 0).add(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); const packer = new Packer(); diff --git a/demo/demo35.ts b/demo/demo35.ts index 04573edc1e..a2927a6957 100644 --- a/demo/demo35.ts +++ b/demo/demo35.ts @@ -8,7 +8,7 @@ const paragraph = new Paragraph({}); const link = doc.createHyperlink("http://www.example.com", "Hyperlink"); paragraph.addHyperLink(link); -doc.addParagraph(paragraph); +doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo36.ts b/demo/demo36.ts index 655410b56e..1faf0c3e94 100644 --- a/demo/demo36.ts +++ b/demo/demo36.ts @@ -10,12 +10,12 @@ const table = new Table({ rows: 2, columns: 2, }); -table.getCell(1, 1).addParagraph(new Paragraph(image)); +table.getCell(1, 1).add(new Paragraph(image)); -doc.addTable(table); +doc.add(table); // doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.Header.addTable(table); +doc.Header.add(table); // doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); const packer = new Packer(); diff --git a/demo/demo37.ts b/demo/demo37.ts index 8b9e04a12e..6f599cd15a 100644 --- a/demo/demo37.ts +++ b/demo/demo37.ts @@ -5,7 +5,7 @@ import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -doc.addParagraph(new Paragraph("Hello World")); +doc.add(new Paragraph("Hello World")); doc.Header.addImage(image); doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); diff --git a/demo/demo38.ts b/demo/demo38.ts index dfc9a50091..eca2c82ef4 100644 --- a/demo/demo38.ts +++ b/demo/demo38.ts @@ -6,15 +6,15 @@ import { Document, Packer, Paragraph, TextWrappingSide, TextWrappingType } from const doc = new Document(); -doc.addParagraph(new Paragraph( +doc.add(new Paragraph( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.", )); -doc.addParagraph(new Paragraph( +doc.add(new Paragraph( "Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.", )); -doc.addParagraph(new Paragraph( +doc.add(new Paragraph( "Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.", )); diff --git a/demo/demo39.ts b/demo/demo39.ts index 1768ce3074..0c4cf86ca8 100644 --- a/demo/demo39.ts +++ b/demo/demo39.ts @@ -11,11 +11,11 @@ const doc = new Document( }, ); -doc.Header.addParagraph( +doc.Header.add( new Paragraph("Foo Bar corp. ").addRun(new TextRun("Page Number ").pageNumber()).addRun(new TextRun(" to ").numberOfTotalPages()), ); -doc.Footer.addParagraph( +doc.Footer.add( new Paragraph({ text: "Foo Bar corp. ", alignment: AlignmentType.CENTER, @@ -24,11 +24,11 @@ doc.Footer.addParagraph( .addRun(new TextRun(" to ").numberOfTotalPages()), ); -doc.addParagraph(new Paragraph("Hello World 1").pageBreak()); -doc.addParagraph(new Paragraph("Hello World 2").pageBreak()); -doc.addParagraph(new Paragraph("Hello World 3").pageBreak()); -doc.addParagraph(new Paragraph("Hello World 4").pageBreak()); -doc.addParagraph(new Paragraph("Hello World 5").pageBreak()); +doc.add(new Paragraph("Hello World 1").pageBreak()); +doc.add(new Paragraph("Hello World 2").pageBreak()); +doc.add(new Paragraph("Hello World 3").pageBreak()); +doc.add(new Paragraph("Hello World 4").pageBreak()); +doc.add(new Paragraph("Hello World 5").pageBreak()); const packer = new Packer(); diff --git a/demo/demo4.ts b/demo/demo4.ts index 19242b1a71..5e528ac2db 100644 --- a/demo/demo4.ts +++ b/demo/demo4.ts @@ -10,9 +10,9 @@ const table = new Table({ columns: 4, }); -doc.addTable(table); +doc.add(table); -table.getCell(2, 2).addParagraph(new Paragraph("Hello")); +table.getCell(2, 2).add(new Paragraph("Hello")); const packer = new Packer(); diff --git a/demo/demo40.ts b/demo/demo40.ts index ed0e0fe278..6db6e7ba1e 100644 --- a/demo/demo40.ts +++ b/demo/demo40.ts @@ -11,18 +11,18 @@ const doc = new Document( }, ); -doc.addParagraph( +doc.add( new Paragraph({ text: "Hello", heading: HeadingLevel.HEADING_1, }), ); -doc.addParagraph( +doc.add( new Paragraph( "Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.", ), ); -doc.addParagraph( +doc.add( new Paragraph( "Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.", ), diff --git a/demo/demo41.ts b/demo/demo41.ts index 2d3192bdf2..977d99abb5 100644 --- a/demo/demo41.ts +++ b/demo/demo41.ts @@ -10,41 +10,41 @@ const table = new Table({ columns: 6, }); -doc.addTable(table); +doc.add(table); let row = 0; -table.getCell(row, 0).addParagraph(new Paragraph("0,0")); -table.getCell(row, 1).addParagraph(new Paragraph("0,1")); -table.getCell(row, 3).addParagraph(new Paragraph("0,3")); -table.getCell(row, 4).addParagraph(new Paragraph("0,4")); +table.getCell(row, 0).add(new Paragraph("0,0")); +table.getCell(row, 1).add(new Paragraph("0,1")); +table.getCell(row, 3).add(new Paragraph("0,3")); +table.getCell(row, 4).add(new Paragraph("0,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(1, 2); row = 1; -table.getCell(row, 0).addParagraph(new Paragraph("1,0")); -table.getCell(row, 2).addParagraph(new Paragraph("1,2")); -table.getCell(row, 4).addParagraph(new Paragraph("1,4")); +table.getCell(row, 0).add(new Paragraph("1,0")); +table.getCell(row, 2).add(new Paragraph("1,2")); +table.getCell(row, 4).add(new Paragraph("1,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(2, 3); table.getRow(row).mergeCells(0, 1); row = 2; -table.getCell(row, 0).addParagraph(new Paragraph("2,0")); -table.getCell(row, 1).addParagraph(new Paragraph("2,1")); -table.getCell(row, 2).addParagraph(new Paragraph("2,2")); -table.getCell(row, 3).addParagraph(new Paragraph("2,3")); -table.getCell(row, 4).addParagraph(new Paragraph("2,4")); +table.getCell(row, 0).add(new Paragraph("2,0")); +table.getCell(row, 1).add(new Paragraph("2,1")); +table.getCell(row, 2).add(new Paragraph("2,2")); +table.getCell(row, 3).add(new Paragraph("2,3")); +table.getCell(row, 4).add(new Paragraph("2,4")); table.getRow(row).mergeCells(4, 5); table.getRow(row).mergeCells(1, 2); row = 3; -table.getCell(row, 0).addParagraph(new Paragraph("3,0")); -table.getCell(row, 1).addParagraph(new Paragraph("3,1")); -table.getCell(row, 2).addParagraph(new Paragraph("3,2")); -table.getCell(row, 3).addParagraph(new Paragraph("3,3")); -table.getCell(row, 4).addParagraph(new Paragraph("3,4")); -table.getCell(row, 5).addParagraph(new Paragraph("3,5")); +table.getCell(row, 0).add(new Paragraph("3,0")); +table.getCell(row, 1).add(new Paragraph("3,1")); +table.getCell(row, 2).add(new Paragraph("3,2")); +table.getCell(row, 3).add(new Paragraph("3,3")); +table.getCell(row, 4).add(new Paragraph("3,4")); +table.getCell(row, 5).add(new Paragraph("3,5")); row = 4; -table.getCell(row, 0).addParagraph(new Paragraph("4,0")); -table.getCell(row, 5).addParagraph(new Paragraph("4,5")); +table.getCell(row, 0).add(new Paragraph("4,0")); +table.getCell(row, 5).add(new Paragraph("4,5")); table.getRow(row).mergeCells(0, 4); const packer = new Packer(); diff --git a/demo/demo43.ts b/demo/demo43.ts index 65ce2d443a..451d21a0fd 100644 --- a/demo/demo43.ts +++ b/demo/demo43.ts @@ -10,11 +10,11 @@ const table = new Table({ columns: 4, }); -doc.addTable(table); +doc.add(table); -table.getCell(2, 2).addParagraph(new Paragraph("Hello")); +table.getCell(2, 2).add(new Paragraph("Hello")); table.getColumn(3).mergeCells(1, 2); -// table.getCell(3, 2).addParagraph(new Paragraph("Hello")); +// table.getCell(3, 2).add(new Paragraph("Hello")); const packer = new Packer(); diff --git a/demo/demo5.ts b/demo/demo5.ts index 7163a5db60..be340a3530 100644 --- a/demo/demo5.ts +++ b/demo/demo5.ts @@ -7,7 +7,7 @@ import { Document, HorizontalPositionAlign, HorizontalPositionRelativeFrom, Pack const doc = new Document(); const paragraph = new Paragraph("Hello World"); -doc.addParagraph(paragraph); +doc.add(paragraph); doc.createImage(fs.readFileSync("./demo/images/image1.jpeg")); doc.createImage(fs.readFileSync("./demo/images/dog.png").toString("base64")); diff --git a/demo/demo6.ts b/demo/demo6.ts index 042f6d7d94..2629c1b96d 100644 --- a/demo/demo6.ts +++ b/demo/demo6.ts @@ -22,14 +22,14 @@ const dateText = new TextRun({ paragraph.addRun(institutionText); paragraph.addRun(dateText); -doc.addParagraph(paragraph); +doc.add(paragraph); -doc.addParagraph(new Paragraph({ +doc.add(new Paragraph({ text: "Hello World", heading: HeadingLevel.HEADING_1, })); -doc.addParagraph(new Paragraph("Foo bar")); -doc.addParagraph(new Paragraph("Github is the best")); +doc.add(new Paragraph("Foo bar")); +doc.add(new Paragraph("Github is the best")); const packer = new Packer(); diff --git a/demo/demo7.ts b/demo/demo7.ts index fe9fccf928..db528cb157 100644 --- a/demo/demo7.ts +++ b/demo/demo7.ts @@ -9,7 +9,7 @@ const doc = new Document(undefined, { const paragraph = new Paragraph("Hello World"); -doc.addParagraph(paragraph); +doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo8.ts b/demo/demo8.ts index 89d474568d..1e3dfbaada 100644 --- a/demo/demo8.ts +++ b/demo/demo8.ts @@ -5,10 +5,10 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.addParagraph(new Paragraph("Hello World")); +doc.add(new Paragraph("Hello World")); -doc.Header.addParagraph(new Paragraph("Header text")); -doc.Footer.addParagraph(new Paragraph("Footer text")); +doc.Header.add(new Paragraph("Header text")); +doc.Footer.add(new Paragraph("Footer text")); const packer = new Packer(); diff --git a/demo/demo9.ts b/demo/demo9.ts index 71b8b25a77..8787d43b24 100644 --- a/demo/demo9.ts +++ b/demo/demo9.ts @@ -5,7 +5,7 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.addParagraph(new Paragraph("Hello World")); +doc.add(new Paragraph("Hello World")); doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); diff --git a/docs/README.md b/docs/README.md index fd5ad9ecd9..caee21e8b8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,7 +39,7 @@ var doc = new docx.Document(); var paragraph = new docx.Paragraph("Some cool text here."); // Add more text into the paragraph if you wish paragraph.addRun(new docx.TextRun("Lorem Ipsum Foo Bar")); -doc.addParagraph(paragraph); +doc.add(paragraph); // Used to export the file into a .docx file var packer = new docx.Packer(); diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md index 7f61964032..4092d246a4 100644 --- a/docs/contribution-guidelines.md +++ b/docs/contribution-guidelines.md @@ -92,7 +92,7 @@ This is just a guideline, and the rules can sometimes be broken. *Note:* This may look like its breaking the previous guideline, but it has semantically different meanings. The previous one is using data to construct an object, whereas this one is simply adding elements into the document: ```js - public addParagraph(paragraph: Paragraph) { + public add(paragraph: Paragraph) { this.root.push(paragraph); } ``` diff --git a/docs/usage/bullet-points.md b/docs/usage/bullet-points.md index c2fb2987d0..5926e0eca7 100644 --- a/docs/usage/bullet-points.md +++ b/docs/usage/bullet-points.md @@ -11,8 +11,8 @@ var paragraph = new docx.Paragraph(text).bullet(); var text2 = new docx.TextRun("Are awesome"); var paragraph2 = new docx.Paragraph(text2).bullet(); -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); +doc.add(paragraph); +doc.add(paragraph2); ``` ### This will produce: diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index 6864bd1e73..28f815e4b2 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -23,7 +23,7 @@ var paragraph = new docx.Paragraph("Short hand notation for adding text."); After you create the paragraph, you must add the paragraph into the `document`: ```js -doc.addParagraph(paragraph); +doc.add(paragraph); ``` ## Styles diff --git a/docs/usage/styling-with-xml.md b/docs/usage/styling-with-xml.md index 5f138d31d6..1aad181d2d 100644 --- a/docs/usage/styling-with-xml.md +++ b/docs/usage/styling-with-xml.md @@ -39,7 +39,7 @@ doc.createParagraph("Cool Heading Text").heading1(); let paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"'); paragraph.style("Cool New Style"); -doc.addParagraph(paragraph); +doc.add(paragraph); doc.createParagraph("Some normal text"); ``` diff --git a/docs/usage/table-of-contents.md b/docs/usage/table-of-contents.md index c1fb439143..02ef2eff14 100644 --- a/docs/usage/table-of-contents.md +++ b/docs/usage/table-of-contents.md @@ -58,15 +58,15 @@ const toc = new TableOfContents("Summary", { doc.addTableOfContents(toc); -doc.addParagraph(new Paragraph("Header #1").heading1().pageBreakBefore()); -doc.addParagraph(new Paragraph("I'm a little text, very nicely written.'")); +doc.add(new Paragraph("Header #1").heading1().pageBreakBefore()); +doc.add(new Paragraph("I'm a little text, very nicely written.'")); -doc.addParagraph(new Paragraph("Header #2").heading1().pageBreakBefore()); -doc.addParagraph(new Paragraph("I'm another text very nicely written.'")); -doc.addParagraph(new Paragraph("Header #2.1").heading2()); -doc.addParagraph(new Paragraph("I'm another text very nicely written.'")); +doc.add(new Paragraph("Header #2").heading1().pageBreakBefore()); +doc.add(new Paragraph("I'm another text very nicely written.'")); +doc.add(new Paragraph("Header #2.1").heading2()); +doc.add(new Paragraph("I'm another text very nicely written.'")); -doc.addParagraph(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore()); +doc.add(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore()); ``` ### Complete example diff --git a/docs/usage/tables.md b/docs/usage/tables.md index 437d579b8f..70556ae028 100644 --- a/docs/usage/tables.md +++ b/docs/usage/tables.md @@ -4,10 +4,10 @@ You can create tables with `docx`. More information can be found [here](http://o ## Create Table -To create a table, simply create one with `new Table()`, then add it to the document: `doc.addTable()`. +To create a table, simply create one with `new Table()`, then add it to the document: `doc.add()`. ```ts -const table = doc.addTable(new Table({ +const table = doc.add(new Table({ rows: [NUMBER OF ROWS], columns: [NUMBER OF COLUMNS] }); @@ -17,7 +17,7 @@ Alternatively, you can create a table object directly, and then add it in the `d ```ts const table = new Table(4, 4); -doc.addTable(table); +doc.add(table); ``` The snippet below creates a table of 2 rows and 4 columns. @@ -27,7 +27,7 @@ const table = new Table({ rows: 2, columns: 4, }); -doc.addTable(table); +doc.add(table); ``` ## Rows and Columns @@ -92,10 +92,10 @@ const cell = column.getCell(2); ### Add paragraph to a cell -Once you have got the cell, you can add data to it with the `addParagraph()` method. +Once you have got the cell, you can add data to it with the `add()` method. ```ts -cell.addParagraph(new Paragraph("Hello")); +cell.add(new Paragraph("Hello")); ``` ### Set width of a cell @@ -226,7 +226,7 @@ It has not been implemented yet, but it will follow a similar structure as mergi To have a table within a table ```ts -cell.addTable(new Table(1, 1)); +cell.add(new Table(1, 1)); ``` ## Pagination diff --git a/src/file/document/document.ts b/src/file/document/document.ts index c517124ef3..b716c1367b 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -37,7 +37,7 @@ export class Document extends XmlComponent { this.root.push(this.body); } - public addParagraph(paragraph: Paragraph): Document { + public add(paragraph: Paragraph | Table): Document { this.body.push(paragraph); return this; } @@ -47,11 +47,6 @@ export class Document extends XmlComponent { return this; } - public addTable(table: Table): Document { - this.body.push(table); - return this; - } - public get Body(): Body { return this.body; } diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 6b0b7aa251..b11a5f61ec 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -80,20 +80,18 @@ describe("File", () => { }); }); - describe("#addParagraph", () => { - it("should call the underlying document's addParagraph", () => { + describe("#add", () => { + it("should call the underlying document's add a Paragraph", () => { const file = new File(); - const spy = sinon.spy(file.Document, "addParagraph"); + const spy = sinon.spy(file.Document, "add"); file.add(new Paragraph({})); expect(spy.called).to.equal(true); }); - }); - describe("#add", () => { - it("should call the underlying document's addTable", () => { + it("should call the underlying document's add when adding a Table", () => { const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "addTable"); + const spy = sinon.spy(wrapper.Document, "add"); wrapper.add( new Table({ rows: 1, @@ -104,6 +102,17 @@ describe("File", () => { expect(spy.called).to.equal(true); }); + it("should call the underlying document's add when adding an Image (paragraph)", () => { + const wrapper = new File(); + const spy = sinon.spy(wrapper.Document, "add"); + // tslint:disable-next-line:no-any + wrapper.add(new Paragraph("")); + + expect(spy.called).to.equal(true); + }); + }); + + describe("#add", () => { it("should call the underlying document's addTableOfContents", () => { const wrapper = new File(); const spy = sinon.spy(wrapper.Document, "addTableOfContents"); @@ -111,22 +120,13 @@ describe("File", () => { expect(spy.called).to.equal(true); }); - - it("should call the underlying document's addImage", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "addParagraph"); - // tslint:disable-next-line:no-any - wrapper.add(new Paragraph("")); - - expect(spy.called).to.equal(true); - }); }); describe("#createImage", () => { it("should call the underlying document's createImage", () => { const wrapper = new File(); const spy = sinon.spy(wrapper.Media, "addMedia"); - const wrapperSpy = sinon.spy(wrapper.Document, "addParagraph"); + const wrapperSpy = sinon.spy(wrapper.Document, "add"); wrapper.createImage(""); expect(spy.called).to.equal(true); diff --git a/src/file/file.ts b/src/file/file.ts index 26848c8e5b..a8fba1d512 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -114,11 +114,11 @@ export class File { public add(item: Paragraph | Table | TableOfContents): File { if (item instanceof Paragraph) { - this.document.addParagraph(item); + this.document.add(item); } if (item instanceof Table) { - this.document.addTable(item); + this.document.add(item); } if (item instanceof TableOfContents) { @@ -136,7 +136,7 @@ export class File { ): Paragraph { const image = Media.addImage(this, buffer, width, height, drawingOptions); const paragraph = new Paragraph(image); - this.document.addParagraph(paragraph); + this.document.add(paragraph); return paragraph; } diff --git a/src/file/footnotes/footnote/footnote.ts b/src/file/footnotes/footnote/footnote.ts index 0567695c40..60e6e533c8 100644 --- a/src/file/footnotes/footnote/footnote.ts +++ b/src/file/footnotes/footnote/footnote.ts @@ -20,7 +20,7 @@ export class Footnote extends XmlComponent { ); } - public addParagraph(paragraph: Paragraph): void { + public add(paragraph: Paragraph): void { paragraph.addRunToFront(new FootnoteRefRun()); this.root.push(paragraph); } diff --git a/src/file/footnotes/footnotes.ts b/src/file/footnotes/footnotes.ts index 1681928afb..2fea5fe380 100644 --- a/src/file/footnotes/footnotes.ts +++ b/src/file/footnotes/footnotes.ts @@ -37,7 +37,7 @@ export class FootNotes extends XmlComponent { ); const begin = new Footnote(-1, FootnoteType.SEPERATOR); - begin.addParagraph( + begin.add( new Paragraph({ spacing: { after: 0, @@ -49,7 +49,7 @@ export class FootNotes extends XmlComponent { this.root.push(begin); const spacing = new Footnote(0, FootnoteType.CONTINUATION_SEPERATOR); - spacing.addParagraph( + spacing.add( new Paragraph({ spacing: { after: 0, @@ -63,7 +63,7 @@ export class FootNotes extends XmlComponent { public createFootNote(paragraph: Paragraph): void { const footnote = new Footnote(this.currentId); - footnote.addParagraph(paragraph); + footnote.add(paragraph); this.root.push(footnote); this.currentId++; diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts index 830797dbed..1c546ab934 100644 --- a/src/file/table/table-cell/table-cell.ts +++ b/src/file/table/table-cell/table-cell.ts @@ -22,13 +22,9 @@ export class TableCell extends XmlComponent { this.root.push(this.properties); } - public addParagraph(content: Paragraph): TableCell { - this.root.push(content); - return this; - } + public add(item: Paragraph | Table): TableCell { + this.root.push(item); - public addTable(content: Table): TableCell { - this.root.push(content); return this; } @@ -36,7 +32,7 @@ export class TableCell extends XmlComponent { // Cells must end with a paragraph if (!(this.root[this.root.length - 1] instanceof Paragraph)) { const para = new Paragraph({}); - this.addParagraph(para); + this.add(para); } return super.prepForXml(); } diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index 70fc2db165..7c93c5fc8e 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -163,19 +163,19 @@ describe("Table", () => { table .getRow(0) .getCell(0) - .addParagraph(new Paragraph("A1")); + .add(new Paragraph("A1")); table .getRow(0) .getCell(1) - .addParagraph(new Paragraph("B1")); + .add(new Paragraph("B1")); table .getRow(1) .getCell(0) - .addParagraph(new Paragraph("A2")); + .add(new Paragraph("A2")); table .getRow(1) .getCell(1) - .addParagraph(new Paragraph("B2")); + .add(new Paragraph("B2")); const tree = new Formatter().format(table); const cell = (c) => ({ "w:tc": [ @@ -221,10 +221,10 @@ describe("Table", () => { rows: 2, columns: 2, }); - table.getCell(0, 0).addParagraph(new Paragraph("A1")); - table.getCell(0, 1).addParagraph(new Paragraph("B1")); - table.getCell(1, 0).addParagraph(new Paragraph("A2")); - table.getCell(1, 1).addParagraph(new Paragraph("B2")); + table.getCell(0, 0).add(new Paragraph("A1")); + table.getCell(0, 1).add(new Paragraph("B1")); + table.getCell(1, 0).add(new Paragraph("A2")); + table.getCell(1, 1).add(new Paragraph("B2")); const tree = new Formatter().format(table); const cell = (c) => ({ "w:tc": [ @@ -295,7 +295,7 @@ describe("Table", () => { rows: 1, columns: 1, }); - parentTable.getCell(0, 0).addTable( + parentTable.getCell(0, 0).add( new Table({ rows: 1, columns: 1, @@ -322,7 +322,7 @@ describe("Table", () => { rows: 1, columns: 1, }); - parentTable.getCell(0, 0).addParagraph(new Paragraph("Hello")); + parentTable.getCell(0, 0).add(new Paragraph("Hello")); const tree = new Formatter().format(parentTable); expect(tree) .to.have.property("w:tbl") From 58346a8937ead91899476e933f3690371e58efb0 Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 7 Jul 2019 03:54:29 +0100 Subject: [PATCH 12/38] Section WIP --- demo/demo16.ts | 87 ++++++++++++++++++++++++------------------- src/file/file.spec.ts | 6 +-- src/file/file.ts | 16 +++++++- 3 files changed, 66 insertions(+), 43 deletions(-) diff --git a/demo/demo16.ts b/demo/demo16.ts index cd1507d747..ee77ce7ebb 100644 --- a/demo/demo16.ts +++ b/demo/demo16.ts @@ -15,68 +15,77 @@ const footer = doc.createFooter(); footer.add(new Paragraph("Footer on another page")); doc.addSection({ - headers: { - default: header, + properties: { + headers: { + default: header, + }, + footers: { + default: footer, + }, + pageNumberStart: 1, + pageNumberFormatType: PageNumberFormat.DECIMAL, }, - footers: { - default: footer, - }, - pageNumberStart: 1, - pageNumberFormatType: PageNumberFormat.DECIMAL, + children: [new Paragraph("hello")], }); -doc.add(new Paragraph("hello")); - doc.addSection({ - headers: { - default: header, + properties: { + headers: { + default: header, + }, + footers: { + default: footer, + }, + pageNumberStart: 1, + pageNumberFormatType: PageNumberFormat.DECIMAL, + orientation: PageOrientation.LANDSCAPE, }, - footers: { - default: footer, - }, - pageNumberStart: 1, - pageNumberFormatType: PageNumberFormat.DECIMAL, - orientation: PageOrientation.LANDSCAPE, + children: [new Paragraph("hello in landscape")], }); -doc.add(new Paragraph("hello in landscape")); - const header2 = doc.createHeader(); const pageNumber = new TextRun("Page number: ").pageNumber(); header2.add(new Paragraph({}).addRun(pageNumber)); doc.addSection({ - headers: { - default: header2, + properties: { + headers: { + default: header2, + }, + orientation: PageOrientation.PORTRAIT, }, - orientation: PageOrientation.PORTRAIT, + children: [new Paragraph("Page number in the header must be 2, because it continues from the previous section.")], }); -doc.add(new Paragraph("Page number in the header must be 2, because it continues from the previous section.")); - doc.addSection({ - headers: { - default: header2, + properties: { + headers: { + default: header2, + }, + pageNumberFormatType: PageNumberFormat.UPPER_ROMAN, + orientation: PageOrientation.PORTRAIT, }, - pageNumberFormatType: PageNumberFormat.UPPER_ROMAN, - orientation: PageOrientation.PORTRAIT, + children: [ + new Paragraph( + "Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.", + ), + ], }); -doc.add(new Paragraph( - "Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.", -)); - doc.addSection({ - headers: { - default: header2, + properties: { + headers: { + default: header2, + }, + pageNumberFormatType: PageNumberFormat.DECIMAL, + pageNumberStart: 25, + orientation: PageOrientation.PORTRAIT, }, - pageNumberFormatType: PageNumberFormat.DECIMAL, - pageNumberStart: 25, - orientation: PageOrientation.PORTRAIT, + children: [ + new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section."), + ], }); -doc.add(new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section.")); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index b11a5f61ec..00e0b7d02b 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -15,7 +15,7 @@ describe("File", () => { const header = doc.createHeader(); const footer = doc.createFooter(); - doc.addSection({ + doc.addSectionOld({ headers: { default: header, }, @@ -35,7 +35,7 @@ describe("File", () => { const header = doc.createHeader(); const footer = doc.createFooter(); - doc.addSection({ + doc.addSectionOld({ headers: { first: header, }, @@ -55,7 +55,7 @@ describe("File", () => { const header = doc.createHeader(); const footer = doc.createFooter(); - doc.addSection({ + doc.addSectionOld({ headers: { default: header, first: header, diff --git a/src/file/file.ts b/src/file/file.ts index a8fba1d512..0f4c77c82b 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -27,6 +27,11 @@ import { DefaultStylesFactory } from "./styles/factory"; import { Table } from "./table"; import { TableOfContents } from "./table-of-contents"; +export interface ISectionOptions { + readonly properties: SectionPropertiesOptions; + readonly children: Array; +} + export class File { // tslint:disable-next-line:readonly-keyword private currentRelationshipId: number = 1; @@ -54,6 +59,7 @@ export class File { }, sectionPropertiesOptions: SectionPropertiesOptions = {}, fileProperties: IFileProperties = {}, + sections: ISectionOptions[] = [], ) { this.coreProperties = new CoreProperties(options); this.numbering = new Numbering(); @@ -110,6 +116,14 @@ export class File { this.document = new Document(newSectionPropertiesOptions); this.settings = new Settings(); + + for (const section of sections) { + this.document.Body.addSection(section.properties); + + for (const child of section.children) { + this.add(child); + } + } } public add(item: Paragraph | Table | TableOfContents): File { @@ -167,7 +181,7 @@ export class File { return bookmark; } - public addSection(sectionPropertiesOptions: SectionPropertiesOptions): void { + public addSectionOld(sectionPropertiesOptions: SectionPropertiesOptions): void { this.document.Body.addSection(sectionPropertiesOptions); } From bf80311ef73b8db5c1ac67b41c51a3855b6f959a Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Sun, 7 Jul 2019 20:23:42 +0100 Subject: [PATCH 13/38] Add new section method --- src/file/file.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/file/file.ts b/src/file/file.ts index 0f4c77c82b..a78acd86e6 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -185,6 +185,14 @@ export class File { this.document.Body.addSection(sectionPropertiesOptions); } + public addSection(section: ISectionOptions): void { + this.document.Body.addSection(section.properties); + + for (const child of section.children) { + this.add(child); + } + } + public createFootnote(paragraph: Paragraph): void { this.footNotes.createFootNote(paragraph); } From ac5b15d0e3efc83b45e622653f5b06adf6301da5 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Wed, 31 Jul 2019 08:48:02 +0100 Subject: [PATCH 14/38] Mandatory Sections --- demo/browser-demo.html | 66 +++-- demo/demo1.ts | 29 +- demo/demo10.ts | 221 +++++++------- demo/demo11.ts | 161 +++++----- demo/demo12.ts | 20 +- demo/demo13.ts | 34 +-- demo/demo14.ts | 51 ++-- demo/demo15.ts | 15 +- demo/demo16.ts | 95 +++--- demo/demo17.ts | 8 +- demo/demo18.ts | 13 +- demo/demo19.ts | 28 +- demo/demo2.ts | 148 ++++------ demo/demo20.ts | 2 +- demo/demo21.ts | 28 +- demo/demo22.ts | 62 ++-- demo/demo23.ts | 26 +- demo/demo24.ts | 4 +- demo/demo26.ts | 43 ++- demo/demo27.ts | 31 +- demo/demo28.ts | 63 ++-- demo/demo29.ts | 99 +++---- demo/demo3.ts | 125 ++++---- demo/demo30.ts | 16 +- demo/demo31.ts | 8 +- demo/demo32.ts | 64 ++-- demo/demo33.ts | 29 +- demo/demo34.ts | 6 +- demo/demo35.ts | 4 +- demo/demo36.ts | 16 +- demo/demo37.ts | 16 +- demo/demo38.ts | 31 +- demo/demo39.ts | 58 ++-- demo/demo4.ts | 6 +- demo/demo40.ts | 38 ++- demo/demo41.ts | 6 +- demo/demo43.ts | 7 +- demo/demo44.ts | 40 +-- demo/demo5.ts | 41 ++- demo/demo6.ts | 56 ++-- demo/demo7.ts | 13 +- demo/demo8.ts | 19 +- demo/demo9.ts | 28 +- src/export/packer/next-compiler.spec.ts | 37 ++- src/export/packer/packer.spec.ts | 36 ++- src/file/document/body/body.spec.ts | 73 +---- src/file/document/body/body.ts | 31 +- .../header-reference/header-reference.ts | 4 +- src/file/document/document.spec.ts | 41 ++- src/file/document/document.ts | 18 +- src/file/file.spec.ts | 111 +++---- src/file/file.ts | 279 +++++------------- src/file/footer-wrapper.spec.ts | 11 - src/file/footer-wrapper.ts | 14 - src/file/header-wrapper.spec.ts | 11 - src/file/header-wrapper.ts | 14 - src/file/header.ts | 14 + src/file/index.ts | 1 + src/file/media/image.ts | 4 - src/file/numbering/level.ts | 3 +- src/file/paragraph/image.spec.ts | 192 +----------- src/file/paragraph/image.ts | 4 - src/file/paragraph/run/picture-run.ts | 10 +- 63 files changed, 1194 insertions(+), 1588 deletions(-) create mode 100644 src/file/header.ts diff --git a/demo/browser-demo.html b/demo/browser-demo.html index 535b55beea..a199c1b4e8 100644 --- a/demo/browser-demo.html +++ b/demo/browser-demo.html @@ -1,39 +1,45 @@ + + + + - - - - + +

DOCX browser Word document generation

- + -

DOCX browser Word document generation

+ - - + const packer = new Packer(); + packer.toBlob(doc).then((blob) => { + console.log(blob); + saveAs(blob, "example.docx"); + console.log("Document created successfully"); + }); + } + + diff --git a/demo/demo1.ts b/demo/demo1.ts index c8ed2e4781..2787c869d7 100644 --- a/demo/demo1.ts +++ b/demo/demo1.ts @@ -5,19 +5,24 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun({ - text: "Foo Bar", - bold: true, +doc.addSection({ + properties: {}, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + new TextRun({ + text: "Github is the best", + bold: true, + }).tab(), + ], + }), + ], }); -const dateText = new TextRun({ - text: "Github is the best", - bold: true, -}).tab(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo10.ts b/demo/demo10.ts index 62077cf4c4..f7a89a0512 100644 --- a/demo/demo10.ts +++ b/demo/demo10.ts @@ -127,97 +127,86 @@ const achievements = [ ]; class DocumentCreator { - public create(data: object[]): Document { - // tslint:disable-next-line:no-any - const experiences = data[0] as any[]; - // tslint:disable-next-line:no-any - const educations = data[1] as any[]; - const skills = data[2] as object[]; - const achivements = data[3] as object[]; + // tslint:disable-next-line: typedef + public create([experiences, educations, skills, achivements]): Document { const document = new Document(); - document.add( - new Paragraph({ - text: "Dolan Miu", - heading: HeadingLevel.TITLE, - }), - ); - document.add(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); - document.add(this.createHeading("Education")); + document.addSection({ + children: [ + new Paragraph({ + text: "Dolan Miu", + heading: HeadingLevel.TITLE, + }), + this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL), + this.createHeading("Education"), + ...educations + .map((education) => { + const arr: Paragraph[] = []; + arr.push( + this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`), + ); + arr.push(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`)); - for (const education of educations) { - document.add( - this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`), - ); - document.add(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`)); + const bulletPoints = this.splitParagraphIntoBullets(education.notes); + bulletPoints.forEach((bulletPoint) => { + arr.push(this.createBullet(bulletPoint)); + }); - const bulletPoints = this.splitParagraphIntoBullets(education.notes); - bulletPoints.forEach((bulletPoint) => { - document.add(this.createBullet(bulletPoint)); - }); - } + return arr; + }) + .reduce((prev, curr) => prev.concat(curr), []), + this.createHeading("Experience"), + ...experiences + .map((position) => { + const arr: Paragraph[] = []; - document.add(this.createHeading("Experience")); + arr.push( + this.createInstitutionHeader( + position.company.name, + this.createPositionDateText(position.startDate, position.endDate, position.isCurrent), + ), + ); + arr.push(this.createRoleText(position.title)); - for (const position of experiences) { - document.add( - this.createInstitutionHeader( - position.company.name, - this.createPositionDateText(position.startDate, position.endDate, position.isCurrent), + const bulletPoints = this.splitParagraphIntoBullets(position.summary); + + bulletPoints.forEach((bulletPoint) => { + arr.push(this.createBullet(bulletPoint)); + }); + + return arr; + }) + .reduce((prev, curr) => prev.concat(curr), []), + this.createHeading("Skills, Achievements and Interests"), + this.createSubHeading("Skills"), + this.createSkillList(skills), + this.createSubHeading("Achievements"), + ...this.createAchivementsList(achivements), + this.createSubHeading("Interests"), + this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing."), + this.createHeading("References"), + new Paragraph( + "Dr. Dean Mohamedally Director of Postgraduate Studies Department of Computer Science, University College London Malet Place, Bloomsbury, London WC1E d.mohamedally@ucl.ac.uk", ), - ); - document.add(this.createRoleText(position.title)); + new Paragraph("More references upon request"), + new Paragraph({ + text: "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", + alignment: AlignmentType.CENTER, + }), + ], + }); - const bulletPoints = this.splitParagraphIntoBullets(position.summary); - - bulletPoints.forEach((bulletPoint) => { - document.add(this.createBullet(bulletPoint)); - }); - } - - document.add(this.createHeading("Skills, Achievements and Interests")); - - document.add(this.createSubHeading("Skills")); - document.add(this.createSkillList(skills)); - - document.add(this.createSubHeading("Achievements")); - - for (const achievementParagraph of this.createAchivementsList(achivements)) { - document.add(achievementParagraph); - } - - document.add(this.createSubHeading("Interests")); - - document.add(this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing.")); - - document.add(this.createHeading("References")); - - document.add( - new Paragraph( - "Dr. Dean Mohamedally Director of Postgraduate Studies Department of Computer Science, University College London Malet Place, Bloomsbury, London WC1E d.mohamedally@ucl.ac.uk", - ), - ); - document.add(new Paragraph("More references upon request")); - document.add( - new Paragraph({ - text: "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", - alignment: AlignmentType.CENTER, - }), - ); return document; } public createContactInfo(phoneNumber: string, profileUrl: string, email: string): Paragraph { - const paragraph = new Paragraph({ + return new Paragraph({ alignment: AlignmentType.CENTER, + children: [ + new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`), + new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(), + ], }); - const contactInfo = new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`); - const address = new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(); - - paragraph.addRun(contactInfo); - paragraph.addRun(address); - - return paragraph; } public createHeading(text: string): Paragraph { @@ -236,36 +225,32 @@ class DocumentCreator { } public createInstitutionHeader(institutionName: string, dateText: string): Paragraph { - const paragraph = new Paragraph({ + return new Paragraph({ tabStop: { maxRight: {}, }, + children: [ + new TextRun({ + text: institutionName, + bold: true, + }), + new TextRun({ + text: dateText, + bold: true, + }).tab(), + ], }); - const institution = new TextRun({ - text: institutionName, - bold: true, - }); - const date = new TextRun({ - text: dateText, - bold: true, - }).tab(); - - paragraph.addRun(institution); - paragraph.addRun(date); - - return paragraph; } public createRoleText(roleText: string): Paragraph { - const paragraph = new Paragraph({}); - const role = new TextRun({ - text: roleText, - italics: true, + return new Paragraph({ + children: [ + new TextRun({ + text: roleText, + italics: true, + }), + ], }); - - paragraph.addRun(role); - - return paragraph; } public createBullet(text: string): Paragraph { @@ -279,36 +264,28 @@ class DocumentCreator { // tslint:disable-next-line:no-any public createSkillList(skills: any[]): Paragraph { - const paragraph = new Paragraph({}); - const skillConcat = skills.map((skill) => skill.name).join(", ") + "."; - - paragraph.addRun(new TextRun(skillConcat)); - - return paragraph; + return new Paragraph({ + children: [new TextRun(skills.map((skill) => skill.name).join(", ") + ".")], + }); } // tslint:disable-next-line:no-any public createAchivementsList(achivements: any[]): Paragraph[] { - const arr: Paragraph[] = []; - - for (const achievement of achivements) { - const paragraph = new Paragraph({ - text: achievement.name, - bullet: { - level: 0, - }, - }); - arr.push(paragraph); - } - - return arr; + return achivements.map( + (achievement) => + new Paragraph({ + text: achievement.name, + bullet: { + level: 0, + }, + }), + ); } public createInterests(interests: string): Paragraph { - const paragraph = new Paragraph({}); - - paragraph.addRun(new TextRun(interests)); - return paragraph; + return new Paragraph({ + children: [new TextRun(interests)], + }); } public splitParagraphIntoBullets(text: string): string[] { diff --git a/demo/demo11.ts b/demo/demo11.ts index 3861447df9..e286ed7556 100644 --- a/demo/demo11.ts +++ b/demo/demo11.ts @@ -1,14 +1,9 @@ // Setting styles with JavaScript configuration // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, Table } from "../build"; +import { AlignmentType, Document, Footer, HeadingLevel, Media, Packer, Paragraph, Table } from "../build"; -const doc = new Document(undefined, { - top: 700, - right: 700, - bottom: 700, - left: 700, -}); +const doc = new Document(); doc.Styles.createParagraphStyle("Heading1", "Heading 1") .basedOn("Normal") @@ -83,76 +78,7 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") .quickFormat() .basedOn("Normal"); -doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.add( - new Paragraph({ - text: "HEADING", - heading: HeadingLevel.HEADING_1, - alignment: AlignmentType.CENTER, - }), -); - -doc.Footer.add( - new Paragraph({ - text: "1", - style: "normalPara", - alignment: AlignmentType.RIGHT, - }), -); - -doc.add( - new Paragraph({ - text: "Ref. :", - style: "normalPara", - }), -); -doc.add( - new Paragraph({ - text: "Date :", - style: "normalPara", - }), -); - -doc.add( - new Paragraph({ - text: "To,", - style: "normalPara", - }), -); -doc.add( - new Paragraph({ - text: "The Superindenting Engineer,(O &M)", - style: "normalPara", - }), -); - -doc.add( - new Paragraph({ - text: "Sub : ", - style: "normalPara", - }), -); - -doc.add( - new Paragraph({ - text: "Ref. : ", - style: "normalPara", - }), -); - -doc.add( - new Paragraph({ - text: "Sir,", - style: "normalPara", - }), -); - -doc.add( - new Paragraph({ - text: "BRIEF DESCRIPTION", - style: "normalPara", - }), -); +const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); const table = new Table({ rows: 4, @@ -163,27 +89,78 @@ table .getCell(0) .add(new Paragraph("Pole No.")); -doc.add(table); +const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -const arrboth = [ - { - image: "./demo/images/pizza.gif", - comment: "Test", +doc.addSection({ + properties: { + top: 700, + right: 700, + bottom: 700, + left: 700, }, - { - image: "./demo/images/pizza.gif", - comment: "Test 2", + footers: { + default: new Footer({ + children: [ + new Paragraph({ + text: "1", + style: "normalPara", + alignment: AlignmentType.RIGHT, + }), + ], + }), }, -]; - -arrboth.forEach((item) => { - doc.createImage(fs.readFileSync(item.image)); - doc.add( + children: [ + new Paragraph(image), new Paragraph({ - text: item.comment, + text: "HEADING", + heading: HeadingLevel.HEADING_1, + alignment: AlignmentType.CENTER, + }), + new Paragraph({ + text: "Ref. :", + style: "normalPara", + }), + new Paragraph({ + text: "Date :", + style: "normalPara", + }), + new Paragraph({ + text: "To,", + style: "normalPara", + }), + new Paragraph({ + text: "The Superindenting Engineer,(O &M)", + style: "normalPara", + }), + new Paragraph({ + text: "Sub : ", + style: "normalPara", + }), + new Paragraph({ + text: "Ref. : ", + style: "normalPara", + }), + new Paragraph({ + text: "Sir,", + style: "normalPara", + }), + new Paragraph({ + text: "BRIEF DESCRIPTION", + style: "normalPara", + }), + table, + new Paragraph(image1), + new Paragraph({ + text: "Test", style: "normalPara2", }), - ); + new Paragraph(image2), + new Paragraph({ + text: "Test 2", + style: "normalPara2", + }), + ], }); const packer = new Packer(); diff --git a/demo/demo12.ts b/demo/demo12.ts index f27aee4968..2de556a262 100644 --- a/demo/demo12.ts +++ b/demo/demo12.ts @@ -1,22 +1,18 @@ // Scaling images // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -doc.add(paragraph); +const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 50, 50); +const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 100, 100); +const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 250, 250); +const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 400, 400); -const image = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -const image2 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -const image3 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -const image4 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); - -image.scale(0.5); -image2.scale(1); -image3.scale(2.5); -image4.scale(4); +doc.addSection({ + children: [new Paragraph("Hello World"), new Paragraph(image), new Paragraph(image2), new Paragraph(image3), new Paragraph(image4)], +}); const packer = new Packer(); diff --git a/demo/demo13.ts b/demo/demo13.ts index 53287c2e1a..9d84777f68 100644 --- a/demo/demo13.ts +++ b/demo/demo13.ts @@ -9,25 +9,23 @@ const doc = new Document({ externalStyles: styles, }); -doc.add(new Paragraph({ - text: "Cool Heading Text", - heading: HeadingLevel.HEADING_1, -})); - -const paragraph = new Paragraph({ - text: 'This is a custom named style from the template "MyFancyStyle"', - style: "MyFancyStyle", +doc.addSection({ + children: [ + new Paragraph({ + text: "Cool Heading Text", + heading: HeadingLevel.HEADING_1, + }), + new Paragraph({ + text: 'This is a custom named style from the template "MyFancyStyle"', + style: "MyFancyStyle", + }), + new Paragraph("Some normal text"), + new Paragraph({ + text: "MyFancyStyle again", + style: "MyFancyStyle", + }), + ], }); -doc.add(paragraph); - -doc.add(new Paragraph("Some normal text")); - -doc.add(new Paragraph({ - text: "MyFancyStyle again", - style: "MyFancyStyle", -})); - -doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo14.ts b/demo/demo14.ts index 310f854301..f8e024547c 100644 --- a/demo/demo14.ts +++ b/demo/demo14.ts @@ -1,36 +1,37 @@ // Page numbers // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { AlignmentType, Document, Packer, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, Header, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -doc.add( - new Paragraph({ - text: "First Page", - }).pageBreak(), -); -doc.add(new Paragraph("Second Page")); - -const pageNumber = new TextRun("Page ").pageNumber(); - -const pageoneheader = new Paragraph({ - text: "First Page Header ", - alignment: AlignmentType.RIGHT, +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [new TextRun("My Title "), new TextRun("Page ").pageNumber()], + }), + ], + }), + first: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [new TextRun("First Page Header "), new TextRun("Page ").pageNumber()], + }), + ], + }), + }, + children: [ + new Paragraph({ + text: "First Page", + }).pageBreak(), + new Paragraph("Second Page"), + ], }); -pageoneheader.addRun(pageNumber); -const firstPageHeader = doc.createFirstPageHeader(); -firstPageHeader.add(pageoneheader); - -const pagetwoheader = new Paragraph({ - text: "My Title ", - alignment: AlignmentType.RIGHT, -}); - -pagetwoheader.addRun(pageNumber); -doc.Header.add(pagetwoheader); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo15.ts b/demo/demo15.ts index f25639bf2f..73ab48680e 100644 --- a/demo/demo15.ts +++ b/demo/demo15.ts @@ -5,15 +5,16 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -const paragraph2 = new Paragraph({ - text: "Hello World on another page", - pageBreakBefore: true, +doc.addSection({ + children: [ + new Paragraph("Hello World"), + new Paragraph({ + text: "Hello World on another page", + pageBreakBefore: true, + }), + ], }); -doc.add(paragraph); -doc.add(paragraph2); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo16.ts b/demo/demo16.ts index ee77ce7ebb..ede5e4058e 100644 --- a/demo/demo16.ts +++ b/demo/demo16.ts @@ -1,27 +1,26 @@ // Multiple sections and headers // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build"; +import { Document, Footer, Header, Packer, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World").pageBreak(); - -doc.add(paragraph); - -const header = doc.createHeader(); -header.add(new Paragraph("Header on another page")); -const footer = doc.createFooter(); -footer.add(new Paragraph("Footer on another page")); +doc.addSection({ + children: [new Paragraph("Hello World").pageBreak()], +}); doc.addSection({ + headers: { + default: new Header({ + children: [new Paragraph("First Default Header on another page")], + }), + }, + footers: { + default: new Footer({ + children: [new Paragraph("Footer on another page")], + }), + }, properties: { - headers: { - default: header, - }, - footers: { - default: footer, - }, pageNumberStart: 1, pageNumberFormatType: PageNumberFormat.DECIMAL, }, @@ -29,39 +28,53 @@ doc.addSection({ }); doc.addSection({ + headers: { + default: new Header({ + children: [new Paragraph("Second Default Header on another page")], + }), + }, + footers: { + default: new Footer({ + children: [new Paragraph("Footer on another page")], + }), + }, + size: { + orientation: PageOrientation.LANDSCAPE, + }, properties: { - headers: { - default: header, - }, - footers: { - default: footer, - }, pageNumberStart: 1, pageNumberFormatType: PageNumberFormat.DECIMAL, - orientation: PageOrientation.LANDSCAPE, }, children: [new Paragraph("hello in landscape")], }); -const header2 = doc.createHeader(); -const pageNumber = new TextRun("Page number: ").pageNumber(); -header2.add(new Paragraph({}).addRun(pageNumber)); - doc.addSection({ - properties: { - headers: { - default: header2, - }, + headers: { + default: new Header({ + children: [ + new Paragraph({ + children: [new TextRun("Page number: ").pageNumber()], + }), + ], + }), + }, + size: { orientation: PageOrientation.PORTRAIT, }, children: [new Paragraph("Page number in the header must be 2, because it continues from the previous section.")], }); doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + children: [new TextRun("Page number: ").pageNumber()], + }), + ], + }), + }, properties: { - headers: { - default: header2, - }, pageNumberFormatType: PageNumberFormat.UPPER_ROMAN, orientation: PageOrientation.PORTRAIT, }, @@ -73,13 +86,21 @@ doc.addSection({ }); doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + children: [new TextRun("Page number: ").pageNumber()], + }), + ], + }), + }, + size: { + orientation: PageOrientation.PORTRAIT, + }, properties: { - headers: { - default: header2, - }, pageNumberFormatType: PageNumberFormat.DECIMAL, pageNumberStart: 25, - orientation: PageOrientation.PORTRAIT, }, children: [ new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section."), diff --git a/demo/demo17.ts b/demo/demo17.ts index 1d928b60b5..e316ea4edb 100644 --- a/demo/demo17.ts +++ b/demo/demo17.ts @@ -5,11 +5,9 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World").referenceFootnote(1); -const paragraph2 = new Paragraph("Hello World").referenceFootnote(2); - -doc.add(paragraph); -doc.add(paragraph2); +doc.addSection({ + children: [new Paragraph("Hello World").referenceFootnote(1), new Paragraph("Hello World").referenceFootnote(2)], +}); doc.createFootnote(new Paragraph("Test")); doc.createFootnote(new Paragraph("My amazing reference")); diff --git a/demo/demo18.ts b/demo/demo18.ts index 4a61488c1f..7eefdc4328 100644 --- a/demo/demo18.ts +++ b/demo/demo18.ts @@ -1,14 +1,21 @@ // Insert image from a buffer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`; -// doc.createImage(Buffer.from(imageBase64Data, 'base64')); -doc.createImage(Buffer.from(imageBase64Data, "base64"), 100, 100); +const image = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100); + +doc.addSection({ + children: [ + new Paragraph({ + children: [image], + }), + ], +}); const packer = new Packer(); diff --git a/demo/demo19.ts b/demo/demo19.ts index f8930db836..84991cc929 100644 --- a/demo/demo19.ts +++ b/demo/demo19.ts @@ -5,19 +5,23 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun({ - text: "Foo", - bold: true, +doc.addSection({ + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo", + bold: true, + }), + new TextRun({ + text: "Bar", + bold: true, + }).tab(), + ], + }), + ], }); -const dateText = new TextRun({ - text: "Bar", - bold: true, -}).tab(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.add(paragraph); const packer = new Packer(); diff --git a/demo/demo2.ts b/demo/demo2.ts index 5764f40f91..3397f41ee8 100644 --- a/demo/demo2.ts +++ b/demo/demo2.ts @@ -46,96 +46,76 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") const numberedAbstract = doc.Numbering.createAbstractNumbering(); numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left"); -doc.add( - new Paragraph({ - text: "Test heading1, bold and italicized", - heading: HeadingLevel.HEADING_1, - }), -); -doc.add(new Paragraph("Some simple content")); -doc.add( - new Paragraph({ - text: "Test heading2 with double red underline", - heading: HeadingLevel.HEADING_2, - }), -); - const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract); const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract); letterNumbering5.overrideLevel(0, 5); -doc.add( - new Paragraph({ - text: "Option1", - numbering: { - num: letterNumbering, - level: 0, - }, - }), -); -doc.add( - new Paragraph({ - text: "Option5 -- override 2 to 5", - numbering: { - num: letterNumbering, - level: 0, - }, - }), -); -doc.add( - new Paragraph({ - text: "Option3", - numbering: { - num: letterNumbering, - level: 0, - }, - }), -); - -doc.add( - new Paragraph({}).addRun( - new TextRun({ - text: "Some monospaced content", - font: { - name: "Monospace", +doc.addSection({ + children: [ + new Paragraph({ + text: "Test heading1, bold and italicized", + heading: HeadingLevel.HEADING_1, + }), + new Paragraph("Some simple content"), + new Paragraph({ + text: "Test heading2 with double red underline", + heading: HeadingLevel.HEADING_2, + }), + new Paragraph({ + text: "Option1", + numbering: { + num: letterNumbering, + level: 0, }, }), - ), -); - -doc.add( - new Paragraph({ - text: "An aside, in light gray italics and indented", - style: "aside", - }), -); -doc.add( - new Paragraph({ - text: "This is normal, but well-spaced text", - style: "wellSpaced", - }), -); -const para = new Paragraph({}); -doc.add(para); -// Showing the different ways to create a TextRun -para.addRun( - new TextRun({ - text: "This is a bold run,", - bold: true, - }), -); -para.addRun(new TextRun(" switching to normal ")); -para.addRun( - new TextRun({ - text: "and then underlined ", - underline: {}, - }), -); -para.addRun( - new TextRun({ - text: "and back to normal.", - }), -); + new Paragraph({ + text: "Option5 -- override 2 to 5", + numbering: { + num: letterNumbering, + level: 0, + }, + }), + new Paragraph({ + text: "Option3", + numbering: { + num: letterNumbering, + level: 0, + }, + }), + new Paragraph({}).addRun( + new TextRun({ + text: "Some monospaced content", + font: { + name: "Monospace", + }, + }), + ), + new Paragraph({ + text: "An aside, in light gray italics and indented", + style: "aside", + }), + new Paragraph({ + text: "This is normal, but well-spaced text", + style: "wellSpaced", + }), + new Paragraph({ + children: [ + new TextRun({ + text: "This is a bold run,", + bold: true, + }), + new TextRun(" switching to normal "), + new TextRun({ + text: "and then underlined ", + underline: {}, + }), + new TextRun({ + text: "and back to normal.", + }), + ], + }), + ], +}); const packer = new Packer(); diff --git a/demo/demo20.ts b/demo/demo20.ts index b861a10cfa..ee2b7918e2 100644 --- a/demo/demo20.ts +++ b/demo/demo20.ts @@ -10,7 +10,7 @@ const table = new Table({ columns: 4, }); -doc.add(table); +doc.addSection({ children: [table] }); table .getCell(2, 2) .add(new Paragraph("Hello")) diff --git a/demo/demo21.ts b/demo/demo21.ts index 5ce3bc2930..1193ee01c0 100644 --- a/demo/demo21.ts +++ b/demo/demo21.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import { Document, HeadingLevel, Packer, Paragraph } from "../build"; -const loremIpsum = +const LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante."; const doc = new Document({ @@ -16,21 +16,19 @@ const anchorId = "anchorID"; // First create the bookmark const bookmark = doc.createBookmark(anchorId, "Lorem Ipsum"); -// That has header styling -doc.add( - new Paragraph({ - heading: HeadingLevel.HEADING_1, - }).addBookmark(bookmark), -); - -doc.add(new Paragraph("\n")); - -doc.add(new Paragraph(loremIpsum)); -doc.add(new Paragraph({}).pageBreak()); - -// Now the link back up to the bookmark const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); -doc.add(new Paragraph({}).addHyperLink(hyperlink)); + +doc.addSection({ + children: [ + new Paragraph({ + heading: HeadingLevel.HEADING_1, + }).addBookmark(bookmark), + new Paragraph("\n"), + new Paragraph(LOREM_IPSUM), + new Paragraph({}).pageBreak(), + new Paragraph({}).addHyperLink(hyperlink), + ], +}); const packer = new Packer(); diff --git a/demo/demo22.ts b/demo/demo22.ts index c92406071e..3a70c01d21 100644 --- a/demo/demo22.ts +++ b/demo/demo22.ts @@ -5,37 +5,39 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph1 = new Paragraph({ - bidirectional: true, +doc.addSection({ + children: [ + new Paragraph({ + bidirectional: true, + children: [ + new TextRun({ + text: "שלום עולם", + rightToLeft: true, + }), + ], + }), + new Paragraph({ + bidirectional: true, + children: [ + new TextRun({ + text: "שלום עולם", + bold: true, + rightToLeft: true, + }), + ], + }), + new Paragraph({ + bidirectional: true, + children: [ + new TextRun({ + text: "שלום עולם", + italics: true, + rightToLeft: true, + }), + ], + }), + ], }); -const textRun1 = new TextRun({ - text: "שלום עולם", - rightToLeft: true, -}); -paragraph1.addRun(textRun1); -doc.add(paragraph1); - -const paragraph2 = new Paragraph({ - bidirectional: true, -}); -const textRun2 = new TextRun({ - text: "שלום עולם", - bold: true, - rightToLeft: true, -}); -paragraph2.addRun(textRun2); -doc.add(paragraph2); - -const paragraph3 = new Paragraph({ - bidirectional: true, -}); -const textRun3 = new TextRun({ - text: "שלום עולם", - italics: true, - rightToLeft: true, -}); -paragraph3.addRun(textRun3); -doc.add(paragraph3); const packer = new Packer(); diff --git a/demo/demo23.ts b/demo/demo23.ts index 8cbdac292c..5333d91e9b 100644 --- a/demo/demo23.ts +++ b/demo/demo23.ts @@ -1,13 +1,10 @@ // This demo adds an image to the Media cache, and then insert to the document afterwards // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer, Paragraph } from "../build"; +import { Document, Media, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -doc.add(paragraph); - const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png")); const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg")); @@ -17,15 +14,18 @@ const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`; const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100); -// I am adding an image to the paragraph rather than the document to make the image inline -paragraph.addImage(image5); - -doc.add(image); -doc.add(image2); -doc.add(image3); -doc.add(image4); -doc.add(image5); -doc.add(image6); +doc.addSection({ + children: [ + new Paragraph({ + children: [new TextRun("Hello World"), image5], + }), + new Paragraph(image), + new Paragraph(image2), + new Paragraph(image3), + new Paragraph(image4), + new Paragraph(image6), + ], +}); const packer = new Packer(); diff --git a/demo/demo24.ts b/demo/demo24.ts index fc940eed1d..2ea6f664c3 100644 --- a/demo/demo24.ts +++ b/demo/demo24.ts @@ -10,7 +10,9 @@ const table = new Table({ columns: 4, }); -doc.add(table); +doc.addSection({ + children: [table], +}); table.getCell(2, 2).add(new Paragraph("Hello")); diff --git a/demo/demo26.ts b/demo/demo26.ts index ef914e9465..421d8477e5 100644 --- a/demo/demo26.ts +++ b/demo/demo26.ts @@ -5,30 +5,29 @@ import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("No border!"); - -doc.add(paragraph); - -const borderParagraph = new Paragraph({ - text: "I have borders on my top and bottom sides!", - border: { - top: { - color: "auto", - space: 1, - value: "single", - size: 6, - }, - bottom: { - color: "auto", - space: 1, - value: "single", - size: 6, - }, - }, +doc.addSection({ + children: [ + new Paragraph("No border!"), + new Paragraph({ + text: "I have borders on my top and bottom sides!", + border: { + top: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + bottom: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + }, + }), + ], }); -doc.add(borderParagraph); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo27.ts b/demo/demo27.ts index 28d2ba5d09..a31ce0b44b 100644 --- a/demo/demo27.ts +++ b/demo/demo27.ts @@ -4,12 +4,10 @@ import * as fs from "fs"; import { Document, HeadingLevel, Packer, Paragraph } from "../build"; const doc = new Document(); -const myStyles = doc.Styles; // The first argument is an ID you use to apply the style to paragraphs // The second argument is a human-friendly name to show in the UI -myStyles - .createParagraphStyle("myWonkyStyle", "My Wonky Style") +doc.Styles.createParagraphStyle("myWonkyStyle", "My Wonky Style") .basedOn("Normal") .next("Normal") .color("990000") @@ -17,8 +15,7 @@ myStyles .indent({ left: 720 }) // 720 TWIP === 720 / 20 pt === .5 in .spacing({ line: 276 }); // 276 / 240 = 1.15x line spacing -myStyles - .createParagraphStyle("Heading2", "Heading 2") +doc.Styles.createParagraphStyle("Heading2", "Heading 2") .basedOn("Normal") .next("Normal") .quickFormat() @@ -27,18 +24,18 @@ myStyles .underline("double", "FF0000") .spacing({ before: 240, after: 120 }); // TWIP for both -doc.add( - new Paragraph({ - text: "Hello", - style: "myWonkyStyle", - }), -); -doc.add( - new Paragraph({ - text: "World", - heading: HeadingLevel.HEADING_2, - }), -); // Uses the Heading2 style +doc.addSection({ + children: [ + new Paragraph({ + text: "Hello", + style: "myWonkyStyle", + }), + new Paragraph({ + text: "World", + heading: HeadingLevel.HEADING_2, + }), + ], +}); const packer = new Packer(); diff --git a/demo/demo28.ts b/demo/demo28.ts index 0bef4470bc..414c2ad97d 100644 --- a/demo/demo28.ts +++ b/demo/demo28.ts @@ -18,39 +18,40 @@ doc.Styles.createParagraphStyle("MySpectacularStyle", "My Spectacular Style") // Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle, // making the entries be hyperlinks for the paragraph -const toc = new TableOfContents("Summary", { - hyperlink: true, - headingStyleRange: "1-5", - stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)], + +doc.addSection({ + children: [ + new TableOfContents("Summary", { + hyperlink: true, + headingStyleRange: "1-5", + stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)], + }), + new Paragraph({ + text: "Header #1", + heading: HeadingLevel.HEADING_1, + pageBreakBefore: true, + }), + new Paragraph("I'm a little text very nicely written.'"), + new Paragraph({ + text: "Header #2", + heading: HeadingLevel.HEADING_1, + pageBreakBefore: true, + }), + new Paragraph("I'm a other text very nicely written.'"), + new Paragraph({ + text: "Header #2.1", + heading: HeadingLevel.HEADING_2, + }), + new Paragraph("I'm a another text very nicely written.'"), + new Paragraph({ + text: "My Spectacular Style #1", + style: "MySpectacularStyle", + pageBreakBefore: true, + }), + + ], }); -doc.addTableOfContents(toc); - -doc.add(new Paragraph({ - text: "Header #1", - heading: HeadingLevel.HEADING_1, - pageBreakBefore: true, -})); -doc.add(new Paragraph("I'm a little text very nicely written.'")); - -doc.add(new Paragraph({ - text: "Header #2", - heading: HeadingLevel.HEADING_1, - pageBreakBefore: true, -})); -doc.add(new Paragraph("I'm a other text very nicely written.'")); -doc.add(new Paragraph({ - text: "Header #2.1", - heading: HeadingLevel.HEADING_2, -})); -doc.add(new Paragraph("I'm a another text very nicely written.'")); - -doc.add(new Paragraph({ - text: "My Spectacular Style #1", - style: "MySpectacularStyle", - pageBreakBefore: true, -})); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo29.ts b/demo/demo29.ts index f8982e425d..31dcd6d28f 100644 --- a/demo/demo29.ts +++ b/demo/demo29.ts @@ -1,66 +1,65 @@ // Numbered lists // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Indent, Numbering, Packer, Paragraph } from "../build"; +import { Document, Numbering, Packer, Paragraph } from "../build"; const doc = new Document(); const numbering = new Numbering(); const abstractNum = numbering.createAbstractNumbering(); -abstractNum.createLevel(0, "upperRoman", "%1", "start").addProperty(new Indent({ left: 720, hanging: 260 })); +abstractNum.createLevel(0, "upperRoman", "%1", "start").indent({ left: 720, hanging: 260 }); const concrete = numbering.createConcreteNumbering(abstractNum); -const item1 = new Paragraph({ - text: "line with contextual spacing", - numbering: { - num: concrete, - level: 0, - }, - contextualSpacing: true, - spacing: { - before: 200, - }, +doc.addSection({ + children: [ + new Paragraph({ + text: "line with contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: true, + spacing: { + before: 200, + }, + }), + new Paragraph({ + text: "line with contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: true, + spacing: { + before: 200, + }, + }), + new Paragraph({ + text: "line without contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: false, + spacing: { + before: 200, + }, + }), + new Paragraph({ + text: "line without contextual spacing", + numbering: { + num: concrete, + level: 0, + }, + contextualSpacing: false, + spacing: { + before: 200, + }, + }), + ], }); -const item2 = new Paragraph({ - text: "line with contextual spacing", - numbering: { - num: concrete, - level: 0, - }, - contextualSpacing: true, - spacing: { - before: 200, - }, -}); -const item3 = new Paragraph({ - text: "line without contextual spacing", - numbering: { - num: concrete, - level: 0, - }, - contextualSpacing: false, - spacing: { - before: 200, - }, -}); -const item4 = new Paragraph({ - text: "line without contextual spacing", - numbering: { - num: concrete, - level: 0, - }, - contextualSpacing: false, - spacing: { - before: 200, - }, -}); - -doc.add(item1); -doc.add(item2); -doc.add(item3); -doc.add(item4); const packer = new Packer(); diff --git a/demo/demo3.ts b/demo/demo3.ts index e901049ec9..79545c75ec 100644 --- a/demo/demo3.ts +++ b/demo/demo3.ts @@ -1,82 +1,75 @@ // Numbering and bullet points example // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Indent, Numbering, Packer, Paragraph } from "../build"; +import { Document, Numbering, Packer, Paragraph } from "../build"; const doc = new Document(); const numbering = new Numbering(); const abstractNum = numbering.createAbstractNumbering(); -abstractNum.createLevel(0, "upperRoman", "%1", "start").addProperty(new Indent({ left: 720, hanging: 260 })); -abstractNum.createLevel(1, "decimal", "%2.", "start").addProperty(new Indent({ left: 1440, hanging: 980 })); -abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addProperty(new Indent({ left: 14402160, hanging: 1700 })); +abstractNum.createLevel(0, "upperRoman", "%1", "start").indent({ left: 720, hanging: 260 }); +abstractNum.createLevel(1, "decimal", "%2.", "start").indent({ left: 1440, hanging: 980 }); +abstractNum.createLevel(2, "lowerLetter", "%3)", "start").indent({ left: 14402160, hanging: 1700 }); const concrete = numbering.createConcreteNumbering(abstractNum); -const topLevelP = new Paragraph({ - text: "Hey you", - numbering: { - num: concrete, - level: 0, - }, +doc.addSection({ + children: [ + new Paragraph({ + text: "Hey you", + numbering: { + num: concrete, + level: 0, + }, + }), + new Paragraph({ + text: "What's up fam", + numbering: { + num: concrete, + level: 1, + }, + }), + new Paragraph({ + text: "Hello World 2", + numbering: { + num: concrete, + level: 1, + }, + }), + new Paragraph({ + text: "Yeah boi", + numbering: { + num: concrete, + level: 2, + }, + }), + new Paragraph({ + text: "Hey you", + bullet: { + level: 0, + }, + }), + new Paragraph({ + text: "What's up fam", + bullet: { + level: 1, + }, + }), + new Paragraph({ + text: "Hello World 2", + bullet: { + level: 2, + }, + }), + new Paragraph({ + text: "Yeah boi", + bullet: { + level: 3, + }, + }), + ], }); -const subP = new Paragraph({ - text: "What's up fam", - numbering: { - num: concrete, - level: 1, - }, -}); -const secondSubP = new Paragraph({ - text: "Hello World 2", - numbering: { - num: concrete, - level: 1, - }, -}); -const subSubP = new Paragraph({ - text: "Yeah boi", - numbering: { - num: concrete, - level: 2, - }, -}); - -doc.add(topLevelP); -doc.add(subP); -doc.add(secondSubP); -doc.add(subSubP); - -const bullet1 = new Paragraph({ - text: "Hey you", - bullet: { - level: 0, - }, -}); -const bullet2 = new Paragraph({ - text: "What's up fam", - bullet: { - level: 1, - }, -}); -const bullet3 = new Paragraph({ - text: "Hello World 2", - bullet: { - level: 2, - }, -}); -const bullet4 = new Paragraph({ - text: "Yeah boi", - bullet: { - level: 3, - }, -}); - -doc.add(bullet1); -doc.add(bullet2); -doc.add(bullet3); -doc.add(bullet4); const packer = new Packer(); diff --git a/demo/demo30.ts b/demo/demo30.ts index 92b929bd30..e9ebfd5c2b 100644 --- a/demo/demo30.ts +++ b/demo/demo30.ts @@ -12,16 +12,16 @@ fs.readFile(filePath, (err, data) => { } importDotx.extract(data).then((templateDocument) => { - // This any needs fixing - const sectionProps = { - titlePage: templateDocument.titlePageIsDefined, - } as any; - - const doc = new Document(undefined, sectionProps, { + const doc = new Document(undefined, { template: templateDocument, }); - const paragraph = new Paragraph("Hello World"); - doc.add(paragraph); + + doc.addSection({ + properties: { + titlePage: templateDocument.titlePageIsDefined, + }, + children: [new Paragraph("Hello World")], + }); const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo31.ts b/demo/demo31.ts index 32c8cd755a..d3e4cd3a8a 100644 --- a/demo/demo31.ts +++ b/demo/demo31.ts @@ -1,7 +1,7 @@ // Example of how you would create a table and add data to it // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, HeadingLevel, Packer, Paragraph, VerticalAlign, Table } from "../build"; +import { Document, HeadingLevel, Packer, Paragraph, Table, VerticalAlign } from "../build"; const doc = new Document(); @@ -10,8 +10,6 @@ const table = new Table({ columns: 2, }); -doc.add(table); - table .getCell(1, 1) .add(new Paragraph("This text should be in the middle of the cell")) @@ -25,6 +23,10 @@ table.getCell(1, 0).add( }), ); +doc.addSection({ + children: [table], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo32.ts b/demo/demo32.ts index c2fd76ebf6..8526dc4916 100644 --- a/demo/demo32.ts +++ b/demo/demo32.ts @@ -5,24 +5,15 @@ import { Document, HeadingLevel, Packer, Paragraph, ShadingType, Table, WidthTyp const doc = new Document(); -let table = new Table({ +const table = new Table({ rows: 2, columns: 2, }); -doc.add(table); - table.getCell(0, 0).add(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); -doc.add( - new Paragraph({ - text: "Another table", - heading: HeadingLevel.HEADING_2, - }), -); - -table = new Table({ +const table2 = new Table({ rows: 2, columns: 3, width: 100, @@ -30,9 +21,7 @@ table = new Table({ columnWidths: [1000, 1000, 1000], }); -doc.add(table); - -table +table2 .getCell(0, 0) .add(new Paragraph("World")) .setMargins({ @@ -43,14 +32,7 @@ table }); table.getRow(0).mergeCells(0, 2); -doc.add( - new Paragraph({ - text: "Another table", - heading: HeadingLevel.HEADING_2, - }), -); - -table = new Table({ +const table3 = new Table({ rows: 2, columns: 4, width: 7000, @@ -63,12 +45,10 @@ table = new Table({ }, }); -doc.add(table); +table3.getCell(0, 0).add(new Paragraph("Foo")); +table3.getCell(0, 1).add(new Paragraph("v")); -table.getCell(0, 0).add(new Paragraph("Foo")); -table.getCell(0, 1).add(new Paragraph("v")); - -table +table3 .getCell(1, 0) .add(new Paragraph("Bar1")) .setShading({ @@ -76,7 +56,7 @@ table val: ShadingType.REVERSE_DIAGONAL_STRIPE, color: "auto", }); -table +table3 .getCell(1, 1) .add(new Paragraph("Bar2")) .setShading({ @@ -84,7 +64,7 @@ table val: ShadingType.PERCENT_95, color: "auto", }); -table +table3 .getCell(1, 2) .add(new Paragraph("Bar3")) .setShading({ @@ -92,7 +72,7 @@ table val: ShadingType.PERCENT_10, color: "e2df0b", }); -table +table3 .getCell(1, 3) .add(new Paragraph("Bar4")) .setShading({ @@ -101,18 +81,32 @@ table color: "auto", }); -table.getRow(0).mergeCells(0, 3); +table3.getRow(0).mergeCells(0, 3); -doc.add(new Paragraph("hi")); - -table = new Table({ +const table4 = new Table({ rows: 2, columns: 2, width: 100, widthUnitType: WidthType.PERCENTAGE, }); -doc.add(table); +doc.addSection({ + children: [ + table, + new Paragraph({ + text: "Another table", + heading: HeadingLevel.HEADING_2, + }), + table2, + new Paragraph({ + text: "Another table", + heading: HeadingLevel.HEADING_2, + }), + table3, + new Paragraph("hi"), + table4, + ], +}); const packer = new Packer(); diff --git a/demo/demo33.ts b/demo/demo33.ts index b4831d849b..bf0913d6f1 100644 --- a/demo/demo33.ts +++ b/demo/demo33.ts @@ -5,15 +5,26 @@ import { Document, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World 1->").addSequentialIdentifier("Caption").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Caption"); -const paragraph2 = new Paragraph("Hello World 1->").addSequentialIdentifier("Label").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Label"); -const paragraph3 = new Paragraph("Hello World 1->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 3->")).addSequentialIdentifier("Label"); -const paragraph4 = new Paragraph("Hello World 2->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 4->")).addSequentialIdentifier("Label"); - -doc.add(paragraph); -doc.add(paragraph2); -doc.add(paragraph3); -doc.add(paragraph4); +doc.addSection({ + children: [ + new Paragraph("Hello World 1->") + .addSequentialIdentifier("Caption") + .addRun(new TextRun(" text after sequencial caption 2->")) + .addSequentialIdentifier("Caption"), + new Paragraph("Hello World 1->") + .addSequentialIdentifier("Label") + .addRun(new TextRun(" text after sequencial caption 2->")) + .addSequentialIdentifier("Label"), + new Paragraph("Hello World 1->") + .addSequentialIdentifier("Another") + .addRun(new TextRun(" text after sequencial caption 3->")) + .addSequentialIdentifier("Label"), + new Paragraph("Hello World 2->") + .addSequentialIdentifier("Another") + .addRun(new TextRun(" text after sequencial caption 4->")) + .addSequentialIdentifier("Label"), + ], +}); const packer = new Packer(); diff --git a/demo/demo34.ts b/demo/demo34.ts index 007be8efdb..c24246b709 100644 --- a/demo/demo34.ts +++ b/demo/demo34.ts @@ -29,11 +29,13 @@ const table = new Table({ layout: TableLayoutType.FIXED, }); -doc.add(table); - table.getCell(0, 0).add(new Paragraph("Hello")); table.getRow(0).mergeCells(0, 1); +doc.addSection({ + children: [table], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo35.ts b/demo/demo35.ts index a2927a6957..41117a6a51 100644 --- a/demo/demo35.ts +++ b/demo/demo35.ts @@ -8,7 +8,9 @@ const paragraph = new Paragraph({}); const link = doc.createHyperlink("http://www.example.com", "Hyperlink"); paragraph.addHyperLink(link); -doc.add(paragraph); +doc.addSection({ + children: [paragraph], +}); const packer = new Packer(); diff --git a/demo/demo36.ts b/demo/demo36.ts index 1faf0c3e94..689a07a997 100644 --- a/demo/demo36.ts +++ b/demo/demo36.ts @@ -1,7 +1,7 @@ // Add image to table cell // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer, Paragraph, Table } from "../build"; +import { Document, Header, Media, Packer, Paragraph, Table } from "../build"; const doc = new Document(); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); @@ -12,11 +12,15 @@ const table = new Table({ }); table.getCell(1, 1).add(new Paragraph(image)); -doc.add(table); - -// doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.Header.add(table); -// doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); +// Adding same table in the body and in the header +doc.addSection({ + headers: { + default: new Header({ + children: [table], + }), + }, + children: [table], +}); const packer = new Packer(); diff --git a/demo/demo37.ts b/demo/demo37.ts index 6f599cd15a..08c4e547f5 100644 --- a/demo/demo37.ts +++ b/demo/demo37.ts @@ -1,15 +1,21 @@ // Add images to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Media, Packer, Paragraph } from "../build"; +import { Document, Header, Media, Packer, Paragraph } from "../build"; const doc = new Document(); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -doc.add(new Paragraph("Hello World")); +const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -doc.Header.addImage(image); -doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.Header.createImage(fs.readFileSync("./demo/images/image1.jpeg")); +doc.addSection({ + headers: { + default: new Header({ + children: [new Paragraph(image), new Paragraph(image1), new Paragraph(image2)], + }), + }, + children: [new Paragraph("Hello World")], +}); const packer = new Packer(); diff --git a/demo/demo38.ts b/demo/demo38.ts index eca2c82ef4..84eb162fa5 100644 --- a/demo/demo38.ts +++ b/demo/demo38.ts @@ -2,23 +2,11 @@ // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; // import { Document, Packer, Paragraph } from "../build"; -import { Document, Packer, Paragraph, TextWrappingSide, TextWrappingType } from "../build"; +import { Document, Media, Packer, Paragraph, TextWrappingSide, TextWrappingType } from "../build"; const doc = new Document(); -doc.add(new Paragraph( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.", -)); - -doc.add(new Paragraph( - "Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.", -)); - -doc.add(new Paragraph( - "Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.", -)); - -doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { horizontalPosition: { offset: 2014400, @@ -37,6 +25,21 @@ doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { }, }); +doc.addSection({ + children: [ + new Paragraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.", + ), + new Paragraph( + "Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.", + ), + new Paragraph( + "Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.", + ), + new Paragraph(image), + ], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo39.ts b/demo/demo39.ts index 0c4cf86ca8..811115b876 100644 --- a/demo/demo39.ts +++ b/demo/demo39.ts @@ -1,34 +1,44 @@ // Example how to display page numbers // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { AlignmentType, Document, Packer, PageNumberFormat, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, Footer, Header, Packer, PageNumberFormat, Paragraph, TextRun } from "../build"; -const doc = new Document( - {}, - { +const doc = new Document({}); + +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph("Foo Bar corp. ") + .addRun(new TextRun("Page Number ").pageNumber()) + .addRun(new TextRun(" to ").numberOfTotalPages()), + ], + }), + }, + footers: { + default: new Footer({ + children: [ + new Paragraph({ + text: "Foo Bar corp. ", + alignment: AlignmentType.CENTER, + }) + .addRun(new TextRun("Page Number: ").pageNumber()) + .addRun(new TextRun(" to ").numberOfTotalPages()), + ], + }), + }, + properties: { pageNumberStart: 1, pageNumberFormatType: PageNumberFormat.DECIMAL, }, -); - -doc.Header.add( - new Paragraph("Foo Bar corp. ").addRun(new TextRun("Page Number ").pageNumber()).addRun(new TextRun(" to ").numberOfTotalPages()), -); - -doc.Footer.add( - new Paragraph({ - text: "Foo Bar corp. ", - alignment: AlignmentType.CENTER, - }) - .addRun(new TextRun("Page Number: ").pageNumber()) - .addRun(new TextRun(" to ").numberOfTotalPages()), -); - -doc.add(new Paragraph("Hello World 1").pageBreak()); -doc.add(new Paragraph("Hello World 2").pageBreak()); -doc.add(new Paragraph("Hello World 3").pageBreak()); -doc.add(new Paragraph("Hello World 4").pageBreak()); -doc.add(new Paragraph("Hello World 5").pageBreak()); + children: [ + new Paragraph("Hello World 1").pageBreak(), + new Paragraph("Hello World 2").pageBreak(), + new Paragraph("Hello World 3").pageBreak(), + new Paragraph("Hello World 4").pageBreak(), + new Paragraph("Hello World 5").pageBreak(), + ], +}); const packer = new Packer(); diff --git a/demo/demo4.ts b/demo/demo4.ts index 5e528ac2db..48bcca1c0a 100644 --- a/demo/demo4.ts +++ b/demo/demo4.ts @@ -10,10 +10,12 @@ const table = new Table({ columns: 4, }); -doc.add(table); - table.getCell(2, 2).add(new Paragraph("Hello")); +doc.addSection({ + children: [table], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo40.ts b/demo/demo40.ts index 6db6e7ba1e..f3bef349ec 100644 --- a/demo/demo40.ts +++ b/demo/demo40.ts @@ -3,30 +3,26 @@ import * as fs from "fs"; import { Document, HeadingLevel, LineNumberRestartFormat, Packer, Paragraph } from "../build"; -const doc = new Document( - {}, - { +const doc = new Document(); + +doc.addSection({ + properties: { lineNumberCountBy: 1, lineNumberRestart: LineNumberRestartFormat.CONTINUOUS, }, -); - -doc.add( - new Paragraph({ - text: "Hello", - heading: HeadingLevel.HEADING_1, - }), -); -doc.add( - new Paragraph( - "Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.", - ), -); -doc.add( - new Paragraph( - "Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.", - ), -); + children: [ + new Paragraph({ + text: "Hello", + heading: HeadingLevel.HEADING_1, + }), + new Paragraph( + "Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.", + ), + new Paragraph( + "Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.", + ), + ], +}); const packer = new Packer(); diff --git a/demo/demo41.ts b/demo/demo41.ts index 977d99abb5..2d3609fe5d 100644 --- a/demo/demo41.ts +++ b/demo/demo41.ts @@ -10,8 +10,6 @@ const table = new Table({ columns: 6, }); -doc.add(table); - let row = 0; table.getCell(row, 0).add(new Paragraph("0,0")); table.getCell(row, 1).add(new Paragraph("0,1")); @@ -47,6 +45,10 @@ table.getCell(row, 0).add(new Paragraph("4,0")); table.getCell(row, 5).add(new Paragraph("4,5")); table.getRow(row).mergeCells(0, 4); +doc.addSection({ + children: [table], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo43.ts b/demo/demo43.ts index 451d21a0fd..06806d5780 100644 --- a/demo/demo43.ts +++ b/demo/demo43.ts @@ -10,11 +10,12 @@ const table = new Table({ columns: 4, }); -doc.add(table); - table.getCell(2, 2).add(new Paragraph("Hello")); table.getColumn(3).mergeCells(1, 2); -// table.getCell(3, 2).add(new Paragraph("Hello")); + +doc.addSection({ + children: [table], +}); const packer = new Packer(); diff --git a/demo/demo44.ts b/demo/demo44.ts index a64062222b..83fbcf9efe 100644 --- a/demo/demo44.ts +++ b/demo/demo44.ts @@ -1,34 +1,40 @@ // Sections with multiple columns // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer } from "../build"; +import { Document, Packer, Paragraph } from "../build"; const doc = new Document(); doc.addSection({ - column: { - width: 708, - count: 2, + properties: { + column: { + width: 708, + count: 2, + }, }, + children: [ + new Paragraph("This text will be split into 2 columns on a page."), + new Paragraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + ), + ], }); -doc.createParagraph("This text will be split into 2 columns on a page."); -doc.createParagraph( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", -); - doc.addSection({ - column: { - width: 708, - count: 2, + properties: { + column: { + width: 708, + count: 3, + }, }, + children: [ + new Paragraph("This text will be split into 3 columns on a page."), + new Paragraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + ), + ], }); -doc.createParagraph("This text will be split into 3 columns on a page."); -doc.createParagraph( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", -); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo5.ts b/demo/demo5.ts index be340a3530..0102998570 100644 --- a/demo/demo5.ts +++ b/demo/demo5.ts @@ -2,19 +2,25 @@ // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; // import { Document, Packer, Paragraph } from "../build"; -import { Document, HorizontalPositionAlign, HorizontalPositionRelativeFrom, Packer, Paragraph, VerticalPositionAlign, VerticalPositionRelativeFrom} from "../build"; +import { + Document, + HorizontalPositionAlign, + HorizontalPositionRelativeFrom, + Media, + Packer, + Paragraph, + VerticalPositionAlign, + VerticalPositionRelativeFrom, +} from "../build"; const doc = new Document(); -const paragraph = new Paragraph("Hello World"); -doc.add(paragraph); - -doc.createImage(fs.readFileSync("./demo/images/image1.jpeg")); -doc.createImage(fs.readFileSync("./demo/images/dog.png").toString("base64")); -doc.createImage(fs.readFileSync("./demo/images/cat.jpg")); -doc.createImage(fs.readFileSync("./demo/images/parrots.bmp")); -doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); +const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png").toString("base64")); +const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg")); +const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp")); +const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image6 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { horizontalPosition: { offset: 1014400, @@ -25,7 +31,7 @@ doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { }, }); -doc.createImage(fs.readFileSync("./demo/images/cat.jpg"), 200, 200, { +const image7 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"), 200, 200, { floating: { horizontalPosition: { relative: HorizontalPositionRelativeFrom.PAGE, @@ -38,6 +44,19 @@ doc.createImage(fs.readFileSync("./demo/images/cat.jpg"), 200, 200, { }, }); +doc.addSection({ + children: [ + new Paragraph("Hello World"), + new Paragraph(image1), + new Paragraph(image2), + new Paragraph(image3), + new Paragraph(image4), + new Paragraph(image5), + new Paragraph(image6), + new Paragraph(image7), + ], +}); + const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo6.ts b/demo/demo6.ts index 2629c1b96d..47cca9c5f6 100644 --- a/demo/demo6.ts +++ b/demo/demo6.ts @@ -3,34 +3,38 @@ import * as fs from "fs"; import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build"; -const doc = new Document(undefined, { - top: 0, - right: 0, - bottom: 0, - left: 0, +const doc = new Document(); + +doc.addSection({ + margins: { + top: 0, + right: 0, + bottom: 0, + left: 0, + }, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo bar", + bold: true, + }), + new TextRun({ + text: "Github is the best", + bold: true, + }).tab(), + ], + }), + new Paragraph({ + text: "Hello World", + heading: HeadingLevel.HEADING_1, + }), + new Paragraph("Foo bar"), + new Paragraph("Github is the best"), + ], }); -const paragraph = new Paragraph("Hello World"); -const institutionText = new TextRun({ - text: "Foo bar", - bold: true, -}); -const dateText = new TextRun({ - text: "Github is the best", - bold: true, -}).tab(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.add(paragraph); - -doc.add(new Paragraph({ - text: "Hello World", - heading: HeadingLevel.HEADING_1, -})); -doc.add(new Paragraph("Foo bar")); -doc.add(new Paragraph("Github is the best")); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo7.ts b/demo/demo7.ts index db528cb157..2b171dea2f 100644 --- a/demo/demo7.ts +++ b/demo/demo7.ts @@ -3,14 +3,15 @@ import * as fs from "fs"; import { Document, Packer, PageOrientation, Paragraph } from "../build"; -const doc = new Document(undefined, { - orientation: PageOrientation.LANDSCAPE, +const doc = new Document(); + +doc.addSection({ + size: { + orientation: PageOrientation.LANDSCAPE, + }, + children: [new Paragraph("Hello World")], }); -const paragraph = new Paragraph("Hello World"); - -doc.add(paragraph); - const packer = new Packer(); packer.toBuffer(doc).then((buffer) => { diff --git a/demo/demo8.ts b/demo/demo8.ts index 1e3dfbaada..012a4a7bf5 100644 --- a/demo/demo8.ts +++ b/demo/demo8.ts @@ -1,14 +1,23 @@ // Add text to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Footer, Header, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.add(new Paragraph("Hello World")); - -doc.Header.add(new Paragraph("Header text")); -doc.Footer.add(new Paragraph("Footer text")); +doc.addSection({ + headers: { + default: new Header({ + children: [new Paragraph("Header text")], + }), + }, + footers: { + default: new Footer({ + children: [new Paragraph("Footer text")], + }), + }, + children: [new Paragraph("Hello World")], +}); const packer = new Packer(); diff --git a/demo/demo9.ts b/demo/demo9.ts index 8787d43b24..eb81879223 100644 --- a/demo/demo9.ts +++ b/demo/demo9.ts @@ -1,14 +1,34 @@ // Add images to header and footer // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { Document, Packer, Paragraph } from "../build"; +import { Document, Footer, Header, Media, Packer, Paragraph } from "../build"; const doc = new Document(); -doc.add(new Paragraph("Hello World")); +const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + children: [image1], + }), + ], + }), + }, + footers: { + default: new Footer({ + children: [ + new Paragraph({ + children: [image2], + }), + ], + }), + }, + children: [new Paragraph("Hello World")], +}); const packer = new Packer(); diff --git a/src/export/packer/next-compiler.spec.ts b/src/export/packer/next-compiler.spec.ts index dec853ba68..43bd4814f1 100644 --- a/src/export/packer/next-compiler.spec.ts +++ b/src/export/packer/next-compiler.spec.ts @@ -1,7 +1,7 @@ /* tslint:disable:typedef space-before-function-paren */ import { expect } from "chai"; -import { File } from "file"; +import { File, Header, Footer } from "file"; import { Compiler } from "./next-compiler"; @@ -21,28 +21,39 @@ describe("Compiler", () => { const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); expect(fileNames).is.an.instanceof(Array); - expect(fileNames).has.length(18); + expect(fileNames).has.length(14); expect(fileNames).to.include("word/document.xml"); expect(fileNames).to.include("word/styles.xml"); expect(fileNames).to.include("docProps/core.xml"); expect(fileNames).to.include("docProps/app.xml"); expect(fileNames).to.include("word/numbering.xml"); - expect(fileNames).to.include("word/header1.xml"); - expect(fileNames).to.include("word/_rels/header1.xml.rels"); - expect(fileNames).to.include("word/footer1.xml"); expect(fileNames).to.include("word/footnotes.xml"); expect(fileNames).to.include("word/settings.xml"); - expect(fileNames).to.include("word/_rels/footer1.xml.rels"); expect(fileNames).to.include("word/_rels/document.xml.rels"); expect(fileNames).to.include("[Content_Types].xml"); expect(fileNames).to.include("_rels/.rels"); }); it("should pack all additional headers and footers", async function() { - file.createFooter(); - file.createFooter(); - file.createHeader(); - file.createHeader(); + file.addSection({ + headers: { + default: new Header(), + }, + footers: { + default: new Footer(), + }, + children: [], + }); + + file.addSection({ + headers: { + default: new Header(), + }, + footers: { + default: new Footer(), + }, + children: [], + }); this.timeout(99999999); @@ -50,20 +61,16 @@ describe("Compiler", () => { const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); expect(fileNames).is.an.instanceof(Array); - expect(fileNames).has.length(26); + expect(fileNames).has.length(22); expect(fileNames).to.include("word/header1.xml"); expect(fileNames).to.include("word/_rels/header1.xml.rels"); expect(fileNames).to.include("word/header2.xml"); expect(fileNames).to.include("word/_rels/header2.xml.rels"); - expect(fileNames).to.include("word/header3.xml"); - expect(fileNames).to.include("word/_rels/header3.xml.rels"); expect(fileNames).to.include("word/footer1.xml"); expect(fileNames).to.include("word/_rels/footer1.xml.rels"); expect(fileNames).to.include("word/footer2.xml"); expect(fileNames).to.include("word/_rels/footer2.xml.rels"); - expect(fileNames).to.include("word/footer3.xml"); - expect(fileNames).to.include("word/_rels/footer3.xml.rels"); }); }); }); diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index 201f5eb38d..e2be5aca44 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -16,26 +16,24 @@ describe("Packer", () => { revision: "1", lastModifiedBy: "Dolan Miu", }); - const paragraph = new Paragraph("test text"); - const heading = new Paragraph({ - text: "Hello world", - heading: HeadingLevel.HEADING_1, - }); - file.add( - new Paragraph({ - text: "title", - heading: HeadingLevel.TITLE, - }), - ); - file.add(heading); - file.add( - new Paragraph({ - text: "heading 2", - heading: HeadingLevel.HEADING_2, - }), - ); - file.add(paragraph); + file.addSection({ + children: [ + new Paragraph({ + text: "title", + heading: HeadingLevel.TITLE, + }), + new Paragraph({ + text: "Hello world", + heading: HeadingLevel.HEADING_1, + }), + new Paragraph({ + text: "heading 2", + heading: HeadingLevel.HEADING_2, + }), + new Paragraph("test text"), + ], + }); packer = new Packer(); }); diff --git a/src/file/document/body/body.spec.ts b/src/file/document/body/body.spec.ts index 6eb8cdddad..a5bc222fb4 100644 --- a/src/file/document/body/body.spec.ts +++ b/src/file/document/body/body.spec.ts @@ -11,35 +11,7 @@ describe("Body", () => { body = new Body(); }); - describe("#constructor()", () => { - it("should create default section", () => { - const formatted = new Formatter().format(body)["w:body"][0]; - expect(formatted) - .to.have.property("w:sectPr") - .and.to.be.an.instanceof(Array); - expect(formatted["w:sectPr"]).to.have.length(4); - }); - }); - describe("#addSection", () => { - it("should add section with options", () => { - body.addSection({ - width: 10000, - height: 10000, - }); - - const formatted = new Formatter().format(body)["w:body"]; - expect(formatted).to.be.an.instanceof(Array); - const defaultSectionPr = formatted[0]["w:p"][0]["w:pPr"][0]["w:sectPr"]; - - // check that this is the default section and added first in paragraph - expect(defaultSectionPr[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } }); - - // check for new section (since it's the last one, it's direct child of body) - const newSection = formatted[1]["w:sectPr"]; - expect(newSection[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } } }); - }); - it("should add section with default parameters", () => { body.addSection({ width: 10000, @@ -51,33 +23,7 @@ describe("Body", () => { expect(tree).to.deep.equal({ "w:body": [ { - "w:p": [ - { - "w:pPr": [ - { - "w:sectPr": [ - { "w:pgSz": { _attr: { "w:w": 11906, "w:h": 16838, "w:orient": "portrait" } } }, - { - "w:pgMar": { - _attr: { - "w:top": 1440, - "w:right": 1440, - "w:bottom": 1440, - "w:left": 1440, - "w:header": 708, - "w:footer": 708, - "w:gutter": 0, - "w:mirrorMargins": false, - }, - }, - }, - { "w:cols": { _attr: { "w:space": 708, "w:num": 1 } } }, - { "w:docGrid": { _attr: { "w:linePitch": 360 } } }, - ], - }, - ], - }, - ], + "w:p": {}, }, { "w:sectPr": [ @@ -104,21 +50,4 @@ describe("Body", () => { }); }); }); - - describe("#getParagraphs", () => { - it("should get no paragraphs", () => { - const paragraphs = body.getParagraphs(); - - expect(paragraphs).to.be.an.instanceof(Array); - }); - }); - - describe("#DefaultSection", () => { - it("should get section", () => { - const section = body.DefaultSection; - - const tree = new Formatter().format(section); - expect(tree["w:sectPr"]).to.be.an.instanceof(Array); - }); - }); }); diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index 54d08ef9c5..e91b72d59a 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -3,15 +3,10 @@ import { Paragraph, ParagraphProperties, TableOfContents } from "../.."; import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; export class Body extends XmlComponent { - private readonly defaultSection: SectionProperties; - private readonly sections: SectionProperties[] = []; - constructor(sectionPropertiesOptions?: SectionPropertiesOptions) { + constructor() { super("w:body"); - - this.defaultSection = new SectionProperties(sectionPropertiesOptions); - this.sections.push(this.defaultSection); } /** @@ -20,21 +15,15 @@ export class Body extends XmlComponent { * The spec says: * - section element should be in the last paragraph of the section * - last section should be direct child of body - * @param section new section + * @param options new section options */ - public addSection(section: SectionPropertiesOptions | SectionProperties): void { + public addSection(options: SectionPropertiesOptions): void { const currentSection = this.sections.pop() as SectionProperties; this.root.push(this.createSectionParagraph(currentSection)); - if (section instanceof SectionProperties) { - this.sections.push(section); - } else { - const params = { - ...this.defaultSection.Options, - ...section, - }; - this.sections.push(new SectionProperties(params)); - } + + this.sections.push(new SectionProperties(options)); } + public prepForXml(): IXmlableObject | undefined { if (this.sections.length === 1) { this.root.push(this.sections.pop() as SectionProperties); @@ -47,18 +36,10 @@ export class Body extends XmlComponent { this.root.push(component); } - public get DefaultSection(): SectionProperties { - return this.defaultSection; - } - public getTablesOfContents(): TableOfContents[] { return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[]; } - public getParagraphs(): Paragraph[] { - return this.root.filter((child) => child instanceof Paragraph) as Paragraph[]; - } - private createSectionParagraph(section: SectionProperties): Paragraph { const paragraph = new Paragraph({}); const properties = new ParagraphProperties({}); diff --git a/src/file/document/body/section-properties/header-reference/header-reference.ts b/src/file/document/body/section-properties/header-reference/header-reference.ts index 8f89ea09b3..b1bc4ef4f4 100644 --- a/src/file/document/body/section-properties/header-reference/header-reference.ts +++ b/src/file/document/body/section-properties/header-reference/header-reference.ts @@ -1,13 +1,13 @@ import { XmlComponent } from "file/xml-components"; import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes"; -export interface IHeaderOptions { +export interface IHeaderReferenceOptions { readonly headerType?: HeaderReferenceType; readonly headerId?: number; } export class HeaderReference extends XmlComponent { - constructor(options: IHeaderOptions) { + constructor(options: IHeaderReferenceOptions) { super("w:headerReference"); this.root.push( new HeaderReferenceAttributes({ diff --git a/src/file/document/document.spec.ts b/src/file/document/document.spec.ts index 780dca0f27..dba489601e 100644 --- a/src/file/document/document.spec.ts +++ b/src/file/document/document.spec.ts @@ -1,4 +1,4 @@ -import { assert, expect } from "chai"; +import { expect } from "chai"; import { Formatter } from "export/formatter"; @@ -13,19 +13,34 @@ describe("Document", () => { describe("#constructor()", () => { it("should create valid JSON", () => { - const stringifiedJson = JSON.stringify(document); + const tree = new Formatter().format(document); - try { - JSON.parse(stringifiedJson); - } catch (e) { - assert.isTrue(false); - } - assert.isTrue(true); - }); - - it("should create default section", () => { - const body = new Formatter().format(document)["w:document"][1]["w:body"]; - expect(body[0]).to.have.property("w:sectPr"); + expect(tree).to.deep.equal({ + "w:document": [ + { + _attr: { + "xmlns:wpc": "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas", + "xmlns:mc": "http://schemas.openxmlformats.org/markup-compatibility/2006", + "xmlns:o": "urn:schemas-microsoft-com:office:office", + "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + "xmlns:m": "http://schemas.openxmlformats.org/officeDocument/2006/math", + "xmlns:v": "urn:schemas-microsoft-com:vml", + "xmlns:wp14": "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", + "xmlns:wp": "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", + "xmlns:w10": "urn:schemas-microsoft-com:office:word", + "xmlns:w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + "xmlns:w14": "http://schemas.microsoft.com/office/word/2010/wordml", + "xmlns:w15": "http://schemas.microsoft.com/office/word/2012/wordml", + "xmlns:wpg": "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", + "xmlns:wpi": "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", + "xmlns:wne": "http://schemas.microsoft.com/office/word/2006/wordml", + "xmlns:wps": "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", + "mc:Ignorable": "w14 w15 wp14", + }, + }, + { "w:body": {} }, + ], + }); }); }); }); diff --git a/src/file/document/document.ts b/src/file/document/document.ts index b716c1367b..d8c0c55131 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -4,13 +4,12 @@ import { Paragraph } from "../paragraph"; import { Table } from "../table"; import { TableOfContents } from "../table-of-contents"; import { Body } from "./body"; -import { SectionPropertiesOptions } from "./body/section-properties"; import { DocumentAttributes } from "./document-attributes"; export class Document extends XmlComponent { private readonly body: Body; - constructor(sectionPropertiesOptions?: SectionPropertiesOptions) { + constructor() { super("w:document"); this.root.push( new DocumentAttributes({ @@ -33,17 +32,12 @@ export class Document extends XmlComponent { Ignorable: "w14 w15 wp14", }), ); - this.body = new Body(sectionPropertiesOptions); + this.body = new Body(); this.root.push(this.body); } - public add(paragraph: Paragraph | Table): Document { - this.body.push(paragraph); - return this; - } - - public addTableOfContents(toc: TableOfContents): Document { - this.body.push(toc); + public add(item: Paragraph | Table | TableOfContents): Document { + this.body.push(item); return this; } @@ -54,8 +48,4 @@ export class Document extends XmlComponent { public getTablesOfContents(): TableOfContents[] { return this.body.getTablesOfContents(); } - - public getParagraphs(): Paragraph[] { - return this.body.getParagraphs(); - } } diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 00e0b7d02b..6c4532a889 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -4,24 +4,37 @@ import * as sinon from "sinon"; import { Formatter } from "export/formatter"; import { File } from "./file"; +import { Footer, Header } from "./header"; import { Paragraph } from "./paragraph"; import { Table } from "./table"; import { TableOfContents } from "./table-of-contents"; describe("File", () => { describe("#constructor", () => { + it("should create with correct headers and footers by default", () => { + const doc = new File(); + + doc.addSection({ + children: [], + }); + + const tree = new Formatter().format(doc.Document.Body); + + expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"]._attr["w:type"]).to.equal("default"); + expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"]._attr["w:type"]).to.equal("default"); + }); + it("should create with correct headers and footers", () => { const doc = new File(); - const header = doc.createHeader(); - const footer = doc.createFooter(); - doc.addSectionOld({ + doc.addSection({ headers: { - default: header, + default: new Header(), }, footers: { - default: footer, + default: new Footer(), }, + children: [], }); const tree = new Formatter().format(doc.Document.Body); @@ -32,40 +45,40 @@ describe("File", () => { it("should create with first headers and footers", () => { const doc = new File(); - const header = doc.createHeader(); - const footer = doc.createFooter(); - doc.addSectionOld({ + doc.addSection({ headers: { - first: header, + first: new Header(), }, footers: { - first: footer, + first: new Footer(), }, + children: [], }); const tree = new Formatter().format(doc.Document.Body); - expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"]._attr["w:type"]).to.equal("first"); - expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"]._attr["w:type"]).to.equal("first"); + console.log(JSON.stringify(tree, null, 2)); + + expect(tree["w:body"][1]["w:sectPr"][5]["w:headerReference"]._attr["w:type"]).to.equal("first"); + expect(tree["w:body"][1]["w:sectPr"][7]["w:footerReference"]._attr["w:type"]).to.equal("first"); }); it("should create with correct headers", () => { const doc = new File(); - const header = doc.createHeader(); - const footer = doc.createFooter(); - doc.addSectionOld({ + doc.addSection({ headers: { - default: header, - first: header, - even: header, + default: new Header(), + first: new Header(), + even: new Header(), }, footers: { - default: footer, - first: footer, - even: footer, + default: new Footer(), + first: new Footer(), + even: new Footer(), }, + children: [], }); const tree = new Formatter().format(doc.Document.Body); @@ -80,60 +93,56 @@ describe("File", () => { }); }); - describe("#add", () => { + describe("#addSection", () => { it("should call the underlying document's add a Paragraph", () => { const file = new File(); const spy = sinon.spy(file.Document, "add"); - file.add(new Paragraph({})); + file.addSection({ + children: [new Paragraph({})], + }); expect(spy.called).to.equal(true); }); it("should call the underlying document's add when adding a Table", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "add"); - wrapper.add( - new Table({ - rows: 1, - columns: 1, - }), - ); + const file = new File(); + const spy = sinon.spy(file.Document, "add"); + file.addSection({ + children: [ + new Table({ + rows: 1, + columns: 1, + }), + ], + }); expect(spy.called).to.equal(true); }); it("should call the underlying document's add when adding an Image (paragraph)", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "add"); + const file = new File(); + const spy = sinon.spy(file.Document, "add"); // tslint:disable-next-line:no-any - wrapper.add(new Paragraph("")); + file.addSection({ + children: [new Paragraph("")], + }); expect(spy.called).to.equal(true); }); }); - describe("#add", () => { - it("should call the underlying document's addTableOfContents", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Document, "addTableOfContents"); - wrapper.add(new TableOfContents()); + describe("#addSection", () => { + it("should call the underlying document's add", () => { + const file = new File(); + const spy = sinon.spy(file.Document, "add"); + file.addSection({ + children: [new TableOfContents()], + }); expect(spy.called).to.equal(true); }); }); - describe("#createImage", () => { - it("should call the underlying document's createImage", () => { - const wrapper = new File(); - const spy = sinon.spy(wrapper.Media, "addMedia"); - const wrapperSpy = sinon.spy(wrapper.Document, "add"); - wrapper.createImage(""); - - expect(spy.called).to.equal(true); - expect(wrapperSpy.called).to.equal(true); - }); - }); - describe("#createFootnote", () => { it("should call the underlying document's createFootnote", () => { const wrapper = new File(); diff --git a/src/file/file.ts b/src/file/file.ts index a78acd86e6..c0adf21e30 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -3,17 +3,16 @@ import { ContentTypes } from "./content-types/content-types"; import { CoreProperties, IPropertiesOptions } from "./core-properties"; import { Document } from "./document"; import { - FooterReference, FooterReferenceType, - HeaderReference, HeaderReferenceType, - IHeaderFooterGroup, + IPageSizeAttributes, SectionPropertiesOptions, } from "./document/body/section-properties"; -import { IDrawingOptions } from "./drawing"; +import { IPageMarginAttributes } from "./document/body/section-properties/page-margin/page-margin-attributes"; import { IFileProperties } from "./file-properties"; import { FooterWrapper, IDocumentFooter } from "./footer-wrapper"; import { FootNotes } from "./footnotes"; +import { Footer, Header } from "./header"; import { HeaderWrapper, IDocumentHeader } from "./header-wrapper"; import { Media } from "./media"; import { Numbering } from "./numbering"; @@ -28,7 +27,19 @@ import { Table } from "./table"; import { TableOfContents } from "./table-of-contents"; export interface ISectionOptions { - readonly properties: SectionPropertiesOptions; + readonly headers?: { + readonly default?: Header; + readonly first?: Header; + readonly even?: Header; + }; + readonly footers?: { + readonly default?: Footer; + readonly first?: Footer; + readonly even?: Footer; + }; + readonly size?: IPageSizeAttributes; + readonly margins?: IPageMarginAttributes; + readonly properties?: SectionPropertiesOptions; readonly children: Array; } @@ -57,7 +68,6 @@ export class File { revision: "1", lastModifiedBy: "Un-named", }, - sectionPropertiesOptions: SectionPropertiesOptions = {}, fileProperties: IFileProperties = {}, sections: ISectionOptions[] = [], ) { @@ -68,6 +78,8 @@ export class File { this.appProperties = new AppProperties(); this.footNotes = new FootNotes(); this.contentTypes = new ContentTypes(); + this.document = new Document(); + this.settings = new Settings(); this.media = fileProperties.template && fileProperties.template.media ? fileProperties.template.media : new Media(); @@ -96,65 +108,23 @@ export class File { for (const templateHeader of fileProperties.template.headers) { this.addHeaderToDocument(templateHeader.header, templateHeader.type); } - } else { - this.createHeader(); } if (fileProperties.template && fileProperties.template.footers) { for (const templateFooter of fileProperties.template.footers) { this.addFooterToDocument(templateFooter.footer, templateFooter.type); } - } else { - this.createFooter(); } - const newSectionPropertiesOptions = { - ...sectionPropertiesOptions, - headers: this.groupHeaders(this.headers, sectionPropertiesOptions.headers), - footers: this.groupFooters(this.footers, sectionPropertiesOptions.footers), - }; - - this.document = new Document(newSectionPropertiesOptions); - this.settings = new Settings(); - for (const section of sections) { - this.document.Body.addSection(section.properties); + this.document.Body.addSection(section.properties ? section.properties : {}); for (const child of section.children) { - this.add(child); + this.document.add(child); } } } - public add(item: Paragraph | Table | TableOfContents): File { - if (item instanceof Paragraph) { - this.document.add(item); - } - - if (item instanceof Table) { - this.document.add(item); - } - - if (item instanceof TableOfContents) { - this.document.addTableOfContents(item); - } - - return this; - } - - public createImage( - buffer: Buffer | string | Uint8Array | ArrayBuffer, - width?: number, - height?: number, - drawingOptions?: IDrawingOptions, - ): Paragraph { - const image = Media.addImage(this, buffer, width, height, drawingOptions); - const paragraph = new Paragraph(image); - this.document.add(paragraph); - - return paragraph; - } - public createHyperlink(link: string, text?: string): Hyperlink { const newText = text === undefined ? link : text; const hyperlink = new Hyperlink(newText, this.docRelationships.RelationshipCount); @@ -175,21 +145,36 @@ export class File { return hyperlink; } - public createBookmark(name: string, text?: string): Bookmark { - const newText = text === undefined ? name : text; - const bookmark = new Bookmark(name, newText, this.docRelationships.RelationshipCount); - return bookmark; + public createBookmark(name: string, text: string = name): Bookmark { + return new Bookmark(name, text, this.docRelationships.RelationshipCount); } - public addSectionOld(sectionPropertiesOptions: SectionPropertiesOptions): void { - this.document.Body.addSection(sectionPropertiesOptions); - } + public addSection({ + headers = { default: new Header() }, + footers = { default: new Header() }, + margins = {}, + size = {}, + properties, + children, + }: ISectionOptions): void { + this.document.Body.addSection({ + ...properties, + headers: { + default: headers.default ? this.createHeader(headers.default) : this.createHeader(new Header()), + first: headers.first ? this.createHeader(headers.first) : undefined, + even: headers.even ? this.createHeader(headers.even) : undefined, + }, + footers: { + default: footers.default ? this.createFooter(footers.default) : this.createFooter(new Footer()), + first: footers.first ? this.createFooter(footers.first) : undefined, + even: footers.even ? this.createFooter(footers.even) : undefined, + }, + ...margins, + ...size, + }); - public addSection(section: ISectionOptions): void { - this.document.Body.addSection(section.properties); - - for (const child of section.children) { - this.add(child); + for (const child of children) { + this.document.add(child); } } @@ -197,92 +182,34 @@ export class File { this.footNotes.createFootNote(paragraph); } - public createHeader(): HeaderWrapper { - const header = new HeaderWrapper(this.media, this.currentRelationshipId++); - this.addHeaderToDocument(header); - return header; - } - - public createFooter(): FooterWrapper { - const footer = new FooterWrapper(this.media, this.currentRelationshipId++); - this.addFooterToDocument(footer); - return footer; - } - - public createFirstPageHeader(): HeaderWrapper { - const headerWrapper = this.createHeader(); - - this.document.Body.DefaultSection.addChildElement( - new HeaderReference({ - headerType: HeaderReferenceType.FIRST, - headerId: headerWrapper.Header.ReferenceId, - }), - ); - - return headerWrapper; - } - - public createEvenPageHeader(): HeaderWrapper { - const headerWrapper = this.createHeader(); - - this.document.Body.DefaultSection.addChildElement( - new HeaderReference({ - headerType: HeaderReferenceType.EVEN, - headerId: headerWrapper.Header.ReferenceId, - }), - ); - - return headerWrapper; - } - - public createFirstPageFooter(): FooterWrapper { - const footerWrapper = this.createFooter(); - - this.document.Body.DefaultSection.addChildElement( - new FooterReference({ - footerType: FooterReferenceType.FIRST, - footerId: footerWrapper.Footer.ReferenceId, - }), - ); - - return footerWrapper; - } - - public createEvenPageFooter(): FooterWrapper { - const footerWrapper = this.createFooter(); - - this.document.Body.DefaultSection.addChildElement( - new FooterReference({ - footerType: FooterReferenceType.EVEN, - footerId: footerWrapper.Footer.ReferenceId, - }), - ); - - return footerWrapper; - } - - public getFooterByReferenceNumber(refId: number): FooterWrapper { - const entry = this.footers.map((item) => item.footer).find((h) => h.Footer.ReferenceId === refId); - if (entry) { - return entry; - } - throw new Error(`There is no footer with given reference id ${refId}`); - } - - public getHeaderByReferenceNumber(refId: number): HeaderWrapper { - const entry = this.headers.map((item) => item.header).find((h) => h.Header.ReferenceId === refId); - if (entry) { - return entry; - } - throw new Error(`There is no header with given reference id ${refId}`); - } - public verifyUpdateFields(): void { if (this.document.getTablesOfContents().length) { this.settings.addUpdateFields(); } } + private createHeader(header: Header): HeaderWrapper { + const wrapper = new HeaderWrapper(this.media, this.currentRelationshipId++); + + for (const child of header.options.children) { + wrapper.add(child); + } + + this.addHeaderToDocument(wrapper); + return wrapper; + } + + private createFooter(footer: Footer): FooterWrapper { + const wrapper = new FooterWrapper(this.media, this.currentRelationshipId++); + + for (const child of footer.options.children) { + wrapper.add(child); + } + + this.addFooterToDocument(wrapper); + return wrapper; + } + private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void { this.headers.push({ header, type }); this.docRelationships.createRelationship( @@ -342,66 +269,6 @@ export class File { ); } - private groupHeaders(headers: IDocumentHeader[], group: IHeaderFooterGroup = {}): IHeaderFooterGroup { - let newGroup = group; - - for (const header of headers) { - switch (header.type) { - case HeaderReferenceType.FIRST: - newGroup = { - ...newGroup, - first: header.header, - }; - break; - case HeaderReferenceType.EVEN: - newGroup = { - ...newGroup, - even: header.header, - }; - break; - case HeaderReferenceType.DEFAULT: - default: - newGroup = { - ...newGroup, - default: header.header, - }; - break; - } - } - - return newGroup; - } - - private groupFooters(footers: IDocumentFooter[], group: IHeaderFooterGroup = {}): IHeaderFooterGroup { - let newGroup = group; - - for (const footer of footers) { - switch (footer.type) { - case FooterReferenceType.FIRST: - newGroup = { - ...newGroup, - first: footer.footer, - }; - break; - case FooterReferenceType.EVEN: - newGroup = { - ...newGroup, - even: footer.footer, - }; - break; - case FooterReferenceType.DEFAULT: - default: - newGroup = { - ...newGroup, - default: footer.footer, - }; - break; - } - } - - return newGroup; - } - public get Document(): Document { return this.document; } @@ -434,18 +301,10 @@ export class File { return this.fileRelationships; } - public get Header(): HeaderWrapper { - return this.headers[0].header; - } - public get Headers(): HeaderWrapper[] { return this.headers.map((item) => item.header); } - public get Footer(): FooterWrapper { - return this.footers[0].footer; - } - public get Footers(): FooterWrapper[] { return this.footers.map((item) => item.footer); } diff --git a/src/file/footer-wrapper.spec.ts b/src/file/footer-wrapper.spec.ts index 882e47fadf..3f6fb01b82 100644 --- a/src/file/footer-wrapper.spec.ts +++ b/src/file/footer-wrapper.spec.ts @@ -39,17 +39,6 @@ describe("FooterWrapper", () => { }); }); - describe("#createImage", () => { - it("should call the underlying footer's createImage", () => { - const file = new FooterWrapper(new Media(), 1); - const spy = sinon.spy(Media, "addImage"); - file.createImage(""); - - expect(spy.called).to.equal(true); - spy.restore(); - }); - }); - describe("#addChildElement", () => { it("should call the underlying footer's addChildElement", () => { const file = new FooterWrapper(new Media(), 1); diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index ebd0610a23..01087e9861 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -1,7 +1,6 @@ import { XmlComponent } from "file/xml-components"; import { FooterReferenceType } from "./document"; -import { IDrawingOptions } from "./drawing"; import { Footer } from "./footer/footer"; import { Image, Media } from "./media"; import { Paragraph } from "./paragraph"; @@ -35,19 +34,6 @@ export class FooterWrapper { this.footer.addChildElement(childElement); } - public createImage( - buffer: Buffer | string | Uint8Array | ArrayBuffer, - width?: number, - height?: number, - drawingOptions?: IDrawingOptions, - ): Paragraph { - const image = Media.addImage(this, buffer, width, height, drawingOptions); - const paragraph = new Paragraph(image); - this.add(paragraph); - - return paragraph; - } - public get Footer(): Footer { return this.footer; } diff --git a/src/file/header-wrapper.spec.ts b/src/file/header-wrapper.spec.ts index 0d10b5818a..d07473f03a 100644 --- a/src/file/header-wrapper.spec.ts +++ b/src/file/header-wrapper.spec.ts @@ -41,17 +41,6 @@ describe("HeaderWrapper", () => { }); }); - describe("#createImage", () => { - it("should call the underlying header's createImage", () => { - const file = new HeaderWrapper(new Media(), 1); - const spy = sinon.spy(Media, "addImage"); - file.createImage(""); - - expect(spy.called).to.equal(true); - spy.restore(); - }); - }); - describe("#addChildElement", () => { it("should call the underlying header's addChildElement", () => { const file = new HeaderWrapper(new Media(), 1); diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index 58826ec03b..d698505e4a 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -1,7 +1,6 @@ import { XmlComponent } from "file/xml-components"; import { HeaderReferenceType } from "./document"; -import { IDrawingOptions } from "./drawing"; import { Header } from "./header/header"; import { Image, Media } from "./media"; import { Paragraph } from "./paragraph"; @@ -37,19 +36,6 @@ export class HeaderWrapper { this.header.addChildElement(childElement); } - public createImage( - buffer: Buffer | string | Uint8Array | ArrayBuffer, - width?: number, - height?: number, - drawingOptions?: IDrawingOptions, - ): Paragraph { - const image = Media.addImage(this, buffer, width, height, drawingOptions); - const paragraph = new Paragraph(image); - this.add(paragraph); - - return paragraph; - } - public get Header(): Header { return this.header; } diff --git a/src/file/header.ts b/src/file/header.ts new file mode 100644 index 0000000000..05e227d9f8 --- /dev/null +++ b/src/file/header.ts @@ -0,0 +1,14 @@ +import { Paragraph } from "./paragraph"; +import { Table } from "./table"; + +export interface IHeaderOptions { + readonly children: Array; +} + +export class Header { + constructor(public readonly options: IHeaderOptions = { children: [] }) {} +} + +export class Footer { + constructor(public readonly options: IHeaderOptions = { children: [] }) {} +} diff --git a/src/file/index.ts b/src/file/index.ts index 199679bee3..d14d4d9b1a 100644 --- a/src/file/index.ts +++ b/src/file/index.ts @@ -11,3 +11,4 @@ export * from "./table-of-contents"; export * from "./xml-components"; export * from "./header-wrapper"; export * from "./footer-wrapper"; +export * from "./header"; diff --git a/src/file/media/image.ts b/src/file/media/image.ts index b596f77d9d..8255fe7398 100644 --- a/src/file/media/image.ts +++ b/src/file/media/image.ts @@ -10,8 +10,4 @@ export class Image { public get Run(): PictureRun { return this.paragraph.Run; } - - public scale(factorX: number, factorY?: number): void { - this.paragraph.Run.scale(factorX, factorY); - } } diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index bd213cfa6c..d8c3d07b0f 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -2,6 +2,7 @@ import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-compon import { Alignment, AlignmentType, + IIndentAttributesProperties, Indent, ISpacingProperties, KeepLines, @@ -235,7 +236,7 @@ export class LevelBase extends XmlComponent { return this; } - public indent(attrs: object): Level { + public indent(attrs: IIndentAttributesProperties): Level { this.addParagraphProperty(new Indent(attrs)); return this; } diff --git a/src/file/paragraph/image.spec.ts b/src/file/paragraph/image.spec.ts index 6fb07e5294..715c1c93ab 100644 --- a/src/file/paragraph/image.spec.ts +++ b/src/file/paragraph/image.spec.ts @@ -1,12 +1,8 @@ // tslint:disable:object-literal-key-quotes -import { assert, expect } from "chai"; - -import { Formatter } from "export/formatter"; +import { assert } from "chai"; import { ImageParagraph } from "./image"; -import { EMPTY_OBJECT } from "file/xml-components"; - describe("Image", () => { let image: ImageParagraph; @@ -40,190 +36,4 @@ describe("Image", () => { assert.isTrue(true); }); }); - - describe("#scale()", () => { - it("should set the scale of the object properly", () => { - image.scale(2); - const tree = new Formatter().format(image); - expect(tree).to.deep.equal({ - "w:p": [ - { - "w:r": [ - { - "w:drawing": [ - { - "wp:inline": [ - { - _attr: { - distB: 0, - distL: 0, - distR: 0, - distT: 0, - }, - }, - { - "wp:extent": { - _attr: { - cx: 20, - cy: 20, - }, - }, - }, - { - "wp:effectExtent": { - _attr: { - b: 0, - l: 0, - r: 0, - t: 0, - }, - }, - }, - { - "wp:docPr": { - _attr: { - descr: "", - id: 0, - name: "", - }, - }, - }, - { - "wp:cNvGraphicFramePr": [ - { - "a:graphicFrameLocks": { - _attr: { - noChangeAspect: 1, - "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", - }, - }, - }, - ], - }, - { - "a:graphic": [ - { - _attr: { - "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main", - }, - }, - { - "a:graphicData": [ - { - _attr: { - uri: "http://schemas.openxmlformats.org/drawingml/2006/picture", - }, - }, - { - "pic:pic": [ - { - _attr: { - "xmlns:pic": - "http://schemas.openxmlformats.org/drawingml/2006/picture", - }, - }, - { - "pic:nvPicPr": [ - { - "pic:cNvPr": { - _attr: { - desc: "", - id: 0, - name: "", - }, - }, - }, - { - "pic:cNvPicPr": [ - { - "a:picLocks": { - _attr: { - noChangeArrowheads: 1, - noChangeAspect: 1, - }, - }, - }, - ], - }, - ], - }, - { - "pic:blipFill": [ - { - "a:blip": { - _attr: { - cstate: "none", - "r:embed": "rId{test.png}", - }, - }, - }, - { - "a:srcRect": EMPTY_OBJECT, - }, - { - "a:stretch": [ - { - "a:fillRect": EMPTY_OBJECT, - }, - ], - }, - ], - }, - { - "pic:spPr": [ - { - _attr: { - bwMode: "auto", - }, - }, - { - "a:xfrm": [ - { - "a:ext": { - _attr: { - cx: 10, - cy: 10, - }, - }, - }, - { - "a:off": { - _attr: { - x: 0, - y: 0, - }, - }, - }, - ], - }, - { - "a:prstGeom": [ - { - _attr: { - prst: "rect", - }, - }, - { - "a:avLst": EMPTY_OBJECT, - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }); - }); - }); }); diff --git a/src/file/paragraph/image.ts b/src/file/paragraph/image.ts index f4adffbdd4..4fa3d97b9f 100644 --- a/src/file/paragraph/image.ts +++ b/src/file/paragraph/image.ts @@ -12,10 +12,6 @@ export class ImageParagraph extends Paragraph { this.root.push(this.pictureRun); } - public scale(factorX: number, factorY?: number): void { - this.pictureRun.scale(factorX, factorY); - } - public get Run(): PictureRun { return this.pictureRun; } diff --git a/src/file/paragraph/run/picture-run.ts b/src/file/paragraph/run/picture-run.ts index 9f8cd7393c..c796beebfc 100644 --- a/src/file/paragraph/run/picture-run.ts +++ b/src/file/paragraph/run/picture-run.ts @@ -4,8 +4,6 @@ import { IMediaData } from "../../media/data"; import { Run } from "../run"; export class PictureRun extends Run { - private readonly drawing: Drawing; - constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { super({}); @@ -13,12 +11,8 @@ export class PictureRun extends Run { throw new Error("imageData cannot be undefined"); } - this.drawing = new Drawing(imageData, drawingOptions); + const drawing = new Drawing(imageData, drawingOptions); - this.root.push(this.drawing); - } - - public scale(factorX: number = 1, factorY: number = factorX): void { - this.drawing.scale(factorX, factorY); + this.root.push(drawing); } } From 9938a8bcc07b644070f06948155825d8628a5e38 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Wed, 31 Jul 2019 08:48:25 +0100 Subject: [PATCH 15/38] Fix linting --- src/export/packer/next-compiler.spec.ts | 2 +- src/file/file.spec.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/export/packer/next-compiler.spec.ts b/src/export/packer/next-compiler.spec.ts index 43bd4814f1..ac271c02d9 100644 --- a/src/export/packer/next-compiler.spec.ts +++ b/src/export/packer/next-compiler.spec.ts @@ -1,7 +1,7 @@ /* tslint:disable:typedef space-before-function-paren */ import { expect } from "chai"; -import { File, Header, Footer } from "file"; +import { File, Footer, Header } from "file"; import { Compiler } from "./next-compiler"; diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index 6c4532a889..dae4af33fb 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -58,8 +58,6 @@ describe("File", () => { const tree = new Formatter().format(doc.Document.Body); - console.log(JSON.stringify(tree, null, 2)); - expect(tree["w:body"][1]["w:sectPr"][5]["w:headerReference"]._attr["w:type"]).to.equal("first"); expect(tree["w:body"][1]["w:sectPr"][7]["w:footerReference"]._attr["w:type"]).to.equal("first"); }); From c2c05b0140dc073afb08f6a157e3ac34f3b8d07a Mon Sep 17 00:00:00 2001 From: Dolan Date: Sat, 3 Aug 2019 13:42:24 +0100 Subject: [PATCH 16/38] Adding some documentation --- docs/README.md | 42 +++++-- docs/_sidebar.md | 1 + docs/usage/document.md | 4 +- docs/usage/headers-and-footers.md | 2 + docs/usage/images.md | 10 +- docs/usage/paragraph.md | 183 ++++++++++++++++++++++++++---- docs/usage/sections.md | 2 + docs/usage/text.md | 11 +- src/file/paragraph/paragraph.ts | 7 -- 9 files changed, 212 insertions(+), 50 deletions(-) create mode 100644 docs/usage/sections.md diff --git a/docs/README.md b/docs/README.md index caee21e8b8..dca4001a48 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,5 @@

- clippy the assistant + clippy the assistant

@@ -22,29 +22,47 @@ Then you can `require` or `import` as usual: let docx = require("docx"); ``` -```js +```ts import * as docx from "docx"; +// or +import { ... } from "docx"; ``` ## Basic Usage ```js -var fs = require("fs"); -var docx = require("docx"); +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "docx"; // Create document -var doc = new docx.Document(); +const doc = new Document(); -// Add some content in the document -var paragraph = new docx.Paragraph("Some cool text here."); -// Add more text into the paragraph if you wish -paragraph.addRun(new docx.TextRun("Lorem Ipsum Foo Bar")); -doc.add(paragraph); +// Documents contain sections, you can have multiple sections per document, go here to learn more about sections +// This simple example will only contain one section +doc.addSection({ + properties: {}, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + new TextRun({ + text: "Github is the best", + bold: true, + }).tab(), + ], + }), + ], +}); // Used to export the file into a .docx file -var packer = new docx.Packer(); +const packer = new Packer(); + packer.toBuffer(doc).then((buffer) => { - fs.writeFileSync("My First Document.docx", buffer); + fs.writeFileSync("My Document.docx", buffer); }); // Done! A file called 'My First Document.docx' will be in your file system. diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 558029dbf6..9e329b6448 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -9,6 +9,7 @@ * Usage * [Document](usage/document.md) + * [Sections](usage/sections.md) * [Paragraph](usage/paragraph.md) * [Text](usage/text.md) * [Image](usage/images.md) diff --git a/docs/usage/document.md b/docs/usage/document.md index 175e4ecad1..56f4826355 100644 --- a/docs/usage/document.md +++ b/docs/usage/document.md @@ -33,7 +33,7 @@ const doc = new docx.Document({ You can mix and match whatever properties you want, or provide no properties. -### units for positioning +### Units for positioning Various parts of the API require positioning arguments. The units are "20ths of a point" from the [OOXML](http://officeopenxml.com/index.php) specification. -See [Lars Corneliussen's blog post](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/) for more information and how to convert units. \ No newline at end of file +See [Lars Corneliussen's blog post](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/) for more information and how to convert units. diff --git a/docs/usage/headers-and-footers.md b/docs/usage/headers-and-footers.md index 22951abdee..541214da3f 100644 --- a/docs/usage/headers-and-footers.md +++ b/docs/usage/headers-and-footers.md @@ -1,5 +1,7 @@ # Headers and Footers +!> Headers and Footers requires an understanding of [Sections](usage/sections.md). + ## Example Creating Headers and footers is simple. Access the `Header` and `Footer` by doing so like this: diff --git a/docs/usage/images.md b/docs/usage/images.md index 8f4c34643c..b108347df4 100644 --- a/docs/usage/images.md +++ b/docs/usage/images.md @@ -3,7 +3,7 @@ To create a `floating` image on top of text: ```ts -doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { horizontalPosition: { offset: 1014400, @@ -18,7 +18,7 @@ doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { By default with no arguments, its an `inline` image: ```ts -doc.createImage(fs.readFileSync("./demo/images/parrots.bmp")); +Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp")); ``` You can also create images manually and add them later: @@ -35,7 +35,7 @@ Adding images can be done in two ways: 1. Call the `createImage` method to add the image directly into the `document`: ```js - doc.createImage([IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]); + Media.addImage(doc, [IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]); ``` 2. Create an `image` first, then add it into the `document`: @@ -141,7 +141,7 @@ wrap: { For example: ```ts -doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { horizontalPosition: { offset: 2014400, @@ -184,7 +184,7 @@ margins: { For example: ```ts -doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { floating: { horizontalPosition: { offset: 2014400, diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index 28f815e4b2..b5af10778c 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -2,28 +2,170 @@ > Everything (text, images, graphs etc) in OpenXML is organised in paragraphs. -## Example +!> Paragraphs requires an understanding of [Sections](usage/sections.md). -You can add more text to the paragraph by doing this: +You can create `Paragraphs` in the following ways: + +### Shorthand ```js -var paragraph = new docx.Paragraph(), +import { Paragraph } from "docx"; + +var paragraph = new Paragraph("Short hand Hello World"); ``` +### Children Method + +This method is useful for adding different `text` with different styles or adding `images` inline. + ```js -var text = new docx.TextRun("Lorem Ipsum Foo Bar"); -var paragraph = new docx.Paragraph(); -paragraph.addRun(text); +var paragraph = new Paragraph({ + children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")], +}); ``` +### Explicit + ```js -var paragraph = new docx.Paragraph("Short hand notation for adding text."); +var paragraph = new Paragraph({ + text: "Short hand notation for adding text.", +}); ``` -After you create the paragraph, you must add the paragraph into the `document`: +After you create the paragraph, you must add the paragraph into the `document's section`. Learn more about `sections` here: ```js -doc.add(paragraph); +doc.addSection({ + children: [paragraph], +}); +``` + +Or the preferred convension, define the paragraph inside the section and remove the usage of variables: + +```js +doc.addSection({ + children: [ + new Paragraph({ + children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")], + }), + ], +}); +``` + +## Options + +This is the list of options for a paragraph. A detailed explanation is below: + +| Property | Type | Mandatory? | Possible Values | +| ------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- | +| [text](#text) | `string` | Optional | | +| [heading](#heading) | `HeadingLevel` | Optional | `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`, `TITLE` | +| [border](#border) | `IBorderOptions` | Optional | `top`, `bottom`, `left`, `right`. Each of these are of type IBorderPropertyOptions. Click here for Example | +| [spacing](#spacing) | `ISpacingProperties` | Optional | See below for ISpacingProperties | +| outlineLevel | `number` | Optional | | +| alignment | `AlignmentType` | Optional | | +| heading | `HeadingLevel` | Optional | | +| bidirectional | `boolean` | Optional | | +| thematicBreak | `boolean` | Optional | | +| pageBreakBefore | `boolean` | Optional | | +| contextualSpacing | `boolean` | Optional | | +| indent | `IIndentAttributesProperties` | Optional | | +| keepLines | `boolean` | Optional | | +| keepNext | `boolean` | Optional | | +| children | `(TextRun or PictureRun or Hyperlink)[]` | Optional | | +| style | `string` | Optional | | +| tabStop | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | | +| bullet | `{ level: number }` | Optional | | +| numbering | `{ num: Num; level: number; custom?: boolean }` | Optional | | + +## Text + +This is the text in a paragraph. You can also add text by using the `Paragraph` shorthand (mentioned above) or adding `children`. + +**Example:** + +```ts +const paragraph = new Paragraph({ + text: "Hello World", +}); +``` + +## Heading + +**Example:** + +Setting a Heading 1 paragraph with "Hello World" as it's text: + +```ts +const paragraph = new Paragraph({ + text: "Hello World", + heading: HeadingLevel.HEADING_1, +}); +``` + +## Border + +Add borders to a `Paragraph`. Good for making the `Paragraph` stand out + +#### IBorderPropertyOptions + +`top`, `bottom`, `left`, `right` of the border + +| Property | Type | Notes | +| -------- | -------- | -------- | +| color | `string` | Required | +| space | `number` | Required | +| value | `string` | Required | +| size | `number` | Required | + +**Example:** + +Add border on the top and the bottom of the paragraph + +```ts +const paragraph = new Paragraph({ + text: "I have borders on my top and bottom sides!", + border: { + top: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + bottom: { + color: "auto", + space: 1, + value: "single", + size: 6, + }, + }, +}); +``` + +## Spacing + +Adding spacing between paragraphs + +### ISpacingProperties + +| Property | Type | Notes | +| -------- | -------- | -------- | +| after | `number` | Optional | +| before | `number` | Optional | +| line | `number` | Optional | +| lineRule | `string` | Optional | + +**Example:** + +Add spacing before the paragraph: + +```ts +const paragraph = new Paragraph({ + text: "line with contextual spacing", + spacing: { + before: 200, + }, +}); ``` ## Styles @@ -32,20 +174,15 @@ To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/ ![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu") -### Heading1 - Heading5 +### Headings and titles ```js -paragraph.heading1(); -paragraph.heading2(); -paragraph.heading3(); -paragraph.heading4(); -paragraph.heading5(); -``` +import { HeadingLevel, Paragraph } from "docx"; -### Title - -```js -paragraph.title(); +const paragraph = new Paragraph({ + text: "Hello World", + heading: HeadingLevel.TITLE, +}); ``` ## Text Alignment @@ -71,7 +208,11 @@ paragraph.justified(); ### Example ```js -paragraph.heading1().center(); +const paragraph = new Paragraph({ + text: "Hello World", + heading: HeadingLevel.HEADING_1, + alignment: AlignmentType.CENTER, +}); ``` The above will create a `heading 1` which is `centered`. diff --git a/docs/usage/sections.md b/docs/usage/sections.md new file mode 100644 index 0000000000..f0046692d6 --- /dev/null +++ b/docs/usage/sections.md @@ -0,0 +1,2 @@ +# Sections + diff --git a/docs/usage/text.md b/docs/usage/text.md index faa2bdf2d5..ed02dad742 100644 --- a/docs/usage/text.md +++ b/docs/usage/text.md @@ -1,10 +1,15 @@ # Text -Paragraphs need `text run` objects. To create text: +You can add multiple `text runs` in `Paragraphs`. This is the most verbose way of writing a `Paragraph` but it is also the most flexible: ```js -var text = new docx.TextRun("My awesome text here for my university dissertation"); -paragraph.addRun(text); +import { Paragraph, Text } from "docx"; + +const paragraph = new Paragraph({ + children: [ + new TextRun("My awesome text here for my university dissertation"), + ], +}); ``` Text objects have methods inside which changes the way the text is displayed. diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 74aff05bf5..3f39ba68bc 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -27,7 +27,6 @@ export interface IParagraphOptions { readonly text?: string; readonly border?: IBorderOptions; readonly spacing?: ISpacingProperties; - readonly runs?: Run[]; readonly outlineLevel?: number; readonly alignment?: AlignmentType; readonly heading?: HeadingLevel; @@ -166,12 +165,6 @@ export class Paragraph extends XmlComponent { this.properties.push(new NumberProperties(options.numbering.num.id, options.numbering.level)); } - if (options.runs) { - for (const run of options.runs) { - this.root.push(run); - } - } - if (options.children) { for (const child of options.children) { this.root.push(child); From cb699e17b399bf93ca12138342c8dfe08a96681f Mon Sep 17 00:00:00 2001 From: Dolan Date: Mon, 5 Aug 2019 23:24:43 +0100 Subject: [PATCH 17/38] Paragraph documentation --- docs/usage/paragraph.md | 48 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index b5af10778c..efa5462594 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -56,27 +56,27 @@ doc.addSection({ This is the list of options for a paragraph. A detailed explanation is below: -| Property | Type | Mandatory? | Possible Values | -| ------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- | -| [text](#text) | `string` | Optional | | -| [heading](#heading) | `HeadingLevel` | Optional | `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`, `TITLE` | -| [border](#border) | `IBorderOptions` | Optional | `top`, `bottom`, `left`, `right`. Each of these are of type IBorderPropertyOptions. Click here for Example | -| [spacing](#spacing) | `ISpacingProperties` | Optional | See below for ISpacingProperties | -| outlineLevel | `number` | Optional | | -| alignment | `AlignmentType` | Optional | | -| heading | `HeadingLevel` | Optional | | -| bidirectional | `boolean` | Optional | | -| thematicBreak | `boolean` | Optional | | -| pageBreakBefore | `boolean` | Optional | | -| contextualSpacing | `boolean` | Optional | | -| indent | `IIndentAttributesProperties` | Optional | | -| keepLines | `boolean` | Optional | | -| keepNext | `boolean` | Optional | | -| children | `(TextRun or PictureRun or Hyperlink)[]` | Optional | | -| style | `string` | Optional | | -| tabStop | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | | -| bullet | `{ level: number }` | Optional | | -| numbering | `{ num: Num; level: number; custom?: boolean }` | Optional | | +| Property | Type | Mandatory? | Possible Values | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- | +| [text](#text) | `string` | Optional | | +| [heading](#heading) | `HeadingLevel` | Optional | `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`, `TITLE` | +| [border](#border) | `IBorderOptions` | Optional | `top`, `bottom`, `left`, `right`. Each of these are of type IBorderPropertyOptions. Click here for Example | +| [spacing](#spacing) | `ISpacingProperties` | Optional | See below for ISpacingProperties | +| [outlineLevel](#outline-level) | `number` | Optional | | +| alignment | `AlignmentType` | Optional | | +| heading | `HeadingLevel` | Optional | | +| bidirectional | `boolean` | Optional | | +| thematicBreak | `boolean` | Optional | | +| pageBreakBefore | `boolean` | Optional | | +| contextualSpacing | `boolean` | Optional | | +| indent | `IIndentAttributesProperties` | Optional | | +| keepLines | `boolean` | Optional | | +| keepNext | `boolean` | Optional | | +| children | `(TextRun or PictureRun or Hyperlink)[]` | Optional | | +| style | `string` | Optional | | +| tabStop | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | | +| bullet | `{ level: number }` | Optional | | +| numbering | `{ num: Num; level: number; custom?: boolean }` | Optional | | ## Text @@ -161,13 +161,17 @@ Add spacing before the paragraph: ```ts const paragraph = new Paragraph({ - text: "line with contextual spacing", + text: "Paragraph with spacing before", spacing: { before: 200, }, }); ``` +## Outline Level + +**Example:** + ## Styles To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/docx/wiki/Styling From 4b19131dbd9d46884c971f48c95b92d3d5aa3aaa Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 00:52:50 +0100 Subject: [PATCH 18/38] Add description about sections --- docs/usage/sections.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/usage/sections.md b/docs/usage/sections.md index f0046692d6..44d409f5f6 100644 --- a/docs/usage/sections.md +++ b/docs/usage/sections.md @@ -1,2 +1,7 @@ # Sections +> Every document is made up of one or more sections + +A section is a grouping of paragraphs that have a specific set of properties used to define the pages on which the text will appear. Properties include page size, page numbers, page orientation, headers, borders and margins. + +For example, you could have one section which is portrait with a header and footer, and another section in landscape with no footer, and a header showing the current page number. diff --git a/package.json b/package.json index 965a8b51e9..77750352d4 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@types/webpack": "^4.4.24", "awesome-typescript-loader": "^3.4.1", "chai": "^3.5.0", - "docsify": "^4.9.1", + "docsify-cli": "^4.3.0", "glob": "^7.1.2", "istanbul-instrumenter-loader": "^3.0.1", "jszip": "^3.1.5", From fa710d1ba6d7bc7c4a0a5de2147ad06db63cf890 Mon Sep 17 00:00:00 2001 From: Forman Date: Mon, 5 Aug 2019 13:42:45 +0300 Subject: [PATCH 19/38] Highlighting --- demo/demo45.ts | 27 ++++++++++ demo/demo46.ts | 27 ++++++++++ src/file/numbering/level.ts | 9 ++++ src/file/numbering/numbering.spec.ts | 18 +++++++ src/file/paragraph/run/formatting.ts | 52 ++++++++++++++++++- src/file/paragraph/run/run.spec.ts | 48 +++++++++++++++++ src/file/paragraph/run/run.ts | 16 ++++++ src/file/styles/style/character-style.spec.ts | 46 ++++++++++++++++ src/file/styles/style/character-style.ts | 8 +++ src/file/styles/style/paragraph-style.spec.ts | 26 ++++++++++ src/file/styles/style/paragraph-style.ts | 8 +++ src/file/xml-components/attributes.ts | 2 + 12 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 demo/demo45.ts create mode 100644 demo/demo46.ts diff --git a/demo/demo45.ts b/demo/demo45.ts new file mode 100644 index 0000000000..7cef926537 --- /dev/null +++ b/demo/demo45.ts @@ -0,0 +1,27 @@ +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "../build"; + +const doc = new Document(); + +const header = doc.Header.createTable(1, 3) + // @ts-ignore + header.properties.root[1] = [] + + header.getCell(0, 2).addParagraph( + new Paragraph() + .addRun( + new TextRun('W.P. 660') + .color('red') + .bold() + .size(12 * 2) + .font('Garamond') + .highlight('yellow') + ) + .right() + ) + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo46.ts b/demo/demo46.ts new file mode 100644 index 0000000000..bc38e8dc19 --- /dev/null +++ b/demo/demo46.ts @@ -0,0 +1,27 @@ +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "../build"; + +const doc = new Document(); + +const header = doc.Header.createTable(1, 3) + // @ts-ignore + header.properties.root[1] = [] + + header.getCell(0, 2).addParagraph( + new Paragraph() + .addRun( + new TextRun('W.P. 660') + .color('red') + .bold() + .size(12 * 2) + .font('Garamond') + .shadow('pct10','00FFFF','FF0000') + ) + .right() + ) + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index 716f313104..d53bd84522 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -198,6 +198,15 @@ export class LevelBase extends XmlComponent { return this; } + public highlight(color: string): Level { + this.addRunProperty(new formatting.Highlight(color)); + return this; + } + + public shadow(value: string, fill: string, color: string): Level { + this.addRunProperty(new formatting.Shadow(value, fill, color)); + return this; + } // --------------------- Paragraph formatting ------------------------ // public center(): Level { diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 3ba39b15f6..2240fb4108 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -325,6 +325,24 @@ describe("AbstractNumbering", () => { }); }); + it("#highlight", () => { + const abstractNumbering = new AbstractNumbering(1); + const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").highlight("005599"); + const tree = new Formatter().format(level); + expect(tree["w:lvl"]).to.include({ + "w:rPr": [{ "w:highlight ": { _attr: { "w:val": "005599" } } }], + }); + }); + + it("#shadow", () => { + const abstractNumbering = new AbstractNumbering(1); + const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").shadow("pct10", "00FFFF", "FF0000"); + const tree = new Formatter().format(level); + expect(tree["w:lvl"]).to.include({ + "w:rPr": [{ "w:shd ": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + }); + }); + describe("#underline", () => { it("should set underline to 'single' if no arguments are given", () => { const abstractNumbering = new AbstractNumbering(1); diff --git a/src/file/paragraph/run/formatting.ts b/src/file/paragraph/run/formatting.ts index 30d437e268..87273b9459 100644 --- a/src/file/paragraph/run/formatting.ts +++ b/src/file/paragraph/run/formatting.ts @@ -113,7 +113,7 @@ export class Imprint extends XmlComponent { } } -export class Shadow extends XmlComponent { +/* export class Shadow extends XmlComponent { constructor() { super("w:shadow"); this.root.push( @@ -122,7 +122,7 @@ export class Shadow extends XmlComponent { }), ); } -} +} */ export class SmallCaps extends XmlComponent { constructor() { @@ -178,3 +178,51 @@ export class RightToLeft extends XmlComponent { ); } } + +export class Highlight extends XmlComponent { + constructor(color: string) { + super("w:highlight"); + this.root.push( + new Attributes({ + val: color, + }), + ); + } +} + +export class HighlightComplexScript extends XmlComponent { + constructor(color: string) { + super("w:highlightCs"); + this.root.push( + new Attributes({ + val: color, + }), + ); + } +} + +export class Shadow extends XmlComponent { + constructor(value: string, fill: string, color: string) { + super("w:shd"); + this.root.push( + new Attributes({ + val: value, + fill: fill, + color: color, + }), + ); + } +} + +export class ShadowComplexScript extends XmlComponent { + constructor(value: string, fill: string, color: string) { + super("w:shdCs"); + this.root.push( + new Attributes({ + val: value, + fill: fill, + color: color, + }), + ); + } +} diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index ae6526a229..eb4b523976 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -115,6 +115,54 @@ describe("Run", () => { }); }); + describe("#highlight()", () => { + it("it should add highlight to the properties", () => { + run.highlight("005599"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [ + { + "w:rPr": [ + { "w:highlight ": { _attr: { "w:val": "005599" } } }, + { + "w:highlightCs": { + _attr: { + "w:val": "005599", + }, + }, + }, + ], + }, + ], + }); + }); + }); + + describe("#shadow()", () => { + it("it should add shadow to the properties", () => { + run.shadow("pct10", "00FFFF", "FF0000"); + const tree = new Formatter().format(run); + expect(tree).to.deep.equal({ + "w:r": [ + { + "w:rPr": [ + { "w:shd ": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { + "w:shdCs": { + _attr: { + "w:val": "pct10", + "w:fill": "00FFFF", + "w:color": "FF0000", + }, + }, + }, + ], + }, + ], + }); + }); + }); + describe("#break()", () => { it("it should add break to the run", () => { run.break(); diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index 32777cd31d..1ef16d0f45 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -7,9 +7,13 @@ import { BoldComplexScript, Color, DoubleStrike, + Highlight, + HighlightComplexScript, Italics, ItalicsComplexScript, RightToLeft, + Shadow, + ShadowComplexScript, Size, SizeComplexScript, Strike, @@ -131,4 +135,16 @@ export class Run extends XmlComponent { this.properties.push(new Style(styleId)); return this; } + + public highlight(color: string): Run { + this.properties.push(new Highlight(color)); + this.properties.push(new HighlightComplexScript(color)); + return this; + } + + public shadow(value: string, fill: string, color: string): Run { + this.properties.push(new Shadow(value, fill, color)); + this.properties.push(new ShadowComplexScript(value, fill, color)); + return this; + } } diff --git a/src/file/styles/style/character-style.spec.ts b/src/file/styles/style/character-style.spec.ts index 793ead4ff2..c7594f3829 100644 --- a/src/file/styles/style/character-style.spec.ts +++ b/src/file/styles/style/character-style.spec.ts @@ -307,5 +307,51 @@ describe("CharacterStyle", () => { ], }); }); + + it("#highlight", () => { + const style = new CharacterStyle("myStyleId").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", + }, + }, + }, + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); + }); + + it("#shadow", () => { + const style = new CharacterStyle("myStyleId").shadow("pct10", "00FFFF", "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" } } }], + }, + { + "w:uiPriority": { + _attr: { + "w:val": "99", + }, + }, + }, + { + "w:unhideWhenUsed": EMPTY_OBJECT, + }, + ], + }); + }); }); }); diff --git a/src/file/styles/style/character-style.ts b/src/file/styles/style/character-style.ts index c7f677b331..4ac49ba950 100644 --- a/src/file/styles/style/character-style.ts +++ b/src/file/styles/style/character-style.ts @@ -58,4 +58,12 @@ export class CharacterStyle extends Style { this.root.push(new SemiHidden()); return this; } + + public highlight(color: string): CharacterStyle { + return this.addRunProperty(new formatting.Highlight(color)); + } + + public shadow(value: string, fill: string, color: string): CharacterStyle { + return this.addRunProperty(new formatting.Shadow(value, fill, color)); + } } diff --git a/src/file/styles/style/paragraph-style.spec.ts b/src/file/styles/style/paragraph-style.spec.ts index 41ef0fddab..ac39460861 100644 --- a/src/file/styles/style/paragraph-style.spec.ts +++ b/src/file/styles/style/paragraph-style.spec.ts @@ -375,6 +375,32 @@ describe("ParagraphStyle", () => { }); }); + it("#highlight", () => { + const style = new ParagraphStyle("myStyleId").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" } } }], + }, + ], + }); + }); + + it("#shadow", () => { + const style = new ParagraphStyle("myStyleId").shadow("pct10", "00FFFF", "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" } } }], + }, + ], + }); + }); + describe("#underline", () => { it("should set underline to 'single' if no arguments are given", () => { const style = new ParagraphStyle("myStyleId").underline(); diff --git a/src/file/styles/style/paragraph-style.ts b/src/file/styles/style/paragraph-style.ts index d231c58f33..0b1438f3d0 100644 --- a/src/file/styles/style/paragraph-style.ts +++ b/src/file/styles/style/paragraph-style.ts @@ -114,6 +114,14 @@ export class ParagraphStyle extends Style { return this.addRunProperty(new formatting.CharacterSpacing(value)); } + public highlight(color: string): ParagraphStyle { + return this.addRunProperty(new formatting.Highlight(color)); + } + + public shadow(value: string, fill: string, color: string): ParagraphStyle { + return this.addRunProperty(new formatting.Shadow(value, fill, color)); + } + // --------------------- Paragraph formatting ------------------------ // public center(): ParagraphStyle { diff --git a/src/file/xml-components/attributes.ts b/src/file/xml-components/attributes.ts index 02ed46b434..703ee1a679 100644 --- a/src/file/xml-components/attributes.ts +++ b/src/file/xml-components/attributes.ts @@ -3,6 +3,7 @@ import { XmlAttributeComponent } from "./default-attributes"; export interface IAttributesProperties { readonly val?: string | number | boolean; readonly color?: string; + readonly fill?: string; readonly space?: string; readonly sz?: string; readonly type?: string; @@ -26,6 +27,7 @@ export class Attributes extends XmlAttributeComponent { protected readonly xmlKeys = { val: "w:val", color: "w:color", + fill: "w:fill", space: "w:space", sz: "w:sz", type: "w:type", From ebc7dca9496109c8ef8bb9e4d7b8bcaf60011363 Mon Sep 17 00:00:00 2001 From: Forman Date: Tue, 6 Aug 2019 13:39:05 +0300 Subject: [PATCH 20/38] Fix tests --- src/file/numbering/numbering.spec.ts | 4 ++-- src/file/paragraph/run/run.spec.ts | 4 ++-- src/file/styles/style/paragraph-style.spec.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 2240fb4108..f483e723f3 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -330,7 +330,7 @@ describe("AbstractNumbering", () => { const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").highlight("005599"); const tree = new Formatter().format(level); expect(tree["w:lvl"]).to.include({ - "w:rPr": [{ "w:highlight ": { _attr: { "w:val": "005599" } } }], + "w:rPr": [{ "w:highlight": { _attr: { "w:val": "005599" } } }], }); }); @@ -339,7 +339,7 @@ describe("AbstractNumbering", () => { const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").shadow("pct10", "00FFFF", "FF0000"); const tree = new Formatter().format(level); expect(tree["w:lvl"]).to.include({ - "w:rPr": [{ "w:shd ": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + "w:rPr": [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], }); }); diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index eb4b523976..0a36d1dbe5 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -123,7 +123,7 @@ describe("Run", () => { "w:r": [ { "w:rPr": [ - { "w:highlight ": { _attr: { "w:val": "005599" } } }, + { "w:highlight": { _attr: { "w:val": "005599" } } }, { "w:highlightCs": { _attr: { @@ -146,7 +146,7 @@ describe("Run", () => { "w:r": [ { "w:rPr": [ - { "w:shd ": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, + { "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }, { "w:shdCs": { _attr: { diff --git a/src/file/styles/style/paragraph-style.spec.ts b/src/file/styles/style/paragraph-style.spec.ts index ac39460861..4c6d1a402c 100644 --- a/src/file/styles/style/paragraph-style.spec.ts +++ b/src/file/styles/style/paragraph-style.spec.ts @@ -382,7 +382,7 @@ describe("ParagraphStyle", () => { "w:style": [ { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { - "w:rPr": [{ "w:highlight ": { _attr: { "w:val": "005599" } } }], + "w:rPr": [{ "w:highlight": { _attr: { "w:val": "005599" } } }], }, ], }); @@ -395,7 +395,7 @@ describe("ParagraphStyle", () => { "w:style": [ { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { - "w:rPr": [{ "w:shd ": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], + "w:rPr": [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }], }, ], }); From 5a005365b28c2a39663f311a646a154a27904c66 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 17:15:45 +0100 Subject: [PATCH 21/38] Add more documentation --- docs/usage/paragraph.md | 26 ++++++++++++++++++++------ docs/usage/sections.md | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index efa5462594..48e98d471d 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -172,6 +172,12 @@ const paragraph = new Paragraph({ **Example:** +```ts +const paragraph = new Paragraph({ + outlineLevel: 0, +}); +``` + ## Styles To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/docx/wiki/Styling @@ -239,10 +245,15 @@ The result is: ## Thematic Break -To add a break in the page, simply add `.thematicBreak()` on a paragraph: +To add a thematic break in the `Paragraph`: ```js -var paragraph = new docx.Paragraph("Amazing Heading").heading1().thematicBreak(); +var paragraph = new docx.Paragraph("Amazing Heading"); +const paragraph = new Paragraph({ + text: "Amazing Heading", + heading: HeadingLevel.HEADING_1, + thematicBreak: true, +}); ``` The above example will create a heading with a page break directly under it. @@ -251,8 +262,8 @@ The above example will create a heading with a page break directly under it. To move to a new page (insert a page break), simply add `.pageBreak()` on a paragraph: -```js -var paragraph = new docx.Paragraph("Amazing Heading").heading1().pageBreak(); +```ts +const paragraph = new docx.Paragraph("Amazing Heading").pageBreak(); ``` The above example will create a heading and start a new page immediately afterwards. @@ -261,8 +272,11 @@ The above example will create a heading and start a new page immediately afterwa This option (available in word) will make sure that the paragraph will start on a new page (if it's not already on a new page). -```js -var paragraph = new docx.Paragraph("Hello World on another page").pageBreakBefore(); +```ts +const paragraph = new Paragraph({ + text: "Hello World on another page", + pageBreakBefore: true, +}); ``` ![Page Break Before in Word](https://user-images.githubusercontent.com/34742290/40176503-df3a8398-59db-11e8-8b9c-d719f13aa8b4.png) diff --git a/docs/usage/sections.md b/docs/usage/sections.md index 44d409f5f6..5b6d4e9c74 100644 --- a/docs/usage/sections.md +++ b/docs/usage/sections.md @@ -5,3 +5,17 @@ A section is a grouping of paragraphs that have a specific set of properties used to define the pages on which the text will appear. Properties include page size, page numbers, page orientation, headers, borders and margins. For example, you could have one section which is portrait with a header and footer, and another section in landscape with no footer, and a header showing the current page number. + +## Example + +This creates a simple section in a document with one paragraph inside: + +```ts +doc.addSection({ + children: [ + new Paragraph({ + children: [new TextRun("Hello World")], + }), + ], +}); +``` From b5503e7b9be915647c516fd06d6c63aa71fe4b69 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 17:36:05 +0100 Subject: [PATCH 22/38] Add documentation for AlignmentType --- docs/usage/paragraph.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index 48e98d471d..f7bb863c94 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -197,25 +197,9 @@ const paragraph = new Paragraph({ ## Text Alignment -To change the text alignment of a paragraph, for center, left, right or justified: +To change the text alignment of a paragraph, add an `AlignmentType` option on the paragraph.for center, left, right or justified: -```js -paragraph.center(); -``` - -```js -paragraph.left(); -``` - -```js -paragraph.right(); -``` - -```js -paragraph.justified(); -``` - -### Example +**Example:** ```js const paragraph = new Paragraph({ From 0f1f398e6df27e0d1d7493f2b97f9b2d5c58a0a0 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 17:48:07 +0100 Subject: [PATCH 23/38] Amended images documentation --- docs/usage/images.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/docs/usage/images.md b/docs/usage/images.md index b108347df4..693b2d4781 100644 --- a/docs/usage/images.md +++ b/docs/usage/images.md @@ -1,5 +1,7 @@ # Images +!> Images requires an understanding of [Sections](usage/sections.md) and [Paragraphs](usage/paragraph.md). + To create a `floating` image on top of text: ```ts @@ -18,14 +20,27 @@ Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { By default with no arguments, its an `inline` image: ```ts -Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp")); +const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); ``` -You can also create images manually and add them later: +Add it into the document by adding the image into a paragraph: ```ts -const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -doc.addImage(image); +doc.addSection({ + children: [new Paragraph(image)], +}); +``` + +Or: + +```ts +doc.addSection({ + children: [ + new Paragraph({ + children: [image], + }), + ], +}); ``` ## Intro @@ -34,7 +49,7 @@ Adding images can be done in two ways: 1. Call the `createImage` method to add the image directly into the `document`: - ```js + ```ts Media.addImage(doc, [IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]); ``` @@ -42,7 +57,9 @@ Adding images can be done in two ways: ```ts const image = Media.addImage(doc, [IMAGE_BUFFER]); - doc.addImage(image); + doc.addSection({ + children: [new Paragraph(image)], + }); ``` `docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png` @@ -210,7 +227,7 @@ Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { Importing Images from file system path -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_ @@ -218,7 +235,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_ Example showing how to add image to headers and footers -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_ @@ -226,6 +243,6 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_ Example showing how to float images on top of text and optimally give a `margin` -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo38.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo38.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo38.ts_ From 820e5edc1ea59c22906210b4b7373f2dccfd5bc2 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 17:51:13 +0100 Subject: [PATCH 24/38] Using const rather than var and let, and using ts rather than js examples --- docs/README.md | 6 +++--- docs/contribution-guidelines.md | 32 +++++++++++++++---------------- docs/usage/bullet-points.md | 10 +++++----- docs/usage/document.md | 4 ++-- docs/usage/headers-and-footers.md | 8 ++++---- docs/usage/numbering.md | 6 +++--- docs/usage/packers.md | 16 ++++++++-------- docs/usage/paragraph.md | 24 +++++++++++------------ docs/usage/styling-with-js.md | 12 ++++++------ docs/usage/styling-with-xml.md | 6 +++--- docs/usage/tab-stops.md | 22 ++++++++++----------- docs/usage/table-of-contents.md | 4 ++-- docs/usage/text.md | 24 +++++++++++------------ 13 files changed, 87 insertions(+), 87 deletions(-) diff --git a/docs/README.md b/docs/README.md index dca4001a48..e8da69f267 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,8 +18,8 @@ npm install --save docx Then you can `require` or `import` as usual: -```js -let docx = require("docx"); +```ts +const docx = require("docx"); ``` ```ts @@ -30,7 +30,7 @@ import { ... } from "docx"; ## Basic Usage -```js +```ts import * as fs from "fs"; import { Document, Packer, Paragraph, TextRun } from "docx"; diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md index 4092d246a4..1305c4c4bd 100644 --- a/docs/contribution-guidelines.md +++ b/docs/contribution-guidelines.md @@ -2,7 +2,7 @@ * Include documentation reference(s) at the top of each file: - ```js + ```ts // http://officeopenxml.com/WPdocument.php ``` @@ -44,7 +44,7 @@ Try to make method parameters of the outside API accept primitives, or `json` ob This is so that: 1. Imports are much cleaner for the end user, no need for: - ```js + ```ts import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component"; ``` @@ -55,7 +55,7 @@ This is so that: `TableFloatProperties` is a class. The outside world would have to `new` up the object, and inject it in like so: -```js +```ts public float(tableFloatProperties: TableFloatProperties): Table ``` @@ -67,7 +67,7 @@ This is so that: `ITableFloatOptions` is an interface for a JSON of primitives. The end user would need to pass in a json object and not need to worry about the internals: -```js +```ts public float(tableFloatOptions: ITableFloatOptions): Table ``` @@ -81,7 +81,7 @@ This is just a guideline, and the rules can sometimes be broken. * Use `create` if the method `new`'s up an element inside: - ```js + ```ts public createParagraph() { const paragraph = new Paragraph(); this.root.push(paragraph); @@ -91,7 +91,7 @@ This is just a guideline, and the rules can sometimes be broken. * Use `add` if you add the element into the method as a parameter. *Note:* This may look like its breaking the previous guideline, but it has semantically different meanings. The previous one is using data to construct an object, whereas this one is simply adding elements into the document: - ```js + ```ts public add(paragraph: Paragraph) { this.root.push(paragraph); } @@ -101,7 +101,7 @@ This is just a guideline, and the rules can sometimes be broken. Getters and Setters are done with a capital letter like so: -```js +```ts public get Level() { ... } @@ -111,13 +111,13 @@ There is no performance advantage by doing this. It means we don't need to prefi **Do not:** -```js +```ts private get _level: string; ``` **Do** -```js +```ts private get level: string; ``` @@ -158,13 +158,13 @@ Do not use `type`, but rather use `Interfaces`. `type` cannot be extended, and a **Do not:** -```js +```ts type RelationshipFileInfo = { id: number, target: string }; ``` **Do:** -```js +```ts interface IRelationshipFileInfo { id: number; target: string; @@ -177,13 +177,13 @@ To take full advantage of TypeScript's typing system, its best to use `string en **Do not:** -```js +```ts type WeaponType = "bow" | "sword" | "wand"; ``` **Do:** -```js +```ts enum WeaponType = { BOW = "bow", SWORD = "sword", @@ -196,7 +196,7 @@ enum WeaponType = { I am not sure where these habits in software development come from, but I do not believe it is beneficial: **Do not:** -```js +```ts readdy // misspelling perm // abbreviation conf // abbreviation @@ -206,7 +206,7 @@ colour // U.K. English ``` **Do:** -```js +```ts ready permission config @@ -231,7 +231,7 @@ Please write a test of every file you make and suffix it with `.spec.ts`. Here is a template of a test: -```js +```ts import { assert } from "chai"; describe("ClassName", () => { diff --git a/docs/usage/bullet-points.md b/docs/usage/bullet-points.md index 5926e0eca7..dde800ec4d 100644 --- a/docs/usage/bullet-points.md +++ b/docs/usage/bullet-points.md @@ -4,12 +4,12 @@ To make a bullet point, simply make a paragraph into a bullet point: -```js -var text = new docx.TextRun("Bullet points"); -var paragraph = new docx.Paragraph(text).bullet(); +```ts +const text = new docx.TextRun("Bullet points"); +const paragraph = new docx.Paragraph(text).bullet(); -var text2 = new docx.TextRun("Are awesome"); -var paragraph2 = new docx.Paragraph(text2).bullet(); +const text2 = new docx.TextRun("Are awesome"); +const paragraph2 = new docx.Paragraph(text2).bullet(); doc.add(paragraph); doc.add(paragraph2); diff --git a/docs/usage/document.md b/docs/usage/document.md index 56f4826355..bf06d30613 100644 --- a/docs/usage/document.md +++ b/docs/usage/document.md @@ -4,7 +4,7 @@ To create a new document, it is very easy: -```js +```ts const doc = new docx.Document(); ``` @@ -12,7 +12,7 @@ const doc = new docx.Document(); You can add properties to the Word document by specifying options, for example: -```js +```ts const doc = new docx.Document({ creator: "Dolan Miu", description: "My extremely interesting document", diff --git a/docs/usage/headers-and-footers.md b/docs/usage/headers-and-footers.md index 541214da3f..f93cae332c 100644 --- a/docs/usage/headers-and-footers.md +++ b/docs/usage/headers-and-footers.md @@ -6,21 +6,21 @@ Creating Headers and footers is simple. Access the `Header` and `Footer` by doing so like this: -```js +```ts doc.Header; doc.Footer; ``` You can call the same methods as you would with a `File`: -```js +```ts doc.Header.createParagraph("Header text"); doc.Footer.createParagraph("Footer text"); ``` Even add images: -```js +```ts doc.Header.createImage([BUFFER_OF_YOUR_IMAGE]); doc.Footer.createImage([BUFFER_OF_YOUR_IMAGE]); ``` @@ -33,7 +33,7 @@ Also all the supported section properties are implemented according to: http://o ### Example -```js +```ts const header = this.document.createHeader(); const footer = this.document.createFooter(); diff --git a/docs/usage/numbering.md b/docs/usage/numbering.md index ba8f10cdba..1f61c53dca 100644 --- a/docs/usage/numbering.md +++ b/docs/usage/numbering.md @@ -67,7 +67,7 @@ First you need to create a new numbering container class and use it to create your abstract numbering style, define your levels, and create your concrete numbering style: -```js +```ts const numbering = new docx.Numbering(); const abstractNum = numbering.createAbstractNumbering(); @@ -81,7 +81,7 @@ const concrete = numbering.createConcreteNumbering(abstractNum); You can then apply your concrete style to paragraphs using the `setNumbering` method: -```js +```ts topLevelP.setNumbering(concrete, 0); subP.setNumbering(concrete, 1); subSubP.setNumbering(concrete, 2); @@ -90,7 +90,7 @@ subSubP.setNumbering(concrete, 2); Finally, you need to let your exporter know about your numbering styles when you're ready to render the document: -```js +```ts const packer = new Packer(doc, undefined, undefined, numbering); packer.pack(myOutput); ``` diff --git a/docs/usage/packers.md b/docs/usage/packers.md index 11f107390d..274942b715 100644 --- a/docs/usage/packers.md +++ b/docs/usage/packers.md @@ -10,7 +10,7 @@ Packers in `version 4` and above are now one single `Packer`. It works in both a This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead. -```js +```ts const packer = new docx.Packer(); packer.toBuffer(doc).then((buffer) => { @@ -20,7 +20,7 @@ packer.toBuffer(doc).then((buffer) => { ### Export as a `base64` string -```js +```ts const packer = new docx.Packer(); packer.toBase64String(doc).then((string) => { @@ -32,7 +32,7 @@ packer.toBase64String(doc).then((string) => { This is useful if you want to send it as an downloadable in a browser environment. -```js +```ts const packer = new docx.Packer(); packer.toBlob(doc).then((blob) => { @@ -45,7 +45,7 @@ packer.toBlob(doc).then((blob) => { ### File System Packer -```js +```ts const docx = require("docx"); const doc = new docx.Document(); @@ -56,7 +56,7 @@ exporter.pack("My Document"); ### Buffer Packer -```js +```ts const docx = require("docx"); const doc = new docx.Document(); @@ -68,7 +68,7 @@ const buffer = exporter.pack(); Creates a `node` `Readable` stream -```js +```ts const docx = require("docx"); const doc = new docx.Document(); @@ -88,7 +88,7 @@ I used the express exporter in my [website](http://www.dolan.bio). The recommended way is to use the `StreamPacker` and handle the `express` magic outside of the library: -```js +```ts const docx = require("docx"); const doc = new docx.Document(); @@ -107,7 +107,7 @@ where `res` is the response object obtained through the Express router. It is th You can export your word document as a PDF file like so: -```js +```ts const exporter = new docx.LocalPacker(doc); exporter.packPdf("My Document"); diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index f7bb863c94..a398c82e40 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -8,33 +8,33 @@ You can create `Paragraphs` in the following ways: ### Shorthand -```js +```ts import { Paragraph } from "docx"; -var paragraph = new Paragraph("Short hand Hello World"); +const paragraph = new Paragraph("Short hand Hello World"); ``` ### Children Method This method is useful for adding different `text` with different styles or adding `images` inline. -```js -var paragraph = new Paragraph({ +```ts +const paragraph = new Paragraph({ children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")], }); ``` ### Explicit -```js -var paragraph = new Paragraph({ +```ts +const paragraph = new Paragraph({ text: "Short hand notation for adding text.", }); ``` After you create the paragraph, you must add the paragraph into the `document's section`. Learn more about `sections` here: -```js +```ts doc.addSection({ children: [paragraph], }); @@ -42,7 +42,7 @@ doc.addSection({ Or the preferred convension, define the paragraph inside the section and remove the usage of variables: -```js +```ts doc.addSection({ children: [ new Paragraph({ @@ -186,7 +186,7 @@ To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/ ### Headings and titles -```js +```ts import { HeadingLevel, Paragraph } from "docx"; const paragraph = new Paragraph({ @@ -201,7 +201,7 @@ To change the text alignment of a paragraph, add an `AlignmentType` option on th **Example:** -```js +```ts const paragraph = new Paragraph({ text: "Hello World", heading: HeadingLevel.HEADING_1, @@ -231,8 +231,8 @@ The result is: To add a thematic break in the `Paragraph`: -```js -var paragraph = new docx.Paragraph("Amazing Heading"); +```ts +const paragraph = new docx.Paragraph("Amazing Heading"); const paragraph = new Paragraph({ text: "Amazing Heading", heading: HeadingLevel.HEADING_1, diff --git a/docs/usage/styling-with-js.md b/docs/usage/styling-with-js.md index f1f043cb1b..74fcdffb93 100644 --- a/docs/usage/styling-with-js.md +++ b/docs/usage/styling-with-js.md @@ -2,7 +2,7 @@ ## Example -```js +```ts const para = new Paragraph("To whom it may concern:").heading2().center(); const name = new TextRun("Name:") @@ -56,7 +56,7 @@ Unlike CSS, less specific rules don't _necessarily_ override parent rules. The r This is the type of formatting that your uncle uses when he types out documents: _N ... a ... m ... e ... :_ Then he grabs the mouse, highlights _Name:_ and moves over to the **B** for bold. This manner of formatting results in markup that is similar to writing `Name:` if you were typing out HTML. DOCX (the format) allows you to specify this for any of the four types of items. `docx` (the library) only supports this type of formatting for paragraphs and characters, using a _fluent_ api. Thus you could do: -```js +```ts const name = new TextRun("Name:") .bold() .font("Calibri") @@ -65,7 +65,7 @@ const name = new TextRun("Name:") Or for paragraph formatting: -```js +```ts const para = new Paragraph("To whom it may concern:").heading2().center(); ``` @@ -76,12 +76,12 @@ DOCX files contain a styles section separate from the main content, much like ho There are three parts to using custom styles with `docx`: 1. Create a container object for the style definitions: - ```js + ```ts const myStyles = new docx.Styles(); ``` 2. Define your custom styles, similar to the way you would format a paragraph or run - ```js + ```ts // The first argument is an ID you use to apply the style to paragraphs // The second argument is a human-friendly name to show in the UI myStyles @@ -106,7 +106,7 @@ There are three parts to using custom styles with `docx`: 3. When you generate your document, make sure to pass the `styles` container to the `Packer`: - ```js + ```ts const packer = new Packer(doc, myStyles); packer.pack(myOutStream); ``` diff --git a/docs/usage/styling-with-xml.md b/docs/usage/styling-with-xml.md index 1aad181d2d..ee5a2b1db4 100644 --- a/docs/usage/styling-with-xml.md +++ b/docs/usage/styling-with-xml.md @@ -24,7 +24,7 @@ Read the styles using `fs`, and put it into the `Document` object in the constructor: -```js +```ts const styles = fs.readFileSync("./styles.xml", "utf-8"); const doc = new docx.Document({ title: "Title", @@ -34,10 +34,10 @@ const doc = new docx.Document({ You can use paragraphs, `heading1()`, `heading2()` etc and it will be styled according to your `styles.xml` created earlier. You can even use your new style you made by calling the `style` method: -```js +```ts doc.createParagraph("Cool Heading Text").heading1(); -let paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"'); +const paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"'); paragraph.style("Cool New Style"); doc.add(paragraph); diff --git a/docs/usage/tab-stops.md b/docs/usage/tab-stops.md index aa15ea75a9..e172c7f9b0 100644 --- a/docs/usage/tab-stops.md +++ b/docs/usage/tab-stops.md @@ -10,45 +10,45 @@ Simply call the relevant methods on the paragraph listed below. Then just add a ## Example -```js -var paragraph = new docx.Paragraph().maxRightTabStop(); -var leftText = new docx.TextRun("Hey everyone").bold(); -var rightText = new docx.TextRun("11th November 2015").tab(); +```ts +const paragraph = new docx.Paragraph().maxRightTabStop(); +const leftText = new docx.TextRun("Hey everyone").bold(); +const rightText = new docx.TextRun("11th November 2015").tab(); paragraph.addRun(leftText); paragraph.addRun(rightText); ``` The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. YUK! -```js -var paragraph = new docx.Paragraph(); +```ts +const paragraph = new docx.Paragraph(); paragraph.maxRightTabStop(); paragraph.leftTabStop(1000); -var text = new docx.TextRun("Second tab stop here I come!").tab().tab(); +const text = new docx.TextRun("Second tab stop here I come!").tab().tab(); paragraph.addRun(text); ``` The above shows the use of two tab stops, and how to select/use it. ## Left Tab Stop -```js +```ts paragraph.leftTabStop(2268); ``` 2268 is the distance from the left side. ## Center Tab Stop -```js +```ts paragraph.centerTabStop(2268); ``` 2268 is the distance from the left side. ## Right Tab Stop -```js +```ts paragraph.rightTabStop(2268); ``` 2268 is the distance from the left side. ## Max Right Tab Stop -```js +```ts paragraph.maxRightTabStop(); ``` This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line. diff --git a/docs/usage/table-of-contents.md b/docs/usage/table-of-contents.md index 02ef2eff14..53e8e7df57 100644 --- a/docs/usage/table-of-contents.md +++ b/docs/usage/table-of-contents.md @@ -12,7 +12,7 @@ The complete documentation can be found [here](https://www.ecma-international.or All you need to do is create a `TableOfContents` object and assign it to the document. -```js +```ts const toc = new TableOfContents("Summary", { hyperlink: true, headingStyleRange: "1-5", @@ -47,7 +47,7 @@ Here is the list of all options that you can use to generate your tables of cont ## Examples -```js +```ts // Let's define the options for generate a TOC for heading 1-5 and MySpectacularStyle, // making the entries be hyperlinks for the paragraph const toc = new TableOfContents("Summary", { diff --git a/docs/usage/text.md b/docs/usage/text.md index ed02dad742..9de3193cd6 100644 --- a/docs/usage/text.md +++ b/docs/usage/text.md @@ -2,7 +2,7 @@ You can add multiple `text runs` in `Paragraphs`. This is the most verbose way of writing a `Paragraph` but it is also the most flexible: -```js +```ts import { Paragraph, Text } from "docx"; const paragraph = new Paragraph({ @@ -20,55 +20,55 @@ More info [here](https://english.stackexchange.com/questions/97081/what-is-the-t ### Bold -```js +```ts text.bold(); ``` ### Italics -```js +```ts text.italics(); ``` ### Underline -```js +```ts text.underline(); ``` ### Strike through -```js +```ts text.strike(); ``` ### Double strike through -```js +```ts text.doubleStrike(); ``` ### Superscript -```js +```ts text.superScript(); ``` ### Subscript -```js +```ts text.subScript(); ``` ### All Capitals -```js +```ts text.allCaps(); ``` ### Small Capitals -```js +```ts text.smallCaps(); ``` @@ -76,7 +76,7 @@ text.smallCaps(); Sometimes you would want to put text underneath another line of text but inside the same paragraph. -```js +```ts text.break(); ``` @@ -84,6 +84,6 @@ text.break(); What if you want to create a paragraph which is **_bold_** and **_italic_**? -```js +```ts paragraph.bold().italics(); ``` From 9da9f31c7792fa8fb4a218fc53217e2dec67912c Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Tue, 6 Aug 2019 18:27:00 +0100 Subject: [PATCH 25/38] Change text documentation --- docs/usage/text.md | 48 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/docs/usage/text.md b/docs/usage/text.md index 9de3193cd6..6cbd9da224 100644 --- a/docs/usage/text.md +++ b/docs/usage/text.md @@ -1,14 +1,14 @@ -# Text +# Text Runs + +!> TextRuns requires an understanding of [Paragraphs](usage/paragraph.md). You can add multiple `text runs` in `Paragraphs`. This is the most verbose way of writing a `Paragraph` but it is also the most flexible: ```ts -import { Paragraph, Text } from "docx"; +import { Paragraph, TextRun } from "docx"; const paragraph = new Paragraph({ - children: [ - new TextRun("My awesome text here for my university dissertation"), - ], + children: [new TextRun("My awesome text here for my university dissertation"), new TextRun("Foo Bar")], }); ``` @@ -21,19 +21,51 @@ More info [here](https://english.stackexchange.com/questions/97081/what-is-the-t ### Bold ```ts -text.bold(); +const text = new TextRun({ + text: "Foo Bar", + bold: true, +}); ``` ### Italics ```ts -text.italics(); +const text = new TextRun({ + text: "Foo Bar", + italics: true, +}); ``` ### Underline +Underline has a few options + +#### Options + +| Property | Type | Notes | Possible Values | +| -------- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| type | `UnderlineType` | Optional | SINGLE, WORD, DOUBLE, THICK, DOTTED, DOTTEDHEAV, DASH, DASHEDHEAV, DASHLONG, DASHLONGHEAV, DOTDASH, DASHDOTHEAVY, DOTDOTDAS, DASHDOTDOTHEAVY, WAVE, WAVYHEAVY, WAVYDOUBLE | +| color | `string` | Optional | Color Hex values | + +**Example:** + ```ts -text.underline(); +const text = new TextRun({ + text: "and then underlined ", + underline: { + type: UnderlineType.DOUBLE, + color: "990011", + }, +}); +``` + +To do a simple vanilla underline: + +```ts +const text = new TextRun({ + text: "and then underlined ", + underline: {}, +}); ``` ### Strike through From e45e7ffe06df4b3d933d1aaa8160ef51fbf47242 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 6 Aug 2019 21:37:33 +0100 Subject: [PATCH 26/38] Consolidate highlight and shadow API --- demo/demo45.ts | 42 ++++++++++------- demo/demo46.ts | 46 ++++++++++++------- src/file/paragraph/run/run.spec.ts | 15 +++++- src/file/paragraph/run/run.ts | 73 ++++++++---------------------- 4 files changed, 86 insertions(+), 90 deletions(-) diff --git a/demo/demo45.ts b/demo/demo45.ts index 7cef926537..dc44693e4d 100644 --- a/demo/demo45.ts +++ b/demo/demo45.ts @@ -1,24 +1,32 @@ import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, Header, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -const header = doc.Header.createTable(1, 3) - // @ts-ignore - header.properties.root[1] = [] - - header.getCell(0, 2).addParagraph( - new Paragraph() - .addRun( - new TextRun('W.P. 660') - .color('red') - .bold() - .size(12 * 2) - .font('Garamond') - .highlight('yellow') - ) - .right() - ) +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun({ + text: "Hello World", + color: "red", + bold: true, + size: 24, + font: { + name: "Garamond", + }, + highlight: "yellow", + }), + ], + }), + ], + }), + }, + children: [], +}); const packer = new Packer(); diff --git a/demo/demo46.ts b/demo/demo46.ts index bc38e8dc19..2bb31abdf9 100644 --- a/demo/demo46.ts +++ b/demo/demo46.ts @@ -1,24 +1,36 @@ import * as fs from "fs"; -import { Document, Packer, Paragraph, TextRun } from "../build"; +import { AlignmentType, Document, Header, Packer, Paragraph, ShadingType, TextRun } from "../build"; const doc = new Document(); -const header = doc.Header.createTable(1, 3) - // @ts-ignore - header.properties.root[1] = [] - - header.getCell(0, 2).addParagraph( - new Paragraph() - .addRun( - new TextRun('W.P. 660') - .color('red') - .bold() - .size(12 * 2) - .font('Garamond') - .shadow('pct10','00FFFF','FF0000') - ) - .right() - ) +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun({ + text: "Hello World", + color: "red", + bold: true, + size: 24, + font: { + name: "Garamond", + }, + shadow: { + type: ShadingType.REVERSE_DIAGONAL_STRIPE, + color: "00FFFF", + fill: "FF0000", + }, + }), + ], + }), + ], + }), + }, + children: [], +}); const packer = new Packer(); diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index a77e59844f..ed43584292 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; import { Formatter } from "export/formatter"; +import { ShadingType } from "file/table"; import { Run } from "./"; import { UnderlineType } from "./underline"; @@ -131,7 +132,10 @@ describe("Run", () => { describe("#highlight()", () => { it("it should add highlight to the properties", () => { - run.highlight("005599"); + const run = new Run({ + doubleStrike: true, + highlight: "005599", + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [ @@ -154,7 +158,14 @@ describe("Run", () => { describe("#shadow()", () => { it("it should add shadow to the properties", () => { - run.shadow("pct10", "00FFFF", "FF0000"); + const run = new Run({ + doubleStrike: true, + shadow: { + type: ShadingType.PERCENT_10, + fill: "00FFFF", + color: "FF0000", + }, + }); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [ diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index 5b62d5b9c8..2e5cd63439 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -1,4 +1,7 @@ // http://officeopenxml.com/WPtext.php +import { ShadingType } from "file/table"; +import { XmlComponent } from "file/xml-components"; + import { Break } from "./break"; import { Caps, SmallCaps } from "./caps"; import { Begin, End, Separate } from "./field"; @@ -26,8 +29,6 @@ import { Style } from "./style"; import { Tab } from "./tab"; import { Underline, UnderlineType } from "./underline"; -import { XmlComponent } from "file/xml-components"; - export interface IRunOptions { readonly bold?: true; readonly italics?: true; @@ -49,6 +50,12 @@ export interface IRunOptions { readonly name: string; readonly hint?: string; }; + readonly highlight?: string; + readonly shadow?: { + readonly type: ShadingType; + readonly fill: string; + readonly color: string; + }; } export class Run extends XmlComponent { @@ -117,6 +124,16 @@ export class Run extends XmlComponent { if (options.font) { this.properties.push(new RunFonts(options.font.name, options.font.hint)); } + + if (options.highlight) { + this.properties.push(new Highlight(options.highlight)); + this.properties.push(new HighlightComplexScript(options.highlight)); + } + + if (options.shadow) { + this.properties.push(new Shadow(options.shadow.type, options.shadow.fill, options.shadow.color)); + this.properties.push(new ShadowComplexScript(options.shadow.type, options.shadow.fill, options.shadow.color)); + } } public break(): Run { @@ -144,56 +161,4 @@ export class Run extends XmlComponent { this.root.push(new End()); return this; } - - public smallCaps(): Run { - this.properties.push(new SmallCaps()); - return this; - } - - public allCaps(): Run { - this.properties.push(new Caps()); - return this; - } - - public strike(): Run { - this.properties.push(new Strike()); - return this; - } - - public doubleStrike(): Run { - this.properties.push(new DoubleStrike()); - return this; - } - - public subScript(): Run { - this.properties.push(new SubScript()); - return this; - } - - public superScript(): Run { - this.properties.push(new SuperScript()); - return this; - } - - public font(fontName: string, hint?: string | undefined): Run { - this.properties.push(new RunFonts(fontName, hint)); - return this; - } - - public style(styleId: string): Run { - this.properties.push(new Style(styleId)); - return this; - } - - public highlight(color: string): Run { - this.properties.push(new Highlight(color)); - this.properties.push(new HighlightComplexScript(color)); - return this; - } - - public shadow(value: string, fill: string, color: string): Run { - this.properties.push(new Shadow(value, fill, color)); - this.properties.push(new ShadowComplexScript(value, fill, color)); - return this; - } } From 82fef4c2b19ca2414e1f7a7f8fbbdcbbe71b8a67 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 6 Aug 2019 22:27:16 +0100 Subject: [PATCH 27/38] Fix tests --- src/file/paragraph/run/run.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index ed43584292..b8b30295d6 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -133,7 +133,6 @@ describe("Run", () => { describe("#highlight()", () => { it("it should add highlight to the properties", () => { const run = new Run({ - doubleStrike: true, highlight: "005599", }); const tree = new Formatter().format(run); @@ -159,7 +158,6 @@ describe("Run", () => { describe("#shadow()", () => { it("it should add shadow to the properties", () => { const run = new Run({ - doubleStrike: true, shadow: { type: ShadingType.PERCENT_10, fill: "00FFFF", From b741db3050dc932b6997bdd0fa1d2014ca6f6aac Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 6 Aug 2019 23:08:21 +0100 Subject: [PATCH 28/38] Using a better demo naming system --- demo/{demo1.ts => 1-basic.ts} | 0 demo/{demo10.ts => 10-my-cv.ts} | 0 demo/{demo11.ts => 11-declaritive-styles-2.ts} | 0 demo/{demo12.ts => 12-scaling-images.ts} | 0 demo/{demo13.ts => 13-xml-styles.ts} | 0 demo/{demo14.ts => 14-page-numbers.ts} | 0 demo/{demo15.ts => 15-page-break-before.ts} | 0 demo/{demo16.ts => 16-multiple-sections.ts} | 0 demo/{demo17.ts => 17-footnotes.ts} | 0 demo/{demo18.ts => 18-image-from-buffer.ts} | 0 demo/{demo19.ts => 19-export-to-base64.ts} | 0 demo/{demo2.ts => 2-declaritive-styles.ts} | 0 demo/{demo20.ts => 20-table-cell-borders.ts} | 0 demo/{demo21.ts => 21-bookmarks.ts} | 0 demo/{demo22.ts => 22-right-to-left-text.ts} | 0 demo/{demo23.ts => 23-base64-images.ts} | 0 demo/{demo24.ts => 24-images-to-table-cell.ts} | 0 demo/{demo26.ts => 26-paragraph-borders.ts} | 0 demo/{demo27.ts => 27-declaritive-styles-3.ts} | 0 demo/{demo28.ts => 28-table-of-contents.ts} | 0 demo/{demo29.ts => 29-numbered-lists.ts} | 0 demo/{demo3.ts => 3-numbering-and-bullet-points.ts} | 0 demo/{demo30.ts => 30-template-document.ts} | 0 demo/{demo31.ts => 31-tables.ts} | 0 demo/{demo32.ts => 32-merge-table-cells.ts} | 0 demo/{demo33.ts => 33-sequential-captions.ts} | 0 demo/{demo34.ts => 34-floating-tables.ts} | 0 demo/{demo35.ts => 35-hyperlinks.ts} | 0 demo/{demo36.ts => 36-image-to-table-cell.ts} | 0 demo/{demo37.ts => 37-images-to-header-and-footer.ts} | 0 demo/{demo38.ts => 38-text-wrapping.ts} | 0 demo/{demo39.ts => 39-page-numbers.ts} | 0 demo/{demo4.ts => 4-basic-table.ts} | 0 demo/{demo40.ts => 40-line-numbers.ts} | 0 demo/{demo41.ts => 41-merge-table-cells-2.ts} | 0 demo/{demo43.ts => 43-images-to-table-cell-2.ts} | 0 demo/{demo44.ts => 44-multiple-columns.ts} | 0 demo/{demo45.ts => 45-highlighting-text.ts} | 2 ++ demo/{demo46.ts => 46-shading-text.ts} | 4 +++- demo/{demo5.ts => 5-images.ts} | 0 demo/{demo6.ts => 6-page-borders.ts} | 0 demo/{demo7.ts => 7-landscape.ts} | 0 demo/{demo8.ts => 8-header-footer.ts} | 0 demo/{demo9.ts => 9-images-in-header-and-footer.ts} | 0 demo/index.ts | 11 +++++++---- src/file/numbering/level.ts | 2 +- src/file/paragraph/run/formatting.ts | 2 +- src/file/paragraph/run/run.spec.ts | 2 +- src/file/paragraph/run/run.ts | 10 +++++----- src/file/styles/style/character-style.ts | 2 +- src/file/styles/style/paragraph-style.ts | 2 +- 51 files changed, 22 insertions(+), 15 deletions(-) rename demo/{demo1.ts => 1-basic.ts} (100%) rename demo/{demo10.ts => 10-my-cv.ts} (100%) rename demo/{demo11.ts => 11-declaritive-styles-2.ts} (100%) rename demo/{demo12.ts => 12-scaling-images.ts} (100%) rename demo/{demo13.ts => 13-xml-styles.ts} (100%) rename demo/{demo14.ts => 14-page-numbers.ts} (100%) rename demo/{demo15.ts => 15-page-break-before.ts} (100%) rename demo/{demo16.ts => 16-multiple-sections.ts} (100%) rename demo/{demo17.ts => 17-footnotes.ts} (100%) rename demo/{demo18.ts => 18-image-from-buffer.ts} (100%) rename demo/{demo19.ts => 19-export-to-base64.ts} (100%) rename demo/{demo2.ts => 2-declaritive-styles.ts} (100%) rename demo/{demo20.ts => 20-table-cell-borders.ts} (100%) rename demo/{demo21.ts => 21-bookmarks.ts} (100%) rename demo/{demo22.ts => 22-right-to-left-text.ts} (100%) rename demo/{demo23.ts => 23-base64-images.ts} (100%) rename demo/{demo24.ts => 24-images-to-table-cell.ts} (100%) rename demo/{demo26.ts => 26-paragraph-borders.ts} (100%) rename demo/{demo27.ts => 27-declaritive-styles-3.ts} (100%) rename demo/{demo28.ts => 28-table-of-contents.ts} (100%) rename demo/{demo29.ts => 29-numbered-lists.ts} (100%) rename demo/{demo3.ts => 3-numbering-and-bullet-points.ts} (100%) rename demo/{demo30.ts => 30-template-document.ts} (100%) rename demo/{demo31.ts => 31-tables.ts} (100%) rename demo/{demo32.ts => 32-merge-table-cells.ts} (100%) rename demo/{demo33.ts => 33-sequential-captions.ts} (100%) rename demo/{demo34.ts => 34-floating-tables.ts} (100%) rename demo/{demo35.ts => 35-hyperlinks.ts} (100%) rename demo/{demo36.ts => 36-image-to-table-cell.ts} (100%) rename demo/{demo37.ts => 37-images-to-header-and-footer.ts} (100%) rename demo/{demo38.ts => 38-text-wrapping.ts} (100%) rename demo/{demo39.ts => 39-page-numbers.ts} (100%) rename demo/{demo4.ts => 4-basic-table.ts} (100%) rename demo/{demo40.ts => 40-line-numbers.ts} (100%) rename demo/{demo41.ts => 41-merge-table-cells-2.ts} (100%) rename demo/{demo43.ts => 43-images-to-table-cell-2.ts} (100%) rename demo/{demo44.ts => 44-multiple-columns.ts} (100%) rename demo/{demo45.ts => 45-highlighting-text.ts} (91%) rename demo/{demo46.ts => 46-shading-text.ts} (90%) rename demo/{demo5.ts => 5-images.ts} (100%) rename demo/{demo6.ts => 6-page-borders.ts} (100%) rename demo/{demo7.ts => 7-landscape.ts} (100%) rename demo/{demo8.ts => 8-header-footer.ts} (100%) rename demo/{demo9.ts => 9-images-in-header-and-footer.ts} (100%) diff --git a/demo/demo1.ts b/demo/1-basic.ts similarity index 100% rename from demo/demo1.ts rename to demo/1-basic.ts diff --git a/demo/demo10.ts b/demo/10-my-cv.ts similarity index 100% rename from demo/demo10.ts rename to demo/10-my-cv.ts diff --git a/demo/demo11.ts b/demo/11-declaritive-styles-2.ts similarity index 100% rename from demo/demo11.ts rename to demo/11-declaritive-styles-2.ts diff --git a/demo/demo12.ts b/demo/12-scaling-images.ts similarity index 100% rename from demo/demo12.ts rename to demo/12-scaling-images.ts diff --git a/demo/demo13.ts b/demo/13-xml-styles.ts similarity index 100% rename from demo/demo13.ts rename to demo/13-xml-styles.ts diff --git a/demo/demo14.ts b/demo/14-page-numbers.ts similarity index 100% rename from demo/demo14.ts rename to demo/14-page-numbers.ts diff --git a/demo/demo15.ts b/demo/15-page-break-before.ts similarity index 100% rename from demo/demo15.ts rename to demo/15-page-break-before.ts diff --git a/demo/demo16.ts b/demo/16-multiple-sections.ts similarity index 100% rename from demo/demo16.ts rename to demo/16-multiple-sections.ts diff --git a/demo/demo17.ts b/demo/17-footnotes.ts similarity index 100% rename from demo/demo17.ts rename to demo/17-footnotes.ts diff --git a/demo/demo18.ts b/demo/18-image-from-buffer.ts similarity index 100% rename from demo/demo18.ts rename to demo/18-image-from-buffer.ts diff --git a/demo/demo19.ts b/demo/19-export-to-base64.ts similarity index 100% rename from demo/demo19.ts rename to demo/19-export-to-base64.ts diff --git a/demo/demo2.ts b/demo/2-declaritive-styles.ts similarity index 100% rename from demo/demo2.ts rename to demo/2-declaritive-styles.ts diff --git a/demo/demo20.ts b/demo/20-table-cell-borders.ts similarity index 100% rename from demo/demo20.ts rename to demo/20-table-cell-borders.ts diff --git a/demo/demo21.ts b/demo/21-bookmarks.ts similarity index 100% rename from demo/demo21.ts rename to demo/21-bookmarks.ts diff --git a/demo/demo22.ts b/demo/22-right-to-left-text.ts similarity index 100% rename from demo/demo22.ts rename to demo/22-right-to-left-text.ts diff --git a/demo/demo23.ts b/demo/23-base64-images.ts similarity index 100% rename from demo/demo23.ts rename to demo/23-base64-images.ts diff --git a/demo/demo24.ts b/demo/24-images-to-table-cell.ts similarity index 100% rename from demo/demo24.ts rename to demo/24-images-to-table-cell.ts diff --git a/demo/demo26.ts b/demo/26-paragraph-borders.ts similarity index 100% rename from demo/demo26.ts rename to demo/26-paragraph-borders.ts diff --git a/demo/demo27.ts b/demo/27-declaritive-styles-3.ts similarity index 100% rename from demo/demo27.ts rename to demo/27-declaritive-styles-3.ts diff --git a/demo/demo28.ts b/demo/28-table-of-contents.ts similarity index 100% rename from demo/demo28.ts rename to demo/28-table-of-contents.ts diff --git a/demo/demo29.ts b/demo/29-numbered-lists.ts similarity index 100% rename from demo/demo29.ts rename to demo/29-numbered-lists.ts diff --git a/demo/demo3.ts b/demo/3-numbering-and-bullet-points.ts similarity index 100% rename from demo/demo3.ts rename to demo/3-numbering-and-bullet-points.ts diff --git a/demo/demo30.ts b/demo/30-template-document.ts similarity index 100% rename from demo/demo30.ts rename to demo/30-template-document.ts diff --git a/demo/demo31.ts b/demo/31-tables.ts similarity index 100% rename from demo/demo31.ts rename to demo/31-tables.ts diff --git a/demo/demo32.ts b/demo/32-merge-table-cells.ts similarity index 100% rename from demo/demo32.ts rename to demo/32-merge-table-cells.ts diff --git a/demo/demo33.ts b/demo/33-sequential-captions.ts similarity index 100% rename from demo/demo33.ts rename to demo/33-sequential-captions.ts diff --git a/demo/demo34.ts b/demo/34-floating-tables.ts similarity index 100% rename from demo/demo34.ts rename to demo/34-floating-tables.ts diff --git a/demo/demo35.ts b/demo/35-hyperlinks.ts similarity index 100% rename from demo/demo35.ts rename to demo/35-hyperlinks.ts diff --git a/demo/demo36.ts b/demo/36-image-to-table-cell.ts similarity index 100% rename from demo/demo36.ts rename to demo/36-image-to-table-cell.ts diff --git a/demo/demo37.ts b/demo/37-images-to-header-and-footer.ts similarity index 100% rename from demo/demo37.ts rename to demo/37-images-to-header-and-footer.ts diff --git a/demo/demo38.ts b/demo/38-text-wrapping.ts similarity index 100% rename from demo/demo38.ts rename to demo/38-text-wrapping.ts diff --git a/demo/demo39.ts b/demo/39-page-numbers.ts similarity index 100% rename from demo/demo39.ts rename to demo/39-page-numbers.ts diff --git a/demo/demo4.ts b/demo/4-basic-table.ts similarity index 100% rename from demo/demo4.ts rename to demo/4-basic-table.ts diff --git a/demo/demo40.ts b/demo/40-line-numbers.ts similarity index 100% rename from demo/demo40.ts rename to demo/40-line-numbers.ts diff --git a/demo/demo41.ts b/demo/41-merge-table-cells-2.ts similarity index 100% rename from demo/demo41.ts rename to demo/41-merge-table-cells-2.ts diff --git a/demo/demo43.ts b/demo/43-images-to-table-cell-2.ts similarity index 100% rename from demo/demo43.ts rename to demo/43-images-to-table-cell-2.ts diff --git a/demo/demo44.ts b/demo/44-multiple-columns.ts similarity index 100% rename from demo/demo44.ts rename to demo/44-multiple-columns.ts diff --git a/demo/demo45.ts b/demo/45-highlighting-text.ts similarity index 91% rename from demo/demo45.ts rename to demo/45-highlighting-text.ts index dc44693e4d..0e2b416f33 100644 --- a/demo/demo45.ts +++ b/demo/45-highlighting-text.ts @@ -1,3 +1,5 @@ +// Highlighting text +// Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; import { AlignmentType, Document, Header, Packer, Paragraph, TextRun } from "../build"; diff --git a/demo/demo46.ts b/demo/46-shading-text.ts similarity index 90% rename from demo/demo46.ts rename to demo/46-shading-text.ts index 2bb31abdf9..5e0b816a63 100644 --- a/demo/demo46.ts +++ b/demo/46-shading-text.ts @@ -1,3 +1,5 @@ +// Shading text +// Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; import { AlignmentType, Document, Header, Packer, Paragraph, ShadingType, TextRun } from "../build"; @@ -18,7 +20,7 @@ doc.addSection({ font: { name: "Garamond", }, - shadow: { + shading: { type: ShadingType.REVERSE_DIAGONAL_STRIPE, color: "00FFFF", fill: "FF0000", diff --git a/demo/demo5.ts b/demo/5-images.ts similarity index 100% rename from demo/demo5.ts rename to demo/5-images.ts diff --git a/demo/demo6.ts b/demo/6-page-borders.ts similarity index 100% rename from demo/demo6.ts rename to demo/6-page-borders.ts diff --git a/demo/demo7.ts b/demo/7-landscape.ts similarity index 100% rename from demo/demo7.ts rename to demo/7-landscape.ts diff --git a/demo/demo8.ts b/demo/8-header-footer.ts similarity index 100% rename from demo/demo8.ts rename to demo/8-header-footer.ts diff --git a/demo/demo9.ts b/demo/9-images-in-header-and-footer.ts similarity index 100% rename from demo/demo9.ts rename to demo/9-images-in-header-and-footer.ts diff --git a/demo/index.ts b/demo/index.ts index 50b65572f2..8764e25f31 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -19,13 +19,16 @@ prompt.start(); prompt.get(schema, (_, result) => { const demoNumber = result.number; - const filePath = `./demo/demo${demoNumber}.ts`; + const files = fs.readdirSync("./demo").filter((fn) => fn.startsWith(demoNumber)); - if (!fs.existsSync(filePath)) { - console.error(`demo${demoNumber} does not exist: ${filePath}`); + if (files.length === 0) { + console.error(`demo number ${demoNumber} does not exist`); return; } - console.log(`Running demo ${demoNumber}`); + + const filePath = `./demo/${files[0]}`; + + console.log(`Running demo ${demoNumber}: ${files[0]}`); if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) { console.log("Document created successfully"); } else { diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index bbfb27493f..8a266fa47f 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -205,7 +205,7 @@ export class LevelBase extends XmlComponent { } public shadow(value: string, fill: string, color: string): Level { - this.addRunProperty(new formatting.Shadow(value, fill, color)); + this.addRunProperty(new formatting.Shading(value, fill, color)); return this; } // --------------------- Paragraph formatting ------------------------ // diff --git a/src/file/paragraph/run/formatting.ts b/src/file/paragraph/run/formatting.ts index 87273b9459..549f2ae552 100644 --- a/src/file/paragraph/run/formatting.ts +++ b/src/file/paragraph/run/formatting.ts @@ -201,7 +201,7 @@ export class HighlightComplexScript extends XmlComponent { } } -export class Shadow extends XmlComponent { +export class Shading extends XmlComponent { constructor(value: string, fill: string, color: string) { super("w:shd"); this.root.push( diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index b8b30295d6..81033425e4 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -158,7 +158,7 @@ describe("Run", () => { describe("#shadow()", () => { it("it should add shadow to the properties", () => { const run = new Run({ - shadow: { + shading: { type: ShadingType.PERCENT_10, fill: "00FFFF", color: "FF0000", diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index 2e5cd63439..f6ac359852 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -15,7 +15,7 @@ import { Italics, ItalicsComplexScript, RightToLeft, - Shadow, + Shading, ShadowComplexScript, Size, SizeComplexScript, @@ -51,7 +51,7 @@ export interface IRunOptions { readonly hint?: string; }; readonly highlight?: string; - readonly shadow?: { + readonly shading?: { readonly type: ShadingType; readonly fill: string; readonly color: string; @@ -130,9 +130,9 @@ export class Run extends XmlComponent { this.properties.push(new HighlightComplexScript(options.highlight)); } - if (options.shadow) { - this.properties.push(new Shadow(options.shadow.type, options.shadow.fill, options.shadow.color)); - this.properties.push(new ShadowComplexScript(options.shadow.type, options.shadow.fill, options.shadow.color)); + 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)); } } diff --git a/src/file/styles/style/character-style.ts b/src/file/styles/style/character-style.ts index 4ac49ba950..c60cca9394 100644 --- a/src/file/styles/style/character-style.ts +++ b/src/file/styles/style/character-style.ts @@ -64,6 +64,6 @@ export class CharacterStyle extends Style { } public shadow(value: string, fill: string, color: string): CharacterStyle { - return this.addRunProperty(new formatting.Shadow(value, fill, color)); + return this.addRunProperty(new formatting.Shading(value, fill, color)); } } diff --git a/src/file/styles/style/paragraph-style.ts b/src/file/styles/style/paragraph-style.ts index a1d3d86775..e79c6abe17 100644 --- a/src/file/styles/style/paragraph-style.ts +++ b/src/file/styles/style/paragraph-style.ts @@ -119,7 +119,7 @@ export class ParagraphStyle extends Style { } public shadow(value: string, fill: string, color: string): ParagraphStyle { - return this.addRunProperty(new formatting.Shadow(value, fill, color)); + return this.addRunProperty(new formatting.Shading(value, fill, color)); } // --------------------- Paragraph formatting ------------------------ // From 65c5177dafb4279d8fa9c34364eda8a62a44df4f Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 6 Aug 2019 23:28:12 +0100 Subject: [PATCH 29/38] Fix demo paths --- .travis.yml | 66 ++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2fd9123e2a..3c015ad296 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,43 +9,43 @@ script: - npm run test.coverage - npm run style - npm run build - - npm run ts-node -- ./demo/demo1.ts + - npm run ts-node -- ./demo/1-basic.ts - npm run e2e "My Document.docx" - - npm run ts-node -- ./demo/demo2.ts - - npm run ts-node -- ./demo/demo3.ts - - npm run ts-node -- ./demo/demo4.ts - - npm run ts-node -- ./demo/demo5.ts - - npm run ts-node -- ./demo/demo6.ts - - npm run ts-node -- ./demo/demo7.ts - - npm run ts-node -- ./demo/demo8.ts - - npm run ts-node -- ./demo/demo9.ts - - npm run ts-node -- ./demo/demo10.ts + - npm run ts-node -- ./demo/2-declaritive-styles.ts + - npm run ts-node -- ./demo/3-numbering-and-bullet-points.ts + - npm run ts-node -- ./demo/4-basic-table.ts + - npm run ts-node -- ./demo/5-images.ts + - npm run ts-node -- ./demo/6-page-borders.ts + - npm run ts-node -- ./demo/7-landscape.ts + - npm run ts-node -- ./demo/8-header-footer.ts + - npm run ts-node -- ./demo/9-images-in-header-and-footer.ts + - npm run ts-node -- ./demo/10-my-cv.ts - npm run e2e "My Document.docx" - - npm run ts-node -- ./demo/demo11.ts - - npm run ts-node -- ./demo/demo12.ts - - npm run ts-node -- ./demo/demo13.ts - - npm run ts-node -- ./demo/demo14.ts - - npm run ts-node -- ./demo/demo15.ts - - npm run ts-node -- ./demo/demo16.ts - - npm run ts-node -- ./demo/demo17.ts - - npm run ts-node -- ./demo/demo18.ts - - npm run ts-node -- ./demo/demo19.ts - - npm run ts-node -- ./demo/demo20.ts - - npm run ts-node -- ./demo/demo21.ts - - npm run ts-node -- ./demo/demo22.ts - - npm run ts-node -- ./demo/demo23.ts - - npm run ts-node -- ./demo/demo24.ts + - npm run ts-node -- ./demo/11-declaritive-styles-2.ts + - npm run ts-node -- ./demo/12-scaling-images.ts + - npm run ts-node -- ./demo/13-xml-styles.ts + - npm run ts-node -- ./demo/14-page-numbers.ts + - npm run ts-node -- ./demo/15-page-break-before.ts + - npm run ts-node -- ./demo/16-multiple-sections.ts + - npm run ts-node -- ./demo/17-footnotes.ts + - npm run ts-node -- ./demo/18-image-from-buffer.ts + - npm run ts-node -- ./demo/19-export-to-base64.ts + - npm run ts-node -- ./demo/20-table-cell-borders.ts + - npm run ts-node -- ./demo/21-bookmarks.ts + - npm run ts-node -- ./demo/22-right-to-left-text.ts + - npm run ts-node -- ./demo/23-base64-images.ts + - npm run ts-node -- ./demo/24-images-to-table-cell.ts # - npm run ts-node -- ./demo/demo25.ts - - npm run ts-node -- ./demo/demo26.ts - - npm run ts-node -- ./demo/demo27.ts - - npm run ts-node -- ./demo/demo28.ts - - npm run ts-node -- ./demo/demo29.ts - - npm run ts-node -- ./demo/demo30.ts - - npm run ts-node -- ./demo/demo31.ts - - npm run ts-node -- ./demo/demo32.ts + - npm run ts-node -- ./demo/26-paragraph-borders.ts + - npm run ts-node -- ./demo/27-declaritive-styles-3.ts + - npm run ts-node -- ./demo/28-table-of-contents.ts + - npm run ts-node -- ./demo/29-numbered-lists.ts + - npm run ts-node -- ./demo/30-template-document.ts + - npm run ts-node -- ./demo/31-tables.ts + - npm run ts-node -- ./demo/32-merge-table-cells.ts # - npm run e2e "My Document.docx" // Need to fix - - npm run ts-node -- ./demo/demo33.ts - - npm run ts-node -- ./demo/demo34.ts + - npm run ts-node -- ./demo/33-sequential-captions.ts + - npm run ts-node -- ./demo/34-floating-tables.ts after_failure: - "cat /home/travis/builds/dolanmiu/docx/npm-debug.log" after_success: From d8b60d82f33b64b2c3223ee670713fe4f7d7517f Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 7 Aug 2019 22:12:14 +0100 Subject: [PATCH 30/38] Turn Packer static --- demo/1-basic.ts | 4 +-- demo/10-my-cv.ts | 4 +-- demo/11-declaritive-styles-2.ts | 4 +-- demo/12-scaling-images.ts | 4 +-- demo/13-xml-styles.ts | 4 +-- demo/14-page-numbers.ts | 4 +-- demo/15-page-break-before.ts | 4 +-- demo/16-multiple-sections.ts | 4 +-- demo/17-footnotes.ts | 4 +-- demo/18-image-from-buffer.ts | 4 +-- demo/19-export-to-base64.ts | 4 +-- demo/2-declaritive-styles.ts | 4 +-- demo/20-table-cell-borders.ts | 4 +-- demo/21-bookmarks.ts | 4 +-- demo/22-right-to-left-text.ts | 4 +-- demo/23-base64-images.ts | 4 +-- demo/24-images-to-table-cell.ts | 4 +-- demo/26-paragraph-borders.ts | 4 +-- demo/27-declaritive-styles-3.ts | 4 +-- demo/28-table-of-contents.ts | 5 +-- demo/29-numbered-lists.ts | 4 +-- demo/3-numbering-and-bullet-points.ts | 4 +-- demo/30-template-document.ts | 3 +- demo/31-tables.ts | 4 +-- demo/32-merge-table-cells.ts | 4 +-- demo/33-sequential-captions.ts | 4 +-- demo/34-floating-tables.ts | 4 +-- demo/35-hyperlinks.ts | 4 +-- demo/36-image-to-table-cell.ts | 4 +-- demo/37-images-to-header-and-footer.ts | 4 +-- demo/38-text-wrapping.ts | 4 +-- demo/39-page-numbers.ts | 4 +-- demo/4-basic-table.ts | 4 +-- demo/40-line-numbers.ts | 4 +-- demo/41-merge-table-cells-2.ts | 4 +-- demo/43-images-to-table-cell-2.ts | 4 +-- demo/44-multiple-columns.ts | 4 +-- demo/45-highlighting-text.ts | 4 +-- demo/46-shading-text.ts | 4 +-- demo/5-images.ts | 4 +-- demo/6-page-borders.ts | 4 +-- demo/7-landscape.ts | 4 +-- demo/8-header-footer.ts | 4 +-- demo/9-images-in-header-and-footer.ts | 4 +-- demo/browser-demo.html | 4 +-- docs/README.md | 4 +-- docs/usage/packers.md | 37 ++++++++++++++++++++++- docs/usage/styling-with-js.md | 3 +- src/export/packer/next-compiler.ts | 42 ++++++++++++-------------- src/export/packer/packer.spec.ts | 15 ++++----- src/export/packer/packer.ts | 20 +++++------- 51 files changed, 118 insertions(+), 183 deletions(-) diff --git a/demo/1-basic.ts b/demo/1-basic.ts index 2787c869d7..7db8870259 100644 --- a/demo/1-basic.ts +++ b/demo/1-basic.ts @@ -24,8 +24,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/10-my-cv.ts b/demo/10-my-cv.ts index f7a89a0512..6c60be4f48 100644 --- a/demo/10-my-cv.ts +++ b/demo/10-my-cv.ts @@ -336,8 +336,6 @@ const documentCreator = new DocumentCreator(); const doc = documentCreator.create([experiences, education, skills, achievements]); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/11-declaritive-styles-2.ts b/demo/11-declaritive-styles-2.ts index e286ed7556..bb6428d518 100644 --- a/demo/11-declaritive-styles-2.ts +++ b/demo/11-declaritive-styles-2.ts @@ -163,8 +163,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/12-scaling-images.ts b/demo/12-scaling-images.ts index 2de556a262..6de5f49b92 100644 --- a/demo/12-scaling-images.ts +++ b/demo/12-scaling-images.ts @@ -14,8 +14,6 @@ doc.addSection({ children: [new Paragraph("Hello World"), new Paragraph(image), new Paragraph(image2), new Paragraph(image3), new Paragraph(image4)], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/13-xml-styles.ts b/demo/13-xml-styles.ts index 9d84777f68..1a4f60c24a 100644 --- a/demo/13-xml-styles.ts +++ b/demo/13-xml-styles.ts @@ -27,8 +27,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/14-page-numbers.ts b/demo/14-page-numbers.ts index f8e024547c..fc9a20169d 100644 --- a/demo/14-page-numbers.ts +++ b/demo/14-page-numbers.ts @@ -32,8 +32,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/15-page-break-before.ts b/demo/15-page-break-before.ts index 73ab48680e..bfb56fd7dd 100644 --- a/demo/15-page-break-before.ts +++ b/demo/15-page-break-before.ts @@ -15,8 +15,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/16-multiple-sections.ts b/demo/16-multiple-sections.ts index ede5e4058e..10e2098704 100644 --- a/demo/16-multiple-sections.ts +++ b/demo/16-multiple-sections.ts @@ -107,8 +107,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/17-footnotes.ts b/demo/17-footnotes.ts index e316ea4edb..3920d0dce8 100644 --- a/demo/17-footnotes.ts +++ b/demo/17-footnotes.ts @@ -12,8 +12,6 @@ doc.addSection({ doc.createFootnote(new Paragraph("Test")); doc.createFootnote(new Paragraph("My amazing reference")); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/18-image-from-buffer.ts b/demo/18-image-from-buffer.ts index 7eefdc4328..146b1b421f 100644 --- a/demo/18-image-from-buffer.ts +++ b/demo/18-image-from-buffer.ts @@ -17,8 +17,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/19-export-to-base64.ts b/demo/19-export-to-base64.ts index 84991cc929..676d844c8d 100644 --- a/demo/19-export-to-base64.ts +++ b/demo/19-export-to-base64.ts @@ -23,8 +23,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBase64String(doc).then((str) => { +Packer.toBase64String(doc).then((str) => { fs.writeFileSync("My Document.docx", str); }); diff --git a/demo/2-declaritive-styles.ts b/demo/2-declaritive-styles.ts index 3397f41ee8..a854b04546 100644 --- a/demo/2-declaritive-styles.ts +++ b/demo/2-declaritive-styles.ts @@ -117,8 +117,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/20-table-cell-borders.ts b/demo/20-table-cell-borders.ts index ee2b7918e2..13809a6164 100644 --- a/demo/20-table-cell-borders.ts +++ b/demo/20-table-cell-borders.ts @@ -19,8 +19,6 @@ table .addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green") .addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/21-bookmarks.ts b/demo/21-bookmarks.ts index 1193ee01c0..7a8e7b523b 100644 --- a/demo/21-bookmarks.ts +++ b/demo/21-bookmarks.ts @@ -30,8 +30,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/22-right-to-left-text.ts b/demo/22-right-to-left-text.ts index 3a70c01d21..2c3984fb46 100644 --- a/demo/22-right-to-left-text.ts +++ b/demo/22-right-to-left-text.ts @@ -39,8 +39,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/23-base64-images.ts b/demo/23-base64-images.ts index 5333d91e9b..c927ba45ef 100644 --- a/demo/23-base64-images.ts +++ b/demo/23-base64-images.ts @@ -27,8 +27,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/24-images-to-table-cell.ts b/demo/24-images-to-table-cell.ts index 2ea6f664c3..114be5491e 100644 --- a/demo/24-images-to-table-cell.ts +++ b/demo/24-images-to-table-cell.ts @@ -19,8 +19,6 @@ table.getCell(2, 2).add(new Paragraph("Hello")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); table.getCell(1, 1).add(new Paragraph(image)); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/26-paragraph-borders.ts b/demo/26-paragraph-borders.ts index 421d8477e5..40057d756a 100644 --- a/demo/26-paragraph-borders.ts +++ b/demo/26-paragraph-borders.ts @@ -28,8 +28,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/27-declaritive-styles-3.ts b/demo/27-declaritive-styles-3.ts index a31ce0b44b..31994dfe4a 100644 --- a/demo/27-declaritive-styles-3.ts +++ b/demo/27-declaritive-styles-3.ts @@ -37,8 +37,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/28-table-of-contents.ts b/demo/28-table-of-contents.ts index 414c2ad97d..83160b0177 100644 --- a/demo/28-table-of-contents.ts +++ b/demo/28-table-of-contents.ts @@ -48,12 +48,9 @@ doc.addSection({ style: "MySpectacularStyle", pageBreakBefore: true, }), - ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/29-numbered-lists.ts b/demo/29-numbered-lists.ts index 31dcd6d28f..740320e5f8 100644 --- a/demo/29-numbered-lists.ts +++ b/demo/29-numbered-lists.ts @@ -61,8 +61,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/3-numbering-and-bullet-points.ts b/demo/3-numbering-and-bullet-points.ts index 79545c75ec..94d5665568 100644 --- a/demo/3-numbering-and-bullet-points.ts +++ b/demo/3-numbering-and-bullet-points.ts @@ -71,8 +71,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/30-template-document.ts b/demo/30-template-document.ts index e9ebfd5c2b..3b3c724b5c 100644 --- a/demo/30-template-document.ts +++ b/demo/30-template-document.ts @@ -23,8 +23,7 @@ fs.readFile(filePath, (err, data) => { children: [new Paragraph("Hello World")], }); - const packer = new Packer(); - packer.toBuffer(doc).then((buffer) => { + Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); }); diff --git a/demo/31-tables.ts b/demo/31-tables.ts index d3e4cd3a8a..050403bb99 100644 --- a/demo/31-tables.ts +++ b/demo/31-tables.ts @@ -27,8 +27,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/32-merge-table-cells.ts b/demo/32-merge-table-cells.ts index 8526dc4916..cd850067e5 100644 --- a/demo/32-merge-table-cells.ts +++ b/demo/32-merge-table-cells.ts @@ -108,8 +108,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/33-sequential-captions.ts b/demo/33-sequential-captions.ts index bf0913d6f1..c06c3aa1cc 100644 --- a/demo/33-sequential-captions.ts +++ b/demo/33-sequential-captions.ts @@ -26,8 +26,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/34-floating-tables.ts b/demo/34-floating-tables.ts index c24246b709..c5b8a18cf8 100644 --- a/demo/34-floating-tables.ts +++ b/demo/34-floating-tables.ts @@ -36,8 +36,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/35-hyperlinks.ts b/demo/35-hyperlinks.ts index 41117a6a51..c547d93b36 100644 --- a/demo/35-hyperlinks.ts +++ b/demo/35-hyperlinks.ts @@ -12,8 +12,6 @@ doc.addSection({ children: [paragraph], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/36-image-to-table-cell.ts b/demo/36-image-to-table-cell.ts index 689a07a997..1c7897c558 100644 --- a/demo/36-image-to-table-cell.ts +++ b/demo/36-image-to-table-cell.ts @@ -22,8 +22,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/37-images-to-header-and-footer.ts b/demo/37-images-to-header-and-footer.ts index 08c4e547f5..86a8a20218 100644 --- a/demo/37-images-to-header-and-footer.ts +++ b/demo/37-images-to-header-and-footer.ts @@ -17,8 +17,6 @@ doc.addSection({ children: [new Paragraph("Hello World")], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/38-text-wrapping.ts b/demo/38-text-wrapping.ts index 84eb162fa5..9dac048e52 100644 --- a/demo/38-text-wrapping.ts +++ b/demo/38-text-wrapping.ts @@ -40,8 +40,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/39-page-numbers.ts b/demo/39-page-numbers.ts index 811115b876..edc9c411f9 100644 --- a/demo/39-page-numbers.ts +++ b/demo/39-page-numbers.ts @@ -40,8 +40,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/4-basic-table.ts b/demo/4-basic-table.ts index 48bcca1c0a..78367caab9 100644 --- a/demo/4-basic-table.ts +++ b/demo/4-basic-table.ts @@ -16,8 +16,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/40-line-numbers.ts b/demo/40-line-numbers.ts index f3bef349ec..d8da6f3074 100644 --- a/demo/40-line-numbers.ts +++ b/demo/40-line-numbers.ts @@ -24,8 +24,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/41-merge-table-cells-2.ts b/demo/41-merge-table-cells-2.ts index 2d3609fe5d..1801eb4a6e 100644 --- a/demo/41-merge-table-cells-2.ts +++ b/demo/41-merge-table-cells-2.ts @@ -49,8 +49,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/43-images-to-table-cell-2.ts b/demo/43-images-to-table-cell-2.ts index 06806d5780..90d6322bb7 100644 --- a/demo/43-images-to-table-cell-2.ts +++ b/demo/43-images-to-table-cell-2.ts @@ -17,8 +17,6 @@ doc.addSection({ children: [table], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/44-multiple-columns.ts b/demo/44-multiple-columns.ts index 83fbcf9efe..3fdf328461 100644 --- a/demo/44-multiple-columns.ts +++ b/demo/44-multiple-columns.ts @@ -35,8 +35,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/45-highlighting-text.ts b/demo/45-highlighting-text.ts index 0e2b416f33..d33a99fb94 100644 --- a/demo/45-highlighting-text.ts +++ b/demo/45-highlighting-text.ts @@ -30,8 +30,6 @@ doc.addSection({ children: [], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/46-shading-text.ts b/demo/46-shading-text.ts index 5e0b816a63..61f3f3d984 100644 --- a/demo/46-shading-text.ts +++ b/demo/46-shading-text.ts @@ -34,8 +34,6 @@ doc.addSection({ children: [], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/5-images.ts b/demo/5-images.ts index 0102998570..260fd25f15 100644 --- a/demo/5-images.ts +++ b/demo/5-images.ts @@ -57,8 +57,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/6-page-borders.ts b/demo/6-page-borders.ts index 47cca9c5f6..d54aac9a94 100644 --- a/demo/6-page-borders.ts +++ b/demo/6-page-borders.ts @@ -35,8 +35,6 @@ doc.addSection({ ], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/7-landscape.ts b/demo/7-landscape.ts index 2b171dea2f..fa3e551728 100644 --- a/demo/7-landscape.ts +++ b/demo/7-landscape.ts @@ -12,8 +12,6 @@ doc.addSection({ children: [new Paragraph("Hello World")], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/8-header-footer.ts b/demo/8-header-footer.ts index 012a4a7bf5..6455d94390 100644 --- a/demo/8-header-footer.ts +++ b/demo/8-header-footer.ts @@ -19,8 +19,6 @@ doc.addSection({ children: [new Paragraph("Hello World")], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/9-images-in-header-and-footer.ts b/demo/9-images-in-header-and-footer.ts index eb81879223..75acd4f07f 100644 --- a/demo/9-images-in-header-and-footer.ts +++ b/demo/9-images-in-header-and-footer.ts @@ -30,8 +30,6 @@ doc.addSection({ children: [new Paragraph("Hello World")], }); -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/demo/browser-demo.html b/demo/browser-demo.html index a199c1b4e8..22c7c821a5 100644 --- a/demo/browser-demo.html +++ b/demo/browser-demo.html @@ -32,9 +32,9 @@ ], }); - const packer = new Packer(); - packer.toBlob(doc).then((blob) => { + + Packer.toBlob(doc).then((blob) => { console.log(blob); saveAs(blob, "example.docx"); console.log("Document created successfully"); diff --git a/docs/README.md b/docs/README.md index e8da69f267..089c133ac2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -59,9 +59,7 @@ doc.addSection({ }); // Used to export the file into a .docx file -const packer = new Packer(); - -packer.toBuffer(doc).then((buffer) => { +Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); diff --git a/docs/usage/packers.md b/docs/usage/packers.md index 274942b715..e9b3626015 100644 --- a/docs/usage/packers.md +++ b/docs/usage/packers.md @@ -2,9 +2,44 @@ > Packers are the way in which `docx` turns your code into `.docx` format. It is completely decoupled from the `docx.Document`. +Packers in `version 4` and above are now one single `Packer`. It works in both a node and browser environment (Angular etc). Now, the packer returns a `Buffer`, `Blob` or `base64 string`. It is up to you to take that and persist it with node's `fs`, send it down as a downloadable file, or anything else you wish. As of version 4, this library will not have options to export to PDF. + +## Version 5 + +Packers in `version 5` and above are now static methods on `Packer`. + +### Export as Buffer + +This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead. + +```ts +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); +``` + +### Export as a `base64` string + +```ts +Packer.toBase64String(doc).then((string) => { + console.log(string); +}); +``` + +### Export as Blob + +This is useful if you want to send it as an downloadable in a browser environment. + +```ts +Packer.toBlob(doc).then((blob) => { + // saveAs from FileSaver will download the file + saveAs(blob, "example.docx"); +}); +``` + ## Version 4 -Packers in `version 4` and above are now one single `Packer`. It works in both a node and browser environment (Angular etc). Now, the packer returns a `Buffer`, `Blob` or `base64 string`. It is up to you to take that and persist it with node's `fs`, send it down as a downloadable file, or anything else you wish. As of version 4, this library will not have options to export to PDF. +The `Packer` in `version 4` requires an instance of `Packer`, so be sure to `new` it. ### Export as Buffer diff --git a/docs/usage/styling-with-js.md b/docs/usage/styling-with-js.md index 74fcdffb93..c39e7a7f40 100644 --- a/docs/usage/styling-with-js.md +++ b/docs/usage/styling-with-js.md @@ -107,8 +107,7 @@ There are three parts to using custom styles with `docx`: 3. When you generate your document, make sure to pass the `styles` container to the `Packer`: ```ts - const packer = new Packer(doc, myStyles); - packer.pack(myOutStream); + Packer.pack(myOutStream); ``` **Note**: If you are using the `.headingX` or `.title` methods of paragraphs, you must make sure to define `HeadingX` or `Title` styles for these. Otherwise they'll show up unstyled :(. If you are using the `.bullet` or `.setNumbering` methods, you need to define a `ListParagraph` style or the numbers may not show up. diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index a2a09c3a8b..426d32174f 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -30,17 +30,15 @@ interface IXmlifyedFileMapping { export class Compiler { private readonly formatter: Formatter; private readonly imageReplacer: ImageReplacer; - private readonly prettifyXml?: boolean; - constructor(prettifyXml?: boolean) { + constructor() { this.formatter = new Formatter(); this.imageReplacer = new ImageReplacer(); - this.prettifyXml = prettifyXml; } - public compile(file: File): JSZip { + public compile(file: File, prettifyXml?: boolean): JSZip { const zip = new JSZip(); - const xmlifiedFileMapping = this.xmlifyFile(file); + const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml); for (const key in xmlifiedFileMapping) { if (!xmlifiedFileMapping[key]) { @@ -66,14 +64,14 @@ export class Compiler { return zip; } - private xmlifyFile(file: File): IXmlifyedFileMapping { + private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping { file.verifyUpdateFields(); const documentRelationshipCount = file.DocumentRelationships.RelationshipCount + 1; return { Relationships: { data: (() => { - const xmlData = xml(this.formatter.format(file.Document), this.prettifyXml); + const xmlData = xml(this.formatter.format(file.Document), prettify); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -84,13 +82,13 @@ export class Compiler { ); }); - return xml(this.formatter.format(file.DocumentRelationships), this.prettifyXml); + return xml(this.formatter.format(file.DocumentRelationships), prettify); })(), path: "word/_rels/document.xml.rels", }, Document: { data: (() => { - const tempXmlData = xml(this.formatter.format(file.Document), this.prettifyXml); + const tempXmlData = xml(this.formatter.format(file.Document), prettify); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, documentRelationshipCount); @@ -99,7 +97,7 @@ export class Compiler { path: "word/document.xml", }, Styles: { - data: xml(this.formatter.format(file.Styles), this.prettifyXml), + data: xml(this.formatter.format(file.Styles), prettify), path: "word/styles.xml", }, Properties: { @@ -112,15 +110,15 @@ export class Compiler { path: "docProps/core.xml", }, Numbering: { - data: xml(this.formatter.format(file.Numbering), this.prettifyXml), + data: xml(this.formatter.format(file.Numbering), prettify), path: "word/numbering.xml", }, FileRelationships: { - data: xml(this.formatter.format(file.FileRelationships), this.prettifyXml), + data: xml(this.formatter.format(file.FileRelationships), prettify), path: "_rels/.rels", }, HeaderRelationships: file.Headers.map((headerWrapper, index) => { - const xmlData = xml(this.formatter.format(headerWrapper.Header), this.prettifyXml); + const xmlData = xml(this.formatter.format(headerWrapper.Header), prettify); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -132,12 +130,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(headerWrapper.Relationships), this.prettifyXml), + data: xml(this.formatter.format(headerWrapper.Relationships), prettify), path: `word/_rels/header${index + 1}.xml.rels`, }; }), FooterRelationships: file.Footers.map((footerWrapper, index) => { - const xmlData = xml(this.formatter.format(footerWrapper.Footer), this.prettifyXml); + const xmlData = xml(this.formatter.format(footerWrapper.Footer), prettify); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -149,12 +147,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(footerWrapper.Relationships), this.prettifyXml), + data: xml(this.formatter.format(footerWrapper.Relationships), prettify), path: `word/_rels/footer${index + 1}.xml.rels`, }; }), Headers: file.Headers.map((headerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(headerWrapper.Header), this.prettifyXml); + const tempXmlData = xml(this.formatter.format(headerWrapper.Header), prettify); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -165,7 +163,7 @@ export class Compiler { }; }), Footers: file.Footers.map((footerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(footerWrapper.Footer), this.prettifyXml); + const tempXmlData = xml(this.formatter.format(footerWrapper.Footer), prettify); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -176,19 +174,19 @@ export class Compiler { }; }), ContentTypes: { - data: xml(this.formatter.format(file.ContentTypes), this.prettifyXml), + data: xml(this.formatter.format(file.ContentTypes), prettify), path: "[Content_Types].xml", }, AppProperties: { - data: xml(this.formatter.format(file.AppProperties), this.prettifyXml), + data: xml(this.formatter.format(file.AppProperties), prettify), path: "docProps/app.xml", }, FootNotes: { - data: xml(this.formatter.format(file.FootNotes), this.prettifyXml), + data: xml(this.formatter.format(file.FootNotes), prettify), path: "word/footnotes.xml", }, Settings: { - data: xml(this.formatter.format(file.Settings), this.prettifyXml), + data: xml(this.formatter.format(file.Settings), prettify), path: "word/settings.xml", }, }; diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index e2be5aca44..2bf8537bed 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -7,7 +7,6 @@ import { File, HeadingLevel, Paragraph } from "file"; import { Packer } from "./packer"; describe("Packer", () => { - let packer: Packer; let file: File; beforeEach(() => { @@ -34,14 +33,12 @@ describe("Packer", () => { new Paragraph("test text"), ], }); - - packer = new Packer(); }); describe("#toBuffer()", () => { it("should create a standard docx file", async function() { this.timeout(99999999); - const buffer = await packer.toBuffer(file); + const buffer = await Packer.toBuffer(file); assert.isDefined(buffer); assert.isTrue(buffer.byteLength > 0); @@ -49,10 +46,10 @@ describe("Packer", () => { it("should handle exception if it throws any", () => { // tslint:disable-next-line:no-any - const compiler = stub((packer as any).compiler, "compile"); + const compiler = stub((Packer as any).compiler, "compile"); compiler.throwsException(); - return packer.toBuffer(file).catch((error) => { + return Packer.toBuffer(file).catch((error) => { assert.isDefined(error); }); }); @@ -61,7 +58,7 @@ describe("Packer", () => { describe("#toBase64String()", () => { it("should create a standard docx file", async function() { this.timeout(99999999); - const str = await packer.toBase64String(file); + const str = await Packer.toBase64String(file); assert.isDefined(str); assert.isTrue(str.length > 0); @@ -69,10 +66,10 @@ describe("Packer", () => { it("should handle exception if it throws any", () => { // tslint:disable-next-line:no-any - const compiler = stub((packer as any).compiler, "compile"); + const compiler = stub((Packer as any).compiler, "compile"); compiler.throwsException(); - return packer.toBase64String(file).catch((error) => { + return Packer.toBase64String(file).catch((error) => { assert.isDefined(error); }); }); diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index a6c0f33cc4..c064836ed2 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -2,14 +2,8 @@ import { File } from "file"; import { Compiler } from "./next-compiler"; export class Packer { - private readonly compiler: Compiler; - - constructor(prettifyXml?: boolean) { - this.compiler = new Compiler(prettifyXml); - } - - public async toBuffer(file: File): Promise { - const zip = this.compiler.compile(file); + public static async toBuffer(file: File, prettify?: boolean): Promise { + const zip = this.compiler.compile(file, prettify); const zipData = (await zip.generateAsync({ type: "nodebuffer", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", @@ -18,8 +12,8 @@ export class Packer { return zipData; } - public async toBase64String(file: File): Promise { - const zip = this.compiler.compile(file); + public static async toBase64String(file: File, prettify?: boolean): Promise { + const zip = this.compiler.compile(file, prettify); const zipData = (await zip.generateAsync({ type: "base64", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", @@ -28,8 +22,8 @@ export class Packer { return zipData; } - public async toBlob(file: File): Promise { - const zip = this.compiler.compile(file); + public static async toBlob(file: File, prettify?: boolean): Promise { + const zip = this.compiler.compile(file, prettify); const zipData = (await zip.generateAsync({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", @@ -37,4 +31,6 @@ export class Packer { return zipData; } + + private static readonly compiler = new Compiler(); } From 9fdd07e7fe0da01d2f6ff442c0533100e8eb5aac Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 7 Aug 2019 22:27:44 +0100 Subject: [PATCH 31/38] Fix tests --- src/export/packer/packer.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index 2bf8537bed..8235649f15 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -53,6 +53,11 @@ describe("Packer", () => { assert.isDefined(error); }); }); + + after(() => { + // tslint:disable-next-line:no-any + (Packer as any).compiler.compile.restore(); + }); }); describe("#toBase64String()", () => { @@ -73,5 +78,10 @@ describe("Packer", () => { assert.isDefined(error); }); }); + + after(() => { + // tslint:disable-next-line:no-any + (Packer as any).compiler.compile.restore(); + }); }); }); From e685da8cc2655621e09cbd6c16c3e95a695a1f57 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 8 Aug 2019 01:52:20 +0100 Subject: [PATCH 32/38] Add more Used by logos --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e359e3627e..6c65ca08bd 100644 --- a/README.md +++ b/README.md @@ -66,9 +66,13 @@ Read the contribution guidelines [here](https://docx.js.org/#/contribution-guide # Used by -[drawing](https://hfour.com/) -[drawing](https://fuzzproductions.com/) -[drawing](https://www.mettzer.com/) +[drawing](https://hfour.com/) +[drawing](https://fuzzproductions.com/) +[drawing](https://www.mettzer.com/) +[drawing](https://www.wisedoc.net/) +[drawing](https://www.dabblewriter.com/) +[drawing](https://turbopatent.com/) +[drawing](http://www.madisoncres.com/) --- From 183062a977d5f4552bbf60569752d500098b3ad4 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 8 Aug 2019 01:55:48 +0100 Subject: [PATCH 33/38] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6c65ca08bd..ad626056d2 100644 --- a/README.md +++ b/README.md @@ -66,13 +66,13 @@ Read the contribution guidelines [here](https://docx.js.org/#/contribution-guide # Used by -[drawing](https://hfour.com/) -[drawing](https://fuzzproductions.com/) -[drawing](https://www.mettzer.com/) -[drawing](https://www.wisedoc.net/) -[drawing](https://www.dabblewriter.com/) -[drawing](https://turbopatent.com/) -[drawing](http://www.madisoncres.com/) +[drawing](https://hfour.com/) +[drawing](https://fuzzproductions.com/) +[drawing](https://www.mettzer.com/) +[drawing](https://www.wisedoc.net/) +[drawing](https://www.dabblewriter.com/) +[drawing](https://turbopatent.com/) +[drawing](http://www.madisoncres.com/) --- From ad4a843a1e0a4941b87f6a044218391ea9e7764f Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 8 Aug 2019 01:56:31 +0100 Subject: [PATCH 34/38] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ad626056d2..7cb5c93879 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ Read the contribution guidelines [here](https://docx.js.org/#/contribution-guide [drawing](https://turbopatent.com/) [drawing](http://www.madisoncres.com/) +...and many more! + --- [![patreon][patreon-image]][patreon-url] From a54c2714dbf29f29ebeb249a5a44c42dc994bfaf Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 8 Aug 2019 02:01:22 +0100 Subject: [PATCH 35/38] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77750352d4..ea3be1ab15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx", - "version": "5.0.0-rc4", + "version": "5.0.0-rc5", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From fd52c8cf47a6be52f02297bb2b771d9369eb3ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pirsch?= Date: Thu, 8 Aug 2019 16:40:16 +0200 Subject: [PATCH 36/38] Enable zip compression --- src/export/packer/packer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index c064836ed2..e51abc9096 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -7,6 +7,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "nodebuffer", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + compression: 'DEFLATE' })) as Buffer; return zipData; @@ -17,6 +18,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "base64", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + compression: 'DEFLATE' })) as string; return zipData; @@ -27,6 +29,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + compression: 'DEFLATE' })) as Blob; return zipData; From 4b49fdbf8e2f5386e43a7fc74f129b2693b212da Mon Sep 17 00:00:00 2001 From: Dolan Date: Fri, 9 Aug 2019 00:19:44 +0100 Subject: [PATCH 37/38] Update packer.ts --- src/export/packer/packer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index e51abc9096..0dd9eeba9b 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -7,7 +7,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "nodebuffer", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: 'DEFLATE' + compression: "DEFLATE" })) as Buffer; return zipData; @@ -18,7 +18,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "base64", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: 'DEFLATE' + compression: "DEFLATE" })) as string; return zipData; @@ -29,7 +29,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: 'DEFLATE' + compression: "DEFLATE" })) as Blob; return zipData; From b609a17362fdf4d543668c2e1fa66fcba517d533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pirsch?= Date: Fri, 9 Aug 2019 09:41:58 +0200 Subject: [PATCH 38/38] Update packer.ts --- src/export/packer/packer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index 0dd9eeba9b..24c29491ce 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -7,7 +7,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "nodebuffer", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: "DEFLATE" + compression: "DEFLATE", })) as Buffer; return zipData; @@ -18,7 +18,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "base64", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: "DEFLATE" + compression: "DEFLATE", })) as string; return zipData; @@ -29,7 +29,7 @@ export class Packer { const zipData = (await zip.generateAsync({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - compression: "DEFLATE" + compression: "DEFLATE", })) as Blob; return zipData;