@aaqu/node-red-aaqu-pdf 0.4.1 → 0.4.3

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
@@ -4,6 +4,8 @@ Your support in the ongoing development of this library would be sincerely appre
4
4
 
5
5
  [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%23FFDD00?style=for-the-badge&logo=buymeacoffee&logoColor=black)](https://buymeacoffee.com/mazuralbert)
6
6
 
7
+ _**The library requires testing and monitoring of RAM usage.**_
8
+
7
9
  # @aaqu/node-red-aaqu-pdf
8
10
 
9
11
  A [Node-RED](https://nodered.org/) node for operating on a PDF document.
@@ -20,15 +22,17 @@ Display page in flow - need [node-red-contrib-image-tools](https://flows.nodered
20
22
 
21
23
  ![example2.png](img/example2.png)
22
24
 
25
+ Create empty PDF and draw text
26
+
27
+ ![create-pdf-draw-text.png](img/create-pdf-draw-text.png)
28
+
23
29
  ---
24
30
 
25
31
  ## Features
26
32
 
27
- - Accepts a PDF document as a `Buffer` in `msg.payload`.
28
- - Page number can be set either in the **node configuration** or dynamically via `msg.pdfPage`.
29
- - Outputs a new `Buffer` containing a PDF with only the selected page.
30
- - Simple integration with existing Node-RED flows.
31
- - Convert pdf page to base64
33
+ - Create empty PDF and draw text
34
+ - Select a single page from pdf to buffer
35
+ - Convert PDF page buffer to base64 image
32
36
 
33
37
  ---
34
38
 
@@ -44,43 +48,63 @@ Then restart Node-RED and the new node will appear in the editor palette.
44
48
 
45
49
  ---
46
50
 
47
- ## Nodes
48
- _pdf-get-page_
51
+ ## Nodes usage
52
+ #### pdf get page
49
53
 
50
54
  ![node-pdf-get-page.png](img/node-pdf-get-page.png)
55
+
51
56
  - **msg.payload** - pdf buffer
52
57
  - **msg.pdfPage** – optional runtime override for the page number (starting at `1`).
53
58
 
54
- _pdf-to-img_
55
-
56
- ![node-pdf-to-img.png](img/node-pdf-to-img.png)
57
- - **msg.payload** - pdf buffer input
58
- ---
59
-
60
- ## Usage
61
-
62
- _**pdf-get-page**_
63
-
64
59
  ```text
65
- [pdf multi page buffer] → [pdf-get-page] → [pdf single page buffer]
60
+ pdf multi page buffer → [pdf get page] → pdf single page buffer
66
61
  ```
67
62
 
68
- Where:
63
+ where:
69
64
  - **pdf multi page buffer** input multi page buffer.
70
- - **pdf-get-page** extracts the configured page (or the page defined in `msg.pdfPage`) default page no 1.
65
+ - **pdf get page** extracts the configured page (or the page defined in `msg.pdfPage`) default page no 1.
71
66
  - **pdf single page buffer** return single page buffer.
72
67
 
73
- _**pdf-to-img**_
68
+
69
+ #### pdf to img
70
+
71
+ ![node-pdf-to-img.png](img/node-pdf-to-img.png)
72
+
73
+ - **msg.payload** - pdf buffer input
74
74
 
75
75
  ```text
76
- [pdf buffer] → [pdf-to-img] → [out base64]
76
+ pdf buffer → [pdf to img] → out base64
77
77
  ```
78
78
 
79
- Where:
80
- - **pdf buffer** a pdf file.
81
- - **aaqu-pdf** extracts the page to image.
79
+ where:
80
+ - **pdf buffer** a pdf file as buffer.
81
+ - **pdf to img** extracts the page to image.
82
82
  - **out base64** return image in base64 (to display use node-red-contrib-image-tools -> viewer).
83
83
 
84
+ #### pdf create
85
+
86
+ ![node-pdf-create.png](img/node-pdf-create.png)
87
+
88
+ create PDF document
89
+
90
+ #### pdf add page
91
+
92
+ ![node-pdf-add-page.png](img/node-pdf-add-page.png)
93
+
94
+ adding a page
95
+
96
+ #### pdf save
97
+
98
+ ![node-pdf-pdf-save.png](img/node-pdf-save.png)
99
+
100
+ buil final PDF
101
+
102
+ #### pdf draw text
103
+
104
+ ![node-pdf-draw-text](img/node-pdf-draw-text.png)
105
+
106
+ add text to page PDF
107
+
84
108
  ---
85
109
 
86
110
  ## Use cases
@@ -0,0 +1,235 @@
1
+ [
2
+ {
3
+ "id": "5e5cbdd3c50fdfa8",
4
+ "type": "pdf-create",
5
+ "z": "8f32c806fc0c3278",
6
+ "name": "",
7
+ "x": 270,
8
+ "y": 80,
9
+ "wires": [
10
+ [
11
+ "b410380ae4540c05"
12
+ ]
13
+ ]
14
+ },
15
+ {
16
+ "id": "0723b41a5ea96294",
17
+ "type": "inject",
18
+ "z": "8f32c806fc0c3278",
19
+ "name": "",
20
+ "props": [],
21
+ "repeat": "",
22
+ "crontab": "",
23
+ "once": false,
24
+ "onceDelay": 0.1,
25
+ "topic": "",
26
+ "x": 110,
27
+ "y": 80,
28
+ "wires": [
29
+ [
30
+ "5e5cbdd3c50fdfa8"
31
+ ]
32
+ ]
33
+ },
34
+ {
35
+ "id": "b410380ae4540c05",
36
+ "type": "pdf-add-page",
37
+ "z": "8f32c806fc0c3278",
38
+ "name": "",
39
+ "width": "595",
40
+ "height": "842",
41
+ "x": 460,
42
+ "y": 80,
43
+ "wires": [
44
+ [
45
+ "017ab61165bbf7ef"
46
+ ]
47
+ ]
48
+ },
49
+ {
50
+ "id": "f707472db673e653",
51
+ "type": "pdf-to-img",
52
+ "z": "8f32c806fc0c3278",
53
+ "name": "",
54
+ "scale": "1",
55
+ "x": 930,
56
+ "y": 340,
57
+ "wires": [
58
+ [
59
+ "6e1a14d70ffeb1ea"
60
+ ]
61
+ ]
62
+ },
63
+ {
64
+ "id": "6e1a14d70ffeb1ea",
65
+ "type": "image viewer",
66
+ "z": "8f32c806fc0c3278",
67
+ "name": "",
68
+ "width": "300",
69
+ "data": "payload",
70
+ "dataType": "msg",
71
+ "active": true,
72
+ "x": 1110,
73
+ "y": 160,
74
+ "wires": [
75
+ []
76
+ ]
77
+ },
78
+ {
79
+ "id": "75a1a683ddc0cfc8",
80
+ "type": "pdf-save",
81
+ "z": "8f32c806fc0c3278",
82
+ "name": "",
83
+ "x": 760,
84
+ "y": 340,
85
+ "wires": [
86
+ [
87
+ "f707472db673e653",
88
+ "d96113d86b0b7eaf"
89
+ ]
90
+ ]
91
+ },
92
+ {
93
+ "id": "017ab61165bbf7ef",
94
+ "type": "pdf-draw-text",
95
+ "z": "8f32c806fc0c3278",
96
+ "name": "",
97
+ "text": "Row 1",
98
+ "font": "CourierBold",
99
+ "fontSize": "70",
100
+ "posX": "50",
101
+ "posY": "600",
102
+ "color": "#000000",
103
+ "x": 570,
104
+ "y": 140,
105
+ "wires": [
106
+ [
107
+ "78d341d93a6f441c"
108
+ ]
109
+ ]
110
+ },
111
+ {
112
+ "id": "78d341d93a6f441c",
113
+ "type": "pdf-draw-text",
114
+ "z": "8f32c806fc0c3278",
115
+ "name": "",
116
+ "text": "Text 2",
117
+ "font": "Helvetica",
118
+ "fontSize": "70",
119
+ "posX": "50",
120
+ "posY": "400",
121
+ "color": "#0e80d8",
122
+ "x": 570,
123
+ "y": 180,
124
+ "wires": [
125
+ [
126
+ "9bd6ce8c8613f691"
127
+ ]
128
+ ]
129
+ },
130
+ {
131
+ "id": "9bd6ce8c8613f691",
132
+ "type": "pdf-draw-text",
133
+ "z": "8f32c806fc0c3278",
134
+ "name": "",
135
+ "text": "Text 3",
136
+ "font": "TimesRomanBoldItalic",
137
+ "fontSize": "30",
138
+ "posX": "50",
139
+ "posY": "200",
140
+ "color": "#0ced1b",
141
+ "x": 570,
142
+ "y": 220,
143
+ "wires": [
144
+ [
145
+ "ce51e629eec17175"
146
+ ]
147
+ ]
148
+ },
149
+ {
150
+ "id": "ce51e629eec17175",
151
+ "type": "pdf-add-page",
152
+ "z": "8f32c806fc0c3278",
153
+ "name": "",
154
+ "width": "595",
155
+ "height": "842",
156
+ "x": 580,
157
+ "y": 280,
158
+ "wires": [
159
+ [
160
+ "3768ee9ea15f60a5"
161
+ ]
162
+ ]
163
+ },
164
+ {
165
+ "id": "7ca03dd7268eeaee",
166
+ "type": "image viewer",
167
+ "z": "8f32c806fc0c3278",
168
+ "name": "",
169
+ "width": "300",
170
+ "data": "payload",
171
+ "dataType": "msg",
172
+ "active": true,
173
+ "x": 1110,
174
+ "y": 660,
175
+ "wires": [
176
+ []
177
+ ]
178
+ },
179
+ {
180
+ "id": "86be12f733c08523",
181
+ "type": "pdf-to-img",
182
+ "z": "8f32c806fc0c3278",
183
+ "name": "",
184
+ "scale": "1",
185
+ "x": 930,
186
+ "y": 420,
187
+ "wires": [
188
+ [
189
+ "7ca03dd7268eeaee"
190
+ ]
191
+ ]
192
+ },
193
+ {
194
+ "id": "d96113d86b0b7eaf",
195
+ "type": "pdf-get-page",
196
+ "z": "8f32c806fc0c3278",
197
+ "name": "",
198
+ "pdfPage": "2",
199
+ "x": 750,
200
+ "y": 420,
201
+ "wires": [
202
+ [
203
+ "86be12f733c08523"
204
+ ]
205
+ ]
206
+ },
207
+ {
208
+ "id": "3768ee9ea15f60a5",
209
+ "type": "pdf-draw-text",
210
+ "z": "8f32c806fc0c3278",
211
+ "name": "",
212
+ "text": "Text Page 2",
213
+ "font": "Helvetica",
214
+ "fontSize": "100",
215
+ "posX": "50",
216
+ "posY": "400",
217
+ "color": "#ae24e0",
218
+ "x": 570,
219
+ "y": 340,
220
+ "wires": [
221
+ [
222
+ "75a1a683ddc0cfc8"
223
+ ]
224
+ ]
225
+ },
226
+ {
227
+ "id": "698f669ace488a64",
228
+ "type": "global-config",
229
+ "env": [],
230
+ "modules": {
231
+ "@aaqu/node-red-aaqu-pdf": "0.4.2",
232
+ "node-red-contrib-image-tools": "2.1.1"
233
+ }
234
+ }
235
+ ]
package/img.png ADDED
Binary file
@@ -39,11 +39,11 @@
39
39
  </div>
40
40
  <div>Size i pt (A4 595x842)</div>
41
41
  <div class="form-row">
42
- <label for="node-input-width"><i class="fa fa-bookmark"></i>Width</label>
42
+ <label for="node-input-width"><i class="fa fa-bookmark"></i> Width</label>
43
43
  <input type="number" id="node-input-width" />
44
44
  </div>
45
45
  <div class="form-row">
46
- <label for="node-input-height"><i class="fa fa-bookmark"></i>Height</label>
46
+ <label for="node-input-height"><i class="fa fa-bookmark"></i> Height</label>
47
47
  <input type="number" id="node-input-height" />
48
48
  </div>
49
49
  </script>
@@ -1,9 +1,12 @@
1
1
  module.exports = function (RED) {
2
2
  function PDFAddPageNode(config) {
3
3
  RED.nodes.createNode(this, config);
4
+
4
5
  this.width = Number(config.width || 595);
5
6
  this.height = Number(config.height || 842);
7
+
6
8
  const node = this;
9
+
7
10
  node.on("input", function (msg) {
8
11
  try {
9
12
  const page = msg.pdfDoc.addPage([node.width, node.height]);
@@ -3,7 +3,9 @@ const { PDFDocument } = require("pdf-lib");
3
3
  module.exports = function (RED) {
4
4
  function PDFCreateNode(config) {
5
5
  RED.nodes.createNode(this, config);
6
- var node = this;
6
+
7
+ const node = this;
8
+
7
9
  node.on("input", async function (msg) {
8
10
  try {
9
11
  msg = {
@@ -9,6 +9,7 @@
9
9
  required: false,
10
10
  // validate: RED.validators.string(),
11
11
  },
12
+ font: { value: "TimesRoman", required: false },
12
13
  fontSize: {
13
14
  value: 12,
14
15
  required: true,
@@ -19,11 +20,12 @@
19
20
  required: true,
20
21
  validate: RED.validators.number(),
21
22
  },
22
- poxY: {
23
+ posY: {
23
24
  value: 0,
24
25
  required: true,
25
26
  validate: RED.validators.number(),
26
27
  },
28
+ color: { value: "#000000" },
27
29
  },
28
30
  inputs: 1,
29
31
  outputs: 1,
@@ -42,23 +44,54 @@
42
44
  </div>
43
45
 
44
46
  <div class="form-row">
45
- <label for="node-input-text"><i class="fa fa-tag"></i> Name</label>
47
+ <label for="node-input-text"
48
+ ><i class="fa fa-pencil-square-o"></i> Text</label
49
+ >
46
50
  <input type="text" id="node-input-text" placeholder="Text" />
47
51
  </div>
48
52
 
49
53
  <div class="form-row">
50
- <label for="node-input-fontSize"><i class="fa fa-text"></i>Font Size</label>
54
+ <label for="node-input-font"><i class="fa fa-font"></i> Choice</label>
55
+ <select id="node-input-font">
56
+ <option value="Courier">Courier</option>
57
+ <option value="CourierBold">Courier Bold</option>
58
+ <option value="CourierOblique">Courier Oblique</option>
59
+ <option value="CourierBoldOblique">Courier Bold Oblique</option>
60
+ <option value="Helvetica">Helvetica</option>
61
+ <option value="HelveticaBold">Helvetica Bold</option>
62
+ <option value="HelveticaOblique">Helvetica Oblique</option>
63
+ <option value="HelveticaBoldOblique">Helvetica Bold Oblique</option>
64
+ <option value="TimesRoman" selected>Times Roman</option>
65
+ <option value="TimesRomanBold">Times Bold</option>
66
+ <option value="TimesRomanItalic">Times Italic</option>
67
+ <option value="TimesRomanBoldItalic">Times Bold Italic</option>
68
+ <option value="Symbol">Symbol</option>
69
+ <option value="ZapfDingbats">Zapf Dingbats</option>
70
+ </select>
71
+ </div>
72
+
73
+ <div class="form-row">
74
+ <label for="node-input-fontSize"
75
+ ><i class="fa fa-text-height"></i> Font Size</label
76
+ >
51
77
  <input type="number" id="node-input-fontSize" />
52
78
  </div>
53
79
 
54
80
  <div class="form-row">
55
- <label for="node-input-posX"><i class="fa fa-text"></i>x</label>
81
+ <label for="node-input-posX"><i class="fa fa-arrows-h"></i> x</label>
56
82
  <input type="number" id="node-input-posX" />
57
83
  </div>
58
84
 
59
85
  <div class="form-row">
60
- <label for="node-input-poxY"><i class="fa fa-text"></i>y</label>
61
- <input type="number" id="node-input-poxY" />
86
+ <label for="node-input-posY"><i class="fa fa-arrows-v"></i> y</label>
87
+ <input type="number" id="node-input-posY" />
88
+ </div>
89
+
90
+ <div class="form-row">
91
+ <label for="node-input-color"
92
+ ><i class="fa fa-paint-brush"></i> Color</label
93
+ >
94
+ <input type="color" id="node-input-color" style="width: 100px;" />
62
95
  </div>
63
96
  </script>
64
97
 
@@ -1,27 +1,50 @@
1
1
  const { StandardFonts, rgb } = require("pdf-lib");
2
2
 
3
+ function hexToRgbObject(hex) {
4
+ hex = hex.replace(/^#/, "");
5
+
6
+ if (hex.length === 3) {
7
+ hex = hex
8
+ .split("")
9
+ .map((ch) => ch + ch)
10
+ .join("");
11
+ }
12
+
13
+ const bigint = parseInt(hex, 16);
14
+ const r = ((bigint >> 16) & 255) / 255;
15
+ const g = ((bigint >> 8) & 255) / 255;
16
+ const b = (bigint & 255) / 255;
17
+
18
+ return { r, g, b };
19
+ }
20
+
3
21
  module.exports = function (RED) {
4
22
  function PDFDrawTextNode(config) {
5
23
  RED.nodes.createNode(this, config);
24
+
6
25
  this.text = config.text || "";
26
+ this.font = config.font || "";
7
27
  this.fontSize = Number(config.fontSize || 12);
8
28
  this.posX = Number(config.posX || 0);
9
- this.poxY = Number(config.poxY || 0);
29
+ this.posY = Number(config.posY || 0);
30
+ this.color = config.color || "#000000";
31
+
10
32
  const node = this;
33
+
11
34
  node.on("input", async function (msg) {
12
35
  try {
13
36
  const page = msg.page;
14
37
 
15
38
  const timesRomanFont = await msg.pdfDoc.embedFont(
16
- StandardFonts.TimesRoman,
39
+ StandardFonts[node.font],
17
40
  );
18
-
41
+ const rgbColor = hexToRgbObject(node.color);
19
42
  page.drawText(node.text, {
20
- x: node.poxX,
21
- y: node.poxY,
43
+ x: node.posX,
44
+ y: node.posY,
22
45
  size: node.fontSize,
23
46
  font: timesRomanFont,
24
- color: rgb(0, 0, 0),
47
+ color: rgb(rgbColor.r, rgbColor.g, rgbColor.b),
25
48
  });
26
49
 
27
50
  msg = {
@@ -23,7 +23,7 @@
23
23
  </div>
24
24
 
25
25
  <div class="form-row">
26
- <label for="node-input-pdfPage"><i class="fa fa-tag"></i>Page</label>
26
+ <label for="node-input-pdfPage"><i class="fa fa-tag"></i> Page</label>
27
27
  <input type="number" id="node-input-pdfPage" placeholder="Page" />
28
28
  </div>
29
29
  </script>
@@ -1,17 +1,20 @@
1
- var pdfLib = require("pdf-lib");
1
+ const { PDFDocument } = require("pdf-lib");
2
2
 
3
3
  module.exports = function (RED) {
4
4
  function PDFGetPageNode(config) {
5
5
  RED.nodes.createNode(this, config);
6
+
6
7
  this.pdfPage = config.pdfPage;
7
- var node = this;
8
+
9
+ const node = this;
10
+
8
11
  node.on("input", async function (msg) {
9
12
  try {
10
- const pdfDoc = await pdfLib.PDFDocument.load(msg.payload);
13
+ const pdfDoc = await PDFDocument.load(msg.payload);
11
14
  //const pages = pdfDoc.getPageCount();
12
15
  // console.log(pages);
13
16
 
14
- const newPDF = await pdfLib.PDFDocument.create();
17
+ const newPDF = await PDFDocument.create();
15
18
 
16
19
  const copiedPages = await newPDF.copyPages(pdfDoc, [node.pdfPage - 1]);
17
20
  const [page] = copiedPages;
package/nodes/pdf-save.js CHANGED
@@ -2,7 +2,8 @@ module.exports = function (RED) {
2
2
  function PDFSaveNode(config) {
3
3
  RED.nodes.createNode(this, config);
4
4
 
5
- var node = this;
5
+ const node = this;
6
+
6
7
  node.on("input", async function (msg) {
7
8
  try {
8
9
  msg = {
@@ -18,12 +18,12 @@
18
18
 
19
19
  <script type="text/html" data-template-name="pdf-to-img">
20
20
  <div class="form-row">
21
- <label for="node-input-name"><i class="fa fa-tag"></i>Name</label>
21
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
22
22
  <input type="text" id="node-input-name" placeholder="Name" />
23
23
  </div>
24
24
 
25
25
  <div class="form-row">
26
- <label for="node-input-scale"><i class="fa fa-tag"></i>Scale</label>
26
+ <label for="node-input-scale"><i class="fa fa-tag"></i> Scale</label>
27
27
  <input type="number" id="node-input-scale" placeholder="Page" />
28
28
  </div>
29
29
  </script>
@@ -3,8 +3,11 @@ const { pdf } = require("pdf-to-img");
3
3
  module.exports = function (RED) {
4
4
  function PDFToImageNode(config) {
5
5
  RED.nodes.createNode(this, config);
6
+
6
7
  this.scale = config.scale;
7
- var node = this;
8
+
9
+ const node = this;
10
+
8
11
  node.on("input", async function (msg) {
9
12
  try {
10
13
  const pdfBuffer = msg.payload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aaqu/node-red-aaqu-pdf",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "node-red pdf creator",
5
5
  "scripts": {
6
6
  "node-red": "node-red"