From c99b2940c612021497fbe6e77bff98f8aa83449f Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 24 Apr 2018 21:12:09 +0100 Subject: [PATCH 01/63] Add next gen compiler using JSZip --- demo/demo13.js | 16 ++++ package.json | 2 + src/export/packer/local.ts | 31 +++++--- src/export/packer/next-compiler.ts | 117 +++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 demo/demo13.js create mode 100644 src/export/packer/next-compiler.ts diff --git a/demo/demo13.js b/demo/demo13.js new file mode 100644 index 0000000000..b68348b1c8 --- /dev/null +++ b/demo/demo13.js @@ -0,0 +1,16 @@ +const docx = require('../build'); + +var doc = new docx.Document(); + +var paragraph = new docx.Paragraph("Hello World"); +var institutionText = new docx.TextRun("University College London").bold(); +var dateText = new docx.TextRun("5th Dec 2015").tab().bold(); +paragraph.addRun(institutionText); +paragraph.addRun(dateText); + +doc.addParagraph(paragraph); + +var exporter = new docx.LocalPacker(doc); +exporter.packPdf('My Document'); + +console.log('Document created successfully at project root!'); diff --git a/package.json b/package.json index 74e591431c..99104a157d 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,11 @@ "@types/archiver": "^2.1.0", "@types/express": "^4.0.35", "@types/image-size": "0.0.29", + "@types/jszip": "^3.1.3", "@types/request-promise": "^4.1.41", "archiver": "^2.1.1", "image-size": "^0.6.2", + "jszip": "^3.1.5", "request": "^2.83.0", "request-promise": "^4.2.2", "xml": "^1.0.1" diff --git a/src/export/packer/local.ts b/src/export/packer/local.ts index 5d0c05fe81..1ebf8787ec 100644 --- a/src/export/packer/local.ts +++ b/src/export/packer/local.ts @@ -3,12 +3,11 @@ import * as os from "os"; import * as path from "path"; import { File } from "../../file"; -import { Compiler } from "./compiler"; +import { Compiler } from "./next-compiler"; import { IPacker } from "./packer"; import { PdfConvertWrapper } from "./pdf-convert-wrapper"; export class LocalPacker implements IPacker { - private stream: fs.WriteStream; private readonly pdfConverter: PdfConvertWrapper; private readonly packer: Compiler; @@ -20,8 +19,8 @@ export class LocalPacker implements IPacker { public async pack(filePath: string): Promise { filePath = filePath.replace(/.docx$/, ""); - this.stream = fs.createWriteStream(`${filePath}.docx`); - await this.packer.compile(this.stream); + const zipData = await this.packer.compile().generateAsync({ type: "base64" }) as string; + await this.writeToFile(`${filePath}.docx`, zipData); } public async packPdf(filePath: string): Promise { @@ -29,19 +28,27 @@ export class LocalPacker implements IPacker { const fileName = path.basename(filePath, path.extname(filePath)); const tempPath = path.join(os.tmpdir(), `${fileName}.docx`); - this.stream = fs.createWriteStream(tempPath); - await this.packer.compile(this.stream); + + const zipData = await this.packer.compile().generateAsync({ type: "base64" }) as string; + await this.writeToFile(tempPath, zipData); + const text = await this.pdfConverter.convert(tempPath); // const writeFile = util.promisify(fs.writeFile); --use this in future, in 3 years time. Only in node 8 // return writeFile(`${filePath}.pdf`, text); - return new Promise((resolve, reject) => { - fs.writeFile(`${filePath}.pdf`, text, (err) => { - if (err) { - reject(err); - return; - } + + await this.writeToFile(`${filePath}.pdf`, text); + } + + private writeToFile(filePath: string, data: string): Promise { + const file = fs.createWriteStream(filePath); + + return new Promise((resolve, reject) => { + file.write(data, "base64"); + file.end(); + file.on("finish", () => { resolve(); }); + file.on("error", reject); }); } } diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts new file mode 100644 index 0000000000..baecd72ae7 --- /dev/null +++ b/src/export/packer/next-compiler.ts @@ -0,0 +1,117 @@ +import * as JSZip from "jszip"; +import * as xml from "xml"; + +import { File } from "file"; +import { Formatter } from "../formatter"; + +interface IXmlifyedFile { + data: string; + path: string; +} + +interface IXmlifyedFileMapping { + Document: IXmlifyedFile; + Styles: IXmlifyedFile; + Properties: IXmlifyedFile; + Numbering: IXmlifyedFile; + Relationships: IXmlifyedFile; + FileRelationships: IXmlifyedFile; + Header: IXmlifyedFile; + Footer: IXmlifyedFile; + HeaderRelationships: IXmlifyedFile; + FooterRelationships: IXmlifyedFile; + ContentTypes: IXmlifyedFile; + AppProperties: IXmlifyedFile; +} + +export class Compiler { + private formatter: Formatter; + + constructor(private file: File) { + this.formatter = new Formatter(); + } + + public compile(): JSZip { + const zip = new JSZip(); + + const xmlifiedFileMapping = this.xmlifyFile(this.file); + + for (const key in xmlifiedFileMapping) { + if (!xmlifiedFileMapping[key]) { + continue; + } + + const xmlifiedFile = xmlifiedFileMapping[key]; + + zip.file(xmlifiedFile.path, xmlifiedFile.data); + } + + // for (const data of file.Media.array) { + // this.archive.append(data.stream, { + // name: `word/media/${data.fileName}`, + // }); + + // zip.file(`word/media/${data.fileName}`, ) + // } + + return zip; + } + + private xmlifyFile(file: File): IXmlifyedFileMapping { + return { + Document: { + data: xml(this.formatter.format(file.Document), true), + path: "word/document.xml", + }, + Styles: { + data: xml(this.formatter.format(file.Styles)), + path: "word/styles.xml", + }, + Properties: { + data: xml(this.formatter.format(file.CoreProperties), { + declaration: { + standalone: "yes", + encoding: "UTF-8", + }, + }), + path: "docProps/core.xml", + }, + Numbering: { + data: xml(this.formatter.format(file.Numbering)), + path: "word/numbering.xml", + }, + Relationships: { + data: xml(this.formatter.format(file.DocumentRelationships)), + path: "word/_rels/document.xml.rels", + }, + FileRelationships: { + data: xml(this.formatter.format(file.FileRelationships)), + path: "_rels/.rels", + }, + Header: { + data: xml(this.formatter.format(file.Header.Header)), + path: "word/header1.xml", + }, + Footer: { + data: xml(this.formatter.format(file.Footer.Footer)), + path: "word/footer1.xml", + }, + HeaderRelationships: { + data: xml(this.formatter.format(file.Header.Relationships)), + path: "word/_rels/header1.xml.rels", + }, + FooterRelationships: { + data: xml(this.formatter.format(file.Footer.Relationships)), + path: "word/_rels/footer1.xml.rels", + }, + ContentTypes: { + data: xml(this.formatter.format(file.ContentTypes)), + path: "[Content_Types].xml", + }, + AppProperties: { + data: xml(this.formatter.format(file.AppProperties)), + path: "docProps/app.xml", + }, + }; + } +} From 06418655c0f24b85958d9f5bf28136e9e9eebf8e Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 24 Apr 2018 22:35:31 +0100 Subject: [PATCH 02/63] Add image support to new packer --- demo/demo13.js | 5 +++-- src/export/packer/local.ts | 7 +++++-- src/export/packer/next-compiler.ts | 27 +++++++++++++++++++-------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/demo/demo13.js b/demo/demo13.js index b68348b1c8..6ce1ddd04e 100644 --- a/demo/demo13.js +++ b/demo/demo13.js @@ -11,6 +11,7 @@ paragraph.addRun(dateText); doc.addParagraph(paragraph); var exporter = new docx.LocalPacker(doc); -exporter.packPdf('My Document'); +exporter.packPdf('My Document').then(() => { + console.log('Document created successfully at project root!'); +}); -console.log('Document created successfully at project root!'); diff --git a/src/export/packer/local.ts b/src/export/packer/local.ts index 1ebf8787ec..27bba0ae69 100644 --- a/src/export/packer/local.ts +++ b/src/export/packer/local.ts @@ -19,7 +19,9 @@ export class LocalPacker implements IPacker { public async pack(filePath: string): Promise { filePath = filePath.replace(/.docx$/, ""); - const zipData = await this.packer.compile().generateAsync({ type: "base64" }) as string; + const zip = await this.packer.compile(); + const zipData = await zip.generateAsync({ type: "base64" }) as string; + await this.writeToFile(`${filePath}.docx`, zipData); } @@ -29,7 +31,8 @@ export class LocalPacker implements IPacker { const fileName = path.basename(filePath, path.extname(filePath)); const tempPath = path.join(os.tmpdir(), `${fileName}.docx`); - const zipData = await this.packer.compile().generateAsync({ type: "base64" }) as string; + const zip = await this.packer.compile(); + const zipData = await zip.generateAsync({ type: "base64" }) as string; await this.writeToFile(tempPath, zipData); const text = await this.pdfConverter.convert(tempPath); diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index baecd72ae7..b8ddaf2b82 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -1,3 +1,4 @@ +import * as fs from "fs"; import * as JSZip from "jszip"; import * as xml from "xml"; @@ -31,7 +32,7 @@ export class Compiler { this.formatter = new Formatter(); } - public compile(): JSZip { + public async compile(): Promise { const zip = new JSZip(); const xmlifiedFileMapping = this.xmlifyFile(this.file); @@ -46,13 +47,10 @@ export class Compiler { zip.file(xmlifiedFile.path, xmlifiedFile.data); } - // for (const data of file.Media.array) { - // this.archive.append(data.stream, { - // name: `word/media/${data.fileName}`, - // }); - - // zip.file(`word/media/${data.fileName}`, ) - // } + for (const data of this.file.Media.array) { + const mediaData = await this.readFile(data.path); + zip.file(`word/media/${data.fileName}`, mediaData); + } return zip; } @@ -114,4 +112,17 @@ export class Compiler { }, }; } + + private readFile(path: string): Promise { + return new Promise((resolve, reject) => { + fs.readFile(path, (err, data) => { + if (err) { + reject(); + return; + } + + resolve(data); + }); + }); + } } From e8bc7952db0e98e5b0b44cc01d523075dee09c8a Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 24 Apr 2018 22:56:56 +0100 Subject: [PATCH 03/63] Move fs to exporter and add browser packer --- demo/browser-demo.html | 22 ++++++++++++++++++++++ package.json | 1 + src/export/packer/browser.ts | 17 +++++++++++++++++ src/export/packer/compiler.ts | 3 ++- src/file/drawing/drawing.spec.ts | 1 - src/file/media/data.ts | 3 --- src/file/media/media.ts | 2 -- webpack.web.config.js | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 demo/browser-demo.html create mode 100644 src/export/packer/browser.ts create mode 100644 webpack.web.config.js diff --git a/demo/browser-demo.html b/demo/browser-demo.html new file mode 100644 index 0000000000..17508b74eb --- /dev/null +++ b/demo/browser-demo.html @@ -0,0 +1,22 @@ + + + + + + + + + +

DOCX browser Word document generation

+ + + + + + + + diff --git a/package.json b/package.json index 99104a157d..cc5394462b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build": "npm run webpack && npm run fix-types", "tsc": "rimraf ./build && tsc -p .", "webpack": "rimraf ./build && webpack", + "build.web": "webpack --config webpack.web.config.js", "demo": "npm run build && node ./demo", "typedoc": "typedoc --out docs/ src/ --module commonjs --target ES6 --disableOutputCheck --excludePrivate --externalPattern \"**/*.spec.ts\"", "style": "prettier -l \"src/**/*.ts\"", diff --git a/src/export/packer/browser.ts b/src/export/packer/browser.ts new file mode 100644 index 0000000000..ad88a5552c --- /dev/null +++ b/src/export/packer/browser.ts @@ -0,0 +1,17 @@ +import { Compiler } from "./next-compiler"; +import { IPacker } from "./packer"; + +declare var saveAs; + +export class BrowserPacker implements IPacker { + private readonly packer: Compiler; + + public async pack(filePath: string): Promise { + filePath = filePath.replace(/.docx$/, ""); + + const zip = await this.packer.compile(); + const zipBlob = await zip.generateAsync({ type: "blob" }); + + saveAs(zipBlob, `${filePath}.docx`); + } +} diff --git a/src/export/packer/compiler.ts b/src/export/packer/compiler.ts index 44c7817249..410ecc669b 100644 --- a/src/export/packer/compiler.ts +++ b/src/export/packer/compiler.ts @@ -1,5 +1,6 @@ import * as archiver from "archiver"; import * as express from "express"; +import * as fs from "fs"; import { Writable } from "stream"; import * as xml from "xml"; @@ -89,7 +90,7 @@ export class Compiler { }); for (const data of this.file.Media.array) { - this.archive.append(data.stream, { + this.archive.append(fs.createReadStream(data.path), { name: `word/media/${data.fileName}`, }); } diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 9b113da0bf..6ca09faa4d 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -12,7 +12,6 @@ describe("Drawing", () => { currentBreak = new Drawing({ fileName: "test.jpg", referenceId: 1, - stream: fs.createReadStream(path), path: path, dimensions: { pixels: { diff --git a/src/file/media/data.ts b/src/file/media/data.ts index 00836ed962..b4a349a967 100644 --- a/src/file/media/data.ts +++ b/src/file/media/data.ts @@ -1,5 +1,3 @@ -import * as fs from "fs"; - export interface IMediaDataDimensions { pixels: { x: number; @@ -13,7 +11,6 @@ export interface IMediaDataDimensions { export interface IMediaData { referenceId: number; - stream: fs.ReadStream; path: string; fileName: string; dimensions: IMediaDataDimensions; diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 5ac8905bc7..3f23e50b38 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,4 +1,3 @@ -import * as fs from "fs"; import * as sizeOf from "image-size"; import * as path from "path"; @@ -27,7 +26,6 @@ export class Media { const imageData = { referenceId: this.map.size + relationshipsCount + 1, - stream: fs.createReadStream(filePath), path: filePath, fileName: key, dimensions: { diff --git a/webpack.web.config.js b/webpack.web.config.js new file mode 100644 index 0000000000..9672df789c --- /dev/null +++ b/webpack.web.config.js @@ -0,0 +1,32 @@ +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + + output: { + path: path.resolve('build'), + filename: 'index.web.js', + libraryTarget: 'umd' + }, + + resolve: { + extensions: ['.tsx', '.ts', '.js'], + modules: [path.resolve('./src'), "node_modules"] + }, + + module: { + rules: [ + { + test: /\.ts$/, + loaders: ["awesome-typescript-loader"], + } + ], + }, + + node: { + __dirname: true, + fs: "empty", + tls: "empty", + net: "empty" + } +}; From 89e2129ca4693875611c99ce3afa9fb990ac4642 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Thu, 21 Jun 2018 14:50:50 +0200 Subject: [PATCH 04/63] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a6ec009e3..c46e7b1713 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.2.11", + "version": "3.3.0", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From 9d3b32a8411863510e35ca7a4415d40c8b933b94 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Mon, 25 Jun 2018 12:53:25 +0200 Subject: [PATCH 05/63] fix: fixed wrong import causing exported SectionProperties class to be unusable --- src/file/document/body/body.ts | 2 +- src/file/document/document.ts | 2 +- src/file/file.ts | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index 691dfd7518..549ba86f97 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -1,5 +1,5 @@ import { XmlComponent, IXmlableObject } from "file/xml-components"; -import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; +import { SectionProperties, SectionPropertiesOptions } from "./section-properties"; import { Paragraph, ParagraphProperties } from "../.."; export class Body extends XmlComponent { diff --git a/src/file/document/document.ts b/src/file/document/document.ts index a71bcbffe9..6dbb4decdf 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -4,7 +4,7 @@ import { XmlComponent } from "file/xml-components"; import { Paragraph, PictureRun } from "../paragraph"; import { Table } from "../table"; import { Body } from "./body"; -import { SectionPropertiesOptions } from "./body/section-properties/section-properties"; +import { SectionPropertiesOptions } from "./body/section-properties"; import { DocumentAttributes } from "./document-attributes"; export class Document extends XmlComponent { diff --git a/src/file/file.ts b/src/file/file.ts index a42e542e33..e805b10ade 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -2,7 +2,6 @@ import { AppProperties } from "./app-properties/app-properties"; import { ContentTypes } from "./content-types/content-types"; import { CoreProperties, IPropertiesOptions } from "./core-properties"; import { Document } from "./document"; -import { SectionPropertiesOptions } from "./document/body/section-properties/section-properties"; import { FooterWrapper } from "./footer-wrapper"; import { HeaderWrapper } from "./header-wrapper"; import { Media } from "./media"; @@ -14,7 +13,7 @@ import { DefaultStylesFactory } from "./styles/factory"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; import { Table } from "./table"; import { IMediaData } from "index"; -import { FooterReferenceType, HeaderReferenceType } from "./document/body/section-properties"; +import { FooterReferenceType, HeaderReferenceType, SectionPropertiesOptions } from "./document/body/section-properties"; export class File { private readonly document: Document; From 52007785afdb6f1e718fa6cb120839540231c743 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Mon, 25 Jun 2018 12:54:36 +0200 Subject: [PATCH 06/63] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c46e7b1713..446427e152 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.3.0", + "version": "3.3.1", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From ed72d60951288e03eab5a08c154ea0243eb3b09a Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Wed, 27 Jun 2018 21:55:15 +0200 Subject: [PATCH 07/63] external-styles: create correct XmlComponents from imported style --- .../styles/external-styles-factory.spec.ts | 69 ++++++++++++++++++- src/file/styles/external-styles-factory.ts | 9 ++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/file/styles/external-styles-factory.spec.ts b/src/file/styles/external-styles-factory.spec.ts index 861a6f05d8..e34bfbaa8d 100644 --- a/src/file/styles/external-styles-factory.spec.ts +++ b/src/file/styles/external-styles-factory.spec.ts @@ -10,6 +10,17 @@ describe("External styles factory", () => { + + + + + + + + + + + @@ -52,7 +63,63 @@ describe("External styles factory", () => { expect(importedStyle.root.length).to.equal(5); expect(importedStyle.root[1]).to.eql({ deleted: false, - root: [], + root: [ + { + deleted: false, + root: [ + { + deleted: false, + root: [ + { + _attr: { + "w:ascii": "Arial", + "w:cstheme": "minorHAnsi", + "w:eastAsiaTheme": "minorHAnsi", + "w:hAnsi": "Arial", + }, + deleted: false, + root: [], + rootKey: "w:rFonts", + }, + { + _attr: { + "w:bidi": "ar-SA", + "w:eastAsia": "en-US", + "w:val": "en-US", + }, + deleted: false, + root: [], + rootKey: "w:lang", + }, + ], + rootKey: "w:rPr", + }, + ], + rootKey: "w:rPrDefault", + }, + { + deleted: false, + root: [ + { + deleted: false, + root: [ + { + _attr: { + "w:after": "160", + "w:line": "259", + "w:lineRule": "auto", + }, + deleted: false, + root: [], + rootKey: "w:spacing", + }, + ], + rootKey: "w:pPr", + }, + ], + rootKey: "w:pPrDefault", + }, + ], rootKey: "w:docDefaults", }); expect(importedStyle.root[2]).to.eql({ diff --git a/src/file/styles/external-styles-factory.ts b/src/file/styles/external-styles-factory.ts index 9757faf8d9..7f54f03d4e 100644 --- a/src/file/styles/external-styles-factory.ts +++ b/src/file/styles/external-styles-factory.ts @@ -1,6 +1,6 @@ import { Styles } from "./"; import * as fastXmlParser from "fast-xml-parser"; -import { ImportedXmlComponent, ImportedRootElementAttributes, parseOptions, convertToXmlComponent } from "./../../file/xml-components"; +import { ImportedRootElementAttributes, parseOptions, convertToXmlComponent } from "./../../file/xml-components"; export class ExternalStylesFactory { /** @@ -34,7 +34,12 @@ export class ExternalStylesFactory { Object.keys(xmlStyles) .filter((element) => element !== "_attr" && element !== "w:style") .forEach((element) => { - importedStyle.push(new ImportedXmlComponent(element, xmlStyles[element]._attr)); + const converted = convertToXmlComponent(element, xmlStyles[element]); + if (Array.isArray(converted)) { + converted.forEach((c) => importedStyle.push(c)); + } else { + importedStyle.push(converted); + } }); // convert the styles one by one From 55220c147db53afe3eab7a44e56452743b1fa0f6 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Wed, 27 Jun 2018 22:10:11 +0200 Subject: [PATCH 08/63] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 446427e152..6cb05a6fb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.3.1", + "version": "3.3.2", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From c797ed9c2570a876a54b251728cc1b8061c23110 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Fri, 29 Jun 2018 00:32:01 +0200 Subject: [PATCH 09/63] media: fixed bug when media size can be decimal - produces invalid docx document --- src/file/media/media.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 7f384f9f98..99a193e88c 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -23,8 +23,8 @@ export class Media { y: dimensions.height, }, emus: { - x: dimensions.width * 9525, - y: dimensions.height * 9525, + x: Math.round(dimensions.width * 9525), + y: Math.round(dimensions.height * 9525), }, }, }; From 612a2f90ac3910b17aec2a0afb96f9e45754b6a5 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Fri, 29 Jun 2018 16:31:25 +0200 Subject: [PATCH 10/63] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6cb05a6fb8..1116182ac4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.3.2", + "version": "3.3.3", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From 796e0008261e14f0049e9a599ac0a10f9c2edd22 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Tue, 3 Jul 2018 13:48:31 +0200 Subject: [PATCH 11/63] feature: add support for section page borders --- .../document/body/section-properties/index.ts | 1 + .../section-properties/page-border/index.ts | 1 + .../page-border/page-borders.spec.ts | 91 ++++++++++++++++++ .../page-border/page-borders.ts | 94 +++++++++++++++++++ .../section-properties.spec.ts | 15 ++- .../section-properties/section-properties.ts | 28 +++++- src/file/styles/border/border-style.ts | 29 ++++++ src/file/styles/border/index.ts | 1 + src/file/styles/index.ts | 1 + src/file/table/table-cell.spec.ts | 3 +- src/file/table/table-cell.ts | 31 +----- 11 files changed, 261 insertions(+), 34 deletions(-) create mode 100644 src/file/document/body/section-properties/page-border/index.ts create mode 100644 src/file/document/body/section-properties/page-border/page-borders.spec.ts create mode 100644 src/file/document/body/section-properties/page-border/page-borders.ts create mode 100644 src/file/styles/border/border-style.ts create mode 100644 src/file/styles/border/index.ts diff --git a/src/file/document/body/section-properties/index.ts b/src/file/document/body/section-properties/index.ts index f1b5eabb84..cab88ac7c7 100644 --- a/src/file/document/body/section-properties/index.ts +++ b/src/file/document/body/section-properties/index.ts @@ -3,3 +3,4 @@ export * from "./footer-reference"; export * from "./header-reference"; export * from "./page-size"; export * from "./page-number"; +export * from "./page-border"; diff --git a/src/file/document/body/section-properties/page-border/index.ts b/src/file/document/body/section-properties/page-border/index.ts new file mode 100644 index 0000000000..53d8b8ce4b --- /dev/null +++ b/src/file/document/body/section-properties/page-border/index.ts @@ -0,0 +1 @@ +export * from "./page-borders"; diff --git a/src/file/document/body/section-properties/page-border/page-borders.spec.ts b/src/file/document/body/section-properties/page-border/page-borders.spec.ts new file mode 100644 index 0000000000..782280f292 --- /dev/null +++ b/src/file/document/body/section-properties/page-border/page-borders.spec.ts @@ -0,0 +1,91 @@ +import { expect } from "chai"; + +import { Formatter } from "../../../../../export/formatter"; +import { PageBorders, PageBorderDisplay, PageBorderZOrder } from "./page-borders"; +import { BorderStyle } from "../../../../styles"; + +describe("PageBorders", () => { + describe("#constructor()", () => { + it("should create empty element when no options are passed", () => { + const properties = new PageBorders(); + const tree = new Formatter().format(properties); + + expect(tree).to.equal(""); + }); + + it("should create page borders with some configuration", () => { + const properties = new PageBorders({ + pageBorders: { + display: PageBorderDisplay.FIRST_PAGE, + }, + }); + const tree = new Formatter().format(properties); + + expect(Object.keys(tree)).to.deep.equal(["w:pgBorders"]); + expect(tree["w:pgBorders"]).to.be.an.instanceof(Array); + expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage" } }); + }); + + it("should create page borders with full configuration", () => { + const properties = new PageBorders({ + pageBorders: { + display: PageBorderDisplay.FIRST_PAGE, + zOrder: PageBorderZOrder.BACK, + }, + pageBorderTop: { + style: BorderStyle.DOUBLE_WAVE, + size: 10, + color: "001122", + }, + pageBorderRight: { + style: BorderStyle.DOUBLE, + size: 20, + color: "223344", + }, + pageBorderBottom: { + style: BorderStyle.SINGLE, + size: 30, + color: "556677", + }, + pageBorderLeft: { + style: BorderStyle.DOTTED, + size: 40, + color: "889900", + }, + }); + const tree = new Formatter().format(properties); + + expect(Object.keys(tree)).to.deep.equal(["w:pgBorders"]); + expect(tree["w:pgBorders"]).to.be.an.instanceof(Array); + expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage", "w:zOrder": "back" } }); + expect(tree["w:pgBorders"][1]).to.deep.equal({ + "w:top": [ + { + _attr: { "w:color": "001122", "w:size": 10, "w:val": "doubleWave" }, + }, + ], + }); + expect(tree["w:pgBorders"][2]).to.deep.equal({ + "w:right": [ + { + _attr: { "w:color": "223344", "w:size": 20, "w:val": "double" }, + }, + ], + }); + expect(tree["w:pgBorders"][3]).to.deep.equal({ + "w:bottom": [ + { + _attr: { "w:color": "556677", "w:size": 30, "w:val": "single" }, + }, + ], + }); + expect(tree["w:pgBorders"][4]).to.deep.equal({ + "w:left": [ + { + _attr: { "w:color": "889900", "w:size": 40, "w:val": "dotted" }, + }, + ], + }); + }); + }); +}); diff --git a/src/file/document/body/section-properties/page-border/page-borders.ts b/src/file/document/body/section-properties/page-border/page-borders.ts new file mode 100644 index 0000000000..88b6ce98dd --- /dev/null +++ b/src/file/document/body/section-properties/page-border/page-borders.ts @@ -0,0 +1,94 @@ +// http://officeopenxml.com/WPsectionBorders.php +import { XmlComponent, XmlAttributeComponent, IXmlableObject } from "file/xml-components"; +import { BorderStyle } from "../../../../styles"; + +export enum PageBorderDisplay { + ALL_PAGES = "allPages", + FIRST_PAGE = "firstPage", + NOT_FIRST_PAGE = "notFirstPage", +} + +export enum PageBorderOffsetFrom { + PAGE = "page", + TEXT = "text", +} + +export enum PageBorderZOrder { + BACK = "back", + FRONT = "front", +} + +export interface IPageBorderAttributes { + display?: PageBorderDisplay; + offsetFrom?: PageBorderOffsetFrom; + zOrder?: PageBorderZOrder; +} + +export interface PageBorderConfiguration { + style?: BorderStyle; + size?: number; + color?: string; + space?: number; +} + +export type PageBordersOptions = { + pageBorders?: IPageBorderAttributes; + pageBorderTop?: PageBorderConfiguration; + pageBorderRight?: PageBorderConfiguration; + pageBorderBottom?: PageBorderConfiguration; + pageBorderLeft?: PageBorderConfiguration; +}; + +class PageBordeAttributes extends XmlAttributeComponent { + protected xmlKeys = { + style: "w:val", + size: "w:size", + color: "w:color", + space: "w:space", + }; +} + +class PageBorder extends XmlComponent { + constructor(key: string, options: PageBorderConfiguration) { + super(key); + + this.root.push(new PageBordeAttributes(options)); + } +} + +class PageBordersAttributes extends XmlAttributeComponent { + protected xmlKeys = { + display: "w:display", + offsetFrom: "w:offsetFrom", + zOrder: "w:zOrder", + }; +} + +export class PageBorders extends XmlComponent { + constructor(options?: PageBordersOptions) { + super("w:pgBorders"); + + if (!options) return; + + let pageBordersAttributes = {}; + + if (options.pageBorders) { + pageBordersAttributes = { + display: options.pageBorders.display, + offsetFrom: options.pageBorders.offsetFrom, + zOrder: options.pageBorders.zOrder, + }; + } + + this.root.push(new PageBordersAttributes(pageBordersAttributes)); + + if (options.pageBorderTop) this.root.push(new PageBorder("w:top", options.pageBorderTop)); + if (options.pageBorderRight) this.root.push(new PageBorder("w:right", options.pageBorderRight)); + if (options.pageBorderBottom) this.root.push(new PageBorder("w:bottom", options.pageBorderBottom)); + if (options.pageBorderLeft) this.root.push(new PageBorder("w:left", options.pageBorderLeft)); + } + + public prepForXml(): IXmlableObject { + return this.root.length > 0 ? super.prepForXml() : ""; + } +} diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts index 05a49d09d9..b2499bbd63 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -2,7 +2,7 @@ import { expect } from "chai"; import { Formatter } from "../../../../export/formatter"; import { SectionProperties } from "./section-properties"; -import { FooterReferenceType, PageNumberFormat } from "."; +import { FooterReferenceType, PageNumberFormat, PageBorderOffsetFrom } from "."; describe("SectionProperties", () => { describe("#constructor()", () => { @@ -155,5 +155,18 @@ describe("SectionProperties", () => { ], }); }); + + it("should create section properties with page borders", () => { + const properties = new SectionProperties({ + pageBorders: { + offsetFrom: PageBorderOffsetFrom.PAGE, + }, + }); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]); + expect(tree["w:sectPr"][7]).to.deep.equal({ + "w:pgBorders": [{ _attr: { "w:offsetFrom": "page" } }], + }); + }); }); }); diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index 993812bd5e..bb7a36746c 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -10,7 +10,7 @@ import { PageMargin } from "./page-margin/page-margin"; import { IPageMarginAttributes } from "./page-margin/page-margin-attributes"; import { PageSize } from "./page-size/page-size"; import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes"; -import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberType, PageNumberFormat } from "."; +import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberType, PageNumberFormat, PageBordersOptions, PageBorders } from "."; import { HeaderReferenceType } from "./header-reference/header-reference-attributes"; export type SectionPropertiesOptions = IPageSizeAttributes & @@ -19,7 +19,8 @@ export type SectionPropertiesOptions = IPageSizeAttributes & IDocGridAttributesProperties & HeaderOptions & FooterOptions & - IPageNumberTypeAttributes; + IPageNumberTypeAttributes & + PageBordersOptions; export class SectionProperties extends XmlComponent { private options: SectionPropertiesOptions; @@ -45,6 +46,11 @@ export class SectionProperties extends XmlComponent { footerId: 0, pageNumberStart: undefined, pageNumberFormatType: PageNumberFormat.DECIMAL, + pageBorders: undefined, + pageBorderTop: undefined, + pageBorderRight: undefined, + pageBorderBottom: undefined, + pageBorderLeft: undefined, }; const mergedOptions = { @@ -81,6 +87,24 @@ export class SectionProperties extends XmlComponent { this.root.push(new PageNumberType(mergedOptions.pageNumberStart, mergedOptions.pageNumberFormatType)); + if ( + mergedOptions.pageBorders || + mergedOptions.pageBorderTop || + mergedOptions.pageBorderRight || + mergedOptions.pageBorderBottom || + mergedOptions.pageBorderLeft + ) { + this.root.push( + new PageBorders({ + pageBorders: mergedOptions.pageBorders, + pageBorderTop: mergedOptions.pageBorderTop, + pageBorderRight: mergedOptions.pageBorderRight, + pageBorderBottom: mergedOptions.pageBorderBottom, + pageBorderLeft: mergedOptions.pageBorderLeft, + }), + ); + } + this.options = mergedOptions; } diff --git a/src/file/styles/border/border-style.ts b/src/file/styles/border/border-style.ts new file mode 100644 index 0000000000..00f4117d31 --- /dev/null +++ b/src/file/styles/border/border-style.ts @@ -0,0 +1,29 @@ +export enum BorderStyle { + SINGLE = "single", + DASH_DOT_STROKED = "dashDotStroked", + DASHED = "dashed", + DASH_SMALL_GAP = "dashSmallGap", + DOT_DASH = "dotDash", + DOT_DOT_DASH = "dotDotDash", + DOTTED = "dotted", + DOUBLE = "double", + DOUBLE_WAVE = "doubleWave", + INSET = "inset", + NIL = "nil", + NONE = "none", + OUTSET = "outset", + THICK = "thick", + THICK_THIN_LARGE_GAP = "thickThinLargeGap", + THICK_THIN_MEDIUM_GAP = "thickThinMediumGap", + THICK_THIN_SMALL_GAP = "thickThinSmallGap", + THIN_THICK_LARGE_GAP = "thinThickLargeGap", + THIN_THICK_MEDIUM_GAP = "thinThickMediumGap", + THIN_THICK_SMALL_GAP = "thinThickSmallGap", + THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap", + THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap", + THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap", + THREE_D_EMBOSS = "threeDEmboss", + THREE_D_ENGRAVE = "threeDEngrave", + TRIPLE = "triple", + WAVE = "wave", +} diff --git a/src/file/styles/border/index.ts b/src/file/styles/border/index.ts new file mode 100644 index 0000000000..e62e5f7dcc --- /dev/null +++ b/src/file/styles/border/index.ts @@ -0,0 +1 @@ +export * from "./border-style"; diff --git a/src/file/styles/index.ts b/src/file/styles/index.ts index 5b0bd1b063..7c75699adc 100644 --- a/src/file/styles/index.ts +++ b/src/file/styles/index.ts @@ -1,6 +1,7 @@ import { XmlComponent, BaseXmlComponent } from "file/xml-components"; import { DocumentDefaults } from "./defaults"; import { ParagraphStyle } from "./style"; +export * from "./border"; export class Styles extends XmlComponent { constructor(_initialStyles?: BaseXmlComponent) { diff --git a/src/file/table/table-cell.spec.ts b/src/file/table/table-cell.spec.ts index 01c81848bb..4e69e958a8 100644 --- a/src/file/table/table-cell.spec.ts +++ b/src/file/table/table-cell.spec.ts @@ -1,7 +1,8 @@ import { expect } from "chai"; -import { TableCellBorders, BorderStyle, TableCellWidth, WidthType } from "./table-cell"; +import { TableCellBorders, TableCellWidth, WidthType } from "./table-cell"; import { Formatter } from "../../export/formatter"; +import { BorderStyle } from "../styles"; describe("TableCellBorders", () => { describe("#prepForXml", () => { diff --git a/src/file/table/table-cell.ts b/src/file/table/table-cell.ts index 99282f1125..59101b9af3 100644 --- a/src/file/table/table-cell.ts +++ b/src/file/table/table-cell.ts @@ -1,34 +1,5 @@ import { XmlComponent, XmlAttributeComponent, IXmlableObject } from "file/xml-components"; - -export enum BorderStyle { - SINGLE = "single", - DASH_DOT_STROKED = "dashDotStroked", - DASHED = "dashed", - DASH_SMALL_GAP = "dashSmallGap", - DOT_DASH = "dotDash", - DOT_DOT_DASH = "dotDotDash", - DOTTED = "dotted", - DOUBLE = "double", - DOUBLE_WAVE = "doubleWave", - INSET = "inset", - NIL = "nil", - NONE = "none", - OUTSET = "outset", - THICK = "thick", - THICK_THIN_LARGE_GAP = "thickThinLargeGap", - THICK_THIN_MEDIUM_GAP = "thickThinMediumGap", - THICK_THIN_SMALL_GAP = "thickThinSmallGap", - THIN_THICK_LARGE_GAP = "thinThickLargeGap", - THIN_THICK_MEDIUM_GAP = "thinThickMediumGap", - THIN_THICK_SMALL_GAP = "thinThickSmallGap", - THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap", - THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap", - THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap", - THREE_D_EMBOSS = "threeDEmboss", - THREE_D_ENGRAVE = "threeDEngrave", - TRIPLE = "triple", - WAVE = "wave", -} +import { BorderStyle } from "../styles"; interface ICellBorder { style: BorderStyle; From c95e765456ba2b02b468cb0d1447f2be2d8a95a3 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Tue, 3 Jul 2018 14:11:19 +0200 Subject: [PATCH 12/63] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1116182ac4..7caa995140 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.3.3", + "version": "3.3.4", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From a05abd0eea80bcc78e4fd6dc42535e43258de2d9 Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Fri, 6 Jul 2018 18:54:30 +0200 Subject: [PATCH 13/63] numbering: add support to define suffix for numbering level --- src/file/numbering/index.ts | 1 + src/file/numbering/level.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/file/numbering/index.ts b/src/file/numbering/index.ts index a861d336ee..d83cffc61c 100644 --- a/src/file/numbering/index.ts +++ b/src/file/numbering/index.ts @@ -1,2 +1,3 @@ export * from "./numbering"; export * from "./abstract-numbering"; +export * from "./level"; diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index bb50bfb2e2..0df90758fb 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -60,6 +60,23 @@ class LevelJc extends XmlComponent { } } +export enum LevelSuffix { + NOTHING = "nothing", + SPACE = "space", + TAB = "tab", +} + +class Suffix extends XmlComponent { + constructor(value: LevelSuffix) { + super("w:suff"); + this.root.push( + new Attributes({ + val: value, + }), + ); + } +} + export class LevelBase extends XmlComponent { private readonly paragraphProperties: ParagraphProperties; private readonly runProperties: RunProperties; @@ -93,6 +110,11 @@ export class LevelBase extends XmlComponent { this.root.push(this.runProperties); } + public setSuffix(value: LevelSuffix) { + this.root.push(new Suffix(value)); + return this; + } + public addParagraphProperty(property: XmlComponent): Level { this.paragraphProperties.push(property); return this; From 3da0bb38df000a47126e212684fb5c348b556f8c Mon Sep 17 00:00:00 2001 From: Igor Bulovski Date: Fri, 6 Jul 2018 19:01:23 +0200 Subject: [PATCH 14/63] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7caa995140..5d2b6176c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx-h4", - "version": "3.3.4", + "version": "3.3.5", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": { From 12c8cb93f6953aff6beea46a354f11570d0c39e9 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 7 Aug 2018 01:25:28 +0100 Subject: [PATCH 15/63] Clean up API --- demo/demo16.js | 8 ++--- demo/demo20.js | 2 +- demo/demo23.js | 12 +++---- docs/contribution-guidelines.md | 45 ++++++++++++++++++++++++ docs/usage/headers-and-footers.md | 4 +-- src/export/packer/compiler.ts | 2 +- src/file/file.ts | 20 +++++------ src/file/footer-wrapper.ts | 4 +-- src/file/footer/footer.ts | 2 +- src/file/header-wrapper.ts | 4 +-- src/file/header/header.ts | 2 +- src/file/media/media.ts | 2 +- src/file/numbering/num.ts | 2 +- src/file/numbering/numbering.spec.ts | 4 +-- src/file/table/properties.spec.ts | 4 +-- src/file/table/properties.ts | 2 +- src/file/table/table.spec.ts | 4 +-- src/file/table/table.ts | 14 ++++---- src/file/xml-components/base.ts | 2 +- src/file/xml-components/xml-component.ts | 2 +- tslint.json | 3 +- 21 files changed, 95 insertions(+), 49 deletions(-) diff --git a/demo/demo16.js b/demo/demo16.js index ce0b162dc1..f850bc9b4b 100644 --- a/demo/demo16.js +++ b/demo/demo16.js @@ -12,8 +12,8 @@ var footer = doc.createFooter(); footer.createParagraph("Footer on another page"); doc.addSection({ - headerId: header.Header.referenceId, - footerId: footer.Footer.referenceId, + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, pageNumberStart: 1, pageNumberFormatType: docx.PageNumberFormat.DECIMAL, }); @@ -21,8 +21,8 @@ doc.addSection({ doc.createParagraph("hello"); doc.addSection({ - headerId: header.Header.referenceId, - footerId: footer.Footer.referenceId, + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, pageNumberStart: 1, pageNumberFormatType: docx.PageNumberFormat.DECIMAL, orientation: docx.PageOrientation.LANDSCAPE, diff --git a/demo/demo20.js b/demo/demo20.js index 12ffb58549..eef332c1ae 100644 --- a/demo/demo20.js +++ b/demo/demo20.js @@ -6,7 +6,7 @@ const table = doc.createTable(4, 4); table .getCell(2, 2) .addContent(new docx.Paragraph("Hello")) - .cellProperties.borders.addTopBorder(docx.BorderStyle.DASH_DOT_STROKED, 3, "red") + .CellProperties.Borders.addTopBorder(docx.BorderStyle.DASH_DOT_STROKED, 3, "red") .addBottomBorder(docx.BorderStyle.DOUBLE, 3, "blue") .addStartBorder(docx.BorderStyle.DOT_DOT_DASH, 3, "green") .addEndBorder(docx.BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); diff --git a/demo/demo23.js b/demo/demo23.js index 906f141e90..ec38db901f 100644 --- a/demo/demo23.js +++ b/demo/demo23.js @@ -15,12 +15,12 @@ const image5 = docx.Media.addImage(doc, "./demo/images/pizza.gif"); const imageBase64Data = `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` const image6 = docx.Media.addImageFromBuffer(doc, Buffer.from(imageBase64Data, 'base64'), 100, 100); -doc.insertImage(image); -doc.insertImage(image2); -doc.insertImage(image3); -doc.insertImage(image4); -doc.insertImage(image5); -doc.insertImage(image6); +doc.addImage(image); +doc.addImage(image2); +doc.addImage(image3); +doc.addImage(image4); +doc.addImage(image5); +doc.addImage(image6); var exporter = new docx.LocalPacker(doc); exporter.pack("My Document"); diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md index 28cfbad954..e50ec54f54 100644 --- a/docs/contribution-guidelines.md +++ b/docs/contribution-guidelines.md @@ -12,6 +12,51 @@ * Follow the `TSLint` rules +## Add vs Create + +This is just a guideline, and the rules can sometimes be broken. + +* Use `create` if the method `new`'s up an element inside: + + ```js + public createParagraph() { + const paragraph = new Paragraph(); + this.root.push(paragraph); + } + ``` + +* Use `add` if you add the element into the method as a parameter: + + ```js + public createParagraph(paragraph: Paragraph) { + this.root.push(paragraph); + } + ``` + +## Getters and Setters + +Getters and Setters are done with a capital letter like so: + +```js +public get Level() { + +} +``` + +There is no performance advantage by doing this. It means we don't need to prefix all private variables with the ugly `_`: + +**Do not:** + +```js +private get _level: string; +``` + +**Do** + +```js +private get level: string; +``` + ## Testing Please write a test of every file you make and suffix it with `.spec.ts`. diff --git a/docs/usage/headers-and-footers.md b/docs/usage/headers-and-footers.md index 72aa424d33..bfe626a04c 100644 --- a/docs/usage/headers-and-footers.md +++ b/docs/usage/headers-and-footers.md @@ -37,8 +37,8 @@ Also all the supported section properties are implemented according to: http://o // Add new section with another header and footer doc.addSection({ - headerId: header.Header.referenceId, - footerId: footer.Footer.referenceId, + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, pageNumberStart: 1, pageNumberFormatType: docx.PageNumberFormat.DECIMAL, }); diff --git a/src/export/packer/compiler.ts b/src/export/packer/compiler.ts index d439e0718c..5cfd8ca17c 100644 --- a/src/export/packer/compiler.ts +++ b/src/export/packer/compiler.ts @@ -97,7 +97,7 @@ export class Compiler { name: "_rels/.rels", }); - for (const data of this.file.Media.array) { + for (const data of this.file.Media.Array) { this.archive.append(data.stream, { name: `word/media/${data.fileName}`, }); diff --git a/src/file/file.ts b/src/file/file.ts index f8d13ed2bf..e742e0dd70 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -98,12 +98,12 @@ export class File { sectionPropertiesOptions = { footerType: FooterReferenceType.DEFAULT, headerType: HeaderReferenceType.DEFAULT, - headerId: header.Header.referenceId, - footerId: footer.Footer.referenceId, + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, }; } else { - sectionPropertiesOptions.headerId = header.Header.referenceId; - sectionPropertiesOptions.footerId = footer.Footer.referenceId; + sectionPropertiesOptions.headerId = header.Header.ReferenceId; + sectionPropertiesOptions.footerId = footer.Footer.ReferenceId; } this.document = new Document(sectionPropertiesOptions); } @@ -131,7 +131,7 @@ export class File { return image; } - public insertImage(image: Image): File { + public addImage(image: Image): File { this.document.addParagraph(image); return this; } @@ -181,7 +181,7 @@ export class File { const header = new HeaderWrapper(this.media, this.currentRelationshipId++); this.headerWrapper.push(header); this.docRelationships.createRelationship( - header.Header.referenceId, + header.Header.ReferenceId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", `header${this.headerWrapper.length}.xml`, ); @@ -193,7 +193,7 @@ export class File { const footer = new FooterWrapper(this.media, this.currentRelationshipId++); this.footerWrapper.push(footer); this.docRelationships.createRelationship( - footer.Footer.referenceId, + footer.Footer.ReferenceId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", `footer${this.footerWrapper.length}.xml`, ); @@ -207,7 +207,7 @@ export class File { this.document.Body.DefaultSection.addChildElement( new HeaderReference({ headerType: HeaderReferenceType.FIRST, - headerId: headerWrapper.Header.referenceId, + headerId: headerWrapper.Header.ReferenceId, }), ); @@ -251,7 +251,7 @@ export class File { } public HeaderByRefNumber(refId: number): HeaderWrapper { - const entry = this.headerWrapper.find((h) => h.Header.referenceId === refId); + const entry = this.headerWrapper.find((h) => h.Header.ReferenceId === refId); if (entry) { return entry; } @@ -267,7 +267,7 @@ export class File { } public FooterByRefNumber(refId: number): FooterWrapper { - const entry = this.footerWrapper.find((h) => h.Footer.referenceId === refId); + const entry = this.footerWrapper.find((h) => h.Footer.ReferenceId === refId); if (entry) { return entry; } diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index 8d90a5a941..b1bd4b534c 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -43,10 +43,10 @@ export class FooterWrapper { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - this.insertImage(new Image(mediaData)); + this.addImage(new Image(mediaData)); } - public insertImage(image: Image): FooterWrapper { + public addImage(image: Image): FooterWrapper { this.footer.addParagraph(image); return this; } diff --git a/src/file/footer/footer.ts b/src/file/footer/footer.ts index 4237e350a4..745b71f0b5 100644 --- a/src/file/footer/footer.ts +++ b/src/file/footer/footer.ts @@ -31,7 +31,7 @@ export class Footer extends XmlComponent { ); } - public get referenceId(): number { + public get ReferenceId(): number { return this.refId; } diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index b8183b92ba..8970dc2560 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -43,10 +43,10 @@ export class HeaderWrapper { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - this.insertImage(new Image(mediaData)); + this.addImage(new Image(mediaData)); } - public insertImage(image: Image): HeaderWrapper { + public addImage(image: Image): HeaderWrapper { this.header.addParagraph(image); return this; } diff --git a/src/file/header/header.ts b/src/file/header/header.ts index 8260b332e3..44ef386901 100644 --- a/src/file/header/header.ts +++ b/src/file/header/header.ts @@ -31,7 +31,7 @@ export class Header extends XmlComponent { ); } - public get referenceId(): number { + public get ReferenceId(): number { return this.refId; } diff --git a/src/file/media/media.ts b/src/file/media/media.ts index ed081cc5e1..e813a2c051 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -120,7 +120,7 @@ export class Media { return imageData; } - public get array(): IMediaData[] { + public get Array(): IMediaData[] { const array = new Array(); this.map.forEach((data) => { diff --git a/src/file/numbering/num.ts b/src/file/numbering/num.ts index c4caaf8881..e4600339cf 100644 --- a/src/file/numbering/num.ts +++ b/src/file/numbering/num.ts @@ -56,7 +56,7 @@ export class LevelOverride extends XmlComponent { } } - public get level(): LevelForOverride { + public get Level(): LevelForOverride { let lvl: LevelForOverride; if (!this.lvl) { lvl = new LevelForOverride(this.levelNum); diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 17b46eda30..05dc4a391a 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -387,9 +387,9 @@ describe("concrete numbering", () => { }); }); - it("sets the lvl element if overrideLevel.level is accessed", () => { + it("sets the lvl element if overrideLevel.Level is accessed", () => { const ol = concreteNumbering.overrideLevel(1); - expect(ol.level).to.be.instanceof(LevelForOverride); + expect(ol.Level).to.be.instanceof(LevelForOverride); const tree = new Formatter().format(concreteNumbering); expect(tree["w:num"]).to.include({ "w:lvlOverride": [ diff --git a/src/file/table/properties.spec.ts b/src/file/table/properties.spec.ts index b6336c1411..c10c18f4c2 100644 --- a/src/file/table/properties.spec.ts +++ b/src/file/table/properties.spec.ts @@ -22,9 +22,9 @@ describe("TableProperties", () => { }); }); - describe("#fixedWidthLayout", () => { + describe("#setFixedWidthLayout", () => { it("sets the table to fixed width layout", () => { - const tp = new TableProperties().fixedWidthLayout(); + const tp = new TableProperties().setFixedWidthLayout(); 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/properties.ts b/src/file/table/properties.ts index 1478399dae..64b0ed53ad 100644 --- a/src/file/table/properties.ts +++ b/src/file/table/properties.ts @@ -12,7 +12,7 @@ export class TableProperties extends XmlComponent { return this; } - public fixedWidthLayout(): TableProperties { + public setFixedWidthLayout(): TableProperties { this.root.push(new TableLayout("fixed")); return this; } diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index 84cbe99590..21ee3e63d4 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -186,9 +186,9 @@ describe("Table", () => { }); }); - describe("#fixedWidthLayout", () => { + describe("#setFixedWidthLayout", () => { it("sets the table to fixed width layout", () => { - const table = new Table(2, 2).fixedWidthLayout(); + const table = new Table(2, 2).setFixedWidthLayout(); const tree = new Formatter().format(table); expect(tree) .to.have.property("w:tbl") diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 68f083ce6a..01f00a4d65 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -72,8 +72,8 @@ export class Table extends XmlComponent { return this; } - public fixedWidthLayout(): Table { - this.properties.fixedWidthLayout(); + public setFixedWidthLayout(): Table { + this.properties.setFixedWidthLayout(); return this; } } @@ -94,7 +94,7 @@ export class TableRow extends XmlComponent { public addGridSpan(ix: number, cellSpan: number): TableCell { const remainCell = this.cells[ix]; - remainCell.cellProperties.addGridSpan(cellSpan); + remainCell.CellProperties.addGridSpan(cellSpan); this.cells.splice(ix + 1, cellSpan - 1); this.root.splice(ix + 2, cellSpan - 1); @@ -138,7 +138,7 @@ export class TableCell extends XmlComponent { return para; } - public get cellProperties(): TableCellProperties { + public get CellProperties(): TableCellProperties { return this.properties; } } @@ -151,7 +151,7 @@ export class TableCellProperties extends XmlComponent { this.root.push(this.cellBorder); } - public get borders(): TableCellBorders { + public get Borders(): TableCellBorders { return this.cellBorder; } @@ -167,8 +167,8 @@ export class TableCellProperties extends XmlComponent { return this; } - public setVerticalAlign(vAlignType: VerticalAlign): TableCellProperties { - this.root.push(new VAlign(vAlignType)); + public setVerticalAlign(type: VerticalAlign): TableCellProperties { + this.root.push(new VAlign(type)); return this; } diff --git a/src/file/xml-components/base.ts b/src/file/xml-components/base.ts index 0dd5333765..a5f24f3824 100644 --- a/src/file/xml-components/base.ts +++ b/src/file/xml-components/base.ts @@ -10,7 +10,7 @@ export abstract class BaseXmlComponent { public abstract prepForXml(): IXmlableObject; - public get isDeleted(): boolean { + public get IsDeleted(): boolean { return this.deleted; } } diff --git a/src/file/xml-components/xml-component.ts b/src/file/xml-components/xml-component.ts index fa7709a043..0ed604e9ee 100644 --- a/src/file/xml-components/xml-component.ts +++ b/src/file/xml-components/xml-component.ts @@ -14,7 +14,7 @@ export abstract class XmlComponent extends BaseXmlComponent { const children = this.root .filter((c) => { if (c instanceof BaseXmlComponent) { - return !c.isDeleted; + return !c.IsDeleted; } return true; }) diff --git a/tslint.json b/tslint.json index 5bbe52b1bc..c61daf35dc 100644 --- a/tslint.json +++ b/tslint.json @@ -37,6 +37,7 @@ ], "no-implicit-dependencies": false, "no-submodule-imports": false, - "no-null-keyword": true + "no-null-keyword": true, + "return-undefined": true } } From e9aecfac1cfa8c9b050904604a671d2b5809afb0 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 7 Aug 2018 01:38:15 +0100 Subject: [PATCH 16/63] Updated lint rules --- package.json | 2 +- src/export/packer/buffer-stream.ts | 4 ++-- src/export/packer/compiler.ts | 4 ++-- src/file/document/body/body.ts | 4 ++-- .../document/body/section-properties/section-properties.ts | 3 ++- src/file/drawing/drawing.ts | 2 +- src/file/drawing/extent/extent.ts | 2 +- .../drawing/inline/graphic/graphic-data/graphic-data.ts | 2 +- src/file/drawing/inline/graphic/graphic-data/pic/pic.ts | 2 +- .../pic/shape-properties/form/extents/extents.ts | 2 +- .../graphic/graphic-data/pic/shape-properties/form/form.ts | 2 +- .../graphic-data/pic/shape-properties/shape-properties.ts | 2 +- src/file/drawing/inline/graphic/graphic.ts | 2 +- src/file/drawing/inline/inline.ts | 6 +++--- src/file/footer/footer.ts | 3 ++- src/file/header/header.ts | 4 +++- src/file/numbering/numbering.ts | 4 ++-- src/file/paragraph/paragraph.ts | 2 +- src/file/paragraph/run/picture-run.ts | 2 +- src/file/table/table.ts | 3 ++- tsconfig.json | 1 + tslint.json | 6 ++---- 22 files changed, 34 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index ebfee8c979..fd6d092f87 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "rimraf": "^2.5.2", "shelljs": "^0.7.7", "sinon": "^5.0.7", - "tslint": "^5.1.0", + "tslint": "^5.11.0", "typedoc": "^0.11.1", "typescript": "2.9.2", "webpack": "^3.10.0" diff --git a/src/export/packer/buffer-stream.ts b/src/export/packer/buffer-stream.ts index d1b9b0daa1..e0d2f8ed73 100644 --- a/src/export/packer/buffer-stream.ts +++ b/src/export/packer/buffer-stream.ts @@ -1,7 +1,7 @@ import { Writable } from "stream"; export class BufferStream extends Writable { - private data: Buffer[]; + private readonly data: Buffer[]; constructor() { super(); @@ -10,7 +10,7 @@ export class BufferStream extends Writable { } // tslint:disable-next-line:no-any - public _write(chunk: any, encoding: string, next: (err?: Error) => void): void { + public _write(chunk: any, _: string, next: (err?: Error) => void): void { this.data.push(Buffer.from(chunk)); next(); } diff --git a/src/export/packer/compiler.ts b/src/export/packer/compiler.ts index 5cfd8ca17c..a845833a34 100644 --- a/src/export/packer/compiler.ts +++ b/src/export/packer/compiler.ts @@ -8,9 +8,9 @@ import { Formatter } from "../formatter"; export class Compiler { protected archive: archiver.Archiver; - private formatter: Formatter; + private readonly formatter: Formatter; - constructor(private file: File) { + constructor(private readonly file: File) { this.formatter = new Formatter(); this.archive = archiver.create("zip", {}); diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index 5acc9f9c2b..4ec5156bfc 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -3,9 +3,9 @@ import { Paragraph, ParagraphProperties } from "../.."; import { SectionProperties, SectionPropertiesOptions } from "./section-properties"; export class Body extends XmlComponent { - private defaultSection: SectionProperties; + private readonly defaultSection: SectionProperties; - private sections: SectionProperties[] = []; + private readonly sections: SectionProperties[] = []; constructor(sectionPropertiesOptions?: SectionPropertiesOptions) { super("w:body"); diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index c1a666b8ed..4cb6d12b99 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -23,7 +23,8 @@ export type SectionPropertiesOptions = IPageSizeAttributes & IPageNumberTypeAttributes; export class SectionProperties extends XmlComponent { - private options: SectionPropertiesOptions; + private readonly options: SectionPropertiesOptions; + constructor(options?: SectionPropertiesOptions) { super("w:sectPr"); diff --git a/src/file/drawing/drawing.ts b/src/file/drawing/drawing.ts index 4c3db93b3a..d45a6ad3bb 100644 --- a/src/file/drawing/drawing.ts +++ b/src/file/drawing/drawing.ts @@ -28,7 +28,7 @@ const defaultDrawingOptions: IDrawingOptions = { }; export class Drawing extends XmlComponent { - private inline: Inline; + private readonly inline: Inline; constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { super("w:drawing"); diff --git a/src/file/drawing/extent/extent.ts b/src/file/drawing/extent/extent.ts index 0e22348cf1..270a85a8a8 100644 --- a/src/file/drawing/extent/extent.ts +++ b/src/file/drawing/extent/extent.ts @@ -2,7 +2,7 @@ import { XmlComponent } from "file/xml-components"; import { ExtentAttributes } from "./extent-attributes"; export class Extent extends XmlComponent { - private attributes: ExtentAttributes; + private readonly attributes: ExtentAttributes; constructor(x: number, y: number) { super("wp:extent"); diff --git a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts index ca3d4600be..78606fd399 100644 --- a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts +++ b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts @@ -3,7 +3,7 @@ import { GraphicDataAttributes } from "./graphic-data-attribute"; import { Pic } from "./pic"; export class GraphicData extends XmlComponent { - private pic: Pic; + private readonly pic: Pic; constructor(referenceId: number, x: number, y: number) { super("a:graphicData"); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts index f8b555af00..14ccf63f02 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts @@ -6,7 +6,7 @@ import { PicAttributes } from "./pic-attributes"; import { ShapeProperties } from "./shape-properties/shape-properties"; export class Pic extends XmlComponent { - private shapeProperties: ShapeProperties; + private readonly shapeProperties: ShapeProperties; constructor(referenceId: number, x: number, y: number) { super("pic:pic"); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts index 74aea18a48..55bf8bae0b 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts @@ -3,7 +3,7 @@ import { XmlComponent } from "file/xml-components"; import { ExtentsAttributes } from "./extents-attributes"; export class Extents extends XmlComponent { - private attributes: ExtentsAttributes; + private readonly attributes: ExtentsAttributes; constructor(x: number, y: number) { super("a:ext"); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts index 06523e0965..48c069f644 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts @@ -4,7 +4,7 @@ import { Extents } from "./extents/extents"; import { Offset } from "./offset/off"; export class Form extends XmlComponent { - private extents: Extents; + private readonly extents: Extents; constructor(x: number, y: number) { super("a:xfrm"); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts index 9c910f62e2..9dacae18d6 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts @@ -7,7 +7,7 @@ import { PresetGeometry } from "./preset-geometry/preset-geometry"; import { ShapePropertiesAttributes } from "./shape-properties-attributes"; export class ShapeProperties extends XmlComponent { - private form: Form; + private readonly form: Form; constructor(x: number, y: number) { super("pic:spPr"); diff --git a/src/file/drawing/inline/graphic/graphic.ts b/src/file/drawing/inline/graphic/graphic.ts index ce61893e05..dba653d2ca 100644 --- a/src/file/drawing/inline/graphic/graphic.ts +++ b/src/file/drawing/inline/graphic/graphic.ts @@ -12,7 +12,7 @@ class GraphicAttributes extends XmlAttributeComponent { } export class Graphic extends XmlComponent { - private data: GraphicData; + private readonly data: GraphicData; constructor(referenceId: number, x: number, y: number) { super("a:graphic"); diff --git a/src/file/drawing/inline/inline.ts b/src/file/drawing/inline/inline.ts index 6e5be2ba13..f36dd19cf3 100644 --- a/src/file/drawing/inline/inline.ts +++ b/src/file/drawing/inline/inline.ts @@ -9,10 +9,10 @@ import { Graphic } from "./../inline/graphic"; import { InlineAttributes } from "./inline-attributes"; export class Inline extends XmlComponent { - private extent: Extent; - private graphic: Graphic; + private readonly extent: Extent; + private readonly graphic: Graphic; - constructor(referenceId: number, private dimensions: IMediaDataDimensions) { + constructor(referenceId: number, private readonly dimensions: IMediaDataDimensions) { super("wp:inline"); this.root.push( diff --git a/src/file/footer/footer.ts b/src/file/footer/footer.ts index 745b71f0b5..532e662c25 100644 --- a/src/file/footer/footer.ts +++ b/src/file/footer/footer.ts @@ -5,7 +5,8 @@ import { Table } from "../table"; import { FooterAttributes } from "./footer-attributes"; export class Footer extends XmlComponent { - private refId: number; + private readonly refId: number; + constructor(referenceNumber: number) { super("w:ftr"); this.refId = referenceNumber; diff --git a/src/file/header/header.ts b/src/file/header/header.ts index 44ef386901..be1708658f 100644 --- a/src/file/header/header.ts +++ b/src/file/header/header.ts @@ -5,9 +5,11 @@ import { Table } from "../table"; import { HeaderAttributes } from "./header-attributes"; export class Header extends XmlComponent { - private refId: number; + private readonly refId: number; + constructor(referenceNumber: number) { super("w:hdr"); + this.refId = referenceNumber; this.root.push( new HeaderAttributes({ diff --git a/src/file/numbering/numbering.ts b/src/file/numbering/numbering.ts index 0a886e5598..a256500c45 100644 --- a/src/file/numbering/numbering.ts +++ b/src/file/numbering/numbering.ts @@ -7,8 +7,8 @@ import { Num } from "./num"; export class Numbering extends XmlComponent { private nextId: number; - private abstractNumbering: XmlComponent[] = []; - private concreteNumbering: XmlComponent[] = []; + private readonly abstractNumbering: XmlComponent[] = []; + private readonly concreteNumbering: XmlComponent[] = []; constructor() { super("w:numbering"); diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 3695b70bd5..22e64fc643 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -19,7 +19,7 @@ import { ParagraphProperties } from "./properties"; import { PictureRun, Run, TextRun } from "./run"; export class Paragraph extends XmlComponent { - private properties: ParagraphProperties; + private readonly properties: ParagraphProperties; constructor(text?: string) { super("w:p"); diff --git a/src/file/paragraph/run/picture-run.ts b/src/file/paragraph/run/picture-run.ts index 6a07b3bd9e..d51d0fc8f9 100644 --- a/src/file/paragraph/run/picture-run.ts +++ b/src/file/paragraph/run/picture-run.ts @@ -4,7 +4,7 @@ import { IMediaData } from "../../media/data"; import { Run } from "../run"; export class PictureRun extends Run { - private drawing: Drawing; + private readonly drawing: Drawing; constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { super(); diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 01f00a4d65..d82da34ff2 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -144,7 +144,8 @@ export class TableCell extends XmlComponent { } export class TableCellProperties extends XmlComponent { - private cellBorder: TableCellBorders; + private readonly cellBorder: TableCellBorders; + constructor() { super("w:tcPr"); this.cellBorder = new TableCellBorders(); diff --git a/tsconfig.json b/tsconfig.json index 2d46f20143..cf7d8dd8be 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "module": "commonjs", "declaration": true, "noUnusedLocals": true, + "noUnusedParameters": true, "baseUrl": "./src", "paths" : { "/*": [ diff --git a/tslint.json b/tslint.json index c61daf35dc..497035eccc 100644 --- a/tslint.json +++ b/tslint.json @@ -32,12 +32,10 @@ "max-classes-per-file": [ false ], - "no-unused-variable": [ - true - ], "no-implicit-dependencies": false, "no-submodule-imports": false, "no-null-keyword": true, - "return-undefined": true + "return-undefined": true, + "prefer-readonly": true } } From cf0c2c7691a8a2271b6dc5ae5541a31a4be2c3e9 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 7 Aug 2018 02:23:58 +0100 Subject: [PATCH 17/63] Add Express packer deprecation warning --- docs/usage/packers.md | 19 +++++++++++++++---- src/export/packer/express.ts | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/usage/packers.md b/docs/usage/packers.md index 1994781639..db837702de 100644 --- a/docs/usage/packers.md +++ b/docs/usage/packers.md @@ -32,21 +32,32 @@ const docx = require("docx"); const doc = new docx.Document(); const exporter = new docx.StreamPacker(doc); -const buffer = exporter.pack(); +const stream = exporter.pack(); ``` ## Express Packer +The old express packer is now deprecated and may disappear soon, so you should upgrade. + +The reason for this is because it means this project needs to know about and use `express`, which for a Word document generator, does not sound right. Seperation of concerns. + +It will still be usable (for now), but it is ill advised. + I used the express exporter in my [website](http://www.dolan.bio). -Pass in the necessary parameters: +The recommended way is to use the `StreamPacker` and handle the `express` magic outside of the library: ```js const docx = require("docx"); const doc = new docx.Document(); -const exporter = new docx.ExpressPacker(doc, res); -exporter.pack("My Document"); +const exporter = new docx.StreamPacker(doc); + +const stream = exporter.pack(); + +// Express' response object +res.attachment('yourfile.xlsx'); +stream.pipe(res); ``` where `res` is the response object obtained through the Express router. It is that simple. The file will begin downloading in the browser. diff --git a/src/export/packer/express.ts b/src/export/packer/express.ts index 4f99298424..3a4fa4b3ef 100644 --- a/src/export/packer/express.ts +++ b/src/export/packer/express.ts @@ -4,6 +4,9 @@ import { File } from "file"; import { Compiler } from "./compiler"; import { IPacker } from "./packer"; +/** + * @deprecated ExpressPacker is now deprecated. Please use the StreamPacker instead and pipe that to `express`' `res` object + */ export class ExpressPacker implements IPacker { private readonly packer: Compiler; From 92da93a16043d1194059026a78fdf96d44ad0706 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 7 Aug 2018 02:47:24 +0100 Subject: [PATCH 18/63] Rename to more readable names --- demo/demo22.js | 4 ++-- .../paragraph/formatting/{bidi.ts => bidirectional.ts} | 2 +- src/file/paragraph/paragraph.spec.ts | 4 ++-- src/file/paragraph/paragraph.ts | 6 +++--- src/file/paragraph/run/formatting.ts | 4 ++-- src/file/paragraph/run/run.spec.ts | 2 +- src/file/paragraph/run/run.ts | 8 ++++---- src/file/styles/defaults/run-properties.ts | 4 ++-- src/file/styles/style/index.ts | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) rename src/file/paragraph/formatting/{bidi.ts => bidirectional.ts} (67%) diff --git a/demo/demo22.js b/demo/demo22.js index ce42f22ccd..4503d6c1c3 100644 --- a/demo/demo22.js +++ b/demo/demo22.js @@ -2,8 +2,8 @@ const docx = require('../build'); var doc = new docx.Document(); -var textRun = new docx.TextRun("שלום עולם").rtl(); -var paragraph = new docx.Paragraph().bidi(); +var textRun = new docx.TextRun("שלום עולם").rightToLeft(); +var paragraph = new docx.Paragraph().bidirectional(); paragraph.addRun(textRun); doc.addParagraph(paragraph); diff --git a/src/file/paragraph/formatting/bidi.ts b/src/file/paragraph/formatting/bidirectional.ts similarity index 67% rename from src/file/paragraph/formatting/bidi.ts rename to src/file/paragraph/formatting/bidirectional.ts index 4a8bbdade9..4083247e78 100644 --- a/src/file/paragraph/formatting/bidi.ts +++ b/src/file/paragraph/formatting/bidirectional.ts @@ -1,6 +1,6 @@ import { XmlComponent } from "file/xml-components"; -export class Bidi extends XmlComponent { +export class Bidirectional extends XmlComponent { constructor() { super("w:bidi"); } diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index a2176f3ecf..e00fa6167c 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -339,9 +339,9 @@ describe("Paragraph", () => { }); }); - describe("#bidi", () => { + describe("#bidirectional", () => { it("set paragraph right to left layout", () => { - paragraph.bidi(); + paragraph.bidirectional(); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ "w:p": [{ "w:pPr": [{ "w:bidi": [] }] }], diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 22e64fc643..ef298604d7 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -5,7 +5,7 @@ import { Num } from "file/numbering/num"; import { XmlComponent } from "file/xml-components"; import { Alignment } from "./formatting/alignment"; -import { Bidi } from "./formatting/bidi"; +import { Bidirectional } from "./formatting/bidirectional"; import { ThematicBreak } from "./formatting/border"; import { Indent } from "./formatting/indent"; import { KeepLines, KeepNext } from "./formatting/keep"; @@ -217,8 +217,8 @@ export class Paragraph extends XmlComponent { return this; } - public bidi(): Paragraph { - this.properties.push(new Bidi()); + public bidirectional(): Paragraph { + this.properties.push(new Bidirectional()); return this; } } diff --git a/src/file/paragraph/run/formatting.ts b/src/file/paragraph/run/formatting.ts index bd9da1c358..31c64844d0 100644 --- a/src/file/paragraph/run/formatting.ts +++ b/src/file/paragraph/run/formatting.ts @@ -124,7 +124,7 @@ export class Size extends XmlComponent { } } -export class SizeCs extends XmlComponent { +export class SizeComplexScript extends XmlComponent { constructor(size: number) { super("w:szCs"); this.root.push( @@ -135,7 +135,7 @@ export class SizeCs extends XmlComponent { } } -export class RTL extends XmlComponent { +export class RightToLeft extends XmlComponent { constructor() { super("w:rtl"); this.root.push( diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index 5fbe93ee92..f05afaafe0 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -145,7 +145,7 @@ describe("Run", () => { describe("#rtl", () => { it("should set the run to the RTL mode", () => { - run.rtl(); + run.rightToLeft(); const tree = new Formatter().format(run); expect(tree).to.deep.equal({ "w:r": [{ "w:rPr": [{ "w:rtl": [{ _attr: { "w:val": true } }] }] }], diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts index ea45bbcd34..415364fb2d 100644 --- a/src/file/paragraph/run/run.ts +++ b/src/file/paragraph/run/run.ts @@ -1,7 +1,7 @@ // http://officeopenxml.com/WPtext.php import { Break } from "./break"; import { Caps, SmallCaps } from "./caps"; -import { Bold, Color, DoubleStrike, Italics, RTL, Size, SizeCs, Strike } from "./formatting"; +import { Bold, Color, DoubleStrike, Italics, RightToLeft, Size, SizeComplexScript, Strike } from "./formatting"; import { Begin, End, Page, Separate } from "./page-number"; import { RunProperties } from "./properties"; import { RunFonts } from "./run-fonts"; @@ -43,12 +43,12 @@ export class Run extends XmlComponent { public size(size: number): Run { this.properties.push(new Size(size)); - this.properties.push(new SizeCs(size)); + this.properties.push(new SizeComplexScript(size)); return this; } - public rtl(): Run { - this.properties.push(new RTL()); + public rightToLeft(): Run { + this.properties.push(new RightToLeft()); return this; } diff --git a/src/file/styles/defaults/run-properties.ts b/src/file/styles/defaults/run-properties.ts index 1f4018dee2..9f30986b84 100644 --- a/src/file/styles/defaults/run-properties.ts +++ b/src/file/styles/defaults/run-properties.ts @@ -1,5 +1,5 @@ import { XmlComponent } from "file/xml-components"; -import { Size, SizeCs } from "../../paragraph/run/formatting"; +import { Size, SizeComplexScript } from "../../paragraph/run/formatting"; import { RunProperties } from "../../paragraph/run/properties"; import { RunFonts } from "../../paragraph/run/run-fonts"; @@ -14,7 +14,7 @@ export class RunPropertiesDefaults extends XmlComponent { public size(size: number): RunPropertiesDefaults { this.properties.push(new Size(size)); - this.properties.push(new SizeCs(size)); + this.properties.push(new SizeComplexScript(size)); return this; } diff --git a/src/file/styles/style/index.ts b/src/file/styles/style/index.ts index 21e60b3d43..655cc28d2a 100644 --- a/src/file/styles/style/index.ts +++ b/src/file/styles/style/index.ts @@ -74,7 +74,7 @@ export class ParagraphStyle extends Style { public size(twips: number): ParagraphStyle { this.addRunProperty(new formatting.Size(twips)); - this.addRunProperty(new formatting.SizeCs(twips)); + this.addRunProperty(new formatting.SizeComplexScript(twips)); return this; } @@ -283,7 +283,7 @@ export class CharacterStyle extends Style { public size(twips: number): CharacterStyle { this.addRunProperty(new formatting.Size(twips)); - this.addRunProperty(new formatting.SizeCs(twips)); + this.addRunProperty(new formatting.SizeComplexScript(twips)); return this; } } From fe43525dada52eb8805d95a986f09ed18123d792 Mon Sep 17 00:00:00 2001 From: amitm02 Date: Tue, 7 Aug 2018 16:19:13 +0300 Subject: [PATCH 19/63] update hebrew demo --- demo/demo22.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/demo/demo22.js b/demo/demo22.js index ce42f22ccd..1a5fd78be7 100644 --- a/demo/demo22.js +++ b/demo/demo22.js @@ -2,11 +2,23 @@ const docx = require('../build'); var doc = new docx.Document(); -var textRun = new docx.TextRun("שלום עולם").rtl(); -var paragraph = new docx.Paragraph().bidi(); -paragraph.addRun(textRun); -doc.addParagraph(paragraph); + +var paragraph1 = new docx.Paragraph().bidi(); +var textRun1 = new docx.TextRun("שלום עולם").rtl(); +paragraph1.addRun(textRun1); +doc.addParagraph(paragraph1); + +var paragraph2 = new docx.Paragraph().bidi(); +var textRun2 = new docx.TextRun("שלום עולם").bold().rtl(); +paragraph2.addRun(textRun2); +doc.addParagraph(paragraph2); + +var paragraph3 = new docx.Paragraph().bidi(); +var textRun3 = new docx.TextRun("שלום עולם").italic().rtl(); +paragraph3.addRun(textRun3); +doc.addParagraph(paragraph3); + var exporter = new docx.LocalPacker(doc); exporter.pack('My Document'); From 3dd6faa620bb0881156683e51891cf587d059c5d Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 8 Aug 2018 01:29:52 +0100 Subject: [PATCH 20/63] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5415a4976e..207401f56c 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ # docx +drawing + ## Install ```sh From 4c75b91ce9e294f2328604ea38d30a9a279065f7 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 8 Aug 2018 01:53:44 +0100 Subject: [PATCH 21/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 207401f56c..a24abcc0a7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ # docx -drawing +drawing ## Install From 94274733f4eb4628cef8dc4489857d79cab0851d Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 8 Aug 2018 22:51:54 +0100 Subject: [PATCH 22/63] Improve API documentation --- package.json | 2 +- tsconfig.json | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fd6d092f87..52b8d3fc56 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "tsc": "rimraf ./build && tsc -p .", "webpack": "rimraf ./build && webpack", "demo": "npm run build && node ./demo", - "typedoc": "typedoc --out docs/api/ src/ --module commonjs --target ES6 --disableOutputCheck --excludePrivate --externalPattern \"**/*.spec.ts\"", + "typedoc": "typedoc src/index.ts", "style": "prettier -l \"src/**/*.ts\"", "style.fix": "prettier \"src/**/*.ts\" --write", "fix-types": "node types-absolute-fixer.js" diff --git a/tsconfig.json b/tsconfig.json index cf7d8dd8be..8e716e322f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,23 @@ "tests", "**/*.spec.ts", "**/_*" - ] + ], + "typedocOptions": { + "mode": "modules", + "out": "docs/api", + "exclude": "test", + "theme": "default", + "ignoreCompilerErrors": true, + "excludePrivate": true, + "excludeProtected": true, + "excludeNotExported": true, + "excludeExternals": false, + "target": "ES6", + "moduleResolution": "node", + "preserveConstEnums": true, + "stripInternal": true, + "suppressExcessPropertyErrors": true, + "suppressImplicitAnyIndexErrors": true, + "module": "commonjs" + } } From e10c20fa4252436ab63727dd4206d65beca5f478 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 01:55:50 +0100 Subject: [PATCH 23/63] Add image to run --- demo/demo23.js | 3 +++ src/file/file.ts | 10 +++++----- src/file/footer-wrapper.ts | 8 ++++---- src/file/header-wrapper.ts | 8 ++++---- src/file/media/image.ts | 13 +++++++++++++ src/file/media/index.ts | 1 + src/file/media/media.ts | 7 ++++--- src/file/paragraph/image.ts | 6 +++++- src/file/paragraph/paragraph.ts | 7 ++++--- 9 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 src/file/media/image.ts diff --git a/demo/demo23.js b/demo/demo23.js index ec38db901f..7fd5ebb6fb 100644 --- a/demo/demo23.js +++ b/demo/demo23.js @@ -15,6 +15,9 @@ const image5 = docx.Media.addImage(doc, "./demo/images/pizza.gif"); const imageBase64Data = `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` const image6 = docx.Media.addImageFromBuffer(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.addImage(image); doc.addImage(image2); doc.addImage(image3); diff --git a/src/file/file.ts b/src/file/file.ts index e742e0dd70..d7ef02b520 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -7,9 +7,9 @@ import { SectionPropertiesOptions } from "./document/body/section-properties/sec import { FooterWrapper } from "./footer-wrapper"; import { FootNotes } from "./footnotes"; import { HeaderWrapper } from "./header-wrapper"; -import { Media } from "./media"; +import { Image, Media } from "./media"; import { Numbering } from "./numbering"; -import { Bookmark, Hyperlink, Image, Paragraph } from "./paragraph"; +import { Bookmark, Hyperlink, Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Styles } from "./styles"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; @@ -126,19 +126,19 @@ export class File { public createImage(filePath: string): Image { const image = Media.addImage(this, filePath); - this.document.addParagraph(image); + this.document.addParagraph(image.Paragraph); return image; } public addImage(image: Image): File { - this.document.addParagraph(image); + this.document.addParagraph(image.Paragraph); return this; } public createImageFromBuffer(buffer: Buffer, width?: number, height?: number): Image { const image = Media.addImageFromBuffer(this, buffer, width, height); - this.document.addParagraph(image); + this.document.addParagraph(image.Paragraph); return image; } diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index b1bd4b534c..c1080bbd4e 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -1,7 +1,7 @@ import { XmlComponent } from "file/xml-components"; import { Footer } from "./footer/footer"; -import { Media } from "./media"; -import { Image, Paragraph } from "./paragraph"; +import { Image, Media } from "./media"; +import { ImageParagraph, Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Table } from "./table"; @@ -43,11 +43,11 @@ export class FooterWrapper { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - this.addImage(new Image(mediaData)); + this.addImage(new Image(new ImageParagraph(mediaData))); } public addImage(image: Image): FooterWrapper { - this.footer.addParagraph(image); + this.footer.addParagraph(image.Paragraph); return this; } diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index 8970dc2560..1053bc2096 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -1,7 +1,7 @@ import { XmlComponent } from "file/xml-components"; import { Header } from "./header/header"; -import { Media } from "./media"; -import { Image, Paragraph } from "./paragraph"; +import { Image, Media } from "./media"; +import { ImageParagraph, Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Table } from "./table"; @@ -43,11 +43,11 @@ export class HeaderWrapper { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - this.addImage(new Image(mediaData)); + this.addImage(new Image(new ImageParagraph(mediaData))); } public addImage(image: Image): HeaderWrapper { - this.header.addParagraph(image); + this.header.addParagraph(image.Paragraph); return this; } diff --git a/src/file/media/image.ts b/src/file/media/image.ts new file mode 100644 index 0000000000..8255fe7398 --- /dev/null +++ b/src/file/media/image.ts @@ -0,0 +1,13 @@ +import { ImageParagraph, PictureRun } from "../paragraph"; + +export class Image { + constructor(private readonly paragraph: ImageParagraph) {} + + public get Paragraph(): ImageParagraph { + return this.paragraph; + } + + public get Run(): PictureRun { + return this.paragraph.Run; + } +} diff --git a/src/file/media/index.ts b/src/file/media/index.ts index 3575274e26..2ccc436e68 100644 --- a/src/file/media/index.ts +++ b/src/file/media/index.ts @@ -1,2 +1,3 @@ export * from "./media"; export * from "./data"; +export * from "./image"; diff --git a/src/file/media/media.ts b/src/file/media/media.ts index e813a2c051..b0fb4019d8 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -3,8 +3,9 @@ import * as sizeOf from "image-size"; import * as path from "path"; import { File } from "../file"; -import { Image } from "../paragraph"; +import { ImageParagraph } from "../paragraph"; import { IMediaData } from "./data"; +import { Image } from "./image"; interface IHackedFile { currentRelationshipId: number; @@ -20,7 +21,7 @@ export class Media { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - return new Image(mediaData); + return new Image(new ImageParagraph(mediaData)); } public static addImageFromBuffer(file: File, buffer: Buffer, width?: number, height?: number): Image { @@ -39,7 +40,7 @@ export class Media { `media/${mediaData.fileName}`, ); - return new Image(mediaData); + return new Image(new ImageParagraph(mediaData)); } private static generateId(): string { diff --git a/src/file/paragraph/image.ts b/src/file/paragraph/image.ts index 214378853c..634f76e517 100644 --- a/src/file/paragraph/image.ts +++ b/src/file/paragraph/image.ts @@ -3,7 +3,7 @@ import { IMediaData } from "../media"; import { Paragraph } from "./paragraph"; import { PictureRun } from "./run"; -export class Image extends Paragraph { +export class ImageParagraph extends Paragraph { private readonly pictureRun: PictureRun; constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) { @@ -15,4 +15,8 @@ export class Image extends Paragraph { 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/paragraph.ts b/src/file/paragraph/paragraph.ts index 22e64fc643..a896044c8e 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -1,6 +1,6 @@ // http://officeopenxml.com/WPparagraph.php import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"; -import { IMediaData } from "file/media"; +import { Image } from "file/media"; import { Num } from "file/numbering/num"; import { XmlComponent } from "file/xml-components"; @@ -54,9 +54,10 @@ export class Paragraph extends XmlComponent { return run; } - public createPictureRun(imageData: IMediaData): PictureRun { - const run = new PictureRun(imageData); + public addImage(image: Image): PictureRun { + const run = image.Run; this.addRun(run); + return run; } From bb8c29f4a2bb5a755c61f30aaa2ae31608cf55e7 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 02:53:28 +0100 Subject: [PATCH 24/63] Fix tests --- src/file/paragraph/image.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file/paragraph/image.spec.ts b/src/file/paragraph/image.spec.ts index 658a99ff81..909a1ca3c3 100644 --- a/src/file/paragraph/image.spec.ts +++ b/src/file/paragraph/image.spec.ts @@ -2,7 +2,7 @@ import { assert, expect } from "chai"; import { Formatter } from "../../export/formatter"; -import { Image } from "./image"; +import { ImageParagraph } from "./image"; describe("Image", () => { let image: Image; From d961721b337cacd6c7f1486936e55fc278caee87 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 02:56:23 +0100 Subject: [PATCH 25/63] Refactor name --- src/file/paragraph/image.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/file/paragraph/image.spec.ts b/src/file/paragraph/image.spec.ts index 909a1ca3c3..45c06b0628 100644 --- a/src/file/paragraph/image.spec.ts +++ b/src/file/paragraph/image.spec.ts @@ -5,10 +5,10 @@ import { Formatter } from "../../export/formatter"; import { ImageParagraph } from "./image"; describe("Image", () => { - let image: Image; + let image: ImageParagraph; beforeEach(() => { - image = new Image({ + image = new ImageParagraph({ referenceId: 0, stream: new Buffer(""), path: "", From e9ea4845be04e378d041f22c5564469ffa2482f4 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 03:13:16 +0100 Subject: [PATCH 26/63] Improve README --- README.md | 22 ++++++---------------- docs/README.md | 10 ++++++++-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a24abcc0a7..f102c85f7e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

- Generate .docx files with JS/TS very easily, written in TS. + Easily generate .docx files with JS/TS.

--- @@ -19,13 +19,9 @@ # docx -drawing - -## Install - -```sh -$ npm install --save docx -``` +

+ drawing +

## Demo @@ -57,18 +53,12 @@ Please refer to [https://docx.js.org/](https://docx.js.org/) for details on how ## Examples -Check the examples section in the [documentation](https://docx.js.org/#/examples) and the [demo folder](https://github.com/dolanmiu/docx/tree/master/demo) for examples. +Check the `examples` section in the [documentation](https://docx.js.org/#/examples) and the [demo folder](https://github.com/dolanmiu/docx/tree/master/demo) for examples. -# Contributing +## Contributing Read the contribution guidelines [here](https://docx.js.org/#/contribution-guidelines). -# Honoured Mentions - -[@felipeochoa](https://github.com/felipeochoa) - -[@h4buli](https://github.com/h4buli) - --- Made with 💖 diff --git a/docs/README.md b/docs/README.md index 2ea6ac25e3..557bcbad65 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,11 +19,11 @@ npm install --save docx Then you can `require` or `import` as usual: ```js -let docx = require('docx'); +let docx = require("docx"); ``` ```js -import * as docx from 'docx' +import * as docx from "docx"; ``` ## Basic Usage @@ -48,6 +48,12 @@ exporter.pack("My First Document"); // Done! A file called 'My First Document.docx' will be in your file system if you used LocalPacker ``` +## Honoured Mentions + +[@felipeochoa](https://github.com/felipeochoa) + +[@h4buli](https://github.com/h4buli) + --- Made with 💖 From f6996a1d989ebc37a377b9521afc7babbebb62a8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 03:20:46 +0100 Subject: [PATCH 27/63] Update README --- README.md | 8 -------- docs/examples.md | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f102c85f7e..ad198e1d03 100644 --- a/README.md +++ b/README.md @@ -39,14 +39,6 @@ Press `endpoint` on the `RunKit` website: * https://runkit.com/dolanmiu/docx-demo8/1.0.1 - Header and Footer * https://runkit.com/dolanmiu/docx-demo10 - **My CV generated with docx** -#### Run demos locally: - -```sh -$ npm run demo -``` - -This command will run the demo selector app in the `demo` folder. It will prompt you to select a demo number, which will run a demo from that folder. - ## How to Please refer to [https://docx.js.org/](https://docx.js.org/) for details on how to use this library, examples and much more! diff --git a/docs/examples.md b/docs/examples.md index c2450496ca..cd811ded43 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -2,6 +2,14 @@ > All examples can run independently and can be found in the `/demo` folder of the project +All the examples below can be ran locally, to do so, run the following command: + +```sh +npm run demo +``` + +This command will run the `demo selector app` in the `/demo` folder. It will prompt you to select a demo number, which will run a demo from that folder. + ## Simple A simple hello world of the `docx` library: From 5e7c5aa620509b75865c9a4a9058855139b2e1c9 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 03:23:07 +0100 Subject: [PATCH 28/63] Fix typo --- docs/contribution-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md index e50ec54f54..5d1442fe0c 100644 --- a/docs/contribution-guidelines.md +++ b/docs/contribution-guidelines.md @@ -28,7 +28,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: ```js - public createParagraph(paragraph: Paragraph) { + public addParagraph(paragraph: Paragraph) { this.root.push(paragraph); } ``` From 0a698514631caaba091fd09ee8230bde0508c90f Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 11:51:27 +0100 Subject: [PATCH 29/63] Update README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ad198e1d03..a22b9d04f3 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,13 @@ [![Dependency Status][daviddm-image]][daviddm-url] [![Known Vulnerabilities][snky-image]][snky-url] [![Chat on Gitter][gitter-image]][gitter-url] -[![code style: prettier][prettier-image]][prettier-url] [![PRs Welcome][pr-image]][pr-url] -# docx -

drawing

-## Demo +# Demo Press `endpoint` on the `RunKit` website: @@ -39,15 +36,15 @@ Press `endpoint` on the `RunKit` website: * https://runkit.com/dolanmiu/docx-demo8/1.0.1 - Header and Footer * https://runkit.com/dolanmiu/docx-demo10 - **My CV generated with docx** -## How to +# How to use & Documentation -Please refer to [https://docx.js.org/](https://docx.js.org/) for details on how to use this library, examples and much more! +Please refer to the [https://docx.js.org/](documentation - https://docx.js.org/) for details on how to use this library, examples and much more! -## Examples +# Examples Check the `examples` section in the [documentation](https://docx.js.org/#/examples) and the [demo folder](https://github.com/dolanmiu/docx/tree/master/demo) for examples. -## Contributing +# Contributing Read the contribution guidelines [here](https://docx.js.org/#/contribution-guidelines). @@ -67,7 +64,5 @@ Made with 💖 [snky-url]: https://snyk.io/test/github/dolanmiu/docx [gitter-image]: https://badges.gitter.im/dolanmiu/docx.svg [gitter-url]: https://gitter.im/docx-lib/Lobby -[prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg -[prettier-url]: https://github.com/prettier/prettier [pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg [pr-url]: http://makeapullrequest.com From e9bd27bc554012b64bac67391039d81ebf6f50df Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 11:52:17 +0100 Subject: [PATCH 30/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a22b9d04f3..09b6c8d2e3 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Press `endpoint` on the `RunKit` website: # How to use & Documentation -Please refer to the [https://docx.js.org/](documentation - https://docx.js.org/) for details on how to use this library, examples and much more! +Please refer to the [documentation - https://docx.js.org/](https://docx.js.org/) for details on how to use this library, examples and much more! # Examples From d9716a1cf766c45466c9715c5c2314e41d247e1a Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 11:52:47 +0100 Subject: [PATCH 31/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 09b6c8d2e3..84b4a75e0b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Press `endpoint` on the `RunKit` website: # How to use & Documentation -Please refer to the [documentation - https://docx.js.org/](https://docx.js.org/) for details on how to use this library, examples and much more! +Please refer to the [documentation at https://docx.js.org/](https://docx.js.org/) for details on how to use this library, examples and much more! # Examples From d8252141fed81a57b434f988018b3adc1dc15c89 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 11:54:05 +0100 Subject: [PATCH 32/63] Update tsconfig.json --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 8e716e322f..4ef656d049 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,7 @@ "**/_*" ], "typedocOptions": { - "mode": "modules", + "mode": "file", "out": "docs/api", "exclude": "test", "theme": "default", From f264e4d0f7e053f56a890ba4c611194e4d2b82bd Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 21:58:50 +0100 Subject: [PATCH 33/63] Add scale method to image --- src/file/media/image.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/file/media/image.ts b/src/file/media/image.ts index 8255fe7398..b596f77d9d 100644 --- a/src/file/media/image.ts +++ b/src/file/media/image.ts @@ -10,4 +10,8 @@ export class Image { public get Run(): PictureRun { return this.paragraph.Run; } + + public scale(factorX: number, factorY?: number): void { + this.paragraph.Run.scale(factorX, factorY); + } } From 89df3c48e00f664369321606bb7907b7741c0161 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 23:22:03 +0100 Subject: [PATCH 34/63] Fix linting errors --- src/file/document/body/body.ts | 3 +- .../page-border/page-borders.spec.ts | 2 +- .../page-border/page-borders.ts | 42 ++++++++++++------- .../section-properties/section-properties.ts | 7 +--- src/file/file.ts | 3 +- src/file/media/media.ts | 10 ++--- src/file/numbering/level.ts | 2 +- src/file/styles/external-styles-factory.ts | 4 +- 8 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index 7fc0e98f38..e274fa359f 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -1,7 +1,6 @@ import { IXmlableObject, XmlComponent } from "file/xml-components"; -import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; import { Paragraph, ParagraphProperties } from "../.."; -import { SectionProperties, SectionPropertiesOptions } from "./section-properties"; +import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; export class Body extends XmlComponent { private readonly defaultSection: SectionProperties; diff --git a/src/file/document/body/section-properties/page-border/page-borders.spec.ts b/src/file/document/body/section-properties/page-border/page-borders.spec.ts index 782280f292..66abb9cc66 100644 --- a/src/file/document/body/section-properties/page-border/page-borders.spec.ts +++ b/src/file/document/body/section-properties/page-border/page-borders.spec.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; import { Formatter } from "../../../../../export/formatter"; -import { PageBorders, PageBorderDisplay, PageBorderZOrder } from "./page-borders"; import { BorderStyle } from "../../../../styles"; +import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders"; describe("PageBorders", () => { describe("#constructor()", () => { diff --git a/src/file/document/body/section-properties/page-border/page-borders.ts b/src/file/document/body/section-properties/page-border/page-borders.ts index 88b6ce98dd..0af96cfd41 100644 --- a/src/file/document/body/section-properties/page-border/page-borders.ts +++ b/src/file/document/body/section-properties/page-border/page-borders.ts @@ -1,5 +1,5 @@ // http://officeopenxml.com/WPsectionBorders.php -import { XmlComponent, XmlAttributeComponent, IXmlableObject } from "file/xml-components"; +import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components"; import { BorderStyle } from "../../../../styles"; export enum PageBorderDisplay { @@ -24,22 +24,22 @@ export interface IPageBorderAttributes { zOrder?: PageBorderZOrder; } -export interface PageBorderConfiguration { +export interface IPageBorderConfiguration { style?: BorderStyle; size?: number; color?: string; space?: number; } -export type PageBordersOptions = { +export interface IPageBordersOptions { pageBorders?: IPageBorderAttributes; - pageBorderTop?: PageBorderConfiguration; - pageBorderRight?: PageBorderConfiguration; - pageBorderBottom?: PageBorderConfiguration; - pageBorderLeft?: PageBorderConfiguration; -}; + pageBorderTop?: IPageBorderConfiguration; + pageBorderRight?: IPageBorderConfiguration; + pageBorderBottom?: IPageBorderConfiguration; + pageBorderLeft?: IPageBorderConfiguration; +} -class PageBordeAttributes extends XmlAttributeComponent { +class PageBordeAttributes extends XmlAttributeComponent { protected xmlKeys = { style: "w:val", size: "w:size", @@ -49,7 +49,7 @@ class PageBordeAttributes extends XmlAttributeComponent } class PageBorder extends XmlComponent { - constructor(key: string, options: PageBorderConfiguration) { + constructor(key: string, options: IPageBorderConfiguration) { super(key); this.root.push(new PageBordeAttributes(options)); @@ -65,10 +65,12 @@ class PageBordersAttributes extends XmlAttributeComponent } export class PageBorders extends XmlComponent { - constructor(options?: PageBordersOptions) { + constructor(options?: IPageBordersOptions) { super("w:pgBorders"); - if (!options) return; + if (!options) { + return; + } let pageBordersAttributes = {}; @@ -82,10 +84,18 @@ export class PageBorders extends XmlComponent { this.root.push(new PageBordersAttributes(pageBordersAttributes)); - if (options.pageBorderTop) this.root.push(new PageBorder("w:top", options.pageBorderTop)); - if (options.pageBorderRight) this.root.push(new PageBorder("w:right", options.pageBorderRight)); - if (options.pageBorderBottom) this.root.push(new PageBorder("w:bottom", options.pageBorderBottom)); - if (options.pageBorderLeft) this.root.push(new PageBorder("w:left", options.pageBorderLeft)); + if (options.pageBorderTop) { + this.root.push(new PageBorder("w:top", options.pageBorderTop)); + } + if (options.pageBorderRight) { + this.root.push(new PageBorder("w:right", options.pageBorderRight)); + } + if (options.pageBorderBottom) { + this.root.push(new PageBorder("w:bottom", options.pageBorderBottom)); + } + if (options.pageBorderLeft) { + this.root.push(new PageBorder("w:left", options.pageBorderLeft)); + } } public prepForXml(): IXmlableObject { diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index 33d0a7a0ae..c23964cd14 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -1,6 +1,6 @@ // http://officeopenxml.com/WPsection.php import { XmlComponent } from "file/xml-components"; -import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberFormat, PageNumberType } from "./"; +import { FooterReferenceType, IPageBordersOptions, IPageNumberTypeAttributes, PageBorders, PageNumberFormat, PageNumberType } from "./"; import { Columns } from "./columns/columns"; import { IColumnsAttributes } from "./columns/columns-attributes"; import { DocumentGrid } from "./doc-grid/doc-grid"; @@ -12,9 +12,6 @@ import { PageMargin } from "./page-margin/page-margin"; import { IPageMarginAttributes } from "./page-margin/page-margin-attributes"; import { PageSize } from "./page-size/page-size"; import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes"; -import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberType, PageNumberFormat } from "."; -// import { TitlePage } from "./title-page/title-page"; -import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberType, PageNumberFormat, PageBordersOptions, PageBorders } from "."; export type SectionPropertiesOptions = IPageSizeAttributes & IPageMarginAttributes & @@ -23,7 +20,7 @@ export type SectionPropertiesOptions = IPageSizeAttributes & IHeaderOptions & IFooterOptions & IPageNumberTypeAttributes & - PageBordersOptions; + IPageBordersOptions; export class SectionProperties extends XmlComponent { private readonly options: SectionPropertiesOptions; diff --git a/src/file/file.ts b/src/file/file.ts index 83d0c8c53b..2482d9b39c 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -2,7 +2,7 @@ import { AppProperties } from "./app-properties/app-properties"; import { ContentTypes } from "./content-types/content-types"; import { CoreProperties, IPropertiesOptions } from "./core-properties"; import { Document } from "./document"; -import { FooterReferenceType, HeaderReference, HeaderReferenceType } from "./document/body/section-properties"; +import { FooterReferenceType, HeaderReference, HeaderReferenceType, SectionPropertiesOptions } from "./document/body/section-properties"; import { FooterWrapper } from "./footer-wrapper"; import { FootNotes } from "./footnotes"; import { HeaderWrapper } from "./header-wrapper"; @@ -14,7 +14,6 @@ import { Styles } from "./styles"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; import { DefaultStylesFactory } from "./styles/factory"; import { Table } from "./table"; -import { FooterReferenceType, HeaderReferenceType, SectionPropertiesOptions } from "./document/body/section-properties"; export class File { private readonly document: Document; diff --git a/src/file/media/media.ts b/src/file/media/media.ts index e8e6044569..aea65777f0 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -61,8 +61,6 @@ export class Media { this.map = new Map(); } - x: Math.round(dimensions.width * 9525), - y: Math.round(dimensions.height * 9525), public getMedia(key: string): IMediaData { const data = this.map.get(key); @@ -108,12 +106,12 @@ export class Media { fileName: key, dimensions: { pixels: { - x: dimensions.width, - y: dimensions.height, + x: Math.round(dimensions.width), + y: Math.round(dimensions.height), }, emus: { - x: dimensions.width * 9525, - y: dimensions.height * 9525, + x: Math.round(dimensions.width * 9525), + y: Math.round(dimensions.height * 9525), }, }, }; diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts index 0df90758fb..8bdc7ff8d7 100644 --- a/src/file/numbering/level.ts +++ b/src/file/numbering/level.ts @@ -110,7 +110,7 @@ export class LevelBase extends XmlComponent { this.root.push(this.runProperties); } - public setSuffix(value: LevelSuffix) { + public setSuffix(value: LevelSuffix): LevelBase { this.root.push(new Suffix(value)); return this; } diff --git a/src/file/styles/external-styles-factory.ts b/src/file/styles/external-styles-factory.ts index 303d563907..301211bdc7 100644 --- a/src/file/styles/external-styles-factory.ts +++ b/src/file/styles/external-styles-factory.ts @@ -1,7 +1,5 @@ import * as fastXmlParser from "fast-xml-parser"; -import { ImportedXmlComponent, ImportedRootElementAttributes, parseOptions, convertToXmlComponent } from "./../../file/xml-components"; -import { convertToXmlComponent, ImportedRootElementAttributes, ImportedXmlComponent, parseOptions } from "file/xml-components"; -import { ImportedRootElementAttributes, parseOptions, convertToXmlComponent } from "./../../file/xml-components"; +import { convertToXmlComponent, ImportedRootElementAttributes, parseOptions } from "file/xml-components"; import { Styles } from "./"; export class ExternalStylesFactory { From 5f594a822fc2b4a89e2c82c5ca255f9ac05eefa7 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 23:29:40 +0100 Subject: [PATCH 35/63] Fix and enable linting on tests --- src/file/content-types/content-types.spec.ts | 3 +++ .../body/section-properties/section-properties.spec.ts | 2 +- src/file/drawing/floating/simple-pos.spec.ts | 2 +- src/file/styles/external-styles-factory.spec.ts | 5 ++++- src/file/table/table-cell.spec.ts | 2 +- src/file/xml-components/imported-xml-component.spec.ts | 6 ++++-- tsconfig.json | 1 - 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/file/content-types/content-types.spec.ts b/src/file/content-types/content-types.spec.ts index 14665df4ee..7e9b62c88f 100644 --- a/src/file/content-types/content-types.spec.ts +++ b/src/file/content-types/content-types.spec.ts @@ -1,6 +1,9 @@ +// tslint:disable:no-string-literal + import { expect } from "chai"; import { Formatter } from "../../export/formatter"; import { ContentTypes } from "./content-types"; + describe("ContentTypes", () => { let contentTypes: ContentTypes; diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts index b2499bbd63..e80facb635 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; import { Formatter } from "../../../../export/formatter"; +import { FooterReferenceType, PageBorderOffsetFrom, PageNumberFormat } from "./"; import { SectionProperties } from "./section-properties"; -import { FooterReferenceType, PageNumberFormat, PageBorderOffsetFrom } from "."; describe("SectionProperties", () => { describe("#constructor()", () => { diff --git a/src/file/drawing/floating/simple-pos.spec.ts b/src/file/drawing/floating/simple-pos.spec.ts index a86739b7b0..5eee49f4c1 100644 --- a/src/file/drawing/floating/simple-pos.spec.ts +++ b/src/file/drawing/floating/simple-pos.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; -import { SimplePos } from "./simple-pos"; import { Utility } from "../../../tests/utility"; +import { SimplePos } from "./simple-pos"; describe("SimplePos", () => { describe("#constructor()", () => { diff --git a/src/file/styles/external-styles-factory.spec.ts b/src/file/styles/external-styles-factory.spec.ts index e34bfbaa8d..295c9644f6 100644 --- a/src/file/styles/external-styles-factory.spec.ts +++ b/src/file/styles/external-styles-factory.spec.ts @@ -22,7 +22,7 @@ describe("External styles factory", () => { - + @@ -48,6 +48,7 @@ describe("External styles factory", () => { describe("#parse", () => { it("should parse w:styles attributes", () => { + // tslint:disable-next-line:no-any const importedStyle = new ExternalStylesFactory().newInstance(externalStyles) as any; expect(importedStyle.rootKey).to.equal("w:styles"); @@ -58,6 +59,7 @@ describe("External styles factory", () => { }); it("should parse other child elements of w:styles", () => { + // tslint:disable-next-line:no-any const importedStyle = new ExternalStylesFactory().newInstance(externalStyles) as any; expect(importedStyle.root.length).to.equal(5); @@ -134,6 +136,7 @@ describe("External styles factory", () => { }); it("should parse styles elements", () => { + // tslint:disable-next-line:no-any const importedStyle = new ExternalStylesFactory().newInstance(externalStyles) as any; expect(importedStyle.root.length).to.equal(5); diff --git a/src/file/table/table-cell.spec.ts b/src/file/table/table-cell.spec.ts index 4e69e958a8..7a3072f186 100644 --- a/src/file/table/table-cell.spec.ts +++ b/src/file/table/table-cell.spec.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; -import { TableCellBorders, TableCellWidth, WidthType } from "./table-cell"; import { Formatter } from "../../export/formatter"; import { BorderStyle } from "../styles"; +import { TableCellBorders, TableCellWidth, WidthType } from "./table-cell"; describe("TableCellBorders", () => { describe("#prepForXml", () => { diff --git a/src/file/xml-components/imported-xml-component.spec.ts b/src/file/xml-components/imported-xml-component.spec.ts index e941d3f0ec..beed8cf09a 100644 --- a/src/file/xml-components/imported-xml-component.spec.ts +++ b/src/file/xml-components/imported-xml-component.spec.ts @@ -1,5 +1,5 @@ import { expect } from "chai"; -import { ImportedXmlComponent, convertToXmlComponent } from "./"; +import { convertToXmlComponent, ImportedXmlComponent } from "./"; const xmlString = ` @@ -11,10 +11,11 @@ const xmlString = ` Text 2 - + `; +// tslint:disable:object-literal-key-quotes const importedXmlElement = { "w:p": { _attr: { "w:one": "value 1", "w:two": "value 2" }, @@ -22,6 +23,7 @@ const importedXmlElement = { "w:r": [{ _attr: { active: "true" }, "w:t": "Text 1" }, { _attr: { active: "true" }, "w:t": "Text 2" }], }, }; +// tslint:enable:object-literal-key-quotes const convertedXmlElement = { deleted: false, diff --git a/tsconfig.json b/tsconfig.json index 4ef656d049..53730ebdfd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,6 @@ "exclude": [ "node_modules", "tests", - "**/*.spec.ts", "**/_*" ], "typedocOptions": { From ad356d27596c57d2d0e5a2b8d15c5430a96da3a8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 9 Aug 2018 23:40:11 +0100 Subject: [PATCH 36/63] Add ignores so it doesnt get generated in documentation --- src/export/packer/packer.ts | 3 +++ src/file/media/data.ts | 3 +++ src/file/xml-components/xmlable-object.ts | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index 64fa05a9aa..848924f457 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -3,4 +3,7 @@ export interface IPacker { } // Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 +/** + * @ignore + */ export const WORKAROUND = ""; diff --git a/src/file/media/data.ts b/src/file/media/data.ts index cbc7d8c5bf..dfc7a664a0 100644 --- a/src/file/media/data.ts +++ b/src/file/media/data.ts @@ -20,4 +20,7 @@ export interface IMediaData { } // Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 +/** + * @ignore + */ export const WORKAROUND2 = ""; diff --git a/src/file/xml-components/xmlable-object.ts b/src/file/xml-components/xmlable-object.ts index 9fa0d5b600..255df14fc2 100644 --- a/src/file/xml-components/xmlable-object.ts +++ b/src/file/xml-components/xmlable-object.ts @@ -3,4 +3,7 @@ export interface IXmlableObject extends Object { } // Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 -export const WORKAROUND3 = "workaround"; +/** + * @ignore + */ +export const WORKAROUND3 = ""; From d850f379047222a3cb177163a4a236c1a9e3db38 Mon Sep 17 00:00:00 2001 From: Dolan Date: Fri, 10 Aug 2018 01:49:37 +0100 Subject: [PATCH 37/63] Remove unused import --- src/file/drawing/drawing.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 70d36f2110..208be2991a 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -1,5 +1,4 @@ import { assert } from "chai"; -import * as fs from "fs"; import { Utility } from "../../tests/utility"; import { Drawing, IDrawingOptions, PlacementPosition } from "./"; From bc1132146f6911e2d630d06623d3e923105ff6ed Mon Sep 17 00:00:00 2001 From: Dolan Date: Fri, 10 Aug 2018 02:46:15 +0100 Subject: [PATCH 38/63] Revert test changes --- src/file/drawing/drawing.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 208be2991a..cf3f926315 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -1,4 +1,5 @@ import { assert } from "chai"; +import * as fs from "fs"; import { Utility } from "../../tests/utility"; import { Drawing, IDrawingOptions, PlacementPosition } from "./"; @@ -9,6 +10,7 @@ function createDrawing(drawingOptions?: IDrawingOptions): Drawing { { fileName: "test.jpg", referenceId: 1, + stream: fs.createReadStream(path), path: path, dimensions: { pixels: { From 675192b86fc5cad868442a18c33f1725f597dd59 Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 12 Aug 2018 23:07:31 +0100 Subject: [PATCH 39/63] Refactor image to accept Buffer only --- demo/demo11.js | 5 +++-- demo/demo12.js | 9 ++++---- demo/demo18.js | 4 ++-- demo/demo5.js | 11 +++++----- demo/demo9.js | 5 +++-- docs/usage/headers-and-footers.md | 4 ++-- docs/usage/images.md | 4 ++-- src/file/file.ts | 11 ++-------- src/file/footer-wrapper.ts | 4 ++-- src/file/header-wrapper.ts | 4 ++-- src/file/media/data.ts | 4 +--- src/file/media/media.ts | 36 +++++-------------------------- 12 files changed, 35 insertions(+), 66 deletions(-) diff --git a/demo/demo11.js b/demo/demo11.js index 2c6305106e..f0597e0da4 100644 --- a/demo/demo11.js +++ b/demo/demo11.js @@ -1,4 +1,5 @@ const docx = require("../build"); +const fs = require('fs'); const doc = new docx.Document(undefined, { top: 700, @@ -80,7 +81,7 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") .quickFormat() .basedOn("Normal"); -doc.createImage("./demo/images/pizza.gif"); +doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); doc .createParagraph("HEADING") .heading1() @@ -122,7 +123,7 @@ var arrboth = [{ arrboth.forEach(function(item) { const para = doc.createParagraph(); - para.createTextRun(doc.createImage(item.image)); + para.createTextRun(doc.createImage(fs.readFileSync(item.image))); para.properties.width = 60; para.properties.height = 90; doc.createParagraph(item.comment).style("normalPara2"); diff --git a/demo/demo12.js b/demo/demo12.js index 7fd5eb5ffc..87c7a405e0 100644 --- a/demo/demo12.js +++ b/demo/demo12.js @@ -1,14 +1,15 @@ const docx = require("../build"); +const fs = require('fs'); var doc = new docx.Document(); var paragraph = new docx.Paragraph("Hello World"); doc.addParagraph(paragraph); -const image = doc.createImage("./demo/images/pizza.gif"); -const image2 = doc.createImage("./demo/images/pizza.gif"); -const image3 = doc.createImage("./demo/images/pizza.gif"); -const image4 = doc.createImage("./demo/images/pizza.gif"); +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) diff --git a/demo/demo18.js b/demo/demo18.js index 9035d19e7a..73a778a6c3 100644 --- a/demo/demo18.js +++ b/demo/demo18.js @@ -6,8 +6,8 @@ var doc = new docx.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.createImageFromBuffer(Buffer.from(imageBase64Data, 'base64')); -doc.createImageFromBuffer(Buffer.from(imageBase64Data, 'base64'), 100, 100); +// doc.createImage(Buffer.from(imageBase64Data, 'base64')); +doc.createImage(Buffer.from(imageBase64Data, 'base64'), 100, 100); var exporter = new docx.LocalPacker(doc); exporter.pack('My Document'); diff --git a/demo/demo5.js b/demo/demo5.js index 89638ad49b..fbb2cd0eaf 100644 --- a/demo/demo5.js +++ b/demo/demo5.js @@ -1,15 +1,16 @@ const docx = require("../build"); +const fs = require('fs'); var doc = new docx.Document(); var paragraph = new docx.Paragraph("Hello World"); doc.addParagraph(paragraph); -doc.createImage("./demo/images/image1.jpeg"); -doc.createImage("./demo/images/dog.png"); -doc.createImage("./demo/images/cat.jpg"); -doc.createImage("./demo/images/parrots.bmp"); -doc.createImage("./demo/images/pizza.gif"); +doc.createImage(fs.readFileSync("./demo/images/image1.jpeg")); +doc.createImage(fs.readFileSync("./demo/images/dog.png")); +doc.createImage(fs.readFileSync("./demo/images/cat.jpg")); +doc.createImage(fs.readFileSync("./demo/images/parrots.bmp")); +doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); var exporter = new docx.LocalPacker(doc); exporter.pack("My Document"); diff --git a/demo/demo9.js b/demo/demo9.js index c93d8fa63c..c0a57cf8f6 100644 --- a/demo/demo9.js +++ b/demo/demo9.js @@ -1,11 +1,12 @@ const docx = require('../build'); +const fs = require('fs'); var doc = new docx.Document(); doc.createParagraph("Hello World"); -doc.Header.createImage("./demo/images/pizza.gif"); -doc.Footer.createImage("./demo/images/pizza.gif"); +doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); +doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); var exporter = new docx.LocalPacker(doc); exporter.pack('My Document'); diff --git a/docs/usage/headers-and-footers.md b/docs/usage/headers-and-footers.md index bfe626a04c..1489576dda 100644 --- a/docs/usage/headers-and-footers.md +++ b/docs/usage/headers-and-footers.md @@ -19,8 +19,8 @@ doc.Footer.createParagraph("Footer text"); Even add images: ```js -doc.Header.createImage([PATH_TO_YOUR_IMAGE]); -doc.Footer.createImage([PATH_TO_YOUR_IMAGE]); +doc.Header.createImage([BUFFER_OF_YOUR_IMAGE]); +doc.Footer.createImage([BUFFER_OF_YOUR_IMAGE]); ``` Refer to `demo8.js` for more information diff --git a/docs/usage/images.md b/docs/usage/images.md index 2cc0339507..a89fa893cd 100644 --- a/docs/usage/images.md +++ b/docs/usage/images.md @@ -7,7 +7,7 @@ Adding images is very simple Simply call the `createImage` method: ```js -const image = doc.createImage([PATH_TO_YOUR_IMAGE]); +const image = doc.createImage([BUFFER_OF_YOUR_IMAGE]); ``` `docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png` @@ -43,7 +43,7 @@ interface DrawingOptions { can be passed when creating `PictureRun()` for example: ```js -const imageData = document.createImageData(filename, buffer, 903, 1149); +const imageData = document.createImage(buffer, 903, 1149); new docx.PictureRun(imageData, { position: docx.PlacementPosition.FLOATING, diff --git a/src/file/file.ts b/src/file/file.ts index d7ef02b520..becc713176 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -124,20 +124,13 @@ export class File { return this.document.createTable(rows, cols); } - public createImage(filePath: string): Image { - const image = Media.addImage(this, filePath); - this.document.addParagraph(image.Paragraph); - - return image; - } - public addImage(image: Image): File { this.document.addParagraph(image.Paragraph); return this; } - public createImageFromBuffer(buffer: Buffer, width?: number, height?: number): Image { - const image = Media.addImageFromBuffer(this, buffer, width, height); + public createImage(buffer: Buffer, width?: number, height?: number): Image { + const image = Media.addImage(this, buffer, width, height); this.document.addParagraph(image.Paragraph); return image; diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index c1080bbd4e..afd673c2b2 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -36,8 +36,8 @@ export class FooterWrapper { this.footer.addChildElement(childElement); } - public createImage(image: string): void { - const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount); + public createImage(image: Buffer, width?: number, height?: number): void { + const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount, width, height); this.relationships.createRelationship( mediaData.referenceId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index 1053bc2096..79a216610a 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -36,8 +36,8 @@ export class HeaderWrapper { this.header.addChildElement(childElement); } - public createImage(image: string): void { - const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount); + public createImage(image: Buffer, width?: number, height?: number): void { + const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount, width, height); this.relationships.createRelationship( mediaData.referenceId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", diff --git a/src/file/media/data.ts b/src/file/media/data.ts index dfc7a664a0..9ac7ab5eee 100644 --- a/src/file/media/data.ts +++ b/src/file/media/data.ts @@ -1,5 +1,3 @@ -import * as fs from "fs"; - export interface IMediaDataDimensions { pixels: { x: number; @@ -13,7 +11,7 @@ export interface IMediaDataDimensions { export interface IMediaData { referenceId: number; - stream: fs.ReadStream | Buffer; + stream: Buffer; path?: string; fileName: string; dimensions: IMediaDataDimensions; diff --git a/src/file/media/media.ts b/src/file/media/media.ts index b0fb4019d8..f2cb71aa2f 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,6 +1,4 @@ -import * as fs from "fs"; import * as sizeOf from "image-size"; -import * as path from "path"; import { File } from "../file"; import { ImageParagraph } from "../paragraph"; @@ -12,28 +10,10 @@ interface IHackedFile { } export class Media { - public static addImage(file: File, filePath: string): Image { + public static addImage(file: File, buffer: Buffer, width?: number, height?: number): Image { // Workaround to expose id without exposing to API const exposedFile = (file as {}) as IHackedFile; - const mediaData = file.Media.addMedia(filePath, exposedFile.currentRelationshipId++); - file.DocumentRelationships.createRelationship( - mediaData.referenceId, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - `media/${mediaData.fileName}`, - ); - return new Image(new ImageParagraph(mediaData)); - } - - public static addImageFromBuffer(file: File, buffer: Buffer, width?: number, height?: number): Image { - // Workaround to expose id without exposing to API - const exposedFile = (file as {}) as IHackedFile; - const mediaData = file.Media.addMediaFromBuffer( - `${Media.generateId()}.png`, - buffer, - exposedFile.currentRelationshipId++, - width, - height, - ); + const mediaData = file.Media.addMedia(buffer, exposedFile.currentRelationshipId++, width, height); file.DocumentRelationships.createRelationship( mediaData.referenceId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", @@ -71,14 +51,8 @@ export class Media { return data; } - public addMedia(filePath: string, referenceId: number): IMediaData { - const key = path.basename(filePath); - const dimensions = sizeOf(filePath); - return this.createMedia(key, referenceId, dimensions, fs.createReadStream(filePath), filePath); - } - - public addMediaFromBuffer(fileName: string, buffer: Buffer, referenceId: number, width?: number, height?: number): IMediaData { - const key = fileName; + public addMedia(buffer: Buffer, referenceId: number, width?: number, height?: number): IMediaData { + const key = `${Media.generateId()}.png`; let dimensions; if (width && height) { dimensions = { @@ -96,7 +70,7 @@ export class Media { key: string, relationshipsCount: number, dimensions: { width: number; height: number }, - data: fs.ReadStream | Buffer, + data: Buffer, filePath?: string, ): IMediaData { const imageData = { From a38abeb4c2c018e69def58ff49d79ec30421be5e Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 14 Aug 2018 01:46:48 +0100 Subject: [PATCH 40/63] Huge refactoring to use new compiler and deprecate all other Packers Add new PdfPacker --- My Document.pdf | 519 ++++++++++++++++++ demo/demo1.js | 8 +- demo/demo26.js | 21 + src/export/index.ts | 5 +- src/export/packer/browser.ts | 17 - src/export/packer/buffer-stream.ts | 28 - src/export/packer/buffer.ts | 20 - src/export/packer/express.spec.ts | 43 -- src/export/packer/express.ts | 32 -- src/export/packer/local.spec.ts | 66 --- src/export/packer/local.ts | 57 -- src/export/packer/next-compiler.spec.ts | 66 +++ src/export/packer/next-compiler.ts | 63 ++- .../packer/{buffer.spec.ts => packer.spec.ts} | 22 +- src/export/packer/packer.ts | 38 +- src/export/packer/pdf-packer.spec.ts | 48 ++ .../{pdf-convert-wrapper.ts => pdf-packer.ts} | 25 +- src/export/packer/stream.ts | 25 - src/file/drawing/drawing.spec.ts | 2 +- 19 files changed, 760 insertions(+), 345 deletions(-) create mode 100644 My Document.pdf create mode 100644 demo/demo26.js delete mode 100644 src/export/packer/browser.ts delete mode 100644 src/export/packer/buffer-stream.ts delete mode 100644 src/export/packer/buffer.ts delete mode 100644 src/export/packer/express.spec.ts delete mode 100644 src/export/packer/express.ts delete mode 100644 src/export/packer/local.spec.ts delete mode 100644 src/export/packer/local.ts create mode 100644 src/export/packer/next-compiler.spec.ts rename src/export/packer/{buffer.spec.ts => packer.spec.ts} (72%) create mode 100644 src/export/packer/pdf-packer.spec.ts rename src/export/packer/{pdf-convert-wrapper.ts => pdf-packer.ts} (66%) delete mode 100644 src/export/packer/stream.ts diff --git a/My Document.pdf b/My Document.pdf new file mode 100644 index 0000000000..0a2b5bf7bf --- /dev/null +++ b/My Document.pdf @@ -0,0 +1,519 @@ + + + + + + Convert DOC to PDF Online | Convert DOCX to PDF Online | Convert Word to PDF Online | Free online converter + + + + + + +
+
+ + + +
+ + + + + + + + + + +
+ + +
+ +
+
+ + + + + + + +
+
+ + + + +
+
+
+ + + + + + + + + +
+ +

+ WELCOME TO 100% FREE WORD TO PDF ONLINE CONVERTER

+
+ +

+ You can convert DOC to PDF and DOCX to PDF for free

+
+
+ + + + + +
+
+
+ Advantages of our free service +
+
+
    +
  1. Absolutely 100% free service
  2. +
  3. No need to have MS Word on your PC (your file is converted on our servers)
  4. +
  5. Produced PDF 100% matches your MS Word document
  6. +
  7. High quality PDF
  8. +
  9. Pictures are not lost
  10. +
  11. MS Word documents in all languages are supported
  12. +
  13. No personal information is required (file is returned to your Internet browser)
  14. +
  15. Conversion of ZIP archives
  16. +
  17. Immediate conversion
  18. +
+ +
+
+
+
+ + + +
+
+
+
+
+
+ +
+
+
+

+ Convert one file online: + How it works

+
+ +
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+ +
+ +   + +
+ Document is not an MS Word document inside it just has .DOC/.DOCX extension or damaged +
+
+
+
+ On this page you can only convert DOC DOCX to + PDF.
+
    +
  • To convert several files, please, use tab Convert zipped files.
  • To convert RTF + ODT MHT HTM HTML TXT FB2 DOT DOTX XLS XLSX XLSB ODS XLT XLTX PPT PPTX PPS PPSX ODP + POT POTX to PDF, please, use the following link Other documents to PDF.
  • To convert JPG JPEG PNG + BMP GIF TIF TIFF to PDF, please, use the following link Image to PDF.
  • +
  • To extract text from PDF, please, use the following link PDF to TXT.
  • To convert DOC DOCX RTF ODT MHT HTM HTML + TXT FB2 DOT DOTX to DOC DOCX DOT ODT RTF TXT or XLS XLSX XLSB XLT XLTX ODS to XLS + XLSX or PPT PPTX PPS PPSX ODP POT POTX to PPT PPTX PPS PPSX JPG TIF PNG GIF BMP, + please, use the following link Other formats.
  • To convert DOC DOCX DOT DOTX RTF + ODT MHT HTM HTML TXT to FB2, please, use the following link Documents to FB2.
  • To + convert JPG JPEG JFIF PNG BMP GIF TIF ICO to other image formats, please, use the + following link + Convert Image.
  • +
  • To convert PDF to MS Word (DOC, DOCX), please, use the following link Convert PDF to Word. +
  • +
  • To convert PDF to JPG, please, use the following link Convert PDF to JPG.
  • +
  • To convert DJVU to PDF, please, use the following link Convert DJVU to PDF.
  • +
  • To recognize text in a PDF or in an image, please, use the following link Recognize + text in PDF or in image.
  • +
+
+
+ +
+
+ + + + +
+
+
+
+
+ + +
+
+ +
+
+
+ + TERMS OF SERVICE
+
+ +
+
+
+
+
+
+ + + + +
+
+ +
+
+ + + + + + + +
+ + + + + + + + + + + + + diff --git a/demo/demo1.js b/demo/demo1.js index 53e0e58834..fc8d4c31a1 100644 --- a/demo/demo1.js +++ b/demo/demo1.js @@ -1,4 +1,5 @@ const docx = require('../build'); +const fs = require('fs'); var doc = new docx.Document(); @@ -10,7 +11,10 @@ paragraph.addRun(dateText); doc.addParagraph(paragraph); -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); +var packer = new docx.Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync('My Document.docx', buffer); +}); console.log('Document created successfully at project root!'); diff --git a/demo/demo26.js b/demo/demo26.js new file mode 100644 index 0000000000..c88fdaea8e --- /dev/null +++ b/demo/demo26.js @@ -0,0 +1,21 @@ +const docx = require('../build'); +const fs = require('fs'); + +var doc = new docx.Document(); + +var paragraph = new docx.Paragraph("Hello World"); +var institutionText = new docx.TextRun("University College London").bold(); +var dateText = new docx.TextRun("5th Dec 2015").tab().bold(); +paragraph.addRun(institutionText); +paragraph.addRun(dateText); + +doc.addParagraph(paragraph); + +var packer = new docx.PdfPacker(); + +packer.toBuffer(doc).then((buffer) => { + console.log(buffer); + fs.writeFileSync('My Document.pdf', buffer); +}); + +console.log('Document created successfully at project root!'); diff --git a/src/export/index.ts b/src/export/index.ts index f6a47e4826..1a661debc6 100644 --- a/src/export/index.ts +++ b/src/export/index.ts @@ -1,5 +1,2 @@ -export * from "./packer/local"; -export * from "./packer/express"; export * from "./packer/packer"; -export * from "./packer/stream"; -export * from "./packer/buffer"; +export * from "./packer/pdf-packer"; diff --git a/src/export/packer/browser.ts b/src/export/packer/browser.ts deleted file mode 100644 index ad88a5552c..0000000000 --- a/src/export/packer/browser.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Compiler } from "./next-compiler"; -import { IPacker } from "./packer"; - -declare var saveAs; - -export class BrowserPacker implements IPacker { - private readonly packer: Compiler; - - public async pack(filePath: string): Promise { - filePath = filePath.replace(/.docx$/, ""); - - const zip = await this.packer.compile(); - const zipBlob = await zip.generateAsync({ type: "blob" }); - - saveAs(zipBlob, `${filePath}.docx`); - } -} diff --git a/src/export/packer/buffer-stream.ts b/src/export/packer/buffer-stream.ts deleted file mode 100644 index e0d2f8ed73..0000000000 --- a/src/export/packer/buffer-stream.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Writable } from "stream"; - -export class BufferStream extends Writable { - private readonly data: Buffer[]; - - constructor() { - super(); - - this.data = []; - } - - // tslint:disable-next-line:no-any - public _write(chunk: any, _: string, next: (err?: Error) => void): void { - this.data.push(Buffer.from(chunk)); - next(); - } - - // tslint:disable-next-line:ban-types - public end(cb?: Function): void { - super.end(cb); - - this.emit("close"); - } - - public get Buffer(): Buffer { - return Buffer.concat(this.data); - } -} diff --git a/src/export/packer/buffer.ts b/src/export/packer/buffer.ts deleted file mode 100644 index 9c46c4e166..0000000000 --- a/src/export/packer/buffer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { File } from "../../file"; -import { BufferStream } from "./buffer-stream"; -import { Compiler } from "./compiler"; -import { IPacker } from "./packer"; - -export class BufferPacker implements IPacker { - private readonly packer: Compiler; - - constructor(file: File) { - this.packer = new Compiler(file); - } - - public async pack(): Promise { - const stream = new BufferStream(); - - await this.packer.compile(stream); - - return stream.Buffer; - } -} diff --git a/src/export/packer/express.spec.ts b/src/export/packer/express.spec.ts deleted file mode 100644 index 416d206815..0000000000 --- a/src/export/packer/express.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -// tslint:disable:typedef space-before-function-paren -// tslint:disable:no-empty -// tslint:disable:no-any -import { assert } from "chai"; -import { stub } from "sinon"; - -import { ExpressPacker } from "../../export/packer/express"; -import { File, Paragraph } from "../../file"; - -describe("LocalPacker", () => { - let packer: ExpressPacker; - - beforeEach(() => { - const file = new File({ - creator: "Dolan Miu", - revision: "1", - lastModifiedBy: "Dolan Miu", - }); - const paragraph = new Paragraph("test text"); - const heading = new Paragraph("Hello world").heading1(); - file.addParagraph(new Paragraph("title").title()); - file.addParagraph(heading); - file.addParagraph(new Paragraph("heading 2").heading2()); - file.addParagraph(paragraph); - - const expressResMock = { - on: () => {}, - attachment: () => {}, - }; - - packer = new ExpressPacker(file, expressResMock as any); - }); - - describe("#pack()", () => { - it("should handle exception if it throws any", () => { - const compiler = stub((packer as any).packer, "compile"); - compiler.throwsException(); - return packer.pack("build/tests/test").catch((error) => { - assert.isDefined(error); - }); - }); - }); -}); diff --git a/src/export/packer/express.ts b/src/export/packer/express.ts deleted file mode 100644 index 3a4fa4b3ef..0000000000 --- a/src/export/packer/express.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as express from "express"; - -import { File } from "file"; -import { Compiler } from "./compiler"; -import { IPacker } from "./packer"; - -/** - * @deprecated ExpressPacker is now deprecated. Please use the StreamPacker instead and pipe that to `express`' `res` object - */ -export class ExpressPacker implements IPacker { - private readonly packer: Compiler; - - constructor(file: File, private readonly res: express.Response) { - this.packer = new Compiler(file); - - this.res = res; - - this.res.on("close", () => { - return res - .status(200) - .send("OK") - .end(); - }); - } - - public async pack(name: string): Promise { - name = name.replace(/.docx$/, ""); - - this.res.attachment(`${name}.docx`); - await this.packer.compile(this.res); - } -} diff --git a/src/export/packer/local.spec.ts b/src/export/packer/local.spec.ts deleted file mode 100644 index e942fb70a9..0000000000 --- a/src/export/packer/local.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* tslint:disable:typedef space-before-function-paren */ -import { assert } from "chai"; -import * as fs from "fs"; -import { stub } from "sinon"; - -import { LocalPacker } from "../../export/packer/local"; -import { File, Paragraph } from "../../file"; - -describe("LocalPacker", () => { - let packer: LocalPacker; - - beforeEach(() => { - const file = new File({ - creator: "Dolan Miu", - revision: "1", - lastModifiedBy: "Dolan Miu", - }); - const paragraph = new Paragraph("test text"); - const heading = new Paragraph("Hello world").heading1(); - file.addParagraph(new Paragraph("title").title()); - file.addParagraph(heading); - file.addParagraph(new Paragraph("heading 2").heading2()); - file.addParagraph(paragraph); - - packer = new LocalPacker(file); - }); - - describe("#pack()", () => { - it("should create a standard docx file", async function() { - this.timeout(99999999); - await packer.pack("build/tests/test"); - fs.statSync("build/tests/test.docx"); - }); - - it("should handle exception if it throws any", () => { - // tslint:disable-next-line:no-any - const compiler = stub((packer as any).packer, "compile"); - compiler.throwsException(); - return packer.pack("build/tests/test").catch((error) => { - assert.isDefined(error); - }); - }); - }); - - describe("#packPdf", () => { - it("should create a standard PDF file", async function() { - this.timeout(99999999); - - // tslint:disable-next-line:no-any - const pdfConverterConvert = stub((packer as any).pdfConverter, "convert"); - pdfConverterConvert.returns("Test PDF Contents"); - - await packer.packPdf("build/tests/pdf-test"); - fs.statSync("build/tests/pdf-test.pdf"); - }); - - it("should handle exception if it throws any", () => { - // tslint:disable-next-line:no-any - const compiler = stub((packer as any).packer, "compile"); - compiler.throwsException(); - return packer.packPdf("build/tests/pdf-test").catch((error) => { - assert.isDefined(error); - }); - }); - }); -}); diff --git a/src/export/packer/local.ts b/src/export/packer/local.ts deleted file mode 100644 index 892a3422f1..0000000000 --- a/src/export/packer/local.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as fs from "fs"; -import * as os from "os"; -import * as path from "path"; - -import { File } from "../../file"; -import { Compiler } from "./next-compiler"; -import { IPacker } from "./packer"; -import { PdfConvertWrapper } from "./pdf-convert-wrapper"; - -export class LocalPacker implements IPacker { - private readonly pdfConverter: PdfConvertWrapper; - private readonly packer: Compiler; - - constructor(file: File) { - this.pdfConverter = new PdfConvertWrapper(); - this.packer = new Compiler(file); - } - - public async pack(filePath: string): Promise { - filePath = filePath.replace(/.docx$/, ""); - - const zip = await this.packer.compile(); - const zipData = (await zip.generateAsync({ type: "base64" })) as string; - - await this.writeToFile(`${filePath}.docx`, zipData); - } - - public async packPdf(filePath: string): Promise { - filePath = filePath.replace(/.pdf$/, ""); - - const fileName = path.basename(filePath, path.extname(filePath)); - const tempPath = path.join(os.tmpdir(), `${fileName}.docx`); - - const zip = await this.packer.compile(); - const zipData = (await zip.generateAsync({ type: "base64" })) as string; - await this.writeToFile(tempPath, zipData); - - const text = await this.pdfConverter.convert(tempPath); - // const writeFile = util.promisify(fs.writeFile); --use this in future, in 3 years time. Only in node 8 - // return writeFile(`${filePath}.pdf`, text); - - await this.writeToFile(`${filePath}.pdf`, text); - } - - private writeToFile(filePath: string, data: string): Promise { - const file = fs.createWriteStream(filePath); - - return new Promise((resolve, reject) => { - file.write(data, "base64"); - file.end(); - file.on("finish", () => { - resolve(); - }); - file.on("error", reject); - }); - } -} diff --git a/src/export/packer/next-compiler.spec.ts b/src/export/packer/next-compiler.spec.ts new file mode 100644 index 0000000000..fc02d4a814 --- /dev/null +++ b/src/export/packer/next-compiler.spec.ts @@ -0,0 +1,66 @@ +/* tslint:disable:typedef space-before-function-paren */ +import { expect } from "chai"; +import { File } from "../../file"; +import { Compiler } from "./next-compiler"; + +describe("Compiler", () => { + let compiler: Compiler; + let file: File; + + beforeEach(() => { + file = new File(); + compiler = new Compiler(); + }); + + describe("#compile()", () => { + it("should pack all the content", async function() { + this.timeout(99999999); + const zipFile = await compiler.compile(file); + const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); + + expect(fileNames).is.an.instanceof(Array); + expect(fileNames).has.length(17); + 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/_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(); + + this.timeout(99999999); + + const zipFile = await compiler.compile(file); + const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); + + expect(fileNames).is.an.instanceof(Array); + expect(fileNames).has.length(25); + + 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/next-compiler.ts b/src/export/packer/next-compiler.ts index 4d26fbd5ea..f06c09e196 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -16,37 +16,44 @@ interface IXmlifyedFileMapping { Numbering: IXmlifyedFile; Relationships: IXmlifyedFile; FileRelationships: IXmlifyedFile; - Header: IXmlifyedFile; - Footer: IXmlifyedFile; - HeaderRelationships: IXmlifyedFile; - FooterRelationships: IXmlifyedFile; + Headers: IXmlifyedFile[]; + Footers: IXmlifyedFile[]; + HeaderRelationships: IXmlifyedFile[]; + FooterRelationships: IXmlifyedFile[]; ContentTypes: IXmlifyedFile; AppProperties: IXmlifyedFile; + FootNotes: IXmlifyedFile; } export class Compiler { private readonly formatter: Formatter; - constructor(private readonly file: File) { + constructor() { this.formatter = new Formatter(); } - public async compile(): Promise { + public async compile(file: File): Promise { const zip = new JSZip(); - const xmlifiedFileMapping = this.xmlifyFile(this.file); + const xmlifiedFileMapping = this.xmlifyFile(file); for (const key in xmlifiedFileMapping) { if (!xmlifiedFileMapping[key]) { continue; } - const xmlifiedFile = xmlifiedFileMapping[key]; + const obj = xmlifiedFileMapping[key] as IXmlifyedFile | IXmlifyedFile[]; - zip.file(xmlifiedFile.path, xmlifiedFile.data); + if (Array.isArray(obj)) { + for (const subFile of obj) { + zip.file(subFile.path, subFile.data); + } + } else { + zip.file(obj.path, obj.data); + } } - for (const data of this.file.Media.Array) { + for (const data of file.Media.Array) { const mediaData = data.stream; zip.file(`word/media/${data.fileName}`, mediaData); } @@ -85,22 +92,22 @@ export class Compiler { data: xml(this.formatter.format(file.FileRelationships)), path: "_rels/.rels", }, - Header: { - data: xml(this.formatter.format(file.Header.Header)), - path: "word/header1.xml", - }, - Footer: { - data: xml(this.formatter.format(file.Footer.Footer)), - path: "word/footer1.xml", - }, - HeaderRelationships: { - data: xml(this.formatter.format(file.Header.Relationships)), - path: "word/_rels/header1.xml.rels", - }, - FooterRelationships: { - data: xml(this.formatter.format(file.Footer.Relationships)), - path: "word/_rels/footer1.xml.rels", - }, + Headers: file.Headers.map((headerWrapper, index) => ({ + data: xml(this.formatter.format(headerWrapper.Header)), + path: `word/header${index + 1}.xml`, + })), + Footers: file.Footers.map((footerWrapper, index) => ({ + data: xml(this.formatter.format(footerWrapper.Footer)), + path: `word/footer${index + 1}.xml`, + })), + HeaderRelationships: file.Headers.map((headerWrapper, index) => ({ + data: xml(this.formatter.format(headerWrapper.Relationships)), + path: `word/_rels/header${index + 1}.xml.rels`, + })), + FooterRelationships: file.Footers.map((footerWrapper, index) => ({ + data: xml(this.formatter.format(footerWrapper.Relationships)), + path: `word/_rels/footer${index + 1}.xml.rels`, + })), ContentTypes: { data: xml(this.formatter.format(file.ContentTypes)), path: "[Content_Types].xml", @@ -109,6 +116,10 @@ export class Compiler { data: xml(this.formatter.format(file.AppProperties)), path: "docProps/app.xml", }, + FootNotes: { + data: xml(this.formatter.format(file.FootNotes)), + path: "word/footnotes.xml", + }, }; } } diff --git a/src/export/packer/buffer.spec.ts b/src/export/packer/packer.spec.ts similarity index 72% rename from src/export/packer/buffer.spec.ts rename to src/export/packer/packer.spec.ts index 95eccc5ecc..497e3e46b7 100644 --- a/src/export/packer/buffer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -2,41 +2,45 @@ import { assert } from "chai"; import { stub } from "sinon"; -import { BufferPacker } from "../../export/packer/buffer"; import { File, Paragraph } from "../../file"; +import { Packer } from "./packer"; -describe("BufferPacker", () => { - let packer: BufferPacker; +describe("Packer", () => { + let packer: Packer; + let file: File; beforeEach(() => { - const file = new File({ + file = new File({ creator: "Dolan Miu", revision: "1", lastModifiedBy: "Dolan Miu", }); const paragraph = new Paragraph("test text"); const heading = new Paragraph("Hello world").heading1(); + file.addParagraph(new Paragraph("title").title()); file.addParagraph(heading); file.addParagraph(new Paragraph("heading 2").heading2()); file.addParagraph(paragraph); - packer = new BufferPacker(file); + packer = new Packer(); }); - describe("#pack()", () => { + describe("#toBuffer()", () => { it("should create a standard docx file", async function() { this.timeout(99999999); - const buffer = await packer.pack(); + const buffer = await packer.toBuffer(file); + assert.isDefined(buffer); assert.isTrue(buffer.byteLength > 0); }); it("should handle exception if it throws any", () => { // tslint:disable-next-line:no-any - const compiler = stub((packer as any).packer, "compile"); + const compiler = stub((packer as any).compiler, "compile"); + compiler.throwsException(); - return packer.pack().catch((error) => { + return packer.toBuffer(file).catch((error) => { assert.isDefined(error); }); }); diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index 848924f457..e85b42c8ea 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -1,9 +1,31 @@ -export interface IPacker { - pack(path: string): void; -} +import { File } from "file"; +import { Compiler } from "./next-compiler"; -// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 -/** - * @ignore - */ -export const WORKAROUND = ""; +export class Packer { + private readonly compiler: Compiler; + + constructor() { + this.compiler = new Compiler(); + } + + public async toBuffer(file: File): Promise { + const zip = await this.compiler.compile(file); + const zipData = (await zip.generateAsync({ type: "nodebuffer" })) as Buffer; + + return zipData; + } + + public async toBase64String(file: File): Promise { + const zip = await this.compiler.compile(file); + const zipData = (await zip.generateAsync({ type: "base64" })) as string; + + return zipData; + } + + public async toBlob(file: File): Promise { + const zip = await this.compiler.compile(file); + const zipData = (await zip.generateAsync({ type: "blob" })) as Blob; + + return zipData; + } +} diff --git a/src/export/packer/pdf-packer.spec.ts b/src/export/packer/pdf-packer.spec.ts new file mode 100644 index 0000000000..b1062b348b --- /dev/null +++ b/src/export/packer/pdf-packer.spec.ts @@ -0,0 +1,48 @@ +/* tslint:disable:typedef space-before-function-paren */ +import { assert, expect } from "chai"; +import { stub } from "sinon"; + +import { File, Paragraph } from "../../file"; +import { PdfPacker } from "./pdf-packer"; + +describe("PdfPacker", () => { + let packer: PdfPacker; + let file: File; + + beforeEach(() => { + file = new File({ + creator: "Dolan Miu", + revision: "1", + lastModifiedBy: "Dolan Miu", + }); + const paragraph = new Paragraph("test text"); + const heading = new Paragraph("Hello world").heading1(); + + file.addParagraph(new Paragraph("title").title()); + file.addParagraph(heading); + file.addParagraph(new Paragraph("heading 2").heading2()); + file.addParagraph(paragraph); + + packer = new PdfPacker(); + }); + + describe("#packPdf", () => { + it("should create a standard PDF file", async function() { + this.timeout(99999999); + // tslint:disable-next-line:no-any + const pdfConverterConvert = stub((packer as any).pdfConverter, "convert"); + pdfConverterConvert.returns(new Buffer("")); + const buffer = await packer.toBuffer(file); + expect(buffer).is.an.instanceof(Buffer); + }); + + it("should handle exception if it throws any", () => { + // tslint:disable-next-line:no-any + const compiler = stub((packer as any).packer, "toBuffer"); + compiler.throwsException(); + return packer.toBuffer(file).catch((error) => { + assert.isDefined(error); + }); + }); + }); +}); diff --git a/src/export/packer/pdf-convert-wrapper.ts b/src/export/packer/pdf-packer.ts similarity index 66% rename from src/export/packer/pdf-convert-wrapper.ts rename to src/export/packer/pdf-packer.ts index e1229cf768..9c3629ed0e 100644 --- a/src/export/packer/pdf-convert-wrapper.ts +++ b/src/export/packer/pdf-packer.ts @@ -1,12 +1,23 @@ -import * as fs from "fs"; import * as request from "request-promise"; -export interface IConvertOutput { - data: string; -} +import { File } from "file"; +import { Packer } from "./packer"; -export class PdfConvertWrapper { - public convert(filePath: string): request.RequestPromise { +export class PdfPacker { + private readonly packer: Packer; + + constructor() { + this.packer = new Packer(); + } + + public async toBuffer(file: File): Promise { + const buffer = await this.packer.toBuffer(file); + const text = await this.convert(buffer); + + return text; + } + + private convert(buffer: Buffer): request.RequestPromise { return request.post({ url: "http://mirror1.convertonlinefree.com", // tslint:disable-next-line:no-null-keyword @@ -20,7 +31,7 @@ export class PdfConvertWrapper { __EVENTARGUMENT: "", __VIEWSTATE: "", ctl00$MainContent$fu: { - value: fs.readFileSync(filePath), + value: buffer, options: { filename: "output.docx", contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", diff --git a/src/export/packer/stream.ts b/src/export/packer/stream.ts deleted file mode 100644 index 1182cd5dcb..0000000000 --- a/src/export/packer/stream.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Readable, Transform } from "stream"; -import { File } from "../../file"; -import { Compiler } from "./compiler"; -import { IPacker } from "./packer"; - -class Pipe extends Transform { - public _transform(chunk: Buffer | string, encoding: string, callback: () => void): void { - this.push(chunk, encoding); - callback(); - } -} - -export class StreamPacker implements IPacker { - private readonly compiler: Compiler; - - constructor(file: File) { - this.compiler = new Compiler(file); - } - - public pack(): Readable { - const pipe = new Pipe(); - this.compiler.compile(pipe); - return pipe; - } -} diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index cf3f926315..3bbb3f815e 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -10,7 +10,7 @@ function createDrawing(drawingOptions?: IDrawingOptions): Drawing { { fileName: "test.jpg", referenceId: 1, - stream: fs.createReadStream(path), + stream: fs.readFileSync(path), path: path, dimensions: { pixels: { From 36157bb8db1ddfd0887c784700c57ed4d2b99774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mendon=C3=A7a?= Date: Tue, 14 Aug 2018 11:06:17 -0300 Subject: [PATCH 41/63] Added optional drawingOptions parameter to addImage and addImageFromBuffer methods. This way it can be passaed to Image constructor. --- src/file/media/media.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/file/media/media.ts b/src/file/media/media.ts index e813a2c051..ccd1c5b5c1 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -3,6 +3,7 @@ import * as sizeOf from "image-size"; import * as path from "path"; import { File } from "../file"; +import { IDrawingOptions } from "../drawing"; import { Image } from "../paragraph"; import { IMediaData } from "./data"; @@ -11,7 +12,7 @@ interface IHackedFile { } export class Media { - public static addImage(file: File, filePath: string): Image { + public static addImage(file: File, filePath: string, drawingOptions?: IDrawingOptions): Image { // Workaround to expose id without exposing to API const exposedFile = (file as {}) as IHackedFile; const mediaData = file.Media.addMedia(filePath, exposedFile.currentRelationshipId++); @@ -20,10 +21,10 @@ export class Media { "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${mediaData.fileName}`, ); - return new Image(mediaData); + return new Image(mediaData, drawingOptions); } - public static addImageFromBuffer(file: File, buffer: Buffer, width?: number, height?: number): Image { + public static addImageFromBuffer(file: File, buffer: Buffer, width?: number, height?: number, drawingOptions?: IDrawingOptions): Image { // Workaround to expose id without exposing to API const exposedFile = (file as {}) as IHackedFile; const mediaData = file.Media.addMediaFromBuffer( @@ -39,7 +40,7 @@ export class Media { `media/${mediaData.fileName}`, ); - return new Image(mediaData); + return new Image(mediaData, drawingOptions); } private static generateId(): string { From 3d91c8496634d7f7f64d7b16ba489dd7f1fee6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mendon=C3=A7a?= Date: Tue, 14 Aug 2018 11:28:01 -0300 Subject: [PATCH 42/63] alphabetized import sources --- src/file/media/media.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file/media/media.ts b/src/file/media/media.ts index dcec83de47..704abba6a6 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -2,8 +2,8 @@ import * as fs from "fs"; import * as sizeOf from "image-size"; import * as path from "path"; -import { File } from "../file"; import { IDrawingOptions } from "../drawing"; +import { File } from "../file"; import { ImageParagraph } from "../paragraph"; import { IMediaData } from "./data"; import { Image } from "./image"; From bfa0edeb09c6659fbea2f2c280e7fa4c2292f61a Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 14 Aug 2018 21:56:38 +0100 Subject: [PATCH 43/63] Remove pdf packer --- package.json | 2 -- src/export/index.ts | 1 - src/export/packer/pdf-packer.spec.ts | 48 ---------------------------- src/export/packer/pdf-packer.ts | 45 -------------------------- 4 files changed, 96 deletions(-) delete mode 100644 src/export/packer/pdf-packer.spec.ts delete mode 100644 src/export/packer/pdf-packer.ts diff --git a/package.json b/package.json index 5d4bd2e7a8..dbffae25cb 100644 --- a/package.json +++ b/package.json @@ -51,13 +51,11 @@ "@types/express": "^4.0.35", "@types/image-size": "0.0.29", "@types/jszip": "^3.1.3", - "@types/request-promise": "^4.1.42", "archiver": "^2.1.1", "fast-xml-parser": "^3.3.6", "image-size": "^0.6.2", "jszip": "^3.1.5", "request": "^2.83.0", - "request-promise": "^4.2.2", "xml": "^1.0.1" }, "author": "Dolan Miu", diff --git a/src/export/index.ts b/src/export/index.ts index 1a661debc6..042cb4366d 100644 --- a/src/export/index.ts +++ b/src/export/index.ts @@ -1,2 +1 @@ export * from "./packer/packer"; -export * from "./packer/pdf-packer"; diff --git a/src/export/packer/pdf-packer.spec.ts b/src/export/packer/pdf-packer.spec.ts deleted file mode 100644 index b1062b348b..0000000000 --- a/src/export/packer/pdf-packer.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* tslint:disable:typedef space-before-function-paren */ -import { assert, expect } from "chai"; -import { stub } from "sinon"; - -import { File, Paragraph } from "../../file"; -import { PdfPacker } from "./pdf-packer"; - -describe("PdfPacker", () => { - let packer: PdfPacker; - let file: File; - - beforeEach(() => { - file = new File({ - creator: "Dolan Miu", - revision: "1", - lastModifiedBy: "Dolan Miu", - }); - const paragraph = new Paragraph("test text"); - const heading = new Paragraph("Hello world").heading1(); - - file.addParagraph(new Paragraph("title").title()); - file.addParagraph(heading); - file.addParagraph(new Paragraph("heading 2").heading2()); - file.addParagraph(paragraph); - - packer = new PdfPacker(); - }); - - describe("#packPdf", () => { - it("should create a standard PDF file", async function() { - this.timeout(99999999); - // tslint:disable-next-line:no-any - const pdfConverterConvert = stub((packer as any).pdfConverter, "convert"); - pdfConverterConvert.returns(new Buffer("")); - const buffer = await packer.toBuffer(file); - expect(buffer).is.an.instanceof(Buffer); - }); - - it("should handle exception if it throws any", () => { - // tslint:disable-next-line:no-any - const compiler = stub((packer as any).packer, "toBuffer"); - compiler.throwsException(); - return packer.toBuffer(file).catch((error) => { - assert.isDefined(error); - }); - }); - }); -}); diff --git a/src/export/packer/pdf-packer.ts b/src/export/packer/pdf-packer.ts deleted file mode 100644 index 9c3629ed0e..0000000000 --- a/src/export/packer/pdf-packer.ts +++ /dev/null @@ -1,45 +0,0 @@ -import * as request from "request-promise"; - -import { File } from "file"; -import { Packer } from "./packer"; - -export class PdfPacker { - private readonly packer: Packer; - - constructor() { - this.packer = new Packer(); - } - - public async toBuffer(file: File): Promise { - const buffer = await this.packer.toBuffer(file); - const text = await this.convert(buffer); - - return text; - } - - private convert(buffer: Buffer): request.RequestPromise { - return request.post({ - url: "http://mirror1.convertonlinefree.com", - // tslint:disable-next-line:no-null-keyword - encoding: null, - headers: { - "User-Agent": - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36", - }, - formData: { - __EVENTTARGET: "", - __EVENTARGUMENT: "", - __VIEWSTATE: "", - ctl00$MainContent$fu: { - value: buffer, - options: { - filename: "output.docx", - contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - }, - }, - ctl00$MainContent$btnConvert: "Convert", - ctl00$MainContent$fuZip: "", - }, - }); - } -} From 2018f41368136709e5b2c5731211b923c5d88146 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 14 Aug 2018 22:05:04 +0100 Subject: [PATCH 44/63] Discard pdf --- My Document.pdf | 519 ------------------------------------------------ 1 file changed, 519 deletions(-) delete mode 100644 My Document.pdf diff --git a/My Document.pdf b/My Document.pdf deleted file mode 100644 index 0a2b5bf7bf..0000000000 --- a/My Document.pdf +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - Convert DOC to PDF Online | Convert DOCX to PDF Online | Convert Word to PDF Online | Free online converter - - - - - - -
-
- - - -
- - - - - - - - - - -
- - -
- -
-
- - - - - - - -
-
- - - - -
-
-
- - - - - - - - - -
- -

- WELCOME TO 100% FREE WORD TO PDF ONLINE CONVERTER

-
- -

- You can convert DOC to PDF and DOCX to PDF for free

-
-
- - - - - -
-
-
- Advantages of our free service -
-
-
    -
  1. Absolutely 100% free service
  2. -
  3. No need to have MS Word on your PC (your file is converted on our servers)
  4. -
  5. Produced PDF 100% matches your MS Word document
  6. -
  7. High quality PDF
  8. -
  9. Pictures are not lost
  10. -
  11. MS Word documents in all languages are supported
  12. -
  13. No personal information is required (file is returned to your Internet browser)
  14. -
  15. Conversion of ZIP archives
  16. -
  17. Immediate conversion
  18. -
- -
-
-
-
- - - -
-
-
-
-
-
- -
-
-
-

- Convert one file online: - How it works

-
- -
- -
-
-
-
- - - - -
-
-
-
-
-
-
- -
- -   - -
- Document is not an MS Word document inside it just has .DOC/.DOCX extension or damaged -
-
-
-
- On this page you can only convert DOC DOCX to - PDF.
-
    -
  • To convert several files, please, use tab Convert zipped files.
  • To convert RTF - ODT MHT HTM HTML TXT FB2 DOT DOTX XLS XLSX XLSB ODS XLT XLTX PPT PPTX PPS PPSX ODP - POT POTX to PDF, please, use the following link Other documents to PDF.
  • To convert JPG JPEG PNG - BMP GIF TIF TIFF to PDF, please, use the following link Image to PDF.
  • -
  • To extract text from PDF, please, use the following link PDF to TXT.
  • To convert DOC DOCX RTF ODT MHT HTM HTML - TXT FB2 DOT DOTX to DOC DOCX DOT ODT RTF TXT or XLS XLSX XLSB XLT XLTX ODS to XLS - XLSX or PPT PPTX PPS PPSX ODP POT POTX to PPT PPTX PPS PPSX JPG TIF PNG GIF BMP, - please, use the following link Other formats.
  • To convert DOC DOCX DOT DOTX RTF - ODT MHT HTM HTML TXT to FB2, please, use the following link Documents to FB2.
  • To - convert JPG JPEG JFIF PNG BMP GIF TIF ICO to other image formats, please, use the - following link - Convert Image.
  • -
  • To convert PDF to MS Word (DOC, DOCX), please, use the following link Convert PDF to Word. -
  • -
  • To convert PDF to JPG, please, use the following link Convert PDF to JPG.
  • -
  • To convert DJVU to PDF, please, use the following link Convert DJVU to PDF.
  • -
  • To recognize text in a PDF or in an image, please, use the following link Recognize - text in PDF or in image.
  • -
-
-
- -
-
- - - - -
-
-
-
-
- - -
-
- -
-
-
- - TERMS OF SERVICE
-
- -
-
-
-
-
-
- - - - -
-
- -
-
- - - - - - - -
- - - - - - - - - - - - - From 07261232ffd2b6f85e48d76715810d914f9f8022 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 15 Aug 2018 01:22:22 +0100 Subject: [PATCH 45/63] Removed old compiler and unused dependencies --- package.json | 5 -- src/export/packer/compiler.spec.ts | 76 ------------------- src/export/packer/compiler.ts | 114 ----------------------------- 3 files changed, 195 deletions(-) delete mode 100644 src/export/packer/compiler.spec.ts delete mode 100644 src/export/packer/compiler.ts diff --git a/package.json b/package.json index dbffae25cb..98acfbfe79 100644 --- a/package.json +++ b/package.json @@ -46,16 +46,11 @@ ], "types": "./build/index.d.ts", "dependencies": { - "@types/archiver": "^2.1.0", - "@types/bluebird": "3.5.20", - "@types/express": "^4.0.35", "@types/image-size": "0.0.29", "@types/jszip": "^3.1.3", - "archiver": "^2.1.1", "fast-xml-parser": "^3.3.6", "image-size": "^0.6.2", "jszip": "^3.1.5", - "request": "^2.83.0", "xml": "^1.0.1" }, "author": "Dolan Miu", diff --git a/src/export/packer/compiler.spec.ts b/src/export/packer/compiler.spec.ts deleted file mode 100644 index 78d2339b11..0000000000 --- a/src/export/packer/compiler.spec.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* tslint:disable:typedef space-before-function-paren */ -import * as fs from "fs"; -import * as JSZip from "jszip"; - -import { expect } from "chai"; -import { File } from "../../file"; -import { Compiler } from "./compiler"; - -describe("Compiler", () => { - let compiler: Compiler; - let file: File; - - beforeEach(() => { - file = new File(); - compiler = new Compiler(file); - }); - - describe("#compile()", () => { - it("should pack all the content", async function() { - this.timeout(99999999); - const fileName = "build/tests/test.docx"; - await compiler.compile(fs.createWriteStream(fileName)); - - const docxFile = fs.readFileSync(fileName); - const zipFile: JSZip = await JSZip.loadAsync(docxFile); - const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); - - expect(fileNames).is.an.instanceof(Array); - expect(fileNames).has.length(13); - 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/_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(); - - this.timeout(99999999); - const fileName = "build/tests/test2.docx"; - await compiler.compile(fs.createWriteStream(fileName)); - - const docxFile = fs.readFileSync(fileName); - const zipFile: JSZip = await JSZip.loadAsync(docxFile); - const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); - - expect(fileNames).is.an.instanceof(Array); - expect(fileNames).has.length(21); - - 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/compiler.ts b/src/export/packer/compiler.ts deleted file mode 100644 index a845833a34..0000000000 --- a/src/export/packer/compiler.ts +++ /dev/null @@ -1,114 +0,0 @@ -import * as archiver from "archiver"; -import * as express from "express"; -import { Writable } from "stream"; -import * as xml from "xml"; - -import { File } from "file"; -import { Formatter } from "../formatter"; - -export class Compiler { - protected archive: archiver.Archiver; - private readonly formatter: Formatter; - - constructor(private readonly file: File) { - this.formatter = new Formatter(); - this.archive = archiver.create("zip", {}); - - this.archive.on("error", (err) => { - throw err; - }); - } - - public async compile(output: Writable | express.Response): Promise { - this.archive.pipe(output); - - const xmlDocument = xml(this.formatter.format(this.file.Document)); - const xmlStyles = xml(this.formatter.format(this.file.Styles)); - const xmlProperties = xml(this.formatter.format(this.file.CoreProperties), { - declaration: { - standalone: "yes", - encoding: "UTF-8", - }, - }); - const xmlNumbering = xml(this.formatter.format(this.file.Numbering)); - const xmlRelationships = xml(this.formatter.format(this.file.DocumentRelationships)); - const xmlFileRelationships = xml(this.formatter.format(this.file.FileRelationships)); - const xmlContentTypes = xml(this.formatter.format(this.file.ContentTypes)); - const xmlAppProperties = xml(this.formatter.format(this.file.AppProperties)); - const xmlFootnotes = xml(this.formatter.format(this.file.FootNotes)); - - this.archive.append(xmlDocument, { - name: "word/document.xml", - }); - - this.archive.append(xmlStyles, { - name: "word/styles.xml", - }); - - this.archive.append(xmlProperties, { - name: "docProps/core.xml", - }); - - this.archive.append(xmlAppProperties, { - name: "docProps/app.xml", - }); - - this.archive.append(xmlNumbering, { - name: "word/numbering.xml", - }); - - // headers - for (let i = 0; i < this.file.Headers.length; i++) { - const element = this.file.Headers[i]; - this.archive.append(xml(this.formatter.format(element.Header)), { - name: `word/header${i + 1}.xml`, - }); - - this.archive.append(xml(this.formatter.format(element.Relationships)), { - name: `word/_rels/header${i + 1}.xml.rels`, - }); - } - - // footers - for (let i = 0; i < this.file.Footers.length; i++) { - const element = this.file.Footers[i]; - this.archive.append(xml(this.formatter.format(element.Footer)), { - name: `word/footer${i + 1}.xml`, - }); - - this.archive.append(xml(this.formatter.format(element.Relationships)), { - name: `word/_rels/footer${i + 1}.xml.rels`, - }); - } - - this.archive.append(xmlFootnotes, { - name: "word/footnotes.xml", - }); - - this.archive.append(xmlRelationships, { - name: "word/_rels/document.xml.rels", - }); - - this.archive.append(xmlContentTypes, { - name: "[Content_Types].xml", - }); - - this.archive.append(xmlFileRelationships, { - name: "_rels/.rels", - }); - - for (const data of this.file.Media.Array) { - this.archive.append(data.stream, { - name: `word/media/${data.fileName}`, - }); - } - - this.archive.finalize(); - - return new Promise((resolve) => { - output.on("close", () => { - resolve(); - }); - }); - } -} From f969c866a78ae40b04d1e97117f7a9b7046327e4 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 15 Aug 2018 01:38:00 +0100 Subject: [PATCH 46/63] Update target for library --- webpack.config.js | 23 ++++++++++------------- webpack.web.config.js | 32 -------------------------------- 2 files changed, 10 insertions(+), 45 deletions(-) delete mode 100644 webpack.web.config.js diff --git a/webpack.config.js b/webpack.config.js index a8000404c1..01ecff1540 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,17 +1,17 @@ -const path = require('path'); +const path = require("path"); module.exports = { - entry: './src/index.ts', + entry: "./src/index.ts", output: { - path: path.resolve('build'), - filename: 'index.js', - libraryTarget: 'umd' + path: path.resolve("build"), + filename: "index.js", + libraryTarget: "umd", }, resolve: { - extensions: ['.tsx', '.ts', '.js'], - modules: [path.resolve('./src'), "node_modules"] + extensions: [".tsx", ".ts", ".js"], + modules: [path.resolve("./src"), "node_modules"], }, module: { @@ -19,13 +19,10 @@ module.exports = { { test: /\.ts$/, loaders: ["awesome-typescript-loader"], - } + }, ], }, - target: 'node', - - node: { - __dirname: true - } + // Because docx is now targetting web + // target: 'node', }; diff --git a/webpack.web.config.js b/webpack.web.config.js deleted file mode 100644 index 9672df789c..0000000000 --- a/webpack.web.config.js +++ /dev/null @@ -1,32 +0,0 @@ -const path = require('path'); - -module.exports = { - entry: './src/index.ts', - - output: { - path: path.resolve('build'), - filename: 'index.web.js', - libraryTarget: 'umd' - }, - - resolve: { - extensions: ['.tsx', '.ts', '.js'], - modules: [path.resolve('./src'), "node_modules"] - }, - - module: { - rules: [ - { - test: /\.ts$/, - loaders: ["awesome-typescript-loader"], - } - ], - }, - - node: { - __dirname: true, - fs: "empty", - tls: "empty", - net: "empty" - } -}; From bf5bcea607a14d5e81a5be4c42f21fe5f0ced3cd Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 15 Aug 2018 22:20:43 +0100 Subject: [PATCH 47/63] Make add image support base64 strings --- src/file/file.ts | 2 +- src/file/media/data.ts | 2 +- src/file/media/media.ts | 53 ++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/file/file.ts b/src/file/file.ts index becc713176..9ab305fd57 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -129,7 +129,7 @@ export class File { return this; } - public createImage(buffer: Buffer, width?: number, height?: number): Image { + public createImage(buffer: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): Image { const image = Media.addImage(this, buffer, width, height); this.document.addParagraph(image.Paragraph); diff --git a/src/file/media/data.ts b/src/file/media/data.ts index 9ac7ab5eee..42e5874f99 100644 --- a/src/file/media/data.ts +++ b/src/file/media/data.ts @@ -11,7 +11,7 @@ export interface IMediaDataDimensions { export interface IMediaData { referenceId: number; - stream: Buffer; + stream: Buffer | Uint8Array | ArrayBuffer; path?: string; fileName: string; dimensions: IMediaDataDimensions; diff --git a/src/file/media/media.ts b/src/file/media/media.ts index f2cb71aa2f..1c8e0609dc 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,5 +1,3 @@ -import * as sizeOf from "image-size"; - import { File } from "../file"; import { ImageParagraph } from "../paragraph"; import { IMediaData } from "./data"; @@ -10,7 +8,7 @@ interface IHackedFile { } export class Media { - public static addImage(file: File, buffer: Buffer, width?: number, height?: number): Image { + public static addImage(file: File, buffer: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): Image { // Workaround to expose id without exposing to API const exposedFile = (file as {}) as IHackedFile; const mediaData = file.Media.addMedia(buffer, exposedFile.currentRelationshipId++, width, height); @@ -51,28 +49,36 @@ export class Media { return data; } - public addMedia(buffer: Buffer, referenceId: number, width?: number, height?: number): IMediaData { + public addMedia( + buffer: Buffer | string | Uint8Array | ArrayBuffer, + referenceId: number, + width: number = 100, + height: number = 100, + ): IMediaData { const key = `${Media.generateId()}.png`; - let dimensions; - if (width && height) { - dimensions = { + + return this.createMedia( + key, + referenceId, + { width: width, height: height, - }; - } else { - dimensions = sizeOf(buffer); - } - - return this.createMedia(key, referenceId, dimensions, buffer); + }, + buffer, + ); } private createMedia( key: string, relationshipsCount: number, dimensions: { width: number; height: number }, - data: Buffer, + data: Buffer | string | Uint8Array | ArrayBuffer, filePath?: string, ): IMediaData { + if (typeof data === "string") { + data = this.convertDataURIToBinary(data); + } + const imageData = { referenceId: this.map.size + relationshipsCount + 1, stream: data, @@ -104,4 +110,23 @@ export class Media { return array; } + + private convertDataURIToBinary(dataURI: string): Uint8Array { + // https://gist.github.com/borismus/1032746 + // https://github.com/mafintosh/base64-to-uint8array + const BASE64_MARKER = ";base64,"; + + const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length; + + if (typeof atob === "function") { + return new Uint8Array( + atob(dataURI.substring(base64Index)) + .split("") + .map((c) => c.charCodeAt(0)), + ); + } else { + const b = require("buf" + "fer"); + return new b.Buffer(dataURI, "base64"); + } + } } From f9a0d1b3881459347b97f34a4110bc750d35a5df Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 15 Aug 2018 23:06:48 +0100 Subject: [PATCH 48/63] Fix tests --- src/file/drawing/drawing.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 3bbb3f815e..87ea5e9e44 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -1,16 +1,17 @@ import { assert } from "chai"; -import * as fs from "fs"; import { Utility } from "../../tests/utility"; import { Drawing, IDrawingOptions, PlacementPosition } from "./"; +const imageBase64Data = `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`; + function createDrawing(drawingOptions?: IDrawingOptions): Drawing { const path = "./demo/images/image1.jpeg"; return new Drawing( { fileName: "test.jpg", referenceId: 1, - stream: fs.readFileSync(path), + stream: Buffer.from(imageBase64Data, "base64"), path: path, dimensions: { pixels: { From 0411153832a01d7b2f5464f06fd0990005d02ea1 Mon Sep 17 00:00:00 2001 From: Noah Schechter Date: Sun, 19 Aug 2018 11:59:38 -0400 Subject: [PATCH 49/63] 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 50/63] 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 a7f6224fb2df29dc620c25718a486b61f0b05164 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 21 Aug 2018 02:46:21 +0100 Subject: [PATCH 51/63] Made demo files into typescript files --- demo/demo1.js | 20 ------- demo/demo1.ts | 20 +++++++ demo/{demo10.js => demo10.ts} | 62 +++++++++++--------- demo/{demo11.js => demo11.ts} | 52 ++++++++++------- demo/{demo12.js => demo12.ts} | 19 +++--- demo/demo13.js | 26 --------- demo/demo13.ts | 28 +++++++++ demo/demo14.js | 24 -------- demo/demo14.ts | 28 +++++++++ demo/demo15.js | 14 ----- demo/demo15.ts | 18 ++++++ demo/demo16.js | 36 ------------ demo/demo16.ts | 40 +++++++++++++ demo/demo17.js | 17 ------ demo/demo17.ts | 21 +++++++ demo/{demo18.js => demo18.ts} | 18 +++--- demo/demo19.js | 20 ------- demo/demo19.ts | 20 +++++++ demo/demo2.js | 74 ----------------------- demo/demo2.ts | 78 +++++++++++++++++++++++++ demo/demo20.js | 17 ------ demo/demo20.ts | 21 +++++++ demo/demo21.js | 31 ---------- demo/demo21.ts | 37 ++++++++++++ demo/demo22.js | 26 --------- demo/demo22.ts | 27 +++++++++ demo/{demo23.js => demo23.ts} | 29 ++++----- demo/demo24.js | 15 ----- demo/demo24.ts | 18 ++++++ demo/demo25.js | 15 ----- demo/demo26.js | 21 ------- demo/demo3.js | 45 -------------- demo/demo3.ts | 46 +++++++++++++++ demo/demo4.js | 12 ---- demo/demo4.ts | 15 +++++ demo/demo5.js | 18 ------ demo/demo5.ts | 21 +++++++ demo/demo6.js | 25 -------- demo/demo6.ts | 29 +++++++++ demo/demo7.js | 14 ----- demo/demo7.ts | 18 ++++++ demo/demo8.js | 13 ----- demo/demo8.ts | 17 ++++++ demo/demo9.js | 14 ----- demo/demo9.ts | 17 ++++++ demo/index.js | 8 ++- package.json | 4 +- src/file/paragraph/formatting/indent.ts | 4 +- src/file/paragraph/paragraph.ts | 8 ++- tsconfig.json | 3 +- 50 files changed, 638 insertions(+), 585 deletions(-) delete mode 100644 demo/demo1.js create mode 100644 demo/demo1.ts rename demo/{demo10.js => demo10.ts} (83%) rename demo/{demo11.js => demo11.ts} (75%) rename demo/{demo12.js => demo12.ts} (50%) delete mode 100644 demo/demo13.js create mode 100644 demo/demo13.ts delete mode 100644 demo/demo14.js create mode 100644 demo/demo14.ts delete mode 100644 demo/demo15.js create mode 100644 demo/demo15.ts delete mode 100644 demo/demo16.js create mode 100644 demo/demo16.ts delete mode 100644 demo/demo17.js create mode 100644 demo/demo17.ts rename demo/{demo18.js => demo18.ts} (89%) delete mode 100644 demo/demo19.js create mode 100644 demo/demo19.ts delete mode 100644 demo/demo2.js create mode 100644 demo/demo2.ts delete mode 100644 demo/demo20.js create mode 100644 demo/demo20.ts delete mode 100644 demo/demo21.js create mode 100644 demo/demo21.ts delete mode 100644 demo/demo22.js create mode 100644 demo/demo22.ts rename demo/{demo23.js => demo23.ts} (82%) delete mode 100644 demo/demo24.js create mode 100644 demo/demo24.ts delete mode 100644 demo/demo25.js delete mode 100644 demo/demo26.js delete mode 100644 demo/demo3.js create mode 100644 demo/demo3.ts delete mode 100644 demo/demo4.js create mode 100644 demo/demo4.ts delete mode 100644 demo/demo5.js create mode 100644 demo/demo5.ts delete mode 100644 demo/demo6.js create mode 100644 demo/demo6.ts delete mode 100644 demo/demo7.js create mode 100644 demo/demo7.ts delete mode 100644 demo/demo8.js create mode 100644 demo/demo8.ts delete mode 100644 demo/demo9.js create mode 100644 demo/demo9.ts diff --git a/demo/demo1.js b/demo/demo1.js deleted file mode 100644 index fc8d4c31a1..0000000000 --- a/demo/demo1.js +++ /dev/null @@ -1,20 +0,0 @@ -const docx = require('../build'); -const fs = require('fs'); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -var institutionText = new docx.TextRun("University College London").bold(); -var dateText = new docx.TextRun("5th Dec 2015").tab().bold(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.addParagraph(paragraph); - -var packer = new docx.Packer(); - -packer.toBuffer(doc).then((buffer) => { - fs.writeFileSync('My Document.docx', buffer); -}); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo1.ts b/demo/demo1.ts new file mode 100644 index 0000000000..ba3a0bcc2f --- /dev/null +++ b/demo/demo1.ts @@ -0,0 +1,20 @@ +// Simple example to add text to a document +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +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(); +paragraph.addRun(institutionText); +paragraph.addRun(dateText); + +doc.addParagraph(paragraph); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo10.js b/demo/demo10.ts similarity index 83% rename from demo/demo10.js rename to demo/demo10.ts index 2b986dbf65..b55542b866 100644 --- a/demo/demo10.js +++ b/demo/demo10.ts @@ -1,8 +1,11 @@ -const docx = require("../build"); +// 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, TextRun } from "../build"; const PHONE_NUMBER = "07534563401"; const PROFILE_URL = "https://www.linkedin.com/in/dolan1"; -const EMAIL = "docx@docx.com"; +const EMAIL = "docx@com"; const experiences = [ { @@ -122,13 +125,13 @@ const achievements = [ ]; class DocumentCreator { - create(data) { + public create(data): Document { const experiences = data[0]; const educations = data[1]; const skills = data[2]; const achivements = data[3]; - const document = new docx.Document(); - document.addParagraph(new docx.Paragraph("Dolan Miu").title()); + const document = new Document(); + document.addParagraph(new Paragraph("Dolan Miu").title()); document.addParagraph(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); document.addParagraph(this.createHeading("Education")); @@ -181,23 +184,23 @@ class DocumentCreator { document.addParagraph(this.createHeading("References")); document.addParagraph( - new docx.Paragraph( + 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 docx.Paragraph("More references upon request")); + document.addParagraph(new Paragraph("More references upon request")); document.addParagraph( - new docx.Paragraph( + new Paragraph( "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.", ).center(), ); return document; } - createContactInfo(phoneNumber, profileUrl, email) { - const paragraph = new docx.Paragraph().center(); - const contactInfo = new docx.TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`); - const address = new docx.TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(); + createContactInfo(phoneNumber: string, profileUrl: string, email: string) { + const paragraph = new Paragraph().center(); + 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); @@ -206,17 +209,17 @@ class DocumentCreator { } createHeading(text) { - return new docx.Paragraph(text).heading1().thematicBreak(); + return new Paragraph(text).heading1().thematicBreak(); } createSubHeading(text) { - return new docx.Paragraph(text).heading2(); + return new Paragraph(text).heading2(); } createInstitutionHeader(institutionName, dateText) { - const paragraph = new docx.Paragraph().maxRightTabStop(); - const institution = new docx.TextRun(institutionName).bold(); - const date = new docx.TextRun(dateText).tab().bold(); + const paragraph = new Paragraph().maxRightTabStop(); + const institution = new TextRun(institutionName).bold(); + const date = new TextRun(dateText).tab().bold(); paragraph.addRun(institution); paragraph.addRun(date); @@ -225,8 +228,8 @@ class DocumentCreator { } createRoleText(roleText) { - const paragraph = new docx.Paragraph(); - const role = new docx.TextRun(roleText).italic(); + const paragraph = new Paragraph(); + const role = new TextRun(roleText).italic(); paragraph.addRun(role); @@ -234,32 +237,32 @@ class DocumentCreator { } createBullet(text) { - return new docx.Paragraph(text).bullet(); + return new Paragraph(text).bullet(); } createSkillList(skills) { - const paragraph = new docx.Paragraph(); + const paragraph = new Paragraph(); const skillConcat = skills.map((skill) => skill.name).join(", ") + "."; - paragraph.addRun(new docx.TextRun(skillConcat)); + paragraph.addRun(new TextRun(skillConcat)); return paragraph; } - createAchivementsList(achivements) { + public createAchivementsList(achivements): Paragraph { const arr = []; for (const achievement of achivements) { - arr.push(new docx.Paragraph(achievement.name).bullet()); + arr.push(new Paragraph(achievement.name).bullet()); } return arr; } createInterests(interests) { - const paragraph = new docx.Paragraph(); + const paragraph = new Paragraph(); - paragraph.addRun(new docx.TextRun(interests)); + paragraph.addRun(new TextRun(interests)); return paragraph; } @@ -308,7 +311,8 @@ const documentCreator = new DocumentCreator(); const doc = documentCreator.create([experiences, education, skills, achievements]); -var exporter = new docx.LocalPacker(doc); -exporter.pack("Dolan Miu CV"); +const packer = new Packer(); -console.log("Document created successfully at project root!"); +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo11.js b/demo/demo11.ts similarity index 75% rename from demo/demo11.js rename to demo/demo11.ts index f0597e0da4..3b0cf0b01f 100644 --- a/demo/demo11.js +++ b/demo/demo11.ts @@ -1,7 +1,9 @@ -const docx = require("../build"); -const fs = require('fs'); +// 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"; -const doc = new docx.Document(undefined, { +const doc = new Document(undefined, { top: 700, right: 700, bottom: 700, @@ -52,7 +54,7 @@ doc.Styles.createParagraphStyle("normalPara", "Normal Para") .font("Calibri") .quickFormat() .leftTabStop(453.543307087) - .maxRightTabStop(453.543307087) + .maxRightTabStop() .size(26) .spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 }); @@ -70,7 +72,7 @@ doc.Styles.createParagraphStyle("aside", "Aside") .next("Normal") .color("999999") .italics() - .indent(720) + .indent({ left: 720 }) .spacing({ line: 276 }); doc.Styles.createParagraphStyle("wellSpaced", "Well Spaced") @@ -105,29 +107,35 @@ doc.createParagraph("Sir,").style("normalPara"); doc.createParagraph("BRIEF DESCRIPTION").style("normalPara"); -var table = new docx.Table(4, 4); -var contentParagraph = table +const table = new Table(4, 4); +table .getRow(0) .getCell(0) - .addContent(new docx.Paragraph("Pole No.")); -table.properties.width = 10000; + .addContent(new Paragraph("Pole No.")); +table.Properties.width = 10000; doc.addTable(table); -var arrboth = [{ - image: "./demo/images/pizza.gif", - comment: "Test" -}, { - image: "./demo/images/pizza.gif", - comment: "Test 2" -}]; +const arrboth = [ + { + image: "./demo/images/pizza.gif", + comment: "Test", + }, + { + image: "./demo/images/pizza.gif", + comment: "Test 2", + }, +]; -arrboth.forEach(function(item) { +arrboth.forEach((item) => { const para = doc.createParagraph(); - para.createTextRun(doc.createImage(fs.readFileSync(item.image))); - para.properties.width = 60; - para.properties.height = 90; + para.addImage(doc.createImage(fs.readFileSync(item.image))); + para.Properties.width = 60; + para.Properties.height = 90; doc.createParagraph(item.comment).style("normalPara2"); }); -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo12.js b/demo/demo12.ts similarity index 50% rename from demo/demo12.js rename to demo/demo12.ts index 87c7a405e0..a3479c3cbf 100644 --- a/demo/demo12.js +++ b/demo/demo12.ts @@ -1,9 +1,11 @@ -const docx = require("../build"); -const fs = require('fs'); +// Scaling images +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph } from "../build"; -var doc = new docx.Document(); +const doc = new Document(); -var paragraph = new docx.Paragraph("Hello World"); +const paragraph = new Paragraph("Hello World"); doc.addParagraph(paragraph); const image = doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); @@ -12,11 +14,12 @@ 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) +image2.scale(1); image3.scale(2.5); image4.scale(4); -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); +const packer = new Packer(); -console.log("Document created successfully at project root!"); +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo13.js b/demo/demo13.js deleted file mode 100644 index f141547d7a..0000000000 --- a/demo/demo13.js +++ /dev/null @@ -1,26 +0,0 @@ -// This example shows 3 styles -const fs = require('fs'); -const docx = require('../build'); - -const styles = fs.readFileSync('./demo/assets/custom-styles.xml', 'utf-8'); -const doc = new docx.Document({ - title: 'Title', - externalStyles: styles -}); - -doc.createParagraph('Cool Heading Text').heading1(); - -let paragraph = new docx.Paragraph('This is a custom named style from the template "MyFancyStyle"'); -paragraph.style('MyFancyStyle'); -doc.addParagraph(paragraph); - -doc.createParagraph('Some normal text') - -doc.createParagraph('MyFancyStyle again').style('MyFancyStyle'); -paragraph.style('MyFancyStyle'); -doc.addParagraph(paragraph); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo13.ts b/demo/demo13.ts new file mode 100644 index 0000000000..b80b9fdc22 --- /dev/null +++ b/demo/demo13.ts @@ -0,0 +1,28 @@ +// 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"; + +const styles = fs.readFileSync("./demo/assets/custom-styles.xml", "utf-8"); +const doc = new Document({ + title: "Title", + externalStyles: styles, +}); + +doc.createParagraph("Cool Heading Text").heading1(); + +const paragraph = new Paragraph('This is a custom named style from the template "MyFancyStyle"'); +paragraph.style("MyFancyStyle"); +doc.addParagraph(paragraph); + +doc.createParagraph("Some normal text"); + +doc.createParagraph("MyFancyStyle again").style("MyFancyStyle"); +paragraph.style("MyFancyStyle"); +doc.addParagraph(paragraph); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo14.js b/demo/demo14.js deleted file mode 100644 index b2262f106a..0000000000 --- a/demo/demo14.js +++ /dev/null @@ -1,24 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -doc.createParagraph("First Page").pageBreak() -doc.createParagraph("Second Page"); - -var pageNumber = new docx.TextRun().pageNumber() - -var pageoneheader = new docx.Paragraph("First Page Header ").right(); - -pageoneheader.addRun(pageNumber); -var firstPageHeader = doc.createFirstPageHeader(); -firstPageHeader.addParagraph(pageoneheader); - -var pagetwoheader = new docx.Paragraph("My Title ").right(); - -pagetwoheader.addRun(pageNumber) -doc.Header.addParagraph(pagetwoheader) - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo14.ts b/demo/demo14.ts new file mode 100644 index 0000000000..94d45a66a6 --- /dev/null +++ b/demo/demo14.ts @@ -0,0 +1,28 @@ +// 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"; + +const doc = new Document(); + +doc.createParagraph("First Page").pageBreak(); +doc.createParagraph("Second Page"); + +const pageNumber = new TextRun("Page ").pageNumber(); + +const pageoneheader = new Paragraph("First Page Header ").right(); + +pageoneheader.addRun(pageNumber); +const firstPageHeader = doc.createFirstPageHeader(); +firstPageHeader.addParagraph(pageoneheader); + +const pagetwoheader = new Paragraph("My Title ").right(); + +pagetwoheader.addRun(pageNumber); +doc.Header.addParagraph(pagetwoheader); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo15.js b/demo/demo15.js deleted file mode 100644 index 61d9351817..0000000000 --- a/demo/demo15.js +++ /dev/null @@ -1,14 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -var paragraph2 = new docx.Paragraph("Hello World on another page").pageBreakBefore(); - -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo15.ts b/demo/demo15.ts new file mode 100644 index 0000000000..5da6c826b5 --- /dev/null +++ b/demo/demo15.ts @@ -0,0 +1,18 @@ +// Page break before example +// 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("Hello World"); +const paragraph2 = new Paragraph("Hello World on another page").pageBreakBefore(); + +doc.addParagraph(paragraph); +doc.addParagraph(paragraph2); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo16.js b/demo/demo16.js deleted file mode 100644 index f850bc9b4b..0000000000 --- a/demo/demo16.js +++ /dev/null @@ -1,36 +0,0 @@ -const docx = require("../build"); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World").pageBreak(); - -doc.addParagraph(paragraph); - -var header = doc.createHeader(); -header.createParagraph("Header on another page"); -var footer = doc.createFooter(); -footer.createParagraph("Footer on another page"); - -doc.addSection({ - headerId: header.Header.ReferenceId, - footerId: footer.Footer.ReferenceId, - pageNumberStart: 1, - pageNumberFormatType: docx.PageNumberFormat.DECIMAL, -}); - -doc.createParagraph("hello"); - -doc.addSection({ - headerId: header.Header.ReferenceId, - footerId: footer.Footer.ReferenceId, - pageNumberStart: 1, - pageNumberFormatType: docx.PageNumberFormat.DECIMAL, - orientation: docx.PageOrientation.LANDSCAPE, -}); - -doc.createParagraph("hello in landscape"); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo16.ts b/demo/demo16.ts new file mode 100644 index 0000000000..4b92dc0d7e --- /dev/null +++ b/demo/demo16.ts @@ -0,0 +1,40 @@ +// 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 } from "../build"; + +const doc = new Document(); + +const paragraph = new Paragraph("Hello World").pageBreak(); + +doc.addParagraph(paragraph); + +const header = doc.createHeader(); +header.createParagraph("Header on another page"); +const footer = doc.createFooter(); +footer.createParagraph("Footer on another page"); + +doc.addSection({ + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, + pageNumberStart: 1, + pageNumberFormatType: PageNumberFormat.DECIMAL, +}); + +doc.createParagraph("hello"); + +doc.addSection({ + headerId: header.Header.ReferenceId, + footerId: footer.Footer.ReferenceId, + pageNumberStart: 1, + pageNumberFormatType: PageNumberFormat.DECIMAL, + orientation: PageOrientation.LANDSCAPE, +}); + +doc.createParagraph("hello in landscape"); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo17.js b/demo/demo17.js deleted file mode 100644 index 266e556b7d..0000000000 --- a/demo/demo17.js +++ /dev/null @@ -1,17 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World").referenceFootnote(1); -var paragraph2 = new docx.Paragraph("Hello World").referenceFootnote(2); - -doc.addParagraph(paragraph); -doc.addParagraph(paragraph2); - -doc.createFootnote(new docx.Paragraph("Test")); -doc.createFootnote(new docx.Paragraph("My amazing reference")); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo17.ts b/demo/demo17.ts new file mode 100644 index 0000000000..c48a2e67e8 --- /dev/null +++ b/demo/demo17.ts @@ -0,0 +1,21 @@ +// Footnotes +// 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("Hello World").referenceFootnote(1); +const paragraph2 = new Paragraph("Hello World").referenceFootnote(2); + +doc.addParagraph(paragraph); +doc.addParagraph(paragraph2); + +doc.createFootnote(new Paragraph("Test")); +doc.createFootnote(new Paragraph("My amazing reference")); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo18.js b/demo/demo18.ts similarity index 89% rename from demo/demo18.js rename to demo/demo18.ts index 73a778a6c3..4a61488c1f 100644 --- a/demo/demo18.js +++ b/demo/demo18.ts @@ -1,15 +1,17 @@ // Insert image from a buffer -const docx = require('../build'); +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer } from "../build"; -var doc = new docx.Document(); +const doc = new Document(); - -const imageBase64Data = `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` +const imageBase64Data = `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`; // doc.createImage(Buffer.from(imageBase64Data, 'base64')); -doc.createImage(Buffer.from(imageBase64Data, 'base64'), 100, 100); +doc.createImage(Buffer.from(imageBase64Data, "base64"), 100, 100); -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); +const packer = new Packer(); -console.log('Document created successfully at project root!'); +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo19.js b/demo/demo19.js deleted file mode 100644 index 3aafebc142..0000000000 --- a/demo/demo19.js +++ /dev/null @@ -1,20 +0,0 @@ -const fs = require("fs"); -const docx = require("../build"); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -var institutionText = new docx.TextRun("Foo").bold(); -var dateText = new docx.TextRun("Bar").tab().bold(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.addParagraph(paragraph); - -var exporter = new docx.BufferPacker(doc); -exporter.pack("My Document").then((buffer) => { - // At this point, you can do anything with the buffer, including casting it to a string etc. - console.log(buffer); - fs.writeFileSync('My Document.docx', buffer); - console.log("Document created successfully at project root!"); -}); diff --git a/demo/demo19.ts b/demo/demo19.ts new file mode 100644 index 0000000000..52b5fd6694 --- /dev/null +++ b/demo/demo19.ts @@ -0,0 +1,20 @@ +// Export to base64 string - Useful in a browser environment. +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +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(); +paragraph.addRun(institutionText); +paragraph.addRun(dateText); + +doc.addParagraph(paragraph); + +const packer = new Packer(); + +packer.toBase64String(doc).then((str) => { + fs.writeFileSync("My Document.docx", str); +}); diff --git a/demo/demo2.js b/demo/demo2.js deleted file mode 100644 index 841e31b6bf..0000000000 --- a/demo/demo2.js +++ /dev/null @@ -1,74 +0,0 @@ -const docx = require('../build'); - -const doc = new docx.Document({ - creator: 'Clippy', - title: 'Sample Document', - description: 'A brief example of using docx', -}); - -doc.Styles.createParagraphStyle('Heading1', 'Heading 1') - .basedOn("Normal") - .next("Normal") - .quickFormat() - .size(28) - .bold() - .italics() - .spacing({after: 120}); - -doc.Styles.createParagraphStyle('Heading2', 'Heading 2') - .basedOn("Normal") - .next("Normal") - .quickFormat() - .size(26) - .bold() - .underline('double', 'FF0000') - .spacing({before: 240, after: 120}); - -doc.Styles.createParagraphStyle('aside', 'Aside') - .basedOn('Normal') - .next('Normal') - .color('999999') - .italics() - .indent(720) - .spacing({line: 276}); - -doc.Styles.createParagraphStyle('wellSpaced', 'Well Spaced') - .basedOn('Normal') - .spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05}); - -doc.Styles.createParagraphStyle('ListParagraph', 'List Paragraph') - .quickFormat() - .basedOn('Normal'); - - -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(); - -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.createParagraph() - .createTextRun('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.'); - -const exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo2.ts b/demo/demo2.ts new file mode 100644 index 0000000000..f32779fa06 --- /dev/null +++ b/demo/demo2.ts @@ -0,0 +1,78 @@ +// 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"; + +const doc = new Document({ + creator: "Clippy", + title: "Sample Document", + description: "A brief example of using docx", +}); + +doc.Styles.createParagraphStyle("Heading1", "Heading 1") + .basedOn("Normal") + .next("Normal") + .quickFormat() + .size(28) + .bold() + .italics() + .spacing({ after: 120 }); + +doc.Styles.createParagraphStyle("Heading2", "Heading 2") + .basedOn("Normal") + .next("Normal") + .quickFormat() + .size(26) + .bold() + .underline("double", "FF0000") + .spacing({ before: 240, after: 120 }); + +doc.Styles.createParagraphStyle("aside", "Aside") + .basedOn("Normal") + .next("Normal") + .color("999999") + .italics() + .indent({ left: 720 }) + .spacing({ line: 276 }); + +doc.Styles.createParagraphStyle("wellSpaced", "Well Spaced") + .basedOn("Normal") + .spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 }); + +doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph") + .quickFormat() + .basedOn("Normal"); + +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(); + +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 + .createParagraph() + .createTextRun("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."); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo20.js b/demo/demo20.js deleted file mode 100644 index eef332c1ae..0000000000 --- a/demo/demo20.js +++ /dev/null @@ -1,17 +0,0 @@ -const docx = require("../build"); - -var doc = new docx.Document(); - -const table = doc.createTable(4, 4); -table - .getCell(2, 2) - .addContent(new docx.Paragraph("Hello")) - .CellProperties.Borders.addTopBorder(docx.BorderStyle.DASH_DOT_STROKED, 3, "red") - .addBottomBorder(docx.BorderStyle.DOUBLE, 3, "blue") - .addStartBorder(docx.BorderStyle.DOT_DOT_DASH, 3, "green") - .addEndBorder(docx.BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo20.ts b/demo/demo20.ts new file mode 100644 index 0000000000..f3f43edb26 --- /dev/null +++ b/demo/demo20.ts @@ -0,0 +1,21 @@ +// 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"; + +const doc = new Document(); + +const table = doc.createTable(4, 4); +table + .getCell(2, 2) + .addContent(new Paragraph("Hello")) + .CellProperties.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red") + .addBottomBorder(BorderStyle.DOUBLE, 3, "blue") + .addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green") + .addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo21.js b/demo/demo21.js deleted file mode 100644 index fd74e61b31..0000000000 --- a/demo/demo21.js +++ /dev/null @@ -1,31 +0,0 @@ -/** This demo shows how to create bookmarks then link to them with internal hyperlinks */ - -const docx = require("../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."; - -const doc = new docx.Document({ - creator: 'Clippy', - title: 'Sample Document', - description: 'A brief example of using docx with bookmarks and internal hyperlinks', -}); - -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.createParagraph(loremIpsum); -doc.createParagraph().pageBreak(); - -// Now the link back up to the bookmark -const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); -doc.createParagraph().addHyperLink(hyperlink); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo21.ts b/demo/demo21.ts new file mode 100644 index 0000000000..b02da56065 --- /dev/null +++ b/demo/demo21.ts @@ -0,0 +1,37 @@ +// 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"; + +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."; + +const doc = new Document({ + creator: "Clippy", + title: "Sample Document", + description: "A brief example of using docx with bookmarks and internal hyperlinks", +}); + +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.createParagraph(loremIpsum); +doc.createParagraph().pageBreak(); + +// Now the link back up to the bookmark +const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); +doc.createParagraph().addHyperLink(hyperlink); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo22.js b/demo/demo22.js deleted file mode 100644 index 9bc7e9ac54..0000000000 --- a/demo/demo22.js +++ /dev/null @@ -1,26 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - - - -var paragraph1 = new docx.Paragraph().bidirectional(); -var textRun1 = new docx.TextRun("שלום עולם").rightToLeft(); -paragraph1.addRun(textRun1); -doc.addParagraph(paragraph1); - -var paragraph2 = new docx.Paragraph().bidirectional(); -var textRun2 = new docx.TextRun("שלום עולם").bold().rightToLeft(); -paragraph2.addRun(textRun2); -doc.addParagraph(paragraph2); - -var paragraph3 = new docx.Paragraph().bidirectional(); -var textRun3 = new docx.TextRun("שלום עולם").italic().rightToLeft(); -paragraph3.addRun(textRun3); -doc.addParagraph(paragraph3); - - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo22.ts b/demo/demo22.ts new file mode 100644 index 0000000000..c5051ab019 --- /dev/null +++ b/demo/demo22.ts @@ -0,0 +1,27 @@ +// This demo shows right to left for special languages +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "../build"; + +const doc = new Document(); + +const paragraph1 = new Paragraph().bidirectional(); +const textRun1 = new TextRun("שלום עולם").rightToLeft(); +paragraph1.addRun(textRun1); +doc.addParagraph(paragraph1); + +const paragraph2 = new Paragraph().bidirectional(); +const textRun2 = new TextRun("שלום עולם").bold().rightToLeft(); +paragraph2.addRun(textRun2); +doc.addParagraph(paragraph2); + +const paragraph3 = new Paragraph().bidirectional(); +const textRun3 = new TextRun("שלום עולם").italic().rightToLeft(); +paragraph3.addRun(textRun3); +doc.addParagraph(paragraph3); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo23.js b/demo/demo23.ts similarity index 82% rename from demo/demo23.js rename to demo/demo23.ts index 7fd5ebb6fb..47ee26a6f9 100644 --- a/demo/demo23.js +++ b/demo/demo23.ts @@ -1,19 +1,21 @@ // This demo adds an image to the Media cache, and then insert to the document afterwards -const docx = require("../build"); +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Media, Packer, Paragraph } from "../build"; -var doc = new docx.Document(); +const doc = new Document(); -var paragraph = new docx.Paragraph("Hello World"); +const paragraph = new Paragraph("Hello World"); doc.addParagraph(paragraph); -const image = docx.Media.addImage(doc, "./demo/images/image1.jpeg"); -const image2 = docx.Media.addImage(doc, "./demo/images/dog.png"); -const image3 = docx.Media.addImage(doc, "./demo/images/cat.jpg"); -const image4 = docx.Media.addImage(doc, "./demo/images/parrots.bmp"); -const image5 = docx.Media.addImage(doc, "./demo/images/pizza.gif"); +const image = Media.addImage(doc, "./demo/images/image1.jpeg"); +const image2 = Media.addImage(doc, "./demo/images/dog.png"); +const image3 = Media.addImage(doc, "./demo/images/cat.jpg"); +const image4 = Media.addImage(doc, "./demo/images/parrots.bmp"); +const image5 = Media.addImage(doc, "./demo/images/pizza.gif"); -const imageBase64Data = `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` -const image6 = docx.Media.addImageFromBuffer(doc, Buffer.from(imageBase64Data, 'base64'), 100, 100); +const imageBase64Data = `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`; +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); @@ -25,7 +27,8 @@ doc.addImage(image4); doc.addImage(image5); doc.addImage(image6); -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); +const packer = new Packer(); -console.log("Document created successfully at project root!"); +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo24.js b/demo/demo24.js deleted file mode 100644 index a95189a6ed..0000000000 --- a/demo/demo24.js +++ /dev/null @@ -1,15 +0,0 @@ -// Add image to table cell -const docx = require('../build'); - -var doc = new docx.Document(); - -const table = doc.createTable(4, 4); -table.getCell(2, 2).addContent(new docx.Paragraph('Hello')); - -const image = docx.Media.addImage(doc, "./demo/images/image1.jpeg"); -table.getCell(1, 1).addContent(image); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo24.ts b/demo/demo24.ts new file mode 100644 index 0000000000..23828aec65 --- /dev/null +++ b/demo/demo24.ts @@ -0,0 +1,18 @@ +// 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"; + +const doc = new Document(); + +const table = doc.createTable(4, 4); +table.getCell(2, 2).addContent(new Paragraph("Hello")); + +const image = Media.addImage(doc, "./demo/images/image1.jpeg"); +table.getCell(1, 1).addContent(image.Paragraph); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo25.js b/demo/demo25.js deleted file mode 100644 index 85dd29febe..0000000000 --- a/demo/demo25.js +++ /dev/null @@ -1,15 +0,0 @@ -const fs = require("fs"); -const docx = require("../build"); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -var institutionText = new docx.TextRun("Foo").bold(); -var dateText = new docx.TextRun("Bar").tab().bold(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.addParagraph(paragraph); - -var exporter = new docx.LocalPacker(doc); -exporter.packPdf("My Document"); diff --git a/demo/demo26.js b/demo/demo26.js deleted file mode 100644 index c88fdaea8e..0000000000 --- a/demo/demo26.js +++ /dev/null @@ -1,21 +0,0 @@ -const docx = require('../build'); -const fs = require('fs'); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -var institutionText = new docx.TextRun("University College London").bold(); -var dateText = new docx.TextRun("5th Dec 2015").tab().bold(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.addParagraph(paragraph); - -var packer = new docx.PdfPacker(); - -packer.toBuffer(doc).then((buffer) => { - console.log(buffer); - fs.writeFileSync('My Document.pdf', buffer); -}); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo3.js b/demo/demo3.js deleted file mode 100644 index accd597905..0000000000 --- a/demo/demo3.js +++ /dev/null @@ -1,45 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -const numbering = new docx.Numbering(); - -const abstractNum = numbering.createAbstractNumbering(); -abstractNum.createLevel(0, "upperRoman", "%1", "start") - .addParagraphProperty(new docx.Indent(720, 260)); -abstractNum.createLevel(1, "decimal", "%2.", "start") - .addParagraphProperty(new docx.Indent(1440, 980)); -abstractNum.createLevel(2, "lowerLetter", "%3)", "start") - .addParagraphProperty(new docx.Indent(2160, 1700)); - -const concrete = numbering.createConcreteNumbering(abstractNum); - -var topLevelP = new docx.Paragraph("Hey you"); -var subP = new docx.Paragraph("What's up fam"); -var secondSubP = new docx.Paragraph("Hello World 2"); -var subSubP = new docx.Paragraph("Yeah boi"); - -topLevelP.setNumbering(concrete, 0); -subP.setNumbering(concrete, 1); -secondSubP.setNumbering(concrete, 1); -subSubP.setNumbering(concrete, 2); - -doc.addParagraph(topLevelP); -doc.addParagraph(subP); -doc.addParagraph(secondSubP); -doc.addParagraph(subSubP); - -var bullet1 = new docx.Paragraph("Hey you").bullet(); -var bullet2 = new docx.Paragraph("What's up fam").bullet(1); -var bullet3 = new docx.Paragraph("Hello World 2").bullet(2); -var bullet4 = new docx.Paragraph("Yeah boi").bullet(3); - -doc.addParagraph(bullet1); -doc.addParagraph(bullet2); -doc.addParagraph(bullet3); -doc.addParagraph(bullet4); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo3.ts b/demo/demo3.ts new file mode 100644 index 0000000000..ac3680ef32 --- /dev/null +++ b/demo/demo3.ts @@ -0,0 +1,46 @@ +// 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"; + +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 })); + +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); + +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); + +doc.addParagraph(bullet1); +doc.addParagraph(bullet2); +doc.addParagraph(bullet3); +doc.addParagraph(bullet4); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo4.js b/demo/demo4.js deleted file mode 100644 index 6ded74254c..0000000000 --- a/demo/demo4.js +++ /dev/null @@ -1,12 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -const table = doc.createTable(4, 4); -table.getCell(2, 2).addContent(new docx.Paragraph('Hello')); - - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo4.ts b/demo/demo4.ts new file mode 100644 index 0000000000..eb6f5b8c09 --- /dev/null +++ b/demo/demo4.ts @@ -0,0 +1,15 @@ +// 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"; + +const doc = new Document(); + +const table = doc.createTable(4, 4); +table.getCell(2, 2).addContent(new Paragraph("Hello")); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo5.js b/demo/demo5.js deleted file mode 100644 index fbb2cd0eaf..0000000000 --- a/demo/demo5.js +++ /dev/null @@ -1,18 +0,0 @@ -const docx = require("../build"); -const fs = require('fs'); - -var doc = new docx.Document(); - -var paragraph = new docx.Paragraph("Hello World"); -doc.addParagraph(paragraph); - -doc.createImage(fs.readFileSync("./demo/images/image1.jpeg")); -doc.createImage(fs.readFileSync("./demo/images/dog.png")); -doc.createImage(fs.readFileSync("./demo/images/cat.jpg")); -doc.createImage(fs.readFileSync("./demo/images/parrots.bmp")); -doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo5.ts b/demo/demo5.ts new file mode 100644 index 0000000000..e56cdfc01e --- /dev/null +++ b/demo/demo5.ts @@ -0,0 +1,21 @@ +// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings +// 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("Hello World"); +doc.addParagraph(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")); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo6.js b/demo/demo6.js deleted file mode 100644 index 939f590d05..0000000000 --- a/demo/demo6.js +++ /dev/null @@ -1,25 +0,0 @@ -const docx = require("../build"); - -var doc = new docx.Document(undefined, { - top: 0, - right: 0, - bottom: 0, - left: 0, -}); - -var paragraph = new docx.Paragraph("Hello World"); -var institutionText = new docx.TextRun("University College London").bold(); -var dateText = new docx.TextRun("5th Dec 2015").tab().bold(); -paragraph.addRun(institutionText); -paragraph.addRun(dateText); - -doc.addParagraph(paragraph); - -doc.createParagraph("Hello World").heading1(); -doc.createParagraph("University College London"); -doc.createParagraph("5th Dec 2015"); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo6.ts b/demo/demo6.ts new file mode 100644 index 0000000000..5c9ff2798f --- /dev/null +++ b/demo/demo6.ts @@ -0,0 +1,29 @@ +// 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"; + +const doc = new Document(undefined, { + top: 0, + right: 0, + bottom: 0, + left: 0, +}); + +const paragraph = new Paragraph("Hello World"); +const institutionText = new TextRun("Foo bar").bold(); +const dateText = new TextRun("Github is the best").tab().bold(); +paragraph.addRun(institutionText); +paragraph.addRun(dateText); + +doc.addParagraph(paragraph); + +doc.createParagraph("Hello World").heading1(); +doc.createParagraph("Foo bar"); +doc.createParagraph("Github is the best"); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo7.js b/demo/demo7.js deleted file mode 100644 index f60dcd1911..0000000000 --- a/demo/demo7.js +++ /dev/null @@ -1,14 +0,0 @@ -const docx = require("../build"); - -var doc = new docx.Document(undefined, { - orientation: "landscape", -}); - -var paragraph = new docx.Paragraph("Hello World"); - -doc.addParagraph(paragraph); - -var exporter = new docx.LocalPacker(doc); -exporter.pack("My Document"); - -console.log("Document created successfully at project root!"); diff --git a/demo/demo7.ts b/demo/demo7.ts new file mode 100644 index 0000000000..fe9fccf928 --- /dev/null +++ b/demo/demo7.ts @@ -0,0 +1,18 @@ +// Example of how to set the document to landscape +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, PageOrientation, Paragraph } from "../build"; + +const doc = new Document(undefined, { + orientation: PageOrientation.LANDSCAPE, +}); + +const paragraph = new Paragraph("Hello World"); + +doc.addParagraph(paragraph); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo8.js b/demo/demo8.js deleted file mode 100644 index 03ba944473..0000000000 --- a/demo/demo8.js +++ /dev/null @@ -1,13 +0,0 @@ -const docx = require('../build'); - -var doc = new docx.Document(); - -doc.createParagraph("Hello World"); - -doc.Header.createParagraph("Header text"); -doc.Footer.createParagraph("Footer text"); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); \ No newline at end of file diff --git a/demo/demo8.ts b/demo/demo8.ts new file mode 100644 index 0000000000..c4fb96a78c --- /dev/null +++ b/demo/demo8.ts @@ -0,0 +1,17 @@ +// 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"; + +const doc = new Document(); + +doc.createParagraph("Hello World"); + +doc.Header.createParagraph("Header text"); +doc.Footer.createParagraph("Footer text"); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/demo9.js b/demo/demo9.js deleted file mode 100644 index c0a57cf8f6..0000000000 --- a/demo/demo9.js +++ /dev/null @@ -1,14 +0,0 @@ -const docx = require('../build'); -const fs = require('fs'); - -var doc = new docx.Document(); - -doc.createParagraph("Hello World"); - -doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); -doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); - -var exporter = new docx.LocalPacker(doc); -exporter.pack('My Document'); - -console.log('Document created successfully at project root!'); diff --git a/demo/demo9.ts b/demo/demo9.ts new file mode 100644 index 0000000000..87fe9b5192 --- /dev/null +++ b/demo/demo9.ts @@ -0,0 +1,17 @@ +// 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"; + +const doc = new Document(); + +doc.createParagraph("Hello World"); + +doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif")); +doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif")); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/index.js b/demo/index.js index 8ae9aac536..e6c7d926d0 100644 --- a/demo/index.js +++ b/demo/index.js @@ -18,12 +18,16 @@ prompt.start(); prompt.get(schema, function (err, result) { var demoNumber = result.number; - var filePath = `./demo/demo${demoNumber}.js`; + var filePath = `./demo/demo${demoNumber}.ts`; if (!fs.existsSync(filePath)) { console.error(`demo${demoNumber} does not exist: ${filePath}`); return; } console.log(`Running demo ${demoNumber}`); - shelljs.exec(`node ${filePath}`); + if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) { + console.log("Document created successfully"); + } else { + console.error('Something went wrong with the demo'); + } }); diff --git a/package.json b/package.json index 98acfbfe79..3132ae6445 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "typedoc": "typedoc src/index.ts", "style": "prettier -l \"src/**/*.ts\"", "style.fix": "prettier \"src/**/*.ts\" --write", - "fix-types": "node types-absolute-fixer.js" + "fix-types": "node types-absolute-fixer.js", + "ts-node": "ts-node" }, "pre-commit": [ "style", @@ -76,6 +77,7 @@ "rimraf": "^2.5.2", "shelljs": "^0.7.7", "sinon": "^5.0.7", + "ts-node": "^7.0.1", "tslint": "^5.11.0", "typedoc": "^0.11.1", "typescript": "2.9.2", diff --git a/src/file/paragraph/formatting/indent.ts b/src/file/paragraph/formatting/indent.ts index 0b42246689..cd7528d2b8 100644 --- a/src/file/paragraph/formatting/indent.ts +++ b/src/file/paragraph/formatting/indent.ts @@ -1,7 +1,7 @@ // http://officeopenxml.com/WPindentation.php import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; -interface IIndentAttributesProperties { +export interface IIndentAttributesProperties { left?: number; hanging?: number; firstLine?: number; @@ -20,7 +20,7 @@ class IndentAttributes extends XmlAttributeComponent Date: Tue, 21 Aug 2018 10:27:46 +0100 Subject: [PATCH 52/63] Update .travis.yml --- .travis.yml | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 986233743d..373070eeb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,18 +8,30 @@ script: - npm test - npm run style - npm run build - - node ./demo/demo1.js - - node ./demo/demo2.js - - node ./demo/demo3.js - - node ./demo/demo4.js - - node ./demo/demo5.js - - node ./demo/demo6.js - - node ./demo/demo7.js - - node ./demo/demo8.js - - node ./demo/demo9.js - - node ./demo/demo10.js - - node ./demo/demo11.js - - node ./demo/demo12.js + - npm run ts-node -- ./demo/demo1.ts + - 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/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 after_failure: - "cat /home/travis/builds/dolanmiu/docx/npm-debug.log" after_success: From a777842f9d3488562770f202e663df069bd5e290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mendon=C3=A7a?= Date: Tue, 21 Aug 2018 07:16:27 -0300 Subject: [PATCH 53/63] updated mocha to version 5 due to vulnerabilities found by npm audit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 52b8d3fc56..c89bbd2de6 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "chai": "^3.5.0", "glob": "^7.1.2", "jszip": "^3.1.5", - "mocha": "^3.2.0", + "mocha": "^5.2.0", "mocha-webpack": "^1.0.1", "pre-commit": "^1.2.2", "prettier": "^1.12.1", From 410080a8a3ccb6bd843ae85a0587fa4e8fe53b07 Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 21 Aug 2018 19:27:07 +0100 Subject: [PATCH 54/63] Fix tests --- demo/demo10.ts | 48 +++++++++++++++++++++++++---------------- demo/demo11.ts | 8 +++---- src/file/table/table.ts | 4 ++++ 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/demo/demo10.ts b/demo/demo10.ts index b55542b866..84713e777f 100644 --- a/demo/demo10.ts +++ b/demo/demo10.ts @@ -3,6 +3,8 @@ import * as fs from "fs"; import { Document, Packer, Paragraph, TextRun } from "../build"; +// tslint:disable:no-shadowed-variable + const PHONE_NUMBER = "07534563401"; const PROFILE_URL = "https://www.linkedin.com/in/dolan1"; const EMAIL = "docx@com"; @@ -125,11 +127,13 @@ const achievements = [ ]; class DocumentCreator { - public create(data): Document { - const experiences = data[0]; - const educations = data[1]; - const skills = data[2]; - const achivements = data[3]; + 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[]; const document = new Document(); document.addParagraph(new Paragraph("Dolan Miu").title()); @@ -197,7 +201,7 @@ class DocumentCreator { return document; } - createContactInfo(phoneNumber: string, profileUrl: string, email: string) { + public createContactInfo(phoneNumber: string, profileUrl: string, email: string): Paragraph { const paragraph = new Paragraph().center(); const contactInfo = new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`); const address = new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(); @@ -208,15 +212,15 @@ class DocumentCreator { return paragraph; } - createHeading(text) { + public createHeading(text: string): Paragraph { return new Paragraph(text).heading1().thematicBreak(); } - createSubHeading(text) { + public createSubHeading(text: string): Paragraph { return new Paragraph(text).heading2(); } - createInstitutionHeader(institutionName, dateText) { + public createInstitutionHeader(institutionName: string, dateText: string): Paragraph { const paragraph = new Paragraph().maxRightTabStop(); const institution = new TextRun(institutionName).bold(); const date = new TextRun(dateText).tab().bold(); @@ -227,7 +231,7 @@ class DocumentCreator { return paragraph; } - createRoleText(roleText) { + public createRoleText(roleText: string): Paragraph { const paragraph = new Paragraph(); const role = new TextRun(roleText).italic(); @@ -236,11 +240,12 @@ class DocumentCreator { return paragraph; } - createBullet(text) { + public createBullet(text: string): Paragraph { return new Paragraph(text).bullet(); } - createSkillList(skills) { + // tslint:disable-next-line:no-any + public createSkillList(skills: any[]): Paragraph { const paragraph = new Paragraph(); const skillConcat = skills.map((skill) => skill.name).join(", ") + "."; @@ -249,35 +254,38 @@ class DocumentCreator { return paragraph; } - public createAchivementsList(achivements): Paragraph { - const arr = []; + // tslint:disable-next-line:no-any + public createAchivementsList(achivements: any[]): Paragraph[] { + const arr: Paragraph[] = []; for (const achievement of achivements) { - arr.push(new Paragraph(achievement.name).bullet()); + const paragraph = new Paragraph(achievement.name).bullet(); + arr.push(paragraph); } return arr; } - createInterests(interests) { + public createInterests(interests: string): Paragraph { const paragraph = new Paragraph(); paragraph.addRun(new TextRun(interests)); return paragraph; } - splitParagraphIntoBullets(text) { + public splitParagraphIntoBullets(text: string): string[] { return text.split("\n\n"); } - createPositionDateText(startDate, endDate, isCurrent) { + // tslint:disable-next-line:no-any + public createPositionDateText(startDate: any, endDate: any, isCurrent: boolean): string { const startDateText = this.getMonthFromInt(startDate.month) + ". " + startDate.year; const endDateText = isCurrent ? "Present" : `${this.getMonthFromInt(endDate.month)}. ${endDate.year}`; return `${startDateText} - ${endDateText}`; } - getMonthFromInt(value) { + public getMonthFromInt(value: number): string { switch (value) { case 1: return "Jan"; @@ -303,6 +311,8 @@ class DocumentCreator { return "Nov"; case 12: return "Dec"; + default: + return "N/A"; } } } diff --git a/demo/demo11.ts b/demo/demo11.ts index 3b0cf0b01f..76ec915060 100644 --- a/demo/demo11.ts +++ b/demo/demo11.ts @@ -18,7 +18,7 @@ doc.Styles.createParagraphStyle("Heading1", "Heading 1") .size(52) .center() .bold() - .color(000000) + .color("000000") .spacing({ line: 340 }) .underline("single", "000000"); @@ -112,7 +112,7 @@ table .getRow(0) .getCell(0) .addContent(new Paragraph("Pole No.")); -table.Properties.width = 10000; +// table.Properties.width = 10000; doc.addTable(table); const arrboth = [ @@ -129,8 +129,8 @@ const arrboth = [ arrboth.forEach((item) => { const para = doc.createParagraph(); para.addImage(doc.createImage(fs.readFileSync(item.image))); - para.Properties.width = 60; - para.Properties.height = 90; + // para.Properties.width = 60; + // para.Properties.height = 90; doc.createParagraph(item.comment).style("normalPara2"); }); diff --git a/src/file/table/table.ts b/src/file/table/table.ts index d82da34ff2..335f5fd1c2 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -76,6 +76,10 @@ export class Table extends XmlComponent { this.properties.setFixedWidthLayout(); return this; } + + public get Properties(): TableProperties { + return this.properties; + } } export class TableRow extends XmlComponent { From 6f0f3ccca737360fd466c7a5fc73a6c42aae704a Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 21 Aug 2018 21:46:12 +0100 Subject: [PATCH 55/63] Update documentation --- docs/usage/packers.md | 57 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/docs/usage/packers.md b/docs/usage/packers.md index db837702de..11f107390d 100644 --- a/docs/usage/packers.md +++ b/docs/usage/packers.md @@ -2,7 +2,48 @@ > Packers are the way in which `docx` turns your code into `.docx` format. It is completely decoupled from the `docx.Document`. -## File System Packer +## 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. + +### Export as Buffer + +This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead. + +```js +const packer = new docx.Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); +``` + +### Export as a `base64` string + +```js +const packer = new docx.Packer(); + +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. + +```js +const packer = new docx.Packer(); + +packer.toBlob(doc).then((blob) => { + // saveAs from FileSaver will download the file + saveAs(blob, "example.docx"); +}); +``` + +## Version 3 and below + +### File System Packer ```js const docx = require("docx"); @@ -13,7 +54,7 @@ exporter.pack("My Document"); // Word Document is in file system ``` -## Buffer Packer +### Buffer Packer ```js const docx = require("docx"); @@ -23,7 +64,7 @@ const exporter = new docx.BufferPacker(doc); const buffer = exporter.pack(); ``` -## Stream Packer +### Stream Packer Creates a `node` `Readable` stream @@ -35,7 +76,7 @@ const exporter = new docx.StreamPacker(doc); const stream = exporter.pack(); ``` -## Express Packer +### Express Packer The old express packer is now deprecated and may disappear soon, so you should upgrade. @@ -56,13 +97,13 @@ const exporter = new docx.StreamPacker(doc); const stream = exporter.pack(); // Express' response object -res.attachment('yourfile.xlsx'); +res.attachment("yourfile.xlsx"); stream.pipe(res); ``` where `res` is the response object obtained through the Express router. It is that simple. The file will begin downloading in the browser. -## PDF Exporting +### PDF Exporting You can export your word document as a PDF file like so: @@ -74,7 +115,3 @@ exporter.packPdf("My Document"); const exporter = new docx.ExpressPacker(doc, res); exporter.packPdf("My Document"); ``` - -## Browser based docx exporting - -It is on the bucket list. It has been requested by a few, and work is already on it From 6c2f335a318d6a71b15f2bfa8dd169ead50bde4b Mon Sep 17 00:00:00 2001 From: Dolan Date: Tue, 21 Aug 2018 22:29:40 +0100 Subject: [PATCH 56/63] Add new slogan --- README.md | 2 +- docs/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 84b4a75e0b..7e25666ee0 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

- Easily generate .docx files with JS/TS. + Easily generate .docx files with JS/TS. Works for Node and on the Browser.

--- diff --git a/docs/README.md b/docs/README.md index 557bcbad65..f3134b8fa3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@

- Easily generate .docx files with JS/TS. :100: + Easily generate .docx files with JS/TS. Works for Node and on the Browser. :100:

--- From 9a6c92222c7055906a0166164559c404abefd794 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 22 Aug 2018 00:51:18 +0100 Subject: [PATCH 57/63] 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); +}); From 85f686dede9cfdd12c44a429bb2ef63f38776d22 Mon Sep 17 00:00:00 2001 From: Dolan Date: Wed, 22 Aug 2018 01:14:17 +0100 Subject: [PATCH 58/63] Fix demo examples --- docs/examples.md | 105 ++++++------ src/file/paragraph/paragraph.ts.orig | 243 +++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 56 deletions(-) create mode 100644 src/file/paragraph/paragraph.ts.orig diff --git a/docs/examples.md b/docs/examples.md index cd811ded43..05dbfb2de5 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -14,9 +14,9 @@ This command will run the `demo selector app` in the `/demo` folder. It will pro A simple hello world of the `docx` library: -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo1.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo1.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo1.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo1.ts_ ## Styles @@ -24,41 +24,41 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo1.js_ This example shows how to customise the look and feel of a document using JS configuration -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo2.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo2.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo2.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo2.ts_ ### Styling with XML This example shows how to customise the look and feel of a document using XML configuration -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo13.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo13.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo13.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo13.ts_ ## Numbering This example shows many levels of numbering -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo3.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo3.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo3.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo3.ts_ ## Table Example of simple table -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_ ### Styling table borders Styling the borders of a table -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_ ## Images @@ -66,73 +66,73 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.js_ Importing Images from file system path -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_ ### Add images to header and footer Example showing how to add image to headers and footers -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_ ### Scaling images Example showing how to scale images -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo12.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo12.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo12.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo12.ts_ ### Add Image to media before adding to document This is the best way to add an image to a document because you can add the same image in two locations without increasing document size by re-using the same image -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo23.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo23.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo23.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo23.ts_ ### Add image to table As before, to add an image to a table, you would need to add it to the `Media` object first -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo24.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo24.ts_ ### Images using Base64 URI If you want to use a Base64 image instead -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo18.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo18.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo18.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo18.ts_ ## Margins Example showing how to set custom margains -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo6.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo6.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo6.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo6.ts_ ## Orientation Example showing how to set the document to `landscape` or `portrait` -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo7.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo7.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo7.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo7.ts_ ## Headers & Footers Example showing how to add headers and footers -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo8.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo8.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo8.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo8.ts_ ## Multiple headers and footers @@ -144,67 +144,60 @@ Check out `Sections` for this feature Example showing how to page break -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo14.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo14.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo14.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo14.ts_ ### Page break before Example showing how to page break before like in Word -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo15.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo15.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo15.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo15.ts_ ## Sections Example of how sections work. Sections allow multiple headers and footers, and `landscape`/`portrait` inside the same document -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo16.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo16.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo16.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo16.ts_ ## Footnotes Example of how to add footnotes. Good for references -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo17.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo17.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo17.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo17.ts_ ## Packers -## Buffer Packer +## Buffer output Example showing how to use the Buffer packer and then write that buffer to the file system -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo19.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo19.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo19.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo19.ts_ -## PDF Packing - -Example of how to use the `LocalPacker` to create a PDF document - -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo25.js ":include") - -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo25.js_ ## Bookmarks Example showing how to make bookmarks to make internal hyperlinks within the document -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo21.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo21.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo21.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo21.ts_ ## Bidirectional text Example showing how to use bidirectional text for certain languages such as Hebrew -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo22.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo22.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo22.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo22.ts_ ## Showcase @@ -212,14 +205,14 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo22.js_ Example showing how to add headers and footers -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo10.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo10.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo10.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo10.ts_ ### Style and Images This example shows how to customise the look and feel of a document and add images -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo11.js ":include") +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo11.ts ":include") -_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo11.js_ +_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo11.ts_ diff --git a/src/file/paragraph/paragraph.ts.orig b/src/file/paragraph/paragraph.ts.orig new file mode 100644 index 0000000000..7ffbeca43d --- /dev/null +++ b/src/file/paragraph/paragraph.ts.orig @@ -0,0 +1,243 @@ +// 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; + } +} From e68bc50e6eee7cdc1f3b116be13d5c23bd461177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mendon=C3=A7a?= Date: Wed, 22 Aug 2018 10:39:13 -0300 Subject: [PATCH 59/63] style fixed --- src/file/media/media.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/file/media/media.ts b/src/file/media/media.ts index cd90105581..284ca8806d 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -9,8 +9,13 @@ interface IHackedFile { } export class Media { - - public static addImage(file: File, buffer: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number, drawingOptions?: IDrawingOptions): Image { + public static addImage( + file: File, + buffer: Buffer | string | Uint8Array | ArrayBuffer, + width?: number, + height?: number, + drawingOptions?: IDrawingOptions, + ): Image { // Workaround to expose id without exposing to API const exposedFile = (file as {}) as IHackedFile; const mediaData = file.Media.addMedia(buffer, exposedFile.currentRelationshipId++, width, height); From 877dcb462f0569e247be45ff1830a918b17c1a03 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 23 Aug 2018 00:55:33 +0100 Subject: [PATCH 60/63] Add table cell margin --- src/file/table/properties.spec.ts | 14 +++++++- src/file/table/properties.ts | 19 +++++++--- src/file/table/table-cell-margin.ts | 55 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 src/file/table/table-cell-margin.ts diff --git a/src/file/table/properties.spec.ts b/src/file/table/properties.spec.ts index c10c18f4c2..a26e3fd352 100644 --- a/src/file/table/properties.spec.ts +++ b/src/file/table/properties.spec.ts @@ -2,6 +2,7 @@ import { expect } from "chai"; import { Formatter } from "../../export/formatter"; import { TableProperties } from "./properties"; +import { WidthType } from "./table-cell"; describe("TableProperties", () => { describe("#constructor", () => { @@ -14,7 +15,7 @@ describe("TableProperties", () => { describe("#setWidth", () => { it("adds a table width property", () => { - const tp = new TableProperties().setWidth("dxa", 1234); + const tp = new TableProperties().setWidth(WidthType.DXA, 1234); const tree = new Formatter().format(tp); expect(tree).to.deep.equal({ "w:tblPr": [{ "w:tblW": [{ _attr: { "w:type": "dxa", "w:w": 1234 } }] }], @@ -31,4 +32,15 @@ describe("TableProperties", () => { }); }); }); + + describe("#cellMargin", () => { + it("adds a table cell top margin", () => { + const tp = new TableProperties(); + tp.CellMargin.addTopMargin(1234, WidthType.DXA); + const tree = new Formatter().format(tp); + expect(tree).to.deep.equal({ + "w:tblPr": [{ "w:tblCellMar": [{ "w:top": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] }], + }); + }); + }); }); diff --git a/src/file/table/properties.ts b/src/file/table/properties.ts index 64b0ed53ad..7c5b0bad76 100644 --- a/src/file/table/properties.ts +++ b/src/file/table/properties.ts @@ -1,13 +1,18 @@ import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; - -export type WidthTypes = "dxa" | "pct" | "nil" | "auto"; +import { WidthType } from "./table-cell"; +import { TableCellMargin } from "./table-cell-margin"; export class TableProperties extends XmlComponent { + private readonly cellMargain: TableCellMargin; + constructor() { super("w:tblPr"); + + this.cellMargain = new TableCellMargin(); + this.root.push(this.cellMargain); } - public setWidth(type: WidthTypes, w: number | string): TableProperties { + public setWidth(type: WidthType, w: number | string): TableProperties { this.root.push(new PreferredTableWidth(type, w)); return this; } @@ -21,10 +26,14 @@ export class TableProperties extends XmlComponent { this.root.push(new TableBorders()); return this; } + + public get CellMargin(): TableCellMargin { + return this.cellMargain; + } } interface ITableWidth { - type: WidthTypes; + type: WidthType; w: number | string; } @@ -33,7 +42,7 @@ class TableWidthAttributes extends XmlAttributeComponent { } class PreferredTableWidth extends XmlComponent { - constructor(type: WidthTypes, w: number | string) { + constructor(type: WidthType, w: number | string) { super("w:tblW"); this.root.push(new TableWidthAttributes({ type, w })); } diff --git a/src/file/table/table-cell-margin.ts b/src/file/table/table-cell-margin.ts new file mode 100644 index 0000000000..198dc89cbd --- /dev/null +++ b/src/file/table/table-cell-margin.ts @@ -0,0 +1,55 @@ +import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components"; +import { WidthType } from "./table-cell"; + +class TableCellMarginAttributes extends XmlAttributeComponent<{ type: WidthType; value: number }> { + protected xmlKeys = { value: "w:w", type: "w:sz" }; +} + +class BaseTableCellMargin extends XmlComponent { + public setProperties(value: number, type: WidthType = WidthType.DXA): void { + this.root.push( + new TableCellMarginAttributes({ + type: type, + value: value, + }), + ); + } +} + +export class TableCellMargin extends XmlComponent { + constructor() { + super("w:tblCellMar"); + } + + public prepForXml(): IXmlableObject { + return this.root.length > 0 ? super.prepForXml() : ""; + } + + public addTopMargin(value: number, type: WidthType = WidthType.DXA): void { + const top = new BaseTableCellMargin("w:top"); + + top.setProperties(value, type); + this.root.push(top); + } + + public addLeftMargin(value: number, type: WidthType = WidthType.DXA): void { + const left = new BaseTableCellMargin("w:left"); + + left.setProperties(value, type); + this.root.push(left); + } + + public addBottomMargin(value: number, type: WidthType = WidthType.DXA): void { + const bottom = new BaseTableCellMargin("w:bottom"); + + bottom.setProperties(value, type); + this.root.push(bottom); + } + + public addRightMargin(value: number, type: WidthType = WidthType.DXA): void { + const right = new BaseTableCellMargin("w:right"); + + right.setProperties(value, type); + this.root.push(right); + } +} From fe2032a3d45befda0090468751361beebf8b09e8 Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 23 Aug 2018 01:05:26 +0100 Subject: [PATCH 61/63] change demos to typescript and WidthType disparity --- demo/index.js | 33 --------------------------------- demo/index.ts | 34 ++++++++++++++++++++++++++++++++++ package.json | 2 +- src/file/table/table.spec.ts | 3 ++- src/file/table/table.ts | 4 ++-- 5 files changed, 39 insertions(+), 37 deletions(-) delete mode 100644 demo/index.js create mode 100644 demo/index.ts diff --git a/demo/index.js b/demo/index.js deleted file mode 100644 index e6c7d926d0..0000000000 --- a/demo/index.js +++ /dev/null @@ -1,33 +0,0 @@ -var prompt = require('prompt'); -var shelljs = require('shelljs'); -var fs = require('fs'); - -console.log('What demo do you wish to run? (Enter a number)'); - -var schema = { - properties: { - number: { - pattern: /^[0-9]+$/, - message: 'Please enter a number.', - required: true - } - } -}; - -prompt.start(); - -prompt.get(schema, function (err, result) { - var demoNumber = result.number; - var filePath = `./demo/demo${demoNumber}.ts`; - - if (!fs.existsSync(filePath)) { - console.error(`demo${demoNumber} does not exist: ${filePath}`); - return; - } - console.log(`Running demo ${demoNumber}`); - if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) { - console.log("Document created successfully"); - } else { - console.error('Something went wrong with the demo'); - } -}); diff --git a/demo/index.ts b/demo/index.ts new file mode 100644 index 0000000000..50b65572f2 --- /dev/null +++ b/demo/index.ts @@ -0,0 +1,34 @@ +// tslint:disable:no-console +import * as fs from "fs"; +import * as prompt from "prompt"; +import * as shelljs from "shelljs"; + +console.log("What demo do you wish to run? (Enter a number)"); + +const schema = { + properties: { + number: { + pattern: /^[0-9]+$/, + message: "Please enter a number.", + required: true, + }, + }, +}; + +prompt.start(); + +prompt.get(schema, (_, result) => { + const demoNumber = result.number; + const filePath = `./demo/demo${demoNumber}.ts`; + + if (!fs.existsSync(filePath)) { + console.error(`demo${demoNumber} does not exist: ${filePath}`); + return; + } + console.log(`Running demo ${demoNumber}`); + if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) { + console.log("Document created successfully"); + } else { + console.error("Something went wrong with the demo"); + } +}); diff --git a/package.json b/package.json index d34f093a50..999b6b6393 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "tsc": "rimraf ./build && tsc -p .", "webpack": "rimraf ./build && webpack", "build.web": "webpack --config webpack.web.config.js", - "demo": "npm run build && node ./demo", + "demo": "npm run build && npm run ts-node ./demo", "typedoc": "typedoc src/index.ts", "style": "prettier -l \"src/**/*.ts\"", "style.fix": "prettier \"src/**/*.ts\" --write", diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index 21ee3e63d4..65871655b4 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -4,6 +4,7 @@ import { expect } from "chai"; import { Formatter } from "../../export/formatter"; import { Paragraph } from "../paragraph"; import { Table } from "./"; +import { WidthType } from "./table-cell"; const DEFAULT_TABLE_PROPERTIES = { "w:tblBorders": [ @@ -174,7 +175,7 @@ describe("Table", () => { describe("#setWidth", () => { it("sets the preferred width on the table", () => { - const table = new Table(2, 2).setWidth("pct", 1000); + const table = new Table(2, 2).setWidth(WidthType.PERCENTAGE, 1000); const tree = new Formatter().format(table); expect(tree) .to.have.property("w:tbl") diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 335f5fd1c2..0406bdf549 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -12,7 +12,7 @@ import { import { IXmlableObject, XmlComponent } from "file/xml-components"; import { Paragraph } from "../paragraph"; import { TableGrid } from "./grid"; -import { TableProperties, WidthTypes } from "./properties"; +import { TableProperties } from "./properties"; export class Table extends XmlComponent { private readonly properties: TableProperties; @@ -67,7 +67,7 @@ export class Table extends XmlComponent { return this.getRow(row).getCell(col); } - public setWidth(type: WidthTypes, width: number | string): Table { + public setWidth(type: WidthType, width: number | string): Table { this.properties.setWidth(type, width); return this; } From 90497036a6ef8f8cdf072a4472d29f2e6fa0acaf Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 23 Aug 2018 01:12:54 +0100 Subject: [PATCH 62/63] Fix browser demo --- demo/browser-demo.html | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/demo/browser-demo.html b/demo/browser-demo.html index 17508b74eb..fff5dc7989 100644 --- a/demo/browser-demo.html +++ b/demo/browser-demo.html @@ -2,7 +2,8 @@ - + + @@ -13,7 +14,23 @@ From 60abe4857bddee76e21ee6536940d5648dba974b Mon Sep 17 00:00:00 2001 From: Dolan Date: Thu, 23 Aug 2018 01:26:30 +0100 Subject: [PATCH 63/63] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 999b6b6393..330ad72bac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docx", - "version": "3.6.0", + "version": "4.0.0", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "main": "build/index.js", "scripts": {