xls-codec 0.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/dist/biff/cursor.cjs +73 -0
  4. package/dist/biff/cursor.d.cts +28 -0
  5. package/dist/biff/cursor.d.ts +28 -0
  6. package/dist/biff/cursor.js +72 -0
  7. package/dist/biff/errors.cjs +18 -0
  8. package/dist/biff/errors.d.cts +5 -0
  9. package/dist/biff/errors.d.ts +5 -0
  10. package/dist/biff/errors.js +17 -0
  11. package/dist/biff/record-types.cjs +108 -0
  12. package/dist/biff/record-types.d.cts +73 -0
  13. package/dist/biff/record-types.d.ts +73 -0
  14. package/dist/biff/record-types.js +73 -0
  15. package/dist/biff/records.cjs +40 -0
  16. package/dist/biff/records.d.cts +2 -0
  17. package/dist/biff/records.d.ts +2 -0
  18. package/dist/biff/records.js +38 -0
  19. package/dist/biff/rk.cjs +29 -0
  20. package/dist/biff/rk.d.cts +5 -0
  21. package/dist/biff/rk.d.ts +5 -0
  22. package/dist/biff/rk.js +28 -0
  23. package/dist/biff/strings.cjs +66 -0
  24. package/dist/biff/strings.d.cts +14 -0
  25. package/dist/biff/strings.d.ts +14 -0
  26. package/dist/biff/strings.js +63 -0
  27. package/dist/biff/substreams.cjs +71 -0
  28. package/dist/biff/substreams.d.cts +21 -0
  29. package/dist/biff/substreams.d.ts +21 -0
  30. package/dist/biff/substreams.js +69 -0
  31. package/dist/container.cjs +46 -0
  32. package/dist/container.d.cts +15 -0
  33. package/dist/container.d.ts +15 -0
  34. package/dist/container.js +44 -0
  35. package/dist/content.cjs +230 -0
  36. package/dist/content.d.cts +20 -0
  37. package/dist/content.d.ts +20 -0
  38. package/dist/content.js +228 -0
  39. package/dist/index.cjs +74 -0
  40. package/dist/index.d.cts +15 -0
  41. package/dist/index.d.ts +15 -0
  42. package/dist/index.js +15 -0
  43. package/dist/number-format.cjs +298 -0
  44. package/dist/number-format.d.cts +32 -0
  45. package/dist/number-format.d.ts +32 -0
  46. package/dist/number-format.js +296 -0
  47. package/dist/records-DVIqXFKk.d.cts +20 -0
  48. package/dist/records-DVIqXFKk.d.ts +20 -0
  49. package/dist/serial.cjs +62 -0
  50. package/dist/serial.d.cts +7 -0
  51. package/dist/serial.d.ts +7 -0
  52. package/dist/serial.js +59 -0
  53. package/dist/units.cjs +30 -0
  54. package/dist/units.d.cts +11 -0
  55. package/dist/units.d.ts +11 -0
  56. package/dist/units.js +28 -0
  57. package/dist/workbook/globals.cjs +106 -0
  58. package/dist/workbook/globals.d.cts +45 -0
  59. package/dist/workbook/globals.d.ts +45 -0
  60. package/dist/workbook/globals.js +104 -0
  61. package/dist/workbook/sheet.cjs +372 -0
  62. package/dist/workbook/sheet.d.cts +58 -0
  63. package/dist/workbook/sheet.d.ts +58 -0
  64. package/dist/workbook/sheet.js +371 -0
  65. package/package.json +85 -2
@@ -0,0 +1,58 @@
1
+ import { RecordGroup } from "../biff/substreams.cjs";
2
+ //#region src/workbook/sheet.d.ts
3
+ /** A cell's value as its own record carries it, before number-format classification decides whether a number is really a date, a percentage, or an amount of money. */
4
+ type RawCellValue = {
5
+ kind: "number";
6
+ value: number;
7
+ } | {
8
+ kind: "string";
9
+ value: string;
10
+ } | {
11
+ kind: "boolean";
12
+ value: boolean;
13
+ } | {
14
+ kind: "error";
15
+ value: string;
16
+ } | {
17
+ kind: "blank";
18
+ };
19
+ /** One cell of the cell table. */
20
+ interface RawCell {
21
+ readonly row: number;
22
+ readonly column: number;
23
+ /** The cell's own ixfe ([MS-XLS] 2.5.168): an index into the globals substream's XF table. */
24
+ readonly xfIndex: number;
25
+ readonly value: RawCellValue;
26
+ /** True when the value is a Formula record's CACHED result rather than a literal. The formula expression itself is not read: BIFF8 stores it as a compiled Ptg token stream, not as text. */
27
+ readonly fromFormula: boolean;
28
+ }
29
+ interface RawRow {
30
+ readonly index: number;
31
+ /** The row's declared height in points, absent when the record declared none. */
32
+ readonly heightPt?: number;
33
+ readonly hidden: boolean;
34
+ }
35
+ interface RawColumn {
36
+ readonly index: number;
37
+ readonly widthPt?: number;
38
+ readonly hidden: boolean;
39
+ }
40
+ interface RawRange {
41
+ readonly startRow: number;
42
+ readonly startColumn: number;
43
+ readonly endRow: number;
44
+ readonly endColumn: number;
45
+ }
46
+ /** One worksheet's records, read but not yet mapped onto the shared schema. */
47
+ interface RawSheet {
48
+ readonly cells: readonly RawCell[];
49
+ readonly rows: readonly RawRow[];
50
+ readonly columns: readonly RawColumn[];
51
+ readonly merges: readonly RawRange[];
52
+ /** The used range from the Dimensions record ([MS-XLS] 2.4.90), when the sheet declared one. */
53
+ readonly usedRange?: RawRange;
54
+ }
55
+ /** Reads one worksheet substream's records. */
56
+ declare function readSheetRecords(records: readonly RecordGroup[], sharedStrings: readonly string[]): RawSheet;
57
+ //#endregion
58
+ export { RawCell, RawCellValue, RawColumn, RawRange, RawRow, RawSheet, readSheetRecords };
@@ -0,0 +1,58 @@
1
+ import { RecordGroup } from "../biff/substreams.js";
2
+ //#region src/workbook/sheet.d.ts
3
+ /** A cell's value as its own record carries it, before number-format classification decides whether a number is really a date, a percentage, or an amount of money. */
4
+ type RawCellValue = {
5
+ kind: "number";
6
+ value: number;
7
+ } | {
8
+ kind: "string";
9
+ value: string;
10
+ } | {
11
+ kind: "boolean";
12
+ value: boolean;
13
+ } | {
14
+ kind: "error";
15
+ value: string;
16
+ } | {
17
+ kind: "blank";
18
+ };
19
+ /** One cell of the cell table. */
20
+ interface RawCell {
21
+ readonly row: number;
22
+ readonly column: number;
23
+ /** The cell's own ixfe ([MS-XLS] 2.5.168): an index into the globals substream's XF table. */
24
+ readonly xfIndex: number;
25
+ readonly value: RawCellValue;
26
+ /** True when the value is a Formula record's CACHED result rather than a literal. The formula expression itself is not read: BIFF8 stores it as a compiled Ptg token stream, not as text. */
27
+ readonly fromFormula: boolean;
28
+ }
29
+ interface RawRow {
30
+ readonly index: number;
31
+ /** The row's declared height in points, absent when the record declared none. */
32
+ readonly heightPt?: number;
33
+ readonly hidden: boolean;
34
+ }
35
+ interface RawColumn {
36
+ readonly index: number;
37
+ readonly widthPt?: number;
38
+ readonly hidden: boolean;
39
+ }
40
+ interface RawRange {
41
+ readonly startRow: number;
42
+ readonly startColumn: number;
43
+ readonly endRow: number;
44
+ readonly endColumn: number;
45
+ }
46
+ /** One worksheet's records, read but not yet mapped onto the shared schema. */
47
+ interface RawSheet {
48
+ readonly cells: readonly RawCell[];
49
+ readonly rows: readonly RawRow[];
50
+ readonly columns: readonly RawColumn[];
51
+ readonly merges: readonly RawRange[];
52
+ /** The used range from the Dimensions record ([MS-XLS] 2.4.90), when the sheet declared one. */
53
+ readonly usedRange?: RawRange;
54
+ }
55
+ /** Reads one worksheet substream's records. */
56
+ declare function readSheetRecords(records: readonly RecordGroup[], sharedStrings: readonly string[]): RawSheet;
57
+ //#endregion
58
+ export { RawCell, RawCellValue, RawColumn, RawRange, RawRow, RawSheet, readSheetRecords };
@@ -0,0 +1,371 @@
1
+ import "../biff/record-types.js";
2
+ import { BiffFormatError } from "../biff/records.js";
3
+ import { BlockCursor } from "../biff/cursor.js";
4
+ import { readXLUnicodeString } from "../biff/strings.js";
5
+ import { errorTextOf } from "../biff/errors.js";
6
+ import { decodeRkNumber } from "../biff/rk.js";
7
+ import { columnWidthToPoints, twipsToPoints } from "../units.js";
8
+ //#region src/workbook/sheet.ts
9
+ /** Row record flag bits, in the 32-bit field following unused1 ([MS-XLS] 2.4.221). */
10
+ const ROW_FLAG_HIDDEN = 32;
11
+ /** fUnsynced: the row height was set manually. When clear the height is the sheet default rather than a per-row declaration. */
12
+ const ROW_FLAG_UNSYNCED = 64;
13
+ /** ColInfo flag bits ([MS-XLS] 2.4.53). */
14
+ const COLINFO_FLAG_HIDDEN = 1;
15
+ /** A FormulaValue whose fExprO field is this is not an Xnum but a tagged non-numeric value ([MS-XLS] 2.5.133). */
16
+ const FORMULA_VALUE_TAGGED = 65535;
17
+ /** The tag byte's own vocabulary in that case. */
18
+ const FORMULA_VALUE_STRING = 0;
19
+ const FORMULA_VALUE_BOOLEAN = 1;
20
+ const FORMULA_VALUE_ERROR = 2;
21
+ const FORMULA_VALUE_BLANK = 3;
22
+ /** MulRk carries rw, colFirst, N six-byte RkRecs, then colLast; MulBlank the same with two-byte ixfe entries. */
23
+ const MUL_FIXED_BYTES = 6;
24
+ const MULRK_ENTRY_BYTES = 6;
25
+ const MULBLANK_ENTRY_BYTES = 2;
26
+ /** Reads one worksheet substream's records. */
27
+ function readSheetRecords(records, sharedStrings) {
28
+ const cells = [];
29
+ const rows = [];
30
+ const columns = [];
31
+ const merges = [];
32
+ let usedRange;
33
+ for (let index = 0; index < records.length; index += 1) {
34
+ const record = records[index];
35
+ if (record === void 0) continue;
36
+ switch (record.type) {
37
+ case 512:
38
+ usedRange = readDimensions(record);
39
+ break;
40
+ case 520:
41
+ rows.push(readRow(record));
42
+ break;
43
+ case 125:
44
+ columns.push(...readColInfo(record));
45
+ break;
46
+ case 229:
47
+ merges.push(...readMergeCells(record));
48
+ break;
49
+ case 513:
50
+ cells.push(readBlank(record));
51
+ break;
52
+ case 190:
53
+ cells.push(...readMulBlank(record));
54
+ break;
55
+ case 638:
56
+ cells.push(readRk(record));
57
+ break;
58
+ case 189:
59
+ cells.push(...readMulRk(record));
60
+ break;
61
+ case 515:
62
+ cells.push(readNumber(record));
63
+ break;
64
+ case 517: {
65
+ const cell = readBoolErr(record);
66
+ if (cell !== void 0) cells.push(cell);
67
+ break;
68
+ }
69
+ case 253:
70
+ cells.push(readLabelSst(record, sharedStrings));
71
+ break;
72
+ case 516:
73
+ cells.push(readLabel(record));
74
+ break;
75
+ case 6: cells.push(readFormula(record, stringResultAfter(records, index)));
76
+ }
77
+ }
78
+ return usedRange === void 0 ? {
79
+ cells,
80
+ rows,
81
+ columns,
82
+ merges
83
+ } : {
84
+ cells,
85
+ rows,
86
+ columns,
87
+ merges,
88
+ usedRange
89
+ };
90
+ }
91
+ /**
92
+ * Finds the String record carrying a Formula's cached string result, if it has one.
93
+ *
94
+ * [MS-XLS] 2.5.133 says the String "immediately follows" the Formula, but the FORMULA production of [MS-XLS] 2.1.7.20.6 is wider than that -- `[Uncalced] Formula [Array / Table / ShrFmla / SUB] [String *Continue]` -- so an array formula, a data table, or a member of a shared-formula run puts one record in between. Skipping exactly those three finds the String in both shapes; anything else ends the search, so a Formula with no string result never reaches past its own cell into the next one's records.
95
+ */
96
+ function stringResultAfter(records, formulaIndex) {
97
+ for (let index = formulaIndex + 1; index < records.length; index += 1) {
98
+ const candidate = records[index];
99
+ if (candidate === void 0) return;
100
+ if (candidate.type === 519) return candidate;
101
+ if (candidate.type !== 545 && candidate.type !== 566 && candidate.type !== 1212) return;
102
+ }
103
+ }
104
+ /** Dimensions ([MS-XLS] 2.4.90): a four-byte first row, a four-byte past-the-end row, a two-byte first column, and a two-byte past-the-end column. */
105
+ function readDimensions(record) {
106
+ const cursor = new BlockCursor(record.blocks);
107
+ const rwMic = cursor.u32();
108
+ const rwMac = cursor.u32();
109
+ const colMic = cursor.u16();
110
+ const colMac = cursor.u16();
111
+ if (rwMac === 0 || colMac === 0) return;
112
+ return {
113
+ startRow: rwMic,
114
+ startColumn: colMic,
115
+ endRow: rwMac - 1,
116
+ endColumn: colMac - 1
117
+ };
118
+ }
119
+ /** Row ([MS-XLS] 2.4.221): sixteen bytes, of which this reader uses the index, the height, and the hidden and manually-set flags. */
120
+ function readRow(record) {
121
+ const cursor = new BlockCursor(record.blocks);
122
+ const index = cursor.u16();
123
+ cursor.skip(4);
124
+ const heightTwips = cursor.u16();
125
+ cursor.skip(4);
126
+ const flags = cursor.u8();
127
+ const hidden = (flags & ROW_FLAG_HIDDEN) !== 0;
128
+ const declared = (flags & ROW_FLAG_UNSYNCED) !== 0;
129
+ const heightPt = twipsToPoints(heightTwips);
130
+ return declared && heightPt > 0 ? {
131
+ index,
132
+ heightPt,
133
+ hidden
134
+ } : {
135
+ index,
136
+ hidden
137
+ };
138
+ }
139
+ /** ColInfo ([MS-XLS] 2.4.53): one record covering an inclusive RANGE of columns, so it expands to one entry per column it names. */
140
+ function readColInfo(record) {
141
+ const cursor = new BlockCursor(record.blocks);
142
+ const first = cursor.u16();
143
+ const last = cursor.u16();
144
+ const coldx = cursor.u16();
145
+ cursor.skip(2);
146
+ const hidden = (cursor.u16() & COLINFO_FLAG_HIDDEN) !== 0;
147
+ const widthPt = columnWidthToPoints(coldx);
148
+ const columns = [];
149
+ const end = Math.min(last, 255);
150
+ for (let index = first; index <= end; index += 1) columns.push(widthPt > 0 ? {
151
+ index,
152
+ widthPt,
153
+ hidden
154
+ } : {
155
+ index,
156
+ hidden
157
+ });
158
+ return columns;
159
+ }
160
+ /** MergeCells ([MS-XLS] 2.4.168): a count then that many Ref8 structures ([MS-XLS] 2.5.208), each an inclusive row and column range. */
161
+ function readMergeCells(record) {
162
+ const cursor = new BlockCursor(record.blocks);
163
+ const count = cursor.u16();
164
+ const ranges = [];
165
+ for (let index = 0; index < count; index += 1) {
166
+ const startRow = cursor.u16();
167
+ const endRow = cursor.u16();
168
+ const startColumn = cursor.u16();
169
+ const endColumn = cursor.u16();
170
+ ranges.push({
171
+ startRow,
172
+ startColumn,
173
+ endRow,
174
+ endColumn
175
+ });
176
+ }
177
+ return ranges;
178
+ }
179
+ /** The Cell structure ([MS-XLS] 2.5.19) every single-cell record opens with. */
180
+ function readCellHeader(cursor) {
181
+ return {
182
+ row: cursor.u16(),
183
+ column: cursor.u16(),
184
+ xfIndex: cursor.u16()
185
+ };
186
+ }
187
+ function readBlank(record) {
188
+ return {
189
+ ...readCellHeader(new BlockCursor(record.blocks)),
190
+ value: { kind: "blank" },
191
+ fromFormula: false
192
+ };
193
+ }
194
+ /** MulBlank ([MS-XLS] 2.4.174): a run of blank cells in one row, each with its own format index. The entry count is derived from the record's own length rather than from colLast, which sits AFTER the variable-length array. */
195
+ function readMulBlank(record) {
196
+ const cursor = new BlockCursor(record.blocks);
197
+ const row = cursor.u16();
198
+ const first = cursor.u16();
199
+ const count = mulEntryCount(record, MULBLANK_ENTRY_BYTES);
200
+ const cells = [];
201
+ for (let offset = 0; offset < count; offset += 1) cells.push({
202
+ row,
203
+ column: first + offset,
204
+ xfIndex: cursor.u16(),
205
+ value: { kind: "blank" },
206
+ fromFormula: false
207
+ });
208
+ return cells;
209
+ }
210
+ function readRk(record) {
211
+ const cursor = new BlockCursor(record.blocks);
212
+ return {
213
+ row: cursor.u16(),
214
+ column: cursor.u16(),
215
+ xfIndex: cursor.u16(),
216
+ value: {
217
+ kind: "number",
218
+ value: decodeRkNumber(cursor.u32())
219
+ },
220
+ fromFormula: false
221
+ };
222
+ }
223
+ /** MulRk ([MS-XLS] 2.4.175): a run of RK-encoded numeric cells in one row, each an RkRec ([MS-XLS] 2.5.218) of a format index and an RK word. */
224
+ function readMulRk(record) {
225
+ const cursor = new BlockCursor(record.blocks);
226
+ const row = cursor.u16();
227
+ const first = cursor.u16();
228
+ const count = mulEntryCount(record, MULRK_ENTRY_BYTES);
229
+ const cells = [];
230
+ for (let offset = 0; offset < count; offset += 1) {
231
+ const xfIndex = cursor.u16();
232
+ cells.push({
233
+ row,
234
+ column: first + offset,
235
+ xfIndex,
236
+ value: {
237
+ kind: "number",
238
+ value: decodeRkNumber(cursor.u32())
239
+ },
240
+ fromFormula: false
241
+ });
242
+ }
243
+ return cells;
244
+ }
245
+ /** Both Mul records put colLast after their variable-length array, so the entry count follows from the record's own length: total = rw + colFirst + N*entry + colLast. */
246
+ function mulEntryCount(record, entryBytes) {
247
+ const total = record.blocks.reduce((sum, block) => sum + block.length, 0);
248
+ const payload = total - MUL_FIXED_BYTES;
249
+ if (payload < 0 || payload % entryBytes !== 0) throw new BiffFormatError(`multiple-cell record of ${total} bytes does not hold a whole number of ${entryBytes}-byte entries`);
250
+ return payload / entryBytes;
251
+ }
252
+ function readNumber(record) {
253
+ const cursor = new BlockCursor(record.blocks);
254
+ return {
255
+ ...readCellHeader(cursor),
256
+ value: {
257
+ kind: "number",
258
+ value: cursor.f64()
259
+ },
260
+ fromFormula: false
261
+ };
262
+ }
263
+ /** BoolErr ([MS-XLS] 2.4.24): a Cell then a Bes ([MS-XLS] 2.5.10), whose second byte says whether the first is a boolean or an error code. An error code the specification does not define yields no cell at all rather than a fabricated spelling. */
264
+ function readBoolErr(record) {
265
+ const cursor = new BlockCursor(record.blocks);
266
+ const header = readCellHeader(cursor);
267
+ const value = cursor.u8();
268
+ if (!(cursor.u8() !== 0)) return {
269
+ ...header,
270
+ value: {
271
+ kind: "boolean",
272
+ value: value !== 0
273
+ },
274
+ fromFormula: false
275
+ };
276
+ const text = errorTextOf(value);
277
+ return text === void 0 ? void 0 : {
278
+ ...header,
279
+ value: {
280
+ kind: "error",
281
+ value: text
282
+ },
283
+ fromFormula: false
284
+ };
285
+ }
286
+ /** LabelSst ([MS-XLS] 2.4.149): a Cell then a four-byte index into the shared string table. An index the table does not hold yields an empty string rather than throwing, since one dangling index should not fail a whole workbook. */
287
+ function readLabelSst(record, sharedStrings) {
288
+ const cursor = new BlockCursor(record.blocks);
289
+ const header = readCellHeader(cursor);
290
+ const index = cursor.u32();
291
+ return {
292
+ ...header,
293
+ value: {
294
+ kind: "string",
295
+ value: sharedStrings[index] ?? ""
296
+ },
297
+ fromFormula: false
298
+ };
299
+ }
300
+ /**
301
+ * Label ([MS-XLS] 2.4.148): a Cell then an inline XLUnicodeString.
302
+ *
303
+ * In BIFF8 proper a string cell is a LabelSst indexing the shared string table, and [MS-XLS] documents this record in its charting sense. It is read as a string cell anyway because the layout is identical either way and third-party producers -- and files converted up from BIFF5, where Label WAS the string cell record -- still emit it in a worksheet's cell table, where reading it costs nothing and skipping it would silently drop real text.
304
+ */
305
+ function readLabel(record) {
306
+ const cursor = new BlockCursor(record.blocks);
307
+ return {
308
+ ...readCellHeader(cursor),
309
+ value: {
310
+ kind: "string",
311
+ value: readXLUnicodeString(cursor)
312
+ },
313
+ fromFormula: false
314
+ };
315
+ }
316
+ /**
317
+ * Formula ([MS-XLS] 2.4.127): a Cell, an eight-byte FormulaValue, flags, a calculation cache, then the compiled expression.
318
+ *
319
+ * Only the cached VALUE is read. The expression is a CellParsedFormula -- a compiled Ptg token stream rather than text -- and turning one back into a formula string means implementing the whole Ptg vocabulary plus shared-formula and external-reference resolution, which is its own substantial piece of work. So the cell's displayed value is correct and its `formula` field stays absent, rather than a plausible-looking expression being invented for it.
320
+ */
321
+ function readFormula(record, next) {
322
+ const cursor = new BlockCursor(record.blocks);
323
+ const header = readCellHeader(cursor);
324
+ const bytes = cursor.take(8);
325
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
326
+ if (!(view.getUint16(6, true) === FORMULA_VALUE_TAGGED)) return {
327
+ ...header,
328
+ value: {
329
+ kind: "number",
330
+ value: view.getFloat64(0, true)
331
+ },
332
+ fromFormula: true
333
+ };
334
+ return {
335
+ ...header,
336
+ value: taggedFormulaValue(view, next),
337
+ fromFormula: true
338
+ };
339
+ }
340
+ /** The non-numeric readings of a FormulaValue ([MS-XLS] 2.5.133), selected by its first byte. */
341
+ function taggedFormulaValue(view, next) {
342
+ switch (view.getUint8(0)) {
343
+ case FORMULA_VALUE_STRING:
344
+ if (next?.type !== 519) return {
345
+ kind: "string",
346
+ value: ""
347
+ };
348
+ return {
349
+ kind: "string",
350
+ value: readXLUnicodeString(new BlockCursor(next.blocks))
351
+ };
352
+ case FORMULA_VALUE_BOOLEAN: return {
353
+ kind: "boolean",
354
+ value: view.getUint8(2) !== 0
355
+ };
356
+ case FORMULA_VALUE_ERROR: {
357
+ const text = errorTextOf(view.getUint8(2));
358
+ return text === void 0 ? { kind: "blank" } : {
359
+ kind: "error",
360
+ value: text
361
+ };
362
+ }
363
+ case FORMULA_VALUE_BLANK: return {
364
+ kind: "string",
365
+ value: ""
366
+ };
367
+ default: return { kind: "blank" };
368
+ }
369
+ }
370
+ //#endregion
371
+ export { readSheetRecords };
package/package.json CHANGED
@@ -1,5 +1,88 @@
1
1
  {
2
2
  "name": "xls-codec",
3
- "version": "0.0.0",
4
- "private": false
3
+ "version": "1.0.1",
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
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ExaDev/documents.js.git",
9
+ "directory": "packages/xls-codec"
10
+ },
11
+ "homepage": "https://github.com/ExaDev/documents.js/tree/main/packages/xls-codec",
12
+ "bugs": {
13
+ "url": "https://github.com/ExaDev/documents.js/issues"
14
+ },
15
+ "license": "MIT",
16
+ "exports": {
17
+ ".": {
18
+ "types": {
19
+ "import": "./dist/index.d.ts",
20
+ "require": "./dist/index.d.cts"
21
+ },
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs"
24
+ },
25
+ "./*": {
26
+ "types": {
27
+ "import": "./dist/*.d.ts",
28
+ "require": "./dist/*.d.cts"
29
+ },
30
+ "import": "./dist/*.js",
31
+ "require": "./dist/*.cjs"
32
+ }
33
+ },
34
+ "main": "./dist/index.cjs",
35
+ "module": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true,
43
+ "registry": "https://registry.npmjs.org/"
44
+ },
45
+ "sideEffects": false,
46
+ "engines": {
47
+ "node": ">=20"
48
+ },
49
+ "scripts": {
50
+ "build": "turbo run _build",
51
+ "_build": "tsdown",
52
+ "prepublishOnly": "pnpm run lint && pnpm run typecheck && tsdown && publint && attw --pack",
53
+ "lint": "turbo run _lint",
54
+ "_lint": "eslint . --fix --cache --max-warnings 0",
55
+ "lint:check": "eslint . --max-warnings 0",
56
+ "typecheck": "turbo run _typecheck _typecheck:attw",
57
+ "_typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.node.json",
58
+ "_typecheck:attw": "attw --pack",
59
+ "test": "turbo run _test",
60
+ "_test": "vitest run --project unit",
61
+ "test:watch": "vitest --project unit",
62
+ "test:workers": "turbo run _test:workers",
63
+ "_test:workers": "vitest run --config vitest.workers.config.ts",
64
+ "test:smoke": "turbo run _test:smoke",
65
+ "_test:smoke": "vitest run --project smoke",
66
+ "prepare": "husky"
67
+ },
68
+ "packageManager": "pnpm@11.6.0",
69
+ "dependencies": {
70
+ "archive-codec": "^1.3.0",
71
+ "document-schema.js": "^5.4.0"
72
+ },
73
+ "devDependencies": {
74
+ "@arethetypeswrong/cli": "^0.18.5",
75
+ "@cloudflare/vitest-pool-workers": "^0.20.1",
76
+ "@types/node": "^26.1.2",
77
+ "eslint": "^10.8.0",
78
+ "husky": "^9.1.7",
79
+ "publint": "^0.3.21",
80
+ "tsdown": "^0.22.13",
81
+ "turbo": "^2.10.8",
82
+ "typescript": "^6.0.3",
83
+ "vitest": "^4.1.10"
84
+ },
85
+ "lint-staged": {
86
+ "*.ts": "eslint --fix"
87
+ }
5
88
  }