doc-codec 1.0.2 → 1.1.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 +192 -50
- package/dist/color.cjs +166 -0
- package/dist/color.d.cts +20 -0
- package/dist/color.d.ts +20 -0
- package/dist/color.js +160 -0
- package/dist/detect.cjs +3 -0
- package/dist/detect.d.cts +3 -1
- package/dist/detect.d.ts +3 -1
- package/dist/detect.js +3 -1
- package/dist/fib/fib.cjs +9 -1
- package/dist/fib/fib.d.cts +1 -28
- package/dist/fib/fib.d.ts +1 -28
- package/dist/fib/fib.js +9 -1
- package/dist/fib/offsets.cjs +9 -1
- package/dist/fib/offsets.d.cts +8 -0
- package/dist/fib/offsets.d.ts +8 -0
- package/dist/fib/offsets.js +9 -1
- package/dist/fib/write.cjs +43 -0
- package/dist/fib/write.d.cts +21 -0
- package/dist/fib/write.d.ts +21 -0
- package/dist/fib/write.js +42 -0
- package/dist/fib-CtsLtF96.d.cts +37 -0
- package/dist/fib-CtsLtF96.d.ts +37 -0
- package/dist/index.cjs +31 -0
- package/dist/index.d.cts +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +14 -3
- package/dist/list/numbering.cjs +206 -0
- package/dist/list/numbering.d.cts +2 -0
- package/dist/list/numbering.d.ts +2 -0
- package/dist/list/numbering.js +205 -0
- package/dist/metadata.cjs +14 -0
- package/dist/metadata.d.cts +6 -0
- package/dist/metadata.d.ts +6 -0
- package/dist/metadata.js +13 -0
- package/dist/numbering-Cir-uGdc.d.cts +22 -0
- package/dist/numbering-DF1z1PyG.d.ts +22 -0
- package/dist/pap-BkFo8dZO.d.ts +29 -0
- package/dist/pap-BmelEYEP.d.cts +29 -0
- package/dist/prop/chp-write.cjs +47 -0
- package/dist/prop/chp-write.d.cts +5 -0
- package/dist/prop/chp-write.d.ts +5 -0
- package/dist/prop/chp-write.js +46 -0
- package/dist/prop/chp.cjs +15 -107
- package/dist/prop/chp.d.cts +3 -2
- package/dist/prop/chp.d.ts +3 -2
- package/dist/prop/chp.js +15 -107
- package/dist/prop/fkp-write.cjs +139 -0
- package/dist/prop/fkp-write.d.cts +21 -0
- package/dist/prop/fkp-write.d.ts +21 -0
- package/dist/prop/fkp-write.js +135 -0
- package/dist/prop/pap-write.cjs +67 -0
- package/dist/prop/pap-write.d.cts +5 -0
- package/dist/prop/pap-write.d.ts +5 -0
- package/dist/prop/pap-write.js +66 -0
- package/dist/prop/pap.cjs +10 -0
- package/dist/prop/pap.d.cts +1 -24
- package/dist/prop/pap.d.ts +1 -24
- package/dist/prop/pap.js +11 -1
- package/dist/prop/sep-write.cjs +63 -0
- package/dist/prop/sep-write.d.cts +9 -0
- package/dist/prop/sep-write.d.ts +9 -0
- package/dist/prop/sep-write.js +60 -0
- package/dist/prop/sep.cjs +63 -0
- package/dist/prop/sep.d.cts +16 -0
- package/dist/prop/sep.d.ts +16 -0
- package/dist/prop/sep.js +61 -0
- package/dist/prop/sprm.d.cts +1 -25
- package/dist/prop/sprm.d.ts +1 -25
- package/dist/read.cjs +44 -18
- package/dist/read.d.cts +21 -4
- package/dist/read.d.ts +21 -4
- package/dist/read.js +46 -20
- package/dist/sprm-Djg5RNiq.d.cts +26 -0
- package/dist/sprm-Djg5RNiq.d.ts +26 -0
- package/dist/style/fonts.cjs +68 -0
- package/dist/style/fonts.d.cts +5 -0
- package/dist/style/fonts.d.ts +5 -0
- package/dist/style/fonts.js +66 -0
- package/dist/style/stsh.cjs +23 -0
- package/dist/style/stsh.d.cts +2 -1
- package/dist/style/stsh.d.ts +2 -1
- package/dist/style/stsh.js +23 -1
- package/dist/table/decoration.cjs +220 -0
- package/dist/table/decoration.d.cts +41 -0
- package/dist/table/decoration.d.ts +41 -0
- package/dist/table/decoration.js +205 -0
- package/dist/table/read.cjs +192 -0
- package/dist/table/read.d.cts +6 -0
- package/dist/table/read.d.ts +6 -0
- package/dist/table/read.js +191 -0
- package/dist/table/tap-write.cjs +125 -0
- package/dist/table/tap-write.d.cts +13 -0
- package/dist/table/tap-write.d.ts +13 -0
- package/dist/table/tap-write.js +124 -0
- package/dist/table/tap.cjs +217 -0
- package/dist/table/tap.d.cts +29 -0
- package/dist/table/tap.d.ts +29 -0
- package/dist/table/tap.js +213 -0
- package/dist/table/write.cjs +136 -0
- package/dist/table/write.d.cts +13 -0
- package/dist/table/write.d.ts +13 -0
- package/dist/table/write.js +135 -0
- package/dist/text/piece-table-write.cjs +24 -0
- package/dist/text/piece-table-write.d.cts +4 -0
- package/dist/text/piece-table-write.d.ts +4 -0
- package/dist/text/piece-table-write.js +23 -0
- package/dist/write.cjs +175 -0
- package/dist/write.d.cts +5 -0
- package/dist/write.d.ts +5 -0
- package/dist/write.js +174 -0
- package/package.json +3 -3
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_bytes = require("../bytes.cjs");
|
|
3
|
+
const require_prop_sprm = require("../prop/sprm.cjs");
|
|
4
|
+
const require_table_decoration = require("./decoration.cjs");
|
|
5
|
+
//#region src/table/tap.ts
|
|
6
|
+
const SPRM_T_DEF_TABLE = 54792;
|
|
7
|
+
const SPRM_T_DYA_ROW_HEIGHT = 37895;
|
|
8
|
+
/** sprmTMerge: an ItcFirstLim naming a range of cells to horizontally merge, the first cell becoming the anchor -- a spec-conformant mechanism this reader still honours for a genuine third-party producer, even though this package's own writer no longer emits it (see this module's own top-of-file note and table/write.ts's). */
|
|
9
|
+
const SPRM_T_MERGE = 22052;
|
|
10
|
+
/** sprmTVertMerge (0xD62B): a VertMergeOperand naming one cell (itc) and its own VerticalMergeFlag, the incremental per-cell equivalent of sprmTMerge for a vertical merge. */
|
|
11
|
+
const SPRM_T_VERT_MERGE = 54827;
|
|
12
|
+
/** sprmTSetBrc (0xD62F): a TableBrcOperand ([MS-DOC] 2.9.305) restating one cell range's borders on the named sides, with an exact COLORREF rather than TC80's own Ico index. */
|
|
13
|
+
const SPRM_T_SET_BRC = 54831;
|
|
14
|
+
/** sprmTDefTableShd80 (0xD609): a DefTableShd80Operand ([MS-DOC] 2.9.52), the Word 97-era array of one Shd80 per cell starting at the row's first. */
|
|
15
|
+
const SPRM_T_DEF_TABLE_SHD80 = 54793;
|
|
16
|
+
/** sprmTDefTableShd3rd (0xD60C): a DefTableShdOperand ([MS-DOC] 2.9.53) shading cells 45-63 -- index 44 onward. */
|
|
17
|
+
const SPRM_T_DEF_TABLE_SHD_3RD = 54796;
|
|
18
|
+
/** sprmTDefTableShd (0xD612): a DefTableShdOperand shading cells 1-22 -- index 0 onward. */
|
|
19
|
+
const SPRM_T_DEF_TABLE_SHD = 54802;
|
|
20
|
+
/** sprmTDefTableShd2nd (0xD616): a DefTableShdOperand shading cells 23-44 -- index 22 onward. */
|
|
21
|
+
const SPRM_T_DEF_TABLE_SHD_2ND = 54806;
|
|
22
|
+
/** sprmTSetShd (0xD62D): a TableShadeOperand ([MS-DOC] 2.9.308) shading one ItcFirstLim cell range. */
|
|
23
|
+
const SPRM_T_SET_SHD = 54829;
|
|
24
|
+
/** sprmTSetShdOdd (0xD62E): the same TableShadeOperand, applied to every other cell of the range starting at itcFirst -- [MS-DOC] 2.6.3's own worked example, "if the set of cells is 0 through 5, then this sets the background shading for cells 0, 2 and 4". */
|
|
25
|
+
const SPRM_T_SET_SHD_ODD = 54830;
|
|
26
|
+
/** sprmTDefTableShdRaw/Raw2nd/Raw3rd (0xD670-0xD672): the same three DefTableShdOperand arrays, differing from the sprms above only in how ShdNil is treated inside a table style -- which this package neither reads nor writes, so all six resolve identically here. A real producer (LibreOffice) writes both families for the same row. */
|
|
27
|
+
const SPRM_T_DEF_TABLE_SHD_RAW = 54896;
|
|
28
|
+
const SPRM_T_DEF_TABLE_SHD_RAW_2ND = 54897;
|
|
29
|
+
const SPRM_T_DEF_TABLE_SHD_RAW_3RD = 54898;
|
|
30
|
+
/** The first cell index each of the three DefTableShdOperand sprms shades, [MS-DOC] 2.6.3: "Cells 1 - 22 are shaded by sprmTDefTableShd, and cells 23 - 44 are shaded by sprmTDefTableShd2nd" and 45-63 by the third -- one-based there, so zero-based here. */
|
|
31
|
+
const SHD_ARRAY_FIRST_CELL = {
|
|
32
|
+
[SPRM_T_DEF_TABLE_SHD]: 0,
|
|
33
|
+
[SPRM_T_DEF_TABLE_SHD_RAW]: 0,
|
|
34
|
+
[SPRM_T_DEF_TABLE_SHD_2ND]: 22,
|
|
35
|
+
[SPRM_T_DEF_TABLE_SHD_RAW_2ND]: 22,
|
|
36
|
+
[SPRM_T_DEF_TABLE_SHD_3RD]: 44,
|
|
37
|
+
[SPRM_T_DEF_TABLE_SHD_RAW_3RD]: 44
|
|
38
|
+
};
|
|
39
|
+
const TWIPS_PER_POINT = 20;
|
|
40
|
+
/** TC80's own fixed size, [MS-DOC] 2.9.313: tcgrf (2) + wWidth (2) + brcTop/brcLeft/brcBottom/brcRight (4 each). */
|
|
41
|
+
const TC80_SIZE = 20;
|
|
42
|
+
/** The offset of TC80's own first border field, brcTop, past tcgrf and wWidth. The four follow it back to back in CELL_BORDER_SIDES order. */
|
|
43
|
+
const TC80_BORDERS_OFFSET = 4;
|
|
44
|
+
/** TCGRF.horzMerge, [MS-DOC] 2.9.317: 0 not merged, 1 a continuation cell (contributes its layout region, its own contents are not rendered), 2 or 3 the first cell of a horizontally merged set. */
|
|
45
|
+
const HORZ_MERGE_CONTINUATION = 1;
|
|
46
|
+
/** VerticalMergeFlag's fvmMerge: TCGRF.vertMerge continuation (fvmClear=0, fvmMerge=1, fvmRestart=3 -- 2 is not a defined member). */
|
|
47
|
+
const VERT_MERGE_CONTINUATION = 1;
|
|
48
|
+
const VERT_MERGE_RESTART = 3;
|
|
49
|
+
function readTdefTableOperand(operand) {
|
|
50
|
+
const numberOfColumns = require_bytes.readUint8(operand, 2);
|
|
51
|
+
const boundariesStart = 3;
|
|
52
|
+
const columnBoundariesTwips = [];
|
|
53
|
+
for (let index = 0; index <= numberOfColumns; index += 1) columnBoundariesTwips.push(require_bytes.readInt16LE(operand, boundariesStart + index * 2));
|
|
54
|
+
const tc80Start = boundariesStart + (numberOfColumns + 1) * 2;
|
|
55
|
+
const cells = [];
|
|
56
|
+
for (let index = 0; index < numberOfColumns; index += 1) {
|
|
57
|
+
const tc80Offset = tc80Start + index * TC80_SIZE;
|
|
58
|
+
if (tc80Offset + TC80_SIZE > operand.length) {
|
|
59
|
+
cells.push({
|
|
60
|
+
horzMerge: 0,
|
|
61
|
+
vertMerge: 0
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const tcgrf = require_bytes.readUint16LE(operand, tc80Offset);
|
|
66
|
+
const sides = {
|
|
67
|
+
top: void 0,
|
|
68
|
+
left: void 0,
|
|
69
|
+
bottom: void 0,
|
|
70
|
+
right: void 0
|
|
71
|
+
};
|
|
72
|
+
require_table_decoration.CELL_BORDER_SIDES.forEach((side, sideIndex) => {
|
|
73
|
+
sides[side] = require_table_decoration.readBrc80(operand, tc80Offset + TC80_BORDERS_OFFSET + sideIndex * 4);
|
|
74
|
+
});
|
|
75
|
+
cells.push({
|
|
76
|
+
horzMerge: tcgrf & 3,
|
|
77
|
+
vertMerge: tcgrf >> 5 & 3,
|
|
78
|
+
borders: require_table_decoration.cellBordersFrom(sides)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
columnBoundariesTwips,
|
|
83
|
+
cells
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Replaces one cell's own entry in a definition, keeping every other cell and the row's boundaries untouched -- the shape every incremental sprm below folds through, so none of them has to restate how a definition is rebuilt. */
|
|
87
|
+
function withCells(definition, next) {
|
|
88
|
+
return {
|
|
89
|
+
columnBoundariesTwips: definition.columnBoundariesTwips,
|
|
90
|
+
cells: definition.cells.map(next)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Overlays the sides one TableBrcOperand names onto a cell's existing borders, leaving every side it does not name as TC80's own Brc80 stated it. A named side whose Brc is a NilBrc removes that side's border, which is how a producer states "this cell has no top border" over a row-level one it would otherwise inherit. */
|
|
94
|
+
function applyBrcToCell(cell, bordersToApply, border) {
|
|
95
|
+
const sides = {
|
|
96
|
+
top: cell.borders?.top,
|
|
97
|
+
left: cell.borders?.left,
|
|
98
|
+
bottom: cell.borders?.bottom,
|
|
99
|
+
right: cell.borders?.right
|
|
100
|
+
};
|
|
101
|
+
for (const side of require_table_decoration.CELL_BORDER_SIDES) if ((bordersToApply & require_table_decoration.BORDERS_TO_APPLY[side]) !== 0) sides[side] = border;
|
|
102
|
+
return {
|
|
103
|
+
horzMerge: cell.horzMerge,
|
|
104
|
+
vertMerge: cell.vertMerge,
|
|
105
|
+
borders: require_table_decoration.cellBordersFrom(sides),
|
|
106
|
+
background: cell.background
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function withBackground(cell, background) {
|
|
110
|
+
return {
|
|
111
|
+
horzMerge: cell.horzMerge,
|
|
112
|
+
vertMerge: cell.vertMerge,
|
|
113
|
+
borders: cell.borders,
|
|
114
|
+
background
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Applies a DefTableShdOperand's ([MS-DOC] 2.9.53) rgShd array from `firstCell` onward. The array carries "only ... elements necessary to define all shaded cells in the row", so cells past its end keep whatever an earlier sprm left them -- an entry that is present and states ShdAuto/ShdNil genuinely clears its own cell, which is how a real producer's full-length array turns a row's unshaded cells back off. */
|
|
118
|
+
function applyShdArray(definition, operand, firstCell, entrySize, colorAt) {
|
|
119
|
+
const cb = require_bytes.readUint8(operand, 0);
|
|
120
|
+
const count = Math.floor(cb / entrySize);
|
|
121
|
+
return withCells(definition, (cell, index) => {
|
|
122
|
+
const entry = index - firstCell;
|
|
123
|
+
if (entry < 0 || entry >= count) return cell;
|
|
124
|
+
return withBackground(cell, colorAt(operand, 1 + entry * entrySize));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** Applies a TableShadeOperand ([MS-DOC] 2.9.308): cb, an ItcFirstLim naming the range, then a single Shd applied to every cell the range covers -- not one Shd per cell. `step` is 1 for sprmTSetShd and 2 for sprmTSetShdOdd, whose own range covers every other cell from itcFirst. */
|
|
128
|
+
function applyTableShade(definition, operand, step) {
|
|
129
|
+
const itcFirst = require_bytes.readUint8(operand, 1);
|
|
130
|
+
const itcLim = require_bytes.readUint8(operand, 2);
|
|
131
|
+
const background = require_table_decoration.readShd(operand, 3);
|
|
132
|
+
return withCells(definition, (cell, index) => {
|
|
133
|
+
if (index < itcFirst || index >= itcLim) return cell;
|
|
134
|
+
if ((index - itcFirst) % step !== 0) return cell;
|
|
135
|
+
return withBackground(cell, background);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function applyTableSprms(prls, into) {
|
|
139
|
+
for (const prl of prls) if (prl.sprm.sgc === require_prop_sprm.SGC.table && prl.sprm.value === SPRM_T_DEF_TABLE) into.definition = readTdefTableOperand(prl.operand);
|
|
140
|
+
for (const prl of prls) {
|
|
141
|
+
if (prl.sprm.sgc !== require_prop_sprm.SGC.table) continue;
|
|
142
|
+
switch (prl.sprm.value) {
|
|
143
|
+
case SPRM_T_DEF_TABLE: break;
|
|
144
|
+
case SPRM_T_DYA_ROW_HEIGHT: {
|
|
145
|
+
const dyaRowHeight = require_bytes.readInt16LE(prl.operand, 0);
|
|
146
|
+
const heightPt = Math.abs(dyaRowHeight) / TWIPS_PER_POINT;
|
|
147
|
+
into.heightPt = heightPt > 0 ? heightPt : void 0;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case SPRM_T_MERGE: {
|
|
151
|
+
if (into.definition === void 0) break;
|
|
152
|
+
const itcFirst = require_bytes.readUint8(prl.operand, 0);
|
|
153
|
+
const itcLim = require_bytes.readUint8(prl.operand, 1);
|
|
154
|
+
into.definition = withCells(into.definition, (cell, index) => {
|
|
155
|
+
if (index < itcFirst || index >= itcLim) return cell;
|
|
156
|
+
return {
|
|
157
|
+
horzMerge: index === itcFirst ? 2 : 1,
|
|
158
|
+
vertMerge: cell.vertMerge,
|
|
159
|
+
borders: cell.borders,
|
|
160
|
+
background: cell.background
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case SPRM_T_VERT_MERGE: {
|
|
166
|
+
if (into.definition === void 0) break;
|
|
167
|
+
const itc = require_bytes.readUint8(prl.operand, 1);
|
|
168
|
+
const vertMergeFlags = require_bytes.readUint8(prl.operand, 2);
|
|
169
|
+
into.definition = withCells(into.definition, (cell, index) => index === itc ? {
|
|
170
|
+
horzMerge: cell.horzMerge,
|
|
171
|
+
vertMerge: vertMergeFlags,
|
|
172
|
+
borders: cell.borders,
|
|
173
|
+
background: cell.background
|
|
174
|
+
} : cell);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case SPRM_T_SET_BRC: {
|
|
178
|
+
if (into.definition === void 0) break;
|
|
179
|
+
const itcFirst = require_bytes.readUint8(prl.operand, 1);
|
|
180
|
+
const itcLim = require_bytes.readUint8(prl.operand, 2);
|
|
181
|
+
const bordersToApply = require_bytes.readUint8(prl.operand, 3);
|
|
182
|
+
const border = require_table_decoration.readBrc(prl.operand, 4);
|
|
183
|
+
into.definition = withCells(into.definition, (cell, index) => index < itcFirst || index >= itcLim ? cell : applyBrcToCell(cell, bordersToApply, border));
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case SPRM_T_DEF_TABLE_SHD:
|
|
187
|
+
case SPRM_T_DEF_TABLE_SHD_2ND:
|
|
188
|
+
case SPRM_T_DEF_TABLE_SHD_3RD:
|
|
189
|
+
case SPRM_T_DEF_TABLE_SHD_RAW:
|
|
190
|
+
case SPRM_T_DEF_TABLE_SHD_RAW_2ND:
|
|
191
|
+
case SPRM_T_DEF_TABLE_SHD_RAW_3RD: {
|
|
192
|
+
if (into.definition === void 0) break;
|
|
193
|
+
const firstCell = SHD_ARRAY_FIRST_CELL[prl.sprm.value];
|
|
194
|
+
if (firstCell === void 0) break;
|
|
195
|
+
into.definition = applyShdArray(into.definition, prl.operand, firstCell, 10, require_table_decoration.readShd);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case SPRM_T_DEF_TABLE_SHD80:
|
|
199
|
+
if (into.definition === void 0) break;
|
|
200
|
+
into.definition = applyShdArray(into.definition, prl.operand, 0, 2, (operand, offset) => require_table_decoration.readShd80(require_bytes.readUint16LE(operand, offset)));
|
|
201
|
+
break;
|
|
202
|
+
case SPRM_T_SET_SHD:
|
|
203
|
+
if (into.definition === void 0) break;
|
|
204
|
+
into.definition = applyTableShade(into.definition, prl.operand, 1);
|
|
205
|
+
break;
|
|
206
|
+
case SPRM_T_SET_SHD_ODD:
|
|
207
|
+
if (into.definition === void 0) break;
|
|
208
|
+
into.definition = applyTableShade(into.definition, prl.operand, 2);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return into;
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
exports.HORZ_MERGE_CONTINUATION = HORZ_MERGE_CONTINUATION;
|
|
215
|
+
exports.VERT_MERGE_CONTINUATION = VERT_MERGE_CONTINUATION;
|
|
216
|
+
exports.VERT_MERGE_RESTART = VERT_MERGE_RESTART;
|
|
217
|
+
exports.applyTableSprms = applyTableSprms;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { t as Prl } from "../sprm-Djg5RNiq.cjs";
|
|
2
|
+
import { Color, ContentCellBorders } from "document-schema.js";
|
|
3
|
+
//#region src/table/tap.d.ts
|
|
4
|
+
/** TCGRF.horzMerge, [MS-DOC] 2.9.317: 0 not merged, 1 a continuation cell (contributes its layout region, its own contents are not rendered), 2 or 3 the first cell of a horizontally merged set. */
|
|
5
|
+
declare const HORZ_MERGE_CONTINUATION = 1;
|
|
6
|
+
/** VerticalMergeFlag's fvmMerge: TCGRF.vertMerge continuation (fvmClear=0, fvmMerge=1, fvmRestart=3 -- 2 is not a defined member). */
|
|
7
|
+
declare const VERT_MERGE_CONTINUATION = 1;
|
|
8
|
+
declare const VERT_MERGE_RESTART = 3;
|
|
9
|
+
interface TableCellProperties {
|
|
10
|
+
readonly horzMerge: number;
|
|
11
|
+
readonly vertMerge: number;
|
|
12
|
+
/** The cell's own four borders, absent when it states none on any side. */
|
|
13
|
+
readonly borders?: ContentCellBorders;
|
|
14
|
+
/** The cell's own flat background colour, absent when it states no shading or states a pattern Color cannot express (see decoration.ts's readShd). */
|
|
15
|
+
readonly background?: Color;
|
|
16
|
+
}
|
|
17
|
+
interface TableRowDefinition {
|
|
18
|
+
/** rgdxaCenter, in twips: one more entry than there are physical cells in the row -- column i's width is boundaries[i + 1] - boundaries[i]. */
|
|
19
|
+
readonly columnBoundariesTwips: readonly number[];
|
|
20
|
+
/** One entry per physical cell in the row, in document order -- every physical cell the row's own cell marks delimit, horizontally- and vertically-merged-away cells included, exactly as [MS-DOC]'s own model keeps them all present. */
|
|
21
|
+
readonly cells: readonly TableCellProperties[];
|
|
22
|
+
}
|
|
23
|
+
interface TableRowProperties {
|
|
24
|
+
definition?: TableRowDefinition;
|
|
25
|
+
heightPt?: number;
|
|
26
|
+
}
|
|
27
|
+
declare function applyTableSprms(prls: readonly Prl[], into: TableRowProperties): TableRowProperties;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { HORZ_MERGE_CONTINUATION, TableCellProperties, TableRowDefinition, TableRowProperties, VERT_MERGE_CONTINUATION, VERT_MERGE_RESTART, applyTableSprms };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { t as Prl } from "../sprm-Djg5RNiq.js";
|
|
2
|
+
import { Color, ContentCellBorders } from "document-schema.js";
|
|
3
|
+
//#region src/table/tap.d.ts
|
|
4
|
+
/** TCGRF.horzMerge, [MS-DOC] 2.9.317: 0 not merged, 1 a continuation cell (contributes its layout region, its own contents are not rendered), 2 or 3 the first cell of a horizontally merged set. */
|
|
5
|
+
declare const HORZ_MERGE_CONTINUATION = 1;
|
|
6
|
+
/** VerticalMergeFlag's fvmMerge: TCGRF.vertMerge continuation (fvmClear=0, fvmMerge=1, fvmRestart=3 -- 2 is not a defined member). */
|
|
7
|
+
declare const VERT_MERGE_CONTINUATION = 1;
|
|
8
|
+
declare const VERT_MERGE_RESTART = 3;
|
|
9
|
+
interface TableCellProperties {
|
|
10
|
+
readonly horzMerge: number;
|
|
11
|
+
readonly vertMerge: number;
|
|
12
|
+
/** The cell's own four borders, absent when it states none on any side. */
|
|
13
|
+
readonly borders?: ContentCellBorders;
|
|
14
|
+
/** The cell's own flat background colour, absent when it states no shading or states a pattern Color cannot express (see decoration.ts's readShd). */
|
|
15
|
+
readonly background?: Color;
|
|
16
|
+
}
|
|
17
|
+
interface TableRowDefinition {
|
|
18
|
+
/** rgdxaCenter, in twips: one more entry than there are physical cells in the row -- column i's width is boundaries[i + 1] - boundaries[i]. */
|
|
19
|
+
readonly columnBoundariesTwips: readonly number[];
|
|
20
|
+
/** One entry per physical cell in the row, in document order -- every physical cell the row's own cell marks delimit, horizontally- and vertically-merged-away cells included, exactly as [MS-DOC]'s own model keeps them all present. */
|
|
21
|
+
readonly cells: readonly TableCellProperties[];
|
|
22
|
+
}
|
|
23
|
+
interface TableRowProperties {
|
|
24
|
+
definition?: TableRowDefinition;
|
|
25
|
+
heightPt?: number;
|
|
26
|
+
}
|
|
27
|
+
declare function applyTableSprms(prls: readonly Prl[], into: TableRowProperties): TableRowProperties;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { HORZ_MERGE_CONTINUATION, TableCellProperties, TableRowDefinition, TableRowProperties, VERT_MERGE_CONTINUATION, VERT_MERGE_RESTART, applyTableSprms };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { readInt16LE, readUint16LE, readUint8 } from "../bytes.js";
|
|
2
|
+
import { SGC } from "../prop/sprm.js";
|
|
3
|
+
import { BORDERS_TO_APPLY, CELL_BORDER_SIDES, cellBordersFrom, readBrc, readBrc80, readShd, readShd80 } from "./decoration.js";
|
|
4
|
+
//#region src/table/tap.ts
|
|
5
|
+
const SPRM_T_DEF_TABLE = 54792;
|
|
6
|
+
const SPRM_T_DYA_ROW_HEIGHT = 37895;
|
|
7
|
+
/** sprmTMerge: an ItcFirstLim naming a range of cells to horizontally merge, the first cell becoming the anchor -- a spec-conformant mechanism this reader still honours for a genuine third-party producer, even though this package's own writer no longer emits it (see this module's own top-of-file note and table/write.ts's). */
|
|
8
|
+
const SPRM_T_MERGE = 22052;
|
|
9
|
+
/** sprmTVertMerge (0xD62B): a VertMergeOperand naming one cell (itc) and its own VerticalMergeFlag, the incremental per-cell equivalent of sprmTMerge for a vertical merge. */
|
|
10
|
+
const SPRM_T_VERT_MERGE = 54827;
|
|
11
|
+
/** sprmTSetBrc (0xD62F): a TableBrcOperand ([MS-DOC] 2.9.305) restating one cell range's borders on the named sides, with an exact COLORREF rather than TC80's own Ico index. */
|
|
12
|
+
const SPRM_T_SET_BRC = 54831;
|
|
13
|
+
/** sprmTDefTableShd80 (0xD609): a DefTableShd80Operand ([MS-DOC] 2.9.52), the Word 97-era array of one Shd80 per cell starting at the row's first. */
|
|
14
|
+
const SPRM_T_DEF_TABLE_SHD80 = 54793;
|
|
15
|
+
/** sprmTDefTableShd3rd (0xD60C): a DefTableShdOperand ([MS-DOC] 2.9.53) shading cells 45-63 -- index 44 onward. */
|
|
16
|
+
const SPRM_T_DEF_TABLE_SHD_3RD = 54796;
|
|
17
|
+
/** sprmTDefTableShd (0xD612): a DefTableShdOperand shading cells 1-22 -- index 0 onward. */
|
|
18
|
+
const SPRM_T_DEF_TABLE_SHD = 54802;
|
|
19
|
+
/** sprmTDefTableShd2nd (0xD616): a DefTableShdOperand shading cells 23-44 -- index 22 onward. */
|
|
20
|
+
const SPRM_T_DEF_TABLE_SHD_2ND = 54806;
|
|
21
|
+
/** sprmTSetShd (0xD62D): a TableShadeOperand ([MS-DOC] 2.9.308) shading one ItcFirstLim cell range. */
|
|
22
|
+
const SPRM_T_SET_SHD = 54829;
|
|
23
|
+
/** sprmTSetShdOdd (0xD62E): the same TableShadeOperand, applied to every other cell of the range starting at itcFirst -- [MS-DOC] 2.6.3's own worked example, "if the set of cells is 0 through 5, then this sets the background shading for cells 0, 2 and 4". */
|
|
24
|
+
const SPRM_T_SET_SHD_ODD = 54830;
|
|
25
|
+
/** sprmTDefTableShdRaw/Raw2nd/Raw3rd (0xD670-0xD672): the same three DefTableShdOperand arrays, differing from the sprms above only in how ShdNil is treated inside a table style -- which this package neither reads nor writes, so all six resolve identically here. A real producer (LibreOffice) writes both families for the same row. */
|
|
26
|
+
const SPRM_T_DEF_TABLE_SHD_RAW = 54896;
|
|
27
|
+
const SPRM_T_DEF_TABLE_SHD_RAW_2ND = 54897;
|
|
28
|
+
const SPRM_T_DEF_TABLE_SHD_RAW_3RD = 54898;
|
|
29
|
+
/** The first cell index each of the three DefTableShdOperand sprms shades, [MS-DOC] 2.6.3: "Cells 1 - 22 are shaded by sprmTDefTableShd, and cells 23 - 44 are shaded by sprmTDefTableShd2nd" and 45-63 by the third -- one-based there, so zero-based here. */
|
|
30
|
+
const SHD_ARRAY_FIRST_CELL = {
|
|
31
|
+
[SPRM_T_DEF_TABLE_SHD]: 0,
|
|
32
|
+
[SPRM_T_DEF_TABLE_SHD_RAW]: 0,
|
|
33
|
+
[SPRM_T_DEF_TABLE_SHD_2ND]: 22,
|
|
34
|
+
[SPRM_T_DEF_TABLE_SHD_RAW_2ND]: 22,
|
|
35
|
+
[SPRM_T_DEF_TABLE_SHD_3RD]: 44,
|
|
36
|
+
[SPRM_T_DEF_TABLE_SHD_RAW_3RD]: 44
|
|
37
|
+
};
|
|
38
|
+
const TWIPS_PER_POINT = 20;
|
|
39
|
+
/** TC80's own fixed size, [MS-DOC] 2.9.313: tcgrf (2) + wWidth (2) + brcTop/brcLeft/brcBottom/brcRight (4 each). */
|
|
40
|
+
const TC80_SIZE = 20;
|
|
41
|
+
/** The offset of TC80's own first border field, brcTop, past tcgrf and wWidth. The four follow it back to back in CELL_BORDER_SIDES order. */
|
|
42
|
+
const TC80_BORDERS_OFFSET = 4;
|
|
43
|
+
/** TCGRF.horzMerge, [MS-DOC] 2.9.317: 0 not merged, 1 a continuation cell (contributes its layout region, its own contents are not rendered), 2 or 3 the first cell of a horizontally merged set. */
|
|
44
|
+
const HORZ_MERGE_CONTINUATION = 1;
|
|
45
|
+
/** VerticalMergeFlag's fvmMerge: TCGRF.vertMerge continuation (fvmClear=0, fvmMerge=1, fvmRestart=3 -- 2 is not a defined member). */
|
|
46
|
+
const VERT_MERGE_CONTINUATION = 1;
|
|
47
|
+
const VERT_MERGE_RESTART = 3;
|
|
48
|
+
function readTdefTableOperand(operand) {
|
|
49
|
+
const numberOfColumns = readUint8(operand, 2);
|
|
50
|
+
const boundariesStart = 3;
|
|
51
|
+
const columnBoundariesTwips = [];
|
|
52
|
+
for (let index = 0; index <= numberOfColumns; index += 1) columnBoundariesTwips.push(readInt16LE(operand, boundariesStart + index * 2));
|
|
53
|
+
const tc80Start = boundariesStart + (numberOfColumns + 1) * 2;
|
|
54
|
+
const cells = [];
|
|
55
|
+
for (let index = 0; index < numberOfColumns; index += 1) {
|
|
56
|
+
const tc80Offset = tc80Start + index * TC80_SIZE;
|
|
57
|
+
if (tc80Offset + TC80_SIZE > operand.length) {
|
|
58
|
+
cells.push({
|
|
59
|
+
horzMerge: 0,
|
|
60
|
+
vertMerge: 0
|
|
61
|
+
});
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const tcgrf = readUint16LE(operand, tc80Offset);
|
|
65
|
+
const sides = {
|
|
66
|
+
top: void 0,
|
|
67
|
+
left: void 0,
|
|
68
|
+
bottom: void 0,
|
|
69
|
+
right: void 0
|
|
70
|
+
};
|
|
71
|
+
CELL_BORDER_SIDES.forEach((side, sideIndex) => {
|
|
72
|
+
sides[side] = readBrc80(operand, tc80Offset + TC80_BORDERS_OFFSET + sideIndex * 4);
|
|
73
|
+
});
|
|
74
|
+
cells.push({
|
|
75
|
+
horzMerge: tcgrf & 3,
|
|
76
|
+
vertMerge: tcgrf >> 5 & 3,
|
|
77
|
+
borders: cellBordersFrom(sides)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
columnBoundariesTwips,
|
|
82
|
+
cells
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Replaces one cell's own entry in a definition, keeping every other cell and the row's boundaries untouched -- the shape every incremental sprm below folds through, so none of them has to restate how a definition is rebuilt. */
|
|
86
|
+
function withCells(definition, next) {
|
|
87
|
+
return {
|
|
88
|
+
columnBoundariesTwips: definition.columnBoundariesTwips,
|
|
89
|
+
cells: definition.cells.map(next)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Overlays the sides one TableBrcOperand names onto a cell's existing borders, leaving every side it does not name as TC80's own Brc80 stated it. A named side whose Brc is a NilBrc removes that side's border, which is how a producer states "this cell has no top border" over a row-level one it would otherwise inherit. */
|
|
93
|
+
function applyBrcToCell(cell, bordersToApply, border) {
|
|
94
|
+
const sides = {
|
|
95
|
+
top: cell.borders?.top,
|
|
96
|
+
left: cell.borders?.left,
|
|
97
|
+
bottom: cell.borders?.bottom,
|
|
98
|
+
right: cell.borders?.right
|
|
99
|
+
};
|
|
100
|
+
for (const side of CELL_BORDER_SIDES) if ((bordersToApply & BORDERS_TO_APPLY[side]) !== 0) sides[side] = border;
|
|
101
|
+
return {
|
|
102
|
+
horzMerge: cell.horzMerge,
|
|
103
|
+
vertMerge: cell.vertMerge,
|
|
104
|
+
borders: cellBordersFrom(sides),
|
|
105
|
+
background: cell.background
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function withBackground(cell, background) {
|
|
109
|
+
return {
|
|
110
|
+
horzMerge: cell.horzMerge,
|
|
111
|
+
vertMerge: cell.vertMerge,
|
|
112
|
+
borders: cell.borders,
|
|
113
|
+
background
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Applies a DefTableShdOperand's ([MS-DOC] 2.9.53) rgShd array from `firstCell` onward. The array carries "only ... elements necessary to define all shaded cells in the row", so cells past its end keep whatever an earlier sprm left them -- an entry that is present and states ShdAuto/ShdNil genuinely clears its own cell, which is how a real producer's full-length array turns a row's unshaded cells back off. */
|
|
117
|
+
function applyShdArray(definition, operand, firstCell, entrySize, colorAt) {
|
|
118
|
+
const cb = readUint8(operand, 0);
|
|
119
|
+
const count = Math.floor(cb / entrySize);
|
|
120
|
+
return withCells(definition, (cell, index) => {
|
|
121
|
+
const entry = index - firstCell;
|
|
122
|
+
if (entry < 0 || entry >= count) return cell;
|
|
123
|
+
return withBackground(cell, colorAt(operand, 1 + entry * entrySize));
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/** Applies a TableShadeOperand ([MS-DOC] 2.9.308): cb, an ItcFirstLim naming the range, then a single Shd applied to every cell the range covers -- not one Shd per cell. `step` is 1 for sprmTSetShd and 2 for sprmTSetShdOdd, whose own range covers every other cell from itcFirst. */
|
|
127
|
+
function applyTableShade(definition, operand, step) {
|
|
128
|
+
const itcFirst = readUint8(operand, 1);
|
|
129
|
+
const itcLim = readUint8(operand, 2);
|
|
130
|
+
const background = readShd(operand, 3);
|
|
131
|
+
return withCells(definition, (cell, index) => {
|
|
132
|
+
if (index < itcFirst || index >= itcLim) return cell;
|
|
133
|
+
if ((index - itcFirst) % step !== 0) return cell;
|
|
134
|
+
return withBackground(cell, background);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function applyTableSprms(prls, into) {
|
|
138
|
+
for (const prl of prls) if (prl.sprm.sgc === SGC.table && prl.sprm.value === SPRM_T_DEF_TABLE) into.definition = readTdefTableOperand(prl.operand);
|
|
139
|
+
for (const prl of prls) {
|
|
140
|
+
if (prl.sprm.sgc !== SGC.table) continue;
|
|
141
|
+
switch (prl.sprm.value) {
|
|
142
|
+
case SPRM_T_DEF_TABLE: break;
|
|
143
|
+
case SPRM_T_DYA_ROW_HEIGHT: {
|
|
144
|
+
const dyaRowHeight = readInt16LE(prl.operand, 0);
|
|
145
|
+
const heightPt = Math.abs(dyaRowHeight) / TWIPS_PER_POINT;
|
|
146
|
+
into.heightPt = heightPt > 0 ? heightPt : void 0;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case SPRM_T_MERGE: {
|
|
150
|
+
if (into.definition === void 0) break;
|
|
151
|
+
const itcFirst = readUint8(prl.operand, 0);
|
|
152
|
+
const itcLim = readUint8(prl.operand, 1);
|
|
153
|
+
into.definition = withCells(into.definition, (cell, index) => {
|
|
154
|
+
if (index < itcFirst || index >= itcLim) return cell;
|
|
155
|
+
return {
|
|
156
|
+
horzMerge: index === itcFirst ? 2 : 1,
|
|
157
|
+
vertMerge: cell.vertMerge,
|
|
158
|
+
borders: cell.borders,
|
|
159
|
+
background: cell.background
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case SPRM_T_VERT_MERGE: {
|
|
165
|
+
if (into.definition === void 0) break;
|
|
166
|
+
const itc = readUint8(prl.operand, 1);
|
|
167
|
+
const vertMergeFlags = readUint8(prl.operand, 2);
|
|
168
|
+
into.definition = withCells(into.definition, (cell, index) => index === itc ? {
|
|
169
|
+
horzMerge: cell.horzMerge,
|
|
170
|
+
vertMerge: vertMergeFlags,
|
|
171
|
+
borders: cell.borders,
|
|
172
|
+
background: cell.background
|
|
173
|
+
} : cell);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case SPRM_T_SET_BRC: {
|
|
177
|
+
if (into.definition === void 0) break;
|
|
178
|
+
const itcFirst = readUint8(prl.operand, 1);
|
|
179
|
+
const itcLim = readUint8(prl.operand, 2);
|
|
180
|
+
const bordersToApply = readUint8(prl.operand, 3);
|
|
181
|
+
const border = readBrc(prl.operand, 4);
|
|
182
|
+
into.definition = withCells(into.definition, (cell, index) => index < itcFirst || index >= itcLim ? cell : applyBrcToCell(cell, bordersToApply, border));
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case SPRM_T_DEF_TABLE_SHD:
|
|
186
|
+
case SPRM_T_DEF_TABLE_SHD_2ND:
|
|
187
|
+
case SPRM_T_DEF_TABLE_SHD_3RD:
|
|
188
|
+
case SPRM_T_DEF_TABLE_SHD_RAW:
|
|
189
|
+
case SPRM_T_DEF_TABLE_SHD_RAW_2ND:
|
|
190
|
+
case SPRM_T_DEF_TABLE_SHD_RAW_3RD: {
|
|
191
|
+
if (into.definition === void 0) break;
|
|
192
|
+
const firstCell = SHD_ARRAY_FIRST_CELL[prl.sprm.value];
|
|
193
|
+
if (firstCell === void 0) break;
|
|
194
|
+
into.definition = applyShdArray(into.definition, prl.operand, firstCell, 10, readShd);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
case SPRM_T_DEF_TABLE_SHD80:
|
|
198
|
+
if (into.definition === void 0) break;
|
|
199
|
+
into.definition = applyShdArray(into.definition, prl.operand, 0, 2, (operand, offset) => readShd80(readUint16LE(operand, offset)));
|
|
200
|
+
break;
|
|
201
|
+
case SPRM_T_SET_SHD:
|
|
202
|
+
if (into.definition === void 0) break;
|
|
203
|
+
into.definition = applyTableShade(into.definition, prl.operand, 1);
|
|
204
|
+
break;
|
|
205
|
+
case SPRM_T_SET_SHD_ODD:
|
|
206
|
+
if (into.definition === void 0) break;
|
|
207
|
+
into.definition = applyTableShade(into.definition, prl.operand, 2);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return into;
|
|
211
|
+
}
|
|
212
|
+
//#endregion
|
|
213
|
+
export { HORZ_MERGE_CONTINUATION, VERT_MERGE_CONTINUATION, VERT_MERGE_RESTART, applyTableSprms };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_errors = require("../errors.cjs");
|
|
3
|
+
require("../text/special.cjs");
|
|
4
|
+
const require_table_tap_write = require("./tap-write.cjs");
|
|
5
|
+
//#region src/table/write.ts
|
|
6
|
+
/** sprmPFInTable (0x2416): a Bool8, "MUST be 1 any time the table depth is greater than zero". */
|
|
7
|
+
const SPRM_P_F_IN_TABLE = 9238;
|
|
8
|
+
/** sprmPFTtp (0x2417): a Bool8 marking a cell mark as the row's own Table Terminating Paragraph mark. */
|
|
9
|
+
const SPRM_P_F_TTP = 9239;
|
|
10
|
+
const TWIPS_PER_POINT = 20;
|
|
11
|
+
function pushSprm(bytes, opcode, operand) {
|
|
12
|
+
bytes.push(opcode & 255, opcode >> 8 & 255, ...operand);
|
|
13
|
+
}
|
|
14
|
+
function inTableGrpprl() {
|
|
15
|
+
const bytes = [];
|
|
16
|
+
pushSprm(bytes, SPRM_P_F_IN_TABLE, [1]);
|
|
17
|
+
return bytes;
|
|
18
|
+
}
|
|
19
|
+
function rowMarkExtraGrpprl(boundaries, cellsToWrite, heightPt) {
|
|
20
|
+
const bytes = inTableGrpprl();
|
|
21
|
+
pushSprm(bytes, SPRM_P_F_TTP, [1]);
|
|
22
|
+
bytes.push(...require_table_tap_write.encodeTableRowGrpprl(boundaries, cellsToWrite, heightPt));
|
|
23
|
+
return bytes;
|
|
24
|
+
}
|
|
25
|
+
function cellParagraphs(blocks) {
|
|
26
|
+
if (blocks.length === 0) return [{
|
|
27
|
+
runs: [],
|
|
28
|
+
properties: {},
|
|
29
|
+
extraGrpprl: inTableGrpprl(),
|
|
30
|
+
terminator: 7
|
|
31
|
+
}];
|
|
32
|
+
return blocks.map((block, index) => {
|
|
33
|
+
if (block.kind !== "paragraph") throw new require_errors.DocUnsupportedError(`doc-codec's writer does not support a '${block.kind}' block inside a table cell (only paragraphs are; nested tables are a separately-tracked gap -- see the README's scope note)`);
|
|
34
|
+
return {
|
|
35
|
+
runs: block.runs,
|
|
36
|
+
properties: block,
|
|
37
|
+
extraGrpprl: inTableGrpprl(),
|
|
38
|
+
terminator: index === blocks.length - 1 ? 7 : 13
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function columnBoundariesTwips(columnWidthsPt) {
|
|
43
|
+
const boundaries = [0];
|
|
44
|
+
let cumulative = 0;
|
|
45
|
+
for (const widthPt of columnWidthsPt) {
|
|
46
|
+
cumulative += widthPt * TWIPS_PER_POINT;
|
|
47
|
+
boundaries.push(cumulative);
|
|
48
|
+
}
|
|
49
|
+
return boundaries;
|
|
50
|
+
}
|
|
51
|
+
function flattenRow(cells, columnCount, boundaries, active) {
|
|
52
|
+
const paragraphs = [];
|
|
53
|
+
const cellsToWrite = [];
|
|
54
|
+
const firstBoundary = boundaries[0];
|
|
55
|
+
if (firstBoundary === void 0) throw new require_errors.DocFormatError("internal defect: a table's own column-boundary array is empty despite the columnCount guard above");
|
|
56
|
+
const rowBoundariesTwips = [firstBoundary];
|
|
57
|
+
let column = 0;
|
|
58
|
+
for (const cell of cells) {
|
|
59
|
+
const covered = active.get(column);
|
|
60
|
+
const isContinuation = cell.blocks.length === 0 && covered !== void 0 && covered.remaining > 0;
|
|
61
|
+
let span;
|
|
62
|
+
let vertMerge;
|
|
63
|
+
let blocks;
|
|
64
|
+
if (isContinuation) {
|
|
65
|
+
covered.remaining -= 1;
|
|
66
|
+
span = covered.span;
|
|
67
|
+
vertMerge = 1;
|
|
68
|
+
blocks = [];
|
|
69
|
+
} else {
|
|
70
|
+
span = cell.colSpan ?? 1;
|
|
71
|
+
const rowSpan = cell.rowSpan ?? 1;
|
|
72
|
+
vertMerge = rowSpan > 1 ? 3 : 0;
|
|
73
|
+
if (rowSpan > 1) active.set(column, {
|
|
74
|
+
span,
|
|
75
|
+
remaining: rowSpan - 1
|
|
76
|
+
});
|
|
77
|
+
blocks = cell.blocks;
|
|
78
|
+
}
|
|
79
|
+
paragraphs.push(...cellParagraphs(blocks));
|
|
80
|
+
cellsToWrite.push(isContinuation ? { vertMerge } : {
|
|
81
|
+
vertMerge,
|
|
82
|
+
borders: cell.borders,
|
|
83
|
+
background: cell.background
|
|
84
|
+
});
|
|
85
|
+
column += span;
|
|
86
|
+
const rightBoundary = boundaries[column];
|
|
87
|
+
if (rightBoundary === void 0) throw new require_errors.DocFormatError(`a table cell's own colSpan runs past the table's ${columnCount}-column grid`);
|
|
88
|
+
rowBoundariesTwips.push(rightBoundary);
|
|
89
|
+
}
|
|
90
|
+
if (column !== columnCount) throw new require_errors.DocFormatError(`a table row's own cells cover ${column} columns (via colSpan), but the table declares ${columnCount} in columnWidthsPt`);
|
|
91
|
+
return {
|
|
92
|
+
paragraphs,
|
|
93
|
+
cellsToWrite,
|
|
94
|
+
rowBoundariesTwips
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function flattenTable(table) {
|
|
98
|
+
const columnCount = table.columnWidthsPt.length;
|
|
99
|
+
if (columnCount === 0 || table.rows.length === 0) throw new require_errors.DocFormatError("a table must have at least one column and one row to write");
|
|
100
|
+
const boundaries = columnBoundariesTwips(table.columnWidthsPt);
|
|
101
|
+
const active = /* @__PURE__ */ new Map();
|
|
102
|
+
const output = [];
|
|
103
|
+
for (const row of table.rows) {
|
|
104
|
+
const { paragraphs, cellsToWrite, rowBoundariesTwips } = flattenRow(row.cells, columnCount, boundaries, active);
|
|
105
|
+
output.push(...paragraphs);
|
|
106
|
+
output.push({
|
|
107
|
+
runs: [],
|
|
108
|
+
properties: {},
|
|
109
|
+
extraGrpprl: rowMarkExtraGrpprl(rowBoundariesTwips, cellsToWrite, row.heightPt),
|
|
110
|
+
terminator: 7
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return output;
|
|
114
|
+
}
|
|
115
|
+
function flattenSectionBlocks(blocks) {
|
|
116
|
+
const output = [];
|
|
117
|
+
for (const block of blocks) {
|
|
118
|
+
if (block.kind === "paragraph") {
|
|
119
|
+
output.push({
|
|
120
|
+
runs: block.runs,
|
|
121
|
+
properties: block,
|
|
122
|
+
extraGrpprl: [],
|
|
123
|
+
terminator: 13
|
|
124
|
+
});
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (block.kind === "table") {
|
|
128
|
+
output.push(...flattenTable(block));
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
throw new require_errors.DocUnsupportedError(`doc-codec's writer does not yet support '${block.kind}' blocks (see README's scope note)`);
|
|
132
|
+
}
|
|
133
|
+
return output;
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
exports.flattenSectionBlocks = flattenSectionBlocks;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ContentBlock, ContentParagraph, ContentRun } from "document-schema.js";
|
|
2
|
+
//#region src/table/write.d.ts
|
|
3
|
+
interface WriteParagraph {
|
|
4
|
+
readonly runs: readonly ContentRun[];
|
|
5
|
+
readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore">;
|
|
6
|
+
/** Extra grpprl bytes appended after encodeParagraphGrpprl's own output -- sprmPFInTable on every table paragraph, plus sprmPFTtp and the row's own TAP on a row's trailing mark. */
|
|
7
|
+
readonly extraGrpprl: readonly number[];
|
|
8
|
+
/** The character terminating this paragraph in the text stream: PARAGRAPH_MARK normally, CELL_MARK for a table cell or row mark. */
|
|
9
|
+
readonly terminator: number;
|
|
10
|
+
}
|
|
11
|
+
declare function flattenSectionBlocks(blocks: readonly ContentBlock[]): WriteParagraph[];
|
|
12
|
+
//#endregion
|
|
13
|
+
export { WriteParagraph, flattenSectionBlocks };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ContentBlock, ContentParagraph, ContentRun } from "document-schema.js";
|
|
2
|
+
//#region src/table/write.d.ts
|
|
3
|
+
interface WriteParagraph {
|
|
4
|
+
readonly runs: readonly ContentRun[];
|
|
5
|
+
readonly properties: Pick<ContentParagraph, "alignment" | "indentLeftPt" | "indentFirstLinePt" | "spacingBeforePt" | "spacingAfterPt" | "lineSpacing" | "pageBreakBefore">;
|
|
6
|
+
/** Extra grpprl bytes appended after encodeParagraphGrpprl's own output -- sprmPFInTable on every table paragraph, plus sprmPFTtp and the row's own TAP on a row's trailing mark. */
|
|
7
|
+
readonly extraGrpprl: readonly number[];
|
|
8
|
+
/** The character terminating this paragraph in the text stream: PARAGRAPH_MARK normally, CELL_MARK for a table cell or row mark. */
|
|
9
|
+
readonly terminator: number;
|
|
10
|
+
}
|
|
11
|
+
declare function flattenSectionBlocks(blocks: readonly ContentBlock[]): WriteParagraph[];
|
|
12
|
+
//#endregion
|
|
13
|
+
export { WriteParagraph, flattenSectionBlocks };
|