muhammara 3.8.0 → 4.1.0
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/CHANGELOG.md +47 -1
- package/README.md +260 -3
- package/lib/PDFRStreamForBuffer.js +4 -5
- package/lib/Recipe.js +1 -1
- package/lib/recipe/annotation.js +47 -13
- package/lib/recipe/font.js +2 -0
- package/lib/recipe/htmlToTextObjects.js +1 -0
- package/lib/recipe/overlay.js +1 -0
- package/lib/recipe/page.js +3 -0
- package/lib/recipe/text.js +41 -6
- package/lib/recipe/vector.helper.js +1 -0
- package/muhammara.d.ts +69 -9
- package/node_modules/@mapbox/node-pre-gyp/.github/workflows/codeql.yml +74 -0
- package/node_modules/@mapbox/node-pre-gyp/CHANGELOG.md +3 -0
- package/node_modules/@mapbox/node-pre-gyp/package.json +10 -10
- package/node_modules/balanced-match/package.json +2 -1
- package/node_modules/brace-expansion/package.json +1 -1
- package/node_modules/debug/package.json +2 -1
- package/node_modules/detect-libc/README.md +4 -1
- package/node_modules/detect-libc/index.d.ts +3 -0
- package/node_modules/detect-libc/lib/detect-libc.js +105 -4
- package/node_modules/detect-libc/lib/filesystem.js +41 -0
- package/node_modules/detect-libc/lib/process.js +3 -0
- package/node_modules/detect-libc/package.json +12 -5
- package/node_modules/inherits/package.json +1 -6
- package/node_modules/make-dir/node_modules/semver/package.json +21 -12
- package/node_modules/make-dir/node_modules/semver/semver.js +71 -24
- package/node_modules/minipass/README.md +7 -7
- package/node_modules/minipass/index.d.ts +18 -16
- package/node_modules/minipass/index.js +6 -1
- package/node_modules/minipass/index.mjs +7 -2
- package/node_modules/minipass/package.json +10 -10
- package/node_modules/node-fetch/README.md +2 -1
- package/node_modules/node-fetch/lib/index.es.js +5 -6
- package/node_modules/node-fetch/lib/index.js +5 -5
- package/node_modules/node-fetch/lib/index.mjs +5 -6
- package/node_modules/node-fetch/package.json +5 -5
- package/node_modules/readable-stream/lib/_stream_duplex.js +8 -8
- package/node_modules/readable-stream/lib/_stream_passthrough.js +1 -1
- package/node_modules/readable-stream/lib/_stream_readable.js +37 -36
- package/node_modules/readable-stream/lib/_stream_transform.js +6 -5
- package/node_modules/readable-stream/lib/_stream_writable.js +19 -18
- package/node_modules/readable-stream/lib/internal/streams/async_iterator.js +81 -86
- package/node_modules/readable-stream/lib/internal/streams/buffer_list.js +155 -127
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +17 -16
- package/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +11 -11
- package/node_modules/readable-stream/lib/internal/streams/from.js +6 -6
- package/node_modules/readable-stream/lib/internal/streams/pipeline.js +14 -14
- package/node_modules/readable-stream/lib/internal/streams/state.js +4 -4
- package/node_modules/readable-stream/package.json +5 -5
- package/node_modules/semver/README.md +70 -1
- package/node_modules/semver/bin/semver.js +16 -2
- package/node_modules/semver/classes/comparator.js +39 -34
- package/node_modules/semver/classes/range.js +45 -28
- package/node_modules/semver/classes/semver.js +32 -17
- package/node_modules/semver/functions/coerce.js +1 -1
- package/node_modules/semver/functions/diff.js +58 -16
- package/node_modules/semver/functions/inc.js +3 -2
- package/node_modules/semver/functions/parse.js +5 -22
- package/node_modules/semver/index.js +1 -0
- package/node_modules/semver/internal/constants.js +20 -2
- package/node_modules/semver/internal/parse-options.js +14 -10
- package/node_modules/semver/internal/re.js +34 -4
- package/node_modules/semver/package.json +12 -11
- package/node_modules/semver/ranges/intersects.js +1 -1
- package/node_modules/semver/ranges/subset.js +6 -3
- package/node_modules/tar/lib/normalize-unicode.js +1 -1
- package/node_modules/tar/lib/pack.js +20 -8
- package/node_modules/tar/lib/parse.js +46 -3
- package/node_modules/tar/lib/path-reservations.js +1 -1
- package/node_modules/tar/lib/read-entry.js +2 -2
- package/node_modules/tar/lib/replace.js +1 -1
- package/node_modules/tar/lib/unpack.js +1 -1
- package/node_modules/tar/lib/update.js +1 -1
- package/node_modules/tar/lib/write-entry.js +3 -3
- package/node_modules/tar/package.json +11 -16
- package/node_modules/util-deprecate/package.json +1 -5
- package/package.json +4 -6
- package/node_modules/make-dir/node_modules/semver/CHANGELOG.md +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,50 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [4.1.0] - 2023-12-13
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- definitions: appendPage optionnal parameter
|
|
15
|
+
- Build musl/musl-arm with node 20
|
|
16
|
+
- Support negative rotation in recipe page changes
|
|
17
|
+
- registerFont now returns recipe as stated in typescript definition
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Add nodejs v21.0.0
|
|
22
|
+
|
|
23
|
+
## [4.0.0] - 2023-07-14
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Underline in text object
|
|
28
|
+
- Recipe type / arg documentation
|
|
29
|
+
- Add missing type `userPassword` to `EncryptOptions`
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Strikethrough implementation in text object
|
|
34
|
+
- Add electron 23.2., 23.3
|
|
35
|
+
- Recipe infos to readme
|
|
36
|
+
- Electron v24.1, 24.2, 24.3, 24.4, 24.5, 24.6
|
|
37
|
+
- Add node 20.x
|
|
38
|
+
- Add electron v25.0, 25.1, 25.2, 25.3
|
|
39
|
+
- Option to add annotation replies to annotations
|
|
40
|
+
- Textboxes now show title and date as annotations in pdfs
|
|
41
|
+
|
|
42
|
+
### Removed
|
|
43
|
+
|
|
44
|
+
- Dependency to static-eval and static-module as they are not used directly
|
|
45
|
+
- Node versions: 11.x - 14.x
|
|
46
|
+
- Electron versions: 11.x - 14.2
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- Updated node-gyp version to 1.0.10
|
|
51
|
+
- Older node ubuntu 18.04 builds are now building on docker, as github actions removed 18.04
|
|
52
|
+
- CI linux builds use ubuntu 20.04 instead of 18.04 -> glibc Update, see readme for breaking changes in v4
|
|
53
|
+
|
|
10
54
|
## [3.8.0] - 2023-03-01
|
|
11
55
|
|
|
12
56
|
### Added
|
|
@@ -368,7 +412,9 @@ with the following changes.
|
|
|
368
412
|
|
|
369
413
|
- Initial release
|
|
370
414
|
|
|
371
|
-
[unreleased]: https://github.com/julianhille/MuhammaraJS/compare/
|
|
415
|
+
[unreleased]: https://github.com/julianhille/MuhammaraJS/compare/4.1.0...HEAD
|
|
416
|
+
[4.1.0]: https://github.com/julianhille/MuhammaraJS/compare/4.0.0...4.1.0
|
|
417
|
+
[4.0.0]: https://github.com/julianhille/MuhammaraJS/compare/3.8.0...4.0.0
|
|
372
418
|
[3.8.0]: https://github.com/julianhille/MuhammaraJS/compare/3.7.0...3.8.0
|
|
373
419
|
[3.7.0]: https://github.com/julianhille/MuhammaraJS/compare/3.6.0...3.7.0
|
|
374
420
|
[3.6.0]: https://github.com/julianhille/MuhammaraJS/compare/3.5.0...3.6.0
|
package/README.md
CHANGED
|
@@ -28,15 +28,26 @@ It serves as a drop in replacement.
|
|
|
28
28
|
|
|
29
29
|
# Caution
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
## Breaking changes
|
|
32
|
+
|
|
33
|
+
### Version 2.x
|
|
34
|
+
|
|
35
|
+
will be incompatible with some older node and
|
|
32
36
|
electron versions because we needed to upgrade node-pre-gyp.
|
|
33
37
|
|
|
34
|
-
Version 3.x
|
|
38
|
+
### Version 3.x
|
|
35
39
|
|
|
36
40
|
- Node < 11 and Electron < 11 removed the prebuilts
|
|
37
41
|
- Renamed typo exported value from eTokenSeprator to eTokenSeparator
|
|
38
42
|
|
|
39
|
-
This
|
|
43
|
+
This won't affect a lot of you but still.
|
|
44
|
+
|
|
45
|
+
### Version 4.x
|
|
46
|
+
|
|
47
|
+
- Node < 15 and electron < 15 pre-builts have been removed
|
|
48
|
+
- Ubuntu 18.04 has been removed from github actions and so it is unable to build on 18.04.
|
|
49
|
+
This means the glibc has been raised to 2.31 which might break pre-builts for you.
|
|
50
|
+
It is still possible to build for older glibc version.
|
|
40
51
|
|
|
41
52
|
# Installation
|
|
42
53
|
|
|
@@ -82,3 +93,249 @@ You can find samples and documentation [here](./docs/Home.md)
|
|
|
82
93
|
To generate the documentation you could clone this repo and execute:
|
|
83
94
|
|
|
84
95
|
`npm run recipe-jsdoc`
|
|
96
|
+
|
|
97
|
+
## Recipe
|
|
98
|
+
|
|
99
|
+
### Instructions
|
|
100
|
+
|
|
101
|
+
- [GetStarted](#getstarted)
|
|
102
|
+
- [Coordinate System](#coordinate-system)
|
|
103
|
+
- [Create a new PDF](#create-a-new-pdf)
|
|
104
|
+
- [Modify an existing PDF](#modify-an-existing-pdf)
|
|
105
|
+
- [PDF Pages/Info/Structure](#page-info)
|
|
106
|
+
- [Append PDF](#append-pdf)
|
|
107
|
+
- [Insert PDF](#insert-pdf)
|
|
108
|
+
- [Overlay PDF](#overlay-pdf)
|
|
109
|
+
- [Split PDF](#split-pdf)
|
|
110
|
+
- [Encryption](#encryption)
|
|
111
|
+
|
|
112
|
+
### GetStarted
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
const Recipe = require('muhammara').Recipe
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Coordinate System
|
|
119
|
+
|
|
120
|
+
In order to make things easier, I use `Left-Top` as center `[0,0]` instead of `Left-Bottom`.
|
|
121
|
+
You may write and edit the pdf like you write things on papers from the left top corner.
|
|
122
|
+
It is similar to the [Html Canvas](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage)
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
pdfDoc
|
|
126
|
+
.text('start from here', 0, 0)
|
|
127
|
+
.text('next line', 0, 20)
|
|
128
|
+
.text('some other texts', 100, 100)
|
|
129
|
+
...
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Create a new PDF
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const Recipe = require("muhammara").Recipe;
|
|
136
|
+
|
|
137
|
+
const pdfDoc = new Recipe("new", "output.pdf", {
|
|
138
|
+
version: 1.6,
|
|
139
|
+
author: "John Doe",
|
|
140
|
+
title: "Hummus Recipe",
|
|
141
|
+
subject: "A brand new PDF",
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
pdfDoc.createPage("letter-size").endPage().endPDF();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
const Recipe = require("muhammara").Recipe;
|
|
149
|
+
const pdfDoc = new Recipe("new", "output.pdf");
|
|
150
|
+
|
|
151
|
+
pdfDoc
|
|
152
|
+
// 1st Page
|
|
153
|
+
.createPage("letter-size")
|
|
154
|
+
.circle("center", 100, 30, { stroke: "#3b7721", fill: "#eee000" })
|
|
155
|
+
.polygon(
|
|
156
|
+
[
|
|
157
|
+
[50, 250],
|
|
158
|
+
[100, 200],
|
|
159
|
+
[512, 200],
|
|
160
|
+
[562, 250],
|
|
161
|
+
[512, 300],
|
|
162
|
+
[100, 300],
|
|
163
|
+
[50, 250],
|
|
164
|
+
],
|
|
165
|
+
{
|
|
166
|
+
color: [153, 143, 32],
|
|
167
|
+
stroke: [0, 0, 140],
|
|
168
|
+
fill: [153, 143, 32],
|
|
169
|
+
lineWidth: 5,
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
.rectangle(240, 400, 50, 50, {
|
|
173
|
+
stroke: "#3b7721",
|
|
174
|
+
fill: "#eee000",
|
|
175
|
+
lineWidth: 6,
|
|
176
|
+
opacity: 0.3,
|
|
177
|
+
})
|
|
178
|
+
.moveTo(200, 600)
|
|
179
|
+
.lineTo("center", 650)
|
|
180
|
+
.lineTo(412, 600)
|
|
181
|
+
.text("Welcome to Hummus-Recipe", "center", 250, {
|
|
182
|
+
color: "#066099",
|
|
183
|
+
fontSize: 30,
|
|
184
|
+
bold: true,
|
|
185
|
+
font: "Helvatica",
|
|
186
|
+
align: "center center",
|
|
187
|
+
opacity: 0.8,
|
|
188
|
+
rotation: 180,
|
|
189
|
+
})
|
|
190
|
+
.text("some text box", 450, 400, {
|
|
191
|
+
color: "#066099",
|
|
192
|
+
fontSize: 20,
|
|
193
|
+
font: "Courier New",
|
|
194
|
+
strikeOut: true,
|
|
195
|
+
highlight: {
|
|
196
|
+
color: [255, 0, 0],
|
|
197
|
+
},
|
|
198
|
+
textBox: {
|
|
199
|
+
width: 150,
|
|
200
|
+
lineHeight: 16,
|
|
201
|
+
padding: [5, 15],
|
|
202
|
+
style: {
|
|
203
|
+
lineWidth: 1,
|
|
204
|
+
stroke: "#00ff00",
|
|
205
|
+
fill: "#ff0000",
|
|
206
|
+
dash: [20, 20],
|
|
207
|
+
opacity: 0.1,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
.comment("Feel free to open issues to help us!", "center", 100)
|
|
212
|
+
.endPage()
|
|
213
|
+
// 2nd page
|
|
214
|
+
.createPage("A4", 90)
|
|
215
|
+
.circle(150, 150, 300)
|
|
216
|
+
.endPage()
|
|
217
|
+
// end and save
|
|
218
|
+
.endPDF(() => {
|
|
219
|
+
/* done! */
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Create a new PDF as a Buffer
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
const Recipe = require("muhammara").Recipe;
|
|
227
|
+
|
|
228
|
+
const pdfDoc = new Recipe(Buffer.from("new"), null, {
|
|
229
|
+
version: 1.6,
|
|
230
|
+
author: "John Doe",
|
|
231
|
+
title: "Hummus Recipe",
|
|
232
|
+
subject: "A brand new PDF",
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const pdfBuffer = pdfDoc.createPage("letter-size").endPage().endPDF();
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Modify an existing PDF
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const Recipe = require("muhammara").Recipe;
|
|
242
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
243
|
+
|
|
244
|
+
pdfDoc
|
|
245
|
+
// edit 1st page
|
|
246
|
+
.editPage(1)
|
|
247
|
+
.text("Add some texts to an existing pdf file", 150, 300)
|
|
248
|
+
.rectangle(20, 20, 40, 100)
|
|
249
|
+
.comment("Add 1st comment annotation", 200, 300)
|
|
250
|
+
.image("/path/to/image.jpg", 20, 100, { width: 300, keepAspectRatio: true })
|
|
251
|
+
.endPage()
|
|
252
|
+
// edit 2nd page
|
|
253
|
+
.editPage(2)
|
|
254
|
+
.comment("Add 2nd comment annotation", 200, 100)
|
|
255
|
+
.endPage()
|
|
256
|
+
// end and save
|
|
257
|
+
.endPDF();
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Page Info
|
|
261
|
+
|
|
262
|
+
```javascript
|
|
263
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
264
|
+
console.log(pdfDoc.pageInfo(1));
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### Print the pdf structure
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
271
|
+
|
|
272
|
+
recipe.structure("pdf-structure.txt").endPDF(done);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Append PDF
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
const Recipe = require("muhammara").Recipe;
|
|
279
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
280
|
+
const longPDF = "/longPDF.pdf";
|
|
281
|
+
|
|
282
|
+
pdfDoc
|
|
283
|
+
// just page 10
|
|
284
|
+
.appendPage(longPDF, 10)
|
|
285
|
+
// page 4 and page 6
|
|
286
|
+
.appendPage(longPDF, [4, 6])
|
|
287
|
+
// page 1-3 and 6-20
|
|
288
|
+
.appendPage(longPDF, [
|
|
289
|
+
[1, 3],
|
|
290
|
+
[6, 20],
|
|
291
|
+
])
|
|
292
|
+
// all pages
|
|
293
|
+
.appendPage(longPDF)
|
|
294
|
+
.endPDF();
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Insert PDF
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
const Recipe = require("muhammara").Recipe;
|
|
301
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
302
|
+
|
|
303
|
+
pdfDoc
|
|
304
|
+
// insert page3 from longPDF to current page 2
|
|
305
|
+
.insertPage(2, "/longPDF.pdf", 3)
|
|
306
|
+
.endPDF();
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Overlay PDF
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
const Recipe = require("muhammara").Recipe;
|
|
313
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
314
|
+
|
|
315
|
+
pdfDoc.overlay("/overlayPDF.pdf").endPDF();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Split PDF
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
const Recipe = require("muhammara").Recipe;
|
|
322
|
+
const pdfDoc = new Recipe("input.pdf");
|
|
323
|
+
const outputDir = path.join(__dirname, "output");
|
|
324
|
+
|
|
325
|
+
pdfDoc.split(outputDir, "prefix").endPDF();
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Encryption
|
|
329
|
+
|
|
330
|
+
```javascript
|
|
331
|
+
const Recipe = require("muhammara").Recipe;
|
|
332
|
+
const pdfDoc = new Recipe("input.pdf", "output.pdf");
|
|
333
|
+
|
|
334
|
+
pdfDoc
|
|
335
|
+
.encrypt({
|
|
336
|
+
userPassword: "123",
|
|
337
|
+
ownerPassword: "123",
|
|
338
|
+
userProtectionFlag: 4,
|
|
339
|
+
})
|
|
340
|
+
.endPDF();
|
|
341
|
+
```
|
|
@@ -5,17 +5,16 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
function PDFRStreamForBuffer(buffer) {
|
|
8
|
-
this.
|
|
8
|
+
this.buffer = buffer;
|
|
9
9
|
this.rposition = 0;
|
|
10
|
-
this.fileSize = this.
|
|
10
|
+
this.fileSize = this.buffer.length;
|
|
11
11
|
this.mStartPosition = 0;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
PDFRStreamForBuffer.prototype.read = function (inAmount) {
|
|
15
15
|
var amountToRead = inAmount;
|
|
16
|
-
var arr =
|
|
17
|
-
this.rposition,
|
|
18
|
-
this.rposition + amountToRead
|
|
16
|
+
var arr = Array.from(
|
|
17
|
+
this.buffer.subarray(this.rposition, this.rposition + amountToRead)
|
|
19
18
|
);
|
|
20
19
|
this.rposition += amountToRead;
|
|
21
20
|
return arr;
|
package/lib/Recipe.js
CHANGED
|
@@ -9,7 +9,7 @@ const streams = require("memory-streams");
|
|
|
9
9
|
* @namespace
|
|
10
10
|
* @constructor
|
|
11
11
|
* @param {string} src - The file path or Buffer of the src file.
|
|
12
|
-
* @param {string} output - The path of the output file.
|
|
12
|
+
* @param {string} [output] - The path of the output file uses src if its not a buffer.
|
|
13
13
|
* @param {Object} [options] - The options for pdfDoc
|
|
14
14
|
* @param {number} [options.version] - The pdf version
|
|
15
15
|
* @param {string} [options.author] - The author
|
package/lib/recipe/annotation.js
CHANGED
|
@@ -27,18 +27,22 @@ exports.comment = function comment(text = "", x, y, options = {}) {
|
|
|
27
27
|
* @name annot
|
|
28
28
|
* @function
|
|
29
29
|
* @memberof Recipe
|
|
30
|
-
* @todo support for rich
|
|
30
|
+
* @todo support for rich text RC
|
|
31
31
|
* @todo support for opacity CA
|
|
32
32
|
* @param {number} x - The coordinate x
|
|
33
33
|
* @param {number} y - The coordinate y
|
|
34
|
-
* @param {string} subtype - The markup annotation type 'Text'|'FreeText'|'Line'|'Square'|'Circle'|'Polygon'|'PolyLine'|'Highlight'|'Underline'|'Squiggly'|'StrikeOut'|'
|
|
34
|
+
* @param {string} subtype - The markup annotation type 'Text'|'Link'|'FreeText'|'Line'|'Square'|'Circle'|'Polygon'|'PolyLine'|'Highlight'|'Underline'|'Squiggly'|'StrikeOut'|'Caret'|'Stamp'|'Ink'|'Popup'|'FileAttachment'|'Sound'|'Movie'|'Screen'|'Widget'|'PrinterMark'|'TrapNet'|'Watermark'|'3D'|'Redact'|'Projection'|'RichMedia'
|
|
35
35
|
* @param {Object} [options] - The options
|
|
36
36
|
* @param {string} [options.title] - The title.
|
|
37
|
-
* @param {boolean} [options.open=false] - Open the annotation by default
|
|
37
|
+
* @param {boolean} [options.open=false] - Open the annotation. Annotation will be closed by default. Specific to text annotations; subtype='Text'
|
|
38
|
+
* @param {boolean} [options.richText] - Rich text
|
|
38
39
|
* @param {'invisible'|'hidden'|'print'|'nozoom'|'norotate'|'noview'|'readonly'|'locked'|'togglenoview'} [options.flag] - The flag property
|
|
39
|
-
* @param {'Comment'|'Key'|'Note'|'Help'|'NewParagraph'|'Paragraph'|'Insert'} [options.icon] - The icon of annotation.
|
|
40
|
+
* @param {'Comment'|'Key'|'Note'|'Help'|'NewParagraph'|'Paragraph'|'Insert'} [options.icon='Note'] - The icon of annotation. Specific to text annotations. Default value: 'Note'
|
|
40
41
|
* @param {number} [options.width] - Width
|
|
41
42
|
* @param {number} [options.height] - Height
|
|
43
|
+
* @param {string} [options.date] - Date of annotation
|
|
44
|
+
* @param {string} [options.subject] - The subject.
|
|
45
|
+
* @param {Array} [options.replies] - Array of annotation replies
|
|
42
46
|
*/
|
|
43
47
|
exports.annot = function annot(
|
|
44
48
|
x,
|
|
@@ -46,11 +50,12 @@ exports.annot = function annot(
|
|
|
46
50
|
subtype,
|
|
47
51
|
options = { text: "", width: 0, height: 0 }
|
|
48
52
|
) {
|
|
49
|
-
const { text, width, height } = options;
|
|
53
|
+
const { text, width, height, replies } = options;
|
|
50
54
|
this.annotationsToWrite.push({
|
|
51
55
|
subtype,
|
|
52
56
|
args: { text, x, y, width, height, options },
|
|
53
57
|
pageNumber: this.pageNumber,
|
|
58
|
+
replies,
|
|
54
59
|
});
|
|
55
60
|
return this;
|
|
56
61
|
};
|
|
@@ -59,8 +64,9 @@ exports.annot = function annot(
|
|
|
59
64
|
// Link, Popup, Movie, Widget, Screen, PrinterMark, TrapNet, Watermark, 3D
|
|
60
65
|
exports._attachNonMarkupAnnot = function _attachNonMarkupAnnot() {};
|
|
61
66
|
|
|
62
|
-
exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
63
|
-
const { x, y, width, height,
|
|
67
|
+
exports._annot = function _annot(subtype, args = {}, pageNumber, ref) {
|
|
68
|
+
const { x, y, width, height, options, reply } = args;
|
|
69
|
+
let { text } = args;
|
|
64
70
|
this._startDictionary(pageNumber);
|
|
65
71
|
const { rotate } = this.metadata[pageNumber];
|
|
66
72
|
let { nx, ny } = this._calibrateCoordinateForAnnots(x, y, 0, 0, pageNumber);
|
|
@@ -92,7 +98,7 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
92
98
|
{
|
|
93
99
|
title: "",
|
|
94
100
|
subject: "",
|
|
95
|
-
date:
|
|
101
|
+
date: "",
|
|
96
102
|
open: false,
|
|
97
103
|
flag: "", // 'readonly'
|
|
98
104
|
},
|
|
@@ -103,6 +109,15 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
103
109
|
const ey = nHeight ? nHeight : 0;
|
|
104
110
|
const position = [nx, ny, nx + ex, ny + ey];
|
|
105
111
|
|
|
112
|
+
if (reply && ref) {
|
|
113
|
+
text = reply.text;
|
|
114
|
+
params.title = reply.title || params.title;
|
|
115
|
+
params.date = reply.date || params.date;
|
|
116
|
+
params.subject = reply.subject || params.subject;
|
|
117
|
+
params.richText = Boolean(reply.richText);
|
|
118
|
+
params.flag = reply.flag || params.flag;
|
|
119
|
+
}
|
|
120
|
+
|
|
106
121
|
this.dictionaryContext
|
|
107
122
|
.writeKey("Type")
|
|
108
123
|
.writeNameValue("Annot")
|
|
@@ -117,7 +132,9 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
117
132
|
.writeKey("T")
|
|
118
133
|
.writeLiteralStringValue(params.title || "")
|
|
119
134
|
.writeKey("M")
|
|
120
|
-
.writeLiteralStringValue(
|
|
135
|
+
.writeLiteralStringValue(
|
|
136
|
+
this.writer.createPDFDate(new Date(params.date)).toString()
|
|
137
|
+
)
|
|
121
138
|
.writeKey("Open")
|
|
122
139
|
.writeBooleanValue(params.open)
|
|
123
140
|
.writeKey("F")
|
|
@@ -127,9 +144,9 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
127
144
|
* Rich Text Strings
|
|
128
145
|
* 12.7.3.4
|
|
129
146
|
*/
|
|
130
|
-
if (text &&
|
|
147
|
+
if (text && params.richText) {
|
|
131
148
|
const richText =
|
|
132
|
-
text.substring(0, 5) !== "<?xml" ? contentToRC(text) :
|
|
149
|
+
text.substring(0, 5) !== "<?xml" ? contentToRC(text) : params.richText;
|
|
133
150
|
const richTextContent = richText;
|
|
134
151
|
this.dictionaryContext
|
|
135
152
|
.writeKey("RC")
|
|
@@ -141,6 +158,14 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
141
158
|
.writeLiteralStringValue(textContent);
|
|
142
159
|
}
|
|
143
160
|
|
|
161
|
+
if (reply && ref) {
|
|
162
|
+
this.dictionaryContext
|
|
163
|
+
.writeKey("IRT")
|
|
164
|
+
.writeObjectReferenceValue(ref)
|
|
165
|
+
.writeKey("RT")
|
|
166
|
+
.writeNameValue("R");
|
|
167
|
+
}
|
|
168
|
+
|
|
144
169
|
let { border, color } = options;
|
|
145
170
|
|
|
146
171
|
if (this._getTextMarkupAnnotationSubtype(subtype)) {
|
|
@@ -212,12 +237,19 @@ exports._annot = function _annot(subtype, args = {}, pageNumber) {
|
|
|
212
237
|
if (params.icon) {
|
|
213
238
|
this.dictionaryContext.writeKey("Name").writeNameValue(params.icon);
|
|
214
239
|
}
|
|
215
|
-
this._endDictionary(pageNumber);
|
|
240
|
+
return this._endDictionary(pageNumber);
|
|
216
241
|
};
|
|
217
242
|
|
|
218
243
|
exports._writeAnnotations = function _writeAnnotations() {
|
|
219
244
|
this.annotationsToWrite.forEach((annot) => {
|
|
220
|
-
this._annot(annot.subtype, annot.args, annot.pageNumber);
|
|
245
|
+
const ref = this._annot(annot.subtype, annot.args, annot.pageNumber);
|
|
246
|
+
|
|
247
|
+
if (annot.replies) {
|
|
248
|
+
annot.replies.forEach((reply) => {
|
|
249
|
+
annot.args.reply = reply;
|
|
250
|
+
this._annot(annot.subtype, annot.args, annot.pageNumber, ref);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
221
253
|
});
|
|
222
254
|
this.annotations.forEach((pageAnnots, index) => {
|
|
223
255
|
this._writeAnnotation(index);
|
|
@@ -276,6 +308,8 @@ exports._endDictionary = function _endDictionary(pageNumber) {
|
|
|
276
308
|
const pageIndex = pageNumber - 1;
|
|
277
309
|
this.annotations[pageIndex] = this.annotations[pageIndex] || [];
|
|
278
310
|
this.annotations[pageIndex].push(this.dictionaryObject);
|
|
311
|
+
|
|
312
|
+
return this.dictionaryObject;
|
|
279
313
|
};
|
|
280
314
|
|
|
281
315
|
exports._getTextMarkupAnnotationSubtype =
|
package/lib/recipe/font.js
CHANGED
package/lib/recipe/overlay.js
CHANGED
|
@@ -9,6 +9,7 @@ const { xObjectForm } = require("./xObjectForm");
|
|
|
9
9
|
* @param {number} x - The coordinate x
|
|
10
10
|
* @param {number} y - The coordinate y
|
|
11
11
|
* @param {number} [options.scale] - Scale the overlay pdf, default is 1
|
|
12
|
+
* @param {number} [options.page] - Page of the overlay pdf, default is 1
|
|
12
13
|
* @param {boolean} [options.keepAspectRatio] - To keep the aspect ratio when scaling, default is true
|
|
13
14
|
* @param {boolean} [options.fitWidth] - To set the width to 100% (use with keepAspectRatio=true)
|
|
14
15
|
* @param {boolean} [options.fitHeight] - To set the height to 100% (use with keepAspectRatio=true)
|
package/lib/recipe/page.js
CHANGED
|
@@ -184,12 +184,15 @@ exports._resumePageRotation = function _resumePageRotation(
|
|
|
184
184
|
|
|
185
185
|
switch (rotate) {
|
|
186
186
|
case 90:
|
|
187
|
+
case -270:
|
|
187
188
|
context.cm(0, 1, -1, 0, height - startX, startY);
|
|
188
189
|
break;
|
|
189
190
|
case 180:
|
|
191
|
+
case -180:
|
|
190
192
|
context.cm(-1, 0, 0, -1, width, height);
|
|
191
193
|
break;
|
|
192
194
|
case 270:
|
|
195
|
+
case -90:
|
|
193
196
|
context.cm(0, -1, 1, 0, startX, width - startY);
|
|
194
197
|
break;
|
|
195
198
|
|
package/lib/recipe/text.js
CHANGED
|
@@ -238,6 +238,13 @@ exports._makeTextBox = function _makeTextBox(options) {
|
|
|
238
238
|
* @param {string|number[]} [options.textBox.style.fill] - Text Box border background color (HexColor, PercentColor or DecimalColor)
|
|
239
239
|
* @param {number} [options.textBox.style.opacity=1] - Text Box border background opacity
|
|
240
240
|
* @param {boolean|number|number[]} [options.textBox.style.borderRadius=0] - Border radius to apply to get rounded corners.
|
|
241
|
+
* @param {string} [options.title] - Title of annotation
|
|
242
|
+
* @param {boolean} [options.open=false] - Open the annotation. Annotation will be closed by default. Specific to text annotations; subtype='Text'
|
|
243
|
+
* @param {boolean} [options.richText] - Rich text in annotation
|
|
244
|
+
* @param {AnnotOptionsFlag} [options.flag] - The flag property of annotation
|
|
245
|
+
* @param {AnnotOptionsIcon} [options.icon='Note'] - The icon of annotation. Specific to text annotations. Default value: 'Note'
|
|
246
|
+
* @param {string} [options.date] - Date of text to show up on annotation
|
|
247
|
+
* @param {string} [options.subject] - Subject of annotation
|
|
241
248
|
* When true is given, the default radius size for all corners is 5. A four number array may be used to give specific sizees to each
|
|
242
249
|
* corner. The numbering starts from the top, left corner, and goes clockwise around the text box.
|
|
243
250
|
*/
|
|
@@ -359,12 +366,8 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
359
366
|
const addUnderline = (x, y, ctx, options) => {
|
|
360
367
|
// underline implementation
|
|
361
368
|
if (options.underline) {
|
|
362
|
-
// console.log(textWidth, lineWidth, currentLineWidth)
|
|
363
369
|
const underlineY = y - options.textHeight * 0.1;
|
|
364
|
-
|
|
365
|
-
const width =
|
|
366
|
-
currentLineWidth -
|
|
367
|
-
(isHTML || toWriteTextObject.text.endsWith(" ") ? spaceWidth : 0);
|
|
370
|
+
const width = options.lineWidth;
|
|
368
371
|
ctx
|
|
369
372
|
.q()
|
|
370
373
|
.drawPath(x, underlineY, x + width, underlineY, options)
|
|
@@ -372,6 +375,18 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
372
375
|
}
|
|
373
376
|
};
|
|
374
377
|
|
|
378
|
+
const addStrikeOut = (x, y, ctx, options) => {
|
|
379
|
+
// strikethrough implementation
|
|
380
|
+
if (options.strikeOut) {
|
|
381
|
+
const strikeOutY = y + options.textHeight * 0.2;
|
|
382
|
+
const width = options.lineWidth;
|
|
383
|
+
ctx
|
|
384
|
+
.q()
|
|
385
|
+
.drawPath(x, strikeOutY, x + width, strikeOutY, options)
|
|
386
|
+
.Q();
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
375
390
|
const addTextTraits = (ctx, options) => {
|
|
376
391
|
ctx.Tf(options.font, options.size);
|
|
377
392
|
ctx.Tc(options.charSpace);
|
|
@@ -394,6 +409,7 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
394
409
|
ctx.ET();
|
|
395
410
|
|
|
396
411
|
addUnderline(x, y, ctx, options);
|
|
412
|
+
addStrikeOut(x, y, ctx, options);
|
|
397
413
|
};
|
|
398
414
|
|
|
399
415
|
const justifyText = (left, x, wto, textBox, ctx, options, callback) => {
|
|
@@ -416,7 +432,7 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
416
432
|
|
|
417
433
|
const writeText = (context, x, y, wto) => {
|
|
418
434
|
const options = wto.writeOptions;
|
|
419
|
-
const { lineHeight, text, baseline } = wto;
|
|
435
|
+
const { lineWidth, lineHeight, text, baseline } = wto;
|
|
420
436
|
let next_x = 0;
|
|
421
437
|
|
|
422
438
|
if (text === "") {
|
|
@@ -424,6 +440,10 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
424
440
|
return next_x;
|
|
425
441
|
}
|
|
426
442
|
|
|
443
|
+
if (options.underline || options.strikeOut) {
|
|
444
|
+
options.lineWidth = lineWidth;
|
|
445
|
+
}
|
|
446
|
+
|
|
427
447
|
// Produce a hilite under words?
|
|
428
448
|
if (options.hilite) {
|
|
429
449
|
const bgColor = options.hilite.color || "#ffff00";
|
|
@@ -549,13 +569,24 @@ exports.text = function text(text = "", x, y, options = {}) {
|
|
|
549
569
|
typeof targetAnnotations[key] != "object"
|
|
550
570
|
? {}
|
|
551
571
|
: targetAnnotations[key];
|
|
572
|
+
const { title, open, richText, flag, icon, date, subject } =
|
|
573
|
+
targetAnnotations;
|
|
552
574
|
Object.assign(markupOption, {
|
|
553
575
|
height: textHeight * 1.4,
|
|
554
576
|
width: currentLineWidth,
|
|
555
577
|
text: markupOption.text || "",
|
|
556
578
|
_textHeight: textHeight,
|
|
579
|
+
// add options to annotation
|
|
580
|
+
title: title || "",
|
|
581
|
+
open: Boolean(open),
|
|
582
|
+
richText: Boolean(richText),
|
|
583
|
+
flag: flag || "",
|
|
584
|
+
icon: icon || "",
|
|
585
|
+
date: date || "",
|
|
586
|
+
subject: subject || "",
|
|
557
587
|
});
|
|
558
588
|
const { ox, oy } = this._reverseCoordinate(x, y - textHeight * 0.2);
|
|
589
|
+
|
|
559
590
|
this.annot(ox, oy, subtype, markupOption);
|
|
560
591
|
}
|
|
561
592
|
}
|
|
@@ -798,6 +829,9 @@ exports._layoutText = function _layoutText(textObjects, textBox, pathOptions) {
|
|
|
798
829
|
child.underline = textObject.underline
|
|
799
830
|
? textObject.underline
|
|
800
831
|
: child.underline;
|
|
832
|
+
child.strikeOut = textObject.strikeOut
|
|
833
|
+
? textObject.strikeOut
|
|
834
|
+
: child.strikeOut;
|
|
801
835
|
|
|
802
836
|
child.lineID = textObject.lineID;
|
|
803
837
|
writeValue(child);
|
|
@@ -1075,6 +1109,7 @@ function makeTextObjects(self, textObject = {}, pathOptions, textBox = {}) {
|
|
|
1075
1109
|
color: textObject.styles.color,
|
|
1076
1110
|
opacity: parseFloat(textObject.styles.opacity || pathOptions.opacity || 1),
|
|
1077
1111
|
underline: textObject.underline || pathOptions.underline,
|
|
1112
|
+
strikeOut: textObject.strikeOut || pathOptions.strikeOut,
|
|
1078
1113
|
size: textObject.size,
|
|
1079
1114
|
alignHorizontal: alignHorizontal,
|
|
1080
1115
|
alignVertical: alignVertical,
|
|
@@ -16,6 +16,7 @@ exports._getPathOptions = function _getPathOptions(
|
|
|
16
16
|
size: options.size || this.current.defaultFontSize,
|
|
17
17
|
charSpace: options.charSpace || 0,
|
|
18
18
|
underline: false,
|
|
19
|
+
strikeOut: false,
|
|
19
20
|
color: this._transformColor(options.color, {
|
|
20
21
|
colorspace: colorspace,
|
|
21
22
|
colorName: options.colorName,
|