@muhammara/native-core 7.0.0-beta.4 → 7.0.0-rc.2

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 (44) hide show
  1. package/README.md +57 -7
  2. package/THIRD_PARTY_NOTICES.md +39 -0
  3. package/index.js +120 -1
  4. package/lib/PDFRStreamForBuffer.js +52 -7
  5. package/lib/PDFRStreamForFile.js +56 -7
  6. package/lib/PDFStreamForResponse.js +22 -5
  7. package/lib/PDFWStreamForBuffer.js +49 -10
  8. package/lib/PDFWStreamForFile.js +26 -5
  9. package/lib/Recipe.js +91 -38
  10. package/lib/content-stream.js +503 -0
  11. package/lib/css-colors.js +149 -0
  12. package/lib/font-text.js +1461 -0
  13. package/lib/glyph-list.js +1127 -0
  14. package/lib/recipe/annotation.js +464 -101
  15. package/lib/recipe/appendPage.js +2 -0
  16. package/lib/recipe/colors.js +132 -35
  17. package/lib/recipe/coordinate.js +82 -16
  18. package/lib/recipe/encrypt.js +32 -13
  19. package/lib/recipe/font.js +70 -25
  20. package/lib/recipe/graphics-state.js +3 -2
  21. package/lib/recipe/htmlToTextObjects.js +121 -24
  22. package/lib/recipe/image.js +385 -39
  23. package/lib/recipe/info.js +93 -22
  24. package/lib/recipe/insertPage.js +12 -3
  25. package/lib/recipe/overlay.js +4 -2
  26. package/lib/recipe/page-references.js +436 -0
  27. package/lib/recipe/page.js +363 -262
  28. package/lib/recipe/parameters.js +8 -1
  29. package/lib/recipe/replaceText.js +464 -30
  30. package/lib/recipe/shapes.js +418 -45
  31. package/lib/recipe/split.js +6 -2
  32. package/lib/recipe/table.js +41 -8
  33. package/lib/recipe/text.helper.js +172 -8
  34. package/lib/recipe/text.js +294 -56
  35. package/lib/recipe/utils.js +17 -6
  36. package/lib/recipe/vector-line.js +101 -39
  37. package/lib/recipe/vector-polygon.js +18 -6
  38. package/lib/recipe/vector.helper.js +156 -14
  39. package/lib/recipe/vector.js +156 -52
  40. package/lib/recipe/xObjectForm.js +73 -10
  41. package/lib/recipe-constants.js +373 -0
  42. package/lib/recipe-options.js +47 -0
  43. package/muhammara.d.ts +3501 -160
  44. package/package.json +2 -3
@@ -0,0 +1,503 @@
1
+ // Content-stream tokenizing, string and name tokens, and page-resource lookup
2
+ // shared by the Recipe text operations and the font decoder. Mirrored in
3
+ // packages/wasm/lib/content-stream.js; keep both files identical apart from the
4
+ // module syntax.
5
+
6
+ var WHITESPACE = "\0\t\n\f\r ";
7
+ var DELIMITERS = "()<>[]{}/%";
8
+
9
+ // Content-stream delimiters that start or end a token.
10
+ var Delimiter = Object.freeze({
11
+ LITERAL_STRING_START: "(",
12
+ LITERAL_STRING_END: ")",
13
+ LITERAL_STRING_ESCAPE: "\\",
14
+ HEX_STRING_START: "<",
15
+ HEX_STRING_END: ">",
16
+ DICTIONARY_START: "<<",
17
+ DICTIONARY_END: ">>",
18
+ ARRAY_START: "[",
19
+ ARRAY_END: "]",
20
+ PROCEDURE_START: "{",
21
+ PROCEDURE_END: "}",
22
+ NAME_START: "/",
23
+ COMMENT_START: "%",
24
+ });
25
+
26
+ // Kinds of operand token callers tell apart.
27
+ var TokenKind = Object.freeze({
28
+ LITERAL_STRING: "literalString",
29
+ HEX_STRING: "hexString",
30
+ NAME: "name",
31
+ OTHER: "other",
32
+ });
33
+
34
+ // Literal-string escapes that stand for a control character.
35
+ var LITERAL_ESCAPES = Object.freeze({
36
+ n: "\n",
37
+ r: "\r",
38
+ t: "\t",
39
+ b: "\b",
40
+ f: "\f",
41
+ });
42
+
43
+ // Content-stream operators the tokenizer and its callers interpret.
44
+ var PdfOperator = Object.freeze({
45
+ SHOW_TEXT: "Tj",
46
+ SHOW_TEXT_ARRAY: "TJ",
47
+ NEXT_LINE_SHOW_TEXT: "'",
48
+ SPACING_NEXT_LINE_SHOW_TEXT: '"',
49
+ PAINT_XOBJECT: "Do",
50
+ INLINE_IMAGE_DATA: "ID",
51
+ END_INLINE_IMAGE: "EI",
52
+ SET_FONT: "Tf",
53
+ SAVE_STATE: "q",
54
+ RESTORE_STATE: "Q",
55
+ });
56
+
57
+ // Content-stream keywords that are operands, not operators.
58
+ var PdfKeyword = Object.freeze({
59
+ TRUE: "true",
60
+ FALSE: "false",
61
+ NULL: "null",
62
+ });
63
+
64
+ // Page-tree keys followed for inherited resources.
65
+ var PdfName = Object.freeze({
66
+ PARENT: "Parent",
67
+ RESOURCES: "Resources",
68
+ });
69
+
70
+ // The error both extractors throw when a page exceeds its extraction limits.
71
+ var EXTRACTION_LIMIT_MESSAGE = "Page content exceeds text extraction limits";
72
+
73
+ // Errors created by `extractionLimitError`, so best-effort fallbacks can let
74
+ // them through.
75
+ var extractionLimitErrors = new WeakSet();
76
+
77
+ // Most page-tree ancestors followed for inherited resources. The visited set
78
+ // already stops cycles; this bounds pathological trees.
79
+ var MAX_PAGE_TREE_DEPTH = 256;
80
+
81
+ /**
82
+ * Check whether a content-stream character is PDF whitespace.
83
+ *
84
+ * @param {string} character One character.
85
+ * @returns {boolean} True for PDF whitespace.
86
+ */
87
+ function isWhitespace(character) {
88
+ return character !== "" && WHITESPACE.includes(character);
89
+ }
90
+
91
+ /**
92
+ * Check whether a content-stream character ends a regular token.
93
+ *
94
+ * @param {string} character One character, or an empty string at the end.
95
+ * @returns {boolean} True for whitespace, delimiters, and the end of input.
96
+ */
97
+ function endsRegularToken(character) {
98
+ return (
99
+ character === "" ||
100
+ isWhitespace(character) ||
101
+ DELIMITERS.includes(character)
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Find the end of a literal string that starts at `start`.
107
+ *
108
+ * @param {string} source Latin-1 content stream.
109
+ * @param {number} start Offset of the opening parenthesis.
110
+ * @returns {number} Offset after the closing parenthesis.
111
+ */
112
+ function skipLiteralString(source, start) {
113
+ var depth = 0;
114
+ for (var index = start; index < source.length; index++) {
115
+ var character = source[index];
116
+ if (character === Delimiter.LITERAL_STRING_ESCAPE) {
117
+ index++;
118
+ } else if (character === Delimiter.LITERAL_STRING_START) {
119
+ depth++;
120
+ } else if (character === Delimiter.LITERAL_STRING_END) {
121
+ depth--;
122
+ if (depth === 0) return index + 1;
123
+ }
124
+ }
125
+ return source.length;
126
+ }
127
+
128
+ /**
129
+ * Find the end of inline image data after its `ID` operator.
130
+ *
131
+ * @param {string} source Latin-1 content stream.
132
+ * @param {number} start Offset directly after `ID`.
133
+ * @returns {number} Offset after the closing `EI` operator.
134
+ */
135
+ function skipInlineImageData(source, start) {
136
+ for (var index = start + 1; index < source.length - 1; index++) {
137
+ if (
138
+ source.startsWith(PdfOperator.END_INLINE_IMAGE, index) &&
139
+ isWhitespace(source[index - 1]) &&
140
+ endsRegularToken(source.charAt(index + 2))
141
+ ) {
142
+ return index + 2;
143
+ }
144
+ }
145
+ return source.length;
146
+ }
147
+
148
+ /**
149
+ * Call `callback` for every operator in a content stream, in order. Operands
150
+ * inside arrays and dictionaries are not reported separately; inline image
151
+ * data is skipped and belongs to its `ID` operator.
152
+ *
153
+ * @param {string} source Latin-1 content stream.
154
+ * @param {function({operator: string, operands: Array<{token: string, start:
155
+ * number, end: number}>, end: number}): void} callback Receives each
156
+ * operator, its top-level operand tokens with their offsets, and the offset
157
+ * after the operator.
158
+ * @returns {void}
159
+ */
160
+ function forEachOperation(source, callback) {
161
+ var operands = [];
162
+ var depth = 0;
163
+ var index = 0;
164
+
165
+ while (index < source.length) {
166
+ var character = source[index];
167
+ var start = index;
168
+
169
+ if (isWhitespace(character)) {
170
+ index++;
171
+ continue;
172
+ }
173
+ if (character === Delimiter.COMMENT_START) {
174
+ while (
175
+ index < source.length &&
176
+ source[index] !== "\n" &&
177
+ source[index] !== "\r"
178
+ ) {
179
+ index++;
180
+ }
181
+ continue;
182
+ }
183
+ if (character === Delimiter.LITERAL_STRING_START) {
184
+ index = skipLiteralString(source, index);
185
+ } else if (source.startsWith(Delimiter.DICTIONARY_START, index)) {
186
+ depth++;
187
+ index += 2;
188
+ } else if (source.startsWith(Delimiter.DICTIONARY_END, index)) {
189
+ depth--;
190
+ index += 2;
191
+ } else if (character === Delimiter.HEX_STRING_START) {
192
+ index = source.indexOf(Delimiter.HEX_STRING_END, index);
193
+ index = index === -1 ? source.length : index + 1;
194
+ } else if (
195
+ character === Delimiter.ARRAY_START ||
196
+ character === Delimiter.PROCEDURE_START
197
+ ) {
198
+ depth++;
199
+ index++;
200
+ } else if (
201
+ character === Delimiter.ARRAY_END ||
202
+ character === Delimiter.PROCEDURE_END
203
+ ) {
204
+ depth--;
205
+ index++;
206
+ } else if (character === Delimiter.NAME_START) {
207
+ index++;
208
+ while (!endsRegularToken(source.charAt(index))) index++;
209
+ } else {
210
+ while (!endsRegularToken(source.charAt(index))) index++;
211
+ if (index === start) index++;
212
+ }
213
+
214
+ var token = source.slice(start, index);
215
+ var isOperator =
216
+ depth <= 0 &&
217
+ /^[A-Za-z'"*]/.test(token) &&
218
+ !Object.values(PdfKeyword).includes(token);
219
+
220
+ if (!isOperator) {
221
+ if (depth <= 0) operands.push({ token: token, start: start, end: index });
222
+ continue;
223
+ }
224
+
225
+ if (token === PdfOperator.INLINE_IMAGE_DATA) {
226
+ index = skipInlineImageData(source, index);
227
+ }
228
+ callback({ operator: token, operands: operands, end: index });
229
+ operands = [];
230
+ depth = 0;
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Tell which kind of operand a token is.
236
+ *
237
+ * @param {string} token Operand token.
238
+ * @returns {string} A `TokenKind` value.
239
+ */
240
+ function tokenKind(token) {
241
+ if (token.startsWith(Delimiter.LITERAL_STRING_START)) {
242
+ return TokenKind.LITERAL_STRING;
243
+ }
244
+ if (
245
+ token.startsWith(Delimiter.HEX_STRING_START) &&
246
+ !token.startsWith(Delimiter.DICTIONARY_START)
247
+ ) {
248
+ return TokenKind.HEX_STRING;
249
+ }
250
+ if (token.startsWith(Delimiter.NAME_START)) return TokenKind.NAME;
251
+ return TokenKind.OTHER;
252
+ }
253
+
254
+ /**
255
+ * Decode a content-stream name token such as `/Fm#201`. The name's bytes are
256
+ * read as UTF-8, as PDF dictionary keys are, so the result can be looked up in
257
+ * a resource dictionary.
258
+ *
259
+ * @param {string} token Name token including the leading slash.
260
+ * @returns {string} Name without the slash, with `#xx` escapes decoded.
261
+ */
262
+ function decodeName(token) {
263
+ var bytes = token.slice(1).replace(/#([0-9A-Fa-f]{2})/g, decodeNameEscape);
264
+ return /^[\x00-\x7f]*$/.test(bytes) ? bytes : utf8Text(bytes);
265
+ }
266
+
267
+ /**
268
+ * Decode one `#xx` escape of a name token.
269
+ *
270
+ * @param {string} escape The whole escape, such as `#20`.
271
+ * @param {string} hex Its two hexadecimal digits.
272
+ * @returns {string} The escaped byte, as a character.
273
+ */
274
+ function decodeNameEscape(escape, hex) {
275
+ return String.fromCharCode(parseInt(hex, 16));
276
+ }
277
+
278
+ /**
279
+ * Decode a one-byte string as UTF-8.
280
+ *
281
+ * @param {string} bytes One character per byte.
282
+ * @returns {string} Decoded text; invalid sequences become U+FFFD.
283
+ */
284
+ function utf8Text(bytes) {
285
+ var array = new Uint8Array(bytes.length);
286
+ for (var index = 0; index < bytes.length; index++) {
287
+ array[index] = bytes.charCodeAt(index);
288
+ }
289
+ return new TextDecoder().decode(array);
290
+ }
291
+
292
+ /**
293
+ * Decode the bytes of a literal string token such as `(caf\351)`.
294
+ *
295
+ * @param {string} token Literal string token including parentheses.
296
+ * @returns {string} Operand bytes, one character per byte.
297
+ */
298
+ function literalStringBytes(token) {
299
+ return token
300
+ .slice(1, -1)
301
+ .replace(/\r\n?/g, "\n")
302
+ .replace(/\\([0-7]{1,3}|\n|[\s\S])/g, unescapeLiteral);
303
+ }
304
+
305
+ /**
306
+ * Decode one backslash escape of a literal string.
307
+ *
308
+ * @param {string} sequence The whole escape, including the backslash.
309
+ * @param {string} escape The escaped text after the backslash.
310
+ * @returns {string} The byte it stands for; an escaped line break is dropped.
311
+ */
312
+ function unescapeLiteral(sequence, escape) {
313
+ if (/^[0-7]/.test(escape)) {
314
+ return String.fromCharCode(parseInt(escape, 8) & 0xff);
315
+ }
316
+ if (escape === "\n") return "";
317
+ return LITERAL_ESCAPES[escape] || escape;
318
+ }
319
+
320
+ /**
321
+ * Decode hexadecimal digits to bytes, ignoring anything else and padding an
322
+ * odd final digit with zero.
323
+ *
324
+ * @param {string} digits Hexadecimal digits, possibly with whitespace.
325
+ * @returns {string} Bytes, one character per byte.
326
+ */
327
+ function hexBytes(digits) {
328
+ var hex = digits.replace(/[^0-9A-Fa-f]/g, "");
329
+ if (hex.length % 2) hex += "0";
330
+ var bytes = "";
331
+ for (var index = 0; index < hex.length; index += 2) {
332
+ bytes += String.fromCharCode(parseInt(hex.slice(index, index + 2), 16));
333
+ }
334
+ return bytes;
335
+ }
336
+
337
+ /**
338
+ * Decode the bytes of a hex string token such as `<0048>`.
339
+ *
340
+ * @param {string} token Hex string token including angle brackets.
341
+ * @returns {string} Operand bytes, one character per byte.
342
+ */
343
+ function hexStringBytes(token) {
344
+ return hexBytes(token.slice(1, -1));
345
+ }
346
+
347
+ /**
348
+ * Decode the bytes of a literal or hex string token.
349
+ *
350
+ * @param {string} token String token.
351
+ * @returns {string} Operand bytes, one character per byte.
352
+ */
353
+ function stringBytes(token) {
354
+ return tokenKind(token) === TokenKind.HEX_STRING
355
+ ? hexStringBytes(token)
356
+ : literalStringBytes(token);
357
+ }
358
+
359
+ /**
360
+ * Write bytes as a string token of the given kind.
361
+ *
362
+ * @param {string} bytes Operand bytes, one character per byte.
363
+ * @param {string} kind `TokenKind.HEX_STRING` or `TokenKind.LITERAL_STRING`.
364
+ * @returns {string} Hex or literal string token.
365
+ */
366
+ function stringToken(bytes, kind) {
367
+ if (kind === TokenKind.HEX_STRING) {
368
+ var hex = "";
369
+ for (var index = 0; index < bytes.length; index++) {
370
+ hex += ("0" + bytes.charCodeAt(index).toString(16).toUpperCase()).slice(
371
+ -2,
372
+ );
373
+ }
374
+ return Delimiter.HEX_STRING_START + hex + Delimiter.HEX_STRING_END;
375
+ }
376
+ return (
377
+ Delimiter.LITERAL_STRING_START +
378
+ bytes.replace(/[\\()]|[\x00-\x1f]/g, escapeLiteral) +
379
+ Delimiter.LITERAL_STRING_END
380
+ );
381
+ }
382
+
383
+ /**
384
+ * Escape one byte for a literal string: backslashes and parentheses get a
385
+ * backslash, control characters an octal escape.
386
+ *
387
+ * @param {string} character One byte as a character.
388
+ * @returns {string} The escaped byte.
389
+ */
390
+ function escapeLiteral(character) {
391
+ if (/[\\()]/.test(character)) return "\\" + character;
392
+ return "\\" + ("00" + character.charCodeAt(0).toString(8)).slice(-3);
393
+ }
394
+
395
+ /**
396
+ * Read a whole stream as a one-byte string.
397
+ *
398
+ * @param {object} reader PDF reader or parser.
399
+ * @param {object} stream PDF stream object.
400
+ * @param {number} [maxBytes] Most decoded bytes to read.
401
+ * @returns {string|null} Decoded stream bytes, one character per byte, or
402
+ * null when the stream is longer than `maxBytes`.
403
+ */
404
+ function readStreamString(reader, stream, maxBytes) {
405
+ var streamReader = reader.startReadingFromStream(stream);
406
+ var source = "";
407
+ try {
408
+ while (streamReader.notEnded()) {
409
+ var chunk = streamReader.read(65536);
410
+ var bytes = ArrayBuffer.isView(chunk) ? chunk : Uint8Array.from(chunk);
411
+ if (maxBytes !== undefined && source.length + bytes.length > maxBytes) {
412
+ return null;
413
+ }
414
+ for (var offset = 0; offset < bytes.length; offset += 0x8000) {
415
+ source += String.fromCharCode.apply(
416
+ null,
417
+ bytes.subarray(offset, offset + 0x8000),
418
+ );
419
+ }
420
+ }
421
+ } finally {
422
+ if (typeof streamReader.dispose === "function") streamReader.dispose();
423
+ }
424
+ return source;
425
+ }
426
+
427
+ /**
428
+ * Create the error thrown when decoding would exceed the caller's extraction
429
+ * limits. Its message matches the extractors' own limit error.
430
+ *
431
+ * @returns {Error} The error.
432
+ */
433
+ function extractionLimitError() {
434
+ var error = new Error(EXTRACTION_LIMIT_MESSAGE);
435
+ extractionLimitErrors.add(error);
436
+ return error;
437
+ }
438
+
439
+ /**
440
+ * Check whether an error is an extraction limit error.
441
+ *
442
+ * @param {*} error Caught value.
443
+ * @returns {boolean} True for errors from `extractionLimitError`.
444
+ */
445
+ function isExtractionLimitError(error) {
446
+ return typeof error === "object" && error !== null
447
+ ? extractionLimitErrors.has(error)
448
+ : false;
449
+ }
450
+
451
+ /**
452
+ * Find the resources dictionary that applies to a page, following `/Parent`
453
+ * inheritance. A page-tree cycle or an unreadable ancestor ends the search;
454
+ * an extraction limit error is rethrown.
455
+ *
456
+ * @param {object} reader PDF reader or parser.
457
+ * @param {object} types PDF object type constants.
458
+ * @param {object} page Page dictionary.
459
+ * @returns {object|null} Resources dictionary, or null when none applies.
460
+ */
461
+ function inheritedResources(reader, types, page) {
462
+ var visited = new Set();
463
+ var node = page;
464
+ try {
465
+ for (var depth = 0; depth < MAX_PAGE_TREE_DEPTH; depth++) {
466
+ if (!node || node.getType() !== types.ePDFObjectDictionary) return null;
467
+ if (node.exists(PdfName.RESOURCES)) {
468
+ var resources = reader.queryDictionaryObject(node, PdfName.RESOURCES);
469
+ return resources && resources.getType() === types.ePDFObjectDictionary
470
+ ? resources
471
+ : null;
472
+ }
473
+ if (!node.exists(PdfName.PARENT)) return null;
474
+ var parent = node.queryObject(PdfName.PARENT);
475
+ if (parent.getType() === types.ePDFObjectIndirectObjectReference) {
476
+ var objectId = parent.toPDFIndirectObjectReference().getObjectID();
477
+ if (visited.has(objectId)) return null;
478
+ visited.add(objectId);
479
+ parent = reader.parseNewObject(objectId);
480
+ }
481
+ node = parent;
482
+ }
483
+ } catch (error) {
484
+ if (isExtractionLimitError(error)) throw error;
485
+ return null;
486
+ }
487
+ return null;
488
+ }
489
+
490
+ module.exports = {
491
+ PdfOperator: PdfOperator,
492
+ TokenKind: TokenKind,
493
+ decodeName: decodeName,
494
+ hexBytes: hexBytes,
495
+ stringBytes: stringBytes,
496
+ stringToken: stringToken,
497
+ tokenKind: tokenKind,
498
+ extractionLimitError: extractionLimitError,
499
+ isExtractionLimitError: isExtractionLimitError,
500
+ forEachOperation: forEachOperation,
501
+ inheritedResources: inheritedResources,
502
+ readStreamString: readStreamString,
503
+ };
@@ -0,0 +1,149 @@
1
+ /**
2
+ * CSS color names mapped to 0xRRGGBB, the same table the native content
3
+ * context driver uses (`packages/native-with-source/src/CSSColors.h`).
4
+ * Look names up in lower case.
5
+ */
6
+ var cssColors = Object.freeze({
7
+ aliceblue: 0xf0f8ff,
8
+ antiquewhite: 0xfaebd7,
9
+ aqua: 0x00ffff,
10
+ aquamarine: 0x7fffd4,
11
+ azure: 0xf0ffff,
12
+ beige: 0xf5f5dc,
13
+ bisque: 0xffe4c4,
14
+ black: 0x000000,
15
+ blanchedalmond: 0xffebcd,
16
+ blue: 0x0000ff,
17
+ blueviolet: 0x8a2be2,
18
+ brown: 0xa52a2a,
19
+ burlywood: 0xdeb887,
20
+ cadetblue: 0x5f9ea0,
21
+ chartreuse: 0x7fff00,
22
+ chocolate: 0xd2691e,
23
+ coral: 0xff7f50,
24
+ cornflowerblue: 0x6495ed,
25
+ cornsilk: 0xfff8dc,
26
+ crimson: 0xdc143c,
27
+ cyan: 0x00ffff,
28
+ darkblue: 0x00008b,
29
+ darkcyan: 0x008b8b,
30
+ darkgoldenrod: 0xb8860b,
31
+ darkgray: 0xa9a9a9,
32
+ darkgreen: 0x006400,
33
+ darkkhaki: 0xbdb76b,
34
+ darkmagenta: 0x8b008b,
35
+ darkolivegreen: 0x556b2f,
36
+ darkorange: 0xff8c00,
37
+ darkorchid: 0x9932cc,
38
+ darkred: 0x8b0000,
39
+ darksalmon: 0xe9967a,
40
+ darkseagreen: 0x8fbc8f,
41
+ darkslateblue: 0x483d8b,
42
+ darkslategray: 0x2f4f4f,
43
+ darkturquoise: 0x00ced1,
44
+ darkviolet: 0x9400d3,
45
+ deeppink: 0xff1493,
46
+ deepskyblue: 0x00bfff,
47
+ dimgray: 0x696969,
48
+ dodgerblue: 0x1e90ff,
49
+ firebrick: 0xb22222,
50
+ floralwhite: 0xfffaf0,
51
+ forestgreen: 0x228b22,
52
+ fuchsia: 0xff00ff,
53
+ gainsboro: 0xdcdcdc,
54
+ ghostwhite: 0xf8f8ff,
55
+ gold: 0xffd700,
56
+ goldenrod: 0xdaa520,
57
+ gray: 0x808080,
58
+ green: 0x008000,
59
+ greenyellow: 0xadff2f,
60
+ honeydew: 0xf0fff0,
61
+ hotpink: 0xff69b4,
62
+ indianred: 0xcd5c5c,
63
+ indigo: 0x4b0082,
64
+ ivory: 0xfffff0,
65
+ khaki: 0xf0e68c,
66
+ lavender: 0xe6e6fa,
67
+ lavenderblush: 0xfff0f5,
68
+ lawngreen: 0x7cfc00,
69
+ lemonchiffon: 0xfffacd,
70
+ lightblue: 0xadd8e6,
71
+ lightcoral: 0xf08080,
72
+ lightcyan: 0xe0ffff,
73
+ lightgoldenrodyellow: 0xfafad2,
74
+ lightgray: 0xd3d3d3,
75
+ lightgreen: 0x90ee90,
76
+ lightpink: 0xffb6c1,
77
+ lightsalmon: 0xffa07a,
78
+ lightseagreen: 0x20b2aa,
79
+ lightskyblue: 0x87cefa,
80
+ lightslategray: 0x778899,
81
+ lightsteelblue: 0xb0c4de,
82
+ lightyellow: 0xffffe0,
83
+ lime: 0x00ff00,
84
+ limegreen: 0x32cd32,
85
+ linen: 0xfaf0e6,
86
+ magenta: 0xff00ff,
87
+ maroon: 0x800000,
88
+ mediumaquamarine: 0x66cdaa,
89
+ mediumblue: 0x0000cd,
90
+ mediumorchid: 0xba55d3,
91
+ mediumpurple: 0x9370db,
92
+ mediumseagreen: 0x3cb371,
93
+ mediumslateblue: 0x7b68ee,
94
+ mediumspringgreen: 0x00fa9a,
95
+ mediumturquoise: 0x48d1cc,
96
+ mediumvioletred: 0xc71585,
97
+ midnightblue: 0x191970,
98
+ mintcream: 0xf5fffa,
99
+ mistyrose: 0xffe4e1,
100
+ moccasin: 0xffe4b5,
101
+ navajowhite: 0xffdead,
102
+ navy: 0x000080,
103
+ oldlace: 0xfdf5e6,
104
+ olive: 0x808000,
105
+ olivedrab: 0x6b8e23,
106
+ orange: 0xffa500,
107
+ orangered: 0xff4500,
108
+ orchid: 0xda70d6,
109
+ palegoldenrod: 0xeee8aa,
110
+ palegreen: 0x98fb98,
111
+ paleturquoise: 0xafeeee,
112
+ palevioletred: 0xdb7093,
113
+ papayawhip: 0xffefd5,
114
+ peachpuff: 0xffdab9,
115
+ peru: 0xcd853f,
116
+ pink: 0xffc0cb,
117
+ plum: 0xdda0dd,
118
+ powderblue: 0xb0e0e6,
119
+ purple: 0x800080,
120
+ red: 0xff0000,
121
+ rosybrown: 0xbc8f8f,
122
+ royalblue: 0x4169e1,
123
+ saddlebrown: 0x8b4513,
124
+ salmon: 0xfa8072,
125
+ sandybrown: 0xf4a460,
126
+ seagreen: 0x2e8b57,
127
+ seashell: 0xfff5ee,
128
+ sienna: 0xa0522d,
129
+ silver: 0xc0c0c0,
130
+ skyblue: 0x87ceeb,
131
+ slateblue: 0x6a5acd,
132
+ slategray: 0x708090,
133
+ snow: 0xfffafa,
134
+ springgreen: 0x00ff7f,
135
+ steelblue: 0x4682b4,
136
+ tan: 0xd2b48c,
137
+ teal: 0x008080,
138
+ thistle: 0xd8bfd8,
139
+ tomato: 0xff6347,
140
+ turquoise: 0x40e0d0,
141
+ violet: 0xee82ee,
142
+ wheat: 0xf5deb3,
143
+ white: 0xffffff,
144
+ whitesmoke: 0xf5f5f5,
145
+ yellow: 0xffff00,
146
+ yellowgreen: 0x9acd32,
147
+ });
148
+
149
+ module.exports = { cssColors };