pdfbooklet 1.0.4 → 1.0.6
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.
- package/README.md +12 -5
- package/package.json +1 -1
- package/pdfbooklet.js +32 -18
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Generate booklet format of a PDF file for printing
|
|
2
|
+
|
|
3
|
+
Save paper, save trees and save lives.
|
|
4
|
+
|
|
1
5
|
To install
|
|
2
6
|
|
|
3
7
|
```
|
|
@@ -7,11 +11,14 @@ npm i -g pdfbooklet
|
|
|
7
11
|
To use
|
|
8
12
|
|
|
9
13
|
```
|
|
10
|
-
pdfbooklet <
|
|
14
|
+
pdfbooklet [options] <INPUT-FILE.pdf>
|
|
11
15
|
|
|
12
16
|
OPTIONS:
|
|
13
|
-
--
|
|
14
|
-
--margin-inset X reduce margin
|
|
15
|
-
--margin-inset
|
|
16
|
-
--
|
|
17
|
+
--margin-inset X reduce margin of the original pdf on all sides by X inches
|
|
18
|
+
--margin-inset X,Y reduce margin X on top and bottom, Y on left and right, in inches
|
|
19
|
+
--margin-inset T,R,B,L reduce margin-top by T, right by R, bottom by B, left by L, in inches
|
|
20
|
+
--output FILENAME default is INPUT_FILE-booklet.pdf.
|
|
21
|
+
--paper-size (a4|letter) default is letter
|
|
22
|
+
--range X-Y,+N,A-B,... select page X to Y from input, insert N blank pages,
|
|
23
|
+
then from page A to B
|
|
17
24
|
```
|
package/package.json
CHANGED
package/pdfbooklet.js
CHANGED
|
@@ -15,7 +15,11 @@ const pageSize = {
|
|
|
15
15
|
height: 8.5 * INCH,
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// a list of 0-based indexes to the original pdf file,
|
|
19
|
+
// -1 means blank page.
|
|
20
|
+
let inputPageNumbers = []
|
|
21
|
+
let inputPdfPath = undefined
|
|
22
|
+
let outputPdfPath = undefined
|
|
19
23
|
|
|
20
24
|
const err = (msg, exitCode) => {
|
|
21
25
|
console.error(msg);
|
|
@@ -25,14 +29,16 @@ const err = (msg, exitCode) => {
|
|
|
25
29
|
const usage = (msg) => {
|
|
26
30
|
if (msg) console.error(msg);
|
|
27
31
|
console.log(`
|
|
28
|
-
pdfbooklet <
|
|
32
|
+
pdfbooklet [options] <INPUT-FILE.pdf>
|
|
29
33
|
|
|
30
34
|
OPTIONS:
|
|
31
|
-
--
|
|
32
|
-
--
|
|
33
|
-
--margin-inset
|
|
34
|
-
--
|
|
35
|
-
--
|
|
35
|
+
--margin-inset X reduce margin of the original pdf on all sides by X inches
|
|
36
|
+
--margin-inset X,Y reduce margin X on top and bottom, Y on left and right, in inches
|
|
37
|
+
--margin-inset T,R,B,L reduce margin-top by T, right by R, bottom by B, left by L, in inches
|
|
38
|
+
--output FILENAME default is INPUT_FILE-booklet.pdf.
|
|
39
|
+
--paper-size (a4|letter) default is letter
|
|
40
|
+
--range X-Y,+N,A-B,... select page X to Y from input, insert N blank pages,
|
|
41
|
+
then from page A to B
|
|
36
42
|
`)
|
|
37
43
|
process.exit(msg ? 1 : 0)
|
|
38
44
|
}
|
|
@@ -61,12 +67,15 @@ async function createBooklet(inputPdfPath, outputPdfPath) {
|
|
|
61
67
|
const existingPdfBytes = fs.readFileSync(inputPdfPath);
|
|
62
68
|
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
|
63
69
|
const totalPages = pdfDoc.getPageCount();
|
|
64
|
-
|
|
70
|
+
|
|
71
|
+
// If no page numbers specified, use the whole range
|
|
72
|
+
const pageNumbers = inputPageNumbers || Array.from({length: totalPages}, (_, i) => i);
|
|
73
|
+
// Align the numbers to a multiple of 4, use blank page for padding
|
|
65
74
|
while (pageNumbers.length % 4 !== 0) {
|
|
66
75
|
pageNumbers.push(-1);
|
|
67
76
|
}
|
|
77
|
+
|
|
68
78
|
console.log(`Total pages in the input PDF: ${totalPages}`);
|
|
69
|
-
console.log(`Output booklet will have ${pageNumbers.length} pages`);
|
|
70
79
|
|
|
71
80
|
// Create a new PDF for the booklet
|
|
72
81
|
const bookletPdf = await PDFDocument.create();
|
|
@@ -78,7 +87,6 @@ async function createBooklet(inputPdfPath, outputPdfPath) {
|
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
|
|
82
90
|
const leftBox = {
|
|
83
91
|
x: 0,
|
|
84
92
|
y: 0, // Draw the first page on the left half
|
|
@@ -126,15 +134,18 @@ async function createBooklet(inputPdfPath, outputPdfPath) {
|
|
|
126
134
|
// Write the final booklet PDF to a file
|
|
127
135
|
const pdfBytes = await bookletPdf.save();
|
|
128
136
|
fs.writeFileSync(outputPdfPath, pdfBytes);
|
|
129
|
-
console.log(`Booklet PDF created: ${outputPdfPath}
|
|
137
|
+
console.log(`Booklet PDF created: ${outputPdfPath}, ${pageNumbers.length/2} pages`);
|
|
138
|
+
console.log(`Please print it in duplex mode.`);
|
|
130
139
|
}
|
|
131
140
|
|
|
132
|
-
let inputPdfPath;
|
|
133
141
|
|
|
134
142
|
for (let i = 2; i < process.argv.length; i++) {
|
|
135
143
|
switch (process.argv[i]) {
|
|
144
|
+
case '--output':
|
|
145
|
+
outputPdfPath = process.argv[++i];
|
|
146
|
+
break;
|
|
136
147
|
case '--range':
|
|
137
|
-
|
|
148
|
+
inputPageNumbers = process.argv[++i].split(',').map(x => {
|
|
138
149
|
const m = x.match(/^\+(\d+)$/);
|
|
139
150
|
if (m) {
|
|
140
151
|
return Array(parseInt(m[1])).fill(0)
|
|
@@ -149,7 +160,7 @@ for (let i = 2; i < process.argv.length; i++) {
|
|
|
149
160
|
const begin = parseInt(m2[1]);
|
|
150
161
|
const end = parseInt(m2[2]);
|
|
151
162
|
return Array.from({length: end - begin + 1}, (v, i) => begin + i)
|
|
152
|
-
}).flat().map(x => x - 1);
|
|
163
|
+
}).flat().map(x => x - 1); // convert to 0 based index
|
|
153
164
|
break;
|
|
154
165
|
case '--paper-size':
|
|
155
166
|
switch (process.argv[++i]) {
|
|
@@ -199,8 +210,6 @@ for (let i = 2; i < process.argv.length; i++) {
|
|
|
199
210
|
}
|
|
200
211
|
}
|
|
201
212
|
|
|
202
|
-
console.log("pages=", JSON.stringify(opt_pages));
|
|
203
|
-
|
|
204
213
|
if (!inputPdfPath) {
|
|
205
214
|
usage("Missing input file");
|
|
206
215
|
}
|
|
@@ -210,9 +219,14 @@ if (!fs.existsSync(inputPdfPath)) {
|
|
|
210
219
|
}
|
|
211
220
|
|
|
212
221
|
// Automatically generate the output filename by appending '-booklet' before '.pdf'
|
|
213
|
-
|
|
222
|
+
outputPdfPath ||= inputPdfPath.replace(/\.pdf$/i, '-booklet.pdf');
|
|
223
|
+
|
|
224
|
+
if (outputPdfPath === inputPdfPath) {
|
|
225
|
+
err("Output file must not be same as input file");
|
|
226
|
+
}
|
|
227
|
+
|
|
214
228
|
// Usage example
|
|
215
229
|
createBooklet(inputPdfPath, outputPdfPath).catch(err => {
|
|
216
|
-
|
|
230
|
+
err(`Error creating booklet: ${err}`);
|
|
217
231
|
});
|
|
218
232
|
|