n8n-nodes-pdfbro 0.1.6 → 0.1.8

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 CHANGED
@@ -30,19 +30,28 @@ npm install n8n-nodes-pdfbro
30
30
  ## Operations
31
31
 
32
32
  ### Merge PDFs
33
- Merges all input items containing PDF binary data into a single output item with the merged PDF.
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
- Splits a PDF into multiple items, one per page.
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 and adds it to the JSON output.
48
+ Extracts all text from the PDF.
40
49
 
41
50
  ### Extract Metadata
42
- Adds PDF metadata (Title, Author, Creation Date, etc.) to the JSON output.
51
+ Gets title, author, creation date, etc.
43
52
 
44
53
  ### Rotate Pages
45
- Rotates all pages in the PDF by the specified degrees (default 90).
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!
@@ -7,6 +7,17 @@ exports.PdfBro = void 0;
7
7
  const pdf_lib_1 = require("pdf-lib");
8
8
  // @ts-ignore
9
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;
10
21
  class PdfBro {
11
22
  constructor() {
12
23
  this.description = {
@@ -31,12 +42,17 @@ class PdfBro {
31
42
  {
32
43
  name: 'Merge PDFs',
33
44
  value: 'merge',
34
- description: 'Merge multiple PDF items into a single PDF',
45
+ description: 'Merge multiple binary fields into a single PDF',
35
46
  },
36
47
  {
37
48
  name: 'Split Pages',
38
49
  value: 'split',
39
- description: 'Split a PDF into separate pages',
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',
40
56
  },
41
57
  {
42
58
  name: 'Extract Text',
@@ -56,18 +72,11 @@ class PdfBro {
56
72
  ],
57
73
  default: 'merge',
58
74
  },
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
75
+ // MERGE Operations: Multiple Inputs
68
76
  {
69
- displayName: 'Input Binary Fields',
70
- name: 'binaryProperties',
77
+ displayName: 'Input PDF Files',
78
+ name: 'inputBinaries',
79
+ placeholder: 'Add PDF Input',
71
80
  type: 'fixedCollection',
72
81
  typeOptions: {
73
82
  multipleValues: true,
@@ -80,21 +89,21 @@ class PdfBro {
80
89
  default: {},
81
90
  options: [
82
91
  {
83
- name: 'properties',
84
- displayName: 'Binary Property',
92
+ name: 'files',
93
+ displayName: 'Files',
85
94
  values: [
86
95
  {
87
- displayName: 'Property Name',
88
- name: 'property',
96
+ displayName: 'Binary Property',
97
+ name: 'binaryPropertyName',
89
98
  type: 'string',
90
99
  default: 'data',
91
- description: 'Name of the binary property to merge',
100
+ description: 'Name of the binary property containing the PDF to merge',
92
101
  },
93
102
  ],
94
103
  },
95
104
  ],
96
- description: 'List of binary properties to merge (in order)',
97
105
  },
106
+ // Common input for single-file operations
98
107
  {
99
108
  displayName: 'Input Binary Field',
100
109
  name: 'binaryPropertyName',
@@ -102,25 +111,42 @@ class PdfBro {
102
111
  default: 'data',
103
112
  required: true,
104
113
  displayOptions: {
105
- hide: {
106
- operation: ['merge'],
114
+ show: {
115
+ operation: ['split', 'extractText', 'metadata', 'rotate'],
107
116
  },
108
117
  },
109
118
  description: 'The name of the binary field containing the PDF',
110
119
  },
120
+ // SPLIT Operations
111
121
  {
112
- displayName: 'Output Binary Field',
113
- name: 'outputPropertyName',
122
+ displayName: 'Split Range',
123
+ name: 'splitRange',
114
124
  type: 'string',
115
- default: 'merged',
116
- required: true,
125
+ default: '*',
117
126
  displayOptions: {
118
127
  show: {
119
- operation: ['merge'],
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'],
120
145
  },
121
146
  },
122
- description: 'The name of the binary field to put the merged PDF in',
147
+ description: 'The HTML content to convert to PDF',
123
148
  },
149
+ // ROTATE Operations
124
150
  {
125
151
  displayName: 'Rotation Degrees',
126
152
  name: 'rotationDegrees',
@@ -137,84 +163,146 @@ class PdfBro {
137
163
  };
138
164
  }
139
165
  async execute() {
166
+ var _a;
140
167
  const items = this.getInputData();
141
168
  const returnData = [];
142
169
  const operation = this.getNodeParameter('operation', 0);
143
- if (operation === 'merge') {
144
- // Merge multiple binary properties FROM ALL ITEMS into ONE SINGLE PDF
145
- const outputPropertyName = this.getNodeParameter('outputPropertyName', 0);
146
- const mergedPdf = await pdf_lib_1.PDFDocument.create();
147
- for (let i = 0; i < items.length; i++) {
148
- try {
149
- const binaryProps = this.getNodeParameter('binaryProperties', i);
150
- let propsToMerge = [];
151
- if (binaryProps && binaryProps.properties) {
152
- propsToMerge = binaryProps.properties.map((p) => p.property);
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;
153
190
  }
154
- // Fallback: If no properties specified, try 'data' default
155
- if (propsToMerge.length === 0) {
156
- propsToMerge.push('data');
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);
157
203
  }
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));
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);
167
211
  }
168
212
  }
169
- catch (error) {
170
- if (this.continueOnFail()) {
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)
171
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
+ }
172
234
  }
173
- throw error;
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
+ });
174
242
  }
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++) {
243
+ else if (operation === 'split') {
244
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
245
+ const rangeStr = this.getNodeParameter('splitRange', i);
198
246
  const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
199
247
  const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
200
- const numberOfPages = pdf.getPageCount();
201
- for (let j = 0; j < numberOfPages; j++) {
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".
202
270
  const newPdf = await pdf_lib_1.PDFDocument.create();
203
- const [copiedPage] = await newPdf.copyPages(pdf, [j]);
204
- newPdf.addPage(copiedPage);
271
+ const copiedPages = await newPdf.copyPages(pdf, indicesToKeep);
272
+ copiedPages.forEach(p => newPdf.addPage(p));
205
273
  const newPdfBuffer = await newPdf.save();
206
274
  returnData.push({
207
- json: { ...items[i].json, pageNumber: j + 1, totalPages: numberOfPages },
275
+ json: { ...items[i].json, extractedPages: indicesToKeep.map(p => p + 1).join(', ') },
208
276
  binary: {
209
- [binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), `page_${j + 1}.pdf`, 'application/pdf'),
277
+ data: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), 'extracted.pdf', 'application/pdf'),
210
278
  },
211
279
  });
212
280
  }
213
281
  }
214
- }
215
- else if (operation === 'rotate') {
216
- const degreesVal = this.getNodeParameter('rotationDegrees', 0);
217
- for (let i = 0; i < items.length; i++) {
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);
218
306
  const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
219
307
  const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
220
308
  const pages = pdf.getPages();
@@ -230,9 +318,8 @@ class PdfBro {
230
318
  },
231
319
  });
232
320
  }
233
- }
234
- else if (operation === 'extractText') {
235
- for (let i = 0; i < items.length; i++) {
321
+ else if (operation === 'extractText') {
322
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
236
323
  const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
237
324
  const data = await (0, pdf_parse_1.default)(validBuffer);
238
325
  returnData.push({
@@ -245,9 +332,8 @@ class PdfBro {
245
332
  binary: items[i].binary,
246
333
  });
247
334
  }
248
- }
249
- else if (operation === 'metadata') {
250
- for (let i = 0; i < items.length; i++) {
335
+ else if (operation === 'metadata') {
336
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
251
337
  const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
252
338
  const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
253
339
  returnData.push({
@@ -267,6 +353,12 @@ class PdfBro {
267
353
  });
268
354
  }
269
355
  }
356
+ catch (error) {
357
+ if (this.continueOnFail()) {
358
+ continue;
359
+ }
360
+ throw error;
361
+ }
270
362
  }
271
363
  return [returnData];
272
364
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-pdfbro",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Offline PDF utility node for n8n",
5
5
  "keywords": [
6
6
  "n8n-community-node"
@@ -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 +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>
@@ -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;