doc-codec 1.1.2 → 2.1.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 +20 -17
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/prop/fkp-write.cjs +9 -0
- package/dist/prop/fkp-write.d.cts +3 -1
- package/dist/prop/fkp-write.d.ts +3 -1
- package/dist/prop/fkp-write.js +9 -1
- package/dist/table/decoration.cjs +135 -23
- package/dist/table/decoration.d.cts +23 -10
- package/dist/table/decoration.d.ts +23 -10
- package/dist/table/decoration.js +135 -25
- package/dist/table/read.cjs +63 -6
- package/dist/table/read.js +63 -6
- package/dist/table/tap-write.cjs +5 -4
- package/dist/table/tap-write.d.cts +8 -4
- package/dist/table/tap-write.d.ts +8 -4
- package/dist/table/tap-write.js +5 -5
- package/dist/table/tap.cjs +54 -5
- package/dist/table/tap.d.cts +8 -3
- package/dist/table/tap.d.ts +8 -3
- package/dist/table/tap.js +55 -6
- package/dist/table/write.cjs +122 -45
- package/dist/table/write.d.cts +2 -13
- package/dist/table/write.d.ts +2 -13
- package/dist/table/write.js +122 -45
- package/dist/write-C_vJizAM.d.cts +15 -0
- package/dist/write-C_vJizAM.d.ts +15 -0
- package/dist/write.cjs +2 -2
- package/dist/write.d.cts +7 -2
- package/dist/write.d.ts +7 -2
- package/dist/write.js +2 -2
- package/package.json +9 -3
|
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_errors = require("../errors.cjs");
|
|
3
3
|
const require_bytes = require("../bytes.cjs");
|
|
4
4
|
const require_color = require("../color.cjs");
|
|
5
|
+
let document_schema_js = require("document-schema.js");
|
|
5
6
|
//#region src/table/decoration.ts
|
|
6
7
|
/** The four sides of a cell, in the order TC80 declares them ([MS-DOC] 2.9.313: brcTop, brcLeft, brcBottom, brcRight). Used as the iteration order for both directions, so a side can never be read from one offset and written to another. */
|
|
7
8
|
const CELL_BORDER_SIDES = [
|
|
@@ -78,6 +79,10 @@ const EIGHTHS_PER_POINT = 8;
|
|
|
78
79
|
const MIN_DPT_LINE_WIDTH = 2;
|
|
79
80
|
/** dptLineWidth is a single byte, so 255 eighths (31.875pt) is the widest border the format can state at all. */
|
|
80
81
|
const MAX_DPT_LINE_WIDTH = 255;
|
|
82
|
+
/** For BrcType 0x03 (ECMA-376 ST_Border 'double') specifically, dptLineWidth states the width of one of the border's two lines, with the gap between them the same width again, rather than the border's own total rendered width -- neither [MS-DOC] nor [ECMA-376] says so in words, but LibreOffice's own WW8 border-width conversion (editeng/source/items/borderline.cxx: BorderWidthImpl for SvxBorderLineStyle::DOUBLE splits a total width into three equal 1/3 shares for line/gap/line on import, and ConvertBorderWidthToWord divides a total width by 3 on export) states it in code, and this package's own measurements agree with that split exactly: a dptLineWidth of 5 read from a genuine LibreOffice-authored file tripled to 15 eighths (1.875pt) is what LibreOffice's own re-export calls the identical border ~1.8pt double (the small remaining gap is LibreOffice's own twip-rounding on the way through its internal representation, not a further disagreement), and writing a 2pt double border under the pre-fix formula (dptLineWidth 16, i.e. widthPt taken as the field directly) came back from LibreOffice as 6pt double -- 16 read as a single line's width and tripled is exactly 6pt. Scoped to the literal 0x03 value rather than every brcType BRC_TYPE_STYLE collapses onto 'double': the same ConvertBorderWidthToWord gives most of the others their own explicit ratio too, not none -- fWidth/2.0 for THINTHICK_MEDIUMGAP/THICKTHIN_MEDIUMGAP/EMBOSSED/ENGRAVED (BrcTypes 0x0e/0x0f/0x18/0x19), a fixed line/gap width subtracted from the total for THINTHICK_SMALLGAP/THINTHICK_LARGEGAP/THICKTHIN_SMALLGAP/THICKTHIN_LARGEGAP (0x0b/0x11/0x0c/0x12), and that same subtraction halved afterwards for OUTSET/INSET (0x1a/0x1b) -- `std::max(1.0, (fWidth - OUTSET_line1) / 2.0)` and its INSET mirror, not a bare subtraction the way the SMALLGAP/LARGEGAP quartet's own formulas are -- known ratios this package deliberately does not apply, not unknown ones, because BRC_TYPE_STYLE has already collapsed every one of those, plus triple, the three-line thinThickThin gap variants, and doubleWave (none of which LibreOffice's own WW8 exporter writes at all, having no SvxBorderLineStyle member for them), onto ContentStrokeStyle's single 'double' member by the time a ContentBorder reaches dptLineWidthFor on write, so there is no way left to tell which family a given widthPt came from and therefore no way to choose the right one of even the formulas that are known; literal 0x03 is the one case free of that ambiguity, since it is the only BrcType every format in this family's own 'double' token (OOXML's w:val="double", ODF's fo:border-* double) and ContentStrokeStyle's own 'double' member actually mean. Reading one of the other 23 collapsed BrcTypes therefore still reports dptLineWidth's own untripled value as widthPt -- an approximation of unknown accuracy even before this correction existed -- and writing that value back re-emits it as a literal 0x03 with this multiplier applied regardless, a further, compounding approximation on an already-lossy round trip for that narrow, WW8-only decorative corner; decoration.test.ts pins this explicitly rather than leaving it a silent surprise. */
|
|
83
|
+
const DOUBLE_BORDER_WIDTH_MULTIPLIER = 3;
|
|
84
|
+
/** The lowest non-zero dptLineWidth this writer will ever store for a BRC_TYPE_DOUBLE border's own one-third-of-total field, once DOUBLE_BORDER_WIDTH_MULTIPLIER's own division has been applied -- not MIN_DPT_LINE_WIDTH's floor of 2, which belongs to a field that states a border's whole width directly. [MS-DOC]'s "values of less than 2 are considered to be equivalent to 2" is a read-side interpretation rule, not a constraint a producer's own writer has to respect when choosing what to store: LibreOffice's own WW8 export (sw/source/filter/ww8/ww8atr.cxx, TranslateBorderLine, calling editeng's ConvertBorderWidthToWord) applies two separate floors in two different units at two different stages, not one shared floor -- ConvertBorderWidthToWord's own std::max(1.0, fWidth / 3.0) floors double's one-third share to 1.0 twip while the value is still in twips; the result is then converted to eighths-of-a-point ("nWidth = ((nWidth * 8) + 10) / 20", an integer, rounding conversion), which truncates that 1-twip minimum straight down to 0; only then does the "if (0 == nWidth) nWidth = 1; // really thin line, don't omit" floor re-raise it, to 1 eighth-of-a-point (2.5 twips) -- a different, larger unit than the 1.0 twip the first floor stated. The two are analogous in pattern (each is its own never-quite-zero minimum-of-1 rule) but not identical in value, and it is the second, eighths-of-a-point floor MIN_DPT_LINE_WIDTH_DOUBLE mirrors, since that is the one that actually survives into the written BRC. Keeping the general single-line refusal at 2 (MIN_DPT_LINE_WIDTH, a genuinely different field-to-width relationship) while giving double its own floor of 1 keeps refusal for a width the format truly cannot state at all -- below roughly 0.1875pt total, where even a tripled dptLineWidth of 1 rounds down to 0 -- rather than at 0.5625pt, a threshold that only exists as an artefact of applying MIN_DPT_LINE_WIDTH's single-line floor after dividing by three and that no real producer observes: Word's own UI default border width (ooxml.js's own DEFAULT_BORDER_WIDTH_EIGHTH_POINTS, 0.5pt) would otherwise be unwritable as a double border at all. */
|
|
85
|
+
const MIN_DPT_LINE_WIDTH_DOUBLE = 1;
|
|
81
86
|
/** The colour a border with no colour of its own resolves to. [MS-DOC]'s automatic colour (Ico 0x00, or a COLORREF with fAuto set) "designates the default color for the application" and names no components, but ContentBorder.color is required, so a border stating one has to resolve to something. Black is what an automatic border renders as against a default background, and resolving to it keeps the border itself -- which genuinely exists and genuinely renders -- rather than dropping the border outright to avoid stating a colour for it. */
|
|
82
87
|
const AUTOMATIC_BORDER_COLOR = {
|
|
83
88
|
r: 0,
|
|
@@ -87,9 +92,11 @@ const AUTOMATIC_BORDER_COLOR = {
|
|
|
87
92
|
function borderFrom(dptLineWidth, brcType, color) {
|
|
88
93
|
const style = BRC_TYPE_STYLE[brcType];
|
|
89
94
|
if (style === void 0) return void 0;
|
|
95
|
+
const lineWidthEighths = Math.max(dptLineWidth, MIN_DPT_LINE_WIDTH);
|
|
96
|
+
const widthEighths = brcType === BRC_TYPE_DOUBLE ? lineWidthEighths * DOUBLE_BORDER_WIDTH_MULTIPLIER : lineWidthEighths;
|
|
90
97
|
const border = {
|
|
91
98
|
color: color ?? AUTOMATIC_BORDER_COLOR,
|
|
92
|
-
widthPt:
|
|
99
|
+
widthPt: widthEighths / EIGHTHS_PER_POINT
|
|
93
100
|
};
|
|
94
101
|
if (style !== "solid") border.style = style;
|
|
95
102
|
return border;
|
|
@@ -113,6 +120,24 @@ function readBrc(bytes, offset) {
|
|
|
113
120
|
if (brcType === BRC_TYPE_NONE) return void 0;
|
|
114
121
|
return borderFrom(require_bytes.readUint8(bytes, offset + 4), brcType, require_color.readColorRef(bytes, offset));
|
|
115
122
|
}
|
|
123
|
+
function readTableBordersFields(operand, fieldSize, readField) {
|
|
124
|
+
return {
|
|
125
|
+
top: readField(operand, 1),
|
|
126
|
+
left: readField(operand, 1 + fieldSize),
|
|
127
|
+
bottom: readField(operand, 1 + fieldSize * 2),
|
|
128
|
+
right: readField(operand, 1 + fieldSize * 3),
|
|
129
|
+
insideHorizontal: readField(operand, 1 + fieldSize * 4),
|
|
130
|
+
insideVertical: readField(operand, 1 + fieldSize * 5)
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** TableBordersOperand's own 49 bytes ([MS-DOC] 2.9.302): cb (1 byte, MUST be 0x30) then six real Brc fields (8 bytes each, 2.9.16) back to back -- brcTop, brcLeft, brcBottom, brcRight, brcHorizontalInside, brcVerticalInside -- each an exact COLORREF exactly like sprmTSetBrc's own per-cell layer. */
|
|
134
|
+
function readTableBordersOperand(operand) {
|
|
135
|
+
return readTableBordersFields(operand, 8, readBrc);
|
|
136
|
+
}
|
|
137
|
+
/** TableBordersOperand80's own 25 bytes ([MS-DOC] 2.9.303): the Word 97-era spelling, cb (1 byte, MUST be 0x18) then the same six fields as Brc80MayBeNil (4 bytes each, 2.9.18), palette-indexed exactly like TC80's own Brc80 fields. */
|
|
138
|
+
function readTableBordersOperand80(operand) {
|
|
139
|
+
return readTableBordersFields(operand, 4, readBrc80);
|
|
140
|
+
}
|
|
116
141
|
/** Brc80MayBeNil's own no-border value, [MS-DOC] 2.9.18: "When all bits are set (0xFFFFFFFF when interpreted as a 4-byte unsigned integer), this structure specifies that the region in question has no border." */
|
|
117
142
|
const NIL_BRC80 = [
|
|
118
143
|
255,
|
|
@@ -120,28 +145,36 @@ const NIL_BRC80 = [
|
|
|
120
145
|
255,
|
|
121
146
|
255
|
|
122
147
|
];
|
|
123
|
-
/** dptLineWidth for a border of `widthPt`, in the 1/8-point increments [MS-DOC] states it in. Refuses a width the single-byte field cannot hold rather than silently clamping it to a thinner border than the caller asked for, matching how every other out-of-range operand in this writer is handled. */
|
|
124
|
-
function dptLineWidthFor(widthPt) {
|
|
125
|
-
const
|
|
126
|
-
|
|
148
|
+
/** dptLineWidth for a border of `widthPt` rendered as `brcType`, in the 1/8-point increments [MS-DOC] states it in. For BRC_TYPE_DOUBLE, `widthPt` is the border's own total rendered width and the field holds one third of it (see DOUBLE_BORDER_WIDTH_MULTIPLIER's own note); every other brcType states `widthPt` directly. Refuses a width the single-byte field cannot hold rather than silently clamping it to a thinner border than the caller asked for, matching how every other out-of-range operand in this writer is handled -- the minimum itself is brcType-dependent (see MIN_DPT_LINE_WIDTH_DOUBLE's own note for why double's own floor is lower than the general one). Accepting a width does not mean it always survives a round trip unchanged, though: for any `double` `widthPt` in the 0.1875pt (inclusive) to 0.5625pt (exclusive) range, the stored dptLineWidth is exactly 1 -- the one value MIN_DPT_LINE_WIDTH_DOUBLE permits that MIN_DPT_LINE_WIDTH would not -- and borderFrom's own read-side floor then raises that 1 to 2 before DOUBLE_BORDER_WIDTH_MULTIPLIER's tripling applies, so e.g. a border written at 0.5pt reads back as 0.75pt, 50% wider than requested. This is a real, [MS-DOC]-consistent narrowing this function deliberately accepts rather than refuses ("values less than 2 are considered to be equivalent to 2" is exactly what a real producer's own reader would apply to the identical bytes), not a silent bug -- decoration.test.ts pins the exact numbers. */
|
|
149
|
+
function dptLineWidthFor(widthPt, brcType) {
|
|
150
|
+
const multiplier = brcType === BRC_TYPE_DOUBLE ? DOUBLE_BORDER_WIDTH_MULTIPLIER : 1;
|
|
151
|
+
const minEighths = brcType === BRC_TYPE_DOUBLE ? MIN_DPT_LINE_WIDTH_DOUBLE : MIN_DPT_LINE_WIDTH;
|
|
152
|
+
const eighths = Math.round(widthPt / multiplier * EIGHTHS_PER_POINT);
|
|
153
|
+
if (eighths < minEighths || eighths > MAX_DPT_LINE_WIDTH) {
|
|
154
|
+
const minPt = (minEighths - .5) * multiplier / EIGHTHS_PER_POINT;
|
|
155
|
+
const maxPt = 255.5 * multiplier / EIGHTHS_PER_POINT;
|
|
156
|
+
throw new require_errors.DocFormatError(`a table cell border is ${widthPt}pt, outside the ${minPt}..${maxPt}pt range [MS-DOC]'s own single-byte dptLineWidth can state in 1/8-point increments${brcType === BRC_TYPE_DOUBLE ? " of one line's own width, a double border's field being one third of its total rendered width" : ""}`);
|
|
157
|
+
}
|
|
127
158
|
return eighths;
|
|
128
159
|
}
|
|
129
160
|
/** One TC80 border field's own four bytes: the Brc80MayBeNil no-border sentinel for an absent border, otherwise a real Brc80 whose colour is the nearest Ico the fixed palette offers (see color.ts's nearestIco, and borderNeedsExactColor for how the exact colour still reaches the file). dptSpace, fShadow and fFrame are always zero -- ContentBorder models none of the three, so writing anything else would be inventing a fact the input never stated. */
|
|
130
161
|
function writeBrc80(border) {
|
|
131
162
|
if (border === void 0) return [...NIL_BRC80];
|
|
163
|
+
const brcType = STYLE_BRC_TYPE[border.style ?? "solid"];
|
|
132
164
|
return [
|
|
133
|
-
dptLineWidthFor(border.widthPt),
|
|
134
|
-
|
|
165
|
+
dptLineWidthFor(border.widthPt, brcType),
|
|
166
|
+
brcType,
|
|
135
167
|
require_color.nearestIco(border.color),
|
|
136
168
|
0
|
|
137
169
|
];
|
|
138
170
|
}
|
|
139
171
|
/** One TableBrcOperand.brc field's own eight bytes: a real Brc carrying the border's colour exactly, as a COLORREF rather than a palette index. Only ever called for a border that exists, since a TableBrcOperand naming no sides is never emitted at all. */
|
|
140
172
|
function writeBrc(border) {
|
|
173
|
+
const brcType = STYLE_BRC_TYPE[border.style ?? "solid"];
|
|
141
174
|
return [
|
|
142
175
|
...require_color.colorRefBytes(border.color),
|
|
143
|
-
dptLineWidthFor(border.widthPt),
|
|
144
|
-
|
|
176
|
+
dptLineWidthFor(border.widthPt, brcType),
|
|
177
|
+
brcType,
|
|
145
178
|
0,
|
|
146
179
|
0
|
|
147
180
|
];
|
|
@@ -154,41 +187,118 @@ function borderNeedsExactColor(border) {
|
|
|
154
187
|
const approximated = require_color.colorRefBytes(palette);
|
|
155
188
|
return wanted[0] !== approximated[0] || wanted[1] !== approximated[1] || wanted[2] !== approximated[2];
|
|
156
189
|
}
|
|
157
|
-
/** ipatAuto, [MS-DOC] 2.9.121: "Clear, ST_Shd: clear" -- the pattern under which a cell simply shows its own cvBack, which is how both Word and LibreOffice spell a flat background colour
|
|
190
|
+
/** ipatAuto, [MS-DOC] 2.9.121: "Clear, ST_Shd: clear" -- the pattern under which a cell simply shows its own cvBack, which is how both Word and LibreOffice spell a flat background colour. */
|
|
158
191
|
const IPAT_AUTO = 0;
|
|
159
192
|
/** ipatSolid, [MS-DOC] 2.9.121: "Solid ST_Shd: solid" -- the cell is filled entirely with cvFore. */
|
|
160
193
|
const IPAT_SOLID = 1;
|
|
161
194
|
/**
|
|
162
|
-
*
|
|
195
|
+
* Every Ipat value [MS-DOC] 2.9.121 maps onto a real ECMA-376 ST_Shd token, to the ContentCellPatternType name document-schema.js's own ContentCellPatternTypeSchema gives that same ST_Shd token (see that schema's own top comment for the full citation and the two vocabularies' shared naming rationale). ipatAuto and ipatSolid are handled by their own callers rather than listed here, since each resolves to a 'solid' fill, not a 'pattern' one. The sixteen ipatPctNew* fine percentages [MS-DOC] itself says "SHOULD NOT be used" (2.9.121's own note) and that have no ST_Shd equivalent at all -- 2.5%, 7.5%, 17.5%, 22.5%, 27.5%, 32.5%, 42.5%, 47.5%, 52.5%, 57.5%, 67.5%, 72.5%, 77.5%, 82.5%, 92.5%, 97.5% -- are deliberately absent, exactly as ContentCellPatternTypeSchema deliberately has no member for them; a cell stating one of these reads as no background, the same fallback every other genuinely unrepresentable Ipat value already resolves to.
|
|
196
|
+
*/
|
|
197
|
+
const IPAT_TO_PATTERN_TYPE = {
|
|
198
|
+
2: "percent5",
|
|
199
|
+
3: "percent10",
|
|
200
|
+
4: "percent20",
|
|
201
|
+
5: "percent25",
|
|
202
|
+
6: "percent30",
|
|
203
|
+
7: "percent40",
|
|
204
|
+
8: "percent50",
|
|
205
|
+
9: "percent60",
|
|
206
|
+
10: "percent70",
|
|
207
|
+
11: "percent75",
|
|
208
|
+
12: "percent80",
|
|
209
|
+
13: "percent90",
|
|
210
|
+
14: "horizontalStripe",
|
|
211
|
+
15: "verticalStripe",
|
|
212
|
+
16: "reverseDiagonalStripe",
|
|
213
|
+
17: "diagonalStripe",
|
|
214
|
+
18: "horizontalCross",
|
|
215
|
+
19: "diagonalCross",
|
|
216
|
+
20: "thinHorizontalStripe",
|
|
217
|
+
21: "thinVerticalStripe",
|
|
218
|
+
22: "thinReverseDiagonalStripe",
|
|
219
|
+
23: "thinDiagonalStripe",
|
|
220
|
+
24: "thinHorizontalCross",
|
|
221
|
+
25: "thinDiagonalCross",
|
|
222
|
+
37: "percent12",
|
|
223
|
+
38: "percent15",
|
|
224
|
+
43: "percent35",
|
|
225
|
+
44: "percent37",
|
|
226
|
+
46: "percent45",
|
|
227
|
+
49: "percent55",
|
|
228
|
+
51: "percent62",
|
|
229
|
+
52: "percent65",
|
|
230
|
+
57: "percent85",
|
|
231
|
+
58: "percent87",
|
|
232
|
+
60: "percent95"
|
|
233
|
+
};
|
|
234
|
+
/** The inverse of IPAT_TO_PATTERN_TYPE, built from it rather than restated by hand so the two can never drift apart. Every ContentCellPatternType this package's own writer is ever asked to state has an entry, since the Word-family half of the shared vocabulary is exactly IPAT_TO_PATTERN_TYPE's own value set -- the SpreadsheetML-only members (mediumGray through gray0625) are absent, ST_Shd having no equivalent for them at all. */
|
|
235
|
+
const PATTERN_TYPE_TO_IPAT = new Map(Object.entries(IPAT_TO_PATTERN_TYPE).map(([ipat, patternType]) => [patternType, Number(ipat)]));
|
|
236
|
+
/**
|
|
237
|
+
* One Shd ([MS-DOC] 2.9.247) as a ContentCellFill, or undefined where it states none.
|
|
163
238
|
*
|
|
164
|
-
*
|
|
239
|
+
* ipatAuto resolves to a 'solid' fill of cvBack (ECMA-376's own `clear` shading with a fill colour, which is what a real producer writes for a plain cell background) and ipatSolid to a 'solid' fill of cvFore. Every other named Ipat resolves to a real 'pattern' fill via IPAT_TO_PATTERN_TYPE, carrying whichever of cvFore/cvBack the cell actually states -- either may be cvAuto (the application's own default) and therefore absent, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention. ipatNil and the sixteen ipatPctNew* values with no ST_Shd equivalent (see IPAT_TO_PATTERN_TYPE's own note) resolve to no background at all, the same fallback this reader has always used for a pattern it cannot express.
|
|
165
240
|
*
|
|
166
|
-
* A cvAuto colour under
|
|
241
|
+
* A cvAuto colour under ipatAuto/ipatSolid is likewise no background: it designates the application's own default, which for a cell background is "not shaded" rather than a colour to state. ShdAuto and ShdNil -- the two special values [MS-DOC] 2.9.247 names for "no shading is applied" -- both fall out of exactly that, with no separate check: each is a pair of cvAuto colours under ipatAuto.
|
|
167
242
|
*/
|
|
168
243
|
function readShd(bytes, offset) {
|
|
169
|
-
|
|
170
|
-
if (ipat === IPAT_AUTO) return require_color.readColorRef(bytes, offset + 4);
|
|
171
|
-
if (ipat === IPAT_SOLID) return require_color.readColorRef(bytes, offset);
|
|
244
|
+
return shdFill(require_color.readColorRef(bytes, offset), require_color.readColorRef(bytes, offset + 4), require_bytes.readUint16LE(bytes, offset + 8));
|
|
172
245
|
}
|
|
173
|
-
/**
|
|
174
|
-
function
|
|
175
|
-
return
|
|
246
|
+
/** Resolves one cvFore/cvBack/ipat triple -- however the caller sourced the three, whether from Shd's own COLORREFs (readShd) or Shd80's Ico-palette pair (readShd80) -- into the ContentCellFill readShd's own doc comment describes. Shared so the two callers can never disagree about what a given ipat means. */
|
|
247
|
+
function shdFill(cvFore, cvBack, ipat) {
|
|
248
|
+
if (ipat === IPAT_AUTO) return cvBack === void 0 ? void 0 : {
|
|
249
|
+
kind: "solid",
|
|
250
|
+
color: cvBack
|
|
251
|
+
};
|
|
252
|
+
if (ipat === IPAT_SOLID) return cvFore === void 0 ? void 0 : {
|
|
253
|
+
kind: "solid",
|
|
254
|
+
color: cvFore
|
|
255
|
+
};
|
|
256
|
+
const patternType = IPAT_TO_PATTERN_TYPE[ipat];
|
|
257
|
+
if (patternType === void 0) return void 0;
|
|
258
|
+
return {
|
|
259
|
+
kind: "pattern",
|
|
260
|
+
patternType,
|
|
261
|
+
...cvFore !== void 0 ? { foregroundColor: cvFore } : {},
|
|
262
|
+
...cvBack !== void 0 ? { backgroundColor: cvBack } : {}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/** One Shd's own ten bytes, the inverse of readShd: a 'solid' fill states cvFore automatic and the fill's own colour as cvBack under ipatAuto, exactly how LibreOffice 26.2.5.2 writes a plain cell fill (confirmed against its own `.doc` output: a #ffff00 cell came back as cvFore cvAuto, cvBack `ff ff 00 00`, ipat 0x0000) -- writing ipatSolid instead would be an equally spec-conformant alternative Shd never needed, since the two patterns are read identically apart from which COLORREF they draw from. A 'pattern' fill states its own foreground/background colours (automatic where the fill left one unstated) under the Ipat value PATTERN_TYPE_TO_IPAT names for it, throwing DocUnsupportedError for a SpreadsheetML-only pattern type ([MS-DOC]'s Ipat vocabulary has no member for one -- see PATTERN_TYPE_TO_IPAT's own note) rather than silently writing the wrong pattern or dropping it. An absent fill writes ShdAuto -- the all-automatic value [MS-DOC] 2.9.247 defines as "no shading is applied" -- so an undecorated cell inside a row that has decorated ones still states its own lack of shading rather than inheriting a neighbour's. */
|
|
266
|
+
function writeShd(fill) {
|
|
267
|
+
if (fill === void 0) return [
|
|
268
|
+
...require_color.autoColorRefBytes(),
|
|
176
269
|
...require_color.autoColorRefBytes(),
|
|
177
|
-
...background === void 0 ? require_color.autoColorRefBytes() : require_color.colorRefBytes(background),
|
|
178
270
|
0,
|
|
179
271
|
0
|
|
180
272
|
];
|
|
273
|
+
switch (fill.kind) {
|
|
274
|
+
case "solid": return [
|
|
275
|
+
...require_color.autoColorRefBytes(),
|
|
276
|
+
...require_color.colorRefBytes(fill.color),
|
|
277
|
+
0,
|
|
278
|
+
0
|
|
279
|
+
];
|
|
280
|
+
case "pattern": {
|
|
281
|
+
const ipat = PATTERN_TYPE_TO_IPAT.get(fill.patternType);
|
|
282
|
+
if (ipat === void 0) throw new require_errors.DocUnsupportedError(`doc-codec cannot write a '${fill.patternType}' cell fill: [MS-DOC]'s own Ipat enumeration has no member for it, that pattern name belonging only to SpreadsheetML's ST_PatternType half of ContentCellPatternType's shared vocabulary`);
|
|
283
|
+
return [
|
|
284
|
+
...fill.foregroundColor === void 0 ? require_color.autoColorRefBytes() : require_color.colorRefBytes(fill.foregroundColor),
|
|
285
|
+
...fill.backgroundColor === void 0 ? require_color.autoColorRefBytes() : require_color.colorRefBytes(fill.backgroundColor),
|
|
286
|
+
ipat & 255,
|
|
287
|
+
ipat >> 8 & 255
|
|
288
|
+
];
|
|
289
|
+
}
|
|
290
|
+
default: throw new require_errors.DocUnsupportedError(`doc-codec cannot write a cell fill with kind '${(0, document_schema_js.unrecognizedFillKind)(fill)}': ContentCellFillSchema's discriminated union only defines 'solid' and 'pattern'`);
|
|
291
|
+
}
|
|
181
292
|
}
|
|
182
293
|
/** Shd80Nil, [MS-DOC] 2.9.248: icoFore 0x1F, icoBack 0x1F, ipat 0x3F -- every bit set, "specifies that no shading is applied", and explicitly exempt from the Ico and Ipat bounds the fields otherwise carry. */
|
|
183
294
|
const SHD80_NIL = 65535;
|
|
184
|
-
/** One Shd80 ([MS-DOC] 2.9.248) as a
|
|
295
|
+
/** One Shd80 ([MS-DOC] 2.9.248) as a ContentCellFill: the same Ipat vocabulary readShd resolves, over the Ico palette rather than COLORREFs. This is the Word 97-era spelling of cell shading, superseded by Shd but still written -- alongside it -- by a real producer, so a file carrying only this one still reads. Never written by this package, which states shading through Shd alone. icoFore/icoBack are each a 5-bit field, so a value the 17-entry palette cannot hold is a real possibility rather than a format-level impossibility; decorativeIcoColor resolves that case to no concrete colour (the same fallback cvAuto already gets) instead of aborting the whole document read. */
|
|
185
296
|
function readShd80(value) {
|
|
186
297
|
if (value === SHD80_NIL) return void 0;
|
|
187
298
|
const icoFore = value & 31;
|
|
188
299
|
const icoBack = value >> 5 & 31;
|
|
189
300
|
const ipat = value >> 10 & 63;
|
|
190
|
-
|
|
191
|
-
if (ipat === IPAT_SOLID) return require_color.decorativeIcoColor(icoFore);
|
|
301
|
+
return shdFill(require_color.decorativeIcoColor(icoFore), require_color.decorativeIcoColor(icoBack), ipat);
|
|
192
302
|
}
|
|
193
303
|
/** A cell's four sides as a ContentCellBorders, or undefined when it has none -- the shape ContentTableCell.borders carries, with an absent side meaning that side has no border rather than an explicitly-null one. */
|
|
194
304
|
function cellBordersFrom(sides) {
|
|
@@ -215,6 +325,8 @@ exports.readBrc = readBrc;
|
|
|
215
325
|
exports.readBrc80 = readBrc80;
|
|
216
326
|
exports.readShd = readShd;
|
|
217
327
|
exports.readShd80 = readShd80;
|
|
328
|
+
exports.readTableBordersOperand = readTableBordersOperand;
|
|
329
|
+
exports.readTableBordersOperand80 = readTableBordersOperand80;
|
|
218
330
|
exports.writeBrc = writeBrc;
|
|
219
331
|
exports.writeBrc80 = writeBrc80;
|
|
220
332
|
exports.writeShd = writeShd;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContentBorder, ContentCellBorders, ContentCellFill } from "document-schema.js";
|
|
2
2
|
//#region src/table/decoration.d.ts
|
|
3
3
|
/** The four sides of a cell, in the order TC80 declares them ([MS-DOC] 2.9.313: brcTop, brcLeft, brcBottom, brcRight). Used as the iteration order for both directions, so a side can never be read from one offset and written to another. */
|
|
4
4
|
declare const CELL_BORDER_SIDES: readonly ["top", "left", "bottom", "right"];
|
|
@@ -17,6 +17,19 @@ declare const SHD80_SIZE = 2;
|
|
|
17
17
|
declare function readBrc80(bytes: Uint8Array, offset: number): ContentBorder | undefined;
|
|
18
18
|
/** The eight bytes of one TableBrcOperand.brc field: a BrcMayBeNil ([MS-DOC] 2.9.20) -- "If the last four bytes are 0xFFFFFFFF, the BrcMayBeNil is a NilBrc that specifies that the table cells in question have no border", otherwise a Brc ([MS-DOC] 2.9.16) whose own cv states the colour exactly. */
|
|
19
19
|
declare function readBrc(bytes: Uint8Array, offset: number): ContentBorder | undefined;
|
|
20
|
+
/** A row's own six-side border cascade, from sprmTTableBorders ([MS-DOC] 2.9.302) or the Word 97-era sprmTTableBorders80 ([MS-DOC] 2.9.303) -- the layer table/tap.ts's own top-of-file note calls "a cascade above the per-cell layer rather than another spelling of it". Both structures always state all six fields (there is no bordersToApply-style subset the way TableBrcOperand has), in the same order: brcTop, brcLeft, brcBottom, brcRight, brcHorizontalInside (the border between this row and its table neighbours), brcVerticalInside (the border between this row's own cells). Left unresolved onto any particular cell here: which of the six reaches a given cell/side depends on that cell's position in the WHOLE table -- is this the table's first row; does this cell reach the table's real bottom edge (the table's own last physical row directly, or any non-continuation cell -- a plain cell or a vertically-merged anchor -- whose own merge chain's last row no later row covers at all in a ragged table, a plain cell being the length-one special case of that chain); is this row's first or last physical cell -- which only table/read.ts's own cross-row assembly knows -- see its applyRowLevelBorderCascade and cellReachesTableBottom. */
|
|
21
|
+
interface TableBordersSet {
|
|
22
|
+
readonly top?: ContentBorder;
|
|
23
|
+
readonly left?: ContentBorder;
|
|
24
|
+
readonly bottom?: ContentBorder;
|
|
25
|
+
readonly right?: ContentBorder;
|
|
26
|
+
readonly insideHorizontal?: ContentBorder;
|
|
27
|
+
readonly insideVertical?: ContentBorder;
|
|
28
|
+
}
|
|
29
|
+
/** TableBordersOperand's own 49 bytes ([MS-DOC] 2.9.302): cb (1 byte, MUST be 0x30) then six real Brc fields (8 bytes each, 2.9.16) back to back -- brcTop, brcLeft, brcBottom, brcRight, brcHorizontalInside, brcVerticalInside -- each an exact COLORREF exactly like sprmTSetBrc's own per-cell layer. */
|
|
30
|
+
declare function readTableBordersOperand(operand: Uint8Array): TableBordersSet;
|
|
31
|
+
/** TableBordersOperand80's own 25 bytes ([MS-DOC] 2.9.303): the Word 97-era spelling, cb (1 byte, MUST be 0x18) then the same six fields as Brc80MayBeNil (4 bytes each, 2.9.18), palette-indexed exactly like TC80's own Brc80 fields. */
|
|
32
|
+
declare function readTableBordersOperand80(operand: Uint8Array): TableBordersSet;
|
|
20
33
|
/** One TC80 border field's own four bytes: the Brc80MayBeNil no-border sentinel for an absent border, otherwise a real Brc80 whose colour is the nearest Ico the fixed palette offers (see color.ts's nearestIco, and borderNeedsExactColor for how the exact colour still reaches the file). dptSpace, fShadow and fFrame are always zero -- ContentBorder models none of the three, so writing anything else would be inventing a fact the input never stated. */
|
|
21
34
|
declare function writeBrc80(border: ContentBorder | undefined): number[];
|
|
22
35
|
/** One TableBrcOperand.brc field's own eight bytes: a real Brc carrying the border's colour exactly, as a COLORREF rather than a palette index. Only ever called for a border that exists, since a TableBrcOperand naming no sides is never emitted at all. */
|
|
@@ -24,18 +37,18 @@ declare function writeBrc(border: ContentBorder): number[];
|
|
|
24
37
|
/** Whether this border's colour survives the Ico palette Brc80 is limited to. When it does, TC80's own Brc80 already states the border exactly and the sprmTSetBrc precision layer would be pure duplication; when it does not, that layer is the only place the real colour can be stated. Compared on the written byte values rather than the floating-point components, so a colour that round-trips through colorRefBytes to the identical palette entry counts as exact. */
|
|
25
38
|
declare function borderNeedsExactColor(border: ContentBorder): boolean;
|
|
26
39
|
/**
|
|
27
|
-
* One Shd ([MS-DOC] 2.9.247) as a
|
|
40
|
+
* One Shd ([MS-DOC] 2.9.247) as a ContentCellFill, or undefined where it states none.
|
|
28
41
|
*
|
|
29
|
-
*
|
|
42
|
+
* ipatAuto resolves to a 'solid' fill of cvBack (ECMA-376's own `clear` shading with a fill colour, which is what a real producer writes for a plain cell background) and ipatSolid to a 'solid' fill of cvFore. Every other named Ipat resolves to a real 'pattern' fill via IPAT_TO_PATTERN_TYPE, carrying whichever of cvFore/cvBack the cell actually states -- either may be cvAuto (the application's own default) and therefore absent, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention. ipatNil and the sixteen ipatPctNew* values with no ST_Shd equivalent (see IPAT_TO_PATTERN_TYPE's own note) resolve to no background at all, the same fallback this reader has always used for a pattern it cannot express.
|
|
30
43
|
*
|
|
31
|
-
* A cvAuto colour under
|
|
44
|
+
* A cvAuto colour under ipatAuto/ipatSolid is likewise no background: it designates the application's own default, which for a cell background is "not shaded" rather than a colour to state. ShdAuto and ShdNil -- the two special values [MS-DOC] 2.9.247 names for "no shading is applied" -- both fall out of exactly that, with no separate check: each is a pair of cvAuto colours under ipatAuto.
|
|
32
45
|
*/
|
|
33
|
-
declare function readShd(bytes: Uint8Array, offset: number):
|
|
34
|
-
/** One Shd's own ten bytes: cvFore
|
|
35
|
-
declare function writeShd(
|
|
36
|
-
/** One Shd80 ([MS-DOC] 2.9.248) as a
|
|
37
|
-
declare function readShd80(value: number):
|
|
46
|
+
declare function readShd(bytes: Uint8Array, offset: number): ContentCellFill | undefined;
|
|
47
|
+
/** One Shd's own ten bytes, the inverse of readShd: a 'solid' fill states cvFore automatic and the fill's own colour as cvBack under ipatAuto, exactly how LibreOffice 26.2.5.2 writes a plain cell fill (confirmed against its own `.doc` output: a #ffff00 cell came back as cvFore cvAuto, cvBack `ff ff 00 00`, ipat 0x0000) -- writing ipatSolid instead would be an equally spec-conformant alternative Shd never needed, since the two patterns are read identically apart from which COLORREF they draw from. A 'pattern' fill states its own foreground/background colours (automatic where the fill left one unstated) under the Ipat value PATTERN_TYPE_TO_IPAT names for it, throwing DocUnsupportedError for a SpreadsheetML-only pattern type ([MS-DOC]'s Ipat vocabulary has no member for one -- see PATTERN_TYPE_TO_IPAT's own note) rather than silently writing the wrong pattern or dropping it. An absent fill writes ShdAuto -- the all-automatic value [MS-DOC] 2.9.247 defines as "no shading is applied" -- so an undecorated cell inside a row that has decorated ones still states its own lack of shading rather than inheriting a neighbour's. */
|
|
48
|
+
declare function writeShd(fill: ContentCellFill | undefined): number[];
|
|
49
|
+
/** One Shd80 ([MS-DOC] 2.9.248) as a ContentCellFill: the same Ipat vocabulary readShd resolves, over the Ico palette rather than COLORREFs. This is the Word 97-era spelling of cell shading, superseded by Shd but still written -- alongside it -- by a real producer, so a file carrying only this one still reads. Never written by this package, which states shading through Shd alone. icoFore/icoBack are each a 5-bit field, so a value the 17-entry palette cannot hold is a real possibility rather than a format-level impossibility; decorativeIcoColor resolves that case to no concrete colour (the same fallback cvAuto already gets) instead of aborting the whole document read. */
|
|
50
|
+
declare function readShd80(value: number): ContentCellFill | undefined;
|
|
38
51
|
/** A cell's four sides as a ContentCellBorders, or undefined when it has none -- the shape ContentTableCell.borders carries, with an absent side meaning that side has no border rather than an explicitly-null one. */
|
|
39
52
|
declare function cellBordersFrom(sides: Readonly<Record<CellBorderSide, ContentBorder | undefined>>): ContentCellBorders | undefined;
|
|
40
53
|
//#endregion
|
|
41
|
-
export { BORDERS_TO_APPLY, BRC80_SIZE, BRC_SIZE, CELL_BORDER_SIDES, CellBorderSide, SHD80_SIZE, SHD_SIZE, borderNeedsExactColor, cellBordersFrom, readBrc, readBrc80, readShd, readShd80, writeBrc, writeBrc80, writeShd };
|
|
54
|
+
export { BORDERS_TO_APPLY, BRC80_SIZE, BRC_SIZE, CELL_BORDER_SIDES, CellBorderSide, SHD80_SIZE, SHD_SIZE, TableBordersSet, borderNeedsExactColor, cellBordersFrom, readBrc, readBrc80, readShd, readShd80, readTableBordersOperand, readTableBordersOperand80, writeBrc, writeBrc80, writeShd };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContentBorder, ContentCellBorders, ContentCellFill } from "document-schema.js";
|
|
2
2
|
//#region src/table/decoration.d.ts
|
|
3
3
|
/** The four sides of a cell, in the order TC80 declares them ([MS-DOC] 2.9.313: brcTop, brcLeft, brcBottom, brcRight). Used as the iteration order for both directions, so a side can never be read from one offset and written to another. */
|
|
4
4
|
declare const CELL_BORDER_SIDES: readonly ["top", "left", "bottom", "right"];
|
|
@@ -17,6 +17,19 @@ declare const SHD80_SIZE = 2;
|
|
|
17
17
|
declare function readBrc80(bytes: Uint8Array, offset: number): ContentBorder | undefined;
|
|
18
18
|
/** The eight bytes of one TableBrcOperand.brc field: a BrcMayBeNil ([MS-DOC] 2.9.20) -- "If the last four bytes are 0xFFFFFFFF, the BrcMayBeNil is a NilBrc that specifies that the table cells in question have no border", otherwise a Brc ([MS-DOC] 2.9.16) whose own cv states the colour exactly. */
|
|
19
19
|
declare function readBrc(bytes: Uint8Array, offset: number): ContentBorder | undefined;
|
|
20
|
+
/** A row's own six-side border cascade, from sprmTTableBorders ([MS-DOC] 2.9.302) or the Word 97-era sprmTTableBorders80 ([MS-DOC] 2.9.303) -- the layer table/tap.ts's own top-of-file note calls "a cascade above the per-cell layer rather than another spelling of it". Both structures always state all six fields (there is no bordersToApply-style subset the way TableBrcOperand has), in the same order: brcTop, brcLeft, brcBottom, brcRight, brcHorizontalInside (the border between this row and its table neighbours), brcVerticalInside (the border between this row's own cells). Left unresolved onto any particular cell here: which of the six reaches a given cell/side depends on that cell's position in the WHOLE table -- is this the table's first row; does this cell reach the table's real bottom edge (the table's own last physical row directly, or any non-continuation cell -- a plain cell or a vertically-merged anchor -- whose own merge chain's last row no later row covers at all in a ragged table, a plain cell being the length-one special case of that chain); is this row's first or last physical cell -- which only table/read.ts's own cross-row assembly knows -- see its applyRowLevelBorderCascade and cellReachesTableBottom. */
|
|
21
|
+
interface TableBordersSet {
|
|
22
|
+
readonly top?: ContentBorder;
|
|
23
|
+
readonly left?: ContentBorder;
|
|
24
|
+
readonly bottom?: ContentBorder;
|
|
25
|
+
readonly right?: ContentBorder;
|
|
26
|
+
readonly insideHorizontal?: ContentBorder;
|
|
27
|
+
readonly insideVertical?: ContentBorder;
|
|
28
|
+
}
|
|
29
|
+
/** TableBordersOperand's own 49 bytes ([MS-DOC] 2.9.302): cb (1 byte, MUST be 0x30) then six real Brc fields (8 bytes each, 2.9.16) back to back -- brcTop, brcLeft, brcBottom, brcRight, brcHorizontalInside, brcVerticalInside -- each an exact COLORREF exactly like sprmTSetBrc's own per-cell layer. */
|
|
30
|
+
declare function readTableBordersOperand(operand: Uint8Array): TableBordersSet;
|
|
31
|
+
/** TableBordersOperand80's own 25 bytes ([MS-DOC] 2.9.303): the Word 97-era spelling, cb (1 byte, MUST be 0x18) then the same six fields as Brc80MayBeNil (4 bytes each, 2.9.18), palette-indexed exactly like TC80's own Brc80 fields. */
|
|
32
|
+
declare function readTableBordersOperand80(operand: Uint8Array): TableBordersSet;
|
|
20
33
|
/** One TC80 border field's own four bytes: the Brc80MayBeNil no-border sentinel for an absent border, otherwise a real Brc80 whose colour is the nearest Ico the fixed palette offers (see color.ts's nearestIco, and borderNeedsExactColor for how the exact colour still reaches the file). dptSpace, fShadow and fFrame are always zero -- ContentBorder models none of the three, so writing anything else would be inventing a fact the input never stated. */
|
|
21
34
|
declare function writeBrc80(border: ContentBorder | undefined): number[];
|
|
22
35
|
/** One TableBrcOperand.brc field's own eight bytes: a real Brc carrying the border's colour exactly, as a COLORREF rather than a palette index. Only ever called for a border that exists, since a TableBrcOperand naming no sides is never emitted at all. */
|
|
@@ -24,18 +37,18 @@ declare function writeBrc(border: ContentBorder): number[];
|
|
|
24
37
|
/** Whether this border's colour survives the Ico palette Brc80 is limited to. When it does, TC80's own Brc80 already states the border exactly and the sprmTSetBrc precision layer would be pure duplication; when it does not, that layer is the only place the real colour can be stated. Compared on the written byte values rather than the floating-point components, so a colour that round-trips through colorRefBytes to the identical palette entry counts as exact. */
|
|
25
38
|
declare function borderNeedsExactColor(border: ContentBorder): boolean;
|
|
26
39
|
/**
|
|
27
|
-
* One Shd ([MS-DOC] 2.9.247) as a
|
|
40
|
+
* One Shd ([MS-DOC] 2.9.247) as a ContentCellFill, or undefined where it states none.
|
|
28
41
|
*
|
|
29
|
-
*
|
|
42
|
+
* ipatAuto resolves to a 'solid' fill of cvBack (ECMA-376's own `clear` shading with a fill colour, which is what a real producer writes for a plain cell background) and ipatSolid to a 'solid' fill of cvFore. Every other named Ipat resolves to a real 'pattern' fill via IPAT_TO_PATTERN_TYPE, carrying whichever of cvFore/cvBack the cell actually states -- either may be cvAuto (the application's own default) and therefore absent, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention. ipatNil and the sixteen ipatPctNew* values with no ST_Shd equivalent (see IPAT_TO_PATTERN_TYPE's own note) resolve to no background at all, the same fallback this reader has always used for a pattern it cannot express.
|
|
30
43
|
*
|
|
31
|
-
* A cvAuto colour under
|
|
44
|
+
* A cvAuto colour under ipatAuto/ipatSolid is likewise no background: it designates the application's own default, which for a cell background is "not shaded" rather than a colour to state. ShdAuto and ShdNil -- the two special values [MS-DOC] 2.9.247 names for "no shading is applied" -- both fall out of exactly that, with no separate check: each is a pair of cvAuto colours under ipatAuto.
|
|
32
45
|
*/
|
|
33
|
-
declare function readShd(bytes: Uint8Array, offset: number):
|
|
34
|
-
/** One Shd's own ten bytes: cvFore
|
|
35
|
-
declare function writeShd(
|
|
36
|
-
/** One Shd80 ([MS-DOC] 2.9.248) as a
|
|
37
|
-
declare function readShd80(value: number):
|
|
46
|
+
declare function readShd(bytes: Uint8Array, offset: number): ContentCellFill | undefined;
|
|
47
|
+
/** One Shd's own ten bytes, the inverse of readShd: a 'solid' fill states cvFore automatic and the fill's own colour as cvBack under ipatAuto, exactly how LibreOffice 26.2.5.2 writes a plain cell fill (confirmed against its own `.doc` output: a #ffff00 cell came back as cvFore cvAuto, cvBack `ff ff 00 00`, ipat 0x0000) -- writing ipatSolid instead would be an equally spec-conformant alternative Shd never needed, since the two patterns are read identically apart from which COLORREF they draw from. A 'pattern' fill states its own foreground/background colours (automatic where the fill left one unstated) under the Ipat value PATTERN_TYPE_TO_IPAT names for it, throwing DocUnsupportedError for a SpreadsheetML-only pattern type ([MS-DOC]'s Ipat vocabulary has no member for one -- see PATTERN_TYPE_TO_IPAT's own note) rather than silently writing the wrong pattern or dropping it. An absent fill writes ShdAuto -- the all-automatic value [MS-DOC] 2.9.247 defines as "no shading is applied" -- so an undecorated cell inside a row that has decorated ones still states its own lack of shading rather than inheriting a neighbour's. */
|
|
48
|
+
declare function writeShd(fill: ContentCellFill | undefined): number[];
|
|
49
|
+
/** One Shd80 ([MS-DOC] 2.9.248) as a ContentCellFill: the same Ipat vocabulary readShd resolves, over the Ico palette rather than COLORREFs. This is the Word 97-era spelling of cell shading, superseded by Shd but still written -- alongside it -- by a real producer, so a file carrying only this one still reads. Never written by this package, which states shading through Shd alone. icoFore/icoBack are each a 5-bit field, so a value the 17-entry palette cannot hold is a real possibility rather than a format-level impossibility; decorativeIcoColor resolves that case to no concrete colour (the same fallback cvAuto already gets) instead of aborting the whole document read. */
|
|
50
|
+
declare function readShd80(value: number): ContentCellFill | undefined;
|
|
38
51
|
/** A cell's four sides as a ContentCellBorders, or undefined when it has none -- the shape ContentTableCell.borders carries, with an absent side meaning that side has no border rather than an explicitly-null one. */
|
|
39
52
|
declare function cellBordersFrom(sides: Readonly<Record<CellBorderSide, ContentBorder | undefined>>): ContentCellBorders | undefined;
|
|
40
53
|
//#endregion
|
|
41
|
-
export { BORDERS_TO_APPLY, BRC80_SIZE, BRC_SIZE, CELL_BORDER_SIDES, CellBorderSide, SHD80_SIZE, SHD_SIZE, borderNeedsExactColor, cellBordersFrom, readBrc, readBrc80, readShd, readShd80, writeBrc, writeBrc80, writeShd };
|
|
54
|
+
export { BORDERS_TO_APPLY, BRC80_SIZE, BRC_SIZE, CELL_BORDER_SIDES, CellBorderSide, SHD80_SIZE, SHD_SIZE, TableBordersSet, borderNeedsExactColor, cellBordersFrom, readBrc, readBrc80, readShd, readShd80, readTableBordersOperand, readTableBordersOperand80, writeBrc, writeBrc80, writeShd };
|