n8n-nodes-pdfbro 0.1.2 → 0.1.5
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 +9 -0
- package/dist/index.js +2 -2
- package/dist/nodes/PdfUtils/PdfBro.node.js +266 -0
- package/dist/nodes/PdfUtils/pdfUtils.svg +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -47,3 +47,12 @@ Rotates all pages in the PDF by the specified degrees (default 90).
|
|
|
47
47
|
## License
|
|
48
48
|
|
|
49
49
|
MIT
|
|
50
|
+
|
|
51
|
+
## Credits & Attribution
|
|
52
|
+
|
|
53
|
+
This node powers its PDF magic using these awesome open-source libraries:
|
|
54
|
+
|
|
55
|
+
* **[pdf-lib](https://github.com/Hopding/pdf-lib)** (MIT License) - PDF creation and modification.
|
|
56
|
+
* **[pdf-parse](https://gitlab.com/autokent/pdf-parse)** (MIT License) - PDF text extraction.
|
|
57
|
+
|
|
58
|
+
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
|
|
5
|
-
exports.nodes = [
|
|
4
|
+
const PdfBro_node_1 = require("./nodes/PdfUtils/PdfBro.node");
|
|
5
|
+
exports.nodes = [PdfBro_node_1.PdfBro];
|
|
@@ -0,0 +1,266 @@
|
|
|
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: 'List of binary properties to merge (in order)',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
displayName: 'Input Binary Field',
|
|
100
|
+
name: 'binaryPropertyName',
|
|
101
|
+
type: 'string',
|
|
102
|
+
default: 'data',
|
|
103
|
+
required: true,
|
|
104
|
+
displayOptions: {
|
|
105
|
+
hide: {
|
|
106
|
+
operation: ['merge'],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
description: 'The name of the binary field containing the PDF',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
displayName: 'Output Binary Field',
|
|
113
|
+
name: 'outputPropertyName',
|
|
114
|
+
type: 'string',
|
|
115
|
+
default: 'merged',
|
|
116
|
+
required: true,
|
|
117
|
+
displayOptions: {
|
|
118
|
+
show: {
|
|
119
|
+
operation: ['merge'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
description: 'The name of the binary field to put the merged PDF in',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
displayName: 'Rotation Degrees',
|
|
126
|
+
name: 'rotationDegrees',
|
|
127
|
+
type: 'number',
|
|
128
|
+
default: 90,
|
|
129
|
+
displayOptions: {
|
|
130
|
+
show: {
|
|
131
|
+
operation: ['rotate'],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
description: 'Clockwise rotation (e.g. 90, 180, 270)',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async execute() {
|
|
140
|
+
const items = this.getInputData();
|
|
141
|
+
const returnData = [];
|
|
142
|
+
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
|
+
if (binaryProps && binaryProps.properties) {
|
|
151
|
+
for (const propItem of binaryProps.properties) {
|
|
152
|
+
const propName = propItem.property;
|
|
153
|
+
// Check if binary data exists
|
|
154
|
+
if (!items[i].binary || !items[i].binary[propName]) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, propName);
|
|
158
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
159
|
+
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
160
|
+
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (this.continueOnFail()) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Return single item
|
|
172
|
+
const mergedPdfBuffer = await mergedPdf.save();
|
|
173
|
+
// Use the first item's JSON as a base, or empty if no items
|
|
174
|
+
const jsonOutput = items.length > 0 ? items[0].json : {};
|
|
175
|
+
const binaryOutput = items.length > 0 && items[0].binary ? items[0].binary : {};
|
|
176
|
+
returnData.push({
|
|
177
|
+
json: { ...jsonOutput, success: true, pageCount: mergedPdf.getPageCount() },
|
|
178
|
+
binary: {
|
|
179
|
+
...binaryOutput,
|
|
180
|
+
[outputPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(mergedPdfBuffer), 'merged.pdf', 'application/pdf'),
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// For other operations, get the single binaryPropertyName
|
|
186
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
|
|
187
|
+
if (operation === 'split') {
|
|
188
|
+
// Split each input PDF into single pages
|
|
189
|
+
for (let i = 0; i < items.length; i++) {
|
|
190
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
191
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
192
|
+
const numberOfPages = pdf.getPageCount();
|
|
193
|
+
for (let j = 0; j < numberOfPages; j++) {
|
|
194
|
+
const newPdf = await pdf_lib_1.PDFDocument.create();
|
|
195
|
+
const [copiedPage] = await newPdf.copyPages(pdf, [j]);
|
|
196
|
+
newPdf.addPage(copiedPage);
|
|
197
|
+
const newPdfBuffer = await newPdf.save();
|
|
198
|
+
returnData.push({
|
|
199
|
+
json: { ...items[i].json, pageNumber: j + 1, totalPages: numberOfPages },
|
|
200
|
+
binary: {
|
|
201
|
+
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(newPdfBuffer), `page_${j + 1}.pdf`, 'application/pdf'),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (operation === 'rotate') {
|
|
208
|
+
const degreesVal = this.getNodeParameter('rotationDegrees', 0);
|
|
209
|
+
for (let i = 0; i < items.length; i++) {
|
|
210
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
211
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
212
|
+
const pages = pdf.getPages();
|
|
213
|
+
pages.forEach(page => {
|
|
214
|
+
const currentRotation = page.getRotation().angle;
|
|
215
|
+
page.setRotation((0, pdf_lib_1.degrees)(currentRotation + degreesVal));
|
|
216
|
+
});
|
|
217
|
+
const rotatedPdfBuffer = await pdf.save();
|
|
218
|
+
returnData.push({
|
|
219
|
+
json: items[i].json,
|
|
220
|
+
binary: {
|
|
221
|
+
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(rotatedPdfBuffer), 'rotated.pdf', 'application/pdf'),
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else if (operation === 'extractText') {
|
|
227
|
+
for (let i = 0; i < items.length; i++) {
|
|
228
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
229
|
+
const data = await (0, pdf_parse_1.default)(validBuffer);
|
|
230
|
+
returnData.push({
|
|
231
|
+
json: {
|
|
232
|
+
...items[i].json,
|
|
233
|
+
text: data.text,
|
|
234
|
+
numpages: data.numpages,
|
|
235
|
+
info: data.info,
|
|
236
|
+
},
|
|
237
|
+
binary: items[i].binary,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else if (operation === 'metadata') {
|
|
242
|
+
for (let i = 0; i < items.length; i++) {
|
|
243
|
+
const validBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
244
|
+
const pdf = await pdf_lib_1.PDFDocument.load(validBuffer);
|
|
245
|
+
returnData.push({
|
|
246
|
+
json: {
|
|
247
|
+
...items[i].json,
|
|
248
|
+
title: pdf.getTitle(),
|
|
249
|
+
author: pdf.getAuthor(),
|
|
250
|
+
subject: pdf.getSubject(),
|
|
251
|
+
creator: pdf.getCreator(),
|
|
252
|
+
producer: pdf.getProducer(),
|
|
253
|
+
keywords: pdf.getKeywords(),
|
|
254
|
+
pageCount: pdf.getPageCount(),
|
|
255
|
+
creationDate: pdf.getCreationDate(),
|
|
256
|
+
modificationDate: pdf.getModificationDate(),
|
|
257
|
+
},
|
|
258
|
+
binary: items[i].binary,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return [returnData];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
exports.PdfBro = PdfBro;
|
|
@@ -0,0 +1 @@
|
|
|
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>
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-pdfbro",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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/PdfUtils/
|
|
10
|
+
"dist/nodes/PdfUtils/PdfBro.node.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"main": "dist/index.js",
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsc && copyfiles -u 1 nodes/**/*.svg dist",
|
|
21
|
+
"build": "tsc && copyfiles -u 1 nodes/**/*.svg dist/nodes",
|
|
22
22
|
"dev": "tsc --watch"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|