paged 5.87 KB
Newer Older
Fred Chasen's avatar
Fred Chasen committed
1
#!/usr/bin/env node
Fred Chasen's avatar
Fred Chasen committed
2
3
const program = require("commander");
const ora = require("ora");
4
const Printer = require("../index.js");
Fred Chasen's avatar
Fred Chasen committed
5
6
7
8
9
const path = require("path");
const fs = require("fs");
// const { promisify } = require("util");
// const writeFileAsync = promisify(fs.writeFile);
const replaceExt = require("replace-ext");
Fred Chasen's avatar
Fred Chasen committed
10

Fred Chasen's avatar
Fred Chasen committed
11
12
13
14
function commaSeparatedList(value) {
  return value.split(',');
}

Fred Chasen's avatar
Fred Chasen committed
15
program
Fred Chasen's avatar
Fred Chasen committed
16
17
18
19
20
21
22
23
24
  .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")
25
  .option("--forceTransparentBackground", "Print with transparent background")
Fred Chasen's avatar
Fred Chasen committed
26
27
28
29
30
31
32
33
  // .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")
Fred Chasen's avatar
Fred Chasen committed
34
35
36
  .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, [])
Fred Chasen's avatar
Fred Chasen committed
37
38
39
40
41
  .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.")
42
43
44
45
  .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, [])
46
  .option("--browserEndpoint <browserEndpoint>", "Use a remote Chrome server with browserWSEndpoint")
Fred Chasen's avatar
Fred Chasen committed
47
  .option("--browserArgs <browserArgs>", "Launch Chrome with comma separated args", commaSeparatedList)
Fred Chasen's avatar
Fred Chasen committed
48
49
  .parse(process.argv);

50
51
52
53
function collect(value, previous) {
  return previous.concat(value);
}

54
55
56
const options = program.opts();

let input = options.inputs || program.args[0];
Fred Chasen's avatar
Fred Chasen committed
57
58

let dir = process.cwd();
59
60
61
62

let relativePath;
let allowLocal;
try {
Fred Chasen's avatar
Fred Chasen committed
63
  let uri = new URL(input);
64
  allowLocal = false;
Fred Chasen's avatar
Fred Chasen committed
65
} catch (error) {
66
  relativePath = path.resolve(dir, input);
67
  allowLocal = !options.blockLocal;
68
69
}

Fred Chasen's avatar
Fred Chasen committed
70
71
let output;

72
let headless = typeof options.debug === "undefined";
Fred Chasen's avatar
Fred Chasen committed
73

Fred Chasen's avatar
Fred Chasen committed
74
75
76
77
78
79
80
81
// var hyphenator;
// var hyphenateOptions;

if (!input) {
  console.error("You must include an input path");
  return process.exit(1);
}

82
if (relativePath) {
Fred Chasen's avatar
Fred Chasen committed
83

Fred Chasen's avatar
Fred Chasen committed
84
  if ([".html", ".xhtml"].indexOf(path.extname(relativePath)) === -1) {
85
    console.error("Must pass a html or xhtml file as input");
Fred Chasen's avatar
Fred Chasen committed
86
    return process.exit(1);
87
88
89
90
91
92
93
94
  }

  try {
      fs.accessSync(relativePath, fs.F_OK);
  } catch (e) {
      console.error("Input cannot be found", e);
      return process.exit(1);
  }
Fred Chasen's avatar
Fred Chasen committed
95
96
}

97
98
99
if (typeof(options.output) === "string") {
  output = path.resolve(dir, options.output);
} else if (typeof(options.output) !== "undefined") {
Fred Chasen's avatar
Fred Chasen committed
100
  output = "./" + replaceExt(path.basename(input), ".pdf");
Fred Chasen's avatar
Fred Chasen committed
101
102
103
104
105
} else {
  output = "output.pdf";
}


106
107
const spinner = ora({
  spinner: "circleQuarters"
Fred Chasen's avatar
Fred Chasen committed
108
});
Fred Chasen's avatar
Fred Chasen committed
109
110


111
112
113
114
115
if (typeof input === "string") {
  spinner.start("Loading: " + input);
} else {
  spinner.start("Loading");
}
Fred Chasen's avatar
Fred Chasen committed
116

117
(async () => {
118
  const printerOptions = {
Fred Chasen's avatar
Fred Chasen committed
119
120
    headless: headless,
    allowLocal: allowLocal,
121
122
123
124
125
126
127
    allowRemote: !options.blockRemote,
    allowedPaths: options.allowedPaths,
    allowedDomains: options.allowedDomains,
    additionalScripts: options.additionalScript,
    browserEndpoint: options.browserEndpoint,
    timeout: options.timeout,
    browserArgs: options.browserArgs
128
129
  };

130
  if (options.forceTransparentBackground) {
131
132
133
134
    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);
Fred Chasen's avatar
Fred Chasen committed
135

136
137
138
  printer.on("page", (page) => {
    if (page.position === 0) {
      spinner.succeed("Loaded");
Fred Chasen's avatar
Fred Chasen committed
139

140
141
      spinner.start("Rendering: Page " + (page.position + 1));
    } else {
Fred Chasen's avatar
Fred Chasen committed
142
      spinner.text = "Rendering: Page " + (page.position + 1);
143
144
    }
  });
Fred Chasen's avatar
Fred Chasen committed
145

146
147
148
149
150
151
152
153
154
  printer.on("rendered", (msg) => {
    spinner.succeed(msg);
    spinner.start("Generating");
  });

  printer.on("postprocessing", (msg) => {
    spinner.succeed("Generated");
    spinner.start("Processing");
  });
Fred Chasen's avatar
Fred Chasen committed
155
156
157
158

  let file;
  if (headless) {
    let options = {};
159
160
161
162
163
164
    if (options.html) {
      file = await printer.html(input, options)
        .catch((e) => {
          console.error(e);
          process.exit(1);
        });
Fred Chasen's avatar
Fred Chasen committed
165
      output = replaceExt(output, ".html");
Fred Chasen's avatar
Fred Chasen committed
166
    } else {
167
168
169
170
171
172
      options.outlineTags = !options.outlineTags ? [] : options.outlineTags.split(",");
      file = await printer.pdf(input, options)
        .catch((e) => {
          console.error(e);
          process.exit(1);
        });
Fred Chasen's avatar
Fred Chasen committed
173
174
175
176
    }
  } else {
    printer.preview(input);
  }
Fred Chasen's avatar
Fred Chasen committed
177

178
179
  spinner.succeed("Processed");

Fred Chasen's avatar
Fred Chasen committed
180
181
182
  if (file) {
    fs.writeFile(output, file, (err) => {
      if (err) throw err;
183
      spinner.succeed("Saved to " + output);
Fred Chasen's avatar
Fred Chasen committed
184
185
186
      process.exit(0);
    });
  }
Fred Chasen's avatar
Fred Chasen committed
187
})();