reamkit 1.5.0 → 1.7.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 (58) hide show
  1. package/README.md +2 -2
  2. package/dist/esm/core/converter/facade.js +6 -1
  3. package/dist/esm/core/converter/ream.js +2 -1
  4. package/dist/esm/core/document-model/types.d.ts +9 -1
  5. package/dist/esm/core/drawingml/chart-serializer.d.ts +2 -0
  6. package/dist/esm/core/drawingml/chart-serializer.js +53 -0
  7. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  8. package/dist/esm/core/spreadsheet-model/types.d.ts +5 -0
  9. package/dist/esm/excel/column-bands.d.ts +7 -0
  10. package/dist/esm/excel/column-bands.js +87 -0
  11. package/dist/esm/excel/conditional-format.js +22 -0
  12. package/dist/esm/excel/print-model.js +33 -11
  13. package/dist/esm/excel/worksheet-parser.js +26 -0
  14. package/dist/esm/excel/xlsx-writer.js +88 -17
  15. package/dist/esm/html/html-writer.js +100 -5
  16. package/dist/esm/layout/styled-layout.js +88 -19
  17. package/dist/esm/pdf-reader/cmap.d.ts +5 -0
  18. package/dist/esm/pdf-reader/cmap.js +72 -0
  19. package/dist/esm/pdf-reader/content.d.ts +52 -0
  20. package/dist/esm/pdf-reader/content.js +420 -0
  21. package/dist/esm/pdf-reader/crypto.d.ts +7 -0
  22. package/dist/esm/pdf-reader/crypto.js +609 -0
  23. package/dist/esm/pdf-reader/decrypt.d.ts +5 -0
  24. package/dist/esm/pdf-reader/decrypt.js +199 -0
  25. package/dist/esm/pdf-reader/document.d.ts +30 -0
  26. package/dist/esm/pdf-reader/document.js +413 -0
  27. package/dist/esm/pdf-reader/flow-build.d.ts +19 -0
  28. package/dist/esm/pdf-reader/flow-build.js +126 -0
  29. package/dist/esm/pdf-reader/font.d.ts +4 -0
  30. package/dist/esm/pdf-reader/font.js +69 -0
  31. package/dist/esm/pdf-reader/image-decode.d.ts +15 -0
  32. package/dist/esm/pdf-reader/image-decode.js +442 -0
  33. package/dist/esm/pdf-reader/images.d.ts +16 -0
  34. package/dist/esm/pdf-reader/images.js +90 -0
  35. package/dist/esm/pdf-reader/layout.d.ts +3 -0
  36. package/dist/esm/pdf-reader/layout.js +103 -0
  37. package/dist/esm/pdf-reader/lexer.d.ts +43 -0
  38. package/dist/esm/pdf-reader/lexer.js +250 -0
  39. package/dist/esm/pdf-reader/parser.d.ts +10 -0
  40. package/dist/esm/pdf-reader/parser.js +86 -0
  41. package/dist/esm/pdf-reader/png-encode.d.ts +2 -0
  42. package/dist/esm/pdf-reader/png-encode.js +98 -0
  43. package/dist/esm/pdf-reader/predictor.d.ts +7 -0
  44. package/dist/esm/pdf-reader/predictor.js +61 -0
  45. package/dist/esm/pdf-reader/reader.d.ts +4 -0
  46. package/dist/esm/pdf-reader/reader.js +50 -0
  47. package/dist/esm/pdf-reader/struct-tree.d.ts +14 -0
  48. package/dist/esm/pdf-reader/struct-tree.js +92 -0
  49. package/dist/esm/pdf-reader/tagged.d.ts +3 -0
  50. package/dist/esm/pdf-reader/tagged.js +141 -0
  51. package/dist/esm/pdf-reader/text.d.ts +3 -0
  52. package/dist/esm/pdf-reader/text.js +65 -0
  53. package/dist/esm/pdf-reader/vector.d.ts +12 -0
  54. package/dist/esm/pdf-reader/vector.js +54 -0
  55. package/dist/esm/word/docx-writer.js +96 -7
  56. package/dist/esm/word/omml-serializer.d.ts +2 -0
  57. package/dist/esm/word/omml-serializer.js +48 -0
  58. package/package.json +2 -2
@@ -0,0 +1,199 @@
1
+ import { PdfHexString, PdfName, PdfStream } from "../pdf/objects.js";
2
+ import { aesCbcDecrypt, aesCbcEncrypt, md5, rc4, sha256, sha384, sha512 } from "./crypto.js";
3
+ //#region src/pdf-reader/decrypt.ts
4
+ var PAD = Uint8Array.from([
5
+ 40,
6
+ 191,
7
+ 78,
8
+ 94,
9
+ 78,
10
+ 117,
11
+ 138,
12
+ 65,
13
+ 100,
14
+ 0,
15
+ 78,
16
+ 86,
17
+ 255,
18
+ 250,
19
+ 1,
20
+ 8,
21
+ 46,
22
+ 46,
23
+ 0,
24
+ 182,
25
+ 208,
26
+ 104,
27
+ 62,
28
+ 128,
29
+ 47,
30
+ 12,
31
+ 169,
32
+ 254,
33
+ 100,
34
+ 83,
35
+ 105,
36
+ 122
37
+ ]);
38
+ var AES_SALT = Uint8Array.from([
39
+ 115,
40
+ 65,
41
+ 108,
42
+ 84
43
+ ]);
44
+ var ZERO16 = new Uint8Array(16);
45
+ var EMPTY = new Uint8Array(0);
46
+ function buildDecryptor(encrypt, idArray) {
47
+ const filter = encrypt.get("Filter");
48
+ if (!(filter instanceof PdfName) || filter.value !== "Standard") return void 0;
49
+ const v = numOf(encrypt.get("V"));
50
+ const r = numOf(encrypt.get("R"));
51
+ let fileKey;
52
+ let method;
53
+ if (r >= 5 || v >= 5) {
54
+ fileKey = deriveKeyR6(strBytes(encrypt.get("U")), strBytes(encrypt.get("UE")));
55
+ method = "aesv3";
56
+ } else {
57
+ const keyLen = (numOf(encrypt.get("Length")) || 40) / 8;
58
+ const id0 = Array.isArray(idArray) ? strBytes(idArray[0]) : EMPTY;
59
+ fileKey = deriveKeyLegacy(strBytes(encrypt.get("O")), numOf(encrypt.get("P")) | 0, id0, r, Math.max(5, Math.min(16, keyLen)), encrypt.get("EncryptMetadata") !== false);
60
+ const m = cipherMethod(encrypt, v);
61
+ if (m === void 0) return void 0;
62
+ method = m;
63
+ }
64
+ if (!fileKey) return void 0;
65
+ const key = fileKey;
66
+ return { decrypt: (value, objNum, gen) => decryptValue(value, objNum, gen, key, method) };
67
+ }
68
+ function deriveKeyLegacy(o, p, id0, r, keyLen, encryptMetadata) {
69
+ const tail = r >= 4 && !encryptMetadata ? Uint8Array.from([
70
+ 255,
71
+ 255,
72
+ 255,
73
+ 255
74
+ ]) : EMPTY;
75
+ let hash = md5(concat(PAD, o.subarray(0, 32), p32le(p), id0, tail));
76
+ if (r >= 3) for (let i = 0; i < 50; i++) hash = md5(hash.subarray(0, keyLen));
77
+ return hash.subarray(0, keyLen);
78
+ }
79
+ function deriveKeyR6(u, ue) {
80
+ if (u.length < 48 || ue.length < 32) return void 0;
81
+ const validationSalt = u.subarray(32, 40);
82
+ const keySalt = u.subarray(40, 48);
83
+ if (!equal(hash2B(EMPTY, validationSalt, EMPTY), u.subarray(0, 32))) return void 0;
84
+ return aesCbcDecrypt(hash2B(EMPTY, keySalt, EMPTY), ZERO16, ue.subarray(0, 32), false);
85
+ }
86
+ function hash2B(pw, salt, udata) {
87
+ let k = sha256(concat(pw, salt, udata));
88
+ for (let round = 1; round <= 256; round++) {
89
+ const block = concat(pw, k, udata);
90
+ const k1 = new Uint8Array(block.length * 64);
91
+ for (let i = 0; i < 64; i++) k1.set(block, i * block.length);
92
+ const e = aesCbcEncrypt(k.subarray(0, 16), k.subarray(16, 32), k1);
93
+ let sum = 0;
94
+ for (let i = 0; i < 16; i++) sum += e[i];
95
+ const mod = sum % 3;
96
+ k = mod === 0 ? sha256(e) : mod === 1 ? sha384(e) : sha512(e);
97
+ if (round >= 64 && e[e.length - 1] <= round - 32) break;
98
+ }
99
+ return k.subarray(0, 32);
100
+ }
101
+ function cipherMethod(encrypt, v) {
102
+ if (v < 4) return "rc4";
103
+ const stmf = encrypt.get("StmF");
104
+ const cfName = stmf instanceof PdfName ? stmf.value : "StdCF";
105
+ if (cfName === "Identity") return void 0;
106
+ const cf = encrypt.get("CF");
107
+ const cfDict = cf instanceof Map ? cf.get(cfName) : void 0;
108
+ const cfm = cfDict instanceof Map ? cfDict.get("CFM") : void 0;
109
+ if (cfm instanceof PdfName) {
110
+ if (cfm.value === "AESV2") return "aesv2";
111
+ if (cfm.value === "AESV3") return "aesv3";
112
+ }
113
+ return "rc4";
114
+ }
115
+ function objectKey(fileKey, objNum, gen, aes) {
116
+ const extra = aes ? AES_SALT : EMPTY;
117
+ const seed = new Uint8Array(fileKey.length + 5 + extra.length);
118
+ seed.set(fileKey, 0);
119
+ seed[fileKey.length] = objNum & 255;
120
+ seed[fileKey.length + 1] = objNum >> 8 & 255;
121
+ seed[fileKey.length + 2] = objNum >> 16 & 255;
122
+ seed[fileKey.length + 3] = gen & 255;
123
+ seed[fileKey.length + 4] = gen >> 8 & 255;
124
+ seed.set(extra, fileKey.length + 5);
125
+ return md5(seed).subarray(0, Math.min(fileKey.length + 5, 16));
126
+ }
127
+ function decryptBytes(data, objNum, gen, fileKey, method) {
128
+ if (method === "aesv3") {
129
+ if (data.length < 16) return data;
130
+ return aesCbcDecrypt(fileKey, data.subarray(0, 16), data.subarray(16), true);
131
+ }
132
+ const key = objectKey(fileKey, objNum, gen, method === "aesv2");
133
+ if (method === "aesv2") {
134
+ if (data.length < 16) return data;
135
+ return aesCbcDecrypt(key, data.subarray(0, 16), data.subarray(16), true);
136
+ }
137
+ return rc4(key, data);
138
+ }
139
+ function decryptValue(value, objNum, gen, fileKey, method) {
140
+ if (typeof value === "string") return latin1(decryptBytes(strToBytes(value), objNum, gen, fileKey, method));
141
+ if (value instanceof PdfHexString) return new PdfHexString(decryptBytes(value.bytes, objNum, gen, fileKey, method));
142
+ if (value instanceof PdfStream) {
143
+ const dict = decryptValue(value.dict, objNum, gen, fileKey, method);
144
+ const data = decryptBytes(value.data, objNum, gen, fileKey, method);
145
+ return new PdfStream(dict instanceof Map ? dict : value.dict, data);
146
+ }
147
+ if (Array.isArray(value)) return value.map((v) => decryptValue(v, objNum, gen, fileKey, method));
148
+ if (value instanceof Map) {
149
+ const out = /* @__PURE__ */ new Map();
150
+ for (const [k, v] of value) out.set(k, decryptValue(v, objNum, gen, fileKey, method));
151
+ return out;
152
+ }
153
+ return value;
154
+ }
155
+ function numOf(v) {
156
+ return typeof v === "number" ? v : 0;
157
+ }
158
+ function strBytes(v) {
159
+ if (v instanceof PdfHexString) return v.bytes;
160
+ if (typeof v === "string") return strToBytes(v);
161
+ return EMPTY;
162
+ }
163
+ function strToBytes(s) {
164
+ const out = new Uint8Array(s.length);
165
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i) & 255;
166
+ return out;
167
+ }
168
+ function latin1(b) {
169
+ let s = "";
170
+ for (const x of b) s += String.fromCharCode(x);
171
+ return s;
172
+ }
173
+ function p32le(p) {
174
+ const u = p >>> 0;
175
+ return Uint8Array.from([
176
+ u & 255,
177
+ u >> 8 & 255,
178
+ u >> 16 & 255,
179
+ u >> 24 & 255
180
+ ]);
181
+ }
182
+ function concat(...parts) {
183
+ let total = 0;
184
+ for (const p of parts) total += p.length;
185
+ const out = new Uint8Array(total);
186
+ let off = 0;
187
+ for (const p of parts) {
188
+ out.set(p, off);
189
+ off += p.length;
190
+ }
191
+ return out;
192
+ }
193
+ function equal(a, b) {
194
+ if (a.length !== b.length) return false;
195
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
196
+ return true;
197
+ }
198
+ //#endregion
199
+ export { buildDecryptor };
@@ -0,0 +1,30 @@
1
+ import { PdfArray, PdfDict, PdfValue, PdfStream } from '../pdf/objects.js';
2
+ export type Rectangle = readonly [number, number, number, number];
3
+ export interface PdfPage {
4
+ readonly dict: PdfDict;
5
+ readonly mediaBox: Rectangle;
6
+ readonly resources: PdfDict | undefined;
7
+ }
8
+ export declare class PdfFile {
9
+ private readonly buf;
10
+ private readonly xref;
11
+ readonly trailer: PdfDict;
12
+ private readonly cache;
13
+ private readonly objStmCache;
14
+ private decryptor;
15
+ private encryptObjNum;
16
+ private constructor();
17
+ static parse(bytes: Uint8Array): PdfFile;
18
+ private initEncryption;
19
+ private readonly lengthResolver;
20
+ resolve(value: PdfValue): PdfValue;
21
+ private objectFromStream;
22
+ get(dict: PdfDict, key: string): PdfValue;
23
+ get catalog(): PdfDict;
24
+ get encryptionUnsupported(): boolean;
25
+ pages(): Array<PdfPage>;
26
+ private walkPageTree;
27
+ pageContent(page: PdfPage): Uint8Array;
28
+ streamData(stream: PdfStream): Uint8Array;
29
+ }
30
+ export type { PdfArray };
@@ -0,0 +1,413 @@
1
+ import { PDF_NULL, PdfName, PdfRef, PdfStream } from "../pdf/objects.js";
2
+ import { buildDecryptor } from "./decrypt.js";
3
+ import { Lexer } from "./lexer.js";
4
+ import { parseIndirectObject, parseObject } from "./parser.js";
5
+ import { reversePredictor } from "./predictor.js";
6
+ import { unzlibSync } from "fflate";
7
+ //#region src/pdf-reader/document.ts
8
+ var DEFAULT_MEDIA_BOX = [
9
+ 0,
10
+ 0,
11
+ 612,
12
+ 792
13
+ ];
14
+ var MAX_PAGES = 5e4;
15
+ var MAX_OBJSTM_N = 2e5;
16
+ var PdfFile = class PdfFile {
17
+ cache = /* @__PURE__ */ new Map();
18
+ objStmCache = /* @__PURE__ */ new Map();
19
+ decryptor;
20
+ encryptObjNum = -1;
21
+ constructor(buf, xref, trailer) {
22
+ this.buf = buf;
23
+ this.xref = xref;
24
+ this.trailer = trailer;
25
+ }
26
+ static parse(bytes) {
27
+ let xref = /* @__PURE__ */ new Map();
28
+ let trailer = /* @__PURE__ */ new Map();
29
+ try {
30
+ const start = findStartXref(bytes);
31
+ if (start >= 0) {
32
+ const built = readXrefChain(bytes, start);
33
+ xref = built.xref;
34
+ trailer = built.trailer;
35
+ }
36
+ } catch {}
37
+ if (xref.size === 0 || !(trailer.get("Root") instanceof PdfRef)) {
38
+ const scanned = bruteForceScan(bytes);
39
+ for (const [id, entry] of scanned.xref) if (!xref.has(id)) xref.set(id, entry);
40
+ if (!(trailer.get("Root") instanceof PdfRef) && scanned.root) {
41
+ trailer = new Map(trailer);
42
+ trailer.set("Root", scanned.root);
43
+ }
44
+ }
45
+ const file = new PdfFile(bytes, xref, trailer);
46
+ file.initEncryption();
47
+ return file;
48
+ }
49
+ initEncryption() {
50
+ const encVal = this.trailer.get("Encrypt");
51
+ if (encVal === void 0) return;
52
+ if (encVal instanceof PdfRef) this.encryptObjNum = encVal.id;
53
+ const enc = this.resolve(encVal);
54
+ if (!(enc instanceof Map)) return;
55
+ const id = this.trailer.get("ID");
56
+ this.decryptor = buildDecryptor(enc, Array.isArray(id) ? id : void 0);
57
+ }
58
+ lengthResolver = (r) => {
59
+ const n = this.resolve(r);
60
+ return typeof n === "number" ? n : void 0;
61
+ };
62
+ resolve(value) {
63
+ if (!(value instanceof PdfRef)) return value;
64
+ const cached = this.cache.get(value.id);
65
+ if (cached !== void 0) return cached;
66
+ const entry = this.xref.get(value.id);
67
+ if (entry === void 0) return PDF_NULL;
68
+ this.cache.set(value.id, PDF_NULL);
69
+ let result = PDF_NULL;
70
+ if (entry.kind === "uncompressed") {
71
+ if (entry.offset >= 0 && entry.offset < this.buf.length) {
72
+ const obj = parseIndirectObject(new Lexer(this.buf, entry.offset), this.lengthResolver);
73
+ result = obj ? obj.value : PDF_NULL;
74
+ if (this.decryptor && value.id !== this.encryptObjNum) result = this.decryptor.decrypt(result, value.id, obj?.generation ?? 0);
75
+ }
76
+ } else result = this.objectFromStream(entry.streamObj).get(value.id) ?? PDF_NULL;
77
+ this.cache.set(value.id, result);
78
+ return result;
79
+ }
80
+ objectFromStream(streamObj) {
81
+ const cached = this.objStmCache.get(streamObj);
82
+ if (cached) return cached;
83
+ const out = /* @__PURE__ */ new Map();
84
+ this.objStmCache.set(streamObj, out);
85
+ const entry = this.xref.get(streamObj);
86
+ if (!entry || entry.kind !== "uncompressed") return out;
87
+ const obj = parseIndirectObject(new Lexer(this.buf, entry.offset), this.lengthResolver);
88
+ if (!obj || !(obj.value instanceof PdfStream)) return out;
89
+ let stream = obj.value;
90
+ if (this.decryptor) {
91
+ const dec = this.decryptor.decrypt(stream, streamObj, obj.generation);
92
+ if (dec instanceof PdfStream) stream = dec;
93
+ }
94
+ const data = inflateStream(stream);
95
+ const first = numOf(this.resolve(stream.dict.get("First") ?? PDF_NULL));
96
+ for (const member of objStmHeader(data, numOf(this.resolve(stream.dict.get("N") ?? PDF_NULL)))) out.set(member.id, parseObject(new Lexer(data, first + member.off), this.lengthResolver));
97
+ return out;
98
+ }
99
+ get(dict, key) {
100
+ return this.resolve(dict.get(key) ?? PDF_NULL);
101
+ }
102
+ get catalog() {
103
+ const root = this.resolve(this.trailer.get("Root") ?? PDF_NULL);
104
+ return root instanceof Map ? root : /* @__PURE__ */ new Map();
105
+ }
106
+ get encryptionUnsupported() {
107
+ return this.trailer.get("Encrypt") !== void 0 && this.decryptor === void 0;
108
+ }
109
+ pages() {
110
+ const out = [];
111
+ const root = this.get(this.catalog, "Pages");
112
+ if (root instanceof Map) this.walkPageTree(root, {}, out, /* @__PURE__ */ new Set());
113
+ return out;
114
+ }
115
+ walkPageTree(node, inherited, out, seen) {
116
+ if (out.length >= MAX_PAGES || seen.has(node)) return;
117
+ seen.add(node);
118
+ const mediaBox = readRectangle(this.get(node, "MediaBox")) ?? inherited.mediaBox;
119
+ const resourcesVal = this.get(node, "Resources");
120
+ const resources = resourcesVal instanceof Map ? resourcesVal : inherited.resources;
121
+ const type = node.get("Type");
122
+ const kids = this.get(node, "Kids");
123
+ if (type instanceof PdfName && type.value === "Pages" && Array.isArray(kids)) {
124
+ for (const kid of kids) {
125
+ const kidNode = this.resolve(kid);
126
+ if (kidNode instanceof Map) this.walkPageTree(kidNode, {
127
+ mediaBox,
128
+ resources
129
+ }, out, seen);
130
+ if (out.length >= MAX_PAGES) break;
131
+ }
132
+ return;
133
+ }
134
+ out.push({
135
+ dict: node,
136
+ mediaBox: mediaBox ?? DEFAULT_MEDIA_BOX,
137
+ resources
138
+ });
139
+ }
140
+ pageContent(page) {
141
+ const contents = this.get(page.dict, "Contents");
142
+ const streams = [];
143
+ if (contents instanceof PdfStream) streams.push(contents);
144
+ else if (Array.isArray(contents)) for (const c of contents) {
145
+ const s = this.resolve(c);
146
+ if (s instanceof PdfStream) streams.push(s);
147
+ }
148
+ return concatWithSpaces(streams.map((s) => this.streamData(s)));
149
+ }
150
+ streamData(stream) {
151
+ let data = stream.data;
152
+ const filter = this.resolve(stream.dict.get("Filter") ?? PDF_NULL);
153
+ const filters = Array.isArray(filter) ? filter : [filter];
154
+ let flate = false;
155
+ for (const f of filters) if (f instanceof PdfName && (f.value === "FlateDecode" || f.value === "Fl")) try {
156
+ data = unzlibSync(data);
157
+ flate = true;
158
+ } catch {}
159
+ return flate ? applyStreamPredictor(this, stream.dict, data) : data;
160
+ }
161
+ };
162
+ function findStartXref(buf) {
163
+ const tail = lastIndexOfAscii(buf, "startxref");
164
+ if (tail < 0) return -1;
165
+ const tok = new Lexer(buf, tail + 9).nextToken();
166
+ return tok.kind === "num" ? tok.value : -1;
167
+ }
168
+ function readXrefChain(buf, offset) {
169
+ const xref = /* @__PURE__ */ new Map();
170
+ let trailer = /* @__PURE__ */ new Map();
171
+ const visited = /* @__PURE__ */ new Set();
172
+ const queue = [offset];
173
+ while (queue.length > 0) {
174
+ const at = queue.shift();
175
+ if (at < 0 || at >= buf.length || visited.has(at)) continue;
176
+ visited.add(at);
177
+ const section = readXrefAt(buf, at);
178
+ if (!section) continue;
179
+ for (const [id, entry] of section.xref) if (!xref.has(id)) xref.set(id, entry);
180
+ if (trailer.size === 0) trailer = section.trailer;
181
+ const xrefStm = section.trailer.get("XRefStm");
182
+ if (typeof xrefStm === "number") queue.push(xrefStm);
183
+ const prev = section.trailer.get("Prev");
184
+ if (typeof prev === "number") queue.push(prev);
185
+ }
186
+ return {
187
+ xref,
188
+ trailer
189
+ };
190
+ }
191
+ function readXrefAt(buf, offset) {
192
+ const lexer = new Lexer(buf, offset);
193
+ const head = lexer.nextToken();
194
+ if (head.kind === "keyword" && head.value === "xref") return readClassicXref(lexer);
195
+ const obj = parseIndirectObject(new Lexer(buf, offset));
196
+ if (obj && obj.value instanceof PdfStream) return readXrefStream(obj.value);
197
+ }
198
+ function readClassicXref(lexer) {
199
+ const xref = /* @__PURE__ */ new Map();
200
+ for (;;) {
201
+ const tok = lexer.nextToken();
202
+ if (tok.kind === "keyword" && tok.value === "trailer") break;
203
+ if (tok.kind !== "num") return void 0;
204
+ const first = tok.value;
205
+ const countTok = lexer.nextToken();
206
+ if (countTok.kind !== "num") return void 0;
207
+ const count = countTok.value;
208
+ for (let i = 0; i < count; i++) {
209
+ const off = lexer.nextToken();
210
+ const gen = lexer.nextToken();
211
+ const type = lexer.nextToken();
212
+ if (off.kind !== "num" || gen.kind !== "num" || type.kind !== "keyword") return void 0;
213
+ if (type.value === "n" && !xref.has(first + i)) xref.set(first + i, {
214
+ kind: "uncompressed",
215
+ offset: off.value
216
+ });
217
+ }
218
+ }
219
+ const trailerVal = parseObject(lexer);
220
+ return {
221
+ xref,
222
+ trailer: trailerVal instanceof Map ? trailerVal : /* @__PURE__ */ new Map()
223
+ };
224
+ }
225
+ function readXrefStream(stream) {
226
+ const dict = stream.dict;
227
+ const wv = dict.get("W");
228
+ if (!Array.isArray(wv) || wv.length < 3) return void 0;
229
+ const w0 = numOf(wv[0]);
230
+ const w1 = numOf(wv[1]);
231
+ const w2 = numOf(wv[2]);
232
+ const rowLen = w0 + w1 + w2;
233
+ if (rowLen <= 0) return void 0;
234
+ const data = inflateStream(stream);
235
+ const size = numOf(dict.get("Size"));
236
+ const indexV = dict.get("Index");
237
+ const index = Array.isArray(indexV) ? indexV.map(numOf) : [0, size];
238
+ const xref = /* @__PURE__ */ new Map();
239
+ let pos = 0;
240
+ for (let s = 0; s + 1 < index.length; s += 2) {
241
+ const start = index[s];
242
+ const count = index[s + 1];
243
+ for (let i = 0; i < count && pos + rowLen <= data.length; i++) {
244
+ const type = w0 === 0 ? 1 : readBE(data, pos, w0);
245
+ const f2 = readBE(data, pos + w0, w1);
246
+ const f3 = readBE(data, pos + w0 + w1, w2);
247
+ pos += rowLen;
248
+ const id = start + i;
249
+ if (xref.has(id)) continue;
250
+ if (type === 1) xref.set(id, {
251
+ kind: "uncompressed",
252
+ offset: f2
253
+ });
254
+ else if (type === 2) xref.set(id, {
255
+ kind: "compressed",
256
+ streamObj: f2,
257
+ index: f3
258
+ });
259
+ }
260
+ }
261
+ return {
262
+ xref,
263
+ trailer: dict
264
+ };
265
+ }
266
+ function objStmHeader(data, n) {
267
+ const out = [];
268
+ const lexer = new Lexer(data, 0);
269
+ for (let i = 0; i < Math.min(n, MAX_OBJSTM_N); i++) {
270
+ const idTok = lexer.nextToken();
271
+ const offTok = lexer.nextToken();
272
+ if (idTok.kind !== "num" || offTok.kind !== "num") break;
273
+ out.push({
274
+ id: idTok.value,
275
+ off: offTok.value
276
+ });
277
+ }
278
+ return out;
279
+ }
280
+ function inflateStream(stream) {
281
+ let data = stream.data;
282
+ const filter = stream.dict.get("Filter") ?? PDF_NULL;
283
+ const filters = Array.isArray(filter) ? filter : [filter];
284
+ for (const f of filters) if (f instanceof PdfName && (f.value === "FlateDecode" || f.value === "Fl")) try {
285
+ data = unzlibSync(data);
286
+ } catch {
287
+ return new Uint8Array(0);
288
+ }
289
+ const parmsVal = stream.dict.get("DecodeParms") ?? stream.dict.get("DP");
290
+ const parms = parmsVal instanceof Map ? parmsVal : Array.isArray(parmsVal) ? parmsVal.find((p) => p instanceof Map) : void 0;
291
+ if (parms) {
292
+ const predictor = numOf(parms.get("Predictor"));
293
+ if (predictor >= 2) data = reversePredictor(data, {
294
+ predictor,
295
+ colors: numOf(parms.get("Colors")) || 1,
296
+ bitsPerComponent: numOf(parms.get("BitsPerComponent")) || 8,
297
+ columns: numOf(parms.get("Columns")) || 1
298
+ });
299
+ }
300
+ return data;
301
+ }
302
+ function applyStreamPredictor(file, dict, data) {
303
+ const parmsVal = file.get(dict, "DecodeParms");
304
+ const parms = parmsVal instanceof Map ? parmsVal : void 0;
305
+ if (!parms) return data;
306
+ const predictor = numOf(file.get(parms, "Predictor"));
307
+ if (predictor < 2) return data;
308
+ return reversePredictor(data, {
309
+ predictor,
310
+ colors: numOf(file.get(parms, "Colors")) || 1,
311
+ bitsPerComponent: numOf(file.get(parms, "BitsPerComponent")) || 8,
312
+ columns: numOf(file.get(parms, "Columns")) || 1
313
+ });
314
+ }
315
+ function bruteForceScan(buf) {
316
+ const xref = /* @__PURE__ */ new Map();
317
+ const objStmObjs = [];
318
+ let root;
319
+ const lexer = new Lexer(buf);
320
+ let prev2;
321
+ let prev1;
322
+ for (;;) {
323
+ lexer.skipWhitespace();
324
+ const start = lexer.pos;
325
+ const tok = lexer.nextToken();
326
+ if (tok.kind === "eof") break;
327
+ if (tok.kind === "keyword" && tok.value === "obj" && prev2 && prev1) {
328
+ xref.set(prev2.value, {
329
+ kind: "uncompressed",
330
+ offset: prev2.start
331
+ });
332
+ const value = parseIndirectObject(new Lexer(buf, prev2.start))?.value;
333
+ const dict = value instanceof PdfStream ? value.dict : value;
334
+ if (dict instanceof Map) {
335
+ const type = dict.get("Type");
336
+ if (type instanceof PdfName && type.value === "Catalog" && root === void 0) root = new PdfRef(prev2.value, prev1.value);
337
+ else if (type instanceof PdfName && type.value === "ObjStm") objStmObjs.push(prev2.value);
338
+ }
339
+ }
340
+ prev2 = prev1;
341
+ prev1 = tok.kind === "num" ? {
342
+ start,
343
+ value: tok.value
344
+ } : void 0;
345
+ }
346
+ for (const streamObj of objStmObjs) {
347
+ const entry = xref.get(streamObj);
348
+ if (!entry || entry.kind !== "uncompressed") continue;
349
+ const obj = parseIndirectObject(new Lexer(buf, entry.offset));
350
+ if (!obj || !(obj.value instanceof PdfStream)) continue;
351
+ const data = inflateStream(obj.value);
352
+ const first = numOf(obj.value.dict.get("First") ?? PDF_NULL);
353
+ objStmHeader(data, numOf(obj.value.dict.get("N") ?? PDF_NULL)).forEach((member, index) => {
354
+ if (!xref.has(member.id)) xref.set(member.id, {
355
+ kind: "compressed",
356
+ streamObj,
357
+ index
358
+ });
359
+ if (root === void 0) {
360
+ const v = parseObject(new Lexer(data, first + member.off));
361
+ if (v instanceof Map) {
362
+ const t = v.get("Type");
363
+ if (t instanceof PdfName && t.value === "Catalog") root = new PdfRef(member.id, 0);
364
+ }
365
+ }
366
+ });
367
+ }
368
+ return {
369
+ xref,
370
+ root
371
+ };
372
+ }
373
+ function readBE(data, offset, width) {
374
+ let v = 0;
375
+ for (let i = 0; i < width; i++) v = v * 256 + (data[offset + i] ?? 0);
376
+ return v;
377
+ }
378
+ function numOf(v) {
379
+ return typeof v === "number" ? v : 0;
380
+ }
381
+ function readRectangle(value) {
382
+ if (!Array.isArray(value) || value.length < 4) return void 0;
383
+ const nums = value.slice(0, 4).map((v) => typeof v === "number" ? v : NaN);
384
+ if (nums.some((n) => !Number.isFinite(n))) return void 0;
385
+ return [
386
+ nums[0],
387
+ nums[1],
388
+ nums[2],
389
+ nums[3]
390
+ ];
391
+ }
392
+ function concatWithSpaces(parts) {
393
+ if (parts.length === 1) return parts[0];
394
+ const total = parts.reduce((n, p) => n + p.length + 1, 0);
395
+ const out = new Uint8Array(Math.max(0, total - 1));
396
+ let at = 0;
397
+ parts.forEach((p, i) => {
398
+ out.set(p, at);
399
+ at += p.length;
400
+ if (i < parts.length - 1) out[at++] = 10;
401
+ });
402
+ return out;
403
+ }
404
+ function lastIndexOfAscii(buf, needle) {
405
+ const n = needle.length;
406
+ outer: for (let i = buf.length - n; i >= 0; i--) {
407
+ for (let j = 0; j < n; j++) if (buf[i + j] !== needle.charCodeAt(j)) continue outer;
408
+ return i;
409
+ }
410
+ return -1;
411
+ }
412
+ //#endregion
413
+ export { PdfFile };
@@ -0,0 +1,19 @@
1
+ import { BodyElement } from '../core/document-model/index.js';
2
+ import { FlowDoc } from '../core/ir/flow.js';
3
+ import { Loss, ResourceStore } from '../core/ir/index.js';
4
+ import { PdfImage } from './images.js';
5
+ import { PdfVector } from './vector.js';
6
+ export interface Reconstruction {
7
+ readonly doc: FlowDoc;
8
+ readonly losses: ReadonlyArray<Loss>;
9
+ }
10
+ export declare function paragraphBlock(text: string, outlineLevel?: number): BodyElement;
11
+ export interface TextSpan {
12
+ readonly text: string;
13
+ readonly href?: string;
14
+ }
15
+ export declare function paragraphFromRuns(spans: ReadonlyArray<TextSpan>, outlineLevel?: number): BodyElement;
16
+ export declare function imageBlock(image: PdfImage, resources: ResourceStore, alt?: string): BodyElement;
17
+ export declare function dedupeLosses(losses: ReadonlyArray<Loss>): Array<Loss>;
18
+ export declare function shapeBlock(v: PdfVector): BodyElement;
19
+ export declare function buildFlowDoc(body: ReadonlyArray<BodyElement>, resources?: ResourceStore): FlowDoc;