muhammara 3.6.0-beta.1 → 3.6.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +8 -3
  2. package/README.md +35 -6
  3. package/fonts/Courier New.ttf +0 -0
  4. package/fonts/Georgia.ttf +0 -0
  5. package/fonts/Helvetica-bold-italic.ttf +0 -0
  6. package/fonts/Helvetica-bold.ttf +0 -0
  7. package/fonts/Helvetica-italic.ttf +0 -0
  8. package/fonts/Helvetica.ttf +0 -0
  9. package/fonts/Roboto.ttf +0 -0
  10. package/fonts/arial.ttf +0 -0
  11. package/{PDFRStreamForBuffer.js → lib/PDFRStreamForBuffer.js} +0 -0
  12. package/{PDFRStreamForFile.js → lib/PDFRStreamForFile.js} +0 -0
  13. package/{PDFStreamForResponse.js → lib/PDFStreamForResponse.js} +0 -0
  14. package/{PDFWStreamForBuffer.js → lib/PDFWStreamForBuffer.js} +0 -0
  15. package/{PDFWStreamForFile.js → lib/PDFWStreamForFile.js} +0 -0
  16. package/lib/Recipe.js +325 -0
  17. package/lib/index.js +2 -0
  18. package/{muhammara.js → lib/muhammara.js} +1 -2
  19. package/lib/recipe/annotation.js +348 -0
  20. package/lib/recipe/appendPage.js +43 -0
  21. package/lib/recipe/colors.js +396 -0
  22. package/lib/recipe/coordinate.js +114 -0
  23. package/lib/recipe/encrypt.js +110 -0
  24. package/lib/recipe/font.js +126 -0
  25. package/lib/recipe/htmlToTextObjects.js +104 -0
  26. package/lib/recipe/image.js +125 -0
  27. package/lib/recipe/index.js +0 -0
  28. package/lib/recipe/info.js +354 -0
  29. package/lib/recipe/insertPage.js +86 -0
  30. package/lib/recipe/overlay.js +71 -0
  31. package/lib/recipe/page.js +289 -0
  32. package/lib/recipe/parameters.js +86 -0
  33. package/lib/recipe/shapes.js +1319 -0
  34. package/lib/recipe/split.js +26 -0
  35. package/lib/recipe/table.js +342 -0
  36. package/lib/recipe/text.helper.js +307 -0
  37. package/lib/recipe/text.js +1434 -0
  38. package/lib/recipe/utils.js +71 -0
  39. package/lib/recipe/vector-line.js +91 -0
  40. package/lib/recipe/vector-polygon.js +135 -0
  41. package/lib/recipe/vector.helper.js +272 -0
  42. package/lib/recipe/vector.js +552 -0
  43. package/lib/recipe/xObjectForm.js +108 -0
  44. package/node_modules/inherits/package.json +7 -1
  45. package/node_modules/mkdirp/package.json +1 -0
  46. package/node_modules/node-fetch/README.md +43 -0
  47. package/node_modules/node-fetch/browser.js +7 -7
  48. package/node_modules/node-fetch/lib/index.es.js +90 -2
  49. package/node_modules/node-fetch/lib/index.js +90 -2
  50. package/node_modules/node-fetch/lib/index.mjs +90 -2
  51. package/node_modules/node-fetch/package.json +19 -6
  52. package/node_modules/util-deprecate/package.json +5 -1
  53. package/package.json +18 -14
  54. package/src/ByteReaderWithPositionDriver.cpp +2 -0
  55. package/muhammara.d.ts +0 -806
package/CHANGELOG.md CHANGED
@@ -7,11 +7,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [3.6.0-beta.1] - 2022-12-21
10
+ ## [3.6.0] - 2023-01-24
11
11
 
12
12
  ### Added
13
13
 
14
14
  - Pre builts for arm64 / musl architecture (M1 using alpine)
15
+ - Hummus-recipe / Muhammara-recipe as part of this lib
16
+
17
+ ### Fixed
18
+
19
+ - Memory leak in ByteReaderWithPositionDriver when reading PDF files
15
20
 
16
21
  ## [3.5.0] - 2022-12-07
17
22
 
@@ -338,8 +343,8 @@ with the following changes.
338
343
 
339
344
  - Initial release
340
345
 
341
- [unreleased]: https://github.com/julianhille/MuhammaraJS/compare/3.6.0-beta.1...HEAD
342
- [3.6.0-beta.1]: https://github.com/julianhille/MuhammaraJS/compare/3.5.0...3.6.0-beta.1
346
+ [unreleased]: https://github.com/julianhille/MuhammaraJS/compare/3.6.0...HEAD
347
+ [3.6.0]: https://github.com/julianhille/MuhammaraJS/compare/3.5.0...3.6.0
343
348
  [3.5.0]: https://github.com/julianhille/MuhammaraJS/compare/3.4.0...3.5.0
344
349
  [3.4.0]: https://github.com/julianhille/MuhammaraJS/compare/3.3.0...3.4.0
345
350
  [3.3.0]: https://github.com/julianhille/MuhammaraJS/compare/3.2.0...3.3.0
package/README.md CHANGED
@@ -3,19 +3,28 @@
3
3
  [![NPM version](http://img.shields.io/npm/v/muhammara.svg?style=flat)](https://www.npmjs.org/package/muhammara)
4
4
  [![Build status](https://github.com/julianhille/MuhammaraJS/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/julianhille/MuhammaraJS/actions/workflows/build.yml)
5
5
 
6
+ Welcome to MuhammaraJS.
7
+ A Fast NodeJS Module for Creating, Parsing an Manipulating PDF Files and Streams.
8
+
9
+ Original Project (CPP base version)
10
+ Project site is [here](http://www.pdfhummus.com).
11
+
12
+ If you are looking for a C++ Library go [here](https://github.com/galkahana/PDF-Writer).
13
+
14
+ ## Hummus JS is the base
15
+
6
16
  This is a drop in replacement for hummusJS originally made by Galkahana.
7
17
  He did an awesome job, but discontinued hummusjs.
8
18
 
9
19
  The documentation for MuhammaraJS / HummusJS is still located at the
10
20
  hummusJS github wiki: available [here](https://github.com/galkahana/HummusJS/wiki)
11
21
 
12
- Welcome to HummusJS.
13
- A Fast NodeJS Module for Creating, Parsing an Manipulating PDF Files and Streams.
22
+ ## muhammara-recipe '(formerly known as hummus-recipe) as been added
14
23
 
15
- Original Project
16
- Project site is [here](http://www.pdfhummus.com).
24
+ Muhammara-recipe and hummus-recipe has been integrated, dependencies updated
25
+ and is now shipped along with muhammara itself.
17
26
 
18
- If you are looking for a C++ Library go [here](https://github.com/galkahana/PDF-Writer).
27
+ It serves as a drop in replacement.
19
28
 
20
29
  # Caution
21
30
 
@@ -36,7 +45,7 @@ npm install muhammara
36
45
 
37
46
  ```
38
47
 
39
- # Replace hummusJS with MuhammaraJS
48
+ # Replace hummusJS with MuhammaraJS for hummus
40
49
 
41
50
  Replace:
42
51
 
@@ -50,6 +59,26 @@ With:
50
59
  let muhammara = require('muhammara')
51
60
  ```
52
61
 
62
+ # Replace hummus-recipe or muhammara-recipe with MuhammaraJS
63
+
64
+ Replace:
65
+
66
+ `const HummusRecipe = require('hummus-recipe');`
67
+
68
+ With:
69
+
70
+ ```
71
+ const HummusRecipe = require('muhammara').Receipe;
72
+ ```
73
+
53
74
  # Documentation
54
75
 
76
+ ## Muhammara
77
+
55
78
  You can find samples and documentation [here](./docs/Home.md)
79
+
80
+ ### Muhammara Recipe:
81
+
82
+ To generate the documentation you could clone this repo and execute:
83
+
84
+ `npm run recipe-jsdoc`
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/lib/Recipe.js ADDED
@@ -0,0 +1,325 @@
1
+ const muhammara = require("./muhammara");
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const streams = require("memory-streams");
5
+
6
+ /**
7
+ * @name Recipe
8
+ * @desc Create a pdfDoc
9
+ * @namespace
10
+ * @constructor
11
+ * @param {string} src - The file path or Buffer of the src file.
12
+ * @param {string} output - The path of the output file.
13
+ * @param {Object} [options] - The options for pdfDoc
14
+ * @param {number} [options.version] - The pdf version
15
+ * @param {string} [options.author] - The author
16
+ * @param {string} [options.title] - The title
17
+ * @param {string} [options.subject] - The subject
18
+ * @param {string} [options.colorspace] - The default colorspace: rgb, cmyk, gray
19
+ * @param {string[]} [options.keywords] - The array of keywords
20
+ * @param {string} [options.password] - permission password
21
+ * @param {string} [options.userPassword] - this 'view' password also enables encryption
22
+ * @param {string} [options.ownerPassword] - this allows owner to 'edit' file
23
+ * @param {string} [options.userProtectionFlag] - encryption security level (see permissions)
24
+ * @param {string|string[]} [options.fontSrcPath] - directory location(s) of additional fonts
25
+ */
26
+ class Recipe {
27
+ constructor(src, output, options = {}) {
28
+ this.src = src;
29
+ // detect the src is Buffer or not
30
+ this.isBufferSrc = this.src instanceof Buffer;
31
+ this.isNewPDF = !this.isBufferSrc && src.toLowerCase() === "new";
32
+ this.encryptOptions = this._getEncryptOptions(options, this.isNewPDF);
33
+ this.options = Object.assign({}, options, this.encryptOptions);
34
+ this.current = {};
35
+ this.current.defaultFontSize = 14;
36
+
37
+ if (this.isBufferSrc) {
38
+ this.outStream = new streams.WritableStream();
39
+ this.output = output;
40
+ } else {
41
+ this.output = output || src;
42
+ if (this.src) {
43
+ this.filename = path.basename(this.src);
44
+ }
45
+ }
46
+ this.muhammara = muhammara;
47
+ this.logFile = "muhammara-error.log";
48
+
49
+ this.textMarkupAnnotations = [
50
+ "Highlight",
51
+ "Underline",
52
+ "StrikeOut",
53
+ "Squiggly",
54
+ ];
55
+
56
+ this.annotationsToWrite = [];
57
+ this.annotations = [];
58
+ this.vectorsToWrite = [];
59
+
60
+ this.xObjects = [];
61
+
62
+ this.needToEncrypt = false;
63
+
64
+ this.needToInsertPages = false;
65
+
66
+ this._setParameters(options);
67
+
68
+ this._loadFonts(path.join(__dirname, "../fonts"));
69
+
70
+ if (options.fontSrcPath) {
71
+ this._loadFonts(options.fontSrcPath);
72
+ }
73
+ this._createWriter();
74
+ }
75
+
76
+ _createWriter() {
77
+ if (this.isNewPDF) {
78
+ this.writer = muhammara.createWriter(
79
+ this.output,
80
+ Object.assign({}, this.encryptOptions, {
81
+ version: this._getVersion(this.options.version),
82
+ })
83
+ );
84
+ } else {
85
+ this.read();
86
+ try {
87
+ if (this.isBufferSrc) {
88
+ this.writer = muhammara.createWriterToModify(
89
+ new muhammara.PDFRStreamForBuffer(this.src),
90
+ new muhammara.PDFStreamForResponse(this.outStream),
91
+ Object.assign({}, this.encryptOptions, {
92
+ log: this.logFile,
93
+ })
94
+ );
95
+ } else {
96
+ this.writer = muhammara.createWriterToModify(
97
+ this.src,
98
+ Object.assign({}, this.encryptOptions, {
99
+ modifiedFilePath: this.output,
100
+ log: this.logFile,
101
+ })
102
+ );
103
+ }
104
+ } catch (err) {
105
+ throw new Error(err);
106
+ }
107
+ }
108
+
109
+ this.info(this.options);
110
+ }
111
+
112
+ _getVersion(version) {
113
+ const supportedVersions = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7];
114
+ if (!supportedVersions.includes(version)) {
115
+ version = 1.7;
116
+ }
117
+ version = muhammara[`ePDFVersion${version * 10}`];
118
+
119
+ return version;
120
+ }
121
+
122
+ get position() {
123
+ const { ox, oy } = this._reverseCoordinate(
124
+ this._position.x,
125
+ this._position.y
126
+ );
127
+ return {
128
+ x: ox,
129
+ y: oy,
130
+ };
131
+ }
132
+
133
+ read(inSrc) {
134
+ const isForExternal = inSrc ? true : false;
135
+ try {
136
+ let src = isForExternal ? inSrc : this.src;
137
+ if (this.isBufferSrc) {
138
+ src = new muhammara.PDFRStreamForBuffer(this.src);
139
+ }
140
+ const pdfReader = muhammara.createReader(src, this.encryptOptions);
141
+ const pages = pdfReader.getPagesCount();
142
+ if (pages == 0) {
143
+ // broken or modify password protected
144
+ throw "HummusJS: Unable to read/edit PDF file (pages=0)";
145
+ }
146
+ const metadata = {
147
+ pages,
148
+ };
149
+ for (var i = 0; i < pages; i++) {
150
+ const info = pdfReader.parsePage(i);
151
+ const dimensions = info.getMediaBox();
152
+ const rotate = info.getRotate();
153
+
154
+ let layout, width, height, pageSize;
155
+ let side1 = Math.abs(dimensions[2] - dimensions[0]);
156
+ let side2 = Math.abs(dimensions[3] - dimensions[1]);
157
+ if (side1 > side2 && rotate % 180 === 0) {
158
+ layout = "landscape";
159
+ } else if (side1 < side2 && rotate % 180 !== 0) {
160
+ layout = "landscape";
161
+ } else {
162
+ layout = "portrait";
163
+ }
164
+
165
+ if (layout === "landscape") {
166
+ width = side1 > side2 ? side1 : side2;
167
+ height = side1 > side2 ? side2 : side1;
168
+ } else {
169
+ width = side1 > side2 ? side2 : side1;
170
+ height = side1 > side2 ? side1 : side2;
171
+ }
172
+
173
+ pageSize = [width, height].sort((a, b) => {
174
+ return a > b ? 1 : -1;
175
+ });
176
+
177
+ const page = {
178
+ pageNumber: i + 1,
179
+ mediaBox: dimensions,
180
+ layout,
181
+ rotate,
182
+ width,
183
+ height,
184
+ size: pageSize,
185
+ // usually 0
186
+ offsetX: dimensions[0],
187
+ offsetY: dimensions[1],
188
+ };
189
+ metadata[page.pageNumber] = page;
190
+ }
191
+ if (!isForExternal) {
192
+ this.pdfReader = pdfReader;
193
+ this.metadata = metadata;
194
+ }
195
+ return metadata;
196
+ } catch (err) {
197
+ throw new Error(err);
198
+ }
199
+ }
200
+
201
+ /**
202
+ * End the pdfDoc
203
+ * @function
204
+ * @memberof Recipe
205
+ * @param {function} callback - The callback function.
206
+ */
207
+ endPDF(callback) {
208
+ this._writeInfo();
209
+ this.writer.end();
210
+ // This is a temporary work around for copying context will overwrite the current one
211
+ // write annotations at the end.
212
+ if (
213
+ (this.annotations && this.annotations.length > 0) ||
214
+ (this.annotationsToWrite && this.annotationsToWrite.length > 0)
215
+ ) {
216
+ if (this.isBufferSrc) {
217
+ const oldStream = this.outStream;
218
+ this.outStream = new streams.WritableStream();
219
+
220
+ this.writer = muhammara.createWriterToModify(
221
+ new muhammara.PDFRStreamForBuffer(oldStream.toBuffer()),
222
+ new muhammara.PDFStreamForResponse(this.outStream),
223
+ Object.assign({}, this.encryptOptions, {
224
+ log: this.logFile,
225
+ })
226
+ );
227
+ } else {
228
+ this.writer = muhammara.createWriterToModify(
229
+ this.output,
230
+ Object.assign({}, this.encryptOptions, {
231
+ modifiedFilePath: this.output,
232
+ log: this.logFile,
233
+ })
234
+ );
235
+ }
236
+
237
+ this._writeAnnotations();
238
+ this._writeInfo();
239
+ this.writer.end();
240
+ }
241
+ if (this.needToInsertPages) {
242
+ if (this.isBufferSrc) {
243
+ // eslint-disable-next-line no-console
244
+ console.log(
245
+ "Feature: Inserting Pages is not supported in Buffer Mode yet."
246
+ );
247
+ } else {
248
+ this._insertPages();
249
+ }
250
+ }
251
+ if (this.needToEncrypt) {
252
+ if (this.isBufferSrc) {
253
+ // eslint-disable-next-line no-console
254
+ console.log("Feature: Encryption is not supported in Buffer Mode yet.");
255
+ } else {
256
+ this._encrypt();
257
+ }
258
+ }
259
+
260
+ if (this.isBufferSrc && this.output) {
261
+ fs.writeFileSync(this.output, this.outStream.toBuffer());
262
+ }
263
+
264
+ if (callback) {
265
+ if (this.isBufferSrc) {
266
+ if (this.output) {
267
+ return callback(this.output);
268
+ } else {
269
+ return callback(this.outStream.toBuffer());
270
+ }
271
+ } else {
272
+ return callback();
273
+ }
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Register callback procedure with hummus-recipe.
279
+ * @function
280
+ * @memberof Recipe
281
+ * @param {string} key name assigned to given callback. Note that if an actual function is being
282
+ * registered, and its given name is what is to be used to access it, the key is unnecessary.
283
+ * @param {Function} callback procedure that can be accessed through hummus-recipe
284
+ */
285
+ register(key, callback) {
286
+ // Assume simply registering a function which will have an embedded name
287
+ if (typeof key !== "string") {
288
+ if (!key.name) {
289
+ throw "Cannot register unnamed callback function. Provide 'name' as first argument, then callback function.";
290
+ }
291
+ callback = key;
292
+ key = key.name;
293
+ }
294
+
295
+ if (this.__proto__[key]) {
296
+ throw `Found conflict in Recipe prototypes. ${key} already exists.`;
297
+ }
298
+
299
+ if (typeof callback !== "function") {
300
+ throw `${key} expecting callback to be of type function.`;
301
+ }
302
+
303
+ this.__proto__[key] = callback;
304
+ }
305
+ }
306
+
307
+ function loadPrototypes() {
308
+ const ignores = ["xObjectForm.js"];
309
+ fs.readdirSync(path.join(__dirname, "recipe"))
310
+ .filter((file) => {
311
+ return file[0] != "." && !ignores.includes(file);
312
+ })
313
+ .forEach((file) => {
314
+ const module = require(path.join(__dirname, "recipe", file));
315
+ for (let key in module) {
316
+ if (Recipe.prototype[key]) {
317
+ throw `Found conflict prototypes=${key} in ${file}.`;
318
+ }
319
+ Recipe.prototype[key] = module[key];
320
+ }
321
+ });
322
+ }
323
+
324
+ loadPrototypes();
325
+ module.exports = Recipe;
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ module.exports = require("./muhammara");
2
+ module.exports.Recipe = require("./Recipe.js");
@@ -1,8 +1,7 @@
1
- var fs = require("fs");
2
1
  var path = require("path");
3
2
  var pregyp = require("@mapbox/node-pre-gyp");
4
3
  var binding_path = pregyp.find(
5
- path.resolve(path.join(__dirname, "./package.json"))
4
+ path.resolve(path.join(__dirname, "../package.json"))
6
5
  );
7
6
  var muhammara = (module.exports = require(binding_path));
8
7
  var EventEmitter = require("events").EventEmitter;