From 0411153832a01d7b2f5464f06fd0990005d02ea1 Mon Sep 17 00:00:00 2001 From: Noah Schechter Date: Sun, 19 Aug 2018 11:59:38 -0400 Subject: [PATCH 1/3] Added in the ability to create borders for paragraphs --- demo/demo10.js | 14 +++--- demo/demo26.js | 23 ++++++++++ src/file/paragraph/formatting/border.ts | 60 ++++++++++++++++++++----- src/file/paragraph/paragraph.ts | 6 ++- src/file/paragraph/properties.ts | 5 +++ 5 files changed, 89 insertions(+), 19 deletions(-) create mode 100644 demo/demo26.js diff --git a/demo/demo10.js b/demo/demo10.js index 2b986dbf65..3ffac93f32 100644 --- a/demo/demo10.js +++ b/demo/demo10.js @@ -135,7 +135,7 @@ class DocumentCreator { for (const education of educations) { document.addParagraph( - this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`), + this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`) ); document.addParagraph(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`)); @@ -151,8 +151,8 @@ class DocumentCreator { document.addParagraph( this.createInstitutionHeader( position.company.name, - this.createPositionDateText(position.startDate, position.endDate, position.isCurrent), - ), + this.createPositionDateText(position.startDate, position.endDate, position.isCurrent) + ) ); document.addParagraph(this.createRoleText(position.title)); @@ -182,14 +182,14 @@ class DocumentCreator { document.addParagraph( new docx.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", - ), + "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 docx.Paragraph("More references upon request")); document.addParagraph( new docx.Paragraph( - "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", - ).center(), + "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio." + ).center() ); return document; } diff --git a/demo/demo26.js b/demo/demo26.js new file mode 100644 index 0000000000..566c3ea419 --- /dev/null +++ b/demo/demo26.js @@ -0,0 +1,23 @@ +/* + * Creates two paragraphs, one with a border and one without + */ + +const docx = require("../build"); + +let doc = new docx.Document(); + +let paragraph = new docx.Paragraph("No border!"); + +doc.addParagraph(paragraph); + +let borderParagraph = new docx.Paragraph("I have a border on all but one side!"); +console.log(borderParagraph.Borders); +borderParagraph.Borders.addTopBorder(); +borderParagraph.Borders.addBottomBorder(); +borderParagraph.Borders.addLeftBorder(); +console.log(borderParagraph.Borders); + +doc.addParagraph(borderParagraph); + +let exporter = new docx.LocalPacker(doc); +exporter.packPdf('My Document'); \ No newline at end of file diff --git a/src/file/paragraph/formatting/border.ts b/src/file/paragraph/formatting/border.ts index 9ceb0c1336..5a07774024 100644 --- a/src/file/paragraph/formatting/border.ts +++ b/src/file/paragraph/formatting/border.ts @@ -1,23 +1,61 @@ // http://officeopenxml.com/WPborders.php import { Attributes, XmlComponent } from "file/xml-components"; -class Border extends XmlComponent { +class BorderProperty extends XmlComponent { + public setProperties(space: string, value: string, size: string): XmlComponent { + const attrs = new Attributes({ + space: space, + val: value, + sz: size + }); + this.root.push(attrs); + + return this; + } +} + +export class Border extends XmlComponent { constructor() { - super("w:bottom"); - this.root.push( - new Attributes({ - color: "auto", - space: "1", - val: "single", - sz: "6", - }), - ); + super("w:pBdr"); + } + + public addTopBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + const top = new BorderProperty("w:top"); + top.setProperties(space, value, size); + this.root.push(top); + + return this; + } + + public addBottomBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + const bottom = new BorderProperty("w:bottom"); + bottom.setProperties(space, value, size); + this.root.push(bottom); + + return this; + } + + public addLeftBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + const left = new BorderProperty("w:left"); + left.setProperties(space, value, size); + this.root.push(left); + + return this; + } + + public addRightBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + const right = new BorderProperty("w:right"); + right.setProperties(space, value, size); + this.root.push(right); + + return this; } } export class ThematicBreak extends XmlComponent { constructor() { super("w:pBdr"); - this.root.push(new Border()); + const bottom = new BorderProperty("w:bottom"); + this.root.push(bottom); } } diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index b21e2c3ac0..45693f3cf5 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -6,7 +6,7 @@ import { XmlComponent } from "file/xml-components"; import { Alignment } from "./formatting/alignment"; import { Bidirectional } from "./formatting/bidirectional"; -import { ThematicBreak } from "./formatting/border"; +import { ThematicBreak, Border } from "./formatting/border"; import { Indent } from "./formatting/indent"; import { KeepLines, KeepNext } from "./formatting/keep"; import { PageBreak, PageBreakBefore } from "./formatting/page-break"; @@ -30,6 +30,10 @@ export class Paragraph extends XmlComponent { } } + public get Borders(): Border { + return this.properties.paragraphBorder; + } + public addRun(run: Run): Paragraph { this.root.push(run); return this; diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts index 93fba4ce31..a006c40d27 100644 --- a/src/file/paragraph/properties.ts +++ b/src/file/paragraph/properties.ts @@ -1,9 +1,14 @@ // http://officeopenxml.com/WPparagraphProperties.php import { XmlComponent } from "file/xml-components"; +import { Border } from "./formatting/border"; export class ParagraphProperties extends XmlComponent { + public paragraphBorder: Border; + constructor() { super("w:pPr"); + this.paragraphBorder = new Border(); + this.push(this.paragraphBorder); } public push(item: XmlComponent): void { From e97c432a64a3b3618dd0342b6d6643195adfd519 Mon Sep 17 00:00:00 2001 From: Noah Schechter Date: Sun, 19 Aug 2018 19:37:36 -0400 Subject: [PATCH 2/3] added border specs, createBorder method, and color attribute to setProperties --- demo/demo26.js | 7 ++-- src/file/paragraph/formatting/border.ts | 22 ++++++------ src/file/paragraph/paragraph.spec.ts | 45 +++++++++++++++++++++++++ src/file/paragraph/paragraph.ts | 7 +++- src/file/paragraph/properties.ts | 5 ++- 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/demo/demo26.js b/demo/demo26.js index 566c3ea419..e88469c48b 100644 --- a/demo/demo26.js +++ b/demo/demo26.js @@ -10,14 +10,11 @@ let paragraph = new docx.Paragraph("No border!"); doc.addParagraph(paragraph); -let borderParagraph = new docx.Paragraph("I have a border on all but one side!"); -console.log(borderParagraph.Borders); +let borderParagraph = new docx.Paragraph("I have borders on my top and bottom sides!").createBorder(); borderParagraph.Borders.addTopBorder(); borderParagraph.Borders.addBottomBorder(); -borderParagraph.Borders.addLeftBorder(); -console.log(borderParagraph.Borders); doc.addParagraph(borderParagraph); let exporter = new docx.LocalPacker(doc); -exporter.packPdf('My Document'); \ No newline at end of file +exporter.pack('My Document'); \ No newline at end of file diff --git a/src/file/paragraph/formatting/border.ts b/src/file/paragraph/formatting/border.ts index 5a07774024..f37854a3c7 100644 --- a/src/file/paragraph/formatting/border.ts +++ b/src/file/paragraph/formatting/border.ts @@ -2,11 +2,12 @@ import { Attributes, XmlComponent } from "file/xml-components"; class BorderProperty extends XmlComponent { - public setProperties(space: string, value: string, size: string): XmlComponent { + public setProperties(color: string, space: string, value: string, size: string): XmlComponent { const attrs = new Attributes({ + color: color, space: space, val: value, - sz: size + sz: size, }); this.root.push(attrs); @@ -19,33 +20,33 @@ export class Border extends XmlComponent { super("w:pBdr"); } - public addTopBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + public addTopBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { const top = new BorderProperty("w:top"); - top.setProperties(space, value, size); + top.setProperties(color, space, value, size); this.root.push(top); return this; } - public addBottomBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + public addBottomBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { const bottom = new BorderProperty("w:bottom"); - bottom.setProperties(space, value, size); + bottom.setProperties(color, space, value, size); this.root.push(bottom); return this; } - public addLeftBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + public addLeftBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { const left = new BorderProperty("w:left"); - left.setProperties(space, value, size); + left.setProperties(color, space, value, size); this.root.push(left); return this; } - public addRightBorder(space: string = "1", value: string = "single", size: string = "6"): XmlComponent { + public addRightBorder(color: string = "auto", space: string = "1", value: string = "single", size: string = "6"): XmlComponent { const right = new BorderProperty("w:right"); - right.setProperties(space, value, size); + right.setProperties(color, space, value, size); this.root.push(right); return this; @@ -56,6 +57,7 @@ export class ThematicBreak extends XmlComponent { constructor() { super("w:pBdr"); const bottom = new BorderProperty("w:bottom"); + bottom.setProperties("auto", "1", "single", "6"); this.root.push(bottom); } } diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index e00fa6167c..2413769b1e 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -144,6 +144,51 @@ describe("Paragraph", () => { }); }); + describe("#paragraphBorders()", () => { + it("should add a left and right border to a paragraph", () => { + paragraph.createBorder(); + paragraph.Borders.addLeftBorder(); + paragraph.Borders.addRightBorder(); + const tree = new Formatter().format(paragraph); + expect(tree).to.deep.equal({ + "w:p": [ + { + "w:pPr": [ + { + "w:pBdr": [ + { + "w:left": [ + { + _attr: { + "w:color": "auto", + "w:space": "1", + "w:sz": "6", + "w:val": "single", + }, + }, + ], + }, + { + "w:right": [ + { + _attr: { + "w:color": "auto", + "w:space": "1", + "w:sz": "6", + "w:val": "single", + }, + }, + ], + }, + ], + }, + ], + }, + ], + }); + }); + }); + describe("#pageBreak()", () => { it("should add page break to JSON", () => { paragraph.pageBreak(); diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 45693f3cf5..70b8ea9064 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -6,7 +6,7 @@ import { XmlComponent } from "file/xml-components"; import { Alignment } from "./formatting/alignment"; import { Bidirectional } from "./formatting/bidirectional"; -import { ThematicBreak, Border } from "./formatting/border"; +import { Border, ThematicBreak } from "./formatting/border"; import { Indent } from "./formatting/indent"; import { KeepLines, KeepNext } from "./formatting/keep"; import { PageBreak, PageBreakBefore } from "./formatting/page-break"; @@ -34,6 +34,11 @@ export class Paragraph extends XmlComponent { return this.properties.paragraphBorder; } + public createBorder(): Paragraph { + this.properties.createBorder(); + return this; + } + public addRun(run: Run): Paragraph { this.root.push(run); return this; diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts index a006c40d27..5f0c651246 100644 --- a/src/file/paragraph/properties.ts +++ b/src/file/paragraph/properties.ts @@ -4,10 +4,13 @@ import { Border } from "./formatting/border"; export class ParagraphProperties extends XmlComponent { public paragraphBorder: Border; - + constructor() { super("w:pPr"); this.paragraphBorder = new Border(); + } + + public createBorder(): void { this.push(this.paragraphBorder); } From 9a6c92222c7055906a0166164559c404abefd794 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 22 Aug 2018 00:51:18 +0100 Subject: [PATCH 3/3] Change demo26 to typescript --- demo/demo26.js | 20 -------------------- demo/demo26.ts | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 20 deletions(-) delete mode 100644 demo/demo26.js create mode 100644 demo/demo26.ts diff --git a/demo/demo26.js b/demo/demo26.js deleted file mode 100644 index e88469c48b..0000000000 --- a/demo/demo26.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Creates two paragraphs, one with a border and one without - */ - -const docx = require("../build"); - -let doc = new docx.Document(); - -let paragraph = new docx.Paragraph("No border!"); - -doc.addParagraph(paragraph); - -let borderParagraph = new docx.Paragraph("I have borders on my top and bottom sides!").createBorder(); -borderParagraph.Borders.addTopBorder(); -borderParagraph.Borders.addBottomBorder(); - -doc.addParagraph(borderParagraph); - -let exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); \ No newline at end of file diff --git a/demo/demo26.ts b/demo/demo26.ts new file mode 100644 index 0000000000..9fa560d260 --- /dev/null +++ b/demo/demo26.ts @@ -0,0 +1,22 @@ +// Creates two paragraphs, one with a border and one without +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph } from "../build"; + +const doc = new Document(); + +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(); + +doc.addParagraph(borderParagraph); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +});