reamkit 1.13.0 → 1.15.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/README.md +34 -8
- package/dist/esm/core/converter/facade.d.ts +8 -1
- package/dist/esm/core/converter/facade.js +34 -8
- package/dist/esm/core/converter/ream.d.ts +1 -0
- package/dist/esm/core/converter/ream.js +13 -8
- package/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/ir/features.d.ts +1 -0
- package/dist/esm/core/ir/features.js +1 -0
- package/dist/esm/core/ir/sheet.d.ts +42 -3
- package/dist/esm/core/ole/cfb.d.ts +19 -0
- package/dist/esm/core/ole/cfb.js +158 -0
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +81 -1
- package/dist/esm/excel/activex-parser.d.ts +9 -0
- package/dist/esm/excel/activex-parser.js +188 -0
- package/dist/esm/excel/comments-parser.d.ts +4 -0
- package/dist/esm/excel/comments-parser.js +104 -0
- package/dist/esm/excel/conditional-format.d.ts +5 -3
- package/dist/esm/excel/conditional-format.js +248 -12
- package/dist/esm/excel/form-control-parser.d.ts +6 -0
- package/dist/esm/excel/form-control-parser.js +29 -0
- package/dist/esm/excel/formula/context.d.ts +11 -0
- package/dist/esm/excel/formula/dates.d.ts +11 -0
- package/dist/esm/excel/formula/dates.js +46 -0
- package/dist/esm/excel/formula/eval.d.ts +11 -0
- package/dist/esm/excel/formula/eval.js +196 -0
- package/dist/esm/excel/formula/functions.d.ts +7 -0
- package/dist/esm/excel/formula/functions.js +1359 -0
- package/dist/esm/excel/formula/index.d.ts +14 -0
- package/dist/esm/excel/formula/index.js +17 -0
- package/dist/esm/excel/formula/lexer.d.ts +8 -0
- package/dist/esm/excel/formula/lexer.js +163 -0
- package/dist/esm/excel/formula/parser.d.ts +57 -0
- package/dist/esm/excel/formula/parser.js +274 -0
- package/dist/esm/excel/formula/value.d.ts +52 -0
- package/dist/esm/excel/formula/value.js +102 -0
- package/dist/esm/excel/header-footer.d.ts +2 -0
- package/dist/esm/excel/header-footer.js +127 -0
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/number-format.d.ts +2 -0
- package/dist/esm/excel/number-format.js +5 -1
- package/dist/esm/excel/print-model.d.ts +7 -2
- package/dist/esm/excel/print-model.js +123 -16
- package/dist/esm/excel/shared-strings-parser.d.ts +6 -1
- package/dist/esm/excel/shared-strings-parser.js +91 -12
- package/dist/esm/excel/sheet-drawing.d.ts +13 -1
- package/dist/esm/excel/sheet-drawing.js +47 -14
- package/dist/esm/excel/sheet-shape-parser.d.ts +4 -0
- package/dist/esm/excel/sheet-shape-parser.js +96 -0
- package/dist/esm/excel/sheet-to-flow.d.ts +4 -1
- package/dist/esm/excel/sheet-to-flow.js +170 -3
- package/dist/esm/excel/styles-parser.js +37 -0
- package/dist/esm/excel/worksheet-parser.js +191 -1
- package/dist/esm/excel/xls/biff-chart.d.ts +8 -0
- package/dist/esm/excel/xls/biff-chart.js +121 -0
- package/dist/esm/excel/xls/biff-reader.d.ts +4 -0
- package/dist/esm/excel/xls/biff-reader.js +1418 -0
- package/dist/esm/excel/xls/biff-styles.d.ts +8 -0
- package/dist/esm/excel/xls/biff-styles.js +299 -0
- package/dist/esm/excel/xls/escher.d.ts +24 -0
- package/dist/esm/excel/xls/escher.js +171 -0
- package/dist/esm/excel/xls/xls-reader.d.ts +3 -0
- package/dist/esm/excel/xls/xls-reader.js +30 -0
- package/dist/esm/excel/xlsx-reader.d.ts +2 -1
- package/dist/esm/excel/xlsx-reader.js +134 -16
- package/dist/esm/excel/xlsx-to-pdf.d.ts +1 -0
- package/dist/esm/excel/xlsx-to-pdf.js +2 -2
- package/dist/esm/excel/xlsx-writer.js +12 -2
- package/dist/esm/layout/styled-layout.js +29 -0
- package/dist/esm/pptx/ppt/ppt-reader.d.ts +4 -0
- package/dist/esm/pptx/ppt/ppt-reader.js +337 -0
- package/dist/esm/pptx/ppt/ppt-text.d.ts +69 -0
- package/dist/esm/pptx/ppt/ppt-text.js +756 -0
- package/dist/esm/pptx/slide-parser.d.ts +4 -2
- package/dist/esm/pptx/slide-parser.js +1 -1
- package/dist/esm/word/doc/doc-reader.d.ts +4 -0
- package/dist/esm/word/doc/doc-reader.js +421 -0
- package/dist/esm/word/doc/doc-text.d.ts +79 -0
- package/dist/esm/word/doc/doc-text.js +706 -0
- package/package.json +1 -1
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
import { openCfb } from "../../core/ole/cfb.js";
|
|
2
|
+
//#region src/word/doc/doc-text.ts
|
|
3
|
+
var WIDENT = 42476;
|
|
4
|
+
var OFF_FLAGS1 = 10;
|
|
5
|
+
var OFF_CCPTEXT = 76;
|
|
6
|
+
var OFF_CCPFTN = 80;
|
|
7
|
+
var OFF_CCPHDD = 84;
|
|
8
|
+
var OFF_FCPLCFHDD = 242;
|
|
9
|
+
var OFF_LCBPLCFHDD = 246;
|
|
10
|
+
var OFF_FCPLCFBTECHPX = 250;
|
|
11
|
+
var OFF_LCBPLCFBTECHPX = 254;
|
|
12
|
+
var OFF_FCPLCFBTEPAPX = 258;
|
|
13
|
+
var OFF_LCBPLCFBTEPAPX = 262;
|
|
14
|
+
var OFF_FCCLX = 418;
|
|
15
|
+
var OFF_LCBCLX = 422;
|
|
16
|
+
var OFF_FCPLFLST = 738;
|
|
17
|
+
var OFF_LCBPLFLST = 742;
|
|
18
|
+
var OFF_FCPLFLFO = 746;
|
|
19
|
+
var FLAG_ENCRYPTED = 256;
|
|
20
|
+
var FLAG_WHICH_TBL = 512;
|
|
21
|
+
var FC_COMPRESSED = 1073741824;
|
|
22
|
+
var FC_MASK = 1073741823;
|
|
23
|
+
var FKP_SIZE = 512;
|
|
24
|
+
var PN_MASK = 4194303;
|
|
25
|
+
var CR = 13;
|
|
26
|
+
var SPRM_C_FBOLD = 2101;
|
|
27
|
+
var SPRM_C_FITALIC = 2102;
|
|
28
|
+
var SPRM_C_KUL = 10814;
|
|
29
|
+
var SPRM_C_HPS = 19011;
|
|
30
|
+
var SPRM_C_FSPEC = 2133;
|
|
31
|
+
var SPRM_C_PIC_LOCATION = 27139;
|
|
32
|
+
var PIC_CHAR = 1;
|
|
33
|
+
var SPRM_P_JC = 9219;
|
|
34
|
+
var SPRM_P_DXA_RIGHT = 33806;
|
|
35
|
+
var SPRM_P_DXA_LEFT = 33807;
|
|
36
|
+
var SPRM_P_DXA_LEFT1 = 33809;
|
|
37
|
+
var SPRM_P_DYA_BEFORE = 42003;
|
|
38
|
+
var SPRM_P_DYA_AFTER = 42004;
|
|
39
|
+
var SPRM_P_F_IN_TABLE = 9238;
|
|
40
|
+
var SPRM_P_F_TTP = 9239;
|
|
41
|
+
var SPRM_T_DEF_TABLE = 54792;
|
|
42
|
+
var SPRM_T_DEF_TABLE_SHD = 54802;
|
|
43
|
+
var MAX_ROW_CELLS = 256;
|
|
44
|
+
var SPRM_P_ILVL = 9738;
|
|
45
|
+
var SPRM_P_ILFO = 17931;
|
|
46
|
+
var SPRA_LEN = [
|
|
47
|
+
1,
|
|
48
|
+
1,
|
|
49
|
+
2,
|
|
50
|
+
4,
|
|
51
|
+
2,
|
|
52
|
+
2,
|
|
53
|
+
0,
|
|
54
|
+
3
|
|
55
|
+
];
|
|
56
|
+
var SPRM_LONG_OPERAND = new Set([54792, 50701]);
|
|
57
|
+
var CELL_MARK = 7;
|
|
58
|
+
var FIELD_BEGIN = 19;
|
|
59
|
+
var FIELD_SEPARATOR = 20;
|
|
60
|
+
var FIELD_END = 21;
|
|
61
|
+
var MAX_TEXT = 1 << 24;
|
|
62
|
+
var EMPTY = {
|
|
63
|
+
paragraphs: [],
|
|
64
|
+
encrypted: false
|
|
65
|
+
};
|
|
66
|
+
function extractDocContent(bytes) {
|
|
67
|
+
const cfb = openCfb(bytes);
|
|
68
|
+
const wd = cfb.readStream("WordDocument");
|
|
69
|
+
if (!wd || wd.length < OFF_LCBCLX + 4) return EMPTY;
|
|
70
|
+
if (u16(wd, 0) !== WIDENT) return EMPTY;
|
|
71
|
+
const flags = u16(wd, OFF_FLAGS1);
|
|
72
|
+
if ((flags & FLAG_ENCRYPTED) !== 0) return {
|
|
73
|
+
paragraphs: [],
|
|
74
|
+
encrypted: true
|
|
75
|
+
};
|
|
76
|
+
const primary = (flags & FLAG_WHICH_TBL) !== 0 ? "1Table" : "0Table";
|
|
77
|
+
const table = cfb.readStream(primary) ?? cfb.readStream(primary === "1Table" ? "0Table" : "1Table");
|
|
78
|
+
if (!table) return EMPTY;
|
|
79
|
+
const fcClx = u32(wd, OFF_FCCLX);
|
|
80
|
+
const lcbClx = u32(wd, OFF_LCBCLX);
|
|
81
|
+
if (lcbClx === 0 || fcClx + lcbClx > table.length) return EMPTY;
|
|
82
|
+
const plcPcd = findPlcPcd(table.subarray(fcClx, fcClx + lcbClx));
|
|
83
|
+
if (!plcPcd) return EMPTY;
|
|
84
|
+
const pieces = parsePieces(plcPcd);
|
|
85
|
+
const chpx = parsePlcBte(wd, table, OFF_FCPLCFBTECHPX, OFF_LCBPLCFBTECHPX, parseChpxFkp);
|
|
86
|
+
const papx = parsePlcBte(wd, table, OFF_FCPLCFBTEPAPX, OFF_LCBPLCFBTEPAPX, parsePapxFkp);
|
|
87
|
+
const ccpText = u32(wd, OFF_CCPTEXT);
|
|
88
|
+
const data = cfb.readStream("Data");
|
|
89
|
+
const main = buildParagraphs(wd, pieces, chpx, papx, 0, ccpText, data);
|
|
90
|
+
const headerFooters = extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText);
|
|
91
|
+
const listTables = parseListTables(wd, table);
|
|
92
|
+
return {
|
|
93
|
+
paragraphs: main,
|
|
94
|
+
...headerFooters ? { headerFooters } : {},
|
|
95
|
+
...listTables ? { listTables } : {},
|
|
96
|
+
encrypted: false
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function parseListTables(wd, table) {
|
|
100
|
+
const lstFc = u32(wd, OFF_FCPLFLST);
|
|
101
|
+
const lstLcb = u32(wd, OFF_LCBPLFLST);
|
|
102
|
+
if (lstLcb === 0 || lstFc + 2 > table.length) return void 0;
|
|
103
|
+
const lfoLsids = [];
|
|
104
|
+
const lfoFc = u32(wd, OFF_FCPLFLFO);
|
|
105
|
+
if (lfoFc + 4 <= table.length) {
|
|
106
|
+
const lfoMac = u32(table, lfoFc);
|
|
107
|
+
for (let i = 0; i < lfoMac && lfoFc + 4 + i * 16 + 4 <= table.length; i++) lfoLsids.push(u32(table, lfoFc + 4 + i * 16) | 0);
|
|
108
|
+
}
|
|
109
|
+
const cLst = i16(table, lstFc);
|
|
110
|
+
if (cLst <= 0 || cLst > 65535) return void 0;
|
|
111
|
+
const lstfs = [];
|
|
112
|
+
for (let i = 0; i < cLst && lstFc + 2 + i * 28 + 28 <= table.length; i++) {
|
|
113
|
+
const base = lstFc + 2 + i * 28;
|
|
114
|
+
lstfs.push({
|
|
115
|
+
lsid: u32(table, base) | 0,
|
|
116
|
+
simple: (table[base + 26] & 1) !== 0
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const lists = /* @__PURE__ */ new Map();
|
|
120
|
+
let p = lstFc + lstLcb;
|
|
121
|
+
for (const lstf of lstfs) {
|
|
122
|
+
const levels = [];
|
|
123
|
+
for (let l = 0; l < (lstf.simple ? 1 : 9); l++) {
|
|
124
|
+
const lvl = readLvl(table, p);
|
|
125
|
+
if (!lvl) {
|
|
126
|
+
p = table.length;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
levels.push(lvl.info);
|
|
130
|
+
p = lvl.next;
|
|
131
|
+
}
|
|
132
|
+
if (!lists.has(lstf.lsid)) lists.set(lstf.lsid, {
|
|
133
|
+
simple: lstf.simple,
|
|
134
|
+
levels
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return lfoLsids.length > 0 || lists.size > 0 ? {
|
|
138
|
+
lfoLsids,
|
|
139
|
+
lists
|
|
140
|
+
} : void 0;
|
|
141
|
+
}
|
|
142
|
+
function readLvl(d, off) {
|
|
143
|
+
if (off + 28 > d.length) return void 0;
|
|
144
|
+
const iStartAt = u32(d, off) | 0;
|
|
145
|
+
const nfc = d[off + 4];
|
|
146
|
+
const cbChpx = d[off + 24];
|
|
147
|
+
const cbPapx = d[off + 25];
|
|
148
|
+
let p = off + 28 + cbPapx + cbChpx;
|
|
149
|
+
if (p + 2 > d.length) return void 0;
|
|
150
|
+
const cch = u16(d, p);
|
|
151
|
+
p += 2;
|
|
152
|
+
const xst = [];
|
|
153
|
+
for (let i = 0; i < cch && p + 2 <= d.length; i++) {
|
|
154
|
+
xst.push(u16(d, p));
|
|
155
|
+
p += 2;
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
info: {
|
|
159
|
+
nfc,
|
|
160
|
+
iStartAt,
|
|
161
|
+
xst
|
|
162
|
+
},
|
|
163
|
+
next: p
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
var ICO_RGB = [
|
|
167
|
+
"000000",
|
|
168
|
+
"000000",
|
|
169
|
+
"0000FF",
|
|
170
|
+
"00FFFF",
|
|
171
|
+
"00FF00",
|
|
172
|
+
"FF00FF",
|
|
173
|
+
"FF0000",
|
|
174
|
+
"FFFF00",
|
|
175
|
+
"FFFFFF",
|
|
176
|
+
"000080",
|
|
177
|
+
"008080",
|
|
178
|
+
"008000",
|
|
179
|
+
"800080",
|
|
180
|
+
"800000",
|
|
181
|
+
"808000",
|
|
182
|
+
"808080",
|
|
183
|
+
"C0C0C0"
|
|
184
|
+
];
|
|
185
|
+
function parseTc80(d, off) {
|
|
186
|
+
const vm = u16(d, off) >> 5 & 3;
|
|
187
|
+
const top = parseBrc80(d, off + 4);
|
|
188
|
+
const left = parseBrc80(d, off + 8);
|
|
189
|
+
const bottom = parseBrc80(d, off + 12);
|
|
190
|
+
const right = parseBrc80(d, off + 16);
|
|
191
|
+
const borders = {
|
|
192
|
+
...top ? { top } : {},
|
|
193
|
+
...left ? { left } : {},
|
|
194
|
+
...bottom ? { bottom } : {},
|
|
195
|
+
...right ? { right } : {}
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
...Object.keys(borders).length > 0 ? { borders } : {},
|
|
199
|
+
...vm === 3 ? { vMerge: "restart" } : {},
|
|
200
|
+
...vm === 1 ? { vMerge: "continue" } : {}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function parseBrc80(d, off) {
|
|
204
|
+
if (off + 4 > d.length) return void 0;
|
|
205
|
+
const width = d[off];
|
|
206
|
+
const brcType = d[off + 1];
|
|
207
|
+
if (brcType === 0 || brcType === 255 || width === 0) return void 0;
|
|
208
|
+
return {
|
|
209
|
+
widthPt: Math.max(2, width) / 8,
|
|
210
|
+
colorHex: ICO_RGB[d[off + 2]] ?? "000000",
|
|
211
|
+
...brcType === 3 ? { double: true } : {}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function colorHex(r, g, b) {
|
|
215
|
+
return [
|
|
216
|
+
r,
|
|
217
|
+
g,
|
|
218
|
+
b
|
|
219
|
+
].map((c) => c.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
220
|
+
}
|
|
221
|
+
function extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText) {
|
|
222
|
+
if (u32(wd, OFF_CCPHDD) === 0) return void 0;
|
|
223
|
+
const fc = u32(wd, OFF_FCPLCFHDD);
|
|
224
|
+
const lcb = u32(wd, OFF_LCBPLCFHDD);
|
|
225
|
+
if (lcb < 8 || fc + lcb > table.length) return void 0;
|
|
226
|
+
const plc = table.subarray(fc, fc + lcb);
|
|
227
|
+
const n = Math.floor(lcb / 4);
|
|
228
|
+
const hddStart = ccpText + u32(wd, OFF_CCPFTN);
|
|
229
|
+
const story = (i) => {
|
|
230
|
+
if (i + 1 >= n) return void 0;
|
|
231
|
+
const a = hddStart + u32(plc, i * 4);
|
|
232
|
+
const b = hddStart + u32(plc, (i + 1) * 4);
|
|
233
|
+
if (b <= a) return void 0;
|
|
234
|
+
const paras = buildParagraphs(wd, pieces, chpx, papx, a, b, data);
|
|
235
|
+
return paras.some((p) => p.runs.some((r) => r.text.length > 0 || r.picture)) ? paras : void 0;
|
|
236
|
+
};
|
|
237
|
+
const evenHeader = story(6);
|
|
238
|
+
const defaultHeader = story(7);
|
|
239
|
+
const evenFooter = story(8);
|
|
240
|
+
const defaultFooter = story(9);
|
|
241
|
+
const firstHeader = story(10);
|
|
242
|
+
const firstFooter = story(11);
|
|
243
|
+
const hf = {
|
|
244
|
+
...defaultHeader ? { defaultHeader } : {},
|
|
245
|
+
...defaultFooter ? { defaultFooter } : {},
|
|
246
|
+
...firstHeader ? { firstHeader } : {},
|
|
247
|
+
...firstFooter ? { firstFooter } : {},
|
|
248
|
+
...evenHeader ? { evenHeader } : {},
|
|
249
|
+
...evenFooter ? { evenFooter } : {}
|
|
250
|
+
};
|
|
251
|
+
return Object.keys(hf).length > 0 ? hf : void 0;
|
|
252
|
+
}
|
|
253
|
+
function findPlcPcd(clx) {
|
|
254
|
+
let p = 0;
|
|
255
|
+
while (p < clx.length) {
|
|
256
|
+
const clxt = clx[p];
|
|
257
|
+
if (clxt === 1) {
|
|
258
|
+
if (p + 3 > clx.length) return void 0;
|
|
259
|
+
p += 3 + u16(clx, p + 1);
|
|
260
|
+
} else if (clxt === 2) {
|
|
261
|
+
if (p + 5 > clx.length) return void 0;
|
|
262
|
+
const lcb = u32(clx, p + 1);
|
|
263
|
+
const start = p + 5;
|
|
264
|
+
if (start + lcb > clx.length) return void 0;
|
|
265
|
+
return clx.subarray(start, start + lcb);
|
|
266
|
+
} else return;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function parsePieces(plc) {
|
|
270
|
+
if (plc.length < 12) return [];
|
|
271
|
+
const n = Math.floor((plc.length - 4) / 12);
|
|
272
|
+
if (n <= 0) return [];
|
|
273
|
+
const pcdBase = (n + 1) * 4;
|
|
274
|
+
const pieces = [];
|
|
275
|
+
for (let i = 0; i < n; i++) {
|
|
276
|
+
const fcRaw = u32(plc, pcdBase + i * 8 + 2);
|
|
277
|
+
const compressed = (fcRaw & FC_COMPRESSED) !== 0;
|
|
278
|
+
pieces.push({
|
|
279
|
+
cpStart: u32(plc, i * 4),
|
|
280
|
+
cpEnd: u32(plc, (i + 1) * 4),
|
|
281
|
+
fc: compressed ? (fcRaw & FC_MASK) >>> 1 : fcRaw & FC_MASK,
|
|
282
|
+
compressed
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return pieces;
|
|
286
|
+
}
|
|
287
|
+
function parsePlcBte(wd, table, fcOff, lcbOff, parsePage) {
|
|
288
|
+
const fcPlc = u32(wd, fcOff);
|
|
289
|
+
const lcbPlc = u32(wd, lcbOff);
|
|
290
|
+
if (lcbPlc < 8 || fcPlc + lcbPlc > table.length) return [];
|
|
291
|
+
const plc = table.subarray(fcPlc, fcPlc + lcbPlc);
|
|
292
|
+
const n = Math.floor((plc.length - 4) / 8);
|
|
293
|
+
if (n <= 0) return [];
|
|
294
|
+
const pnBase = (n + 1) * 4;
|
|
295
|
+
const out = [];
|
|
296
|
+
for (let i = 0; i < n; i++) {
|
|
297
|
+
const pageOff = (u32(plc, pnBase + i * 4) & PN_MASK) * FKP_SIZE;
|
|
298
|
+
if (pageOff + FKP_SIZE > wd.length) continue;
|
|
299
|
+
parsePage(wd.subarray(pageOff, pageOff + FKP_SIZE), out);
|
|
300
|
+
}
|
|
301
|
+
out.sort((a, b) => a.fcStart - b.fcStart);
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
function parseChpxFkp(page, out) {
|
|
305
|
+
const crun = page[FKP_SIZE - 1];
|
|
306
|
+
if (crun === 0 || (crun + 1) * 4 + crun > FKP_SIZE - 1) return;
|
|
307
|
+
for (let i = 0; i < crun; i++) {
|
|
308
|
+
const fcStart = u32(page, i * 4);
|
|
309
|
+
const fcEnd = u32(page, (i + 1) * 4);
|
|
310
|
+
if (fcEnd <= fcStart) continue;
|
|
311
|
+
let props = {};
|
|
312
|
+
const wordOff = page[(crun + 1) * 4 + i];
|
|
313
|
+
if (wordOff !== 0) {
|
|
314
|
+
const chpxOff = wordOff * 2;
|
|
315
|
+
const cb = chpxOff < FKP_SIZE ? page[chpxOff] : 0;
|
|
316
|
+
if (cb > 0 && chpxOff + 1 + cb <= FKP_SIZE) props = decodeChpxGrpprl(page.subarray(chpxOff + 1, chpxOff + 1 + cb));
|
|
317
|
+
}
|
|
318
|
+
out.push({
|
|
319
|
+
fcStart,
|
|
320
|
+
fcEnd,
|
|
321
|
+
props
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function parsePapxFkp(page, out) {
|
|
326
|
+
const cpara = page[FKP_SIZE - 1];
|
|
327
|
+
if (cpara === 0 || (cpara + 1) * 4 + cpara * 13 > FKP_SIZE - 1) return;
|
|
328
|
+
const bxBase = (cpara + 1) * 4;
|
|
329
|
+
for (let i = 0; i < cpara; i++) {
|
|
330
|
+
const fcStart = u32(page, i * 4);
|
|
331
|
+
const fcEnd = u32(page, (i + 1) * 4);
|
|
332
|
+
if (fcEnd <= fcStart) continue;
|
|
333
|
+
let props = {};
|
|
334
|
+
const papxOff = page[bxBase + i * 13] * 2;
|
|
335
|
+
if (papxOff !== 0 && papxOff < FKP_SIZE) {
|
|
336
|
+
const cb = page[papxOff];
|
|
337
|
+
const size = cb !== 0 ? 2 * cb - 1 : 2 * (page[papxOff + 1] ?? 0);
|
|
338
|
+
const start = cb !== 0 ? papxOff + 1 : papxOff + 2;
|
|
339
|
+
if (size >= 2 && start + size <= FKP_SIZE) props = decodePapxGrpprl(page.subarray(start + 2, start + size));
|
|
340
|
+
}
|
|
341
|
+
out.push({
|
|
342
|
+
fcStart,
|
|
343
|
+
fcEnd,
|
|
344
|
+
props
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function decodeChpxGrpprl(d) {
|
|
349
|
+
let bold;
|
|
350
|
+
let italic;
|
|
351
|
+
let underlineKul;
|
|
352
|
+
let sizeHalfPts;
|
|
353
|
+
let fSpec;
|
|
354
|
+
let picOffset;
|
|
355
|
+
for (const s of sprms(d)) switch (s.sprm) {
|
|
356
|
+
case SPRM_C_FBOLD:
|
|
357
|
+
bold = toggleBool(d[s.op]);
|
|
358
|
+
break;
|
|
359
|
+
case SPRM_C_FITALIC:
|
|
360
|
+
italic = toggleBool(d[s.op]);
|
|
361
|
+
break;
|
|
362
|
+
case SPRM_C_KUL:
|
|
363
|
+
underlineKul = d[s.op];
|
|
364
|
+
break;
|
|
365
|
+
case SPRM_C_HPS:
|
|
366
|
+
sizeHalfPts = u16(d, s.op);
|
|
367
|
+
break;
|
|
368
|
+
case SPRM_C_FSPEC:
|
|
369
|
+
fSpec = d[s.op] !== 0;
|
|
370
|
+
break;
|
|
371
|
+
case SPRM_C_PIC_LOCATION:
|
|
372
|
+
picOffset = u32(d, s.op);
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
...bold !== void 0 ? { bold } : {},
|
|
377
|
+
...italic !== void 0 ? { italic } : {},
|
|
378
|
+
...underlineKul !== void 0 ? { underlineKul } : {},
|
|
379
|
+
...sizeHalfPts !== void 0 ? { sizeHalfPts } : {},
|
|
380
|
+
...fSpec ? { fSpec } : {},
|
|
381
|
+
...picOffset !== void 0 ? { picOffset } : {}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function decodePapxGrpprl(d) {
|
|
385
|
+
let jc;
|
|
386
|
+
let indentLeftTwips;
|
|
387
|
+
let indentRightTwips;
|
|
388
|
+
let indentFirstTwips;
|
|
389
|
+
let spaceBeforeTwips;
|
|
390
|
+
let spaceAfterTwips;
|
|
391
|
+
let inTable;
|
|
392
|
+
let rowEnd;
|
|
393
|
+
let cellEdgesTwips;
|
|
394
|
+
let cellDescriptors;
|
|
395
|
+
let cellShadings;
|
|
396
|
+
let listIlfo;
|
|
397
|
+
let listIlvl;
|
|
398
|
+
for (const s of sprms(d)) switch (s.sprm) {
|
|
399
|
+
case SPRM_P_JC:
|
|
400
|
+
jc = d[s.op];
|
|
401
|
+
break;
|
|
402
|
+
case SPRM_P_DXA_LEFT:
|
|
403
|
+
indentLeftTwips = i16(d, s.op);
|
|
404
|
+
break;
|
|
405
|
+
case SPRM_P_DXA_RIGHT:
|
|
406
|
+
indentRightTwips = i16(d, s.op);
|
|
407
|
+
break;
|
|
408
|
+
case SPRM_P_DXA_LEFT1:
|
|
409
|
+
indentFirstTwips = i16(d, s.op);
|
|
410
|
+
break;
|
|
411
|
+
case SPRM_P_DYA_BEFORE:
|
|
412
|
+
spaceBeforeTwips = u16(d, s.op);
|
|
413
|
+
break;
|
|
414
|
+
case SPRM_P_DYA_AFTER:
|
|
415
|
+
spaceAfterTwips = u16(d, s.op);
|
|
416
|
+
break;
|
|
417
|
+
case SPRM_P_F_IN_TABLE:
|
|
418
|
+
inTable = d[s.op] !== 0;
|
|
419
|
+
break;
|
|
420
|
+
case SPRM_P_F_TTP:
|
|
421
|
+
rowEnd = d[s.op] !== 0;
|
|
422
|
+
break;
|
|
423
|
+
case SPRM_T_DEF_TABLE: {
|
|
424
|
+
const cols = d[s.op] ?? 0;
|
|
425
|
+
const edges = [];
|
|
426
|
+
for (let i = 0; i <= cols && s.op + 1 + i * 2 + 2 <= d.length; i++) edges.push(i16(d, s.op + 1 + i * 2));
|
|
427
|
+
if (edges.length >= 2) cellEdgesTwips = edges;
|
|
428
|
+
const tcBase = s.op + 1 + (cols + 1) * 2;
|
|
429
|
+
const descriptors = [];
|
|
430
|
+
for (let i = 0; i < cols && tcBase + i * 20 + 20 <= d.length; i++) descriptors.push(parseTc80(d, tcBase + i * 20));
|
|
431
|
+
if (descriptors.length > 0) cellDescriptors = descriptors;
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
case SPRM_P_ILVL:
|
|
435
|
+
listIlvl = d[s.op];
|
|
436
|
+
break;
|
|
437
|
+
case SPRM_T_DEF_TABLE_SHD: {
|
|
438
|
+
const shd = [];
|
|
439
|
+
for (let i = 0; s.op + i * 10 + 10 <= d.length && i < MAX_ROW_CELLS; i++) {
|
|
440
|
+
const o = s.op + i * 10 + 4;
|
|
441
|
+
shd.push(d[o + 3] === 0 ? colorHex(d[o], d[o + 1], d[o + 2]) : void 0);
|
|
442
|
+
}
|
|
443
|
+
if (shd.length > 0) cellShadings = shd;
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
446
|
+
case SPRM_P_ILFO:
|
|
447
|
+
listIlfo = u16(d, s.op);
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
...jc !== void 0 ? { jc } : {},
|
|
452
|
+
...indentLeftTwips !== void 0 ? { indentLeftTwips } : {},
|
|
453
|
+
...indentRightTwips !== void 0 ? { indentRightTwips } : {},
|
|
454
|
+
...indentFirstTwips !== void 0 ? { indentFirstTwips } : {},
|
|
455
|
+
...spaceBeforeTwips !== void 0 ? { spaceBeforeTwips } : {},
|
|
456
|
+
...spaceAfterTwips !== void 0 ? { spaceAfterTwips } : {},
|
|
457
|
+
...inTable ? { inTable } : {},
|
|
458
|
+
...rowEnd ? { rowEnd } : {},
|
|
459
|
+
...cellEdgesTwips ? { cellEdgesTwips } : {},
|
|
460
|
+
...cellDescriptors ? { cellDescriptors } : {},
|
|
461
|
+
...cellShadings ? { cellShadings } : {},
|
|
462
|
+
...listIlfo !== void 0 ? { listIlfo } : {},
|
|
463
|
+
...listIlvl !== void 0 ? { listIlvl } : {}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function* sprms(d) {
|
|
467
|
+
let p = 0;
|
|
468
|
+
while (p + 2 <= d.length) {
|
|
469
|
+
const sprm = u16(d, p);
|
|
470
|
+
p += 2;
|
|
471
|
+
const spra = sprm >> 13;
|
|
472
|
+
let op = p;
|
|
473
|
+
let len = SPRA_LEN[spra];
|
|
474
|
+
if (spra === 6) if (SPRM_LONG_OPERAND.has(sprm)) {
|
|
475
|
+
if (p + 2 > d.length) break;
|
|
476
|
+
const cb = u16(d, p);
|
|
477
|
+
if (cb < 1) break;
|
|
478
|
+
len = cb - 1;
|
|
479
|
+
op = p + 2;
|
|
480
|
+
} else {
|
|
481
|
+
if (p >= d.length) break;
|
|
482
|
+
len = d[p];
|
|
483
|
+
op = p + 1;
|
|
484
|
+
}
|
|
485
|
+
if (op + len > d.length) break;
|
|
486
|
+
yield {
|
|
487
|
+
sprm,
|
|
488
|
+
op
|
|
489
|
+
};
|
|
490
|
+
p = op + len;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function toggleBool(v) {
|
|
494
|
+
if (v === 0) return false;
|
|
495
|
+
if (v === 1 || v === 129) return true;
|
|
496
|
+
}
|
|
497
|
+
function extractPicture(data, fcPic) {
|
|
498
|
+
if (fcPic < 0 || fcPic + 36 > data.length) return void 0;
|
|
499
|
+
const lcb = u32(data, fcPic);
|
|
500
|
+
const cbHeader = u16(data, fcPic + 4);
|
|
501
|
+
if (cbHeader < 46 || lcb <= cbHeader || fcPic + lcb > data.length) return void 0;
|
|
502
|
+
const dxaGoal = u16(data, fcPic + 28);
|
|
503
|
+
const dyaGoal = u16(data, fcPic + 30);
|
|
504
|
+
const mx = u16(data, fcPic + 32) || 1e3;
|
|
505
|
+
const my = u16(data, fcPic + 34) || 1e3;
|
|
506
|
+
const bytes = scanImage(data.subarray(fcPic + cbHeader, fcPic + lcb));
|
|
507
|
+
if (!bytes) return void 0;
|
|
508
|
+
return {
|
|
509
|
+
bytes,
|
|
510
|
+
widthTwips: Math.round(dxaGoal * mx / 1e3),
|
|
511
|
+
heightTwips: Math.round(dyaGoal * my / 1e3)
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
var IMAGE_MAGICS = [
|
|
515
|
+
[
|
|
516
|
+
137,
|
|
517
|
+
80,
|
|
518
|
+
78,
|
|
519
|
+
71
|
|
520
|
+
],
|
|
521
|
+
[
|
|
522
|
+
255,
|
|
523
|
+
216,
|
|
524
|
+
255
|
|
525
|
+
],
|
|
526
|
+
[
|
|
527
|
+
71,
|
|
528
|
+
73,
|
|
529
|
+
70,
|
|
530
|
+
56
|
|
531
|
+
],
|
|
532
|
+
[66, 77],
|
|
533
|
+
[
|
|
534
|
+
73,
|
|
535
|
+
73,
|
|
536
|
+
42,
|
|
537
|
+
0
|
|
538
|
+
],
|
|
539
|
+
[
|
|
540
|
+
77,
|
|
541
|
+
77,
|
|
542
|
+
0,
|
|
543
|
+
42
|
|
544
|
+
]
|
|
545
|
+
];
|
|
546
|
+
function scanImage(region) {
|
|
547
|
+
const limit = Math.min(region.length, 512);
|
|
548
|
+
for (let off = 0; off < limit; off++) for (const magic of IMAGE_MAGICS) if (off + magic.length <= region.length && magicAt(region, off, magic)) return region.subarray(off);
|
|
549
|
+
}
|
|
550
|
+
function magicAt(d, off, magic) {
|
|
551
|
+
for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
554
|
+
function buildParagraphs(wd, pieces, chpx, papx, cpStart, cpEnd, data) {
|
|
555
|
+
const end = Math.min(cpEnd, cpStart + MAX_TEXT);
|
|
556
|
+
const paragraphs = [];
|
|
557
|
+
let runs = [];
|
|
558
|
+
let cur = "";
|
|
559
|
+
let curProps = {};
|
|
560
|
+
let lastFc = 0;
|
|
561
|
+
let fieldDepth = 0;
|
|
562
|
+
let codeDepth = 0;
|
|
563
|
+
const flushRun = () => {
|
|
564
|
+
if (cur.length > 0) {
|
|
565
|
+
runs.push({
|
|
566
|
+
text: cur,
|
|
567
|
+
props: curProps
|
|
568
|
+
});
|
|
569
|
+
cur = "";
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
const endParagraph = (fc, cellMark) => {
|
|
573
|
+
flushRun();
|
|
574
|
+
paragraphs.push({
|
|
575
|
+
runs,
|
|
576
|
+
props: lookup(papx, fc) ?? {},
|
|
577
|
+
...cellMark ? { cellMark: true } : {}
|
|
578
|
+
});
|
|
579
|
+
runs = [];
|
|
580
|
+
};
|
|
581
|
+
for (const piece of pieces) {
|
|
582
|
+
if (piece.cpStart >= end) break;
|
|
583
|
+
if (piece.cpEnd <= cpStart) continue;
|
|
584
|
+
const step = piece.compressed ? 1 : 2;
|
|
585
|
+
const kStart = Math.max(0, cpStart - piece.cpStart);
|
|
586
|
+
const kEnd = Math.min(piece.cpEnd - piece.cpStart, end - piece.cpStart);
|
|
587
|
+
for (let k = kStart; k < kEnd; k++) {
|
|
588
|
+
const fc = piece.fc + k * step;
|
|
589
|
+
lastFc = fc;
|
|
590
|
+
const code = piece.compressed ? byteCode(wd, fc) : unitCode(wd, fc);
|
|
591
|
+
if (code < 0) continue;
|
|
592
|
+
if (code === CR || code === CELL_MARK) {
|
|
593
|
+
endParagraph(fc, code === CELL_MARK);
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
if (code === FIELD_BEGIN) {
|
|
597
|
+
fieldDepth++;
|
|
598
|
+
codeDepth++;
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (code === FIELD_SEPARATOR) {
|
|
602
|
+
if (codeDepth > 0) codeDepth--;
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (code === FIELD_END) {
|
|
606
|
+
if (fieldDepth > 0) fieldDepth--;
|
|
607
|
+
if (codeDepth > fieldDepth) codeDepth = fieldDepth;
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (codeDepth > 0) continue;
|
|
611
|
+
if (code === PIC_CHAR) {
|
|
612
|
+
const props = lookup(chpx, fc) ?? {};
|
|
613
|
+
const picture = data && props.fSpec && props.picOffset !== void 0 ? extractPicture(data, props.picOffset) : void 0;
|
|
614
|
+
if (picture) {
|
|
615
|
+
flushRun();
|
|
616
|
+
runs.push({
|
|
617
|
+
text: "",
|
|
618
|
+
props: {},
|
|
619
|
+
picture
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const ch = code === 9 || code === 11 ? " " : code < 32 ? "" : String.fromCharCode(code);
|
|
625
|
+
if (ch.length === 0) continue;
|
|
626
|
+
const props = lookup(chpx, fc) ?? {};
|
|
627
|
+
if (cur.length === 0) curProps = props;
|
|
628
|
+
else if (!sameProps(props, curProps)) {
|
|
629
|
+
flushRun();
|
|
630
|
+
curProps = props;
|
|
631
|
+
}
|
|
632
|
+
cur += ch;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
if (cur.length > 0 || runs.length > 0) endParagraph(lastFc, false);
|
|
636
|
+
return paragraphs;
|
|
637
|
+
}
|
|
638
|
+
function lookup(runs, fc) {
|
|
639
|
+
let lo = 0;
|
|
640
|
+
let hi = runs.length - 1;
|
|
641
|
+
while (lo <= hi) {
|
|
642
|
+
const mid = lo + hi >> 1;
|
|
643
|
+
const r = runs[mid];
|
|
644
|
+
if (fc < r.fcStart) hi = mid - 1;
|
|
645
|
+
else if (fc >= r.fcEnd) lo = mid + 1;
|
|
646
|
+
else return r.props;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
function sameProps(a, b) {
|
|
650
|
+
return a.bold === b.bold && a.italic === b.italic && a.underlineKul === b.underlineKul && a.sizeHalfPts === b.sizeHalfPts;
|
|
651
|
+
}
|
|
652
|
+
var CP1252_HIGH = [
|
|
653
|
+
8364,
|
|
654
|
+
129,
|
|
655
|
+
8218,
|
|
656
|
+
402,
|
|
657
|
+
8222,
|
|
658
|
+
8230,
|
|
659
|
+
8224,
|
|
660
|
+
8225,
|
|
661
|
+
710,
|
|
662
|
+
8240,
|
|
663
|
+
352,
|
|
664
|
+
8249,
|
|
665
|
+
338,
|
|
666
|
+
141,
|
|
667
|
+
381,
|
|
668
|
+
143,
|
|
669
|
+
144,
|
|
670
|
+
8216,
|
|
671
|
+
8217,
|
|
672
|
+
8220,
|
|
673
|
+
8221,
|
|
674
|
+
8226,
|
|
675
|
+
8211,
|
|
676
|
+
8212,
|
|
677
|
+
732,
|
|
678
|
+
8482,
|
|
679
|
+
353,
|
|
680
|
+
8250,
|
|
681
|
+
339,
|
|
682
|
+
157,
|
|
683
|
+
382,
|
|
684
|
+
376
|
|
685
|
+
];
|
|
686
|
+
function byteCode(d, fc) {
|
|
687
|
+
const b = d[fc];
|
|
688
|
+
if (b === void 0) return -1;
|
|
689
|
+
return b >= 128 && b <= 159 ? CP1252_HIGH[b - 128] : b;
|
|
690
|
+
}
|
|
691
|
+
function unitCode(d, fc) {
|
|
692
|
+
if (fc + 1 >= d.length) return -1;
|
|
693
|
+
return d[fc] | d[fc + 1] << 8;
|
|
694
|
+
}
|
|
695
|
+
function u16(d, off) {
|
|
696
|
+
return (d[off] ?? 0) | (d[off + 1] ?? 0) << 8;
|
|
697
|
+
}
|
|
698
|
+
function i16(d, off) {
|
|
699
|
+
const v = u16(d, off);
|
|
700
|
+
return v >= 32768 ? v - 65536 : v;
|
|
701
|
+
}
|
|
702
|
+
function u32(d, off) {
|
|
703
|
+
return ((d[off] ?? 0) | (d[off + 1] ?? 0) << 8 | (d[off + 2] ?? 0) << 16 | (d[off + 3] ?? 0) << 24) >>> 0;
|
|
704
|
+
}
|
|
705
|
+
//#endregion
|
|
706
|
+
export { extractDocContent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reamkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Ream — convert DOCX, XLSX, PPTX and PDF to PDF, SVG, HTML, DOCX and XLSX, built from scratch on the ECMA-376 and ISO 32000 specifications. Parse once, convert anywhere.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alex Krassavin <info@reamkit.dev>",
|