xls-codec 2.0.2 → 3.0.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 CHANGED
@@ -18,7 +18,7 @@ Under active development, with real, tested **read and write** support. Built an
18
18
  - **Formula text recovery** (`src/biff/ptg.ts`, `src/biff/ptg-functions.ts`) — a Formula record's compiled `rgce` token stream ([MS-XLS] 2.5.198's `Ptg` vocabulary) read and rebuilt into the infix text a spreadsheet application would show: literal operands (`PtgInt`/`PtgNum`/`PtgStr`/`PtgBool`/`PtgErr`/`PtgMissArg`), cell and range references including their 3D (cross-sheet) forms (`PtgRef`/`PtgArea`/`PtgRef3d`/`PtgArea3d`, `$`-qualified per their own relative/absolute flags, a 3D reference's sheet name resolved through `EXTERNSHEET` and a self-referencing `SupBook` — `src/workbook/globals.ts`'s own `sheetRanges`), every arithmetic/comparison/unary/percent operator and explicit parentheses, and function calls through both `PtgFunc` (fixed arity, resolved from a curated table of [MS-XLS]'s own Ftab grammar) and `PtgFuncVar` (variable arity, its own on-disk `cparams`) — see "Formula expressions" under Read-side gaps below for the exact boundary of what this does not resolve.
19
19
  - **Schema mapping** — `readXlsContent`/`readXls` (`src/content.ts`) as before, now also populating `ContentSheetCell.formula` wherever the Ptg reader above resolves it; `writeXlsContent`/`writeXls` (`src/write.ts`) the counterpart, taking a `ContentDocument`/`DocumentTree` of `kind: 'spreadsheet'` and producing genuine `.xls` bytes: a real BIFF8 `Workbook` stream (globals substream, one worksheet substream per sheet, `BoundSheet8.lbPlyPos` patched to each sheet's real byte offset once every substream's length is known) wrapped in a real [MS-CFB] compound file via `archive-codec`'s `writeCompoundFile`.
20
20
  - **Document metadata** — `title`/`subject`/`author`/`keywords`/`createdIso`/`modifiedIso` read from a `"\x05SummaryInformation"` stream when one is present, and written back to one whenever the input's metadata carries anything that stream can hold (see [Metadata](#metadata)).
21
- - **Cell decoration** — a cell's background fill (solid pattern only) and per-side borders, read from and written to `XF`'s trailing `CellXF` payload plus the workbook's own `Palette` record, in both directions and verified against real LibreOffice-produced BIFF8, not just this package's own round trip (see [Cell decoration](#cell-decoration)).
21
+ - **Cell decoration** — a cell's background fill (every named `FillPattern` value, solid and pattern alike) and per-side borders, read from and written to `XF`'s trailing `CellXF` payload plus the workbook's own `Palette` record, in both directions and verified against real LibreOffice-produced BIFF8, not just this package's own round trip (see [Cell decoration](#cell-decoration)).
22
22
  - **Print settings** — every field of `ContentSheetPrintSettings`: page size and orientation, all four margins, gridline and row/column-header printing, page order, print scale or fit-to-page counts, manual page breaks, the print range, and the repeated header rows and columns — read from and written to the nine worksheet-substream records and the two built-in defined names that carry them, in both directions and verified against real LibreOffice-produced BIFF8 (see [Print settings](#print-settings)).
23
23
  - **Cell alignment** — a cell's own horizontal (`left`/`center`/`right`/`justify`) and vertical (`top`/`middle`) alignment, read from and written to `XF`'s trailing `CellXF`/`StyleXF` payload's own leading word, in both directions and verified against real LibreOffice-produced BIFF8 (see [Cell alignment](#cell-alignment)).
24
24
 
@@ -26,7 +26,7 @@ Verified primarily by round trip (`src/write.test.ts`, plus a dedicated `test/wo
26
26
 
27
27
  ### Writer scope
28
28
 
29
- What `writeXlsContent`/`writeXls` cover: every `ContentCellValue` kind a real `.xls` can hold (`number`, `percentage`, `currency`, `boolean`, `date`, `time`, `dateTime`, `string`, `error`; an `empty` cell is written as a `Blank` record when it carries formatting and as nothing at all when it does not — see below), merged ranges (`colSpan`/`rowSpan`), row heights and hidden rows, column widths and hidden columns, multiple sheets, explicit and default number formats, a shared string table deduplicated across the whole workbook, every field of a sheet's own [print settings](#print-settings), a cell's own [alignment](#cell-alignment), and — see [Cell decoration](#cell-decoration) — a cell's own solid background fill and per-side borders, deduplicated across the workbook the same way number formats are. What it deliberately does not:
29
+ What `writeXlsContent`/`writeXls` cover: every `ContentCellValue` kind a real `.xls` can hold (`number`, `percentage`, `currency`, `boolean`, `date`, `time`, `dateTime`, `string`, `error`; an `empty` cell is written as a `Blank` record when it carries formatting and as nothing at all when it does not — see below), merged ranges (`colSpan`/`rowSpan`), row heights and hidden rows, column widths and hidden columns, multiple sheets, explicit and default number formats, a shared string table deduplicated across the whole workbook, every field of a sheet's own [print settings](#print-settings), a cell's own [alignment](#cell-alignment), and — see [Cell decoration](#cell-decoration) — a cell's own background fill (solid or a genuine two-colour pattern) and per-side borders, deduplicated across the workbook the same way number formats are. What it deliberately does not:
30
30
 
31
31
  | Not written | Why |
32
32
  | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -46,7 +46,7 @@ Column widths round-trip to the nearest pixel Excel's own integer-pixel-grid qua
46
46
  Each deliberate rather than overlooked:
47
47
 
48
48
  - **Formula expressions, mostly recovered.** A `Formula` record's compiled `Ptg` token stream (`src/biff/ptg.ts`) is walked and rebuilt into real formula text — literal operands, cell/range references (`$`-qualified, including 3D cross-sheet references resolved through `EXTERNSHEET` and a self-referencing `SupBook`), every arithmetic/comparison/unary/percent operator, explicit parentheses, and both fixed- and variable-arity function calls, resolved by name against [MS-XLS]'s own built-in function table (`src/biff/ptg-functions.ts`, covering the whole published table — [MS-XLS] 2.5.198.17 — cited to that table's own `iftab` index; PtgFunc's fixed argument count is a curated subset of it, since PtgFunc's own token carries no count and only a function [MS-XLS]'s grammar states a fixed, non-optional arity for is resolved through it, empirically confirmed against real LibreOffice-written BIFF8 rather than assumed from the grammar alone). Three constructs remain genuinely unresolved, each leaving `ContentSheetCell.formula` absent for that cell specifically rather than fabricating text: a **shared formula** (`PtgExp`, whose real expression lives in a separate `ShrFmla` record this reader does not yet join), an **array formula** (`PtgArray`, whose literal values live in a separate `PtgExtraArray` trailer this reader does not yet parse), and a **genuinely external workbook** reference (a `SupBook` naming another file, a DDE/OLE data source, or an add-in, rather than this same workbook) — each is real, meaningfully separate work, not an oversight. A defined name (`PtgName`/`PtgNameX`) and a natural-language "Elf" reference are likewise not resolved, for the same reason `Lbl` (defined names) is not read at all yet (see below).
49
- - **Cell decoration and alignment resolved for real; font still not.** `XF`'s trailing `CellXF` payload's fill pattern/colour and per-side border style/colour are read and resolved through the `Palette` record (or the default colour table when one is absent) — see [Cell decoration](#cell-decoration) for the full mapping, the fill-pattern-beyond-solid judgment call, and how this was verified against real LibreOffice-produced BIFF8. The same payload's leading word is resolved too — see [Cell alignment](#cell-alignment) for the full `alc`/`alcV` mapping. `Font` records are not read at all: `ContentSheetCell` has no cell-level font field, and `ooxml.js`'s xlsx reader makes the identical scope choice.
49
+ - **Cell decoration and alignment resolved for real; font still not.** `XF`'s trailing `CellXF` payload's fill pattern/colours and per-side border style/colour are read and resolved through the `Palette` record (or the default colour table when one is absent) — see [Cell decoration](#cell-decoration) for the full mapping, including every named pattern beyond solid, and how this was verified against real LibreOffice-produced BIFF8. The same payload's leading word is resolved too — see [Cell alignment](#cell-alignment) for the full `alc`/`alcV` mapping. `Font` records are not read at all: `ContentSheetCell` has no cell-level font field, and `ooxml.js`'s xlsx reader makes the identical scope choice.
50
50
  - **Print settings, resolved for real.** Every field of `ContentSheetPrintSettings` is read from the records that carry it, with Excel's own "Normal" preset standing in per field for whatever the file leaves unstated — see [Print settings](#print-settings) for the record map, the two of BIFF8's own conditional rules that decide how to read `Setup`, and the three things that genuinely do not come through.
51
51
  - **Not read at all:** charts, drawings and images, cell comments (`Note`/`Txo`), data validation, and conditional formatting. Defined names (`Lbl`) are read only for the two built-in ones a sheet's print range and repeated header bands live in ([Print settings](#print-settings)); a user-defined name has nowhere to land in `document-schema.js`'s spreadsheet model, so it is skipped.
52
52
  - **Encrypted workbooks** are refused rather than mis-read: a `FilePass` record means every record after it is ciphertext.
@@ -55,11 +55,11 @@ This package is wired into `documents.js`'s conversion registry (`xlsToPdf`/`pdf
55
55
 
56
56
  ## Cell decoration
57
57
 
58
- A cell's own solid background fill and per-side borders are read from and written to `XF`'s trailing `CellXF`/`StyleXF` payload ([MS-XLS] 2.4.353) and the workbook's own `Palette` record ([MS-XLS] 2.4.188), verified both by round trip and against a real, independent BIFF8 implementation — [ExaDev/documents.js#815](https://github.com/ExaDev/documents.js/issues/815) as a scoped chunk of that issue's own broader tracking, not a claim of closing it outright. `src/biff/xf-colors.ts` is the one place the payload's border/fill bit layout is packed or unpacked, shared by `workbook/globals.ts`'s read side and `biff/xf-writer.ts`'s write side, so the two directions cannot silently disagree on what a given byte means.
58
+ A cell's own background fill -- solid, or a genuine two-colour pattern -- and per-side borders are read from and written to `XF`'s trailing `CellXF`/`StyleXF` payload ([MS-XLS] 2.4.353) and the workbook's own `Palette` record ([MS-XLS] 2.4.188), verified both by round trip and against a real, independent BIFF8 implementation — [ExaDev/documents.js#815](https://github.com/ExaDev/documents.js/issues/815) as a scoped chunk of that issue's own broader tracking, not a claim of closing it outright. `src/biff/xf-colors.ts` is the one place the payload's border/fill bit layout is packed or unpacked, shared by `workbook/globals.ts`'s read side and `biff/xf-writer.ts`'s write side, so the two directions cannot silently disagree on what a given byte means.
59
59
 
60
60
  **Colour resolution.** A fill or border colour is a 7-bit `icv` index into BIFF8's own colour table ([MS-XLS] "Icv"): 0-7 name eight fixed built-in colours (this package's writer never emits one of these, per the spec's own "SHOULD NOT be ≤ 0x07"; the reader still resolves them, for a real third-party file that does), 8-63 index into either the workbook's own `Palette` record when one is present or a fixed 56-entry default table when it is not. The writer scans every distinct decoration colour a workbook's cells use before writing anything: when every one already matches the default table exactly, no `Palette` record is written at all, keeping an undecorated-adjacent file as minimal as it always was; the moment even one colour falls outside that table, a real 56-entry `Palette` record is minted, with every distinct colour the workbook actually uses (not only the non-default ones) assigned its own dedicated slot, so the whole table is self-consistent rather than a mix of "the file's own entries" and "the implicit default".
61
61
 
62
- **Fill patterns beyond solid a deliberate judgment call, not an oversight.** [MS-XLS]'s own `FillPattern` enumeration names nineteen patterns: no fill, solid, four grey shades, and stripe/crosshatch families. `ContentSheetCell.background` models exactly one flat colour, so only `FLSSOLID` maps onto it using the pattern's own foreground colour (`icvFore`), which [MS-XLS] itself documents as the only colour a solid fill actually renders ("If this value is 1, then only `icvFore` is rendered"). Every other pattern reads as no background at all. Approximating a 50% grey crosshatch or a diagonal stripe as its own foreground colour would misreport what the cell actually shows, so this reader leaves it unmapped rather than guessing; this package's own writer never emits anything but `FLSNULL`/`FLSSOLID` either, so a round trip never needs to invent a lossy pattern encoding on the way back out.
62
+ **Fill patterns beyond solid, resolved for real (ExaDev/documents.js#951).** [MS-XLS]/[MS-XLSB]'s own `FillPattern` enumeration names nineteen values: no fill, solid, and seventeen genuine two-colour patterns -- five grey shades (`FLSMEDGRAY`/`FLSDKGRAY`/`FLSLTGRAY`/`FLSGRAY125`/`FLSGRAY0625`) and the stripe/crosshatch families. `ContentSheetCell.background` is `document-schema.js`'s own `ContentCellFill`: a discriminated `'solid'`/`'pattern'` shape, `'pattern'` naming a closed `ContentCellPatternType` vocabulary spanning both this format's own `FillPattern` and WordprocessingML's `ST_Shd` (see that schema's own top comment for the full citation). `FLSSOLID` resolves to a `'solid'` fill of the pattern's own foreground colour (`icvFore`), which [MS-XLS] itself documents as the only colour a solid fill actually renders ("If this value is 1, then only `icvFore` is rendered") -- `icvBack` carries no meaning for it and is never consulted. Every other named `FillPattern` value resolves to a real `'pattern'` fill via `xf-colors.ts`'s own `FILL_PATTERN_TO_PATTERN_TYPE`, an exact 1:1 mapping onto the identical ECMA-376 `ST_PatternType` token name (`FLSMEDGRAY` through `FLSGRAY0625`, values 0x02-0x12, onto `mediumGray` through `gray0625` in that order) -- carrying whichever of the pattern's own foreground (`icvFore`, drawn as the pattern's strokes) and background (`icvBack`, the colour its gaps show through) colours actually resolve to a fixed RGB value; either may be an "Automatic" icv this package cannot express and is left unstated, matching `ContentCellFillSchema`'s own "a colour can defer instead of asserting" convention. A reserved `FillPattern` value beyond 0x12 still reads as no background at all, there being no pattern name to give it. Writing a `'pattern'` fill states its own colours (automatic where the fill leaves one unstated) under the `FillPattern` value the same table's inverse names for it; a WordprocessingML-only pattern name (the `percentN` family, or a stripe/cross member `ST_Shd` names but `ST_PatternType` does not) throws `BiffWriteError` rather than writing the wrong pattern or silently dropping it.
63
63
 
64
64
  **Borders.** Each of a cell's four sides carries its own [MS-XLS] `BorderStyle` line-style token and colour, mapped onto `ContentBorder`'s `widthPt`/`style` pair the same way `ooxml.js`'s own `typed/xlsx/styles.ts` maps xlsx's border tokens: four named weights — hair/thin/medium/thick, at 0.5/0.75/1.5/2.25pt, derived from Excel's own documented 96-DPI rendering and held once in [`document-schema.js`](../document-schema.js/README.md)'s own `border-weight` module, which this package and `ooxml.js` both import rather than each keeping a copy of it — crossed with a pattern (solid/dashed/dotted/double); the dash-family tokens (`dashDot`, `dashDotDot`, and their medium/slant variants) collapse to `'dashed'`, the closest `ContentStrokeStyle` member, exactly as `ooxml.js`'s equivalent table does for xlsx's own dash tokens. Diagonal borders (`dgDiag`/`grbitDiag`) are out of scope — `ContentCellBordersSchema` has no diagonal member — and are always read as absent, always written as none.
65
65
 
@@ -67,7 +67,9 @@ A cell's own solid background fill and per-side borders are read from and writte
67
67
 
68
68
  The decorated-blank case was checked the same way, in both directions and against the same implementation: a `.fods` whose one styled cell has a fill and four borders but no value converts to a `.xls` in which LibreOffice writes a real `Blank` record, and this reader recovers that cell's fill colour and all four border colours exactly; a `.xls` this package writes for the equivalent `empty` cell converts back to a `.fods` in which LibreOffice recovers a valueless cell carrying the same `fo:background-color` and `fo:border` colours — at its own 0.74pt rendering of the `thin` weight, per the note above.
69
69
 
70
- **Decoration on a cell with no value.** A cell can be empty and still have something to show, and BIFF8 says so with a `Blank` record ([MS-XLS] 2.4.20) — a cell header naming an `XF` and nothing else, written precisely because that `XF` carries a fill or a border. Both directions honour it: a `Blank` or `MulBlank` whose `XF` resolves to real decoration is read as an `empty`-kind cell carrying that decoration rather than dropped, and an `empty` cell carrying a background or a border is written back as a `Blank` record pointing at an `XF` encoding it. An empty cell with no decoration is still written as nothing at all and still read as absent, which is what keeps `ContentSheet`'s cell array sparse; "decoration this reader can express" is the same test the value-cell path applies, so a fill pattern beyond solid or an unresolvable colour leaves a blank cell dropped exactly as before.
70
+ A genuine two-colour pattern fill was not checked against LibreOffice in either direction: ODF's own `style:table-cell-properties` has no attribute for a two-colour pattern fill for a hand-authored `.fods` to state one through, so there was no third-party bytes to compare against. Reading and writing every named `FillPattern` value is instead pinned against bytes hand-built from [MS-XLS]/[MS-XLSB]'s own enumeration (`biff/xf-colors.test.ts`) and against a whole-document round trip through this package's own reader and writer (`write.test.ts`).
71
+
72
+ **Decoration on a cell with no value.** A cell can be empty and still have something to show, and BIFF8 says so with a `Blank` record ([MS-XLS] 2.4.20) — a cell header naming an `XF` and nothing else, written precisely because that `XF` carries a fill or a border. Both directions honour it: a `Blank` or `MulBlank` whose `XF` resolves to real decoration is read as an `empty`-kind cell carrying that decoration rather than dropped, and an `empty` cell carrying a background or a border is written back as a `Blank` record pointing at an `XF` encoding it. An empty cell with no decoration is still written as nothing at all and still read as absent, which is what keeps `ContentSheet`'s cell array sparse; "decoration this reader can express" is the same test the value-cell path applies, so a reserved `FillPattern` value with no pattern name, or an unresolvable colour on every field a cell states, leaves a blank cell dropped exactly as before.
71
73
 
72
74
  A per-cell font remains out of scope in both directions — see [Read-side gaps](#read-side-gaps) and [Writer scope](#writer-scope) above. The payload's leading word, once similarly out of scope, is now [Cell alignment](#cell-alignment) below.
73
75
 
@@ -3,8 +3,32 @@ let document_schema_js = require("document-schema.js");
3
3
  //#region src/biff/xf-colors.ts
4
4
  /** FLSNULL: no fill pattern -- the cell's fill colour fields carry no meaning. */
5
5
  const FILL_PATTERN_NONE = 0;
6
- /** FLSSOLID: a solid fill, the only pattern this package maps onto ContentSheetCell.background -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). Every other pattern (50%/75%/25% gray, the stripe and crosshatch families, ...) is a real information-loss case this reader does not approximate: see resolveFillBackground below. */
6
+ /** FLSSOLID: a solid fill -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). */
7
7
  const FILL_PATTERN_SOLID = 1;
8
+ /**
9
+ * Every other named FillPattern value ([MS-XLS]/[MS-XLSB] "FillPattern" enumeration, 0x02-0x12), mapped onto the ContentCellPatternType name document-schema.js's own ContentCellPatternTypeSchema gives that same ECMA-376 ST_PatternType token verbatim -- this is the identical vocabulary, values 0x02 (FLSMEDGRAY, "50% gray") through 0x12 (FLSGRAY0625, "6.25% gray") mapping onto ST_PatternType's mediumGray/darkGray/lightGray/darkHorizontal/darkVertical/darkDown/darkUp/darkGrid/darkTrellis/lightHorizontal/lightVertical/lightDown/lightUp/lightGrid/lightTrellis/gray125/gray0625 in that exact order (see ContentCellPatternTypeSchema's own top comment for the full citation). Unlike doc-codec's Ipat table, every value in this contiguous range names a real pattern -- there is no ipatNil/ipatPctNew*-style gap to skip.
10
+ */
11
+ const FILL_PATTERN_TO_PATTERN_TYPE = {
12
+ 2: "mediumGray",
13
+ 3: "darkGray",
14
+ 4: "lightGray",
15
+ 5: "darkHorizontal",
16
+ 6: "darkVertical",
17
+ 7: "darkDown",
18
+ 8: "darkUp",
19
+ 9: "darkGrid",
20
+ 10: "darkTrellis",
21
+ 11: "lightHorizontal",
22
+ 12: "lightVertical",
23
+ 13: "lightDown",
24
+ 14: "lightUp",
25
+ 15: "lightGrid",
26
+ 16: "lightTrellis",
27
+ 17: "gray125",
28
+ 18: "gray0625"
29
+ };
30
+ /** The inverse of FILL_PATTERN_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 SpreadsheetML half of the shared vocabulary is exactly FILL_PATTERN_TO_PATTERN_TYPE's own value set -- the WordprocessingML-only members (the percentN family and the stripe/cross families ST_Shd names) are absent, FillPattern having no equivalent for them at all. */
31
+ const PATTERN_TYPE_TO_FILL_PATTERN = new Map(Object.entries(FILL_PATTERN_TO_PATTERN_TYPE).map(([fls, patternType]) => [patternType, Number(fls)]));
8
32
  const ALC_GENERAL = 0;
9
33
  const ALC_LEFT = 1;
10
34
  const ALC_CENTER = 2;
@@ -248,10 +272,30 @@ function borderStyleTokenFor(border) {
248
272
  case void 0: return SOLID_BORDER_STYLE[(0, document_schema_js.borderWeightForWidthPt)(border.widthPt)];
249
273
  }
250
274
  }
251
- /** A solid fill's own foreground colour resolved to a real background, or undefined for every other FillPattern value -- FLSNULL (no fill at all) and every pattern beyond solid (50%/75%/25% gray, the stripe and crosshatch family) alike. A non-solid pattern is a real information-loss case rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its foreground colour alone would misrepresent what the cell actually shows -- see xls-codec's README for this package's own stated judgment call. */
252
- function resolveFillBackground(fillPattern, foregroundIcv, palette) {
253
- if (fillPattern !== 1) return;
254
- return resolveIcvColor(foregroundIcv, palette);
275
+ /**
276
+ * Resolves a cell's own FillPattern/icvFore/icvBack triple to a real ContentCellFill (ExaDev/documents.js#951), or undefined for FLSNULL (no fill at all), for a reserved/unrecognised FillPattern value, or for FLSSOLID when its own icvFore does not resolve to a fixed RGB value (an "Automatic" or otherwise unmapped icv, which leaves nothing to state a solid fill's colour as).
277
+ *
278
+ * FLSSOLID resolves to a 'solid' fill of icvFore alone -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF), so icvBack carries no meaning for it and is never consulted. Every other named FillPattern resolves to a real 'pattern' fill via FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of icvFore/icvBack resolves to a real colour (either may be an "Automatic" icv this package cannot express as a fixed RGB value, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention).
279
+ */
280
+ function resolveFillBackground(fillPattern, foregroundIcv, backgroundIcv, palette) {
281
+ if (fillPattern === 0) return;
282
+ if (fillPattern === 1) {
283
+ const color = resolveIcvColor(foregroundIcv, palette);
284
+ return color === void 0 ? void 0 : {
285
+ kind: "solid",
286
+ color
287
+ };
288
+ }
289
+ const patternType = FILL_PATTERN_TO_PATTERN_TYPE[fillPattern];
290
+ if (patternType === void 0) return;
291
+ const foregroundColor = resolveIcvColor(foregroundIcv, palette);
292
+ const backgroundColor = resolveIcvColor(backgroundIcv, palette);
293
+ return {
294
+ kind: "pattern",
295
+ patternType,
296
+ ...foregroundColor !== void 0 ? { foregroundColor } : {},
297
+ ...backgroundColor !== void 0 ? { backgroundColor } : {}
298
+ };
255
299
  }
256
300
  const UNDECORATED_EDGE = {
257
301
  style: 0,
@@ -261,6 +305,7 @@ const UNDECORATED_EDGE = {
261
305
  const UNDECORATED_XF_FIELDS = {
262
306
  fillPattern: 0,
263
307
  fillForegroundIcv: 64,
308
+ fillBackgroundIcv: 65,
264
309
  left: UNDECORATED_EDGE,
265
310
  right: UNDECORATED_EDGE,
266
311
  top: UNDECORATED_EDGE,
@@ -288,6 +333,7 @@ function unpackXfDecoration(word2, word3, word4) {
288
333
  return {
289
334
  fillPattern: word3 >>> 26 & 63,
290
335
  fillForegroundIcv: word4 & 127,
336
+ fillBackgroundIcv: word4 >>> 7 & 127,
291
337
  left: {
292
338
  style: dgLeft,
293
339
  icv: icvLeft
@@ -313,10 +359,14 @@ function unpackXfDecoration(word2, word3, word4) {
313
359
  */
314
360
  function packXfDecorationWords(decoration = UNDECORATED_XF_FIELDS) {
315
361
  const { left, right, top, bottom } = decoration;
362
+ const word2 = left.style & 15 | (right.style & 15) << 4 | (top.style & 15) << 8 | (bottom.style & 15) << 12 | (left.icv & 127) << 16 | (right.icv & 127) << 23 | 0;
363
+ const word3 = top.icv & 127 | (bottom.icv & 127) << 7 | 0 | (decoration.fillPattern & 63) << 26;
364
+ const icvFore = decoration.fillPattern === 0 ? 64 : decoration.fillForegroundIcv;
365
+ const icvBack = decoration.fillPattern === 0 || decoration.fillPattern === 1 ? 65 : decoration.fillBackgroundIcv;
316
366
  return {
317
- word2: left.style & 15 | (right.style & 15) << 4 | (top.style & 15) << 8 | (bottom.style & 15) << 12 | (left.icv & 127) << 16 | (right.icv & 127) << 23 | 0,
318
- word3: top.icv & 127 | (bottom.icv & 127) << 7 | 0 | (decoration.fillPattern & 63) << 26,
319
- word4: (decoration.fillPattern === 1 ? decoration.fillForegroundIcv : 64) & 127 | 8320
367
+ word2,
368
+ word3,
369
+ word4: icvFore & 127 | (icvBack & 127) << 7
320
370
  };
321
371
  }
322
372
  /** LongRGB: red, green, blue, then a reserved byte that MUST be 0 -- one entry of a Palette record's rgColor array, or of the fixed-length buffer this package's own writer emits. */
@@ -358,6 +408,7 @@ exports.ICV_AUTOMATIC_BACKGROUND = ICV_AUTOMATIC_BACKGROUND;
358
408
  exports.ICV_AUTOMATIC_FOREGROUND = ICV_AUTOMATIC_FOREGROUND;
359
409
  exports.PALETTE_BASE_ICV = PALETTE_BASE_ICV;
360
410
  exports.PALETTE_ENTRY_COUNT = PALETTE_ENTRY_COUNT;
411
+ exports.PATTERN_TYPE_TO_FILL_PATTERN = PATTERN_TYPE_TO_FILL_PATTERN;
361
412
  exports.UNDECORATED_XF_FIELDS = UNDECORATED_XF_FIELDS;
362
413
  exports.borderStyleTokenFor = borderStyleTokenFor;
363
414
  exports.horizAlignTokenFor = horizAlignTokenFor;
@@ -1,2 +1,2 @@
1
- import { A as readLongRgbColor, C as XfAlignmentFields, D as horizAlignTokenFor, E as borderStyleTokenFor, F as resolveVerticalAlignment, I as unpackXfAlignment, L as unpackXfDecoration, M as resolveFillBackground, N as resolveHorizontalAlignment, O as longRgbBytesOf, P as resolveIcvColor, R as vertAlignTokenFor, S as UNDECORATED_XF_FIELDS, T as XfDecorationFields, _ as FILL_PATTERN_SOLID, a as BORDER_STYLE_DOUBLE, b as PALETTE_BASE_ICV, c as BORDER_STYLE_MEDIUM_DASHDOT, d as BORDER_STYLE_NONE, f as BORDER_STYLE_SLANT_DASHDOT, g as FILL_PATTERN_NONE, h as DEFAULT_PALETTE_HEX_TO_ICV, i as BORDER_STYLE_DOTTED, j as resolveBorderEdge, k as packXfDecorationWords, l as BORDER_STYLE_MEDIUM_DASHDOTDOT, m as BORDER_STYLE_THIN, n as BORDER_STYLE_DASHDOTDOT, o as BORDER_STYLE_HAIR, p as BORDER_STYLE_THICK, r as BORDER_STYLE_DASHED, s as BORDER_STYLE_MEDIUM, t as BORDER_STYLE_DASHDOT, u as BORDER_STYLE_MEDIUM_DASHED, v as ICV_AUTOMATIC_BACKGROUND, w as XfBorderEdge, x as PALETTE_ENTRY_COUNT, y as ICV_AUTOMATIC_FOREGROUND } from "../xf-colors-CehHZtBy.cjs";
2
- export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, UNDECORATED_XF_FIELDS, XfAlignmentFields, XfBorderEdge, XfDecorationFields, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
1
+ import { A as packXfDecorationWords, C as UNDECORATED_XF_FIELDS, D as borderStyleTokenFor, E as XfDecorationFields, F as resolveIcvColor, I as resolveVerticalAlignment, L as unpackXfAlignment, M as resolveBorderEdge, N as resolveFillBackground, O as horizAlignTokenFor, P as resolveHorizontalAlignment, R as unpackXfDecoration, S as PATTERN_TYPE_TO_FILL_PATTERN, T as XfBorderEdge, _ as FILL_PATTERN_SOLID, a as BORDER_STYLE_DOUBLE, b as PALETTE_BASE_ICV, c as BORDER_STYLE_MEDIUM_DASHDOT, d as BORDER_STYLE_NONE, f as BORDER_STYLE_SLANT_DASHDOT, g as FILL_PATTERN_NONE, h as DEFAULT_PALETTE_HEX_TO_ICV, i as BORDER_STYLE_DOTTED, j as readLongRgbColor, k as longRgbBytesOf, l as BORDER_STYLE_MEDIUM_DASHDOTDOT, m as BORDER_STYLE_THIN, n as BORDER_STYLE_DASHDOTDOT, o as BORDER_STYLE_HAIR, p as BORDER_STYLE_THICK, r as BORDER_STYLE_DASHED, s as BORDER_STYLE_MEDIUM, t as BORDER_STYLE_DASHDOT, u as BORDER_STYLE_MEDIUM_DASHED, v as ICV_AUTOMATIC_BACKGROUND, w as XfAlignmentFields, x as PALETTE_ENTRY_COUNT, y as ICV_AUTOMATIC_FOREGROUND, z as vertAlignTokenFor } from "../xf-colors-BB5MKq6R.cjs";
2
+ export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, PATTERN_TYPE_TO_FILL_PATTERN, UNDECORATED_XF_FIELDS, XfAlignmentFields, XfBorderEdge, XfDecorationFields, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
@@ -1,2 +1,2 @@
1
- import { A as readLongRgbColor, C as XfAlignmentFields, D as horizAlignTokenFor, E as borderStyleTokenFor, F as resolveVerticalAlignment, I as unpackXfAlignment, L as unpackXfDecoration, M as resolveFillBackground, N as resolveHorizontalAlignment, O as longRgbBytesOf, P as resolveIcvColor, R as vertAlignTokenFor, S as UNDECORATED_XF_FIELDS, T as XfDecorationFields, _ as FILL_PATTERN_SOLID, a as BORDER_STYLE_DOUBLE, b as PALETTE_BASE_ICV, c as BORDER_STYLE_MEDIUM_DASHDOT, d as BORDER_STYLE_NONE, f as BORDER_STYLE_SLANT_DASHDOT, g as FILL_PATTERN_NONE, h as DEFAULT_PALETTE_HEX_TO_ICV, i as BORDER_STYLE_DOTTED, j as resolveBorderEdge, k as packXfDecorationWords, l as BORDER_STYLE_MEDIUM_DASHDOTDOT, m as BORDER_STYLE_THIN, n as BORDER_STYLE_DASHDOTDOT, o as BORDER_STYLE_HAIR, p as BORDER_STYLE_THICK, r as BORDER_STYLE_DASHED, s as BORDER_STYLE_MEDIUM, t as BORDER_STYLE_DASHDOT, u as BORDER_STYLE_MEDIUM_DASHED, v as ICV_AUTOMATIC_BACKGROUND, w as XfBorderEdge, x as PALETTE_ENTRY_COUNT, y as ICV_AUTOMATIC_FOREGROUND } from "../xf-colors-CpykR3B9.js";
2
- export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, UNDECORATED_XF_FIELDS, XfAlignmentFields, XfBorderEdge, XfDecorationFields, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
1
+ import { A as packXfDecorationWords, C as UNDECORATED_XF_FIELDS, D as borderStyleTokenFor, E as XfDecorationFields, F as resolveIcvColor, I as resolveVerticalAlignment, L as unpackXfAlignment, M as resolveBorderEdge, N as resolveFillBackground, O as horizAlignTokenFor, P as resolveHorizontalAlignment, R as unpackXfDecoration, S as PATTERN_TYPE_TO_FILL_PATTERN, T as XfBorderEdge, _ as FILL_PATTERN_SOLID, a as BORDER_STYLE_DOUBLE, b as PALETTE_BASE_ICV, c as BORDER_STYLE_MEDIUM_DASHDOT, d as BORDER_STYLE_NONE, f as BORDER_STYLE_SLANT_DASHDOT, g as FILL_PATTERN_NONE, h as DEFAULT_PALETTE_HEX_TO_ICV, i as BORDER_STYLE_DOTTED, j as readLongRgbColor, k as longRgbBytesOf, l as BORDER_STYLE_MEDIUM_DASHDOTDOT, m as BORDER_STYLE_THIN, n as BORDER_STYLE_DASHDOTDOT, o as BORDER_STYLE_HAIR, p as BORDER_STYLE_THICK, r as BORDER_STYLE_DASHED, s as BORDER_STYLE_MEDIUM, t as BORDER_STYLE_DASHDOT, u as BORDER_STYLE_MEDIUM_DASHED, v as ICV_AUTOMATIC_BACKGROUND, w as XfAlignmentFields, x as PALETTE_ENTRY_COUNT, y as ICV_AUTOMATIC_FOREGROUND, z as vertAlignTokenFor } from "../xf-colors--5oxSeI1.js";
2
+ export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, PATTERN_TYPE_TO_FILL_PATTERN, UNDECORATED_XF_FIELDS, XfAlignmentFields, XfBorderEdge, XfDecorationFields, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
@@ -2,8 +2,32 @@ import { BORDER_WIDTH_PT, borderWeightForWidthPt, colorToRgbHex, dashedBorderWei
2
2
  //#region src/biff/xf-colors.ts
3
3
  /** FLSNULL: no fill pattern -- the cell's fill colour fields carry no meaning. */
4
4
  const FILL_PATTERN_NONE = 0;
5
- /** FLSSOLID: a solid fill, the only pattern this package maps onto ContentSheetCell.background -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). Every other pattern (50%/75%/25% gray, the stripe and crosshatch families, ...) is a real information-loss case this reader does not approximate: see resolveFillBackground below. */
5
+ /** FLSSOLID: a solid fill -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). */
6
6
  const FILL_PATTERN_SOLID = 1;
7
+ /**
8
+ * Every other named FillPattern value ([MS-XLS]/[MS-XLSB] "FillPattern" enumeration, 0x02-0x12), mapped onto the ContentCellPatternType name document-schema.js's own ContentCellPatternTypeSchema gives that same ECMA-376 ST_PatternType token verbatim -- this is the identical vocabulary, values 0x02 (FLSMEDGRAY, "50% gray") through 0x12 (FLSGRAY0625, "6.25% gray") mapping onto ST_PatternType's mediumGray/darkGray/lightGray/darkHorizontal/darkVertical/darkDown/darkUp/darkGrid/darkTrellis/lightHorizontal/lightVertical/lightDown/lightUp/lightGrid/lightTrellis/gray125/gray0625 in that exact order (see ContentCellPatternTypeSchema's own top comment for the full citation). Unlike doc-codec's Ipat table, every value in this contiguous range names a real pattern -- there is no ipatNil/ipatPctNew*-style gap to skip.
9
+ */
10
+ const FILL_PATTERN_TO_PATTERN_TYPE = {
11
+ 2: "mediumGray",
12
+ 3: "darkGray",
13
+ 4: "lightGray",
14
+ 5: "darkHorizontal",
15
+ 6: "darkVertical",
16
+ 7: "darkDown",
17
+ 8: "darkUp",
18
+ 9: "darkGrid",
19
+ 10: "darkTrellis",
20
+ 11: "lightHorizontal",
21
+ 12: "lightVertical",
22
+ 13: "lightDown",
23
+ 14: "lightUp",
24
+ 15: "lightGrid",
25
+ 16: "lightTrellis",
26
+ 17: "gray125",
27
+ 18: "gray0625"
28
+ };
29
+ /** The inverse of FILL_PATTERN_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 SpreadsheetML half of the shared vocabulary is exactly FILL_PATTERN_TO_PATTERN_TYPE's own value set -- the WordprocessingML-only members (the percentN family and the stripe/cross families ST_Shd names) are absent, FillPattern having no equivalent for them at all. */
30
+ const PATTERN_TYPE_TO_FILL_PATTERN = new Map(Object.entries(FILL_PATTERN_TO_PATTERN_TYPE).map(([fls, patternType]) => [patternType, Number(fls)]));
7
31
  const ALC_GENERAL = 0;
8
32
  const ALC_LEFT = 1;
9
33
  const ALC_CENTER = 2;
@@ -247,10 +271,30 @@ function borderStyleTokenFor(border) {
247
271
  case void 0: return SOLID_BORDER_STYLE[borderWeightForWidthPt(border.widthPt)];
248
272
  }
249
273
  }
250
- /** A solid fill's own foreground colour resolved to a real background, or undefined for every other FillPattern value -- FLSNULL (no fill at all) and every pattern beyond solid (50%/75%/25% gray, the stripe and crosshatch family) alike. A non-solid pattern is a real information-loss case rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its foreground colour alone would misrepresent what the cell actually shows -- see xls-codec's README for this package's own stated judgment call. */
251
- function resolveFillBackground(fillPattern, foregroundIcv, palette) {
252
- if (fillPattern !== 1) return;
253
- return resolveIcvColor(foregroundIcv, palette);
274
+ /**
275
+ * Resolves a cell's own FillPattern/icvFore/icvBack triple to a real ContentCellFill (ExaDev/documents.js#951), or undefined for FLSNULL (no fill at all), for a reserved/unrecognised FillPattern value, or for FLSSOLID when its own icvFore does not resolve to a fixed RGB value (an "Automatic" or otherwise unmapped icv, which leaves nothing to state a solid fill's colour as).
276
+ *
277
+ * FLSSOLID resolves to a 'solid' fill of icvFore alone -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF), so icvBack carries no meaning for it and is never consulted. Every other named FillPattern resolves to a real 'pattern' fill via FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of icvFore/icvBack resolves to a real colour (either may be an "Automatic" icv this package cannot express as a fixed RGB value, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention).
278
+ */
279
+ function resolveFillBackground(fillPattern, foregroundIcv, backgroundIcv, palette) {
280
+ if (fillPattern === 0) return;
281
+ if (fillPattern === 1) {
282
+ const color = resolveIcvColor(foregroundIcv, palette);
283
+ return color === void 0 ? void 0 : {
284
+ kind: "solid",
285
+ color
286
+ };
287
+ }
288
+ const patternType = FILL_PATTERN_TO_PATTERN_TYPE[fillPattern];
289
+ if (patternType === void 0) return;
290
+ const foregroundColor = resolveIcvColor(foregroundIcv, palette);
291
+ const backgroundColor = resolveIcvColor(backgroundIcv, palette);
292
+ return {
293
+ kind: "pattern",
294
+ patternType,
295
+ ...foregroundColor !== void 0 ? { foregroundColor } : {},
296
+ ...backgroundColor !== void 0 ? { backgroundColor } : {}
297
+ };
254
298
  }
255
299
  const UNDECORATED_EDGE = {
256
300
  style: 0,
@@ -260,6 +304,7 @@ const UNDECORATED_EDGE = {
260
304
  const UNDECORATED_XF_FIELDS = {
261
305
  fillPattern: 0,
262
306
  fillForegroundIcv: 64,
307
+ fillBackgroundIcv: 65,
263
308
  left: UNDECORATED_EDGE,
264
309
  right: UNDECORATED_EDGE,
265
310
  top: UNDECORATED_EDGE,
@@ -287,6 +332,7 @@ function unpackXfDecoration(word2, word3, word4) {
287
332
  return {
288
333
  fillPattern: word3 >>> 26 & 63,
289
334
  fillForegroundIcv: word4 & 127,
335
+ fillBackgroundIcv: word4 >>> 7 & 127,
290
336
  left: {
291
337
  style: dgLeft,
292
338
  icv: icvLeft
@@ -312,10 +358,14 @@ function unpackXfDecoration(word2, word3, word4) {
312
358
  */
313
359
  function packXfDecorationWords(decoration = UNDECORATED_XF_FIELDS) {
314
360
  const { left, right, top, bottom } = decoration;
361
+ const word2 = left.style & 15 | (right.style & 15) << 4 | (top.style & 15) << 8 | (bottom.style & 15) << 12 | (left.icv & 127) << 16 | (right.icv & 127) << 23 | 0;
362
+ const word3 = top.icv & 127 | (bottom.icv & 127) << 7 | 0 | (decoration.fillPattern & 63) << 26;
363
+ const icvFore = decoration.fillPattern === 0 ? 64 : decoration.fillForegroundIcv;
364
+ const icvBack = decoration.fillPattern === 0 || decoration.fillPattern === 1 ? 65 : decoration.fillBackgroundIcv;
315
365
  return {
316
- word2: left.style & 15 | (right.style & 15) << 4 | (top.style & 15) << 8 | (bottom.style & 15) << 12 | (left.icv & 127) << 16 | (right.icv & 127) << 23 | 0,
317
- word3: top.icv & 127 | (bottom.icv & 127) << 7 | 0 | (decoration.fillPattern & 63) << 26,
318
- word4: (decoration.fillPattern === 1 ? decoration.fillForegroundIcv : 64) & 127 | 8320
366
+ word2,
367
+ word3,
368
+ word4: icvFore & 127 | (icvBack & 127) << 7
319
369
  };
320
370
  }
321
371
  /** LongRGB: red, green, blue, then a reserved byte that MUST be 0 -- one entry of a Palette record's rgColor array, or of the fixed-length buffer this package's own writer emits. */
@@ -336,4 +386,4 @@ function longRgbBytesOf(color) {
336
386
  ];
337
387
  }
338
388
  //#endregion
339
- export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, UNDECORATED_XF_FIELDS, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
389
+ export { BORDER_STYLE_DASHDOT, BORDER_STYLE_DASHDOTDOT, BORDER_STYLE_DASHED, BORDER_STYLE_DOTTED, BORDER_STYLE_DOUBLE, BORDER_STYLE_HAIR, BORDER_STYLE_MEDIUM, BORDER_STYLE_MEDIUM_DASHDOT, BORDER_STYLE_MEDIUM_DASHDOTDOT, BORDER_STYLE_MEDIUM_DASHED, BORDER_STYLE_NONE, BORDER_STYLE_SLANT_DASHDOT, BORDER_STYLE_THICK, BORDER_STYLE_THIN, DEFAULT_PALETTE_HEX_TO_ICV, FILL_PATTERN_NONE, FILL_PATTERN_SOLID, ICV_AUTOMATIC_BACKGROUND, ICV_AUTOMATIC_FOREGROUND, PALETTE_BASE_ICV, PALETTE_ENTRY_COUNT, PATTERN_TYPE_TO_FILL_PATTERN, UNDECORATED_XF_FIELDS, borderStyleTokenFor, horizAlignTokenFor, longRgbBytesOf, packXfDecorationWords, readLongRgbColor, resolveBorderEdge, resolveFillBackground, resolveHorizontalAlignment, resolveIcvColor, resolveVerticalAlignment, unpackXfAlignment, unpackXfDecoration, vertAlignTokenFor };
@@ -1,4 +1,4 @@
1
- import { T as XfDecorationFields } from "../xf-colors-CehHZtBy.cjs";
1
+ import { E as XfDecorationFields } from "../xf-colors-BB5MKq6R.cjs";
2
2
  import { Alignment, Color } from "document-schema.js";
3
3
  //#region src/biff/xf-writer.d.ts
4
4
  /** Writes one cell-format XF record (fStyle=0): ifnt/ifmt as given, ixfParent pointing at the Normal cell-style XF (index 0), a CellXF payload carrying `alignment`/`verticalAlignment`/`decoration`'s own fields -- general alignment, bottom vertical alignment, and no fill/border (the same bytes this always wrote before either existed) for whatever is omitted. Twenty bytes total ([MS-XLS] 2.4.353). */
@@ -1,4 +1,4 @@
1
- import { T as XfDecorationFields } from "../xf-colors-CpykR3B9.js";
1
+ import { E as XfDecorationFields } from "../xf-colors--5oxSeI1.js";
2
2
  import { Alignment, Color } from "document-schema.js";
3
3
  //#region src/biff/xf-writer.d.ts
4
4
  /** Writes one cell-format XF record (fStyle=0): ifnt/ifmt as given, ixfParent pointing at the Normal cell-style XF (index 0), a CellXF payload carrying `alignment`/`verticalAlignment`/`decoration`'s own fields -- general alignment, bottom vertical alignment, and no fill/border (the same bytes this always wrote before either existed) for whatever is omitted. Twenty bytes total ([MS-XLS] 2.4.353). */
package/dist/content.cjs CHANGED
@@ -192,14 +192,14 @@ function mapCell(cell, globals) {
192
192
  return mapped;
193
193
  }
194
194
  /**
195
- * A cell's own resolved fill colour, or undefined for a genuinely unfilled cell AND for every fill pattern beyond solid.
195
+ * A cell's own resolved background fill (ExaDev/documents.js#951), or undefined for a genuinely unfilled cell and for a reserved/unrecognised FillPattern value.
196
196
  *
197
- * A non-solid pattern (the 50%/75%/25% gray shades, the stripe and crosshatch family [MS-XLS]'s FillPattern enumeration also names) is a deliberate, permanent gap rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its own foreground colour alone would misreport what the cell actually shows -- see xls-codec's README, "Cell decoration".
197
+ * A solid fill resolves to a 'solid' ContentCellFill of its own foreground colour; every other named FillPattern -- the 50%/75%/25% gray shades, the stripe and crosshatch family -- resolves to a real 'pattern' fill via xf-colors.ts's own FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of the pattern's foreground/background colours actually resolve to a fixed RGB value. See xls-codec's README, "Cell decoration".
198
198
  */
199
199
  function backgroundOf(globals, xfIndex) {
200
200
  const format = globals.cellFormats[xfIndex];
201
201
  if (format === void 0) return;
202
- return require_biff_xf_colors.resolveFillBackground(format.decoration.fillPattern, format.decoration.fillForegroundIcv, globals.palette);
202
+ return require_biff_xf_colors.resolveFillBackground(format.decoration.fillPattern, format.decoration.fillForegroundIcv, format.decoration.fillBackgroundIcv, globals.palette);
203
203
  }
204
204
  /** A cell's own resolved horizontal/vertical alignment -- already the exact Alignment/verticalAlignment members (or undefined) globals.ts's readCellFormat resolved through xf-colors.ts's unpackXfAlignment, so this is a lookup rather than a further resolution step, mirroring backgroundOf/bordersOf's own shape. Both fields undefined for a cell whose XF resolves to no CellFormat at all (an out-of-range xfIndex), matching every other resolveXOf helper's behaviour in that case. */
205
205
  function alignmentOf(globals, xfIndex) {
package/dist/content.js CHANGED
@@ -191,14 +191,14 @@ function mapCell(cell, globals) {
191
191
  return mapped;
192
192
  }
193
193
  /**
194
- * A cell's own resolved fill colour, or undefined for a genuinely unfilled cell AND for every fill pattern beyond solid.
194
+ * A cell's own resolved background fill (ExaDev/documents.js#951), or undefined for a genuinely unfilled cell and for a reserved/unrecognised FillPattern value.
195
195
  *
196
- * A non-solid pattern (the 50%/75%/25% gray shades, the stripe and crosshatch family [MS-XLS]'s FillPattern enumeration also names) is a deliberate, permanent gap rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its own foreground colour alone would misreport what the cell actually shows -- see xls-codec's README, "Cell decoration".
196
+ * A solid fill resolves to a 'solid' ContentCellFill of its own foreground colour; every other named FillPattern -- the 50%/75%/25% gray shades, the stripe and crosshatch family -- resolves to a real 'pattern' fill via xf-colors.ts's own FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of the pattern's foreground/background colours actually resolve to a fixed RGB value. See xls-codec's README, "Cell decoration".
197
197
  */
198
198
  function backgroundOf(globals, xfIndex) {
199
199
  const format = globals.cellFormats[xfIndex];
200
200
  if (format === void 0) return;
201
- return resolveFillBackground(format.decoration.fillPattern, format.decoration.fillForegroundIcv, globals.palette);
201
+ return resolveFillBackground(format.decoration.fillPattern, format.decoration.fillForegroundIcv, format.decoration.fillBackgroundIcv, globals.palette);
202
202
  }
203
203
  /** A cell's own resolved horizontal/vertical alignment -- already the exact Alignment/verticalAlignment members (or undefined) globals.ts's readCellFormat resolved through xf-colors.ts's unpackXfAlignment, so this is a lookup rather than a further resolution step, mirroring backgroundOf/bordersOf's own shape. Both fields undefined for a cell whose XF resolves to no CellFormat at all (an out-of-range xfIndex), matching every other resolveXOf helper's behaviour in that case. */
204
204
  function alignmentOf(globals, xfIndex) {
@@ -1,4 +1,4 @@
1
- import { T as XfDecorationFields } from "../xf-colors-CehHZtBy.cjs";
1
+ import { E as XfDecorationFields } from "../xf-colors-BB5MKq6R.cjs";
2
2
  import { t as PrintNamePlanEntry } from "../print-names-D-njuzVw.cjs";
3
3
  import { Alignment, Color } from "document-schema.js";
4
4
  //#region src/workbook/globals-writer.d.ts
@@ -1,4 +1,4 @@
1
- import { T as XfDecorationFields } from "../xf-colors-CpykR3B9.js";
1
+ import { E as XfDecorationFields } from "../xf-colors--5oxSeI1.js";
2
2
  import { t as PrintNamePlanEntry } from "../print-names-DUlpVE00.js";
3
3
  import { Alignment, Color } from "document-schema.js";
4
4
  //#region src/workbook/globals-writer.d.ts
@@ -1,6 +1,6 @@
1
1
  import { n as SheetRange } from "../ptg-B2K8t3js.cjs";
2
2
  import { t as RecordGroup } from "../substreams-Ddtvn_Vr.cjs";
3
- import { C as XfAlignmentFields, T as XfDecorationFields } from "../xf-colors-CehHZtBy.cjs";
3
+ import { E as XfDecorationFields, w as XfAlignmentFields } from "../xf-colors-BB5MKq6R.cjs";
4
4
  import { n as SheetPrintNames } from "../print-names-D-njuzVw.cjs";
5
5
  import { Color } from "document-schema.js";
6
6
  //#region src/workbook/globals.d.ts
@@ -1,6 +1,6 @@
1
1
  import { n as SheetRange } from "../ptg-B2K8t3js.js";
2
2
  import { t as RecordGroup } from "../substreams-D7dQiJbp.js";
3
- import { C as XfAlignmentFields, T as XfDecorationFields } from "../xf-colors-CpykR3B9.js";
3
+ import { E as XfDecorationFields, w as XfAlignmentFields } from "../xf-colors--5oxSeI1.js";
4
4
  import { n as SheetPrintNames } from "../print-names-DUlpVE00.js";
5
5
  import { Color } from "document-schema.js";
6
6
  //#region src/workbook/globals.d.ts
package/dist/write.cjs CHANGED
@@ -90,9 +90,18 @@ function buildPalettePlan(sheets) {
90
90
  const hex = (0, document_schema_js.colorToRgbHex)(color);
91
91
  if (!colorByHex.has(hex)) colorByHex.set(hex, color);
92
92
  };
93
+ const recordFill = (fill) => {
94
+ if (fill === void 0) return;
95
+ if (fill.kind === "solid") {
96
+ record(fill.color);
97
+ return;
98
+ }
99
+ record(fill.foregroundColor);
100
+ record(fill.backgroundColor);
101
+ };
93
102
  for (const sheet of sheets) for (const cell of sheet.cells) {
94
103
  if (!require_written_cells.writesCellRecord(cell)) continue;
95
- record(cell.background);
104
+ recordFill(cell.background);
96
105
  record(cell.borders?.left?.color);
97
106
  record(cell.borders?.right?.color);
98
107
  record(cell.borders?.top?.color);
@@ -149,12 +158,36 @@ function resolveWriteEdge(border, icvOf) {
149
158
  icv: icvOf(border.color)
150
159
  };
151
160
  }
161
+ /** A ContentCellFill's own fillPattern/fillForegroundIcv/fillBackgroundIcv triple, resolved for whichever of 'solid'/'pattern' the cell states -- undefined input resolves to FLSNULL with both colours Automatic, matching the pre-#951 undecorated case exactly. A 'pattern' fill leaving one of its own colours unstated writes that colour Automatic too, the inverse of xf-colors.ts's own resolveFillBackground treating an unresolvable icv the same way on read. */
162
+ function resolveFillFields(fill, icvOf) {
163
+ if (fill === void 0) return {
164
+ fillPattern: 0,
165
+ fillForegroundIcv: 64,
166
+ fillBackgroundIcv: 65
167
+ };
168
+ switch (fill.kind) {
169
+ case "solid": return {
170
+ fillPattern: 1,
171
+ fillForegroundIcv: icvOf(fill.color),
172
+ fillBackgroundIcv: 65
173
+ };
174
+ case "pattern": {
175
+ const fillPattern = require_biff_xf_colors.PATTERN_TYPE_TO_FILL_PATTERN.get(fill.patternType);
176
+ if (fillPattern === void 0) throw new require_biff_write_errors.BiffWriteError(`xls-codec cannot write a '${fill.patternType}' cell fill: [MS-XLS]'s own FillPattern enumeration has no member for it, that pattern name belonging only to WordprocessingML's ST_Shd half of ContentCellPatternType's shared vocabulary`);
177
+ return {
178
+ fillPattern,
179
+ fillForegroundIcv: fill.foregroundColor === void 0 ? 64 : icvOf(fill.foregroundColor),
180
+ fillBackgroundIcv: fill.backgroundColor === void 0 ? 65 : icvOf(fill.backgroundColor)
181
+ };
182
+ }
183
+ default: throw new require_biff_write_errors.BiffWriteError(`xls-codec cannot write a cell fill with kind '${(0, document_schema_js.unrecognizedFillKind)(fill)}': ContentCellFillSchema's discriminated union only defines 'solid' and 'pattern'`);
184
+ }
185
+ }
152
186
  /** A cell's own decoration, resolved into the raw XfDecorationFields the CellXF payload packs -- undefined for a cell with neither a background nor any border, so it shares the workbook's plain undecorated XF exactly as it did before decoration existed. The "has decoration at all" question is written-cells.ts's, since the writer's own record-emission predicate turns on the identical answer. */
153
187
  function resolveDecorationForCell(cell, icvOf) {
154
188
  if (!require_written_cells.cellCarriesFormatting(cell)) return;
155
189
  return {
156
- fillPattern: cell.background === void 0 ? 0 : 1,
157
- fillForegroundIcv: cell.background === void 0 ? 64 : icvOf(cell.background),
190
+ ...resolveFillFields(cell.background, icvOf),
158
191
  left: resolveWriteEdge(cell.borders?.left, icvOf),
159
192
  right: resolveWriteEdge(cell.borders?.right, icvOf),
160
193
  top: resolveWriteEdge(cell.borders?.top, icvOf),
@@ -165,7 +198,7 @@ function resolveDecorationForCell(cell, icvOf) {
165
198
  function signatureOfCellXf(formatId, alignment, verticalAlignment, decoration) {
166
199
  let signature = `f${formatId}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
167
200
  if (decoration === void 0) return signature;
168
- signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
201
+ signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}:${decoration.fillBackgroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
169
202
  return signature;
170
203
  }
171
204
  /**
package/dist/write.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SUMMARY_INFORMATION_STREAM } from "./container.js";
2
- import { DEFAULT_PALETTE_HEX_TO_ICV, borderStyleTokenFor } from "./biff/xf-colors.js";
2
+ import { DEFAULT_PALETTE_HEX_TO_ICV, PATTERN_TYPE_TO_FILL_PATTERN, borderStyleTokenFor } from "./biff/xf-colors.js";
3
3
  import { BiffWriteError } from "./biff/write-errors.js";
4
4
  import { printNameEntriesFor } from "./workbook/print-names.js";
5
5
  import { layoutMetadataToSummaryInformation as layoutMetadataToSummaryInformation$1 } from "./metadata.js";
@@ -7,7 +7,7 @@ import { GENERAL_CELL_XF_INDEX, buildWorkbookGlobals } from "./workbook/globals-
7
7
  import { cellCarriesFormatting, writesCellRecord } from "./written-cells.js";
8
8
  import { buildWorksheetSubstream } from "./workbook/sheet-writer.js";
9
9
  import { hasSummaryInformationFields, writeCompoundFile, writeSummaryInformationStream } from "archive-codec";
10
- import { colorToRgbHex, flattenTree } from "document-schema.js";
10
+ import { colorToRgbHex, flattenTree, unrecognizedFillKind } from "document-schema.js";
11
11
  import { BUILTIN_NUMBER_FORMATS } from "excel-number-format";
12
12
  //#region src/write.ts
13
13
  const WORKBOOK_STREAM_NAME = "Workbook";
@@ -89,9 +89,18 @@ function buildPalettePlan(sheets) {
89
89
  const hex = colorToRgbHex(color);
90
90
  if (!colorByHex.has(hex)) colorByHex.set(hex, color);
91
91
  };
92
+ const recordFill = (fill) => {
93
+ if (fill === void 0) return;
94
+ if (fill.kind === "solid") {
95
+ record(fill.color);
96
+ return;
97
+ }
98
+ record(fill.foregroundColor);
99
+ record(fill.backgroundColor);
100
+ };
92
101
  for (const sheet of sheets) for (const cell of sheet.cells) {
93
102
  if (!writesCellRecord(cell)) continue;
94
- record(cell.background);
103
+ recordFill(cell.background);
95
104
  record(cell.borders?.left?.color);
96
105
  record(cell.borders?.right?.color);
97
106
  record(cell.borders?.top?.color);
@@ -148,12 +157,36 @@ function resolveWriteEdge(border, icvOf) {
148
157
  icv: icvOf(border.color)
149
158
  };
150
159
  }
160
+ /** A ContentCellFill's own fillPattern/fillForegroundIcv/fillBackgroundIcv triple, resolved for whichever of 'solid'/'pattern' the cell states -- undefined input resolves to FLSNULL with both colours Automatic, matching the pre-#951 undecorated case exactly. A 'pattern' fill leaving one of its own colours unstated writes that colour Automatic too, the inverse of xf-colors.ts's own resolveFillBackground treating an unresolvable icv the same way on read. */
161
+ function resolveFillFields(fill, icvOf) {
162
+ if (fill === void 0) return {
163
+ fillPattern: 0,
164
+ fillForegroundIcv: 64,
165
+ fillBackgroundIcv: 65
166
+ };
167
+ switch (fill.kind) {
168
+ case "solid": return {
169
+ fillPattern: 1,
170
+ fillForegroundIcv: icvOf(fill.color),
171
+ fillBackgroundIcv: 65
172
+ };
173
+ case "pattern": {
174
+ const fillPattern = PATTERN_TYPE_TO_FILL_PATTERN.get(fill.patternType);
175
+ if (fillPattern === void 0) throw new BiffWriteError(`xls-codec cannot write a '${fill.patternType}' cell fill: [MS-XLS]'s own FillPattern enumeration has no member for it, that pattern name belonging only to WordprocessingML's ST_Shd half of ContentCellPatternType's shared vocabulary`);
176
+ return {
177
+ fillPattern,
178
+ fillForegroundIcv: fill.foregroundColor === void 0 ? 64 : icvOf(fill.foregroundColor),
179
+ fillBackgroundIcv: fill.backgroundColor === void 0 ? 65 : icvOf(fill.backgroundColor)
180
+ };
181
+ }
182
+ default: throw new BiffWriteError(`xls-codec cannot write a cell fill with kind '${unrecognizedFillKind(fill)}': ContentCellFillSchema's discriminated union only defines 'solid' and 'pattern'`);
183
+ }
184
+ }
151
185
  /** A cell's own decoration, resolved into the raw XfDecorationFields the CellXF payload packs -- undefined for a cell with neither a background nor any border, so it shares the workbook's plain undecorated XF exactly as it did before decoration existed. The "has decoration at all" question is written-cells.ts's, since the writer's own record-emission predicate turns on the identical answer. */
152
186
  function resolveDecorationForCell(cell, icvOf) {
153
187
  if (!cellCarriesFormatting(cell)) return;
154
188
  return {
155
- fillPattern: cell.background === void 0 ? 0 : 1,
156
- fillForegroundIcv: cell.background === void 0 ? 64 : icvOf(cell.background),
189
+ ...resolveFillFields(cell.background, icvOf),
157
190
  left: resolveWriteEdge(cell.borders?.left, icvOf),
158
191
  right: resolveWriteEdge(cell.borders?.right, icvOf),
159
192
  top: resolveWriteEdge(cell.borders?.top, icvOf),
@@ -164,7 +197,7 @@ function resolveDecorationForCell(cell, icvOf) {
164
197
  function signatureOfCellXf(formatId, alignment, verticalAlignment, decoration) {
165
198
  let signature = `f${formatId}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
166
199
  if (decoration === void 0) return signature;
167
- signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
200
+ signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}:${decoration.fillBackgroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
168
201
  return signature;
169
202
  }
170
203
  /**
@@ -1,10 +1,12 @@
1
1
  import { t as BlockCursor } from "./cursor-VMtw9uVP.js";
2
- import { Alignment, Color, ContentBorder } from "document-schema.js";
2
+ import { Alignment, Color, ContentBorder, ContentCellFill, ContentCellPatternType } from "document-schema.js";
3
3
  //#region src/biff/xf-colors.d.ts
4
4
  /** FLSNULL: no fill pattern -- the cell's fill colour fields carry no meaning. */
5
5
  declare const FILL_PATTERN_NONE = 0;
6
- /** FLSSOLID: a solid fill, the only pattern this package maps onto ContentSheetCell.background -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). Every other pattern (50%/75%/25% gray, the stripe and crosshatch families, ...) is a real information-loss case this reader does not approximate: see resolveFillBackground below. */
6
+ /** FLSSOLID: a solid fill -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). */
7
7
  declare const FILL_PATTERN_SOLID = 1;
8
+ /** The inverse of FILL_PATTERN_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 SpreadsheetML half of the shared vocabulary is exactly FILL_PATTERN_TO_PATTERN_TYPE's own value set -- the WordprocessingML-only members (the percentN family and the stripe/cross families ST_Shd names) are absent, FillPattern having no equivalent for them at all. */
9
+ declare const PATTERN_TYPE_TO_FILL_PATTERN: ReadonlyMap<ContentCellPatternType, number>;
8
10
  /** alc (a CellXF/StyleXF payload's word1, bits 0-2) -> ContentSheetCell.alignment, or undefined for ALCGEN (the value-kind default this field being absent already requests) and for the three HorizAlign members (ALCFILL/ALCCONTCTR/ALCDIST) Alignment has no member for -- matching ooxml.js's readHorizontalAlignment policy of only the four direct members surviving. */
9
11
  declare function resolveHorizontalAlignment(alc: number): Alignment | undefined;
10
12
  /** ContentSheetCell.alignment -> the alc token to pack into word1 -- undefined maps to ALCGEN, the "use the value-kind default" token every genuinely unaligned cell already carried before this module modelled alignment at all. */
@@ -56,12 +58,17 @@ interface XfBorderEdge {
56
58
  declare function resolveBorderEdge(edge: XfBorderEdge, palette: readonly Color[] | undefined): ContentBorder | undefined;
57
59
  /** The inverse of resolveBorderEdge's style resolution: picks the BorderStyle token carrying a ContentBorder's own pattern at the closest named weight, bucketing a solid/dashed border's widthPt back to a weight through document-schema.js's own shared quantisation -- the same one resolveBorderEdge's widths came out of, and the same one ooxml.js's borderToXlsxStyle buckets xlsx's string tokens through. */
58
60
  declare function borderStyleTokenFor(border: ContentBorder): number;
59
- /** A solid fill's own foreground colour resolved to a real background, or undefined for every other FillPattern value -- FLSNULL (no fill at all) and every pattern beyond solid (50%/75%/25% gray, the stripe and crosshatch family) alike. A non-solid pattern is a real information-loss case rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its foreground colour alone would misrepresent what the cell actually shows -- see xls-codec's README for this package's own stated judgment call. */
60
- declare function resolveFillBackground(fillPattern: number, foregroundIcv: number, palette: readonly Color[] | undefined): Color | undefined;
61
- /** Every decoration field the trailing payload's word2/word3/word4 carry ([MS-XLS] 2.4.353's own CellXF/StyleXF "Data" field), read or write side alike: which fill pattern (if any) and its foreground colour, and each of the four sides' own border style plus colour. Diagonal borders (dgDiag/grbitDiag/icvDiag) are out of this package's scope -- ContentCellBordersSchema has no diagonal member -- and are always read as absent / always written as none. */
61
+ /**
62
+ * Resolves a cell's own FillPattern/icvFore/icvBack triple to a real ContentCellFill (ExaDev/documents.js#951), or undefined for FLSNULL (no fill at all), for a reserved/unrecognised FillPattern value, or for FLSSOLID when its own icvFore does not resolve to a fixed RGB value (an "Automatic" or otherwise unmapped icv, which leaves nothing to state a solid fill's colour as).
63
+ *
64
+ * FLSSOLID resolves to a 'solid' fill of icvFore alone -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF), so icvBack carries no meaning for it and is never consulted. Every other named FillPattern resolves to a real 'pattern' fill via FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of icvFore/icvBack resolves to a real colour (either may be an "Automatic" icv this package cannot express as a fixed RGB value, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention).
65
+ */
66
+ declare function resolveFillBackground(fillPattern: number, foregroundIcv: number, backgroundIcv: number, palette: readonly Color[] | undefined): ContentCellFill | undefined;
67
+ /** Every decoration field the trailing payload's word2/word3/word4 carry ([MS-XLS] 2.4.353's own CellXF/StyleXF "Data" field), read or write side alike: which fill pattern (if any) and its foreground/background colours, and each of the four sides' own border style plus colour. fillBackgroundIcv carries no meaning for a solid fill (icvFore alone is rendered) but is real for every other named pattern, where it is the colour the pattern's gaps show through. Diagonal borders (dgDiag/grbitDiag/icvDiag) are out of this package's scope -- ContentCellBordersSchema has no diagonal member -- and are always read as absent / always written as none. */
62
68
  interface XfDecorationFields {
63
69
  readonly fillPattern: number;
64
70
  readonly fillForegroundIcv: number;
71
+ readonly fillBackgroundIcv: number;
65
72
  readonly left: XfBorderEdge;
66
73
  readonly right: XfBorderEdge;
67
74
  readonly top: XfBorderEdge;
@@ -88,4 +95,4 @@ declare function readLongRgbColor(cursor: BlockCursor): Color;
88
95
  /** The inverse of readLongRgbColor: a colour's own red/green/blue/reserved bytes, rounded to the nearest byte (the same rounding colorToRgbHex applies) -- exact for any colour this package itself constructed via rgbHexToColor, which is what write.ts's own palette-colour interning does. */
89
96
  declare function longRgbBytesOf(color: Color): readonly [number, number, number, number];
90
97
  //#endregion
91
- export { readLongRgbColor as A, XfAlignmentFields as C, horizAlignTokenFor as D, borderStyleTokenFor as E, resolveVerticalAlignment as F, unpackXfAlignment as I, unpackXfDecoration as L, resolveFillBackground as M, resolveHorizontalAlignment as N, longRgbBytesOf as O, resolveIcvColor as P, vertAlignTokenFor as R, UNDECORATED_XF_FIELDS as S, XfDecorationFields as T, FILL_PATTERN_SOLID as _, BORDER_STYLE_DOUBLE as a, PALETTE_BASE_ICV as b, BORDER_STYLE_MEDIUM_DASHDOT as c, BORDER_STYLE_NONE as d, BORDER_STYLE_SLANT_DASHDOT as f, FILL_PATTERN_NONE as g, DEFAULT_PALETTE_HEX_TO_ICV as h, BORDER_STYLE_DOTTED as i, resolveBorderEdge as j, packXfDecorationWords as k, BORDER_STYLE_MEDIUM_DASHDOTDOT as l, BORDER_STYLE_THIN as m, BORDER_STYLE_DASHDOTDOT as n, BORDER_STYLE_HAIR as o, BORDER_STYLE_THICK as p, BORDER_STYLE_DASHED as r, BORDER_STYLE_MEDIUM as s, BORDER_STYLE_DASHDOT as t, BORDER_STYLE_MEDIUM_DASHED as u, ICV_AUTOMATIC_BACKGROUND as v, XfBorderEdge as w, PALETTE_ENTRY_COUNT as x, ICV_AUTOMATIC_FOREGROUND as y };
98
+ export { packXfDecorationWords as A, UNDECORATED_XF_FIELDS as C, borderStyleTokenFor as D, XfDecorationFields as E, resolveIcvColor as F, resolveVerticalAlignment as I, unpackXfAlignment as L, resolveBorderEdge as M, resolveFillBackground as N, horizAlignTokenFor as O, resolveHorizontalAlignment as P, unpackXfDecoration as R, PATTERN_TYPE_TO_FILL_PATTERN as S, XfBorderEdge as T, FILL_PATTERN_SOLID as _, BORDER_STYLE_DOUBLE as a, PALETTE_BASE_ICV as b, BORDER_STYLE_MEDIUM_DASHDOT as c, BORDER_STYLE_NONE as d, BORDER_STYLE_SLANT_DASHDOT as f, FILL_PATTERN_NONE as g, DEFAULT_PALETTE_HEX_TO_ICV as h, BORDER_STYLE_DOTTED as i, readLongRgbColor as j, longRgbBytesOf as k, BORDER_STYLE_MEDIUM_DASHDOTDOT as l, BORDER_STYLE_THIN as m, BORDER_STYLE_DASHDOTDOT as n, BORDER_STYLE_HAIR as o, BORDER_STYLE_THICK as p, BORDER_STYLE_DASHED as r, BORDER_STYLE_MEDIUM as s, BORDER_STYLE_DASHDOT as t, BORDER_STYLE_MEDIUM_DASHED as u, ICV_AUTOMATIC_BACKGROUND as v, XfAlignmentFields as w, PALETTE_ENTRY_COUNT as x, ICV_AUTOMATIC_FOREGROUND as y, vertAlignTokenFor as z };
@@ -1,10 +1,12 @@
1
1
  import { t as BlockCursor } from "./cursor-VMtw9uVP.cjs";
2
- import { Alignment, Color, ContentBorder } from "document-schema.js";
2
+ import { Alignment, Color, ContentBorder, ContentCellFill, ContentCellPatternType } from "document-schema.js";
3
3
  //#region src/biff/xf-colors.d.ts
4
4
  /** FLSNULL: no fill pattern -- the cell's fill colour fields carry no meaning. */
5
5
  declare const FILL_PATTERN_NONE = 0;
6
- /** FLSSOLID: a solid fill, the only pattern this package maps onto ContentSheetCell.background -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). Every other pattern (50%/75%/25% gray, the stripe and crosshatch families, ...) is a real information-loss case this reader does not approximate: see resolveFillBackground below. */
6
+ /** FLSSOLID: a solid fill -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF). */
7
7
  declare const FILL_PATTERN_SOLID = 1;
8
+ /** The inverse of FILL_PATTERN_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 SpreadsheetML half of the shared vocabulary is exactly FILL_PATTERN_TO_PATTERN_TYPE's own value set -- the WordprocessingML-only members (the percentN family and the stripe/cross families ST_Shd names) are absent, FillPattern having no equivalent for them at all. */
9
+ declare const PATTERN_TYPE_TO_FILL_PATTERN: ReadonlyMap<ContentCellPatternType, number>;
8
10
  /** alc (a CellXF/StyleXF payload's word1, bits 0-2) -> ContentSheetCell.alignment, or undefined for ALCGEN (the value-kind default this field being absent already requests) and for the three HorizAlign members (ALCFILL/ALCCONTCTR/ALCDIST) Alignment has no member for -- matching ooxml.js's readHorizontalAlignment policy of only the four direct members surviving. */
9
11
  declare function resolveHorizontalAlignment(alc: number): Alignment | undefined;
10
12
  /** ContentSheetCell.alignment -> the alc token to pack into word1 -- undefined maps to ALCGEN, the "use the value-kind default" token every genuinely unaligned cell already carried before this module modelled alignment at all. */
@@ -56,12 +58,17 @@ interface XfBorderEdge {
56
58
  declare function resolveBorderEdge(edge: XfBorderEdge, palette: readonly Color[] | undefined): ContentBorder | undefined;
57
59
  /** The inverse of resolveBorderEdge's style resolution: picks the BorderStyle token carrying a ContentBorder's own pattern at the closest named weight, bucketing a solid/dashed border's widthPt back to a weight through document-schema.js's own shared quantisation -- the same one resolveBorderEdge's widths came out of, and the same one ooxml.js's borderToXlsxStyle buckets xlsx's string tokens through. */
58
60
  declare function borderStyleTokenFor(border: ContentBorder): number;
59
- /** A solid fill's own foreground colour resolved to a real background, or undefined for every other FillPattern value -- FLSNULL (no fill at all) and every pattern beyond solid (50%/75%/25% gray, the stripe and crosshatch family) alike. A non-solid pattern is a real information-loss case rather than an oversight: ContentSheetCell.background models one flat colour, and approximating a striped or crosshatched fill as its foreground colour alone would misrepresent what the cell actually shows -- see xls-codec's README for this package's own stated judgment call. */
60
- declare function resolveFillBackground(fillPattern: number, foregroundIcv: number, palette: readonly Color[] | undefined): Color | undefined;
61
- /** Every decoration field the trailing payload's word2/word3/word4 carry ([MS-XLS] 2.4.353's own CellXF/StyleXF "Data" field), read or write side alike: which fill pattern (if any) and its foreground colour, and each of the four sides' own border style plus colour. Diagonal borders (dgDiag/grbitDiag/icvDiag) are out of this package's scope -- ContentCellBordersSchema has no diagonal member -- and are always read as absent / always written as none. */
61
+ /**
62
+ * Resolves a cell's own FillPattern/icvFore/icvBack triple to a real ContentCellFill (ExaDev/documents.js#951), or undefined for FLSNULL (no fill at all), for a reserved/unrecognised FillPattern value, or for FLSSOLID when its own icvFore does not resolve to a fixed RGB value (an "Automatic" or otherwise unmapped icv, which leaves nothing to state a solid fill's colour as).
63
+ *
64
+ * FLSSOLID resolves to a 'solid' fill of icvFore alone -- "If this value is 1 ... then only icvFore is rendered" ([MS-XLS] CellXF), so icvBack carries no meaning for it and is never consulted. Every other named FillPattern resolves to a real 'pattern' fill via FILL_PATTERN_TO_PATTERN_TYPE, carrying whichever of icvFore/icvBack resolves to a real colour (either may be an "Automatic" icv this package cannot express as a fixed RGB value, matching ContentCellFillSchema's own "a colour can defer instead of asserting" convention).
65
+ */
66
+ declare function resolveFillBackground(fillPattern: number, foregroundIcv: number, backgroundIcv: number, palette: readonly Color[] | undefined): ContentCellFill | undefined;
67
+ /** Every decoration field the trailing payload's word2/word3/word4 carry ([MS-XLS] 2.4.353's own CellXF/StyleXF "Data" field), read or write side alike: which fill pattern (if any) and its foreground/background colours, and each of the four sides' own border style plus colour. fillBackgroundIcv carries no meaning for a solid fill (icvFore alone is rendered) but is real for every other named pattern, where it is the colour the pattern's gaps show through. Diagonal borders (dgDiag/grbitDiag/icvDiag) are out of this package's scope -- ContentCellBordersSchema has no diagonal member -- and are always read as absent / always written as none. */
62
68
  interface XfDecorationFields {
63
69
  readonly fillPattern: number;
64
70
  readonly fillForegroundIcv: number;
71
+ readonly fillBackgroundIcv: number;
65
72
  readonly left: XfBorderEdge;
66
73
  readonly right: XfBorderEdge;
67
74
  readonly top: XfBorderEdge;
@@ -88,4 +95,4 @@ declare function readLongRgbColor(cursor: BlockCursor): Color;
88
95
  /** The inverse of readLongRgbColor: a colour's own red/green/blue/reserved bytes, rounded to the nearest byte (the same rounding colorToRgbHex applies) -- exact for any colour this package itself constructed via rgbHexToColor, which is what write.ts's own palette-colour interning does. */
89
96
  declare function longRgbBytesOf(color: Color): readonly [number, number, number, number];
90
97
  //#endregion
91
- export { readLongRgbColor as A, XfAlignmentFields as C, horizAlignTokenFor as D, borderStyleTokenFor as E, resolveVerticalAlignment as F, unpackXfAlignment as I, unpackXfDecoration as L, resolveFillBackground as M, resolveHorizontalAlignment as N, longRgbBytesOf as O, resolveIcvColor as P, vertAlignTokenFor as R, UNDECORATED_XF_FIELDS as S, XfDecorationFields as T, FILL_PATTERN_SOLID as _, BORDER_STYLE_DOUBLE as a, PALETTE_BASE_ICV as b, BORDER_STYLE_MEDIUM_DASHDOT as c, BORDER_STYLE_NONE as d, BORDER_STYLE_SLANT_DASHDOT as f, FILL_PATTERN_NONE as g, DEFAULT_PALETTE_HEX_TO_ICV as h, BORDER_STYLE_DOTTED as i, resolveBorderEdge as j, packXfDecorationWords as k, BORDER_STYLE_MEDIUM_DASHDOTDOT as l, BORDER_STYLE_THIN as m, BORDER_STYLE_DASHDOTDOT as n, BORDER_STYLE_HAIR as o, BORDER_STYLE_THICK as p, BORDER_STYLE_DASHED as r, BORDER_STYLE_MEDIUM as s, BORDER_STYLE_DASHDOT as t, BORDER_STYLE_MEDIUM_DASHED as u, ICV_AUTOMATIC_BACKGROUND as v, XfBorderEdge as w, PALETTE_ENTRY_COUNT as x, ICV_AUTOMATIC_FOREGROUND as y };
98
+ export { packXfDecorationWords as A, UNDECORATED_XF_FIELDS as C, borderStyleTokenFor as D, XfDecorationFields as E, resolveIcvColor as F, resolveVerticalAlignment as I, unpackXfAlignment as L, resolveBorderEdge as M, resolveFillBackground as N, horizAlignTokenFor as O, resolveHorizontalAlignment as P, unpackXfDecoration as R, PATTERN_TYPE_TO_FILL_PATTERN as S, XfBorderEdge as T, FILL_PATTERN_SOLID as _, BORDER_STYLE_DOUBLE as a, PALETTE_BASE_ICV as b, BORDER_STYLE_MEDIUM_DASHDOT as c, BORDER_STYLE_NONE as d, BORDER_STYLE_SLANT_DASHDOT as f, FILL_PATTERN_NONE as g, DEFAULT_PALETTE_HEX_TO_ICV as h, BORDER_STYLE_DOTTED as i, readLongRgbColor as j, longRgbBytesOf as k, BORDER_STYLE_MEDIUM_DASHDOTDOT as l, BORDER_STYLE_THIN as m, BORDER_STYLE_DASHDOTDOT as n, BORDER_STYLE_HAIR as o, BORDER_STYLE_THICK as p, BORDER_STYLE_DASHED as r, BORDER_STYLE_MEDIUM as s, BORDER_STYLE_DASHDOT as t, BORDER_STYLE_MEDIUM_DASHED as u, ICV_AUTOMATIC_BACKGROUND as v, XfAlignmentFields as w, PALETTE_ENTRY_COUNT as x, ICV_AUTOMATIC_FOREGROUND as y, vertAlignTokenFor as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xls-codec",
3
- "version": "2.0.2",
3
+ "version": "3.0.0",
4
4
  "description": "Hand-written reader for the legacy Excel Binary File Format (.xls, BIFF8) as specified by [MS-XLS], mapping a workbook's record stream onto the shared document-schema.js spreadsheet model - the .xls codec for the documents.js family.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -68,9 +68,9 @@
68
68
  },
69
69
  "packageManager": "pnpm@11.6.0",
70
70
  "dependencies": {
71
- "archive-codec": "^1.4.2",
72
- "document-schema.js": "^5.6.0",
73
- "excel-number-format": "^1.0.1"
71
+ "archive-codec": "^1.4.3",
72
+ "document-schema.js": "^6.0.0",
73
+ "excel-number-format": "^1.0.2"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@arethetypeswrong/cli": "^0.18.5",