wpd-codec 3.1.1 → 3.2.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 +30 -26
- package/dist/bytes/view.cjs +5 -0
- package/dist/bytes/view.d.cts +2 -1
- package/dist/bytes/view.d.ts +2 -1
- package/dist/bytes/view.js +5 -1
- package/dist/container/prefix.cjs +15 -0
- package/dist/container/prefix.d.cts +3 -1
- package/dist/container/prefix.d.ts +3 -1
- package/dist/container/prefix.js +14 -1
- package/dist/{diagnostics-CR0pXOyb.d.cts → diagnostics-Dtb2uPw4.d.cts} +5 -0
- package/dist/{diagnostics-CR0pXOyb.d.ts → diagnostics-Dtb2uPw4.d.ts} +5 -0
- package/dist/diagnostics.cjs +6 -1
- package/dist/diagnostics.d.cts +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +6 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/read.cjs +213 -48
- package/dist/read.d.cts +1 -1
- package/dist/read.d.ts +1 -1
- package/dist/read.js +215 -50
- package/dist/stream/box.cjs +122 -0
- package/dist/stream/box.d.cts +20 -0
- package/dist/stream/box.d.ts +20 -0
- package/dist/stream/box.js +117 -0
- package/dist/stream/formula.cjs +286 -0
- package/dist/stream/formula.d.cts +4 -0
- package/dist/stream/formula.d.ts +4 -0
- package/dist/stream/formula.js +285 -0
- package/dist/stream/style.cjs +19 -0
- package/dist/stream/style.d.cts +3 -1
- package/dist/stream/style.d.ts +3 -1
- package/dist/stream/style.js +18 -1
- package/dist/stream/table.cjs +2 -1
- package/dist/stream/table.d.cts +2 -1
- package/dist/stream/table.d.ts +2 -1
- package/dist/stream/table.js +2 -2
- package/package.json +3 -3
package/dist/read.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { uint16At } from "./bytes/view.js";
|
|
2
2
|
import { decodeSingleByteCharacter, decodeWpCharacter } from "./stream/characters.js";
|
|
3
|
-
import { packetByPrefixId, readTypefaceName } from "./container/prefix.js";
|
|
3
|
+
import { packetByPrefixId, readGeneralWpTextBlocks, readTypefaceName } from "./container/prefix.js";
|
|
4
4
|
import { openWpdDocument } from "./container/container.js";
|
|
5
5
|
import { readDocumentSummary } from "./container/summary.js";
|
|
6
6
|
import { NOOP_WPD_DIAGNOSTIC_SINK, WpdDiagnosticCodes } from "./diagnostics.js";
|
|
7
7
|
import { decodeAttributeByte, runAttributesFrom } from "./stream/attributes.js";
|
|
8
8
|
import { eolMappingForSubfunction, isSingleByteEol, subfunctionForSingleByteEol } from "./stream/eol.js";
|
|
9
9
|
import { readMarginPt, readPageForm } from "./stream/page.js";
|
|
10
|
-
import { isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isStyleScopeCloser, isStyleScopeOpener, readDisplayNumberLevel, readSystemStyleNumber, styleSemanticsFor } from "./stream/style.js";
|
|
10
|
+
import { isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isStyleScopeCloser, isStyleScopeOpener, readDisplayNumberLevel, readStyleBeginBlock, readSystemStyleNumber, styleSemanticsFor } from "./stream/style.js";
|
|
11
11
|
import { findEmbeddedSubfunction, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt } from "./stream/table.js";
|
|
12
|
+
import { readBoxContent } from "./stream/box.js";
|
|
13
|
+
import { readTableFormula } from "./stream/formula.js";
|
|
12
14
|
import { tabEffectFor } from "./stream/tab.js";
|
|
13
15
|
import { tokeniseDocumentArea } from "./stream/tokenise.js";
|
|
14
16
|
import { assembleTree } from "document-schema.js";
|
|
@@ -29,6 +31,8 @@ const CROSS_REFERENCE_GROUP = 213;
|
|
|
29
31
|
const HEADER_FOOTER_GROUP = 214;
|
|
30
32
|
const FOOTNOTE_ENDNOTE_GROUP = 215;
|
|
31
33
|
const MERGE_GROUP = 222;
|
|
34
|
+
const MERGE_FIELD_ON = 76;
|
|
35
|
+
const MERGE_FIELD_OFF = 77;
|
|
32
36
|
const BOX_GROUP = 223;
|
|
33
37
|
const PARAGRAPH_GROUP = 211;
|
|
34
38
|
const PARAGRAPH_SET_JUSTIFICATION = 5;
|
|
@@ -48,6 +52,7 @@ const JUSTIFICATION = [
|
|
|
48
52
|
const THREE_THOUSAND_SIX_HUNDREDTHS_PER_POINT = 50;
|
|
49
53
|
const COLOR_COMPONENT_MAX = 255;
|
|
50
54
|
const NO_SPAN = 1;
|
|
55
|
+
const MAX_STYLE_RESOLUTION_DEPTH = 16;
|
|
51
56
|
function sameAttributes(a, b) {
|
|
52
57
|
return a.bold === b.bold && a.italic === b.italic && a.underline === b.underline && a.strike === b.strike;
|
|
53
58
|
}
|
|
@@ -79,29 +84,35 @@ function flushRun(state) {
|
|
|
79
84
|
function targetBlocks(state) {
|
|
80
85
|
return state.table === void 0 ? state.blocks : state.table.cellBlocks;
|
|
81
86
|
}
|
|
82
|
-
function flushParagraph(state) {
|
|
87
|
+
function flushParagraph(state, sink) {
|
|
83
88
|
flushRun(state);
|
|
89
|
+
if (state.openMergeFieldStartRun !== void 0) {
|
|
90
|
+
state.openMergeFieldStartRun = void 0;
|
|
91
|
+
reportOnce(state, sink, WpdDiagnosticCodes.MergeFieldSpansParagraphs, "A merge field's own On/Off pair straddled a paragraph boundary, which the run-scoped field construct cannot express; its text became ordinary paragraph text with no field tag.");
|
|
92
|
+
}
|
|
84
93
|
const alignment = state.pendingAlignment ?? state.alignment;
|
|
94
|
+
const constructs = state.pendingConstructs.splice(0, state.pendingConstructs.length);
|
|
85
95
|
const paragraph = {
|
|
86
96
|
kind: "paragraph",
|
|
87
97
|
runs: state.runs.splice(0, state.runs.length),
|
|
88
98
|
...alignment === void 0 ? {} : { alignment },
|
|
89
99
|
...state.pendingHeadingLevel === void 0 ? {} : { headingLevel: state.pendingHeadingLevel },
|
|
90
|
-
...state.pendingListLevel === void 0 ? {} : { list: { level: state.pendingListLevel } }
|
|
100
|
+
...state.pendingListLevel === void 0 ? {} : { list: { level: state.pendingListLevel } },
|
|
101
|
+
...constructs.length === 0 ? {} : { constructs }
|
|
91
102
|
};
|
|
92
103
|
state.pendingHeadingLevel = void 0;
|
|
93
104
|
state.pendingListLevel = void 0;
|
|
94
105
|
state.pendingAlignment = void 0;
|
|
95
106
|
targetBlocks(state).push(paragraph);
|
|
96
107
|
}
|
|
97
|
-
function flushParagraphIfContent(state) {
|
|
108
|
+
function flushParagraphIfContent(state, sink) {
|
|
98
109
|
if (state.text.length === 0 && state.runs.length === 0) return;
|
|
99
|
-
flushParagraph(state);
|
|
110
|
+
flushParagraph(state, sink);
|
|
100
111
|
}
|
|
101
112
|
function effectiveStyle(state) {
|
|
102
113
|
for (let index = state.styleScopes.length - 1; index >= 0; index -= 1) {
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
114
|
+
const semantics = state.styleScopes[index]?.semantics;
|
|
115
|
+
if (semantics !== void 0) return semantics;
|
|
105
116
|
}
|
|
106
117
|
}
|
|
107
118
|
function appendText(state, text) {
|
|
@@ -122,6 +133,9 @@ function readCellAttributes(state, nonDeletable, sink) {
|
|
|
122
133
|
const spanning = findEmbeddedSubfunction(subfunctions, 133);
|
|
123
134
|
const fill = findEmbeddedSubfunction(subfunctions, 134);
|
|
124
135
|
const row = findEmbeddedSubfunction(subfunctions, 128);
|
|
136
|
+
const formulaData = findEmbeddedSubfunction(subfunctions, 129);
|
|
137
|
+
const formula = formulaData === void 0 ? void 0 : readTableFormula(formulaData);
|
|
138
|
+
if (formulaData !== void 0 && formula === void 0) reportOnce(state, sink, WpdDiagnosticCodes.TableFormulaUnresolved, "A table cell carries a formula this reader could not decode with confidence, so the cell keeps its displayed text but not the formula that produced it.");
|
|
125
139
|
const cellSpanning = spanning === void 0 ? void 0 : readCellSpanning(spanning);
|
|
126
140
|
const cellFill = fill === void 0 ? void 0 : readCellFill(fill);
|
|
127
141
|
if (cellFill?.blended === true) reportOnce(state, sink, WpdDiagnosticCodes.CellFillBlended, "A cell is filled with a shaded blend of two colours, resolved to a 'pattern' fill whose density is this reader's own best-effort derivation, not a value confirmed against a specification.");
|
|
@@ -131,13 +145,14 @@ function readCellAttributes(state, nonDeletable, sink) {
|
|
|
131
145
|
background: cellFill?.fill,
|
|
132
146
|
columnSpan: cellSpanning?.columnSpan ?? NO_SPAN,
|
|
133
147
|
rowSpan: cellSpanning?.rowSpan ?? NO_SPAN,
|
|
134
|
-
covered: cellSpanning?.coveredFromLeft === true || cellSpanning?.coveredFromAbove === true
|
|
148
|
+
covered: cellSpanning?.coveredFromLeft === true || cellSpanning?.coveredFromAbove === true,
|
|
149
|
+
formula
|
|
135
150
|
},
|
|
136
151
|
rowHeightPt: row === void 0 ? void 0 : readRowInformation(row)?.heightPt
|
|
137
152
|
};
|
|
138
153
|
}
|
|
139
|
-
function closeCell(state, table, attributes) {
|
|
140
|
-
flushParagraphIfContent(state);
|
|
154
|
+
function closeCell(state, table, attributes, sink) {
|
|
155
|
+
flushParagraphIfContent(state, sink);
|
|
141
156
|
const blocks = table.cellBlocks;
|
|
142
157
|
table.cellBlocks = [];
|
|
143
158
|
if (attributes.covered) return;
|
|
@@ -148,7 +163,8 @@ function closeCell(state, table, attributes) {
|
|
|
148
163
|
blocks,
|
|
149
164
|
...attributes.columnSpan > NO_SPAN ? { colSpan: attributes.columnSpan } : {},
|
|
150
165
|
...attributes.rowSpan > NO_SPAN ? { rowSpan: attributes.rowSpan } : {},
|
|
151
|
-
...attributes.background === void 0 ? {} : { background: attributes.background }
|
|
166
|
+
...attributes.background === void 0 ? {} : { background: attributes.background },
|
|
167
|
+
...attributes.formula === void 0 ? {} : { formula: attributes.formula }
|
|
152
168
|
};
|
|
153
169
|
table.cells.push(cell);
|
|
154
170
|
}
|
|
@@ -180,14 +196,14 @@ function applyEolMapping(state, mapping, nonDeletable, sink) {
|
|
|
180
196
|
appendText(state, " ");
|
|
181
197
|
return;
|
|
182
198
|
case "hardReturn":
|
|
183
|
-
flushParagraph(state);
|
|
199
|
+
flushParagraph(state, sink);
|
|
184
200
|
return;
|
|
185
201
|
case "hardEndOfColumn":
|
|
186
202
|
reportOnce(state, sink, WpdDiagnosticCodes.ColumnBreakFlattened, "A column break became a paragraph break.");
|
|
187
|
-
flushParagraph(state);
|
|
203
|
+
flushParagraph(state, sink);
|
|
188
204
|
return;
|
|
189
205
|
case "hardEndOfPage":
|
|
190
|
-
flushParagraph(state);
|
|
206
|
+
flushParagraph(state, sink);
|
|
191
207
|
targetBlocks(state).push({ kind: "pageBreak" });
|
|
192
208
|
return;
|
|
193
209
|
case "tableCell":
|
|
@@ -197,13 +213,13 @@ function applyEolMapping(state, mapping, nonDeletable, sink) {
|
|
|
197
213
|
const table = state.table;
|
|
198
214
|
if (table === void 0) {
|
|
199
215
|
reportOnce(state, sink, WpdDiagnosticCodes.TableFlattened, "A table cell or row boundary appeared with no table definition open; its text became a paragraph.");
|
|
200
|
-
flushParagraph(state);
|
|
216
|
+
flushParagraph(state, sink);
|
|
201
217
|
return;
|
|
202
218
|
}
|
|
203
219
|
const { attributes, rowHeightPt } = readCellAttributes(state, nonDeletable, sink);
|
|
204
220
|
if (rowHeightPt !== void 0) table.rowHeightPt = rowHeightPt;
|
|
205
221
|
const cellIsOpen = state.text.length > 0 || state.runs.length > 0 || table.cellBlocks.length > 0;
|
|
206
|
-
if (mapping !== "tableOff" || cellIsOpen) closeCell(state, table, attributes);
|
|
222
|
+
if (mapping !== "tableOff" || cellIsOpen) closeCell(state, table, attributes, sink);
|
|
207
223
|
if (mapping === "tableCell") return;
|
|
208
224
|
closeRow(table);
|
|
209
225
|
if (mapping === "tableOff") closeTable(state);
|
|
@@ -232,13 +248,13 @@ function applySingleByteFunction(state, code, sink) {
|
|
|
232
248
|
appendText(state, "-");
|
|
233
249
|
return;
|
|
234
250
|
case DORMANT_HARD_RETURN:
|
|
235
|
-
flushParagraph(state);
|
|
251
|
+
flushParagraph(state, sink);
|
|
236
252
|
return;
|
|
237
253
|
case SOFT_END_OF_CENTER_ALIGN:
|
|
238
254
|
appendText(state, " ");
|
|
239
255
|
return;
|
|
240
256
|
case HARD_END_OF_CENTER_ALIGN:
|
|
241
|
-
flushParagraph(state);
|
|
257
|
+
flushParagraph(state, sink);
|
|
242
258
|
return;
|
|
243
259
|
case START_OF_TEXT_TO_SKIP:
|
|
244
260
|
state.skipDepth += 1;
|
|
@@ -300,13 +316,56 @@ function applyColumnGroup(state, token, sink) {
|
|
|
300
316
|
if (token.subgroup === 0) setPageDimension(state, "leftPt", margin, sink);
|
|
301
317
|
else if (token.subgroup === 1) setPageDimension(state, "rightPt", margin, sink);
|
|
302
318
|
}
|
|
303
|
-
function
|
|
319
|
+
function snapshotFormatting(state) {
|
|
320
|
+
return {
|
|
321
|
+
activeAttributes: new Set(state.activeAttributes),
|
|
322
|
+
fontFamily: state.fontFamily,
|
|
323
|
+
sizePt: state.sizePt,
|
|
324
|
+
color: state.color
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function restoreFormattingSnapshot(state, snapshot) {
|
|
328
|
+
flushRun(state);
|
|
329
|
+
state.activeAttributes.clear();
|
|
330
|
+
for (const attribute of snapshot.activeAttributes) state.activeAttributes.add(attribute);
|
|
331
|
+
state.attributes = runAttributesFrom(state.activeAttributes);
|
|
332
|
+
state.fontFamily = snapshot.fontFamily;
|
|
333
|
+
state.sizePt = snapshot.sizePt;
|
|
334
|
+
state.color = snapshot.color;
|
|
335
|
+
}
|
|
336
|
+
function applyStylePacketBegin(state, token, container, sink) {
|
|
337
|
+
const prefixId = token.prefixIds[0];
|
|
338
|
+
if (prefixId === void 0) return;
|
|
339
|
+
const packet = packetByPrefixId(container.packets, prefixId);
|
|
340
|
+
if (packet?.packetType !== 48) return;
|
|
341
|
+
const beginBlock = readStyleBeginBlock(packet.bytes);
|
|
342
|
+
if (beginBlock === void 0) return;
|
|
343
|
+
if (state.styleResolutionDepth >= MAX_STYLE_RESOLUTION_DEPTH) {
|
|
344
|
+
reportOnce(state, sink, WpdDiagnosticCodes.StyleResolutionDepthExceeded, "A chain of styles resolving one another's own packets ran deeper than this reader will follow, so the deepest style's own direct formatting was not applied.");
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const snapshot = snapshotFormatting(state);
|
|
348
|
+
const tokens = tokeniseDocumentArea(beginBlock, 0, beginBlock.length);
|
|
349
|
+
state.styleResolutionDepth += 1;
|
|
350
|
+
for (const beginToken of tokens) applyToken(state, beginToken, container, sink);
|
|
351
|
+
state.styleResolutionDepth -= 1;
|
|
352
|
+
return snapshot;
|
|
353
|
+
}
|
|
354
|
+
function applyStyleGroup(state, token, container, sink) {
|
|
304
355
|
if (isStyleScopeOpener(token.subgroup)) {
|
|
305
356
|
const systemStyleNumber = readSystemStyleNumber(token.nonDeletable);
|
|
306
|
-
|
|
357
|
+
const semantics = systemStyleNumber === void 0 ? void 0 : styleSemanticsFor(systemStyleNumber);
|
|
358
|
+
const snapshot = applyStylePacketBegin(state, token, container, sink);
|
|
359
|
+
state.styleScopes.push({
|
|
360
|
+
semantics,
|
|
361
|
+
snapshot
|
|
362
|
+
});
|
|
307
363
|
return;
|
|
308
364
|
}
|
|
309
|
-
if (isStyleScopeCloser(token.subgroup))
|
|
365
|
+
if (isStyleScopeCloser(token.subgroup)) {
|
|
366
|
+
const entry = state.styleScopes.pop();
|
|
367
|
+
if (entry?.snapshot !== void 0) restoreFormattingSnapshot(state, entry.snapshot);
|
|
368
|
+
}
|
|
310
369
|
}
|
|
311
370
|
function applyDisplayNumberGroup(state, token, sink) {
|
|
312
371
|
if (isParagraphNumberDisplayOn(token.subgroup)) {
|
|
@@ -322,7 +381,7 @@ function applyCharacterGroup(state, token, container, sink) {
|
|
|
322
381
|
switch (token.subgroup) {
|
|
323
382
|
case 42:
|
|
324
383
|
closeTable(state);
|
|
325
|
-
flushParagraphIfContent(state);
|
|
384
|
+
flushParagraphIfContent(state, sink);
|
|
326
385
|
state.table = {
|
|
327
386
|
columnWidthsPt: [],
|
|
328
387
|
rows: [],
|
|
@@ -367,6 +426,104 @@ function applyCharacterGroup(state, token, container, sink) {
|
|
|
367
426
|
default: return;
|
|
368
427
|
}
|
|
369
428
|
}
|
|
429
|
+
function applyMergeGroup(state, token, sink) {
|
|
430
|
+
if (token.subgroup === MERGE_FIELD_ON) {
|
|
431
|
+
flushRun(state);
|
|
432
|
+
state.openMergeFieldStartRun = state.runs.length;
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (token.subgroup === MERGE_FIELD_OFF) {
|
|
436
|
+
const startRun = state.openMergeFieldStartRun;
|
|
437
|
+
state.openMergeFieldStartRun = void 0;
|
|
438
|
+
if (startRun === void 0) return;
|
|
439
|
+
flushRun(state);
|
|
440
|
+
const endRun = state.runs.length;
|
|
441
|
+
const instruction = state.runs.slice(startRun, endRun).map((run) => run.text).join("");
|
|
442
|
+
state.pendingConstructs.push({
|
|
443
|
+
descriptor: {
|
|
444
|
+
kind: "field",
|
|
445
|
+
instruction
|
|
446
|
+
},
|
|
447
|
+
startRun,
|
|
448
|
+
endRun
|
|
449
|
+
});
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
reportOnce(state, sink, WpdDiagnosticCodes.MergeCodeDropped, "This document contains merge codes, which are a form-letter template's placeholders rather than text.");
|
|
453
|
+
}
|
|
454
|
+
function plainTextOf(blocks) {
|
|
455
|
+
return blocks.filter((block) => block.kind === "paragraph").map((paragraph) => paragraph.runs.map((run) => run.text).join("")).join("\n");
|
|
456
|
+
}
|
|
457
|
+
function applyBoxGroup(state, token, container, sink) {
|
|
458
|
+
const boxContent = readBoxContent(token.nonDeletable, token.prefixIds);
|
|
459
|
+
if (boxContent === void 0) {
|
|
460
|
+
reportOnce(state, sink, WpdDiagnosticCodes.BoxDropped, "This document contains a box -- a figure, text box, equation, or graphic -- whose function-level override names no content this reader can resolve.");
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const packet = boxContent.contentType === 1 || boxContent.contentType === 2 || boxContent.contentType === 4 ? packetByPrefixId(container.packets, boxContent.contentPrefixId) : void 0;
|
|
464
|
+
const textBlocks = packet?.packetType !== 8 ? void 0 : readGeneralWpTextBlocks(packet.bytes);
|
|
465
|
+
if (textBlocks === void 0) {
|
|
466
|
+
reportOnce(state, sink, WpdDiagnosticCodes.BoxContentUnresolved, "This document contains a box whose content this reader could not read -- an image, OLE object, or other content type this reader does not yet decode into the shared schema.");
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
if (boxContent.frame === void 0) {
|
|
470
|
+
reportOnce(state, sink, WpdDiagnosticCodes.BoxFrameUnresolved, "This document contains a box whose content this reader could read, but whose function-level override states no width and height this reader can trust, so its content was not lifted.");
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
flushParagraphIfContent(state, sink);
|
|
474
|
+
const nestedTokens = tokeniseDocumentArea(textBlocks, 0, textBlocks.length);
|
|
475
|
+
const frame = {
|
|
476
|
+
xPt: boxContent.frame.xPt,
|
|
477
|
+
yPt: boxContent.frame.yPt,
|
|
478
|
+
widthPt: boxContent.frame.widthPt,
|
|
479
|
+
heightPt: boxContent.frame.heightPt
|
|
480
|
+
};
|
|
481
|
+
if (boxContent.contentType === 4) {
|
|
482
|
+
const { blocks } = foldTokens(nestedTokens, container, sink);
|
|
483
|
+
const embed = {
|
|
484
|
+
kind: "embeddedObject",
|
|
485
|
+
objectKind: "formula",
|
|
486
|
+
frame,
|
|
487
|
+
document: {
|
|
488
|
+
kind: "formula",
|
|
489
|
+
metadata: {},
|
|
490
|
+
formula: {
|
|
491
|
+
mathml: [],
|
|
492
|
+
source: {
|
|
493
|
+
format: "wpd",
|
|
494
|
+
xml: plainTextOf(blocks)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
targetBlocks(state).push(embed);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const { blocks, page } = foldTokens(nestedTokens, container, sink);
|
|
503
|
+
const embed = {
|
|
504
|
+
kind: "embeddedObject",
|
|
505
|
+
objectKind: "wordprocessing",
|
|
506
|
+
frame,
|
|
507
|
+
document: {
|
|
508
|
+
kind: "wordprocessing",
|
|
509
|
+
metadata: {},
|
|
510
|
+
sections: [{
|
|
511
|
+
pageSize: {
|
|
512
|
+
widthPt: page.widthPt ?? 612,
|
|
513
|
+
heightPt: page.heightPt ?? 792
|
|
514
|
+
},
|
|
515
|
+
margins: {
|
|
516
|
+
topPt: page.topPt ?? 72,
|
|
517
|
+
rightPt: page.rightPt ?? 72,
|
|
518
|
+
bottomPt: page.bottomPt ?? 72,
|
|
519
|
+
leftPt: page.leftPt ?? 72
|
|
520
|
+
},
|
|
521
|
+
blocks
|
|
522
|
+
}]
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
targetBlocks(state).push(embed);
|
|
526
|
+
}
|
|
370
527
|
function applyVariableFunction(state, token, container, sink) {
|
|
371
528
|
switch (token.group) {
|
|
372
529
|
case 208: {
|
|
@@ -397,7 +554,7 @@ function applyVariableFunction(state, token, container, sink) {
|
|
|
397
554
|
return;
|
|
398
555
|
}
|
|
399
556
|
case 221:
|
|
400
|
-
applyStyleGroup(state, token);
|
|
557
|
+
applyStyleGroup(state, token, container, sink);
|
|
401
558
|
return;
|
|
402
559
|
case 218:
|
|
403
560
|
applyDisplayNumberGroup(state, token, sink);
|
|
@@ -412,10 +569,10 @@ function applyVariableFunction(state, token, container, sink) {
|
|
|
412
569
|
reportOnce(state, sink, WpdDiagnosticCodes.NoteDropped, "This document contains a footnote or endnote; its text lives in a prefix packet the flat content model has nowhere to put.");
|
|
413
570
|
return;
|
|
414
571
|
case MERGE_GROUP:
|
|
415
|
-
|
|
572
|
+
applyMergeGroup(state, token, sink);
|
|
416
573
|
return;
|
|
417
574
|
case BOX_GROUP:
|
|
418
|
-
|
|
575
|
+
applyBoxGroup(state, token, container, sink);
|
|
419
576
|
return;
|
|
420
577
|
default: return;
|
|
421
578
|
}
|
|
@@ -449,6 +606,32 @@ function applyFixedFunction(state, token, sink) {
|
|
|
449
606
|
flushRun(state);
|
|
450
607
|
state.attributes = next;
|
|
451
608
|
}
|
|
609
|
+
function applyToken(state, token, container, sink) {
|
|
610
|
+
switch (token.kind) {
|
|
611
|
+
case "character": {
|
|
612
|
+
const character = decodeSingleByteCharacter(token.byte);
|
|
613
|
+
if (character === void 0) {
|
|
614
|
+
sink({
|
|
615
|
+
code: WpdDiagnosticCodes.UnmappedCharacter,
|
|
616
|
+
message: `Byte ${token.byte} in the document area has no character mapping and was rendered as U+FFFD.`
|
|
617
|
+
});
|
|
618
|
+
appendText(state, "�");
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
appendText(state, character);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
case "singleByteFunction":
|
|
625
|
+
applySingleByteFunction(state, token.code, sink);
|
|
626
|
+
return;
|
|
627
|
+
case "variableFunction":
|
|
628
|
+
applyVariableFunction(state, token, container, sink);
|
|
629
|
+
return;
|
|
630
|
+
case "fixedFunction":
|
|
631
|
+
applyFixedFunction(state, token, sink);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
452
635
|
function foldTokens(tokens, container, sink) {
|
|
453
636
|
const state = {
|
|
454
637
|
blocks: [],
|
|
@@ -462,6 +645,7 @@ function foldTokens(tokens, container, sink) {
|
|
|
462
645
|
alignment: void 0,
|
|
463
646
|
skipDepth: 0,
|
|
464
647
|
styleScopes: [],
|
|
648
|
+
styleResolutionDepth: 0,
|
|
465
649
|
pendingHeadingLevel: void 0,
|
|
466
650
|
pendingListLevel: void 0,
|
|
467
651
|
pendingAlignment: void 0,
|
|
@@ -476,32 +660,13 @@ function foldTokens(tokens, container, sink) {
|
|
|
476
660
|
changeReported: false
|
|
477
661
|
},
|
|
478
662
|
table: void 0,
|
|
479
|
-
reported: /* @__PURE__ */ new Set()
|
|
663
|
+
reported: /* @__PURE__ */ new Set(),
|
|
664
|
+
pendingConstructs: [],
|
|
665
|
+
openMergeFieldStartRun: void 0
|
|
480
666
|
};
|
|
481
|
-
for (const token of tokens)
|
|
482
|
-
case "character": {
|
|
483
|
-
const character = decodeSingleByteCharacter(token.byte);
|
|
484
|
-
if (character === void 0) {
|
|
485
|
-
sink({
|
|
486
|
-
code: WpdDiagnosticCodes.UnmappedCharacter,
|
|
487
|
-
message: `Byte ${token.byte} in the document area has no character mapping and was rendered as U+FFFD.`
|
|
488
|
-
});
|
|
489
|
-
appendText(state, "�");
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
appendText(state, character);
|
|
493
|
-
break;
|
|
494
|
-
}
|
|
495
|
-
case "singleByteFunction":
|
|
496
|
-
applySingleByteFunction(state, token.code, sink);
|
|
497
|
-
break;
|
|
498
|
-
case "variableFunction":
|
|
499
|
-
applyVariableFunction(state, token, container, sink);
|
|
500
|
-
break;
|
|
501
|
-
case "fixedFunction": applyFixedFunction(state, token, sink);
|
|
502
|
-
}
|
|
667
|
+
for (const token of tokens) applyToken(state, token, container, sink);
|
|
503
668
|
flushRun(state);
|
|
504
|
-
if (state.runs.length > 0) flushParagraph(state);
|
|
669
|
+
if (state.runs.length > 0) flushParagraph(state, sink);
|
|
505
670
|
if (state.table !== void 0) {
|
|
506
671
|
closeRow(state.table);
|
|
507
672
|
closeTable(state);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_bytes_view = require("../bytes/view.cjs");
|
|
3
|
+
const require_stream_units = require("./units.cjs");
|
|
4
|
+
//#region src/stream/box.ts
|
|
5
|
+
const OVERRIDE_BIT_POSITION = 14;
|
|
6
|
+
const OVERRIDE_BIT_CONTENT = 13;
|
|
7
|
+
const OVERRIDE_BIT_HTML = 7;
|
|
8
|
+
const OVERRIDE_FLAGS_OFFSET = 18;
|
|
9
|
+
const FIRST_OVERRIDE_BLOCK_OFFSET = 20;
|
|
10
|
+
function walkOverrideBlocks(nonDeletable) {
|
|
11
|
+
if (nonDeletable.length < FIRST_OVERRIDE_BLOCK_OFFSET) return;
|
|
12
|
+
const flags = require_bytes_view.uint16At(nonDeletable, OVERRIDE_FLAGS_OFFSET);
|
|
13
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
14
|
+
let cursor = FIRST_OVERRIDE_BLOCK_OFFSET;
|
|
15
|
+
for (let bit = 15; bit >= 5; bit -= 1) {
|
|
16
|
+
if ((flags & 1 << bit) === 0) continue;
|
|
17
|
+
if (bit === OVERRIDE_BIT_HTML) continue;
|
|
18
|
+
if (cursor + 2 > nonDeletable.length) return;
|
|
19
|
+
const size = require_bytes_view.uint16At(nonDeletable, cursor);
|
|
20
|
+
cursor += 2;
|
|
21
|
+
if (cursor + size > nonDeletable.length) return;
|
|
22
|
+
blocks.set(bit, nonDeletable.subarray(cursor, cursor + size));
|
|
23
|
+
cursor += size;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
flags,
|
|
27
|
+
blocks
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function readContentType(contentBlock) {
|
|
31
|
+
if (contentBlock.length < 2) return;
|
|
32
|
+
const flags = require_bytes_view.uint16At(contentBlock, 0);
|
|
33
|
+
let cursor = 2;
|
|
34
|
+
if ((flags & 32768) !== 0) {
|
|
35
|
+
if (cursor + 2 > contentBlock.length) return;
|
|
36
|
+
cursor += 2;
|
|
37
|
+
}
|
|
38
|
+
if ((flags & 16384) === 0) return;
|
|
39
|
+
return contentBlock[cursor];
|
|
40
|
+
}
|
|
41
|
+
function readPositionOverride(positionBlock) {
|
|
42
|
+
if (positionBlock.length < 2) return;
|
|
43
|
+
const flags = require_bytes_view.uint16At(positionBlock, 0);
|
|
44
|
+
let cursor = 2;
|
|
45
|
+
let widthWpu;
|
|
46
|
+
let heightWpu;
|
|
47
|
+
let xWpu;
|
|
48
|
+
let yWpu;
|
|
49
|
+
const need = (bytes) => cursor + bytes <= positionBlock.length;
|
|
50
|
+
if ((flags & 32768) !== 0) {
|
|
51
|
+
if (!need(2)) return void 0;
|
|
52
|
+
cursor += 2;
|
|
53
|
+
}
|
|
54
|
+
if ((flags & 16384) !== 0) {
|
|
55
|
+
if (!need(2)) return void 0;
|
|
56
|
+
cursor += 2;
|
|
57
|
+
}
|
|
58
|
+
if ((flags & 8192) !== 0) {
|
|
59
|
+
if (!need(5)) return void 0;
|
|
60
|
+
const horizontalFlags = positionBlock[cursor];
|
|
61
|
+
const offset = require_bytes_view.uint16At(positionBlock, cursor + 1);
|
|
62
|
+
if (horizontalFlags !== void 0 && (horizontalFlags & 3) === 0) xWpu = offset;
|
|
63
|
+
cursor += 5;
|
|
64
|
+
}
|
|
65
|
+
if ((flags & 4096) !== 0) {
|
|
66
|
+
if (!need(3)) return void 0;
|
|
67
|
+
const verticalFlags = positionBlock[cursor];
|
|
68
|
+
const offset = require_bytes_view.uint16At(positionBlock, cursor + 1);
|
|
69
|
+
if (verticalFlags !== void 0 && (verticalFlags & 3) === 0) yWpu = offset;
|
|
70
|
+
cursor += 3;
|
|
71
|
+
}
|
|
72
|
+
if ((flags & 2048) !== 0) {
|
|
73
|
+
if (!need(3)) return void 0;
|
|
74
|
+
widthWpu = require_bytes_view.uint16At(positionBlock, cursor + 1);
|
|
75
|
+
cursor += 3;
|
|
76
|
+
}
|
|
77
|
+
if ((flags & 1024) !== 0) {
|
|
78
|
+
if (!need(3)) return void 0;
|
|
79
|
+
heightWpu = require_bytes_view.uint16At(positionBlock, cursor + 1);
|
|
80
|
+
cursor += 3;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
widthWpu,
|
|
84
|
+
heightWpu,
|
|
85
|
+
xWpu,
|
|
86
|
+
yWpu
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const BOX_CONTENT_TYPE_TEXT = 1;
|
|
90
|
+
const BOX_CONTENT_TYPE_LINKED_TEXT = 2;
|
|
91
|
+
const BOX_CONTENT_TYPE_IMAGE = 3;
|
|
92
|
+
const BOX_CONTENT_TYPE_EQUATION = 4;
|
|
93
|
+
function readBoxContent(nonDeletable, prefixIds) {
|
|
94
|
+
const walk = walkOverrideBlocks(nonDeletable);
|
|
95
|
+
if (walk === void 0) return;
|
|
96
|
+
const { flags, blocks } = walk;
|
|
97
|
+
const contentBlock = blocks.get(OVERRIDE_BIT_CONTENT);
|
|
98
|
+
if (contentBlock === void 0) return;
|
|
99
|
+
const contentType = readContentType(contentBlock);
|
|
100
|
+
if (contentType === void 0) return;
|
|
101
|
+
const contentPrefixId = prefixIds[1 + ((flags & 32768) !== 0 ? 1 : 0)];
|
|
102
|
+
if (contentPrefixId === void 0) return;
|
|
103
|
+
const positionBlock = blocks.get(OVERRIDE_BIT_POSITION);
|
|
104
|
+
const position = positionBlock === void 0 ? void 0 : readPositionOverride(positionBlock);
|
|
105
|
+
return {
|
|
106
|
+
contentType,
|
|
107
|
+
contentPrefixId,
|
|
108
|
+
frame: position?.widthWpu === void 0 || position.heightWpu === void 0 ? void 0 : {
|
|
109
|
+
xPt: require_stream_units.pointsFromWpu(position.xWpu ?? 0),
|
|
110
|
+
yPt: require_stream_units.pointsFromWpu(position.yWpu ?? 0),
|
|
111
|
+
widthPt: require_stream_units.pointsFromWpu(position.widthWpu),
|
|
112
|
+
heightPt: require_stream_units.pointsFromWpu(position.heightWpu),
|
|
113
|
+
positionResolved: position.xWpu !== void 0 && position.yWpu !== void 0
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
exports.BOX_CONTENT_TYPE_EQUATION = BOX_CONTENT_TYPE_EQUATION;
|
|
119
|
+
exports.BOX_CONTENT_TYPE_IMAGE = BOX_CONTENT_TYPE_IMAGE;
|
|
120
|
+
exports.BOX_CONTENT_TYPE_LINKED_TEXT = BOX_CONTENT_TYPE_LINKED_TEXT;
|
|
121
|
+
exports.BOX_CONTENT_TYPE_TEXT = BOX_CONTENT_TYPE_TEXT;
|
|
122
|
+
exports.readBoxContent = readBoxContent;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/stream/box.d.ts
|
|
2
|
+
interface WpdBoxFrame {
|
|
3
|
+
readonly xPt: number;
|
|
4
|
+
readonly yPt: number;
|
|
5
|
+
readonly widthPt: number;
|
|
6
|
+
readonly heightPt: number;
|
|
7
|
+
readonly positionResolved: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface WpdBoxContent {
|
|
10
|
+
readonly contentType: number;
|
|
11
|
+
readonly contentPrefixId: number;
|
|
12
|
+
readonly frame: WpdBoxFrame | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const BOX_CONTENT_TYPE_TEXT = 1;
|
|
15
|
+
declare const BOX_CONTENT_TYPE_LINKED_TEXT = 2;
|
|
16
|
+
declare const BOX_CONTENT_TYPE_IMAGE = 3;
|
|
17
|
+
declare const BOX_CONTENT_TYPE_EQUATION = 4;
|
|
18
|
+
declare function readBoxContent(nonDeletable: Uint8Array, prefixIds: readonly number[]): WpdBoxContent | undefined;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { BOX_CONTENT_TYPE_EQUATION, BOX_CONTENT_TYPE_IMAGE, BOX_CONTENT_TYPE_LINKED_TEXT, BOX_CONTENT_TYPE_TEXT, WpdBoxContent, WpdBoxFrame, readBoxContent };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/stream/box.d.ts
|
|
2
|
+
interface WpdBoxFrame {
|
|
3
|
+
readonly xPt: number;
|
|
4
|
+
readonly yPt: number;
|
|
5
|
+
readonly widthPt: number;
|
|
6
|
+
readonly heightPt: number;
|
|
7
|
+
readonly positionResolved: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface WpdBoxContent {
|
|
10
|
+
readonly contentType: number;
|
|
11
|
+
readonly contentPrefixId: number;
|
|
12
|
+
readonly frame: WpdBoxFrame | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const BOX_CONTENT_TYPE_TEXT = 1;
|
|
15
|
+
declare const BOX_CONTENT_TYPE_LINKED_TEXT = 2;
|
|
16
|
+
declare const BOX_CONTENT_TYPE_IMAGE = 3;
|
|
17
|
+
declare const BOX_CONTENT_TYPE_EQUATION = 4;
|
|
18
|
+
declare function readBoxContent(nonDeletable: Uint8Array, prefixIds: readonly number[]): WpdBoxContent | undefined;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { BOX_CONTENT_TYPE_EQUATION, BOX_CONTENT_TYPE_IMAGE, BOX_CONTENT_TYPE_LINKED_TEXT, BOX_CONTENT_TYPE_TEXT, WpdBoxContent, WpdBoxFrame, readBoxContent };
|