#!/usr/bin/env node const program = require("commander"); const ora = require("ora"); const Printer = require("../"); const path = require("path"); const fs = require("fs"); // const { promisify } = require("util"); // const writeFileAsync = promisify(fs.writeFile); const replaceExt = require("replace-ext"); program .version(require("../package.json").version) .arguments("[inputPath]") .option("-i, --inputs [inputs]", "Inputs") .option("-o, --output [output]", "Output") .option("-d, --debug", "Debug") .option("-l, --landscape", "Landscape printing", false) .option("-s, --page-size [size]", "Print to Page Size [size]") .option("-w, --width [size]", "Print to Page Width [width] in MM") .option("-h --height [size]", "Print to Page Height [weight] in MM") .option("--forceTransparentBackground", "Print with transparent background") // .option("-m, --page-margin [margin]", "Print with margin [margin]") // .option("-n, --hyphenate [lang]", "Hyphenate with language [language], defaults to "en-us"") // .option("-hi, --hypher_ignore [str]", "Ignore passed element selectors, such as ".class_to_ignore, h1"") // .option("-ho, --hypher_only [str]", "Only hyphenate passed elements selector, such as ".hyphenate, aside"") // .option("-e, --encoding [type]", "Set the encoding of the input html, defaults to "utf-8"") .option("-t, --timeout [ms]", "Set a max timeout of [ms]") .option("-x, --html", "output html file") .option("-b, --blockLocal", "Disallow access to filesystem for local files") .option("-r, --blockRemote", "Disallow requests to remote servers") .option("--allowedPath [allowedPaths]", "Only allow access to given filesystem paths, repeatable.", collect, []) .option("--allowedDomain [allowedDomains]", "Only allow access to given remote domains, repeatable", collect, []) .option("--outline-tags [tags]", "Specifies that an outline should be " + "generated for the resulting PDF document. [tags] specifies which " + "HTML tags should be considered for that outline. " + "\"h1,h2\" will trigger an outline with \"h1\" tags as root elements " + "and \"h2\" elements as their childs.") .option("--additional-script <script>", "Additional script tags which are " + "added to the HTML document before rendering. This is useful for " + "adding custom pagedjs handlers. The option can be repeated.", collect, []) .option("--browserEndpoint", "Use a remote Chrome server with browserWSEndpoint") .parse(process.argv); function collect(value, previous) { return previous.concat(value); } let input = program.inputs || program.args[0]; let dir = process.cwd(); let relativePath; let allowLocal; try { let uri = new URL(input); allowLocal = false; } catch (error) { relativePath = path.resolve(dir, input); allowLocal = !program.blockLocal; } let output; let headless = typeof program.debug === "undefined"; // var hyphenator; // var hyphenateOptions; if (!input) { console.error("You must include an input path"); return process.exit(1); } if (relativePath) { if ([".html", ".xhtml"].indexOf(path.extname(relativePath)) === -1) { console.error("Must pass a html or xhtml file as input"); return process.exit(1); } try { fs.accessSync(relativePath, fs.F_OK); } catch (e) { console.error("Input cannot be found", e); return process.exit(1); } } if (typeof(program.output) === "string") { output = path.resolve(dir, program.output); } else if (typeof(program.output) !== "undefined") { output = "./" + replaceExt(path.basename(input), ".pdf"); } else { output = "output.pdf"; } const spinner = ora({ spinner: "circleQuarters" }); if (typeof input === "string") { spinner.start("Loading: " + input); } else { spinner.start("Loading"); } (async () => { const printerOptions = { headless: headless, allowLocal: allowLocal, allowRemote: !program.blockRemote, allowedPaths: program.allowedPaths, allowedDomains: program.allowedDomains, additionalScripts: program.additionalScript, }; if (program.forceTransparentBackground) { printerOptions.overrideDefaultBackgroundColor = { r: 0, g: 0, b: 0, a: 0 }; // Workaround to get a transparent background in the resulting PDF. See https://bugs.chromium.org/p/chromium/issues/detail?id=498892 for more information. } let printer = new Printer(printerOptions); printer.on("page", (page) => { if (page.position === 0) { spinner.succeed("Loaded"); spinner.start("Rendering: Page " + (page.position + 1)); } else { spinner.text = "Rendering: Page " + (page.position + 1); } }); printer.on("rendered", (msg) => { spinner.succeed(msg); spinner.start("Generating"); }); printer.on("postprocessing", (msg) => { spinner.succeed("Generated"); spinner.start("Processing"); }); let file; if (headless) { let options = {}; if (program.html) { file = await printer.html(input, options); output = replaceExt(output, ".html"); } else { options.outlineTags = !program.outlineTags ? [] : program.outlineTags.split(","); file = await printer.pdf(input, options); } } else { printer.preview(input); } spinner.succeed("Processed"); if (file) { fs.writeFile(output, file, (err) => { if (err) throw err; spinner.succeed("Saved to " + output); process.exit(0); }); } })();