node-poppler 8.0.2 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +569 -551
package/src/index.js CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  const { execFile, spawn, spawnSync } = require("node:child_process");
4
4
  const { normalize, resolve: pathResolve } = require("node:path");
5
+ const { platform } = require("node:process");
5
6
  const { promisify } = require("node:util");
6
7
  const camelCase = require("camelcase");
7
8
  const { lt } = require("semver");
8
9
 
9
10
  const execFileAsync = promisify(execFile);
10
11
 
11
- const errorMessages = {
12
+ const ERROR_MSGS = {
12
13
  0: "No Error",
13
14
  1: "Error opening a PDF file",
14
15
  2: "Error opening an output file",
@@ -19,8 +20,9 @@ const errorMessages = {
19
20
  };
20
21
 
21
22
  // Cache immutable regex as they are expensive to create and garbage collect
22
- const popplerVersionRegex = /(\d{1,2}\.\d{1,2}\.\d{1,2})/u;
23
- const pdfInfoFileSizesRegex = /(File\s+size:\s+)0(\s+)bytes/u;
23
+ const POPPLER_VERSION_REG = /(\d{1,2}\.\d{1,2}\.\d{1,2})/u;
24
+ const PDF_INFO_FILE_SIZES_REG = /(File\s+size:\s+)0(\s+)bytes/u;
25
+ const PDF_INFO_PATH_REG = /(.+)pdfinfo/u;
24
26
 
25
27
  /**
26
28
  * @typedef {object} OptionDetails
@@ -104,6 +106,22 @@ function parseOptions(acceptedOptions, options, version) {
104
106
  class Poppler {
105
107
  #popplerPath;
106
108
 
109
+ #pdfAttachBin;
110
+ #pdfDetachBin;
111
+ #pdfFontsBin;
112
+ #pdfImagesBin;
113
+ #pdfInfoBin;
114
+ #pdfSeparateBin;
115
+ #pdfToCairoBin;
116
+ #pdfToHtmlBin;
117
+ #pdfToPpmBin;
118
+ #pdfToPsBin;
119
+ #pdfToTextBin;
120
+ #pdfUniteBin;
121
+
122
+ #binVersions = new Map();
123
+ #acceptedOptions = new Map();
124
+
107
125
  /**
108
126
  * @param {string} [binPath] - Path of poppler-utils binaries.
109
127
  * If not provided, the constructor will attempt to find the Poppler `pdfinfo` binary
@@ -119,12 +137,10 @@ class Poppler {
119
137
  /** @type {string|undefined} */
120
138
  this.#popplerPath = binPath;
121
139
  } else {
122
- const { platform } = process;
123
-
124
140
  const which = spawnSync(platform === "win32" ? "where" : "which", [
125
141
  "pdfinfo",
126
142
  ]).stdout.toString();
127
- const popplerPath = /(.+)pdfinfo/u.exec(which)?.[1];
143
+ const popplerPath = PDF_INFO_PATH_REG.exec(which)?.[1];
128
144
 
129
145
  if (popplerPath) {
130
146
  this.#popplerPath = popplerPath;
@@ -144,10 +160,23 @@ class Poppler {
144
160
  /* istanbul ignore next: unable to test due to https://github.com/jestjs/jest/pull/14297 */
145
161
  if (!this.#popplerPath) {
146
162
  throw new Error(
147
- `Unable to find ${process.platform} Poppler binaries, please pass the installation directory as a parameter to the Poppler instance.`
163
+ `Unable to find ${platform} Poppler binaries, please pass the installation directory as a parameter to the Poppler instance.`
148
164
  );
149
165
  }
150
166
  this.#popplerPath = normalize(this.#popplerPath);
167
+
168
+ this.#pdfAttachBin = pathResolve(this.#popplerPath, "pdfattach");
169
+ this.#pdfDetachBin = pathResolve(this.#popplerPath, "pdfdetach");
170
+ this.#pdfFontsBin = pathResolve(this.#popplerPath, "pdffonts");
171
+ this.#pdfImagesBin = pathResolve(this.#popplerPath, "pdfimages");
172
+ this.#pdfInfoBin = pathResolve(this.#popplerPath, "pdfinfo");
173
+ this.#pdfSeparateBin = pathResolve(this.#popplerPath, "pdfseparate");
174
+ this.#pdfToCairoBin = pathResolve(this.#popplerPath, "pdftocairo");
175
+ this.#pdfToHtmlBin = pathResolve(this.#popplerPath, "pdftohtml");
176
+ this.#pdfToPpmBin = pathResolve(this.#popplerPath, "pdftoppm");
177
+ this.#pdfToPsBin = pathResolve(this.#popplerPath, "pdftops");
178
+ this.#pdfToTextBin = pathResolve(this.#popplerPath, "pdftotext");
179
+ this.#pdfUniteBin = pathResolve(this.#popplerPath, "pdfunite");
151
180
  }
152
181
 
153
182
  /**
@@ -158,6 +187,445 @@ class Poppler {
158
187
  return this.#popplerPath;
159
188
  }
160
189
 
190
+ /**
191
+ * @author Frazer Smith
192
+ * @description Returns the version of the specified Poppler binary.
193
+ * @param {string} binary - The Poppler binary to get the version of.
194
+ * @returns {Promise<string>} A promise that resolves with the version of the binary, or rejects with an `Error` object.
195
+ */
196
+ async #getVersion(binary) {
197
+ if (!this.#binVersions.has(binary)) {
198
+ const { stderr } = await execFileAsync(binary, ["-v"]);
199
+ // @ts-ignore: parseOptions checks if falsy
200
+ const version = POPPLER_VERSION_REG.exec(stderr)[1];
201
+ this.#binVersions.set(binary, version);
202
+ }
203
+ return this.#binVersions.get(binary);
204
+ }
205
+
206
+ /**
207
+ * @author Frazer Smith
208
+ * @description Returns the accepted options for the specified Poppler binary function.
209
+ * @param {string} functionName - The name of the Poppler binary function.
210
+ * @returns {PopplerAcceptedOptions} An object containing the accepted options of the specified function.
211
+ */
212
+ #getAcceptedOptions(functionName) {
213
+ if (!this.#acceptedOptions.has(functionName)) {
214
+ switch (functionName) {
215
+ case "pdfAttach":
216
+ this.#acceptedOptions.set("pdfAttach", {
217
+ printVersionInfo: { arg: "-v", type: "boolean" },
218
+ replace: { arg: "-replace", type: "boolean" },
219
+ });
220
+ break;
221
+ case "pdfDetach":
222
+ this.#acceptedOptions.set("pdfDetach", {
223
+ listEmbedded: { arg: "-list", type: "boolean" },
224
+ outputEncoding: { arg: "-enc", type: "string" },
225
+ outputPath: { arg: "-o", type: "string" },
226
+ ownerPassword: { arg: "-opw", type: "string" },
227
+ printVersionInfo: { arg: "-v", type: "boolean" },
228
+ saveAllFiles: { arg: "-saveall", type: "boolean" },
229
+ saveFile: {
230
+ arg: "-savefile",
231
+ type: "string",
232
+ minVersion: "0.86.0",
233
+ },
234
+ saveSpecificFile: { arg: "-save", type: "number" },
235
+ userPassword: { arg: "-upw", type: "string" },
236
+ });
237
+ break;
238
+ case "pdfFonts":
239
+ this.#acceptedOptions.set("pdfFonts", {
240
+ firstPageToExamine: { arg: "-f", type: "number" },
241
+ lastPageToExamine: { arg: "-l", type: "number" },
242
+ listSubstitutes: { arg: "-subst", type: "boolean" },
243
+ ownerPassword: { arg: "-opw", type: "string" },
244
+ printVersionInfo: { arg: "-v", type: "boolean" },
245
+ userPassword: { arg: "-upw", type: "string" },
246
+ });
247
+ break;
248
+ case "pdfImages":
249
+ this.#acceptedOptions.set("pdfImages", {
250
+ allFiles: { arg: "-all", type: "boolean" },
251
+ ccittFile: { arg: "-ccitt", type: "boolean" },
252
+ firstPageToConvert: { arg: "-f", type: "number" },
253
+ lastPageToConvert: { arg: "-l", type: "number" },
254
+ jbig2File: { arg: "-jbig2", type: "boolean" },
255
+ jpeg2000File: { arg: "-jp2", type: "boolean" },
256
+ jpegFile: { arg: "-j", type: "boolean" },
257
+ list: { arg: "-list", type: "boolean" },
258
+ ownerPassword: { arg: "-opw", type: "string" },
259
+ pngFile: { arg: "-png", type: "boolean" },
260
+ printVersionInfo: { arg: "-v", type: "boolean" },
261
+ tiffFile: { arg: "-tiff", type: "boolean" },
262
+ userPassword: { arg: "-upw", type: "string" },
263
+ });
264
+ break;
265
+ case "pdfInfo":
266
+ this.#acceptedOptions.set("pdfInfo", {
267
+ firstPageToConvert: { arg: "-f", type: "number" },
268
+ lastPageToConvert: { arg: "-l", type: "number" },
269
+ listEncodingOptions: {
270
+ arg: "-listenc",
271
+ type: "boolean",
272
+ },
273
+ outputEncoding: { arg: "-enc", type: "string" },
274
+ ownerPassword: { arg: "-opw", type: "string" },
275
+ printAsJson: { arg: "", type: "boolean" },
276
+ printBoundingBoxes: { arg: "-box", type: "boolean" },
277
+ printDocStruct: { arg: "-struct", type: "boolean" },
278
+ printDocStructText: {
279
+ arg: "-struct-text",
280
+ type: "boolean",
281
+ },
282
+ printIsoDates: { arg: "-isodates", type: "boolean" },
283
+ printJS: { arg: "-js", type: "boolean" },
284
+ printMetadata: { arg: "-meta", type: "boolean" },
285
+ printNamedDests: { arg: "-dests", type: "boolean" },
286
+ printRawDates: { arg: "-rawdates", type: "boolean" },
287
+ printUrls: {
288
+ arg: "-url",
289
+ type: "boolean",
290
+ minVersion: "21.11.0",
291
+ },
292
+ printVersionInfo: { arg: "-v", type: "boolean" },
293
+ userPassword: { arg: "-upw", type: "string" },
294
+ });
295
+ break;
296
+ case "pdfSeparate":
297
+ this.#acceptedOptions.set("pdfSeparate", {
298
+ firstPageToExtract: { arg: "-f", type: "number" },
299
+ lastPageToExtract: { arg: "-l", type: "number" },
300
+ printVersionInfo: { arg: "-v", type: "boolean" },
301
+ });
302
+ break;
303
+ case "pdfToCairo":
304
+ this.#acceptedOptions.set("pdfToCairo", {
305
+ antialias: { arg: "-antialias", type: "string" },
306
+ cropBox: { arg: "-cropbox", type: "boolean" },
307
+ cropHeight: { arg: "-H", type: "number" },
308
+ cropSize: { arg: "-sz", type: "number" },
309
+ cropWidth: { arg: "-W", type: "number" },
310
+ cropXAxis: { arg: "-x", type: "number" },
311
+ cropYAxis: { arg: "-y", type: "number" },
312
+ duplex: { arg: "-duplex", type: "boolean" },
313
+ epsFile: { arg: "-eps", type: "boolean" },
314
+ evenPagesOnly: { arg: "-e", type: "boolean" },
315
+ fillPage: { arg: "-expand", type: "boolean" },
316
+ firstPageToConvert: { arg: "-f", type: "number" },
317
+ grayscaleFile: { arg: "-gray", type: "boolean" },
318
+ iccFile: { arg: "-icc", type: "string" },
319
+ jpegFile: { arg: "-jpeg", type: "boolean" },
320
+ jpegOptions: { arg: "-jpegopt", type: "string" },
321
+ lastPageToConvert: { arg: "-l", type: "number" },
322
+ monochromeFile: { arg: "-mono", type: "boolean" },
323
+ noCenter: { arg: "-nocenter", type: "boolean" },
324
+ noCrop: { arg: "-nocrop", type: "boolean" },
325
+ noShrink: { arg: "-noshrink", type: "boolean" },
326
+ oddPagesOnly: { arg: "-o", type: "boolean" },
327
+ originalPageSizes: {
328
+ arg: "-origpagesizes",
329
+ type: "boolean",
330
+ },
331
+ ownerPassword: { arg: "-opw", type: "string" },
332
+ paperHeight: { arg: "-paperh", type: "number" },
333
+ paperSize: { arg: "-paper", type: "string" },
334
+ paperWidth: { arg: "-paperw", type: "number" },
335
+ pdfFile: { arg: "-pdf", type: "boolean" },
336
+ pngFile: { arg: "-png", type: "boolean" },
337
+ printDocStruct: {
338
+ arg: "-struct",
339
+ type: "boolean",
340
+ minVersion: "23.11.0",
341
+ },
342
+ printVersionInfo: { arg: "-v", type: "boolean" },
343
+ psFile: { arg: "-ps", type: "boolean" },
344
+ psLevel2: { arg: "-level2", type: "boolean" },
345
+ psLevel3: { arg: "-level3", type: "boolean" },
346
+ quiet: { arg: "-q", type: "boolean" },
347
+ resolutionXAxis: { arg: "-rx", type: "number" },
348
+ resolutionXYAxis: { arg: "-r", type: "number" },
349
+ resolutionYAxis: { arg: "-ry", type: "number" },
350
+ scalePageTo: { arg: "-scale-to", type: "number" },
351
+ scalePageToXAxis: {
352
+ arg: "-scale-to-x",
353
+ type: "number",
354
+ },
355
+ scalePageToYAxis: {
356
+ arg: "-scale-to-y",
357
+ type: "number",
358
+ },
359
+ singleFile: { arg: "-singlefile", type: "boolean" },
360
+ svgFile: { arg: "-svg", type: "boolean" },
361
+ tiffCompression: {
362
+ arg: "-tiffcompression",
363
+ type: "string",
364
+ },
365
+ tiffFile: { arg: "-tiff", type: "boolean" },
366
+ transparentPageColor: {
367
+ arg: "-transp",
368
+ type: "boolean",
369
+ },
370
+ userPassword: { arg: "-upw", type: "string" },
371
+ });
372
+ break;
373
+ case "pdfToHtml":
374
+ this.#acceptedOptions.set("pdfToHtml", {
375
+ complexOutput: { arg: "-c", type: "boolean" },
376
+ dataUrls: {
377
+ arg: "-dataurls",
378
+ type: "boolean",
379
+ minVersion: "0.75.0",
380
+ },
381
+ exchangePdfLinks: { arg: "-p", type: "boolean" },
382
+ extractHidden: { arg: "-hidden", type: "boolean" },
383
+ firstPageToConvert: { arg: "-f", type: "number" },
384
+ fontFullName: { arg: "-fontfullname", type: "boolean" },
385
+ ignoreImages: { arg: "-i", type: "boolean" },
386
+ imageFormat: { arg: "-fmt", type: "string" },
387
+ lastPageToConvert: { arg: "-l", type: "number" },
388
+ noDrm: { arg: "-nodrm", type: "boolean" },
389
+ noFrames: { arg: "-noframes", type: "boolean" },
390
+ noMergeParagraph: { arg: "-nomerge", type: "boolean" },
391
+ noRoundedCoordinates: {
392
+ arg: "-noroundcoord",
393
+ type: "boolean",
394
+ },
395
+ outputEncoding: { arg: "-enc", type: "string" },
396
+ ownerPassword: { arg: "-opw", type: "string" },
397
+ printVersionInfo: { arg: "-v", type: "boolean" },
398
+ quiet: { arg: "-q", type: "boolean" },
399
+ singlePage: { arg: "-s", type: "boolean" },
400
+ stdout: { arg: "-stdout", type: "boolean" },
401
+ userPassword: { arg: "-upw", type: "string" },
402
+ wordBreakThreshold: { arg: "-wbt", type: "number" },
403
+ xmlOutput: { arg: "-xml", type: "boolean" },
404
+ zoom: { arg: "-zoom", type: "number" },
405
+ });
406
+ break;
407
+ case "pdfToPpm":
408
+ this.#acceptedOptions.set("pdfToPpm", {
409
+ antialiasFonts: { arg: "-aa", type: "string" },
410
+ antialiasVectors: { arg: "-aaVector", type: "string" },
411
+ cropBox: { arg: "-cropbox", type: "boolean" },
412
+ cropHeight: { arg: "-H", type: "number" },
413
+ cropSize: { arg: "-sz", type: "number" },
414
+ cropWidth: { arg: "-W", type: "number" },
415
+ cropXAxis: { arg: "-x", type: "number" },
416
+ cropYAxis: { arg: "-y", type: "number" },
417
+ defaultCmykProfile: {
418
+ arg: "-defaultcmykprofile",
419
+ type: "string",
420
+ minVersion: "21.01.0",
421
+ },
422
+ defaultGrayProfile: {
423
+ arg: "-defaultgrayprofile",
424
+ type: "string",
425
+ minVersion: "21.01.0",
426
+ },
427
+ defaultRgbProfile: {
428
+ arg: "-defaultrgbprofile",
429
+ type: "string",
430
+ minVersion: "21.01.0",
431
+ },
432
+ displayProfile: {
433
+ arg: "-displayprofile",
434
+ type: "string",
435
+ minVersion: "0.90.0",
436
+ },
437
+ evenPagesOnly: { arg: "-e", type: "boolean" },
438
+ firstPageToConvert: { arg: "-f", type: "number" },
439
+ forcePageNumber: {
440
+ arg: "-forcenum",
441
+ type: "boolean",
442
+ minVersion: "0.75.0",
443
+ },
444
+ freetype: { arg: "-freetype", type: "string" },
445
+ grayscaleFile: { arg: "-gray", type: "boolean" },
446
+ hideAnnotations: {
447
+ arg: "-hide-annotations",
448
+ type: "boolean",
449
+ minVersion: "0.84.0",
450
+ },
451
+ jpegFile: { arg: "-jpeg", type: "boolean" },
452
+ lastPageToConvert: { arg: "-l", type: "number" },
453
+ monochromeFile: { arg: "-mono", type: "boolean" },
454
+ oddPagesOnly: { arg: "-o", type: "boolean" },
455
+ ownerPassword: { arg: "-opw", type: "string" },
456
+ pngFile: { arg: "-png", type: "boolean" },
457
+ printProgress: {
458
+ arg: "-progress",
459
+ type: "boolean",
460
+ minVersion: "21.03.0",
461
+ },
462
+ printVersionInfo: { arg: "-v", type: "boolean" },
463
+ quiet: { arg: "-q", type: "boolean" },
464
+ resolutionXAxis: { arg: "-rx", type: "number" },
465
+ resolutionXYAxis: { arg: "-r", type: "number" },
466
+ resolutionYAxis: { arg: "-ry", type: "number" },
467
+ scalePageTo: { arg: "-scale-to", type: "number" },
468
+ scalePageToXAxis: {
469
+ arg: "-scale-to-x",
470
+ type: "number",
471
+ },
472
+ scalePageToYAxis: {
473
+ arg: "-scale-to-y",
474
+ type: "number",
475
+ },
476
+ separator: {
477
+ arg: "-sep",
478
+ type: "string",
479
+ minVersion: "0.75.0",
480
+ },
481
+ singleFile: { arg: "-singlefile", type: "boolean" },
482
+ thinLineMode: { arg: "-thinlinemode", type: "string" },
483
+ tiffCompression: {
484
+ arg: "-tiffcompression",
485
+ type: "string",
486
+ },
487
+ tiffFile: { arg: "-tiff", type: "boolean" },
488
+ userPassword: { arg: "-upw", type: "string" },
489
+ });
490
+ break;
491
+ case "pdfToPs":
492
+ this.#acceptedOptions.set("pdfToPs", {
493
+ antialias: { arg: "-aaRaster", type: "string" },
494
+ binary: { arg: "-binary", type: "boolean" },
495
+ defaultCmykProfile: {
496
+ arg: "-defaultcmykprofile",
497
+ type: "string",
498
+ minVersion: "21.01.0",
499
+ },
500
+ defaultGrayProfile: {
501
+ arg: "-defaultgrayprofile",
502
+ type: "string",
503
+ minVersion: "21.01.0",
504
+ },
505
+ defaultRgbProfile: {
506
+ arg: "-defaultrgbprofile",
507
+ type: "string",
508
+ minVersion: "21.01.0",
509
+ },
510
+ duplex: { arg: "-duplex", type: "boolean" },
511
+ epsFile: { arg: "-eps", type: "boolean" },
512
+ fillPage: { arg: "-expand", type: "boolean" },
513
+ firstPageToConvert: { arg: "-f", type: "number" },
514
+ form: { arg: "-form", type: "boolean" },
515
+ lastPageToConvert: { arg: "-l", type: "number" },
516
+ level1: { arg: "-level1", type: "boolean" },
517
+ level1Sep: { arg: "-level1sep", type: "boolean" },
518
+ level2: { arg: "-level2", type: "boolean" },
519
+ level2Sep: { arg: "-level2sep", type: "boolean" },
520
+ level3: { arg: "-level3", type: "boolean" },
521
+ level3Sep: { arg: "-level3sep", type: "boolean" },
522
+ noCenter: { arg: "-nocenter", type: "boolean" },
523
+ noCrop: { arg: "-nocrop", type: "boolean" },
524
+ noEmbedCIDFonts: {
525
+ arg: "-noembcidps",
526
+ type: "boolean",
527
+ },
528
+ noEmbedCIDTrueTypeFonts: {
529
+ arg: "-noembcidtt",
530
+ type: "boolean",
531
+ },
532
+ noEmbedTrueTypeFonts: {
533
+ arg: "-noembtt",
534
+ type: "boolean",
535
+ },
536
+ noEmbedType1Fonts: { arg: "-noembt1", type: "boolean" },
537
+ noShrink: { arg: "-noshrink", type: "boolean" },
538
+ opi: { arg: "-opi", type: "boolean" },
539
+ optimizecolorspace: {
540
+ arg: "-optimizecolorspace",
541
+ type: "boolean",
542
+ },
543
+ originalPageSizes: {
544
+ arg: "-origpagesizes",
545
+ type: "boolean",
546
+ },
547
+ overprint: { arg: "-overprint", type: "boolean" },
548
+ ownerPassword: { arg: "-opw", type: "string" },
549
+ paperHeight: { arg: "-paperh", type: "number" },
550
+ paperSize: { arg: "-paper", type: "string" },
551
+ paperWidth: { arg: "-paperw", type: "number" },
552
+ passfonts: { arg: "-passfonts", type: "boolean" },
553
+ preload: { arg: "-preload", type: "boolean" },
554
+ printVersionInfo: { arg: "-v", type: "boolean" },
555
+ processColorFormat: {
556
+ arg: "-processcolorformat",
557
+ type: "string",
558
+ },
559
+ processColorProfile: {
560
+ arg: "-processcolorprofile",
561
+ type: "string",
562
+ },
563
+ quiet: { arg: "-q", type: "boolean" },
564
+ rasterize: {
565
+ arg: "-rasterize",
566
+ type: "string",
567
+ minVersion: "0.90.0",
568
+ },
569
+ resolutionXYAxis: { arg: "-r", type: "number" },
570
+ userPassword: { arg: "-upw", type: "string" },
571
+ });
572
+ break;
573
+ case "pdfToText":
574
+ this.#acceptedOptions.set("pdfToText", {
575
+ boundingBoxXhtml: { arg: "-bbox", type: "boolean" },
576
+ boundingBoxXhtmlLayout: {
577
+ arg: "-bbox-layout",
578
+ type: "boolean",
579
+ },
580
+ cropBox: {
581
+ arg: "-cropbox",
582
+ type: "boolean",
583
+ minVersion: "21.03.0",
584
+ },
585
+ cropHeight: { arg: "-H", type: "number" },
586
+ cropWidth: { arg: "-W", type: "number" },
587
+ cropXAxis: { arg: "-x", type: "number" },
588
+ cropYAxis: { arg: "-y", type: "number" },
589
+ eolConvention: { arg: "-eol", type: "string" },
590
+ firstPageToConvert: { arg: "-f", type: "number" },
591
+ fixedWidthLayout: { arg: "-fixed", type: "number" },
592
+ generateHtmlMetaFile: {
593
+ arg: "-htmlmeta",
594
+ type: "boolean",
595
+ },
596
+ generateTsvFile: { arg: "-tsv", type: "boolean" },
597
+ lastPageToConvert: { arg: "-l", type: "number" },
598
+ listEncodingOptions: {
599
+ arg: "-listenc",
600
+ type: "boolean",
601
+ },
602
+ maintainLayout: { arg: "-layout", type: "boolean" },
603
+ noDiagonalText: {
604
+ arg: "-nodiag",
605
+ type: "boolean",
606
+ minVersion: "0.80.0",
607
+ },
608
+ noPageBreaks: { arg: "-nopgbrk", type: "boolean" },
609
+ outputEncoding: { arg: "-enc", type: "string" },
610
+ ownerPassword: { arg: "-opw", type: "string" },
611
+ printVersionInfo: { arg: "-v", type: "boolean" },
612
+ quiet: { arg: "-q", type: "boolean" },
613
+ rawLayout: { arg: "-raw", type: "boolean" },
614
+ resolution: { arg: "-r", type: "number" },
615
+ userPassword: { arg: "-upw", type: "string" },
616
+ });
617
+ break;
618
+ case "pdfUnite":
619
+ this.#acceptedOptions.set("pdfUnite", {
620
+ printVersionInfo: { arg: "-v", type: "boolean" },
621
+ });
622
+ break;
623
+ }
624
+ }
625
+
626
+ return this.#acceptedOptions.get(functionName);
627
+ }
628
+
161
629
  /**
162
630
  * @author Frazer Smith
163
631
  * @description Embeds files (attachments) into a PDF file.
@@ -170,19 +638,11 @@ class Poppler {
170
638
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
171
639
  */
172
640
  async pdfAttach(file, fileToAttach, outputFile, options = {}) {
173
- /** @type {PopplerAcceptedOptions} */
174
- const acceptedOptions = {
175
- printVersionInfo: { arg: "-v", type: "boolean" },
176
- replace: { arg: "-replace", type: "boolean" },
177
- };
178
-
641
+ const acceptedOptions = this.#getAcceptedOptions("pdfAttach");
179
642
  const args = parseOptions(acceptedOptions, options);
180
643
  args.push(file, fileToAttach, outputFile);
181
644
 
182
- const { stdout } = await execFileAsync(
183
- pathResolve(this.#popplerPath, "pdfattach"),
184
- args
185
- );
645
+ const { stdout } = await execFileAsync(this.#pdfAttachBin, args);
186
646
  return stdout;
187
647
  }
188
648
 
@@ -213,30 +673,11 @@ class Poppler {
213
673
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
214
674
  */
215
675
  async pdfDetach(file, options = {}) {
216
- /** @type {PopplerAcceptedOptions} */
217
- const acceptedOptions = {
218
- listEmbedded: { arg: "-list", type: "boolean" },
219
- outputEncoding: { arg: "-enc", type: "string" },
220
- outputPath: { arg: "-o", type: "string" },
221
- ownerPassword: { arg: "-opw", type: "string" },
222
- printVersionInfo: { arg: "-v", type: "boolean" },
223
- saveAllFiles: { arg: "-saveall", type: "boolean" },
224
- saveFile: {
225
- arg: "-savefile",
226
- type: "string",
227
- minVersion: "0.86.0",
228
- },
229
- saveSpecificFile: { arg: "-save", type: "number" },
230
- userPassword: { arg: "-upw", type: "string" },
231
- };
232
-
676
+ const acceptedOptions = this.#getAcceptedOptions("pdfDetach");
233
677
  const args = parseOptions(acceptedOptions, options);
234
678
  args.push(file);
235
679
 
236
- const { stdout } = await execFileAsync(
237
- pathResolve(this.#popplerPath, "pdfdetach"),
238
- args
239
- );
680
+ const { stdout } = await execFileAsync(this.#pdfDetachBin, args);
240
681
  return stdout;
241
682
  }
242
683
 
@@ -255,33 +696,14 @@ class Poppler {
255
696
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
256
697
  */
257
698
  async pdfFonts(file, options = {}) {
258
- /** @type {PopplerAcceptedOptions} */
259
- const acceptedOptions = {
260
- firstPageToExamine: { arg: "-f", type: "number" },
261
- lastPageToExamine: { arg: "-l", type: "number" },
262
- listSubstitutes: { arg: "-subst", type: "boolean" },
263
- ownerPassword: { arg: "-opw", type: "string" },
264
- printVersionInfo: { arg: "-v", type: "boolean" },
265
- userPassword: { arg: "-upw", type: "string" },
266
- };
267
-
268
- const { stderr } = await execFileAsync(
269
- pathResolve(this.#popplerPath, "pdffonts"),
270
- ["-v"]
271
- );
272
-
273
- // @ts-ignore: parseOptions checks if falsy
274
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
275
-
699
+ const acceptedOptions = this.#getAcceptedOptions("pdfFonts");
700
+ const versionInfo = await this.#getVersion(this.#pdfFontsBin);
276
701
  const args = parseOptions(acceptedOptions, options, versionInfo);
277
702
 
278
703
  return new Promise((resolve, reject) => {
279
704
  args.push(Buffer.isBuffer(file) ? "-" : file);
280
705
 
281
- const child = spawn(
282
- pathResolve(this.#popplerPath, "pdffonts"),
283
- args
284
- );
706
+ const child = spawn(this.#pdfFontsBin, args);
285
707
 
286
708
  if (Buffer.isBuffer(file)) {
287
709
  child.stdin.write(file);
@@ -304,14 +726,14 @@ class Poppler {
304
726
  if (stdOut !== "") {
305
727
  resolve(stdOut.trim());
306
728
  } else if (code === 0) {
307
- resolve(errorMessages[code]);
729
+ resolve(ERROR_MSGS[code]);
308
730
  } else if (stdErr !== "") {
309
731
  reject(new Error(stdErr.trim()));
310
732
  } else {
311
733
  reject(
312
734
  new Error(
313
- // @ts-ignore: Second operand used if code is not in errorMessages
314
- errorMessages[code] ||
735
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
736
+ ERROR_MSGS[code] ||
315
737
  `pdffonts ${args.join(
316
738
  " "
317
739
  )} exited with code ${code}`
@@ -347,31 +769,8 @@ class Poppler {
347
769
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
348
770
  */
349
771
  async pdfImages(file, outputPrefix, options = {}) {
350
- /** @type {PopplerAcceptedOptions} */
351
- const acceptedOptions = {
352
- allFiles: { arg: "-all", type: "boolean" },
353
- ccittFile: { arg: "-ccitt", type: "boolean" },
354
- firstPageToConvert: { arg: "-f", type: "number" },
355
- lastPageToConvert: { arg: "-l", type: "number" },
356
- jbig2File: { arg: "-jbig2", type: "boolean" },
357
- jpeg2000File: { arg: "-jp2", type: "boolean" },
358
- jpegFile: { arg: "-j", type: "boolean" },
359
- list: { arg: "-list", type: "boolean" },
360
- ownerPassword: { arg: "-opw", type: "string" },
361
- pngFile: { arg: "-png", type: "boolean" },
362
- printVersionInfo: { arg: "-v", type: "boolean" },
363
- tiffFile: { arg: "-tiff", type: "boolean" },
364
- userPassword: { arg: "-upw", type: "string" },
365
- };
366
-
367
- const { stderr } = await execFileAsync(
368
- pathResolve(this.#popplerPath, "pdfimages"),
369
- ["-v"]
370
- );
371
-
372
- // @ts-ignore: parseOptions checks if falsy
373
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
374
-
772
+ const acceptedOptions = this.#getAcceptedOptions("pdfImages");
773
+ const versionInfo = await this.#getVersion(this.#pdfImagesBin);
375
774
  const args = parseOptions(acceptedOptions, options, versionInfo);
376
775
 
377
776
  return new Promise((resolve, reject) => {
@@ -381,10 +780,7 @@ class Poppler {
381
780
  args.push(outputPrefix);
382
781
  }
383
782
 
384
- const child = spawn(
385
- pathResolve(this.#popplerPath, "pdfimages"),
386
- args
387
- );
783
+ const child = spawn(this.#pdfImagesBin, args);
388
784
 
389
785
  if (Buffer.isBuffer(file)) {
390
786
  child.stdin.write(file);
@@ -407,14 +803,14 @@ class Poppler {
407
803
  if (stdOut !== "") {
408
804
  resolve(stdOut.trim());
409
805
  } else if (code === 0) {
410
- resolve(errorMessages[code]);
806
+ resolve(ERROR_MSGS[code]);
411
807
  } else if (stdErr !== "") {
412
808
  reject(new Error(stdErr.trim()));
413
809
  } else {
414
810
  reject(
415
811
  new Error(
416
- // @ts-ignore: Second operand used if code is not in errorMessages
417
- errorMessages[code] ||
812
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
813
+ ERROR_MSGS[code] ||
418
814
  `pdfimages ${args.join(
419
815
  " "
420
816
  )} exited with code ${code}`
@@ -460,35 +856,8 @@ class Poppler {
460
856
  * `options.printAsJson` is `true`, or rejects with an `Error` object.
461
857
  */
462
858
  async pdfInfo(file, options = {}) {
463
- /** @type {PopplerAcceptedOptions} */
464
- const acceptedOptions = {
465
- firstPageToConvert: { arg: "-f", type: "number" },
466
- lastPageToConvert: { arg: "-l", type: "number" },
467
- listEncodingOptions: { arg: "-listenc", type: "boolean" },
468
- outputEncoding: { arg: "-enc", type: "string" },
469
- ownerPassword: { arg: "-opw", type: "string" },
470
- printAsJson: { arg: "", type: "boolean" },
471
- printBoundingBoxes: { arg: "-box", type: "boolean" },
472
- printDocStruct: { arg: "-struct", type: "boolean" },
473
- printDocStructText: { arg: "-struct-text", type: "boolean" },
474
- printIsoDates: { arg: "-isodates", type: "boolean" },
475
- printJS: { arg: "-js", type: "boolean" },
476
- printMetadata: { arg: "-meta", type: "boolean" },
477
- printNamedDests: { arg: "-dests", type: "boolean" },
478
- printRawDates: { arg: "-rawdates", type: "boolean" },
479
- printUrls: { arg: "-url", type: "boolean", minVersion: "21.11.0" },
480
- printVersionInfo: { arg: "-v", type: "boolean" },
481
- userPassword: { arg: "-upw", type: "string" },
482
- };
483
-
484
- const { stderr } = await execFileAsync(
485
- pathResolve(this.#popplerPath, "pdfinfo"),
486
- ["-v"]
487
- );
488
-
489
- // @ts-ignore: parseOptions checks if falsy
490
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
491
-
859
+ const acceptedOptions = this.#getAcceptedOptions("pdfInfo");
860
+ const versionInfo = await this.#getVersion(this.#pdfInfoBin);
492
861
  const args = parseOptions(acceptedOptions, options, versionInfo);
493
862
 
494
863
  // Fetch file size if stdin input is a Buffer, as Poppler omits it
@@ -503,10 +872,7 @@ class Poppler {
503
872
  args.push(file);
504
873
  }
505
874
 
506
- const child = spawn(
507
- pathResolve(this.#popplerPath, "pdfinfo"),
508
- args
509
- );
875
+ const child = spawn(this.#pdfInfoBin, args);
510
876
 
511
877
  if (Buffer.isBuffer(file)) {
512
878
  child.stdin.write(file);
@@ -529,7 +895,7 @@ class Poppler {
529
895
  if (stdOut !== "") {
530
896
  if (fileSize) {
531
897
  stdOut = stdOut.replace(
532
- pdfInfoFileSizesRegex,
898
+ PDF_INFO_FILE_SIZES_REG,
533
899
  `$1${fileSize}$2bytes`
534
900
  );
535
901
  }
@@ -551,14 +917,14 @@ class Poppler {
551
917
  resolve(stdOut.trim());
552
918
  }
553
919
  } else if (code === 0) {
554
- resolve(errorMessages[code]);
920
+ resolve(ERROR_MSGS[code]);
555
921
  } else if (stdErr !== "") {
556
922
  reject(new Error(stdErr.trim()));
557
923
  } else {
558
924
  reject(
559
925
  new Error(
560
- // @ts-ignore: Second operand used if code is not in errorMessages
561
- errorMessages[code] ||
926
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
927
+ ERROR_MSGS[code] ||
562
928
  `pdfinfo ${args.join(
563
929
  " "
564
930
  )} exited with code ${code}`
@@ -587,28 +953,12 @@ class Poppler {
587
953
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
588
954
  */
589
955
  async pdfSeparate(file, outputPattern, options = {}) {
590
- /** @type {PopplerAcceptedOptions} */
591
- const acceptedOptions = {
592
- firstPageToExtract: { arg: "-f", type: "number" },
593
- lastPageToExtract: { arg: "-l", type: "number" },
594
- printVersionInfo: { arg: "-v", type: "boolean" },
595
- };
596
-
597
- const { stderr } = await execFileAsync(
598
- pathResolve(this.#popplerPath, "pdfseparate"),
599
- ["-v"]
600
- );
601
-
602
- // @ts-ignore: parseOptions checks if falsy
603
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
604
-
956
+ const acceptedOptions = this.#getAcceptedOptions("pdfSeparate");
957
+ const versionInfo = await this.#getVersion(this.#pdfSeparateBin);
605
958
  const args = parseOptions(acceptedOptions, options, versionInfo);
606
959
  args.push(file, outputPattern);
607
960
 
608
- const { stdout } = await execFileAsync(
609
- pathResolve(this.#popplerPath, "pdfseparate"),
610
- args
611
- );
961
+ const { stdout } = await execFileAsync(this.#pdfSeparateBin, args);
612
962
  return stdout;
613
963
  }
614
964
 
@@ -720,130 +1070,59 @@ class Poppler {
720
1070
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
721
1071
  */
722
1072
  async pdfToCairo(file, outputFile, options = {}) {
723
- /** @type {PopplerAcceptedOptions} */
724
- const acceptedOptions = {
725
- antialias: { arg: "-antialias", type: "string" },
726
- cropBox: { arg: "-cropbox", type: "boolean" },
727
- cropHeight: { arg: "-H", type: "number" },
728
- cropSize: { arg: "-sz", type: "number" },
729
- cropWidth: { arg: "-W", type: "number" },
730
- cropXAxis: { arg: "-x", type: "number" },
731
- cropYAxis: { arg: "-y", type: "number" },
732
- duplex: { arg: "-duplex", type: "boolean" },
733
- epsFile: { arg: "-eps", type: "boolean" },
734
- evenPagesOnly: { arg: "-e", type: "boolean" },
735
- fillPage: { arg: "-expand", type: "boolean" },
736
- firstPageToConvert: { arg: "-f", type: "number" },
737
- grayscaleFile: { arg: "-gray", type: "boolean" },
738
- iccFile: { arg: "-icc", type: "string" },
739
- jpegFile: { arg: "-jpeg", type: "boolean" },
740
- jpegOptions: { arg: "-jpegopt", type: "string" },
741
- lastPageToConvert: { arg: "-l", type: "number" },
742
- monochromeFile: { arg: "-mono", type: "boolean" },
743
- noCenter: { arg: "-nocenter", type: "boolean" },
744
- noCrop: { arg: "-nocrop", type: "boolean" },
745
- noShrink: { arg: "-noshrink", type: "boolean" },
746
- oddPagesOnly: { arg: "-o", type: "boolean" },
747
- originalPageSizes: { arg: "-origpagesizes", type: "boolean" },
748
- ownerPassword: { arg: "-opw", type: "string" },
749
- paperHeight: { arg: "-paperh", type: "number" },
750
- paperSize: { arg: "-paper", type: "string" },
751
- paperWidth: { arg: "-paperw", type: "number" },
752
- pdfFile: { arg: "-pdf", type: "boolean" },
753
- pngFile: { arg: "-png", type: "boolean" },
754
- printDocStruct: {
755
- arg: "-struct",
756
- type: "boolean",
757
- minVersion: "23.11.0",
758
- },
759
- printVersionInfo: { arg: "-v", type: "boolean" },
760
- psFile: { arg: "-ps", type: "boolean" },
761
- psLevel2: { arg: "-level2", type: "boolean" },
762
- psLevel3: { arg: "-level3", type: "boolean" },
763
- quiet: { arg: "-q", type: "boolean" },
764
- resolutionXAxis: { arg: "-rx", type: "number" },
765
- resolutionXYAxis: { arg: "-r", type: "number" },
766
- resolutionYAxis: { arg: "-ry", type: "number" },
767
- scalePageTo: { arg: "-scale-to", type: "number" },
768
- scalePageToXAxis: { arg: "-scale-to-x", type: "number" },
769
- scalePageToYAxis: { arg: "-scale-to-y", type: "number" },
770
- singleFile: { arg: "-singlefile", type: "boolean" },
771
- svgFile: { arg: "-svg", type: "boolean" },
772
- tiffCompression: { arg: "-tiffcompression", type: "string" },
773
- tiffFile: { arg: "-tiff", type: "boolean" },
774
- transparentPageColor: { arg: "-transp", type: "boolean" },
775
- userPassword: { arg: "-upw", type: "string" },
776
- };
777
-
778
- try {
779
- const { stderr } = await execFileAsync(
780
- pathResolve(this.#popplerPath, "pdftocairo"),
781
- ["-v"]
782
- );
783
-
784
- // @ts-ignore: parseOptions checks if falsy
785
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
786
-
787
- const args = parseOptions(acceptedOptions, options, versionInfo);
1073
+ const acceptedOptions = this.#getAcceptedOptions("pdfToCairo");
1074
+ const versionInfo = await this.#getVersion(this.#pdfToCairoBin);
1075
+ const args = parseOptions(acceptedOptions, options, versionInfo);
788
1076
 
789
- return new Promise((resolve, reject) => {
790
- args.push(
791
- Buffer.isBuffer(file) ? "-" : file,
792
- outputFile || "-"
793
- );
1077
+ return new Promise((resolve, reject) => {
1078
+ args.push(Buffer.isBuffer(file) ? "-" : file, outputFile || "-");
794
1079
 
795
- const child = spawn(
796
- pathResolve(this.#popplerPath, "pdftocairo"),
797
- args
798
- );
1080
+ const child = spawn(this.#pdfToCairoBin, args);
799
1081
 
800
- if (
801
- outputFile === undefined &&
802
- args.some((arg) => ["-singlefile", "-pdf"].includes(arg))
803
- ) {
804
- child.stdout.setEncoding("binary");
805
- }
1082
+ if (
1083
+ outputFile === undefined &&
1084
+ args.some((arg) => ["-singlefile", "-pdf"].includes(arg))
1085
+ ) {
1086
+ child.stdout.setEncoding("binary");
1087
+ }
806
1088
 
807
- if (Buffer.isBuffer(file)) {
808
- child.stdin.write(file);
809
- child.stdin.end();
810
- }
1089
+ if (Buffer.isBuffer(file)) {
1090
+ child.stdin.write(file);
1091
+ child.stdin.end();
1092
+ }
811
1093
 
812
- let stdOut = "";
813
- let stdErr = "";
1094
+ let stdOut = "";
1095
+ let stdErr = "";
814
1096
 
815
- child.stdout.on("data", (data) => {
816
- stdOut += data;
817
- });
1097
+ child.stdout.on("data", (data) => {
1098
+ stdOut += data;
1099
+ });
818
1100
 
819
- child.stderr.on("data", (data) => {
820
- stdErr += data;
821
- });
1101
+ child.stderr.on("data", (data) => {
1102
+ stdErr += data;
1103
+ });
822
1104
 
823
- child.on("close", (code) => {
824
- /* istanbul ignore else */
825
- if (stdOut !== "") {
826
- resolve(stdOut.trim());
827
- } else if (code === 0) {
828
- resolve(errorMessages[code]);
829
- } else if (stdErr !== "") {
830
- reject(new Error(stdErr.trim()));
831
- } else {
832
- reject(
833
- new Error(
834
- // @ts-ignore: Second operand used if code is not in errorMessages
835
- errorMessages[code] ||
836
- `pdftocairo ${args.join(
837
- " "
838
- )} exited with code ${code}`
839
- )
840
- );
841
- }
842
- });
1105
+ child.on("close", (code) => {
1106
+ /* istanbul ignore else */
1107
+ if (stdOut !== "") {
1108
+ resolve(stdOut.trim());
1109
+ } else if (code === 0) {
1110
+ resolve(ERROR_MSGS[code]);
1111
+ } else if (stdErr !== "") {
1112
+ reject(new Error(stdErr.trim()));
1113
+ } else {
1114
+ reject(
1115
+ new Error(
1116
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
1117
+ ERROR_MSGS[code] ||
1118
+ `pdftocairo ${args.join(
1119
+ " "
1120
+ )} exited with code ${code}`
1121
+ )
1122
+ );
1123
+ }
843
1124
  });
844
- } catch (err) {
845
- return Promise.reject(err);
846
- }
1125
+ });
847
1126
  }
848
1127
 
849
1128
  /**
@@ -887,45 +1166,8 @@ class Poppler {
887
1166
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
888
1167
  */
889
1168
  async pdfToHtml(file, outputFile, options = {}) {
890
- /** @type {PopplerAcceptedOptions} */
891
- const acceptedOptions = {
892
- complexOutput: { arg: "-c", type: "boolean" },
893
- dataUrls: {
894
- arg: "-dataurls",
895
- type: "boolean",
896
- minVersion: "0.75.0",
897
- },
898
- exchangePdfLinks: { arg: "-p", type: "boolean" },
899
- extractHidden: { arg: "-hidden", type: "boolean" },
900
- firstPageToConvert: { arg: "-f", type: "number" },
901
- fontFullName: { arg: "-fontfullname", type: "boolean" },
902
- ignoreImages: { arg: "-i", type: "boolean" },
903
- imageFormat: { arg: "-fmt", type: "string" },
904
- lastPageToConvert: { arg: "-l", type: "number" },
905
- noDrm: { arg: "-nodrm", type: "boolean" },
906
- noFrames: { arg: "-noframes", type: "boolean" },
907
- noMergeParagraph: { arg: "-nomerge", type: "boolean" },
908
- noRoundedCoordinates: { arg: "-noroundcoord", type: "boolean" },
909
- outputEncoding: { arg: "-enc", type: "string" },
910
- ownerPassword: { arg: "-opw", type: "string" },
911
- printVersionInfo: { arg: "-v", type: "boolean" },
912
- quiet: { arg: "-q", type: "boolean" },
913
- singlePage: { arg: "-s", type: "boolean" },
914
- stdout: { arg: "-stdout", type: "boolean" },
915
- userPassword: { arg: "-upw", type: "string" },
916
- wordBreakThreshold: { arg: "-wbt", type: "number" },
917
- xmlOutput: { arg: "-xml", type: "boolean" },
918
- zoom: { arg: "-zoom", type: "number" },
919
- };
920
-
921
- const { stderr } = await execFileAsync(
922
- pathResolve(this.#popplerPath, "pdftohtml"),
923
- ["-v"]
924
- );
925
-
926
- // @ts-ignore: parseOptions checks if falsy
927
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
928
-
1169
+ const acceptedOptions = this.#getAcceptedOptions("pdfToHtml");
1170
+ const versionInfo = await this.#getVersion(this.#pdfToHtmlBin);
929
1171
  const args = parseOptions(acceptedOptions, options, versionInfo);
930
1172
 
931
1173
  return new Promise((resolve, reject) => {
@@ -935,10 +1177,7 @@ class Poppler {
935
1177
  args.push(outputFile);
936
1178
  }
937
1179
 
938
- const child = spawn(
939
- pathResolve(this.#popplerPath, "pdftohtml"),
940
- args
941
- );
1180
+ const child = spawn(this.#pdfToHtmlBin, args);
942
1181
 
943
1182
  if (Buffer.isBuffer(file)) {
944
1183
  child.stdin.write(file);
@@ -1042,94 +1281,14 @@ class Poppler {
1042
1281
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
1043
1282
  */
1044
1283
  async pdfToPpm(file, outputPath, options = {}) {
1045
- /** @type {PopplerAcceptedOptions} */
1046
- const acceptedOptions = {
1047
- antialiasFonts: { arg: "-aa", type: "string" },
1048
- antialiasVectors: { arg: "-aaVector", type: "string" },
1049
- cropBox: { arg: "-cropbox", type: "boolean" },
1050
- cropHeight: { arg: "-H", type: "number" },
1051
- cropSize: { arg: "-sz", type: "number" },
1052
- cropWidth: { arg: "-W", type: "number" },
1053
- cropXAxis: { arg: "-x", type: "number" },
1054
- cropYAxis: { arg: "-y", type: "number" },
1055
- defaultCmykProfile: {
1056
- arg: "-defaultcmykprofile",
1057
- type: "string",
1058
- minVersion: "21.01.0",
1059
- },
1060
- defaultGrayProfile: {
1061
- arg: "-defaultgrayprofile",
1062
- type: "string",
1063
- minVersion: "21.01.0",
1064
- },
1065
- defaultRgbProfile: {
1066
- arg: "-defaultrgbprofile",
1067
- type: "string",
1068
- minVersion: "21.01.0",
1069
- },
1070
- displayProfile: {
1071
- arg: "-displayprofile",
1072
- type: "string",
1073
- minVersion: "0.90.0",
1074
- },
1075
- evenPagesOnly: { arg: "-e", type: "boolean" },
1076
- firstPageToConvert: { arg: "-f", type: "number" },
1077
- forcePageNumber: {
1078
- arg: "-forcenum",
1079
- type: "boolean",
1080
- minVersion: "0.75.0",
1081
- },
1082
- freetype: { arg: "-freetype", type: "string" },
1083
- grayscaleFile: { arg: "-gray", type: "boolean" },
1084
- hideAnnotations: {
1085
- arg: "-hide-annotations",
1086
- type: "boolean",
1087
- minVersion: "0.84.0",
1088
- },
1089
- jpegFile: { arg: "-jpeg", type: "boolean" },
1090
- lastPageToConvert: { arg: "-l", type: "number" },
1091
- monochromeFile: { arg: "-mono", type: "boolean" },
1092
- oddPagesOnly: { arg: "-o", type: "boolean" },
1093
- ownerPassword: { arg: "-opw", type: "string" },
1094
- pngFile: { arg: "-png", type: "boolean" },
1095
- printProgress: {
1096
- arg: "-progress",
1097
- type: "boolean",
1098
- minVersion: "21.03.0",
1099
- },
1100
- printVersionInfo: { arg: "-v", type: "boolean" },
1101
- quiet: { arg: "-q", type: "boolean" },
1102
- resolutionXAxis: { arg: "-rx", type: "number" },
1103
- resolutionXYAxis: { arg: "-r", type: "number" },
1104
- resolutionYAxis: { arg: "-ry", type: "number" },
1105
- scalePageTo: { arg: "-scale-to", type: "number" },
1106
- scalePageToXAxis: { arg: "-scale-to-x", type: "number" },
1107
- scalePageToYAxis: { arg: "-scale-to-y", type: "number" },
1108
- separator: { arg: "-sep", type: "string", minVersion: "0.75.0" },
1109
- singleFile: { arg: "-singlefile", type: "boolean" },
1110
- thinLineMode: { arg: "-thinlinemode", type: "string" },
1111
- tiffCompression: { arg: "-tiffcompression", type: "string" },
1112
- tiffFile: { arg: "-tiff", type: "boolean" },
1113
- userPassword: { arg: "-upw", type: "string" },
1114
- };
1115
-
1116
- const { stderr } = await execFileAsync(
1117
- pathResolve(this.#popplerPath, "pdftoppm"),
1118
- ["-v"]
1119
- );
1120
-
1121
- // @ts-ignore: parseOptions checks if falsy
1122
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
1123
-
1284
+ const acceptedOptions = this.#getAcceptedOptions("pdfToPpm");
1285
+ const versionInfo = await this.#getVersion(this.#pdfToPpmBin);
1124
1286
  const args = parseOptions(acceptedOptions, options, versionInfo);
1125
1287
 
1126
1288
  return new Promise((resolve, reject) => {
1127
1289
  args.push(Buffer.isBuffer(file) ? "-" : file, outputPath);
1128
1290
 
1129
- const child = spawn(
1130
- pathResolve(this.#popplerPath, "pdftoppm"),
1131
- args
1132
- );
1291
+ const child = spawn(this.#pdfToPpmBin, args);
1133
1292
 
1134
1293
  if (Buffer.isBuffer(file)) {
1135
1294
  child.stdin.write(file);
@@ -1147,12 +1306,12 @@ class Poppler {
1147
1306
  if (stdErr !== "") {
1148
1307
  reject(new Error(stdErr.trim()));
1149
1308
  } else if (code === 0) {
1150
- resolve(errorMessages[code]);
1309
+ resolve(ERROR_MSGS[code]);
1151
1310
  } else {
1152
1311
  reject(
1153
1312
  new Error(
1154
- // @ts-ignore: Second operand used if code is not in errorMessages
1155
- errorMessages[code] ||
1313
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
1314
+ ERROR_MSGS[code] ||
1156
1315
  `pdftoppm ${args.join(
1157
1316
  " "
1158
1317
  )} exited with code ${code}`
@@ -1273,93 +1432,14 @@ class Poppler {
1273
1432
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
1274
1433
  */
1275
1434
  async pdfToPs(file, outputFile, options = {}) {
1276
- /** @type {PopplerAcceptedOptions} */
1277
- const acceptedOptions = {
1278
- antialias: { arg: "-aaRaster", type: "string" },
1279
- binary: { arg: "-binary", type: "boolean" },
1280
- defaultCmykProfile: {
1281
- arg: "-defaultcmykprofile",
1282
- type: "string",
1283
- minVersion: "21.01.0",
1284
- },
1285
- defaultGrayProfile: {
1286
- arg: "-defaultgrayprofile",
1287
- type: "string",
1288
- minVersion: "21.01.0",
1289
- },
1290
- defaultRgbProfile: {
1291
- arg: "-defaultrgbprofile",
1292
- type: "string",
1293
- minVersion: "21.01.0",
1294
- },
1295
- duplex: { arg: "-duplex", type: "boolean" },
1296
- epsFile: { arg: "-eps", type: "boolean" },
1297
- fillPage: { arg: "-expand", type: "boolean" },
1298
- firstPageToConvert: { arg: "-f", type: "number" },
1299
- form: { arg: "-form", type: "boolean" },
1300
- lastPageToConvert: { arg: "-l", type: "number" },
1301
- level1: { arg: "-level1", type: "boolean" },
1302
- level1Sep: { arg: "-level1sep", type: "boolean" },
1303
- level2: { arg: "-level2", type: "boolean" },
1304
- level2Sep: { arg: "-level2sep", type: "boolean" },
1305
- level3: { arg: "-level3", type: "boolean" },
1306
- level3Sep: { arg: "-level3sep", type: "boolean" },
1307
- noCenter: { arg: "-nocenter", type: "boolean" },
1308
- noCrop: { arg: "-nocrop", type: "boolean" },
1309
- noEmbedCIDFonts: { arg: "-noembcidps", type: "boolean" },
1310
- noEmbedCIDTrueTypeFonts: {
1311
- arg: "-noembcidtt",
1312
- type: "boolean",
1313
- },
1314
- noEmbedTrueTypeFonts: { arg: "-noembtt", type: "boolean" },
1315
- noEmbedType1Fonts: { arg: "-noembt1", type: "boolean" },
1316
- noShrink: { arg: "-noshrink", type: "boolean" },
1317
- opi: { arg: "-opi", type: "boolean" },
1318
- optimizecolorspace: {
1319
- arg: "-optimizecolorspace",
1320
- type: "boolean",
1321
- },
1322
- originalPageSizes: { arg: "-origpagesizes", type: "boolean" },
1323
- overprint: { arg: "-overprint", type: "boolean" },
1324
- ownerPassword: { arg: "-opw", type: "string" },
1325
- paperHeight: { arg: "-paperh", type: "number" },
1326
- paperSize: { arg: "-paper", type: "string" },
1327
- paperWidth: { arg: "-paperw", type: "number" },
1328
- passfonts: { arg: "-passfonts", type: "boolean" },
1329
- preload: { arg: "-preload", type: "boolean" },
1330
- printVersionInfo: { arg: "-v", type: "boolean" },
1331
- processColorFormat: { arg: "-processcolorformat", type: "string" },
1332
- processColorProfile: {
1333
- arg: "-processcolorprofile",
1334
- type: "string",
1335
- },
1336
- quiet: { arg: "-q", type: "boolean" },
1337
- rasterize: {
1338
- arg: "-rasterize",
1339
- type: "string",
1340
- minVersion: "0.90.0",
1341
- },
1342
- resolutionXYAxis: { arg: "-r", type: "number" },
1343
- userPassword: { arg: "-upw", type: "string" },
1344
- };
1345
-
1346
- const { stderr } = await execFileAsync(
1347
- pathResolve(this.#popplerPath, "pdftops"),
1348
- ["-v"]
1349
- );
1350
-
1351
- // @ts-ignore: parseOptions checks if falsy
1352
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
1353
-
1435
+ const acceptedOptions = this.#getAcceptedOptions("pdfToPs");
1436
+ const versionInfo = await this.#getVersion(this.#pdfToPsBin);
1354
1437
  const args = parseOptions(acceptedOptions, options, versionInfo);
1355
1438
 
1356
1439
  return new Promise((resolve, reject) => {
1357
1440
  args.push(Buffer.isBuffer(file) ? "-" : file, outputFile || "-");
1358
1441
 
1359
- const child = spawn(
1360
- pathResolve(this.#popplerPath, "pdftops"),
1361
- args
1362
- );
1442
+ const child = spawn(this.#pdfToPsBin, args);
1363
1443
 
1364
1444
  if (Buffer.isBuffer(file)) {
1365
1445
  child.stdin.write(file);
@@ -1382,14 +1462,14 @@ class Poppler {
1382
1462
  if (stdOut !== "") {
1383
1463
  resolve(stdOut.trim());
1384
1464
  } else if (code === 0) {
1385
- resolve(errorMessages[code]);
1465
+ resolve(ERROR_MSGS[code]);
1386
1466
  } else if (stdErr !== "") {
1387
1467
  reject(new Error(stdErr.trim()));
1388
1468
  } else {
1389
1469
  reject(
1390
1470
  new Error(
1391
- // @ts-ignore: Second operand used if code is not in errorMessages
1392
- errorMessages[code] ||
1471
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
1472
+ ERROR_MSGS[code] ||
1393
1473
  `pdftops ${args.join(
1394
1474
  " "
1395
1475
  )} exited with code ${code}`
@@ -1449,62 +1529,14 @@ class Poppler {
1449
1529
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
1450
1530
  */
1451
1531
  async pdfToText(file, outputFile, options = {}) {
1452
- /** @type {PopplerAcceptedOptions} */
1453
- const acceptedOptions = {
1454
- boundingBoxXhtml: { arg: "-bbox", type: "boolean" },
1455
- boundingBoxXhtmlLayout: {
1456
- arg: "-bbox-layout",
1457
- type: "boolean",
1458
- },
1459
- cropBox: {
1460
- arg: "-cropbox",
1461
- type: "boolean",
1462
- minVersion: "21.03.0",
1463
- },
1464
- cropHeight: { arg: "-H", type: "number" },
1465
- cropWidth: { arg: "-W", type: "number" },
1466
- cropXAxis: { arg: "-x", type: "number" },
1467
- cropYAxis: { arg: "-y", type: "number" },
1468
- eolConvention: { arg: "-eol", type: "string" },
1469
- firstPageToConvert: { arg: "-f", type: "number" },
1470
- fixedWidthLayout: { arg: "-fixed", type: "number" },
1471
- generateHtmlMetaFile: { arg: "-htmlmeta", type: "boolean" },
1472
- generateTsvFile: { arg: "-tsv", type: "boolean" },
1473
- lastPageToConvert: { arg: "-l", type: "number" },
1474
- listEncodingOptions: { arg: "-listenc", type: "boolean" },
1475
- maintainLayout: { arg: "-layout", type: "boolean" },
1476
- noDiagonalText: {
1477
- arg: "-nodiag",
1478
- type: "boolean",
1479
- minVersion: "0.80.0",
1480
- },
1481
- noPageBreaks: { arg: "-nopgbrk", type: "boolean" },
1482
- outputEncoding: { arg: "-enc", type: "string" },
1483
- ownerPassword: { arg: "-opw", type: "string" },
1484
- printVersionInfo: { arg: "-v", type: "boolean" },
1485
- quiet: { arg: "-q", type: "boolean" },
1486
- rawLayout: { arg: "-raw", type: "boolean" },
1487
- resolution: { arg: "-r", type: "number" },
1488
- userPassword: { arg: "-upw", type: "string" },
1489
- };
1490
-
1491
- const { stderr } = await execFileAsync(
1492
- pathResolve(this.#popplerPath, "pdftotext"),
1493
- ["-v"]
1494
- );
1495
-
1496
- // @ts-ignore: parseOptions checks if falsy
1497
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
1498
-
1532
+ const acceptedOptions = this.#getAcceptedOptions("pdfToText");
1533
+ const versionInfo = await this.#getVersion(this.#pdfToTextBin);
1499
1534
  const args = parseOptions(acceptedOptions, options, versionInfo);
1500
1535
 
1501
1536
  return new Promise((resolve, reject) => {
1502
1537
  args.push(Buffer.isBuffer(file) ? "-" : file, outputFile || "-");
1503
1538
 
1504
- const child = spawn(
1505
- pathResolve(this.#popplerPath, "pdftotext"),
1506
- args
1507
- );
1539
+ const child = spawn(this.#pdfToTextBin, args);
1508
1540
 
1509
1541
  if (Buffer.isBuffer(file)) {
1510
1542
  child.stdin.write(file);
@@ -1527,14 +1559,14 @@ class Poppler {
1527
1559
  if (stdOut !== "") {
1528
1560
  resolve(options.maintainLayout ? stdOut : stdOut.trim());
1529
1561
  } else if (code === 0) {
1530
- resolve(errorMessages[code]);
1562
+ resolve(ERROR_MSGS[code]);
1531
1563
  } else if (stdErr !== "") {
1532
1564
  reject(new Error(stdErr.trim()));
1533
1565
  } else {
1534
1566
  reject(
1535
1567
  new Error(
1536
- // @ts-ignore: Second operand used if code is not in errorMessages
1537
- errorMessages[code] ||
1568
+ // @ts-ignore: Second operand used if code is not in ERROR_MSGS
1569
+ ERROR_MSGS[code] ||
1538
1570
  `pdftotext ${args.join(
1539
1571
  " "
1540
1572
  )} exited with code ${code}`
@@ -1557,26 +1589,12 @@ class Poppler {
1557
1589
  * @returns {Promise<string>} A promise that resolves with a stdout string, or rejects with an `Error` object.
1558
1590
  */
1559
1591
  async pdfUnite(files, outputFile, options = {}) {
1560
- /** @type {PopplerAcceptedOptions} */
1561
- const acceptedOptions = {
1562
- printVersionInfo: { arg: "-v", type: "boolean" },
1563
- };
1564
-
1565
- const { stderr } = await execFileAsync(
1566
- pathResolve(this.#popplerPath, "pdfunite"),
1567
- ["-v"]
1568
- );
1569
-
1570
- // @ts-ignore: parseOptions checks if falsy
1571
- const versionInfo = popplerVersionRegex.exec(stderr)[1];
1572
-
1592
+ const acceptedOptions = this.#getAcceptedOptions("pdfUnite");
1593
+ const versionInfo = await this.#getVersion(this.#pdfUniteBin);
1573
1594
  const args = parseOptions(acceptedOptions, options, versionInfo);
1574
1595
  args.push(...files, outputFile);
1575
1596
 
1576
- const { stdout } = await execFileAsync(
1577
- pathResolve(this.#popplerPath, "pdfunite"),
1578
- args
1579
- );
1597
+ const { stdout } = await execFileAsync(this.#pdfUniteBin, args);
1580
1598
  return stdout;
1581
1599
  }
1582
1600
  }