@muhammara/native-core 7.0.0-beta.3 → 7.0.0-rc.1
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 +57 -7
- package/THIRD_PARTY_NOTICES.md +39 -0
- package/index.js +120 -1
- package/lib/PDFRStreamForBuffer.js +52 -7
- package/lib/PDFRStreamForFile.js +56 -7
- package/lib/PDFStreamForResponse.js +22 -5
- package/lib/PDFWStreamForBuffer.js +49 -10
- package/lib/PDFWStreamForFile.js +26 -5
- package/lib/Recipe.js +86 -30
- package/lib/content-stream.js +503 -0
- package/lib/css-colors.js +149 -0
- package/lib/font-text.js +1461 -0
- package/lib/glyph-list.js +1127 -0
- package/lib/recipe/annotation.js +482 -105
- package/lib/recipe/appendPage.js +8 -1
- package/lib/recipe/colors.js +132 -35
- package/lib/recipe/coordinate.js +82 -16
- package/lib/recipe/encrypt.js +32 -13
- package/lib/recipe/font.js +70 -25
- package/lib/recipe/graphics-state.js +3 -2
- package/lib/recipe/htmlToTextObjects.js +154 -21
- package/lib/recipe/image.js +34 -9
- package/lib/recipe/info.js +93 -22
- package/lib/recipe/insertPage.js +12 -3
- package/lib/recipe/overlay.js +4 -2
- package/lib/recipe/page-references.js +436 -0
- package/lib/recipe/page.js +379 -275
- package/lib/recipe/parameters.js +11 -2
- package/lib/recipe/replaceText.js +464 -30
- package/lib/recipe/shapes.js +418 -45
- package/lib/recipe/split.js +6 -2
- package/lib/recipe/table.js +260 -173
- package/lib/recipe/text.helper.js +176 -10
- package/lib/recipe/text.js +420 -115
- package/lib/recipe/utils.js +66 -3
- package/lib/recipe/vector-line.js +101 -39
- package/lib/recipe/vector-polygon.js +18 -6
- package/lib/recipe/vector.helper.js +150 -13
- package/lib/recipe/vector.js +150 -53
- package/lib/recipe/xObjectForm.js +73 -10
- package/lib/recipe-constants.js +373 -0
- package/muhammara.d.ts +3487 -152
- package/package.json +1 -1
package/lib/recipe/info.js
CHANGED
|
@@ -1,18 +1,51 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const muhammara = require("../muhammara");
|
|
3
3
|
var { recipeInfoKeys, standardInfoKeys } = require("../recipe-info");
|
|
4
|
+
|
|
5
|
+
// Source Info dictionary keys that _readInfo() keeps as raw values.
|
|
6
|
+
var PdfInfoKey = Object.freeze({
|
|
7
|
+
TRAPPED: "Trapped",
|
|
8
|
+
CREATION_DATE: "CreationDate",
|
|
9
|
+
MOD_DATE: "ModDate",
|
|
10
|
+
CREATOR: "Creator",
|
|
11
|
+
PRODUCER: "Producer",
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Names _readInfo() caches those entries under in this.infoDictionary.
|
|
15
|
+
var CachedInfoKey = Object.freeze({
|
|
16
|
+
TRAPPED: "trapped",
|
|
17
|
+
CREATION_DATE: "creationDate",
|
|
18
|
+
MOD_DATE: "modDate",
|
|
19
|
+
CREATOR: "creator",
|
|
20
|
+
PRODUCER: "producer",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// How _writeInfo() converts each standard info option.
|
|
24
|
+
var InfoFieldType = Object.freeze({
|
|
25
|
+
STRING: "string",
|
|
26
|
+
DATE: "date",
|
|
27
|
+
ARRAY: "array",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
var trappedValues = {
|
|
31
|
+
True: muhammara.EInfoTrappedTrue,
|
|
32
|
+
False: muhammara.EInfoTrappedFalse,
|
|
33
|
+
Unknown: muhammara.EInfoTrappedUnknown,
|
|
34
|
+
};
|
|
35
|
+
|
|
4
36
|
/**
|
|
5
37
|
* @name info
|
|
6
38
|
* @desc Add standard and custom PDF information, or retrieve existing PDF information. Custom keys retain their spelling when written; array values are joined with a comma and space.
|
|
7
39
|
* @memberof Recipe#
|
|
8
40
|
* @function
|
|
9
41
|
* @param {Object} [options] - The options (when missing obtains existing PDF information)
|
|
10
|
-
* @param {number} [options.version] - The pdf version
|
|
11
42
|
* @param {string} [options.author] - The author
|
|
12
43
|
* @param {string} [options.title] - The title
|
|
13
44
|
* @param {string} [options.subject] - The subject
|
|
14
45
|
* @param {string[]} [options.keywords] - The array of keywords
|
|
15
46
|
* @returns {Object|Recipe} The existing information dictionary when options are omitted, otherwise the recipe instance.
|
|
47
|
+
* A new PDF has no existing information, so the call without options returns undefined.
|
|
48
|
+
* @throws {Error} If the source information cannot be read.
|
|
16
49
|
*/
|
|
17
50
|
exports.info = function info(options) {
|
|
18
51
|
let result;
|
|
@@ -36,6 +69,15 @@ exports.info = function info(options) {
|
|
|
36
69
|
return result;
|
|
37
70
|
};
|
|
38
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Read the Info dictionary of the source PDF once and cache it as
|
|
74
|
+
* `this.infoDictionary`, with Trapped, CreationDate and ModDate as raw values
|
|
75
|
+
* and the other entries as text keyed by their lower-cased names.
|
|
76
|
+
* @private
|
|
77
|
+
* @returns {Object|undefined} The cached information, or undefined for a new
|
|
78
|
+
* PDF or a source without an Info dictionary.
|
|
79
|
+
* @throws {Error} If the source cannot be read.
|
|
80
|
+
*/
|
|
39
81
|
exports._readInfo = function _readInfo() {
|
|
40
82
|
if (!this.isNewPDF && !this.infoDictionary) {
|
|
41
83
|
const copyFrom = this.isBufferSrc
|
|
@@ -64,29 +106,32 @@ exports._readInfo = function _readInfo() {
|
|
|
64
106
|
return;
|
|
65
107
|
}
|
|
66
108
|
switch (key) {
|
|
67
|
-
case
|
|
109
|
+
case PdfInfoKey.TRAPPED:
|
|
68
110
|
if (oldInforSrc && oldInforSrc.value) {
|
|
69
|
-
this.infoDictionary.
|
|
111
|
+
this.infoDictionary[CachedInfoKey.TRAPPED] = oldInforSrc.value;
|
|
70
112
|
}
|
|
71
113
|
break;
|
|
72
|
-
case
|
|
114
|
+
case PdfInfoKey.CREATION_DATE:
|
|
73
115
|
if (oldInforSrc && oldInforSrc.value) {
|
|
74
|
-
this.infoDictionary.
|
|
116
|
+
this.infoDictionary[CachedInfoKey.CREATION_DATE] =
|
|
117
|
+
oldInforSrc.value;
|
|
75
118
|
}
|
|
76
119
|
break;
|
|
77
|
-
case
|
|
120
|
+
case PdfInfoKey.MOD_DATE:
|
|
78
121
|
if (oldInforSrc && oldInforSrc.value) {
|
|
79
|
-
this.infoDictionary.
|
|
122
|
+
this.infoDictionary[CachedInfoKey.MOD_DATE] = oldInforSrc.value;
|
|
80
123
|
}
|
|
81
124
|
break;
|
|
82
|
-
case
|
|
125
|
+
case PdfInfoKey.CREATOR:
|
|
83
126
|
if (oldInforSrc && oldInforSrc.toText) {
|
|
84
|
-
this.infoDictionary.
|
|
127
|
+
this.infoDictionary[CachedInfoKey.CREATOR] =
|
|
128
|
+
oldInforSrc.toText();
|
|
85
129
|
}
|
|
86
130
|
break;
|
|
87
|
-
case
|
|
131
|
+
case PdfInfoKey.PRODUCER:
|
|
88
132
|
if (oldInforSrc && oldInforSrc.toText) {
|
|
89
|
-
this.infoDictionary.
|
|
133
|
+
this.infoDictionary[CachedInfoKey.PRODUCER] =
|
|
134
|
+
oldInforSrc.toText();
|
|
90
135
|
}
|
|
91
136
|
break;
|
|
92
137
|
default:
|
|
@@ -104,6 +149,13 @@ exports._readInfo = function _readInfo() {
|
|
|
104
149
|
return this.infoDictionary;
|
|
105
150
|
};
|
|
106
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Write the Info dictionary: the preserved source entries, creation and
|
|
154
|
+
* modification dates, producer and creator, and the info() options.
|
|
155
|
+
* @private
|
|
156
|
+
* @returns {Recipe} The recipe instance.
|
|
157
|
+
* @throws {Error} If the source information cannot be read.
|
|
158
|
+
*/
|
|
107
159
|
exports._writeInfo = function _writeInfo() {
|
|
108
160
|
const options = this.toWriteInfo_ || {};
|
|
109
161
|
const oldInfo = this._readInfo();
|
|
@@ -116,7 +168,10 @@ exports._writeInfo = function _writeInfo() {
|
|
|
116
168
|
const infoDictionary = this.writer.getDocumentContext().getInfoDictionary();
|
|
117
169
|
var fields = standardInfoKeys.map((key) => ({
|
|
118
170
|
key,
|
|
119
|
-
type:
|
|
171
|
+
type:
|
|
172
|
+
key === recipeInfoKeys.keywords
|
|
173
|
+
? InfoFieldType.ARRAY
|
|
174
|
+
: InfoFieldType.STRING,
|
|
120
175
|
}));
|
|
121
176
|
// const ignores = [
|
|
122
177
|
// 'CreationDate', 'Creator', 'ModDate', 'Producer'
|
|
@@ -129,25 +184,28 @@ exports._writeInfo = function _writeInfo() {
|
|
|
129
184
|
}
|
|
130
185
|
|
|
131
186
|
switch (key) {
|
|
132
|
-
case
|
|
133
|
-
|
|
187
|
+
case CachedInfoKey.TRAPPED:
|
|
188
|
+
if (trappedValues[oldInfo[CachedInfoKey.TRAPPED]] !== undefined) {
|
|
189
|
+
infoDictionary.trapped =
|
|
190
|
+
trappedValues[oldInfo[CachedInfoKey.TRAPPED]];
|
|
191
|
+
}
|
|
134
192
|
break;
|
|
135
|
-
case
|
|
193
|
+
case CachedInfoKey.CREATION_DATE:
|
|
136
194
|
infoDictionary.setCreationDate(oldInfo.creationDate);
|
|
137
195
|
break;
|
|
138
|
-
case
|
|
196
|
+
case CachedInfoKey.MOD_DATE:
|
|
139
197
|
infoDictionary.addAdditionalInfoEntry(
|
|
140
198
|
"source-ModDate",
|
|
141
199
|
oldInfo.modDate,
|
|
142
200
|
);
|
|
143
201
|
break;
|
|
144
|
-
case
|
|
202
|
+
case CachedInfoKey.CREATOR:
|
|
145
203
|
infoDictionary.addAdditionalInfoEntry(
|
|
146
204
|
"source-Creator",
|
|
147
205
|
oldInfo.creator,
|
|
148
206
|
);
|
|
149
207
|
break;
|
|
150
|
-
case
|
|
208
|
+
case CachedInfoKey.PRODUCER:
|
|
151
209
|
infoDictionary.addAdditionalInfoEntry(
|
|
152
210
|
"source-Producer",
|
|
153
211
|
oldInfo.producer,
|
|
@@ -174,13 +232,13 @@ exports._writeInfo = function _writeInfo() {
|
|
|
174
232
|
return;
|
|
175
233
|
} else {
|
|
176
234
|
switch (item.type) {
|
|
177
|
-
case
|
|
235
|
+
case InfoFieldType.STRING:
|
|
178
236
|
value = value.toString();
|
|
179
237
|
break;
|
|
180
|
-
case
|
|
238
|
+
case InfoFieldType.DATE:
|
|
181
239
|
value = new Date(value);
|
|
182
240
|
break;
|
|
183
|
-
case
|
|
241
|
+
case InfoFieldType.ARRAY:
|
|
184
242
|
value = Array.isArray(value) ? value : [value];
|
|
185
243
|
break;
|
|
186
244
|
default:
|
|
@@ -201,8 +259,9 @@ exports._writeInfo = function _writeInfo() {
|
|
|
201
259
|
* @memberof Recipe#
|
|
202
260
|
* @function
|
|
203
261
|
* @param {string} key - The key
|
|
204
|
-
* @param {string} value - The value
|
|
262
|
+
* @param {string} value - The value; other values are converted with toString().
|
|
205
263
|
* @returns {Recipe} The recipe instance.
|
|
264
|
+
* @throws {TypeError} If the key or value is null or undefined.
|
|
206
265
|
*/
|
|
207
266
|
exports.custom = function custom(key, value) {
|
|
208
267
|
const infoDictionary = this.writer.getDocumentContext().getInfoDictionary();
|
|
@@ -217,6 +276,8 @@ exports.custom = function custom(key, value) {
|
|
|
217
276
|
* @memberof Recipe#
|
|
218
277
|
* @param {string} output - The output file path.
|
|
219
278
|
* @returns {Recipe} The recipe instance.
|
|
279
|
+
* @throws {Error} If the source reader was released by endPDF(), or the
|
|
280
|
+
* output file cannot be written.
|
|
220
281
|
*/
|
|
221
282
|
exports.structure = function structure(output) {
|
|
222
283
|
// PDF file format http://lotabout.me/orgwiki/pdf.html
|
|
@@ -324,6 +385,16 @@ exports.structure = function structure(output) {
|
|
|
324
385
|
return this;
|
|
325
386
|
};
|
|
326
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Resolve a source PDF object: follow references, recurse into arrays,
|
|
390
|
+
* dictionaries and stream dictionaries, and record leaf objects in
|
|
391
|
+
* `this.pdfStructure`.
|
|
392
|
+
* @private
|
|
393
|
+
* @param {Object} [inObject] - The parsed PDF object.
|
|
394
|
+
* @returns {Object|undefined} The resolved leaf object, or undefined for
|
|
395
|
+
* containers and a missing object.
|
|
396
|
+
* @throws {Error} If the source reader was released by endPDF().
|
|
397
|
+
*/
|
|
327
398
|
exports._parseObjectByType = function _parseObjectByType(inObject) {
|
|
328
399
|
if (!inObject) {
|
|
329
400
|
return;
|
package/lib/recipe/insertPage.js
CHANGED
|
@@ -6,10 +6,12 @@ const utils = require("./utils");
|
|
|
6
6
|
* @name insertPage
|
|
7
7
|
* @function
|
|
8
8
|
* @memberof Recipe#
|
|
9
|
-
* @param {number} afterPageNumber - The page number
|
|
9
|
+
* @param {number} afterPageNumber - The one-based page number to insert after; 0 inserts before the first page.
|
|
10
10
|
* @param {string} pdfSrc - The path for the other pdf
|
|
11
|
-
* @param {number} srcPageNumber - The page number to be
|
|
12
|
-
* @returns {Recipe} The recipe instance.
|
|
11
|
+
* @param {number} srcPageNumber - The one-based page number to be inserted from the other pdf.
|
|
12
|
+
* @returns {Recipe} The recipe instance. Pages are inserted by `endPDF()`;
|
|
13
|
+
* Buffer sources do not support insertion.
|
|
14
|
+
* @throws {Error} If pages were deleted with deletePage() on this Recipe.
|
|
13
15
|
* @throws {Error} If afterPageNumber is not a number.
|
|
14
16
|
* @throws {TypeError} If pdfSrc or srcPageNumber is missing.
|
|
15
17
|
*/
|
|
@@ -39,6 +41,13 @@ exports.insertPage = function insertPage(
|
|
|
39
41
|
return this;
|
|
40
42
|
};
|
|
41
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Rebuild the output file with the pages queued by insertPage() inserted
|
|
46
|
+
* after their target pages.
|
|
47
|
+
* @private
|
|
48
|
+
* @returns {Recipe} The recipe instance.
|
|
49
|
+
* @throws {Error} If nothing was queued, or a file cannot be read, renamed or written.
|
|
50
|
+
*/
|
|
42
51
|
exports._insertPages = function _insertPages() {
|
|
43
52
|
if (!this.insertInformation) {
|
|
44
53
|
throw new Error("No insertInformation");
|
package/lib/recipe/overlay.js
CHANGED
|
@@ -6,8 +6,8 @@ const { xObjectForm } = require("./xObjectForm");
|
|
|
6
6
|
* @function
|
|
7
7
|
* @memberof Recipe#
|
|
8
8
|
* @param {string} pdfSrc - The path for the overlay pdf
|
|
9
|
-
* @param {number|Object} [x=0] - The x
|
|
10
|
-
* @param {number} [y=0] - The
|
|
9
|
+
* @param {number|Object} [x=0] - The PDF x offset from the left edge, or options when using the two-argument form.
|
|
10
|
+
* @param {number} [y=0] - The offset from the top edge.
|
|
11
11
|
* @param {Object} [options] - The options.
|
|
12
12
|
* @param {number} [options.scale] - Scale the overlay pdf, default is 1
|
|
13
13
|
* @param {number} [options.page] - Page of the overlay pdf, default is 1
|
|
@@ -15,6 +15,8 @@ const { xObjectForm } = require("./xObjectForm");
|
|
|
15
15
|
* @param {boolean} [options.fitWidth] - To set the width to 100% (use with keepAspectRatio=true)
|
|
16
16
|
* @param {boolean} [options.fitHeight] - To set the height to 100% (use with keepAspectRatio=true)
|
|
17
17
|
* @returns {Recipe} The recipe instance.
|
|
18
|
+
* @throws {TypeError} If no page is active.
|
|
19
|
+
* @throws {Error} If the overlay PDF cannot be read.
|
|
18
20
|
*/
|
|
19
21
|
exports.overlay = function overlay(pdfSrc, x = 0, y = 0, options = {}) {
|
|
20
22
|
// allow to have only 2 arguments input
|