From 600fef21f63c29853e84c00a0d8bb363b8e88bfc Mon Sep 17 00:00:00 2001 From: Matt Danner Date: Mon, 22 Aug 2022 13:24:12 -0700 Subject: [PATCH 1/6] Update webpack.config.ts for nodestreams Without this alias, JSZip throws a "nodestream not supported on this platform" error. This addition resolves the issue. --- webpack.config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webpack.config.ts b/webpack.config.ts index 0f03537add..5871440f3f 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -23,6 +23,9 @@ const configuration = { stream: require.resolve("stream-browserify"), }, plugins: [new TsconfigPathsPlugin()], + alias: { + jszip: require.resolve('jszip/lib/index.js'), + }, }, module: { From 1a630bcb4d574a1b29d3fbec625784ff7b77d96a Mon Sep 17 00:00:00 2001 From: Matt Danner Date: Mon, 22 Aug 2022 13:25:59 -0700 Subject: [PATCH 2/6] Added toStream export function New Function returns a NodeJS readable stream that allows piping DOCX document data to stream. --- src/export/packer/packer.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index 56d604fe18..fa783234d6 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -1,4 +1,5 @@ import { File } from "@file/file"; +import { Stream } from "stream"; import { Compiler } from "./next-compiler"; @@ -45,6 +46,18 @@ export class Packer { return zipData; } + + public static async toStream(file: File, prettify?: boolean | PrettifyType): Promise { + const zip = this.compiler.compile(file, prettify); + const zipData = zip.generateNodeStream({ + type: "nodebuffer", + streamFiles: true, + mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + compression: "DEFLATE", + }); + + return zipData; + } private static readonly compiler = new Compiler(); } From f4f6ee50551acfdbd08b315bbd86f68145da9ffc Mon Sep 17 00:00:00 2001 From: Matt Danner Date: Mon, 22 Aug 2022 15:26:52 -0500 Subject: [PATCH 3/6] Created toStream example --- demo/74-nodejs-stream.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 demo/74-nodejs-stream.ts diff --git a/demo/74-nodejs-stream.ts b/demo/74-nodejs-stream.ts new file mode 100644 index 0000000000..4dea1f7524 --- /dev/null +++ b/demo/74-nodejs-stream.ts @@ -0,0 +1,31 @@ +// 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({ + sections: [ + { + properties: {}, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + new TextRun({ + text: "\tGithub is the best", + bold: true, + }), + ], + }), + ], + }, + ], +}); + +Packer.toStream(doc).then((stream) => { + stream.pipe(fs.createWriteStream("My Document.docx")); +}); From c982e6499691d982fff3949d87f4f81fe5431d49 Mon Sep 17 00:00:00 2001 From: Matt Danner Date: Wed, 24 Aug 2022 13:01:15 -0500 Subject: [PATCH 4/6] formatting --- src/export/packer/packer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/export/packer/packer.ts b/src/export/packer/packer.ts index fa783234d6..7a3a35316a 100644 --- a/src/export/packer/packer.ts +++ b/src/export/packer/packer.ts @@ -46,7 +46,7 @@ export class Packer { return zipData; } - + public static async toStream(file: File, prettify?: boolean | PrettifyType): Promise { const zip = this.compiler.compile(file, prettify); const zipData = zip.generateNodeStream({ From 9f3940746acf9d2d830098f180c257f7640e20fe Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Thu, 15 Sep 2022 08:15:38 +0100 Subject: [PATCH 5/6] Add tests for stream packer --- src/export/packer/packer.spec.ts | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index 5500144eff..c9ef4232b4 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -114,4 +114,52 @@ describe("Packer", () => { (Packer as any).compiler.compile.restore(); }); }); + + describe("#toStream()", () => { + it("should create a standard docx file", async () => { + // tslint:disable-next-line: no-any + stub((Packer as any).compiler, "compile").callsFake(() => ({ + // tslint:disable-next-line: no-empty + generateNodeStream: () => ({ + on: (event: string, cb: () => void) => { + if (event === "end") { + cb(); + } + }, + }), + })); + const stream = await Packer.toStream(file); + return new Promise((resolve, reject) => { + stream.on("error", () => { + reject(); + }); + + stream.on("end", () => { + resolve(); + }); + }); + }); + + it("should handle exception if it throws any", async () => { + // tslint:disable-next-line:no-any + const compiler = stub((Packer as any).compiler, "compile").callsFake(() => ({ + // tslint:disable-next-line: no-empty + on: (event: string, cb: () => void) => { + if (event === "error") { + cb(); + } + }, + })); + + compiler.throwsException(); + return await Packer.toStream(file).catch((error) => { + assert.isDefined(error); + }); + }); + + afterEach(() => { + // tslint:disable-next-line:no-any + (Packer as any).compiler.compile.restore(); + }); + }); }); From 2b01a6006cf98453263d83193e0562e0ffd635e8 Mon Sep 17 00:00:00 2001 From: Dolan Miu Date: Thu, 15 Sep 2022 12:39:30 +0100 Subject: [PATCH 6/6] Fix linting --- src/export/packer/packer.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index c9ef4232b4..b3ba67a033 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -152,7 +152,7 @@ describe("Packer", () => { })); compiler.throwsException(); - return await Packer.toStream(file).catch((error) => { + return Packer.toStream(file).catch((error) => { assert.isDefined(error); }); });