n8n-nodes-pdfbro 0.1.7 → 0.1.9
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 +17 -5
- package/dist/index.js +1 -1
- package/dist/nodes/PdfBro/PdfBro.node.js +366 -0
- package/package.json +8 -3
- package/dist/nodes/PdfUtils/PdfBro.node.js +0 -274
- package/dist/nodes/PdfUtils/PdfUtils.node.js +0 -191
- package/dist/nodes/PdfUtils/pdfUtils.svg +0 -1
- /package/dist/{PdfUtils → nodes/PdfBro}/pdfUtils.svg +0 -0
package/README.md
CHANGED
|
@@ -30,19 +30,28 @@ npm install n8n-nodes-pdfbro
|
|
|
30
30
|
## Operations
|
|
31
31
|
|
|
32
32
|
### Merge PDFs
|
|
33
|
-
|
|
33
|
+
Link multiple binary fields (up to 10+ via "Add PDF Input") to combine them into a single PDF.
|
|
34
34
|
|
|
35
35
|
### Split Pages
|
|
36
|
-
|
|
36
|
+
Split a PDF into separate pages or ranges.
|
|
37
|
+
**Supported Ranges:**
|
|
38
|
+
- `*` : Split every page into a separate file (Burst).
|
|
39
|
+
- `1, 3, 5` : Extract specific pages.
|
|
40
|
+
- `1-5` : Extract bytes 1 to 5.
|
|
41
|
+
- `7-` : Extract from page 7 to the end.
|
|
42
|
+
- `-1` : Extract the last page.
|
|
43
|
+
|
|
44
|
+
### Invoice Maker (HTML to PDF)
|
|
45
|
+
Convert valid HTML content into a PDF. Useful for generating invoices, reports, or simple documents.
|
|
37
46
|
|
|
38
47
|
### Extract Text
|
|
39
|
-
Extracts all text from the PDF
|
|
48
|
+
Extracts all text from the PDF.
|
|
40
49
|
|
|
41
50
|
### Extract Metadata
|
|
42
|
-
|
|
51
|
+
Gets title, author, creation date, etc.
|
|
43
52
|
|
|
44
53
|
### Rotate Pages
|
|
45
|
-
Rotates all pages
|
|
54
|
+
Rotates all pages by X degrees.
|
|
46
55
|
|
|
47
56
|
## License
|
|
48
57
|
|
|
@@ -53,6 +62,9 @@ MIT
|
|
|
53
62
|
This node powers its PDF magic using these awesome open-source libraries:
|
|
54
63
|
|
|
55
64
|
* **[pdf-lib](https://github.com/Hopding/pdf-lib)** (MIT License) - PDF creation and modification.
|
|
65
|
+
* **[pdfmake](http://pdfmake.org/)** (MIT License) - PDF generation engine.
|
|
66
|
+
* **[html-to-pdfmake](https://github.com/Aymkdn/html-to-pdfmake)** (MIT License) - HTML to PDFMake conversion.
|
|
67
|
+
* **[jsdom](https://github.com/jsdom/jsdom)** (MIT License) - DOM environment.
|
|
56
68
|
* **[pdf-parse](https://gitlab.com/autokent/pdf-parse)** (MIT License) - PDF text extraction.
|
|
57
69
|
|
|
58
70
|
We are grateful to the maintainers of these projects!
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.nodes = void 0;
|
|
4
|
-
const PdfBro_node_1 = require("./nodes/
|
|
4
|
+
const PdfBro_node_1 = require("./nodes/PdfBro/PdfBro.node");
|
|
5
5
|
exports.nodes = [PdfBro_node_1.PdfBro];
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PdfBro = void 0;
|
|
7
|
+
const pdf_lib_1 = require("pdf-lib");
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
const pdf_parse_1 = __importDefault(require("pdf-parse"));
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const pdfmake_1 = __importDefault(require("pdfmake/build/pdfmake"));
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
const vfs_fonts_1 = __importDefault(require("pdfmake/build/vfs_fonts"));
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const html_to_pdfmake_1 = __importDefault(require("html-to-pdfmake"));
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
const jsdom_1 = require("jsdom");
|
|
18
|
+
// Initialize pdfmake fonts
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
pdfmake_1.default.vfs = vfs_fonts_1.default.pdfMake.vfs;
|
|
21
|
+
class PdfBro {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.description = {
|
|
24
|
+
displayName: 'PdfBro',
|
|
25
|
+
name: 'pdfBro',
|
|
26
|
+
icon: 'file:pdfUtils.svg',
|
|
27
|
+
group: ['transform'],
|
|
28
|
+
version: 1,
|
|
29
|
+
description: 'The ultimate PDF utility (powered by pdf-lib & pdf-parse)',
|
|
30
|
+
defaults: {
|
|
31
|
+
name: 'PdfBro',
|
|
32
|
+
},
|
|
33
|
+
inputs: ['main'],
|
|
34
|
+
outputs: ['main'],
|
|
35
|
+
properties: [
|
|
36
|
+
{
|
|
37
|
+
displayName: 'Operation',
|
|
38
|
+
name: 'operation',
|
|
39
|
+
type: 'options',
|
|
40
|
+
noDataExpression: true,
|
|
41
|
+
options: [
|
|
42
|
+
{
|
|
43
|
+
name: 'Merge PDFs',
|
|
44
|
+
value: 'merge',
|
|
45
|
+
description: 'Merge multiple binary fields into a single PDF',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'Split Pages',
|
|
49
|
+
value: 'split',
|
|
50
|
+
description: 'Split a PDF into separate pages or ranges',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Invoice Maker (HTML to PDF)',
|
|
54
|
+
value: 'invoice',
|
|
55
|
+
description: 'Convert HTML to PDF',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'Extract Text',
|
|
59
|
+
value: 'extractText',
|
|
60
|
+
description: 'Extract text content from PDF',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Extract Metadata',
|
|
64
|
+
value: 'metadata',
|
|
65
|
+
description: 'Get PDF metadata (title, author, pages)',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Rotate Pages',
|
|
69
|
+
value: 'rotate',
|
|
70
|
+
description: 'Rotate all pages in a PDF',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
default: 'merge',
|
|
74
|
+
},
|
|
75
|
+
// MERGE Operations: Multiple Inputs
|
|
76
|
+
{
|
|
77
|
+
displayName: 'Input PDF Files',
|
|
78
|
+
name: 'inputBinaries',
|
|
79
|
+
placeholder: 'Add PDF Input',
|
|
80
|
+
type: 'fixedCollection',
|
|
81
|
+
typeOptions: {
|
|
82
|
+
multipleValues: true,
|
|
83
|
+
},
|
|
84
|
+
displayOptions: {
|
|
85
|
+
show: {
|
|
86
|
+
operation: ['merge'],
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
default: {},
|
|
90
|
+
options: [
|
|
91
|
+
{
|
|
92
|
+
name: 'files',
|
|
93
|
+
displayName: 'Files',
|
|
94
|
+
values: [
|
|
95
|
+
{
|
|
96
|
+
displayName: 'Binary Property',
|
|
97
|
+
name: 'binaryPropertyName',
|
|
98
|
+
type: 'string',
|
|
99
|
+
default: 'data',
|
|
100
|
+
description: 'Name of the binary property containing the PDF to merge',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
// Common input for single-file operations
|
|
107
|
+
{
|
|
108
|
+
displayName: 'Input Binary Field',
|
|
109
|
+
name: 'binaryPropertyName',
|
|
110
|
+
type: 'string',
|
|
111
|
+
default: 'data',
|
|
112
|
+
required: true,
|
|
113
|
+
displayOptions: {
|
|
114
|
+
show: {
|
|
115
|
+
operation: ['split', 'extractText', 'metadata', 'rotate'],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
description: 'The name of the binary field containing the PDF',
|
|
119
|
+
},
|
|
120
|
+
// SPLIT Operations
|
|
121
|
+
{
|
|
122
|
+
displayName: 'Split Range',
|
|
123
|
+
name: 'splitRange',
|
|
124
|
+
type: 'string',
|
|
125
|
+
default: '*',
|
|
126
|
+
displayOptions: {
|
|
127
|
+
show: {
|
|
128
|
+
operation: ['split'],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
description: 'Pages to extract. Examples: "1" (1st page), "1-3" (1st to 3rd), "7-" (7th to end), "-1" (last page), "*" (all pages separately).',
|
|
132
|
+
},
|
|
133
|
+
// INVOICE Operations
|
|
134
|
+
{
|
|
135
|
+
displayName: 'HTML Content',
|
|
136
|
+
name: 'htmlContent',
|
|
137
|
+
type: 'string',
|
|
138
|
+
default: '<h1>Invoice</h1><p>Content here...</p>',
|
|
139
|
+
typeOptions: {
|
|
140
|
+
rows: 5,
|
|
141
|
+
},
|
|
142
|
+
displayOptions: {
|
|
143
|
+
show: {
|
|
144
|
+
operation: ['invoice'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
description: 'The HTML content to convert to PDF',
|
|
148
|
+
},
|
|
149
|
+
// ROTATE Operations
|
|
150
|
+
{
|
|
151
|
+
displayName: 'Rotation Degrees',
|
|
152
|
+
name: 'rotationDegrees',
|
|
153
|
+
type: 'number',
|
|
154
|
+
default: 90,
|
|
155
|
+
displayOptions: {
|
|
156
|
+
show: {
|
|
157
|
+
operation: ['rotate'],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
description: 'Clockwise rotation (e.g. 90, 180, 270)',
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async execute() {
|
|
166
|
+
var _a;
|
|
167
|
+
const items = this.getInputData();
|
|
168
|
+
const returnData = [];
|
|
169
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
170
|
+
// --- Helper: Parse Split Range ---
|
|
171
|
+
const parseRange = (rangeStr, totalPages) => {
|
|
172
|
+
if (rangeStr === '*') {
|
|
173
|
+
// Return all page indexes
|
|
174
|
+
return Array.from({ length: totalPages }, (_, i) => i);
|
|
175
|
+
}
|
|
176
|
+
const pages = new Set();
|
|
177
|
+
const parts = rangeStr.split(',').map(p => p.trim());
|
|
178
|
+
for (const part of parts) {
|
|
179
|
+
if (part.includes('-')) {
|
|
180
|
+
let [startStr, endStr] = part.split('-');
|
|
181
|
+
// Handle "7-" (7 to end)
|
|
182
|
+
if (startStr && !endStr) {
|
|
183
|
+
let start = parseInt(startStr);
|
|
184
|
+
if (start < 0)
|
|
185
|
+
start = totalPages + start + 1; // 1-based logic to index
|
|
186
|
+
for (let i = start; i <= totalPages; i++) {
|
|
187
|
+
pages.add(i - 1);
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
let start = parseInt(startStr);
|
|
192
|
+
let end = parseInt(endStr);
|
|
193
|
+
// Handle negative numbers (from end)
|
|
194
|
+
if (start < 0)
|
|
195
|
+
start = totalPages + start + 1;
|
|
196
|
+
if (end < 0)
|
|
197
|
+
end = totalPages + end + 1;
|
|
198
|
+
// Clamp
|
|
199
|
+
start = Math.max(1, start);
|
|
200
|
+
end = Math.min(totalPages, end);
|
|
201
|
+
for (let i = start; i <= end; i++) {
|
|
202
|
+
pages.add(i - 1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
let page = parseInt(part);
|
|
207
|
+
if (page < 0)
|
|
208
|
+
page = totalPages + page + 1;
|
|
209
|
+
if (page >= 1 && page <= totalPages) {
|
|
210
|
+
pages.add(page - 1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return Array.from(pages).sort((a, b) => a - b);
|
|
215
|
+
};
|
|
216
|
+
for (let i = 0; i < items.length; i++) {
|
|
217
|
+
try {
|
|
218
|
+
if (operation === 'merge') {
|
|
219
|
+
const mergedPdf = await pdf_lib_1.PDFDocument.create();
|
|
220
|
+
// Get fixed collection
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
const binaries = ((_a = this.getNodeParameter('inputBinaries', i)) === null || _a === void 0 ? void 0 : _a.files) || [];
|
|
223
|
+
// If user provided no binaries, just skip
|
|
224
|
+
if (binaries.length === 0)
|
|
225
|
+
continue;
|
|
226
|
+
for (const entry of binaries) {
|
|
227
|
+
const propName = entry.binaryPropertyName;
|
|
228
|
+
if (this.helpers.assertBinaryData(i, propName)) {
|
|
229
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, propName);
|
|
230
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
231
|
+
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
232
|
+
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const mergedPdfBuffer = await mergedPdf.save();
|
|
236
|
+
returnData.push({
|
|
237
|
+
json: { success: true, pageCount: mergedPdf.getPageCount() },
|
|
238
|
+
binary: {
|
|
239
|
+
data: await this.helpers.prepareBinaryData(Buffer.from(mergedPdfBuffer), 'merged.pdf', 'application/pdf'),
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
else if (operation === 'split') {
|
|
244
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
245
|
+
const rangeStr = this.getNodeParameter('splitRange', i);
|
|
246
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
247
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
248
|
+
const totalPages = pdf.getPageCount();
|
|
249
|
+
// Parse logic
|
|
250
|
+
let indicesToKeep = parseRange(rangeStr, totalPages);
|
|
251
|
+
if (rangeStr === '*') {
|
|
252
|
+
// Burst mode: return separate items
|
|
253
|
+
for (const pageIndex of indicesToKeep) {
|
|
254
|
+
const newPdf = await pdf_lib_1.PDFDocument.create();
|
|
255
|
+
const [copiedPage] = await newPdf.copyPages(pdf, [pageIndex]);
|
|
256
|
+
newPdf.addPage(copiedPage);
|
|
257
|
+
const newPdfBuffer = await newPdf.save();
|
|
258
|
+
returnData.push({
|
|
259
|
+
json: { ...items[i].json, pageNumber: pageIndex + 1, totalPages },
|
|
260
|
+
binary: {
|
|
261
|
+
data: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), `page_${pageIndex + 1}.pdf`, 'application/pdf'),
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Range mode: return single PDF with selected pages
|
|
268
|
+
// Unless the range logic implies multiple? User said "Use * to split each page".
|
|
269
|
+
// "1-3" usually means "Create a PDF with pages 1 to 3".
|
|
270
|
+
const newPdf = await pdf_lib_1.PDFDocument.create();
|
|
271
|
+
const copiedPages = await newPdf.copyPages(pdf, indicesToKeep);
|
|
272
|
+
copiedPages.forEach(p => newPdf.addPage(p));
|
|
273
|
+
const newPdfBuffer = await newPdf.save();
|
|
274
|
+
returnData.push({
|
|
275
|
+
json: { ...items[i].json, extractedPages: indicesToKeep.map(p => p + 1).join(', ') },
|
|
276
|
+
binary: {
|
|
277
|
+
data: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), 'extracted.pdf', 'application/pdf'),
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
else if (operation === 'invoice') {
|
|
283
|
+
const htmlContent = this.getNodeParameter('htmlContent', i);
|
|
284
|
+
// convert html to pdfmake format (requires window)
|
|
285
|
+
const { window } = new jsdom_1.JSDOM('');
|
|
286
|
+
const docDefContent = (0, html_to_pdfmake_1.default)(htmlContent, { window });
|
|
287
|
+
const docDefinition = {
|
|
288
|
+
content: docDefContent,
|
|
289
|
+
};
|
|
290
|
+
const pdfDocGenerator = pdfmake_1.default.createPdf(docDefinition);
|
|
291
|
+
const buffer = await new Promise((resolve, reject) => {
|
|
292
|
+
pdfDocGenerator.getBuffer((buffer) => {
|
|
293
|
+
resolve(buffer);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
returnData.push({
|
|
297
|
+
json: { success: true },
|
|
298
|
+
binary: {
|
|
299
|
+
data: await this.helpers.prepareBinaryData(buffer, 'invoice.pdf', 'application/pdf'),
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
else if (operation === 'rotate') {
|
|
304
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
305
|
+
const degreesVal = this.getNodeParameter('rotationDegrees', i);
|
|
306
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
307
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
308
|
+
const pages = pdf.getPages();
|
|
309
|
+
pages.forEach(page => {
|
|
310
|
+
const currentRotation = page.getRotation().angle;
|
|
311
|
+
page.setRotation((0, pdf_lib_1.degrees)(currentRotation + degreesVal));
|
|
312
|
+
});
|
|
313
|
+
const rotatedPdfBuffer = await pdf.save();
|
|
314
|
+
returnData.push({
|
|
315
|
+
json: items[i].json,
|
|
316
|
+
binary: {
|
|
317
|
+
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(rotatedPdfBuffer), 'rotated.pdf', 'application/pdf'),
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
else if (operation === 'extractText') {
|
|
322
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
323
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
324
|
+
const data = await (0, pdf_parse_1.default)(validBuffer);
|
|
325
|
+
returnData.push({
|
|
326
|
+
json: {
|
|
327
|
+
...items[i].json,
|
|
328
|
+
text: data.text,
|
|
329
|
+
numpages: data.numpages,
|
|
330
|
+
info: data.info,
|
|
331
|
+
},
|
|
332
|
+
binary: items[i].binary,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
else if (operation === 'metadata') {
|
|
336
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
337
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
338
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
339
|
+
returnData.push({
|
|
340
|
+
json: {
|
|
341
|
+
...items[i].json,
|
|
342
|
+
title: pdf.getTitle(),
|
|
343
|
+
author: pdf.getAuthor(),
|
|
344
|
+
subject: pdf.getSubject(),
|
|
345
|
+
creator: pdf.getCreator(),
|
|
346
|
+
producer: pdf.getProducer(),
|
|
347
|
+
keywords: pdf.getKeywords(),
|
|
348
|
+
pageCount: pdf.getPageCount(),
|
|
349
|
+
creationDate: pdf.getCreationDate(),
|
|
350
|
+
modificationDate: pdf.getModificationDate(),
|
|
351
|
+
},
|
|
352
|
+
binary: items[i].binary,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
if (this.continueOnFail()) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return [returnData];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
exports.PdfBro = PdfBro;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-pdfbro",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Offline PDF utility node for n8n",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node"
|
|
7
7
|
],
|
|
8
8
|
"n8n": {
|
|
9
9
|
"nodes": [
|
|
10
|
-
"dist/nodes/
|
|
10
|
+
"dist/nodes/PdfBro/PdfBro.node.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
@@ -25,11 +25,16 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"html-to-pdfmake": "^2.5.32",
|
|
29
|
+
"jsdom": "^27.3.0",
|
|
28
30
|
"pdf-lib": "^1.17.1",
|
|
29
|
-
"pdf-parse": "^1.1.1"
|
|
31
|
+
"pdf-parse": "^1.1.1",
|
|
32
|
+
"pdfmake": "^0.2.21"
|
|
30
33
|
},
|
|
31
34
|
"devDependencies": {
|
|
35
|
+
"@types/jsdom": "^27.0.0",
|
|
32
36
|
"@types/node": "^16.0.0",
|
|
37
|
+
"@types/pdfmake": "^0.2.12",
|
|
33
38
|
"copyfiles": "^2.4.1",
|
|
34
39
|
"n8n-workflow": "*",
|
|
35
40
|
"typescript": "^5.0.0"
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PdfBro = void 0;
|
|
7
|
-
const pdf_lib_1 = require("pdf-lib");
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
const pdf_parse_1 = __importDefault(require("pdf-parse"));
|
|
10
|
-
class PdfBro {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.description = {
|
|
13
|
-
displayName: 'PdfBro',
|
|
14
|
-
name: 'pdfBro',
|
|
15
|
-
icon: 'file:pdfUtils.svg',
|
|
16
|
-
group: ['transform'],
|
|
17
|
-
version: 1,
|
|
18
|
-
description: 'The ultimate PDF utility (powered by pdf-lib & pdf-parse)',
|
|
19
|
-
defaults: {
|
|
20
|
-
name: 'PdfBro',
|
|
21
|
-
},
|
|
22
|
-
inputs: ['main'],
|
|
23
|
-
outputs: ['main'],
|
|
24
|
-
properties: [
|
|
25
|
-
{
|
|
26
|
-
displayName: 'Operation',
|
|
27
|
-
name: 'operation',
|
|
28
|
-
type: 'options',
|
|
29
|
-
noDataExpression: true,
|
|
30
|
-
options: [
|
|
31
|
-
{
|
|
32
|
-
name: 'Merge PDFs',
|
|
33
|
-
value: 'merge',
|
|
34
|
-
description: 'Merge multiple PDF items into a single PDF',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: 'Split Pages',
|
|
38
|
-
value: 'split',
|
|
39
|
-
description: 'Split a PDF into separate pages',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Extract Text',
|
|
43
|
-
value: 'extractText',
|
|
44
|
-
description: 'Extract text content from PDF',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: 'Extract Metadata',
|
|
48
|
-
value: 'metadata',
|
|
49
|
-
description: 'Get PDF metadata (title, author, pages)',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: 'Rotate Pages',
|
|
53
|
-
value: 'rotate',
|
|
54
|
-
description: 'Rotate all pages in a PDF',
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
default: 'merge',
|
|
58
|
-
},
|
|
59
|
-
/*
|
|
60
|
-
displayName: 'Input Binary Field',
|
|
61
|
-
name: 'binaryPropertyName',
|
|
62
|
-
type: 'string',
|
|
63
|
-
default: 'data',
|
|
64
|
-
required: true,
|
|
65
|
-
description: 'The name of the binary field containing the PDF',
|
|
66
|
-
*/
|
|
67
|
-
// Replaced with fixedCollection for merge, simple string for others
|
|
68
|
-
{
|
|
69
|
-
displayName: 'Input Binary Fields',
|
|
70
|
-
name: 'binaryProperties',
|
|
71
|
-
type: 'fixedCollection',
|
|
72
|
-
typeOptions: {
|
|
73
|
-
multipleValues: true,
|
|
74
|
-
},
|
|
75
|
-
displayOptions: {
|
|
76
|
-
show: {
|
|
77
|
-
operation: ['merge'],
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
default: {},
|
|
81
|
-
options: [
|
|
82
|
-
{
|
|
83
|
-
name: 'properties',
|
|
84
|
-
displayName: 'Binary Property',
|
|
85
|
-
values: [
|
|
86
|
-
{
|
|
87
|
-
displayName: 'Property Name',
|
|
88
|
-
name: 'property',
|
|
89
|
-
type: 'string',
|
|
90
|
-
default: 'data',
|
|
91
|
-
description: 'Name of the binary property to merge',
|
|
92
|
-
},
|
|
93
|
-
],
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
description: 'Add more binary properties to merge (e.g. data2, attachment_1)',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
displayName: 'Input Binary Field',
|
|
100
|
-
name: 'binaryPropertyName',
|
|
101
|
-
type: 'string',
|
|
102
|
-
default: 'data',
|
|
103
|
-
required: true,
|
|
104
|
-
description: 'The name of the binary field containing the PDF',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
displayName: 'Output Binary Field',
|
|
108
|
-
name: 'outputPropertyName',
|
|
109
|
-
type: 'string',
|
|
110
|
-
default: 'merged',
|
|
111
|
-
required: true,
|
|
112
|
-
displayOptions: {
|
|
113
|
-
show: {
|
|
114
|
-
operation: ['merge'],
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
description: 'The name of the binary field to put the merged PDF in',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
displayName: 'Rotation Degrees',
|
|
121
|
-
name: 'rotationDegrees',
|
|
122
|
-
type: 'number',
|
|
123
|
-
default: 90,
|
|
124
|
-
displayOptions: {
|
|
125
|
-
show: {
|
|
126
|
-
operation: ['rotate'],
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
description: 'Clockwise rotation (e.g. 90, 180, 270)',
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
async execute() {
|
|
135
|
-
const items = this.getInputData();
|
|
136
|
-
const returnData = [];
|
|
137
|
-
const operation = this.getNodeParameter('operation', 0);
|
|
138
|
-
if (operation === 'merge') {
|
|
139
|
-
// Merge multiple binary properties FROM ALL ITEMS into ONE SINGLE PDF
|
|
140
|
-
const outputPropertyName = this.getNodeParameter('outputPropertyName', 0);
|
|
141
|
-
// Default primary property
|
|
142
|
-
const primaryBinaryProp = this.getNodeParameter('binaryPropertyName', 0);
|
|
143
|
-
const mergedPdf = await pdf_lib_1.PDFDocument.create();
|
|
144
|
-
for (let i = 0; i < items.length; i++) {
|
|
145
|
-
try {
|
|
146
|
-
const binaryProps = this.getNodeParameter('binaryProperties', i);
|
|
147
|
-
let propsToMerge = [];
|
|
148
|
-
if (binaryProps && binaryProps.properties) {
|
|
149
|
-
propsToMerge = binaryProps.properties.map((p) => p.property);
|
|
150
|
-
}
|
|
151
|
-
// Fallback: If no ADDITIONAL properties specified, use the PRIMARY one.
|
|
152
|
-
// Also, IF properties ARE specified, do we include the primary one?
|
|
153
|
-
// UX Decision: If user specified explicit list, they likely want just that list.
|
|
154
|
-
// BUT, to keep it simple: If list is empty, use primary.
|
|
155
|
-
if (propsToMerge.length === 0) {
|
|
156
|
-
propsToMerge.push(primaryBinaryProp);
|
|
157
|
-
}
|
|
158
|
-
for (const propName of propsToMerge) {
|
|
159
|
-
// Check if binary data exists
|
|
160
|
-
if (!items[i].binary || !items[i].binary[propName]) {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, propName);
|
|
164
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
165
|
-
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
166
|
-
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
if (this.continueOnFail()) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
throw error;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (mergedPdf.getPageCount() === 0) {
|
|
177
|
-
throw new Error('No PDF pages found to merge! Please check your input binary fields.');
|
|
178
|
-
}
|
|
179
|
-
// Return single item
|
|
180
|
-
const mergedPdfBuffer = await mergedPdf.save();
|
|
181
|
-
// Use the first item's JSON as a base, or empty if no items
|
|
182
|
-
const jsonOutput = items.length > 0 ? items[0].json : {};
|
|
183
|
-
const binaryOutput = items.length > 0 && items[0].binary ? items[0].binary : {};
|
|
184
|
-
returnData.push({
|
|
185
|
-
json: { ...jsonOutput, success: true, pageCount: mergedPdf.getPageCount() },
|
|
186
|
-
binary: {
|
|
187
|
-
...binaryOutput,
|
|
188
|
-
[outputPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(mergedPdfBuffer), 'merged.pdf', 'application/pdf'),
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// For other operations, get the single binaryPropertyName
|
|
194
|
-
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
|
|
195
|
-
if (operation === 'split') {
|
|
196
|
-
// Split each input PDF into single pages
|
|
197
|
-
for (let i = 0; i < items.length; i++) {
|
|
198
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
199
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
200
|
-
const numberOfPages = pdf.getPageCount();
|
|
201
|
-
for (let j = 0; j < numberOfPages; j++) {
|
|
202
|
-
const newPdf = await pdf_lib_1.PDFDocument.create();
|
|
203
|
-
const [copiedPage] = await newPdf.copyPages(pdf, [j]);
|
|
204
|
-
newPdf.addPage(copiedPage);
|
|
205
|
-
const newPdfBuffer = await newPdf.save();
|
|
206
|
-
returnData.push({
|
|
207
|
-
json: { ...items[i].json, pageNumber: j + 1, totalPages: numberOfPages },
|
|
208
|
-
binary: {
|
|
209
|
-
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), `page_${j + 1}.pdf`, 'application/pdf'),
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
else if (operation === 'rotate') {
|
|
216
|
-
const degreesVal = this.getNodeParameter('rotationDegrees', 0);
|
|
217
|
-
for (let i = 0; i < items.length; i++) {
|
|
218
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
219
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
220
|
-
const pages = pdf.getPages();
|
|
221
|
-
pages.forEach(page => {
|
|
222
|
-
const currentRotation = page.getRotation().angle;
|
|
223
|
-
page.setRotation((0, pdf_lib_1.degrees)(currentRotation + degreesVal));
|
|
224
|
-
});
|
|
225
|
-
const rotatedPdfBuffer = await pdf.save();
|
|
226
|
-
returnData.push({
|
|
227
|
-
json: items[i].json,
|
|
228
|
-
binary: {
|
|
229
|
-
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(rotatedPdfBuffer), 'rotated.pdf', 'application/pdf'),
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
else if (operation === 'extractText') {
|
|
235
|
-
for (let i = 0; i < items.length; i++) {
|
|
236
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
237
|
-
const data = await (0, pdf_parse_1.default)(validBuffer);
|
|
238
|
-
returnData.push({
|
|
239
|
-
json: {
|
|
240
|
-
...items[i].json,
|
|
241
|
-
text: data.text,
|
|
242
|
-
numpages: data.numpages,
|
|
243
|
-
info: data.info,
|
|
244
|
-
},
|
|
245
|
-
binary: items[i].binary,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
else if (operation === 'metadata') {
|
|
250
|
-
for (let i = 0; i < items.length; i++) {
|
|
251
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
252
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
253
|
-
returnData.push({
|
|
254
|
-
json: {
|
|
255
|
-
...items[i].json,
|
|
256
|
-
title: pdf.getTitle(),
|
|
257
|
-
author: pdf.getAuthor(),
|
|
258
|
-
subject: pdf.getSubject(),
|
|
259
|
-
creator: pdf.getCreator(),
|
|
260
|
-
producer: pdf.getProducer(),
|
|
261
|
-
keywords: pdf.getKeywords(),
|
|
262
|
-
pageCount: pdf.getPageCount(),
|
|
263
|
-
creationDate: pdf.getCreationDate(),
|
|
264
|
-
modificationDate: pdf.getModificationDate(),
|
|
265
|
-
},
|
|
266
|
-
binary: items[i].binary,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return [returnData];
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
exports.PdfBro = PdfBro;
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PdfUtils = void 0;
|
|
7
|
-
const pdf_lib_1 = require("pdf-lib");
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
const pdf_parse_1 = __importDefault(require("pdf-parse"));
|
|
10
|
-
class PdfUtils {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.description = {
|
|
13
|
-
displayName: 'PDF Utils',
|
|
14
|
-
name: 'pdfUtils',
|
|
15
|
-
icon: 'file:pdfUtils.svg',
|
|
16
|
-
group: ['transform'],
|
|
17
|
-
version: 1,
|
|
18
|
-
description: 'Offline PDF operations',
|
|
19
|
-
defaults: {
|
|
20
|
-
name: 'PDF Utils',
|
|
21
|
-
},
|
|
22
|
-
inputs: ['main'],
|
|
23
|
-
outputs: ['main'],
|
|
24
|
-
properties: [
|
|
25
|
-
{
|
|
26
|
-
displayName: 'Operation',
|
|
27
|
-
name: 'operation',
|
|
28
|
-
type: 'options',
|
|
29
|
-
noDataExpression: true,
|
|
30
|
-
options: [
|
|
31
|
-
{
|
|
32
|
-
name: 'Merge PDFs',
|
|
33
|
-
value: 'merge',
|
|
34
|
-
description: 'Merge multiple PDF items into a single PDF',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: 'Split Pages',
|
|
38
|
-
value: 'split',
|
|
39
|
-
description: 'Split a PDF into separate pages',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Extract Text',
|
|
43
|
-
value: 'extractText',
|
|
44
|
-
description: 'Extract text content from PDF',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: 'Extract Metadata',
|
|
48
|
-
value: 'metadata',
|
|
49
|
-
description: 'Get PDF metadata (title, author, pages)',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: 'Rotate Pages',
|
|
53
|
-
value: 'rotate',
|
|
54
|
-
description: 'Rotate all pages in a PDF',
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
default: 'merge',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
displayName: 'Input Binary Field',
|
|
61
|
-
name: 'binaryPropertyName',
|
|
62
|
-
type: 'string',
|
|
63
|
-
default: 'data',
|
|
64
|
-
required: true,
|
|
65
|
-
description: 'The name of the binary field containing the PDF',
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
displayName: 'Rotation Degrees',
|
|
69
|
-
name: 'rotationDegrees',
|
|
70
|
-
type: 'number',
|
|
71
|
-
default: 90,
|
|
72
|
-
displayOptions: {
|
|
73
|
-
show: {
|
|
74
|
-
operation: ['rotate'],
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
description: 'Clockwise rotation (e.g. 90, 180, 270)',
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
async execute() {
|
|
83
|
-
const items = this.getInputData();
|
|
84
|
-
const returnData = [];
|
|
85
|
-
const operation = this.getNodeParameter('operation', 0);
|
|
86
|
-
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
|
|
87
|
-
if (operation === 'merge') {
|
|
88
|
-
// Merge all inputs into one PDF
|
|
89
|
-
const mergedPdf = await pdf_lib_1.PDFDocument.create();
|
|
90
|
-
for (let i = 0; i < items.length; i++) {
|
|
91
|
-
try {
|
|
92
|
-
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
|
93
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
94
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
95
|
-
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
96
|
-
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
if (this.continueOnFail()) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
throw error;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const mergedPdfBuffer = await mergedPdf.save();
|
|
106
|
-
returnData.push({
|
|
107
|
-
json: { success: true, pageCount: mergedPdf.getPageCount() },
|
|
108
|
-
binary: {
|
|
109
|
-
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(mergedPdfBuffer), 'merged.pdf', 'application/pdf'),
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
else if (operation === 'split') {
|
|
114
|
-
// Split each input PDF into single pages
|
|
115
|
-
for (let i = 0; i < items.length; i++) {
|
|
116
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
117
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
118
|
-
const numberOfPages = pdf.getPageCount();
|
|
119
|
-
for (let j = 0; j < numberOfPages; j++) {
|
|
120
|
-
const newPdf = await pdf_lib_1.PDFDocument.create();
|
|
121
|
-
const [copiedPage] = await newPdf.copyPages(pdf, [j]);
|
|
122
|
-
newPdf.addPage(copiedPage);
|
|
123
|
-
const newPdfBuffer = await newPdf.save();
|
|
124
|
-
returnData.push({
|
|
125
|
-
json: { ...items[i].json, pageNumber: j + 1, totalPages: numberOfPages },
|
|
126
|
-
binary: {
|
|
127
|
-
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), `page_${j + 1}.pdf`, 'application/pdf'),
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else if (operation === 'rotate') {
|
|
134
|
-
const degreesVal = this.getNodeParameter('rotationDegrees', 0);
|
|
135
|
-
for (let i = 0; i < items.length; i++) {
|
|
136
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
137
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
138
|
-
const pages = pdf.getPages();
|
|
139
|
-
pages.forEach(page => {
|
|
140
|
-
const currentRotation = page.getRotation().angle;
|
|
141
|
-
page.setRotation((0, pdf_lib_1.degrees)(currentRotation + degreesVal));
|
|
142
|
-
});
|
|
143
|
-
const rotatedPdfBuffer = await pdf.save();
|
|
144
|
-
returnData.push({
|
|
145
|
-
json: items[i].json,
|
|
146
|
-
binary: {
|
|
147
|
-
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(rotatedPdfBuffer), 'rotated.pdf', 'application/pdf'),
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else if (operation === 'extractText') {
|
|
153
|
-
for (let i = 0; i < items.length; i++) {
|
|
154
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
155
|
-
const data = await (0, pdf_parse_1.default)(validBuffer);
|
|
156
|
-
returnData.push({
|
|
157
|
-
json: {
|
|
158
|
-
...items[i].json,
|
|
159
|
-
text: data.text,
|
|
160
|
-
numpages: data.numpages,
|
|
161
|
-
info: data.info,
|
|
162
|
-
},
|
|
163
|
-
binary: items[i].binary,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else if (operation === 'metadata') {
|
|
168
|
-
for (let i = 0; i < items.length; i++) {
|
|
169
|
-
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
170
|
-
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
171
|
-
returnData.push({
|
|
172
|
-
json: {
|
|
173
|
-
...items[i].json,
|
|
174
|
-
title: pdf.getTitle(),
|
|
175
|
-
author: pdf.getAuthor(),
|
|
176
|
-
subject: pdf.getSubject(),
|
|
177
|
-
creator: pdf.getCreator(),
|
|
178
|
-
producer: pdf.getProducer(),
|
|
179
|
-
keywords: pdf.getKeywords(),
|
|
180
|
-
pageCount: pdf.getPageCount(),
|
|
181
|
-
creationDate: pdf.getCreationDate(),
|
|
182
|
-
modificationDate: pdf.getModificationDate(),
|
|
183
|
-
},
|
|
184
|
-
binary: items[i].binary,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return [returnData];
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
exports.PdfUtils = PdfUtils;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ff0000" width="24px" height="24px"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8.5 7.5c0 .83-.67 1.5-1.5 1.5H9v2H7.5V7H10c.83 0 1.5.67 1.5 1.5v1zm5 2c0 .83-.67 1.5-1.5 1.5h-2.5V7H15c.83 0 1.5.67 1.5 1.5v3zm4-3H19v1h1.5V11H19v2h-1.5V7h3v1.5zM9 9.5h1v-1H9v1zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm10 5.5h1v-3h-1v3z"/></svg>
|
|
File without changes
|