diff --git a/package-lock.json b/package-lock.json index 1dab4cc..2165d52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "chai": "4.3.6", "eslint": "8.25.0", "lint-staged": "10.5.4", - "mocha": "10.2.0", + "mocha": "^10.2.0", "pdfjs-dist": "2.16.105", "rollup": "3.7.4", "typescript": "4.7.2", diff --git a/src/cli.js b/src/cli.js index 9f1363d..0a998d7 100644 --- a/src/cli.js +++ b/src/cli.js @@ -32,7 +32,7 @@ function setupDebugMessages(printer) { } } -const argv = yargs(process.argv.slice(2)) +const cargv = yargs(process.argv.slice(2)) .scriptName("print-ready") .version(false) .options({ @@ -44,10 +44,9 @@ const argv = yargs(process.argv.slice(2)) type: "boolean", describe: "Turn on debugging messages." }, - help: { - alias: "h", - type: "boolean", - describe: "Show the help screen." + timeout: { + type: "number", + describe: "Set the rendering timeout in milliseconds." }, version: { alias: "v", @@ -56,21 +55,22 @@ const argv = yargs(process.argv.slice(2)) } }) .usage("$0 [options] filename") - .argv; + .help(); //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- (async() => { - const printer = new Printer(); + const argv = cargv.argv; + const printer = new Printer({ timeout: argv.timeout }); if (argv.debug) { setupDebugMessages(printer); } if (!argv._.length) { - argv.showHelp(); + cargv.showHelp(); process.exit(1); } diff --git a/src/printer.js b/src/printer.js index ba7ce59..f9d4945 100644 --- a/src/printer.js +++ b/src/printer.js @@ -71,7 +71,7 @@ function createPuppeteerOptions() { * PDF options. */ function createPdfOptions(options = {}) { - return { + const pdfOptions = { printBackground: true, displayHeaderFooter: false, preferCSSPageSize: options.width ? false : true, @@ -85,6 +85,12 @@ function createPdfOptions(options = {}) { left: 0 } }; + + if (typeof options.timeout === "number") { + pdfOptions.timeout = options.timeout; + } + + return pdfOptions; } /** @@ -162,7 +168,8 @@ async function setPdfMeta(page, pdf) { export class Printer extends EventEmitter { constructor({ - cwd = process.cwd() + cwd = process.cwd(), + timeout } = {}) { super(); @@ -172,6 +179,12 @@ export class Printer extends EventEmitter { * @type {string} */ this.cwd = cwd; + + /** + * The timeout for the printer rendering. + * @type {number|undefined} + */ + this.timeout = timeout; } get supportedEvents() { @@ -320,7 +333,18 @@ export class Printer extends EventEmitter { // generate the PDF this.emit("pdfstart", { url }); - const blob = await page.pdf(createPdfOptions()); + let blob; + + try { + blob = await page.pdf(createPdfOptions({ + timeout: this.timeout + })); + } catch (error) { + await page.close(); + await browser.close(); + throw error; + } + this.emit("pdfend", { url }); const pdf = await PDFDocument.load(blob); diff --git a/tests/printer.test.js b/tests/printer.test.js index 575f3a1..84492a9 100644 --- a/tests/printer.test.js +++ b/tests/printer.test.js @@ -29,6 +29,22 @@ const FIXTURES_DIR = path.resolve(__dirname, "fixtures"); describe("Printer", () => { + describe("new Printer()", () => { + it("should have default cwd", () => { + const printer = new Printer(); + expect(printer.cwd).to.equal(process.cwd()); + }); + + it("should save cwd", () => { + const printer = new Printer({ cwd: "foo" }); + expect(printer.cwd).to.equal("foo"); + }); + + it("should save timeout", () => { + const printer = new Printer({ timeout: 500 }); + expect(printer.timeout).to.equal(500); + }); + }); describe("printFileToPdf()", () => { @@ -71,7 +87,24 @@ describe("Printer", () => { }); + describe("setting timeout", () => { + const filePath = path.resolve(FIXTURES_DIR, "one-page.html"); + + it("should throw a timeout error", () => { + + const printer = new Printer({ timeout: 1 }); + + return printer.printFileToPdf(filePath) + .then(() => { + expect.fail("Promise should be rejected"); + }) + .catch(error => { + expect(error.message).to.match(/timeout 1ms exceeded/); + }); + }); + + }); }); });