From 2f274dd48c0e537d7fa9ebbc79915a9f97db7941 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 20 Mar 2022 21:39:16 -0400 Subject: [PATCH] book_append_sheet rolling names --- .eslintrc | 1 + README.md | 20 ++- bits/31_rels.js | 3 +- bits/51_xlsxmeta.js | 11 ++ bits/83_numbers.js | 277 +++++++++++++++++++----------- bits/90_utils.js | 12 +- docbits/25_manip.md | 20 ++- misc/51_xlsxmeta.js | 11 ++ misc/docs/README.md | 20 ++- modules/.gitignore | 7 +- modules/51_xlsxmeta.js | 11 ++ modules/51_xlsxmeta.ts | 11 +- modules/83_numbers.js | 277 +++++++++++++++++++----------- modules/83_numbers.ts | 272 ++++++++++++++++++----------- modules/Makefile | 7 +- modules/numbers_to_csv.node.ts | 4 +- modules/reframe.node.ts | 53 ++++++ modules/src/cell.ts | 88 ---------- modules/src/frame.ts | 105 ------------ modules/src/iwa.ts | 40 ----- modules/src/numbers.ts | 228 ------------------------- modules/src/proto.ts | 118 ------------- modules/src/types.ts | 1 + modules/src/util.ts | 56 ------ package.json | 2 +- types/index.d.ts | 2 +- xlsx.flow.js | 303 ++++++++++++++++++++++----------- xlsx.js | 303 ++++++++++++++++++++++----------- xlsx.mjs | 303 ++++++++++++++++++++++----------- 29 files changed, 1308 insertions(+), 1258 deletions(-) create mode 100644 modules/reframe.node.ts delete mode 100644 modules/src/cell.ts delete mode 100644 modules/src/frame.ts delete mode 100644 modules/src/iwa.ts delete mode 100644 modules/src/numbers.ts delete mode 100644 modules/src/proto.ts delete mode 100644 modules/src/util.ts diff --git a/.eslintrc b/.eslintrc index f020fa2..13ef19f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,6 +13,7 @@ "no-bitwise": 0, "no-console": 0, "no-control-regex": 0, + "no-unused-vars": 1, "no-empty": 0, "no-trailing-spaces": 2, "no-use-before-define": [ 1, { diff --git a/README.md b/README.md index fa89a64..7ee39b1 100644 --- a/README.md +++ b/README.md @@ -1388,7 +1388,25 @@ XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name); The `book_append_sheet` utility function appends a worksheet to the workbook. The third argument specifies the desired worksheet name. Multiple worksheets can -be added to a workbook by calling the function multiple times. +be added to a workbook by calling the function multiple times. If the worksheet +name is already used in the workbook, it will throw an error. + +_Append a Worksheet to a Workbook and find a unique name_ + +```js +var new_name = XLSX.utils.book_append_sheet(workbook, worksheet, name, true); +``` + +If the fourth argument is `true`, the function will start with the specified +worksheet name. If the sheet name exists in the workbook, a new worksheet name +will be chosen by finding the name stem and incrementing the counter: + +```js +XLSX.utils.book_append_sheet(workbook, sheetA, "Sheet2", true); // Sheet2 +XLSX.utils.book_append_sheet(workbook, sheetB, "Sheet2", true); // Sheet3 +XLSX.utils.book_append_sheet(workbook, sheetC, "Sheet2", true); // Sheet4 +XLSX.utils.book_append_sheet(workbook, sheetD, "Sheet2", true); // Sheet5 +``` _List the Worksheet names in tab order_ diff --git a/bits/31_rels.js b/bits/31_rels.js index d1da48c..e29600c 100644 --- a/bits/31_rels.js +++ b/bits/31_rels.js @@ -76,7 +76,6 @@ function write_rels(rels)/*:string*/ { return o.join(""); } -var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS]; function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ { if(!relobj) relobj = {}; if(!rels['!id']) rels['!id'] = {}; @@ -87,7 +86,7 @@ function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/) relobj.Type = type; relobj.Target = f; if(targetmode) relobj.TargetMode = targetmode; - else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; + else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId); rels['!id'][relobj.Id] = relobj; rels[('/' + relobj.Target).replace("//","/")] = relobj; diff --git a/bits/51_xlsxmeta.js b/bits/51_xlsxmeta.js index a647c88..25c5860 100644 --- a/bits/51_xlsxmeta.js +++ b/bits/51_xlsxmeta.js @@ -4,6 +4,7 @@ function parse_xlmeta_xml(data, name, opts) { return out; var pass = false; var metatype = 2; + var lastmeta; data.replace(tagregex, function(x) { var y = parsexmltag(x); switch (strip_ns(y[0])) { @@ -21,6 +22,9 @@ function parse_xlmeta_xml(data, name, opts) { case "": break; case "": break; @@ -59,6 +63,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case "> 1 & 1431655765; x = (x & 858993459) + (x >> 2 & 858993459); return (x + (x >> 4) & 252645135) * 16843009 >>> 24; -}; -var readDecimal128LE = function(buf, offset) { +} +function readDecimal128LE(buf, offset) { var exp = (buf[offset + 15] & 127) << 7 | buf[offset + 14] >> 1; var mantissa = buf[offset + 14] & 1; for (var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return (buf[offset + 15] & 128 ? -mantissa : mantissa) * Math.pow(10, exp - 6176); -}; +} function parse_varint49(buf, ptr) { var l = ptr ? ptr[0] : 0; var usz = buf[l] & 127; @@ -60,6 +60,43 @@ function parse_varint49(buf, ptr) { ptr[0] = l; return usz; } +function write_varint49(v) { + var usz = new Uint8Array(7); + usz[0] = v & 127; + var L = 1; + sz: + if (v > 127) { + usz[L - 1] |= 128; + usz[L] = v >> 7 & 127; + ++L; + if (v <= 16383) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 14 & 127; + ++L; + if (v <= 2097151) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 21 & 127; + ++L; + if (v <= 268435455) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 256 >>> 21 & 127; + ++L; + if (v <= 34359738367) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 65536 >>> 21 & 127; + ++L; + if (v <= 4398046511103) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 16777216 >>> 21 & 127; + ++L; + } + return usz.slice(0, L); +} function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; varint: @@ -228,7 +265,7 @@ function parse_snappy_chunk(type, buf) { throw new Error("Unexpected length: ".concat(o.length, " != ").concat(usz)); return o; } -function deframe(buf) { +function decompress_iwa_file(buf) { var out = []; var l = 0; while (l < buf.length) { @@ -242,17 +279,52 @@ function deframe(buf) { throw new Error("data is not a valid framed stream!"); return u8concat(out); } -function parse_old_storage(buf, sst, rsst) { +function compress_iwa_file(buf) { + var out = []; + var l = 0; + while (l < buf.length) { + var c = Math.min(buf.length - l, 268435455); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + if (c <= 60) { + L++; + out.push(new Uint8Array([c - 1 << 2])); + } else if (c <= 256) { + L += 2; + out.push(new Uint8Array([240, c - 1 & 255])); + } else if (c <= 65536) { + L += 3; + out.push(new Uint8Array([244, c - 1 & 255, c - 1 >> 8 & 255])); + } else if (c <= 16777216) { + L += 4; + out.push(new Uint8Array([248, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255])); + } else if (c <= 4294967296) { + L += 5; + out.push(new Uint8Array([252, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255, c - 1 >>> 24 & 255])); + } + out.push(buf.slice(l, l + c)); + L += c; + frame[0] = 0; + frame[1] = L & 255; + frame[2] = L >> 8 & 255; + frame[3] = L >> 16 & 255; + l += c; + } + return u8concat(out); +} +function parse_old_storage(buf, sst, rsst, v) { var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 3470) * 4; + var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if (flags & 512) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 12288) * 4; + data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4; if (flags & 16) { sidx = dv.getUint32(data_offset, true); data_offset += 4; @@ -266,7 +338,7 @@ function parse_old_storage(buf, sst, rsst) { data_offset += 8; } var ret; - switch (ctype) { + switch (buf[2]) { case 0: break; case 2: @@ -306,7 +378,6 @@ function parse_old_storage(buf, sst, rsst) { } function parse_storage(buf, sst, rsst) { var dv = u8_to_dataview(buf); - var ctype = buf[1]; var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -331,7 +402,7 @@ function parse_storage(buf, sst, rsst) { data_offset += 4; } var ret; - switch (ctype) { + switch (buf[1]) { case 0: break; case 2: @@ -357,22 +428,24 @@ function parse_storage(buf, sst, rsst) { if (ridx > -1) ret = { t: "s", v: rsst[ridx] }; else - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } break; case 10: ret = { t: "n", v: d128 }; break; default: - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } return ret; } function parse_cell_storage(buf, sst, rsst) { switch (buf[0]) { + case 0: + case 1: + case 2: case 3: - case 4: - return parse_old_storage(buf, sst, rsst); + return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: @@ -413,47 +486,57 @@ function parse_TST_TableDataList(M, root) { }); return data; } -function parse_TST_TileRowInfo(u8) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; +function parse_TST_TileRowInfo(u8, type) { + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = (_b = (_a = pb[3]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data; - var pre_bnc_offsets = ((_d = (_c = pb[4]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && u8_to_dataview(pb[4][0].data); - var storage = (_f = (_e = pb[6]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; - var storage_offsets = ((_h = (_g = pb[7]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data) && u8_to_dataview(pb[7][0].data); - var wide_offsets = ((_j = (_i = pb[8]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + var wide_offsets = ((_b = (_a = pb[8]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var used_storage_u8, used_storage; + if (((_d = (_c = pb[7]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && type != 0) { + used_storage_u8 = (_f = (_e = pb[7]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; + used_storage = (_h = (_g = pb[6]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data; + } else if (((_j = (_i = pb[4]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && type != 1) { + used_storage_u8 = (_l = (_k = pb[4]) == null ? void 0 : _k[0]) == null ? void 0 : _l.data; + used_storage = (_n = (_m = pb[3]) == null ? void 0 : _m[0]) == null ? void 0 : _n.data; + } else + throw "NUMBERS Tile missing ".concat(type, " cell storage"); var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for (var C = 0; C < pre_bnc_offsets.byteLength / 2; ++C) { - if (storage && storage_offsets) { - off = storage_offsets.getUint16(C * 2, true) * width; - if (off < storage.length) { - cells[C] = storage.subarray(off, storage_offsets.getUint16(C * 2 + 2, true) * width); - continue; - } - } - if (pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C * 2, true) * width; - if (off < pre_bnc.length) - cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C * 2 + 2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets = []; + for (var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C * 2, true); + if (off < 65535) + offsets.push([C, off]); } + if (offsets.length != cnt) + throw "Expected ".concat(cnt, " cells, found ").concat(offsets.length); + var cells = []; + for (C = 0; C < offsets.length - 1; ++C) + cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C + 1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R: R, cells: cells }; } function parse_TST_Tile(M, root) { + var _a; var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce(function(acc, x) { - if (!acc[x.R]) - acc[x.R] = []; - x.cells.forEach(function(cell, C) { - if (acc[x.R][C]) - throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); - acc[x.R][C] = cell; - }); - return acc; - }, []); + var storage = ((_a = pb == null ? void 0 : pb[7]) == null ? void 0 : _a[0]) ? varint_to_i32(pb[7][0].data) >>> 0 > 0 ? 1 : 0 : -1; + var ri = mappa(pb[5], function(u8) { + return parse_TST_TileRowInfo(u8, storage); + }); + return { + nrows: varint_to_i32(pb[4][0].data) >>> 0, + data: ri.reduce(function(acc, x) { + if (!acc[x.R]) + acc[x.R] = []; + x.cells.forEach(function(cell, C) { + if (acc[x.R][C]) + throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); + acc[x.R][C] = cell; + }); + return acc; + }, []) + }; } function parse_TST_TableModelArchive(M, root, ws) { var _a; @@ -466,33 +549,28 @@ function parse_TST_TableModelArchive(M, root, ws) { if (range.e.c < 0) throw new Error("Invalid col varint ".concat(pb[7][0].data)); ws["!ref"] = encode_range(range); - { - var store = parse_shallow(pb[4][0].data); - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - var tile = parse_shallow(store[3][0].data); - var tiles = []; - tile[1].forEach(function(t) { - var tl = parse_shallow(t.data); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if (mtype != 6002) - throw new Error("6001 unexpected reference to ".concat(mtype)); - tiles.push({ id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; + var tile = parse_shallow(store[3][0].data); + var _R = 0; + tile[1].forEach(function(t) { + var tl = parse_shallow(t.data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if (mtype != 6002) + throw new Error("6001 unexpected reference to ".concat(mtype)); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach(function(row, R) { + row.forEach(function(buf, C) { + var addr = encode_cell({ r: _R + R, c: C }); + var res = parse_cell_storage(buf, sst, rsst); + if (res) + ws[addr] = res; }); - tiles.forEach(function(tile2) { - tile2.ref.forEach(function(row, R) { - row.forEach(function(buf, C) { - var addr = encode_cell({ r: R, c: C }); - var res = parse_cell_storage(buf, sst, rsst); - if (res) - ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } function parse_TST_TableInfoArchive(M, root) { var pb = parse_shallow(root.data); @@ -530,8 +608,8 @@ function parse_TN_DocumentArchive(M, root) { var mtype = varint_to_i32(m.meta[1][0].data); if (mtype == 2) { var root2 = parse_TN_SheetArchive(M, m); - root2.sheets.forEach(function(sheet) { - book_append_sheet(out, sheet, root2.name); + root2.sheets.forEach(function(sheet, idx) { + book_append_sheet(out, sheet, idx == 0 ? root2.name : root2.name + "_" + idx, true); }); } }); @@ -541,7 +619,8 @@ function parse_TN_DocumentArchive(M, root) { return out; } function parse_numbers_iwa(cfb) { - var out = []; + var _a, _b, _c, _d; + var out = {}, indices = []; cfb.FullPaths.forEach(function(p) { if (p.match(/\.iwpv2/)) throw new Error("Unsupported password protection"); @@ -551,7 +630,7 @@ function parse_numbers_iwa(cfb) { return; var o; try { - o = deframe(s.content); + o = decompress_iwa_file(s.content); } catch (e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } @@ -562,23 +641,25 @@ function parse_numbers_iwa(cfb) { return console.log("## " + (e.message || e)); } packets.forEach(function(packet) { - out[+packet.id] = packet.messages; + out[packet.id] = packet.messages; + indices.push(packet.id); }); }); - if (!out.length) + if (!indices.length) throw new Error("File has no messages"); - var docroot; - out.forEach(function(iwams) { - iwams.forEach(function(iwam) { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if (mtype == 1) { - if (!docroot) - docroot = iwam; - else - throw new Error("Document has multiple roots"); - } + var docroot = ((_d = (_c = (_b = (_a = out == null ? void 0 : out[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.meta) == null ? void 0 : _c[1]) == null ? void 0 : _d[0].data) && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if (!docroot) + indices.forEach(function(idx) { + out[idx].forEach(function(iwam) { + var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; + if (mtype == 1) { + if (!docroot) + docroot = iwam; + else + throw new Error("Document has multiple roots"); + } + }); }); - }); if (!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); diff --git a/bits/90_utils.js b/bits/90_utils.js index b69a87c..13d2d29 100644 --- a/bits/90_utils.js +++ b/bits/90_utils.js @@ -287,14 +287,22 @@ function book_new()/*:Workbook*/ { } /* add a worksheet to the end of a given workbook */ -function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) { - if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; +function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ { + var i = 1; + if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets"); + if(roll && wb.SheetNames.indexOf(name) >= 0) { + var m = name.match(/(^.*?)(\d+)$/); + i = m && +m[2] || 0; + var root = m && m[1] || name; + for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break; + } check_ws_name(name); if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!"); wb.SheetNames.push(name); wb.Sheets[name] = ws; + return name; } /* set sheet visibility (visible/hidden/very hidden) */ diff --git a/docbits/25_manip.md b/docbits/25_manip.md index 330cfc6..252978e 100644 --- a/docbits/25_manip.md +++ b/docbits/25_manip.md @@ -16,7 +16,25 @@ XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name); The `book_append_sheet` utility function appends a worksheet to the workbook. The third argument specifies the desired worksheet name. Multiple worksheets can -be added to a workbook by calling the function multiple times. +be added to a workbook by calling the function multiple times. If the worksheet +name is already used in the workbook, it will throw an error. + +_Append a Worksheet to a Workbook and find a unique name_ + +```js +var new_name = XLSX.utils.book_append_sheet(workbook, worksheet, name, true); +``` + +If the fourth argument is `true`, the function will start with the specified +worksheet name. If the sheet name exists in the workbook, a new worksheet name +will be chosen by finding the name stem and incrementing the counter: + +```js +XLSX.utils.book_append_sheet(workbook, sheetA, "Sheet2", true); // Sheet2 +XLSX.utils.book_append_sheet(workbook, sheetB, "Sheet2", true); // Sheet3 +XLSX.utils.book_append_sheet(workbook, sheetC, "Sheet2", true); // Sheet4 +XLSX.utils.book_append_sheet(workbook, sheetD, "Sheet2", true); // Sheet5 +``` _List the Worksheet names in tab order_ diff --git a/misc/51_xlsxmeta.js b/misc/51_xlsxmeta.js index a647c88..25c5860 100644 --- a/misc/51_xlsxmeta.js +++ b/misc/51_xlsxmeta.js @@ -4,6 +4,7 @@ function parse_xlmeta_xml(data, name, opts) { return out; var pass = false; var metatype = 2; + var lastmeta; data.replace(tagregex, function(x) { var y = parsexmltag(x); switch (strip_ns(y[0])) { @@ -21,6 +22,9 @@ function parse_xlmeta_xml(data, name, opts) { case "": break; case "": break; @@ -59,6 +63,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case "": break; case "": break; @@ -59,6 +63,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case " { var y: any = parsexmltag(x); @@ -25,7 +26,9 @@ function parse_xlmeta_xml(data: string, name: string, opts?: ParseXLMetaOptions) case '': break; /* 18.9.4 */ - case '': break; /* 18.9.1 */ @@ -54,6 +57,12 @@ function parse_xlmeta_xml(data: string, name: string, opts?: ParseXLMetaOptions) case '': pass=false; break; + case '> 1 & 1431655765; x = (x & 858993459) + (x >> 2 & 858993459); return (x + (x >> 4) & 252645135) * 16843009 >>> 24; -}; -var readDecimal128LE = function(buf, offset) { +} +function readDecimal128LE(buf, offset) { var exp = (buf[offset + 15] & 127) << 7 | buf[offset + 14] >> 1; var mantissa = buf[offset + 14] & 1; for (var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return (buf[offset + 15] & 128 ? -mantissa : mantissa) * Math.pow(10, exp - 6176); -}; +} function parse_varint49(buf, ptr) { var l = ptr ? ptr[0] : 0; var usz = buf[l] & 127; @@ -60,6 +60,43 @@ function parse_varint49(buf, ptr) { ptr[0] = l; return usz; } +function write_varint49(v) { + var usz = new Uint8Array(7); + usz[0] = v & 127; + var L = 1; + sz: + if (v > 127) { + usz[L - 1] |= 128; + usz[L] = v >> 7 & 127; + ++L; + if (v <= 16383) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 14 & 127; + ++L; + if (v <= 2097151) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 21 & 127; + ++L; + if (v <= 268435455) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 256 >>> 21 & 127; + ++L; + if (v <= 34359738367) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 65536 >>> 21 & 127; + ++L; + if (v <= 4398046511103) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 16777216 >>> 21 & 127; + ++L; + } + return usz.slice(0, L); +} function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; varint: @@ -228,7 +265,7 @@ function parse_snappy_chunk(type, buf) { throw new Error("Unexpected length: ".concat(o.length, " != ").concat(usz)); return o; } -function deframe(buf) { +function decompress_iwa_file(buf) { var out = []; var l = 0; while (l < buf.length) { @@ -242,17 +279,52 @@ function deframe(buf) { throw new Error("data is not a valid framed stream!"); return u8concat(out); } -function parse_old_storage(buf, sst, rsst) { +function compress_iwa_file(buf) { + var out = []; + var l = 0; + while (l < buf.length) { + var c = Math.min(buf.length - l, 268435455); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + if (c <= 60) { + L++; + out.push(new Uint8Array([c - 1 << 2])); + } else if (c <= 256) { + L += 2; + out.push(new Uint8Array([240, c - 1 & 255])); + } else if (c <= 65536) { + L += 3; + out.push(new Uint8Array([244, c - 1 & 255, c - 1 >> 8 & 255])); + } else if (c <= 16777216) { + L += 4; + out.push(new Uint8Array([248, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255])); + } else if (c <= 4294967296) { + L += 5; + out.push(new Uint8Array([252, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255, c - 1 >>> 24 & 255])); + } + out.push(buf.slice(l, l + c)); + L += c; + frame[0] = 0; + frame[1] = L & 255; + frame[2] = L >> 8 & 255; + frame[3] = L >> 16 & 255; + l += c; + } + return u8concat(out); +} +function parse_old_storage(buf, sst, rsst, v) { var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 3470) * 4; + var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if (flags & 512) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 12288) * 4; + data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4; if (flags & 16) { sidx = dv.getUint32(data_offset, true); data_offset += 4; @@ -266,7 +338,7 @@ function parse_old_storage(buf, sst, rsst) { data_offset += 8; } var ret; - switch (ctype) { + switch (buf[2]) { case 0: break; case 2: @@ -306,7 +378,6 @@ function parse_old_storage(buf, sst, rsst) { } function parse_storage(buf, sst, rsst) { var dv = u8_to_dataview(buf); - var ctype = buf[1]; var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -331,7 +402,7 @@ function parse_storage(buf, sst, rsst) { data_offset += 4; } var ret; - switch (ctype) { + switch (buf[1]) { case 0: break; case 2: @@ -357,22 +428,24 @@ function parse_storage(buf, sst, rsst) { if (ridx > -1) ret = { t: "s", v: rsst[ridx] }; else - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } break; case 10: ret = { t: "n", v: d128 }; break; default: - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } return ret; } function parse_cell_storage(buf, sst, rsst) { switch (buf[0]) { + case 0: + case 1: + case 2: case 3: - case 4: - return parse_old_storage(buf, sst, rsst); + return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: @@ -413,47 +486,57 @@ function parse_TST_TableDataList(M, root) { }); return data; } -function parse_TST_TileRowInfo(u8) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; +function parse_TST_TileRowInfo(u8, type) { + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = (_b = (_a = pb[3]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data; - var pre_bnc_offsets = ((_d = (_c = pb[4]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && u8_to_dataview(pb[4][0].data); - var storage = (_f = (_e = pb[6]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; - var storage_offsets = ((_h = (_g = pb[7]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data) && u8_to_dataview(pb[7][0].data); - var wide_offsets = ((_j = (_i = pb[8]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + var wide_offsets = ((_b = (_a = pb[8]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var used_storage_u8, used_storage; + if (((_d = (_c = pb[7]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && type != 0) { + used_storage_u8 = (_f = (_e = pb[7]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; + used_storage = (_h = (_g = pb[6]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data; + } else if (((_j = (_i = pb[4]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && type != 1) { + used_storage_u8 = (_l = (_k = pb[4]) == null ? void 0 : _k[0]) == null ? void 0 : _l.data; + used_storage = (_n = (_m = pb[3]) == null ? void 0 : _m[0]) == null ? void 0 : _n.data; + } else + throw "NUMBERS Tile missing ".concat(type, " cell storage"); var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for (var C = 0; C < pre_bnc_offsets.byteLength / 2; ++C) { - if (storage && storage_offsets) { - off = storage_offsets.getUint16(C * 2, true) * width; - if (off < storage.length) { - cells[C] = storage.subarray(off, storage_offsets.getUint16(C * 2 + 2, true) * width); - continue; - } - } - if (pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C * 2, true) * width; - if (off < pre_bnc.length) - cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C * 2 + 2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets = []; + for (var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C * 2, true); + if (off < 65535) + offsets.push([C, off]); } + if (offsets.length != cnt) + throw "Expected ".concat(cnt, " cells, found ").concat(offsets.length); + var cells = []; + for (C = 0; C < offsets.length - 1; ++C) + cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C + 1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R: R, cells: cells }; } function parse_TST_Tile(M, root) { + var _a; var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce(function(acc, x) { - if (!acc[x.R]) - acc[x.R] = []; - x.cells.forEach(function(cell, C) { - if (acc[x.R][C]) - throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); - acc[x.R][C] = cell; - }); - return acc; - }, []); + var storage = ((_a = pb == null ? void 0 : pb[7]) == null ? void 0 : _a[0]) ? varint_to_i32(pb[7][0].data) >>> 0 > 0 ? 1 : 0 : -1; + var ri = mappa(pb[5], function(u8) { + return parse_TST_TileRowInfo(u8, storage); + }); + return { + nrows: varint_to_i32(pb[4][0].data) >>> 0, + data: ri.reduce(function(acc, x) { + if (!acc[x.R]) + acc[x.R] = []; + x.cells.forEach(function(cell, C) { + if (acc[x.R][C]) + throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); + acc[x.R][C] = cell; + }); + return acc; + }, []) + }; } function parse_TST_TableModelArchive(M, root, ws) { var _a; @@ -466,33 +549,28 @@ function parse_TST_TableModelArchive(M, root, ws) { if (range.e.c < 0) throw new Error("Invalid col varint ".concat(pb[7][0].data)); ws["!ref"] = encode_range(range); - { - var store = parse_shallow(pb[4][0].data); - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - var tile = parse_shallow(store[3][0].data); - var tiles = []; - tile[1].forEach(function(t) { - var tl = parse_shallow(t.data); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if (mtype != 6002) - throw new Error("6001 unexpected reference to ".concat(mtype)); - tiles.push({ id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; + var tile = parse_shallow(store[3][0].data); + var _R = 0; + tile[1].forEach(function(t) { + var tl = parse_shallow(t.data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if (mtype != 6002) + throw new Error("6001 unexpected reference to ".concat(mtype)); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach(function(row, R) { + row.forEach(function(buf, C) { + var addr = encode_cell({ r: _R + R, c: C }); + var res = parse_cell_storage(buf, sst, rsst); + if (res) + ws[addr] = res; }); - tiles.forEach(function(tile2) { - tile2.ref.forEach(function(row, R) { - row.forEach(function(buf, C) { - var addr = encode_cell({ r: R, c: C }); - var res = parse_cell_storage(buf, sst, rsst); - if (res) - ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } function parse_TST_TableInfoArchive(M, root) { var pb = parse_shallow(root.data); @@ -530,8 +608,8 @@ function parse_TN_DocumentArchive(M, root) { var mtype = varint_to_i32(m.meta[1][0].data); if (mtype == 2) { var root2 = parse_TN_SheetArchive(M, m); - root2.sheets.forEach(function(sheet) { - book_append_sheet(out, sheet, root2.name); + root2.sheets.forEach(function(sheet, idx) { + book_append_sheet(out, sheet, idx == 0 ? root2.name : root2.name + "_" + idx, true); }); } }); @@ -541,7 +619,8 @@ function parse_TN_DocumentArchive(M, root) { return out; } function parse_numbers_iwa(cfb) { - var out = []; + var _a, _b, _c, _d; + var out = {}, indices = []; cfb.FullPaths.forEach(function(p) { if (p.match(/\.iwpv2/)) throw new Error("Unsupported password protection"); @@ -551,7 +630,7 @@ function parse_numbers_iwa(cfb) { return; var o; try { - o = deframe(s.content); + o = decompress_iwa_file(s.content); } catch (e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } @@ -562,23 +641,25 @@ function parse_numbers_iwa(cfb) { return console.log("## " + (e.message || e)); } packets.forEach(function(packet) { - out[+packet.id] = packet.messages; + out[packet.id] = packet.messages; + indices.push(packet.id); }); }); - if (!out.length) + if (!indices.length) throw new Error("File has no messages"); - var docroot; - out.forEach(function(iwams) { - iwams.forEach(function(iwam) { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if (mtype == 1) { - if (!docroot) - docroot = iwam; - else - throw new Error("Document has multiple roots"); - } + var docroot = ((_d = (_c = (_b = (_a = out == null ? void 0 : out[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.meta) == null ? void 0 : _c[1]) == null ? void 0 : _d[0].data) && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if (!docroot) + indices.forEach(function(idx) { + out[idx].forEach(function(iwam) { + var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; + if (mtype == 1) { + if (!docroot) + docroot = iwam; + else + throw new Error("Document has multiple roots"); + } + }); }); - }); if (!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); diff --git a/modules/83_numbers.ts b/modules/83_numbers.ts index 90f7fbe..405d770 100644 --- a/modules/83_numbers.ts +++ b/modules/83_numbers.ts @@ -1,6 +1,7 @@ /*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ /// +/* these are type imports and do not show up in the generated JS */ import { CFB$Container } from 'cfb'; import { WorkBook, WorkSheet, Range, CellObject } from '../'; import type { utils } from "../"; @@ -9,34 +10,37 @@ declare var encode_cell: typeof utils.encode_cell; declare var encode_range: typeof utils.encode_range; declare var book_new: typeof utils.book_new; declare var book_append_sheet: typeof utils.book_append_sheet; +//< new DataView(array.buffer, array.byteOffset, array.byteLength); +function u8str(u8: Uint8Array): string { return /* Buffer.isBuffer(u8) ? u8.toString() :*/ typeof TextDecoder != "undefined" ? new TextDecoder().decode(u8) : utf8read(a2s(u8)); } -var u8str = (u8: Uint8Array): string => /* Buffer.isBuffer(u8) ? u8.toString() :*/ typeof TextDecoder != "undefined" ? new TextDecoder().decode(u8) : utf8read(a2s(u8)); - -var u8concat = (u8a: Uint8Array[]): Uint8Array => { +/** Concatenate Uint8Arrays */ +function u8concat(u8a: Uint8Array[]): Uint8Array { var len = u8a.reduce((acc: number, x: Uint8Array) => acc + x.length, 0); var out = new Uint8Array(len); var off = 0; u8a.forEach(u8 => { out.set(u8, off); off += u8.length; }); return out; -}; +} +//< { +/** Count the number of bits set (assuming int32_t interpretation) */ +function popcnt(x: number): number { x -= ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >>> 24; -}; +} -/* Used in the modern cell storage */ -var readDecimal128LE = (buf: Uint8Array, offset: number): number => { +/** Read a 128-bit decimal from the modern cell storage */ +function readDecimal128LE(buf: Uint8Array, offset: number): number { var exp = ((buf[offset + 15] & 0x7F) << 7) | (buf[offset + 14] >> 1); var mantissa = buf[offset + 14] & 1; for(var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return ((buf[offset+15] & 0x80) ? -mantissa : mantissa) * Math.pow(10, exp - 0x1820); -}; +} type Ptr = [number]; @@ -55,7 +59,6 @@ function parse_varint49(buf: Uint8Array, ptr?: Ptr): number { if(ptr) ptr[0] = l; return usz; } -/* function write_varint49(v: number): Uint8Array { var usz = new Uint8Array(7); usz[0] = (v & 0x7F); @@ -75,7 +78,6 @@ function write_varint49(v: number): Uint8Array { } return usz.slice(0, L); } -*/ /** Parse a 32-bit signed integer from the raw varint */ function varint_to_i32(buf: Uint8Array): number { @@ -96,7 +98,7 @@ interface ProtoItem { } type ProtoField = Array type ProtoMessage = Array; -/** Shallow parse of a message */ +/** Shallow parse of a Protobuf message */ function parse_shallow(buf: Uint8Array): ProtoMessage { var out: ProtoMessage = [], ptr: Ptr = [0]; while(ptr[0] < buf.length) { @@ -139,6 +141,7 @@ function write_shallow(proto: ProtoMessage): Uint8Array { } */ +/** Map over each entry in a repeated (or single-value) field */ function mappa(data: ProtoField, cb:(Uint8Array) => U): U[] { if(!data) return []; return data.map((d) => { try { @@ -160,7 +163,7 @@ interface IWAArchiveInfo { id?: number; messages?: IWAMessage[]; } - +/** Extract all messages from a IWA file */ function parse_iwa_file(buf: Uint8Array): IWAArchiveInfo[] { var out: IWAArchiveInfo[] = [], ptr: Ptr = [0]; while(ptr[0] < buf.length) { @@ -187,6 +190,7 @@ function parse_iwa_file(buf: Uint8Array): IWAArchiveInfo[] { return out; } +/** Decompress a snappy chunk */ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array { if(type != 0) throw new Error(`Unexpected Snappy chunk type ${type}`); var ptr: Ptr = [0]; @@ -237,7 +241,8 @@ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array { return o; } -function deframe(buf: Uint8Array): Uint8Array { +/** Decompress IWA file */ +function decompress_iwa_file(buf: Uint8Array): Uint8Array { var out = []; var l = 0; while(l < buf.length) { @@ -250,23 +255,51 @@ function deframe(buf: Uint8Array): Uint8Array { return u8concat(out); } -function parse_old_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { +/** Compress IWA file */ +function compress_iwa_file(buf: Uint8Array): Uint8Array { + var out: Uint8Array[] = []; + var l = 0; + while(l < buf.length) { + var c = Math.min(buf.length - l, 0xFFFFFFF); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + + if(c <= 60) { L++; out.push(new Uint8Array([(c - 1)<<2])); } + else if(c <= 0x100) { L += 2; out.push(new Uint8Array([0xF0, (c-1) & 0xFF])); } + else if(c <= 0x10000) { L += 3; out.push(new Uint8Array([0xF4, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF])); } + else if(c <= 0x1000000) { L += 4; out.push(new Uint8Array([0xF8, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF, ((c-1) >> 16) & 0xFF])); } + else if(c <= 0x100000000) { L += 5; out.push(new Uint8Array([0xFC, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF, ((c-1) >> 16) & 0xFF, ((c-1) >>> 24) & 0xFF])); } + + out.push(buf.slice(l, l + c)); L += c; + + frame[0] = 0; + frame[1] = L & 0xFF; frame[2] = (L >> 8) & 0xFF; frame[3] = (L >> 16) & 0xFF; + l += c; + } + return u8concat(out); +} +//< 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 0x0D8E : 0x018E)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if(flags & 0x0200) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 0x3000) * 4; + data_offset += popcnt(flags & (v > 1 ? 0x3000 : 0x1000)) * 4; if(flags & 0x0010) { sidx = dv.getUint32(data_offset, true); data_offset += 4; } if(flags & 0x0020) { ieee = dv.getFloat64(data_offset, true); data_offset += 8; } if(flags & 0x0040) { dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1000); data_offset += 8; } var ret: CellObject; - switch(ctype) { + switch(buf[2]) { case 0: break; // return { t: "z" }; // blank? case 2: ret = { t: "n", v: ieee }; break; // number case 3: ret = { t: "s", v: sst[sidx] }; break; // string @@ -289,10 +322,9 @@ function parse_old_storage(buf: Uint8Array, sst: string[], rsst: string[]): Cell function parse_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { var dv = u8_to_dataview(buf); - var ctype = buf[1]; + var flags = dv.getUint32(8, true); /* TODO: find the correct field position of number formats, formulae, etc */ - var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -304,7 +336,7 @@ function parse_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObje if(flags & 0x0010) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } var ret: CellObject; - switch(ctype) { + switch(buf[1]) { case 0: break; // return { t: "z" }; // blank? case 2: ret = { t: "n", v: d128 }; break; // number case 3: ret = { t: "s", v: sst[sidx] }; break; // string @@ -314,10 +346,10 @@ function parse_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObje case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents case 9: { // "automatic"? if(ridx > -1) ret = { t: "s", v: rsst[ridx] }; - else throw new Error(`Unsupported cell type ${ctype} : ${flags & 0x1F} : ${buf.slice(0,4)}`); + else throw new Error(`Unsupported cell type ${buf[1]} : ${flags & 0x1F} : ${buf.slice(0,4)}`); } break; case 10: ret = { t: "n", v: d128 }; break; // currency - default: throw new Error(`Unsupported cell type ${ctype} : ${flags & 0x1F} : ${buf.slice(0,4)}`); + default: throw new Error(`Unsupported cell type ${buf[1]} : ${flags & 0x1F} : ${buf.slice(0,4)}`); } /* TODO: All styling fields appear after the cell data */ @@ -326,21 +358,28 @@ function parse_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObje function parse_cell_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { switch(buf[0]) { - /* TODO: 0-2? */ - case 3: case 4: return parse_old_storage(buf, sst, rsst); + case 0: case 1: + case 2: case 3: return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: throw new Error(`Unsupported payload version ${buf[0]}`); } } -// .TSP.Reference +/** .TSS.StylesheetArchive */ +//function parse_TSS_StylesheetArchive(M: IWAMessage[][], root: IWAMessage): void { +// var pb = parse_shallow(root.data); +//} + +/** .TSP.Reference */ function parse_TSP_Reference(buf: Uint8Array): number { var pb = parse_shallow(buf); return parse_varint49(pb[1][0].data); } -// .TST.TableDataList -function parse_TST_TableDataList(M: IWAMessage[][], root: IWAMessage): string[] { +type MessageSpace = {[id: number]: IWAMessage[]}; + +/** .TST.TableDataList */ +function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): string[] { var pb = parse_shallow(root.data); // .TST.TableDataList.ListType var type = varint_to_i32(pb[1][0].data); @@ -371,52 +410,67 @@ function parse_TST_TableDataList(M: IWAMessage[][], root: IWAMessage): string[] return data; } +type TileStorageType = -1 | 0 | 1; interface TileRowInfo { + /** Row Index */ R: number; + /** Cell Storage */ cells?: Uint8Array[]; } -// .TSP.TileRowInfo -function parse_TST_TileRowInfo(u8: Uint8Array): TileRowInfo { +/** .TSP.TileRowInfo */ +function parse_TST_TileRowInfo(u8: Uint8Array, type: TileStorageType): TileRowInfo { var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = pb[3]?.[0]?.data; - var pre_bnc_offsets = pb[4]?.[0]?.data && u8_to_dataview(pb[4][0].data); - var storage = pb[6]?.[0]?.data; - var storage_offsets = pb[7]?.[0]?.data && u8_to_dataview(pb[7][0].data); + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + // var version = pb?.[5]?.[0] && (varint_to_i32(pb[5][0].data) >>> 0); var wide_offsets = pb[8]?.[0]?.data && varint_to_i32(pb[8][0].data) > 0 || false; + + /* select storage by type (1 = modern / 0 = old / -1 = try modern, old) */ + var used_storage_u8: Uint8Array, used_storage: Uint8Array; + if(pb[7]?.[0]?.data && type != 0) { used_storage_u8 = pb[7]?.[0]?.data; used_storage = pb[6]?.[0]?.data; } + else if(pb[4]?.[0]?.data && type != 1) { used_storage_u8 = pb[4]?.[0]?.data; used_storage = pb[3]?.[0]?.data; } + else throw `NUMBERS Tile missing ${type} cell storage`; + + /* find all offsets -- 0xFFFF means cells are not present */ var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for(var C = 0; C < pre_bnc_offsets.byteLength/2; ++C) { - /* prefer storage if it is present, otherwise fall back on pre_bnc */ - if(storage && storage_offsets) { - off = storage_offsets.getUint16(C*2, true) * width; - if(off < storage.length) { cells[C] = storage.subarray(off, storage_offsets.getUint16(C*2+2, true) * width); continue; } - } - if(pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C*2, true) * width; - if(off < pre_bnc.length) cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C*2+2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets: Array<[number, number]> = []; + for(var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C*2, true); + if(off < 65535) offsets.push([C, off]); } + if(offsets.length != cnt) throw `Expected ${cnt} cells, found ${offsets.length}`; + + var cells: Uint8Array[] = []; + for(C = 0; C < offsets.length - 1; ++C) cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C+1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R, cells }; } -// .TST.Tile -function parse_TST_Tile(M: IWAMessage[][], root: IWAMessage): Uint8Array[][] { +interface TileInfo { + data: Uint8Array[][]; + nrows: number; +} +/** .TST.Tile */ +function parse_TST_Tile(M: MessageSpace, root: IWAMessage): TileInfo { var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce((acc, x) => { - if(!acc[x.R]) acc[x.R] = []; - x.cells.forEach((cell, C) => { - if(acc[x.R][C]) throw new Error(`Duplicate cell r=${x.R} c=${C}`); - acc[x.R][C] = cell; - }); - return acc; - }, [] as Uint8Array[][]); + var storage: TileStorageType = (pb?.[7]?.[0]) ? ((varint_to_i32(pb[7][0].data)>>>0) > 0 ? 1 : 0 ) : -1; + var ri = mappa(pb[5], (u8: Uint8Array) => parse_TST_TileRowInfo(u8, storage)); + return { + nrows: varint_to_i32(pb[4][0].data)>>>0, + data: ri.reduce((acc, x) => { + if(!acc[x.R]) acc[x.R] = []; + x.cells.forEach((cell, C) => { + if(acc[x.R][C]) throw new Error(`Duplicate cell r=${x.R} c=${C}`); + acc[x.R][C] = cell; + }); + return acc; + }, [] as Uint8Array[][]) + }; } -// .TST.TableModelArchive -function parse_TST_TableModelArchive(M: IWAMessage[][], root: IWAMessage, ws: WorkSheet) { +/** .TST.TableModelArchive */ +function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: WorkSheet) { var pb = parse_shallow(root.data); var range: Range = { s: {r:0, c:0}, e: {r:0, c:0} }; range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1; @@ -425,38 +479,35 @@ function parse_TST_TableModelArchive(M: IWAMessage[][], root: IWAMessage, ws: Wo if(range.e.c < 0) throw new Error(`Invalid col varint ${pb[7][0].data}`); ws["!ref"] = encode_range(range); - { - // .TST.DataStore - var store = parse_shallow(pb[4][0].data); + // .TST.DataStore + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst: string[] = store[17]?.[0] ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst: string[] = store[17]?.[0] ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - // .TST.TileStorage - var tile = parse_shallow(store[3][0].data); - var tiles: Array<{id: number, ref: Uint8Array[][]}> = []; - tile[1].forEach(t => { - var tl = (parse_shallow(t.data)); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if(mtype != 6002) throw new Error(`6001 unexpected reference to ${mtype}`); - tiles.push({id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + // .TST.TileStorage + var tile = parse_shallow(store[3][0].data); + var _R = 0; + /* TODO: should this list be sorted by id ? */ + tile[1].forEach(t => { + var tl = (parse_shallow(t.data)); + // var id = varint_to_i32(tl[1][0].data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if(mtype != 6002) throw new Error(`6001 unexpected reference to ${mtype}`); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach((row, R) => { + row.forEach((buf, C) => { + var addr = encode_cell({r:_R + R,c:C}); + var res = parse_cell_storage(buf, sst, rsst); + if(res) ws[addr] = res; }); - tiles.forEach((tile) => { - tile.ref.forEach((row, R) => { - row.forEach((buf, C) => { - var addr = encode_cell({r:R,c:C}); - var res = parse_cell_storage(buf, sst, rsst); - if(res) ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } -// .TST.TableInfoArchive -function parse_TST_TableInfoArchive(M: IWAMessage[][], root: IWAMessage): WorkSheet { +/** .TST.TableInfoArchive */ +function parse_TST_TableInfoArchive(M: MessageSpace, root: IWAMessage): WorkSheet { var pb = parse_shallow(root.data); var out: WorkSheet = { "!ref": "A1" }; var tableref = M[parse_TSP_Reference(pb[2][0].data)]; @@ -466,12 +517,12 @@ function parse_TST_TableInfoArchive(M: IWAMessage[][], root: IWAMessage): WorkSh return out; } -// .TN.SheetArchive interface NSheet { name: string; sheets: WorkSheet[]; } -function parse_TN_SheetArchive(M: IWAMessage[][], root: IWAMessage): NSheet { +/** .TN.SheetArchive */ +function parse_TN_SheetArchive(M: MessageSpace, root: IWAMessage): NSheet { var pb = parse_shallow(root.data); var out: NSheet = { name: (pb[1]?.[0] ? u8str(pb[1][0].data) : ""), @@ -487,17 +538,26 @@ function parse_TN_SheetArchive(M: IWAMessage[][], root: IWAMessage): NSheet { return out; } -// .TN.DocumentArchive -function parse_TN_DocumentArchive(M: IWAMessage[][], root: IWAMessage): WorkBook { +/** .TN.DocumentArchive */ +function parse_TN_DocumentArchive(M: MessageSpace, root: IWAMessage): WorkBook { var out = book_new(); var pb = parse_shallow(root.data); + + // var stylesheet = mappa(pb[4], parse_TSP_Reference)[0]; + // if(varint_to_i32(M[stylesheet][0].meta[1][0].data) == 401) parse_TSS_StylesheetArchive(M, M[stylesheet][0]); + // var sidebar = mappa(pb[5], parse_TSP_Reference); + // var theme = mappa(pb[6], parse_TSP_Reference); + // var docinfo = parse_shallow(pb[8][0].data); + // var tskinfo = parse_shallow(docinfo[1][0].data); + // var author_storage = mappa(tskinfo[7], parse_TSP_Reference); + var sheetoffs = mappa(pb[1], parse_TSP_Reference); sheetoffs.forEach((off) => { M[off].forEach((m: IWAMessage) => { var mtype = varint_to_i32(m.meta[1][0].data); if(mtype == 2) { var root = parse_TN_SheetArchive(M, m); - root.sheets.forEach(sheet => { book_append_sheet(out, sheet, root.name); }); + root.sheets.forEach((sheet, idx) => { book_append_sheet(out, sheet, idx == 0 ? root.name : root.name + "_" + idx, true); }); } }); }); @@ -505,24 +565,26 @@ function parse_TN_DocumentArchive(M: IWAMessage[][], root: IWAMessage): WorkBook return out; } -/* exported parse_numbers_iwa */ +/** Parse NUMBERS file */ function parse_numbers_iwa(cfb: CFB$Container): WorkBook { - var out: IWAMessage[][] = []; + var out: MessageSpace = {}, indices: number[] = []; cfb.FullPaths.forEach(p => { if(p.match(/\.iwpv2/)) throw new Error(`Unsupported password protection`); }); + /* collect entire message space */ cfb.FileIndex.forEach(s => { if(!s.name.match(/\.iwa$/)) return; var o: Uint8Array; - try { o = deframe(s.content as Uint8Array); } catch(e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } + try { o = decompress_iwa_file(s.content as Uint8Array); } catch(e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } var packets: IWAArchiveInfo[]; try { packets = parse_iwa_file(o); } catch(e) { return console.log("## " + (e.message || e)); } - packets.forEach(packet => {out[+packet.id] = packet.messages;}); + packets.forEach(packet => { out[packet.id] = packet.messages; indices.push(packet.id); }); }); - if(!out.length) throw new Error("File has no messages"); + if(!indices.length) throw new Error("File has no messages"); + /* find document root */ - var docroot: IWAMessage; - out.forEach((iwams) => { - iwams.forEach((iwam) => { + var docroot: IWAMessage = out?.[1]?.[0]?.meta?.[1]?.[0].data && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if(!docroot) indices.forEach((idx) => { + out[idx].forEach((iwam) => { var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; if(mtype == 1) { if(!docroot) docroot = iwam; @@ -533,3 +595,5 @@ function parse_numbers_iwa(cfb: CFB$Container): WorkBook { if(!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); } + +//< $@ + .PHONY: clean clean: rm $(ENTRIES) diff --git a/modules/numbers_to_csv.node.ts b/modules/numbers_to_csv.node.ts index 482139a..8e573e1 100644 --- a/modules/numbers_to_csv.node.ts +++ b/modules/numbers_to_csv.node.ts @@ -2,11 +2,11 @@ /*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ import { read } from 'cfb'; import { utils } from 'xlsx'; -import parse_numbers from './src/numbers'; +import { parse_numbers_iwa } from './src/numbers'; var f = process.argv[2]; var cfb = read(f, {type: "file"}); -var wb = parse_numbers(cfb); +var wb = parse_numbers_iwa(cfb); var sn = process.argv[3]; if(typeof sn == "undefined") { wb.SheetNames.forEach(sn => console.log(utils.sheet_to_csv(wb.Sheets[sn]))); diff --git a/modules/reframe.node.ts b/modules/reframe.node.ts new file mode 100644 index 0000000..4cbc234 --- /dev/null +++ b/modules/reframe.node.ts @@ -0,0 +1,53 @@ +/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ +import { decompress_iwa_file, compress_iwa_file, u8concat } from "./src/numbers"; +import { read, writeFile, utils, find, CFB$Entry } from 'cfb'; + +var f = process.argv[2]; var o = process.argv[3]; +var cfb = read(f, {type: "file"}); + +var FI = cfb.FileIndex; +var bufs = [], mode = 0; +FI.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => { + var fi = row[0], fp = row[1]; + /* blank all plist files */ + if(fi.name.match(/\.plist/)) { + console.error(`Blanking plist ${fi.name}`); + fi.content = new Uint8Array([ + 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0a + ]); + return; + } + + if(fi.type != 2) return; + + /* Remove other metadata */ + if(!fi.name.match(/\.iwa/)) { + if(fi.name.match(/Sh33tJ5/)) return; + console.error(`Removing file ${fi.name}`); + utils.cfb_del(cfb, fp); + return; + } + + /* Reframe .iwa files */ + console.error(`Reframing iwa ${fi.name} (${fi.size})`); + var old_content = fi.content; + var raw1 = decompress_iwa_file(old_content as Uint8Array); + var new_content = compress_iwa_file(raw1); + var raw2 = decompress_iwa_file(new_content); + for(var i = 0; i < raw1.length; ++i) if(raw1[i] != raw2[i]) throw new Error(`${fi.name} did not properly roundtrip`); + bufs.push(raw1); + switch(mode) { + case 1: utils.cfb_del(cfb, fp); break; + /* falls through */ + case 0: fi.content = new_content; break; + } +}); + +if(mode == 1) { + var res = compress_iwa_file(u8concat(bufs)); + console.error(`Adding iwa Document.iwa (${res.length})`); + utils.cfb_add(cfb, "/Index/Document.iwa", res); +} +writeFile(cfb, o, {fileType: "zip"}); diff --git a/modules/src/cell.ts b/modules/src/cell.ts deleted file mode 100644 index 66930c7..0000000 --- a/modules/src/cell.ts +++ /dev/null @@ -1,88 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -import { CellObject } from '../../'; -import { u8_to_dataview, popcnt, readDecimal128LE } from './util'; - -function parse_old_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { - var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; - - /* TODO: find the correct field position of number formats, formulae, etc */ - var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 0x0D8E) * 4; - - var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); - if(flags & 0x0200) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 0x3000) * 4; - if(flags & 0x0010) { sidx = dv.getUint32(data_offset, true); data_offset += 4; } - if(flags & 0x0020) { ieee = dv.getFloat64(data_offset, true); data_offset += 8; } - if(flags & 0x0040) { dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1000); data_offset += 8; } - - var ret: CellObject; - switch(ctype) { - case 0: break; // return { t: "z" }; // blank? - case 2: ret = { t: "n", v: ieee }; break; // number - case 3: ret = { t: "s", v: sst[sidx] }; break; // string - case 5: ret = { t: "d", v: dt }; break; // date-time - case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean - case 7: ret = { t: "n", v: ieee }; break; // duration in seconds TODO: emit [hh]:[mm] style format with adjusted value - case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents - case 9: { // "automatic"? - if(ridx > -1) ret = { t: "s", v: rsst[ridx] }; - else if(sidx > -1) ret = { t: "s", v: sst[sidx] }; - else if(!isNaN(ieee)) ret = { t: "n", v: ieee }; - else throw new Error(`Unsupported cell type ${buf.slice(0,4)}`); - } break; - default: throw new Error(`Unsupported cell type ${buf.slice(0,4)}`); - } - /* TODO: Some fields appear after the cell data */ - - return ret; -} - -function parse_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { - var dv = u8_to_dataview(buf); - var ctype = buf[1]; - - /* TODO: find the correct field position of number formats, formulae, etc */ - var flags = dv.getUint32(8, true); - var data_offset = 12; - - var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); - - if(flags & 0x0001) { d128 = readDecimal128LE(buf, data_offset); data_offset += 16; } - if(flags & 0x0002) { ieee = dv.getFloat64(data_offset, true); data_offset += 8; } - if(flags & 0x0004) { dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1000); data_offset += 8; } - if(flags & 0x0008) { sidx = dv.getUint32(data_offset, true); data_offset += 4; } - if(flags & 0x0010) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - - var ret: CellObject; - switch(ctype) { - case 0: break; // return { t: "z" }; // blank? - case 2: ret = { t: "n", v: d128 }; break; // number - case 3: ret = { t: "s", v: sst[sidx] }; break; // string - case 5: ret = { t: "d", v: dt }; break; // date-time - case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean - case 7: ret = { t: "n", v: ieee }; break; // duration in seconds TODO: emit [hh]:[mm] style format with adjusted value - case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents - case 9: { // "automatic"? - if(ridx > -1) ret = { t: "s", v: rsst[ridx] }; - else throw new Error(`Unsupported cell type ${ctype} : ${flags & 0x1F} : ${buf.slice(0,4)}`); - } break; - case 10: ret = { t: "n", v: d128 }; break; // currency - default: throw new Error(`Unsupported cell type ${ctype} : ${flags & 0x1F} : ${buf.slice(0,4)}`); - } - /* TODO: All styling fields appear after the cell data */ - - return ret; -} - -function parse(buf: Uint8Array, sst: string[], rsst: string[]): CellObject { - switch(buf[0]) { - /* TODO: 0-2? */ - case 3: case 4: return parse_old_storage(buf, sst, rsst); - case 5: return parse_storage(buf, sst, rsst); - default: throw new Error(`Unsupported payload version ${buf[0]}`); - } -} - -export { parse }; \ No newline at end of file diff --git a/modules/src/frame.ts b/modules/src/frame.ts deleted file mode 100644 index e9ebdc6..0000000 --- a/modules/src/frame.ts +++ /dev/null @@ -1,105 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -import { Ptr, parse_varint49, write_varint49 } from './proto'; -import { u8concat } from './util'; - -function is_framed(buf: Uint8Array): boolean { - var l = 0; - while(l < buf.length) { - l++; - var len = buf[l] | (buf[l+1]<<8) | (buf[l+2] << 16); l += 3; - l += len; - } - return l == buf.length; -} -export { is_framed }; - -function deframe(buf: Uint8Array): Uint8Array { - var out = []; - var l = 0; - while(l < buf.length) { - var t = buf[l++]; - var len = buf[l] | (buf[l+1]<<8) | (buf[l+2] << 16); l += 3; - out.push(parse_snappy_chunk(t, buf.slice(l, l + len))); - l += len; - } - if(l !== buf.length) throw new Error("data is not a valid framed stream!"); - return u8concat(out); -} -export { deframe }; - -function reframe(buf: Uint8Array): Uint8Array { - var out: Uint8Array[] = []; - var l = 0; - while(l < buf.length) { - var c = Math.min(buf.length - l, 0xFFFFFFF); - var frame = new Uint8Array(4); - out.push(frame); - var usz = write_varint49(c); - var L = usz.length; - out.push(usz); - - if(c <= 60) { L++; out.push(new Uint8Array([(c - 1)<<2])); } - else if(c <= 0x100) { L += 2; out.push(new Uint8Array([0xF0, (c-1) & 0xFF])); } - else if(c <= 0x10000) { L += 3; out.push(new Uint8Array([0xF4, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF])); } - else if(c <= 0x1000000) { L += 4; out.push(new Uint8Array([0xF8, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF, ((c-1) >> 16) & 0xFF])); } - else if(c <= 0x100000000) { L += 5; out.push(new Uint8Array([0xFC, (c-1) & 0xFF, ((c-1) >> 8) & 0xFF, ((c-1) >> 16) & 0xFF, ((c-1) >>> 24) & 0xFF])); } - - out.push(buf.slice(l, l + c)); L += c; - - frame[0] = 0; - frame[1] = L & 0xFF; frame[2] = (L >> 8) & 0xFF; frame[3] = (L >> 16) & 0xFF; - l += c; - } - return u8concat(out); -} -export { reframe }; - -function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array { - if(type != 0) throw new Error(`Unexpected Snappy chunk type ${type}`); - var ptr: Ptr = [0]; - - var usz = parse_varint49(buf, ptr); - var chunks = []; - while(ptr[0] < buf.length) { - var tag = buf[ptr[0]] & 0x3; - if(tag == 0) { - var len = buf[ptr[0]++] >> 2; - if(len < 60) ++len; - else { - var c = len - 59; - len = buf[ptr[0]]; - if(c > 1) len |= (buf[ptr[0]+1]<<8); - if(c > 2) len |= (buf[ptr[0]+2]<<16); - if(c > 3) len |= (buf[ptr[0]+3]<<24); - len >>>=0; len++; - ptr[0] += c; - } - chunks.push(buf.slice(ptr[0], ptr[0] + len)); ptr[0] += len; continue; - } else { - var offset = 0, length = 0; - if(tag == 1) { - length = ((buf[ptr[0]] >> 2) & 0x7) + 4; - offset = (buf[ptr[0]++] & 0xE0) << 3; - offset |= buf[ptr[0]++]; - } else { - length = (buf[ptr[0]++] >> 2) + 1; - if(tag == 2) { offset = buf[ptr[0]] | (buf[ptr[0]+1]<<8); ptr[0] += 2; } - else { offset = (buf[ptr[0]] | (buf[ptr[0]+1]<<8) | (buf[ptr[0]+2]<<16) | (buf[ptr[0]+3]<<24))>>>0; ptr[0] += 4; } - } - chunks = [u8concat(chunks)]; - if(offset == 0) throw new Error("Invalid offset 0"); - if(offset > chunks[0].length) throw new Error("Invalid offset beyond length"); - if(length >= offset) { - chunks.push(chunks[0].slice(-offset)); length -= offset; - while(length >= chunks[chunks.length-1].length) { - chunks.push(chunks[chunks.length - 1]); - length -= chunks[chunks.length - 1].length; - } - } - chunks.push(chunks[0].slice(-offset, -offset + length)); - } - } - var o = u8concat(chunks); - if(o.length != usz) throw new Error(`Unexpected length: ${o.length} != ${usz}`); - return o; -} \ No newline at end of file diff --git a/modules/src/iwa.ts b/modules/src/iwa.ts deleted file mode 100644 index d13fea5..0000000 --- a/modules/src/iwa.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -import { Ptr, ProtoMessage, parse_shallow, parse_varint49, varint_to_i32 } from './proto'; - -interface IWAMessage { - /** Metadata in .TSP.MessageInfo */ - meta: ProtoMessage; - data: Uint8Array; -} -interface IWAArchiveInfo { - id?: number; - messages?: IWAMessage[]; -} -export { IWAMessage, IWAArchiveInfo }; - -function parse_iwa(buf: Uint8Array): IWAArchiveInfo[] { - var out: IWAArchiveInfo[] = [], ptr: Ptr = [0]; - while(ptr[0] < buf.length) { - /* .TSP.ArchiveInfo */ - var len = parse_varint49(buf, ptr); - var ai = parse_shallow(buf.slice(ptr[0], ptr[0] + len)); - ptr[0] += len; - - var res: IWAArchiveInfo = { - id: varint_to_i32(ai[1][0].data), - messages: [] - }; - ai[2].forEach(b => { - var mi = parse_shallow(b.data); - var fl = varint_to_i32(mi[3][0].data); - res.messages.push({ - meta: mi, - data: buf.slice(ptr[0], ptr[0] + fl) - }); - ptr[0] += fl; - }); - out.push(res); - } - return out; -} -export { parse_iwa }; diff --git a/modules/src/numbers.ts b/modules/src/numbers.ts deleted file mode 100644 index 91f23d8..0000000 --- a/modules/src/numbers.ts +++ /dev/null @@ -1,228 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -import { CFB$Container } from 'cfb'; -import { WorkBook, WorkSheet, CellAddress, Range } from '../../'; -import { u8str, u8_to_dataview } from './util'; -import { parse_shallow, varint_to_i32, parse_varint49, mappa } from './proto'; -import { deframe } from './frame'; -import { IWAArchiveInfo, IWAMessage, parse_iwa } from './iwa'; -import { parse as parse_storage } from "./cell"; - -/* written here to avoid a full import of the 'xlsx' library */ -var encode_col = (C: number): string => { - var s=""; - for(++C; C; C=Math.floor((C-1)/26)) s = String.fromCharCode(((C-1)%26) + 65) + s; - return s; -}; -var encode_cell = (c: CellAddress): string => `${encode_col(c.c)}${c.r+1}`; -var encode_range = (r: Range): string => encode_cell(r.s) + ":" + encode_cell(r.e); -var book_new = (): WorkBook => ({Sheets:{}, SheetNames:[]}); -var book_append_sheet = (wb: WorkBook, ws: WorkSheet, name?: string): void => { - var i = 1; - if(!name) for(; i < 9999; ++i) { - if(wb.SheetNames.indexOf(name = `Sheet ${i}`) == -1) break; - } else if(wb.SheetNames.indexOf(name) > -1) for(; i < 9999; ++i) { - if(wb.SheetNames.indexOf(`${name}_${i}`) == -1) { name = `${name}_${i}`; break; } - } - wb.SheetNames.push(name); wb.Sheets[name] = ws; -}; - -function parse_numbers(cfb: CFB$Container): WorkBook { - var out: IWAMessage[][] = []; - cfb.FullPaths.forEach(p => { if(p.match(/\.iwpv2/)) throw new Error(`Unsupported password protection`); }); - /* collect entire message space */ - cfb.FileIndex.forEach(s => { - if(!s.name.match(/\.iwa$/)) return; - var o: Uint8Array; - try { o = deframe(s.content as Uint8Array); } catch(e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } - var packets: IWAArchiveInfo[]; - try { packets = parse_iwa(o); } catch(e) { return console.log("## " + (e.message || e)); } - packets.forEach(packet => {out[+packet.id] = packet.messages;}); - }); - if(!out.length) throw new Error("File has no messages"); - /* find document root */ - var docroot: IWAMessage; - out.forEach((iwams) => { - iwams.forEach((iwam) => { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if(mtype == 1) { - if(!docroot) docroot = iwam; - else throw new Error("Document has multiple roots"); - } - }); - }); - if(!docroot) throw new Error("Cannot find Document root"); - return parse_docroot(out, docroot); -} -export default parse_numbers; - -// .TSP.Reference -function parse_Reference(buf: Uint8Array): number { - var pb = parse_shallow(buf); - return parse_varint49(pb[1][0].data); -} - -// .TST.TableDataList -function parse_TST_TableDataList(M: IWAMessage[][], root: IWAMessage): string[] { - var pb = parse_shallow(root.data); - // .TST.TableDataList.ListType - var type = varint_to_i32(pb[1][0].data); - - var entries = pb[3]; - var data = []; - (entries||[]).forEach(entry => { - // .TST.TableDataList.ListEntry - var le = parse_shallow(entry.data); - var key = varint_to_i32(le[1][0].data)>>>0; - switch(type) { - case 1: data[key] = u8str(le[3][0].data); break; - case 8: { - // .TSP.RichTextPayloadArchive - var rt = M[parse_Reference(le[9][0].data)][0]; - var rtp = parse_shallow(rt.data); - - // .TSWP.StorageArchive - var rtpref = M[parse_Reference(rtp[1][0].data)][0]; - var mtype = varint_to_i32(rtpref.meta[1][0].data); - if(mtype != 2001) throw new Error(`2000 unexpected reference to ${mtype}`); - var tswpsa = parse_shallow(rtpref.data); - - data[key] = tswpsa[3].map(x => u8str(x.data)).join(""); - } break; - } - }); - return data; -} - -interface TileRowInfo { - R: number; - cells?: Uint8Array[]; -} -// .TSP.TileRowInfo -function parse_TST_TileRowInfo(u8: Uint8Array): TileRowInfo { - var pb = parse_shallow(u8); - var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = pb[3]?.[0]?.data; - var pre_bnc_offsets = pb[4]?.[0]?.data && u8_to_dataview(pb[4][0].data); - var storage = pb[6]?.[0]?.data; - var storage_offsets = pb[7]?.[0]?.data && u8_to_dataview(pb[7][0].data); - var wide_offsets = pb[8]?.[0]?.data && varint_to_i32(pb[8][0].data) > 0 || false; - var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for(var C = 0; C < pre_bnc_offsets.byteLength/2; ++C) { - /* prefer storage if it is present, otherwise fall back on pre_bnc */ - if(storage && storage_offsets) { - off = storage_offsets.getUint16(C*2, true) * width; - if(off < storage.length) { cells[C] = storage.subarray(off, storage_offsets.getUint16(C*2+2, true) * width); continue; } - } - if(pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C*2, true) * width; - if(off < pre_bnc.length) cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C*2+2, true) * width); - } - } - return { R, cells }; -} - -// .TST.Tile -function parse_TST_Tile(M: IWAMessage[][], root: IWAMessage): Uint8Array[][] { - var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce((acc, x) => { - if(!acc[x.R]) acc[x.R] = []; - x.cells.forEach((cell, C) => { - if(acc[x.R][C]) throw new Error(`Duplicate cell r=${x.R} c=${C}`); - acc[x.R][C] = cell; - }); - return acc; - }, [] as Uint8Array[][]); -} - -// .TST.TableModelArchive -function parse_TST_TableModelArchive(M: IWAMessage[][], root: IWAMessage, ws: WorkSheet) { - var pb = parse_shallow(root.data); - var range: Range = { s: {r:0, c:0}, e: {r:0, c:0} }; - range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1; - if(range.e.r < 0) throw new Error(`Invalid row varint ${pb[6][0].data}`); - range.e.c = (varint_to_i32(pb[7][0].data) >>> 0) - 1; - if(range.e.c < 0) throw new Error(`Invalid col varint ${pb[7][0].data}`); - ws["!ref"] = encode_range(range); - - { - // .TST.DataStore - var store = parse_shallow(pb[4][0].data); - - var sst = parse_TST_TableDataList(M, M[parse_Reference(store[4][0].data)][0]); - var rsst: string[] = store[17]?.[0] ? parse_TST_TableDataList(M, M[parse_Reference(store[17][0].data)][0]) : []; - { - // .TST.TileStorage - var tile = parse_shallow(store[3][0].data); - var tiles: Array<{id: number, ref: Uint8Array[][]}> = []; - tile[1].forEach(t => { - var tl = (parse_shallow(t.data)); - var ref = M[parse_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if(mtype != 6002) throw new Error(`6001 unexpected reference to ${mtype}`); - tiles.push({id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); - }); - tiles.forEach((tile) => { - tile.ref.forEach((row, R) => { - row.forEach((buf, C) => { - var addr = encode_cell({r:R,c:C}); - var res = parse_storage(buf, sst, rsst); - if(res) ws[addr] = res; - }); - }); - }); - } - } -} - -// .TST.TableInfoArchive -function parse_TST_TableInfoArchive(M: IWAMessage[][], root: IWAMessage): WorkSheet { - var pb = parse_shallow(root.data); - var out: WorkSheet = { "!ref": "A1" }; - var tableref = M[parse_Reference(pb[2][0].data)]; - var mtype = varint_to_i32(tableref[0].meta[1][0].data); - if(mtype != 6001) throw new Error(`6000 unexpected reference to ${mtype}`); - parse_TST_TableModelArchive(M, tableref[0], out); - return out; -} - -// .TN.SheetArchive -interface NSheet { - name: string; - sheets: WorkSheet[]; -} -function parse_sheetroot(M: IWAMessage[][], root: IWAMessage): NSheet { - var pb = parse_shallow(root.data); - var out: NSheet = { - name: (pb[1]?.[0] ? u8str(pb[1][0].data) : ""), - sheets: [] - }; - var shapeoffs = mappa(pb[2], parse_Reference); - shapeoffs.forEach((off) => { - M[off].forEach((m: IWAMessage) => { - var mtype = varint_to_i32(m.meta[1][0].data); - if(mtype == 6000) out.sheets.push(parse_TST_TableInfoArchive(M, m)); - }); - }); - return out; -} - -// .TN.DocumentArchive -function parse_docroot(M: IWAMessage[][], root: IWAMessage): WorkBook { - var out = book_new(); - var pb = parse_shallow(root.data); - var sheetoffs = mappa(pb[1], parse_Reference); - sheetoffs.forEach((off) => { - M[off].forEach((m: IWAMessage) => { - var mtype = varint_to_i32(m.meta[1][0].data); - if(mtype == 2) { - var root = parse_sheetroot(M, m); - root.sheets.forEach(sheet => { book_append_sheet(out, sheet, root.name); }); - } - }); - }); - if(out.SheetNames.length == 0) throw new Error("Empty NUMBERS file"); - return out; -} diff --git a/modules/src/proto.ts b/modules/src/proto.ts deleted file mode 100644 index 068cf96..0000000 --- a/modules/src/proto.ts +++ /dev/null @@ -1,118 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -import { u8concat } from "./util"; - -type Ptr = [number]; -export { Ptr }; - -/** Parse an integer from the varint that can be exactly stored in a double */ -function parse_varint49(buf: Uint8Array, ptr?: Ptr): number { - var l = ptr ? ptr[0] : 0; - var usz = buf[l] & 0x7F; - varint: if(buf[l++] >= 0x80) { - usz |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint; - usz |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint; - usz |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint; - usz += (buf[l] & 0x7F) * Math.pow(2, 28); ++l; if(buf[l++] < 0x80) break varint; - usz += (buf[l] & 0x7F) * Math.pow(2, 35); ++l; if(buf[l++] < 0x80) break varint; - usz += (buf[l] & 0x7F) * Math.pow(2, 42); ++l; if(buf[l++] < 0x80) break varint; - } - if(ptr) ptr[0] = l; - return usz; -} -export { parse_varint49 }; -function write_varint49(v: number): Uint8Array { - var usz = new Uint8Array(7); - usz[0] = (v & 0x7F); - var L = 1; - sz: if(v > 0x7F) { - usz[L-1] |= 0x80; usz[L] = (v >> 7) & 0x7F; ++L; - if(v <= 0x3FFF) break sz; - usz[L-1] |= 0x80; usz[L] = (v >> 14) & 0x7F; ++L; - if(v <= 0x1FFFFF) break sz; - usz[L-1] |= 0x80; usz[L] = (v >> 21) & 0x7F; ++L; - if(v <= 0xFFFFFFF) break sz; - usz[L-1] |= 0x80; usz[L] = ((v/0x100) >>> 21) & 0x7F; ++L; - if(v <= 0x7FFFFFFFF) break sz; - usz[L-1] |= 0x80; usz[L] = ((v/0x10000) >>> 21) & 0x7F; ++L; - if(v <= 0x3FFFFFFFFFF) break sz; - usz[L-1] |= 0x80; usz[L] = ((v/0x1000000) >>> 21) & 0x7F; ++L; - } - return usz.slice(0, L); -} -export { write_varint49 }; - -/** Parse a 32-bit signed integer from the raw varint */ -function varint_to_i32(buf: Uint8Array): number { - var l = 0, i32 = buf[l] & 0x7F; - varint: if(buf[l++] >= 0x80) { - i32 |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 28; - } - return i32; -} -export { varint_to_i32 }; - -interface ProtoItem { - offset?: number; - data: Uint8Array; - type: number; -} -type ProtoField = Array -type ProtoMessage = Array; -export { ProtoItem, ProtoField, ProtoMessage }; -/** Shallow parse of a message */ -function parse_shallow(buf: Uint8Array): ProtoMessage { - var out: ProtoMessage = [], ptr: Ptr = [0]; - while(ptr[0] < buf.length) { - var off = ptr[0]; - var num = parse_varint49(buf, ptr); - var type = num & 0x07; num = Math.floor(num / 8); - var len = 0; - var res: Uint8Array; - if(num == 0) break; - switch(type) { - case 0: { - var l = ptr[0]; - while(buf[ptr[0]++] >= 0x80); - res = buf.slice(l, ptr[0]); - } break; - case 5: len = 4; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; - case 1: len = 8; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; - case 2: len = parse_varint49(buf, ptr); res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; - case 3: // Start group - case 4: // End group - default: throw new Error(`PB Type ${type} for Field ${num} at offset ${off}`); - } - var v: ProtoItem = { offset: off, data: res, type }; - if(out[num] == null) out[num] = [v]; - else out[num].push(v); - } - return out; -} -export { parse_shallow }; -/** Serialize a shallow parse */ -function write_shallow(proto: ProtoMessage): Uint8Array { - var out: Uint8Array[] = []; - proto.forEach((field, idx) => { - field.forEach(item => { - out.push(write_varint49(idx * 8 + item.type)); - out.push(item.data); - }); - }); - return u8concat(out); -} -export { write_shallow }; - -function mappa(data: ProtoField, cb:(Uint8Array) => U): U[] { - if(!data) return []; - return data.map((d) => { try { - return cb(d.data); - } catch(e) { - var m = e.message?.match(/at offset (\d+)/); - if(m) e.message = e.message.replace(/at offset (\d+)/, "at offset " + (+m[1] + d.offset)); - throw e; - }}); -} -export { mappa }; diff --git a/modules/src/types.ts b/modules/src/types.ts index f67327b..25a648b 100644 --- a/modules/src/types.ts +++ b/modules/src/types.ts @@ -49,6 +49,7 @@ interface ParseXLMetaOptions { } interface XLMDT { name: string; + offsets?: number[]; } interface XLMetaRef { type: string; diff --git a/modules/src/util.ts b/modules/src/util.ts deleted file mode 100644 index 1929389..0000000 --- a/modules/src/util.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ -var u8_to_dataview = (array: Uint8Array): DataView => new DataView(array.buffer, array.byteOffset, array.byteLength); -export { u8_to_dataview }; - -var u8str = (u8: Uint8Array): string => /* Buffer.isBuffer(u8) ? u8.toString() :*/ typeof TextDecoder != "undefined" ? new TextDecoder().decode(u8) : utf8read(a2s(u8)); -export { u8str }; - -var u8concat = (u8a: Uint8Array[]): Uint8Array => { - var len = u8a.reduce((acc: number, x: Uint8Array) => acc + x.length, 0); - var out = new Uint8Array(len); - var off = 0; - u8a.forEach(u8 => { out.set(u8, off); off += u8.length; }); - return out; -}; -export { u8concat }; - -var indent = (str: string, depth: number /* = 1 */): string => str.split(/\n/g).map(x => x && " ".repeat(depth) + x).join("\n"); -export { indent }; - -function u8indexOf(u8: Uint8Array, data: string | number | Uint8Array, byteOffset?: number): number { - //if(Buffer.isBuffer(u8)) return u8.indexOf(data, byteOffset); - if(typeof data == "number") return u8.indexOf(data, byteOffset); - var l = byteOffset; - if(typeof data == "string") { - outs: while((l = u8.indexOf(data.charCodeAt(0), l)) > -1) { - ++l; - for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data.charCodeAt(j)) continue outs; - return l - 1; - } - } else { - outb: while((l = u8.indexOf(data[0], l)) > -1) { - ++l; - for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data[j]) continue outb; - return l - 1; - } - } - return -1; -} -export { u8indexOf }; - -/* Hopefully one day this will be added to the language */ -var popcnt = (x: number): number => { - x -= ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >>> 24; -}; -export { popcnt }; - -/* Used in the modern cell storage */ -var readDecimal128LE = (buf: Uint8Array, offset: number): number => { - var exp = ((buf[offset + 15] & 0x7F) << 7) | (buf[offset + 14] >> 1); - var mantissa = buf[offset + 14] & 1; - for(var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; - return ((buf[offset+15] & 0x80) ? -mantissa : mantissa) * Math.pow(10, exp - 0x1820); -}; -export { readDecimal128LE }; diff --git a/package.json b/package.json index 3160673..e302909 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@sheetjs/uglify-js": "~2.7.3", "@types/node": "^8.5.9", "acorn": "7.4.1", - "alex": "^9.1.0", + "alex": "8.1.1", "blanket": "~1.2.3", "commander": "~2.17.1", "dtslint": "^0.1.2", diff --git a/types/index.d.ts b/types/index.d.ts index 3f696ec..89e551e 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -839,7 +839,7 @@ export interface XLSX$Utils { book_new(): WorkBook; /** Append a worksheet to a workbook */ - book_append_sheet(workbook: WorkBook, worksheet: WorkSheet, name?: string): void; + book_append_sheet(workbook: WorkBook, worksheet: WorkSheet, name?: string, roll?: boolean): void; /** Set sheet visibility (visible/hidden/very hidden) */ book_set_sheet_visibility(workbook: WorkBook, sheet: number|string, visibility: number): void; diff --git a/xlsx.flow.js b/xlsx.flow.js index 2094177..f3502df 100644 --- a/xlsx.flow.js +++ b/xlsx.flow.js @@ -5362,7 +5362,6 @@ function write_rels(rels)/*:string*/ { return o.join(""); } -var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS]; function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ { if(!relobj) relobj = {}; if(!rels['!id']) rels['!id'] = {}; @@ -5373,7 +5372,7 @@ function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/) relobj.Type = type; relobj.Target = f; if(targetmode) relobj.TargetMode = targetmode; - else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; + else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId); rels['!id'][relobj.Id] = relobj; rels[('/' + relobj.Target).replace("//","/")] = relobj; @@ -11482,6 +11481,7 @@ function parse_xlmeta_xml(data, name, opts) { return out; var pass = false; var metatype = 2; + var lastmeta; data.replace(tagregex, function(x) { var y = parsexmltag(x); switch (strip_ns(y[0])) { @@ -11499,6 +11499,9 @@ function parse_xlmeta_xml(data, name, opts) { case "": break; case "": break; @@ -11537,6 +11540,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case "> 1 & 1431655765; x = (x & 858993459) + (x >> 2 & 858993459); return (x + (x >> 4) & 252645135) * 16843009 >>> 24; -}; -var readDecimal128LE = function(buf, offset) { +} +function readDecimal128LE(buf, offset) { var exp = (buf[offset + 15] & 127) << 7 | buf[offset + 14] >> 1; var mantissa = buf[offset + 14] & 1; for (var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return (buf[offset + 15] & 128 ? -mantissa : mantissa) * Math.pow(10, exp - 6176); -}; +} function parse_varint49(buf, ptr) { var l = ptr ? ptr[0] : 0; var usz = buf[l] & 127; @@ -22047,6 +22057,43 @@ function parse_varint49(buf, ptr) { ptr[0] = l; return usz; } +function write_varint49(v) { + var usz = new Uint8Array(7); + usz[0] = v & 127; + var L = 1; + sz: + if (v > 127) { + usz[L - 1] |= 128; + usz[L] = v >> 7 & 127; + ++L; + if (v <= 16383) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 14 & 127; + ++L; + if (v <= 2097151) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 21 & 127; + ++L; + if (v <= 268435455) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 256 >>> 21 & 127; + ++L; + if (v <= 34359738367) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 65536 >>> 21 & 127; + ++L; + if (v <= 4398046511103) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 16777216 >>> 21 & 127; + ++L; + } + return usz.slice(0, L); +} function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; varint: @@ -22215,7 +22262,7 @@ function parse_snappy_chunk(type, buf) { throw new Error("Unexpected length: ".concat(o.length, " != ").concat(usz)); return o; } -function deframe(buf) { +function decompress_iwa_file(buf) { var out = []; var l = 0; while (l < buf.length) { @@ -22229,17 +22276,52 @@ function deframe(buf) { throw new Error("data is not a valid framed stream!"); return u8concat(out); } -function parse_old_storage(buf, sst, rsst) { +function compress_iwa_file(buf) { + var out = []; + var l = 0; + while (l < buf.length) { + var c = Math.min(buf.length - l, 268435455); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + if (c <= 60) { + L++; + out.push(new Uint8Array([c - 1 << 2])); + } else if (c <= 256) { + L += 2; + out.push(new Uint8Array([240, c - 1 & 255])); + } else if (c <= 65536) { + L += 3; + out.push(new Uint8Array([244, c - 1 & 255, c - 1 >> 8 & 255])); + } else if (c <= 16777216) { + L += 4; + out.push(new Uint8Array([248, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255])); + } else if (c <= 4294967296) { + L += 5; + out.push(new Uint8Array([252, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255, c - 1 >>> 24 & 255])); + } + out.push(buf.slice(l, l + c)); + L += c; + frame[0] = 0; + frame[1] = L & 255; + frame[2] = L >> 8 & 255; + frame[3] = L >> 16 & 255; + l += c; + } + return u8concat(out); +} +function parse_old_storage(buf, sst, rsst, v) { var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 3470) * 4; + var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if (flags & 512) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 12288) * 4; + data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4; if (flags & 16) { sidx = dv.getUint32(data_offset, true); data_offset += 4; @@ -22253,7 +22335,7 @@ function parse_old_storage(buf, sst, rsst) { data_offset += 8; } var ret; - switch (ctype) { + switch (buf[2]) { case 0: break; case 2: @@ -22293,7 +22375,6 @@ function parse_old_storage(buf, sst, rsst) { } function parse_storage(buf, sst, rsst) { var dv = u8_to_dataview(buf); - var ctype = buf[1]; var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -22318,7 +22399,7 @@ function parse_storage(buf, sst, rsst) { data_offset += 4; } var ret; - switch (ctype) { + switch (buf[1]) { case 0: break; case 2: @@ -22344,22 +22425,24 @@ function parse_storage(buf, sst, rsst) { if (ridx > -1) ret = { t: "s", v: rsst[ridx] }; else - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } break; case 10: ret = { t: "n", v: d128 }; break; default: - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } return ret; } function parse_cell_storage(buf, sst, rsst) { switch (buf[0]) { + case 0: + case 1: + case 2: case 3: - case 4: - return parse_old_storage(buf, sst, rsst); + return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: @@ -22400,47 +22483,57 @@ function parse_TST_TableDataList(M, root) { }); return data; } -function parse_TST_TileRowInfo(u8) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; +function parse_TST_TileRowInfo(u8, type) { + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = (_b = (_a = pb[3]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data; - var pre_bnc_offsets = ((_d = (_c = pb[4]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && u8_to_dataview(pb[4][0].data); - var storage = (_f = (_e = pb[6]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; - var storage_offsets = ((_h = (_g = pb[7]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data) && u8_to_dataview(pb[7][0].data); - var wide_offsets = ((_j = (_i = pb[8]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + var wide_offsets = ((_b = (_a = pb[8]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var used_storage_u8, used_storage; + if (((_d = (_c = pb[7]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && type != 0) { + used_storage_u8 = (_f = (_e = pb[7]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; + used_storage = (_h = (_g = pb[6]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data; + } else if (((_j = (_i = pb[4]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && type != 1) { + used_storage_u8 = (_l = (_k = pb[4]) == null ? void 0 : _k[0]) == null ? void 0 : _l.data; + used_storage = (_n = (_m = pb[3]) == null ? void 0 : _m[0]) == null ? void 0 : _n.data; + } else + throw "NUMBERS Tile missing ".concat(type, " cell storage"); var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for (var C = 0; C < pre_bnc_offsets.byteLength / 2; ++C) { - if (storage && storage_offsets) { - off = storage_offsets.getUint16(C * 2, true) * width; - if (off < storage.length) { - cells[C] = storage.subarray(off, storage_offsets.getUint16(C * 2 + 2, true) * width); - continue; - } - } - if (pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C * 2, true) * width; - if (off < pre_bnc.length) - cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C * 2 + 2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets = []; + for (var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C * 2, true); + if (off < 65535) + offsets.push([C, off]); } + if (offsets.length != cnt) + throw "Expected ".concat(cnt, " cells, found ").concat(offsets.length); + var cells = []; + for (C = 0; C < offsets.length - 1; ++C) + cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C + 1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R: R, cells: cells }; } function parse_TST_Tile(M, root) { + var _a; var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce(function(acc, x) { - if (!acc[x.R]) - acc[x.R] = []; - x.cells.forEach(function(cell, C) { - if (acc[x.R][C]) - throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); - acc[x.R][C] = cell; - }); - return acc; - }, []); + var storage = ((_a = pb == null ? void 0 : pb[7]) == null ? void 0 : _a[0]) ? varint_to_i32(pb[7][0].data) >>> 0 > 0 ? 1 : 0 : -1; + var ri = mappa(pb[5], function(u8) { + return parse_TST_TileRowInfo(u8, storage); + }); + return { + nrows: varint_to_i32(pb[4][0].data) >>> 0, + data: ri.reduce(function(acc, x) { + if (!acc[x.R]) + acc[x.R] = []; + x.cells.forEach(function(cell, C) { + if (acc[x.R][C]) + throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); + acc[x.R][C] = cell; + }); + return acc; + }, []) + }; } function parse_TST_TableModelArchive(M, root, ws) { var _a; @@ -22453,33 +22546,28 @@ function parse_TST_TableModelArchive(M, root, ws) { if (range.e.c < 0) throw new Error("Invalid col varint ".concat(pb[7][0].data)); ws["!ref"] = encode_range(range); - { - var store = parse_shallow(pb[4][0].data); - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - var tile = parse_shallow(store[3][0].data); - var tiles = []; - tile[1].forEach(function(t) { - var tl = parse_shallow(t.data); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if (mtype != 6002) - throw new Error("6001 unexpected reference to ".concat(mtype)); - tiles.push({ id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; + var tile = parse_shallow(store[3][0].data); + var _R = 0; + tile[1].forEach(function(t) { + var tl = parse_shallow(t.data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if (mtype != 6002) + throw new Error("6001 unexpected reference to ".concat(mtype)); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach(function(row, R) { + row.forEach(function(buf, C) { + var addr = encode_cell({ r: _R + R, c: C }); + var res = parse_cell_storage(buf, sst, rsst); + if (res) + ws[addr] = res; }); - tiles.forEach(function(tile2) { - tile2.ref.forEach(function(row, R) { - row.forEach(function(buf, C) { - var addr = encode_cell({ r: R, c: C }); - var res = parse_cell_storage(buf, sst, rsst); - if (res) - ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } function parse_TST_TableInfoArchive(M, root) { var pb = parse_shallow(root.data); @@ -22517,8 +22605,8 @@ function parse_TN_DocumentArchive(M, root) { var mtype = varint_to_i32(m.meta[1][0].data); if (mtype == 2) { var root2 = parse_TN_SheetArchive(M, m); - root2.sheets.forEach(function(sheet) { - book_append_sheet(out, sheet, root2.name); + root2.sheets.forEach(function(sheet, idx) { + book_append_sheet(out, sheet, idx == 0 ? root2.name : root2.name + "_" + idx, true); }); } }); @@ -22528,7 +22616,8 @@ function parse_TN_DocumentArchive(M, root) { return out; } function parse_numbers_iwa(cfb) { - var out = []; + var _a, _b, _c, _d; + var out = {}, indices = []; cfb.FullPaths.forEach(function(p) { if (p.match(/\.iwpv2/)) throw new Error("Unsupported password protection"); @@ -22538,7 +22627,7 @@ function parse_numbers_iwa(cfb) { return; var o; try { - o = deframe(s.content); + o = decompress_iwa_file(s.content); } catch (e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } @@ -22549,23 +22638,25 @@ function parse_numbers_iwa(cfb) { return console.log("## " + (e.message || e)); } packets.forEach(function(packet) { - out[+packet.id] = packet.messages; + out[packet.id] = packet.messages; + indices.push(packet.id); }); }); - if (!out.length) + if (!indices.length) throw new Error("File has no messages"); - var docroot; - out.forEach(function(iwams) { - iwams.forEach(function(iwam) { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if (mtype == 1) { - if (!docroot) - docroot = iwam; - else - throw new Error("Document has multiple roots"); - } + var docroot = ((_d = (_c = (_b = (_a = out == null ? void 0 : out[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.meta) == null ? void 0 : _c[1]) == null ? void 0 : _d[0].data) && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if (!docroot) + indices.forEach(function(idx) { + out[idx].forEach(function(iwam) { + var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; + if (mtype == 1) { + if (!docroot) + docroot = iwam; + else + throw new Error("Document has multiple roots"); + } + }); }); - }); if (!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); @@ -23808,14 +23899,22 @@ function book_new()/*:Workbook*/ { } /* add a worksheet to the end of a given workbook */ -function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) { - if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; +function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ { + var i = 1; + if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets"); + if(roll && wb.SheetNames.indexOf(name) >= 0) { + var m = name.match(/(^.*?)(\d+)$/); + i = m && +m[2] || 0; + var root = m && m[1] || name; + for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break; + } check_ws_name(name); if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!"); wb.SheetNames.push(name); wb.Sheets[name] = ws; + return name; } /* set sheet visibility (visible/hidden/very hidden) */ diff --git a/xlsx.js b/xlsx.js index f95ebf6..e7e1635 100644 --- a/xlsx.js +++ b/xlsx.js @@ -5275,7 +5275,6 @@ function write_rels(rels) { return o.join(""); } -var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS]; function add_rels(rels, rId, f, type, relobj, targetmode) { if(!relobj) relobj = {}; if(!rels['!id']) rels['!id'] = {}; @@ -5286,7 +5285,7 @@ function add_rels(rels, rId, f, type, relobj, targetmode) { relobj.Type = type; relobj.Target = f; if(targetmode) relobj.TargetMode = targetmode; - else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; + else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId); rels['!id'][relobj.Id] = relobj; rels[('/' + relobj.Target).replace("//","/")] = relobj; @@ -11387,6 +11386,7 @@ function parse_xlmeta_xml(data, name, opts) { return out; var pass = false; var metatype = 2; + var lastmeta; data.replace(tagregex, function(x) { var y = parsexmltag(x); switch (strip_ns(y[0])) { @@ -11404,6 +11404,9 @@ function parse_xlmeta_xml(data, name, opts) { case "": break; case "": break; @@ -11442,6 +11445,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case "> 1 & 1431655765; x = (x & 858993459) + (x >> 2 & 858993459); return (x + (x >> 4) & 252645135) * 16843009 >>> 24; -}; -var readDecimal128LE = function(buf, offset) { +} +function readDecimal128LE(buf, offset) { var exp = (buf[offset + 15] & 127) << 7 | buf[offset + 14] >> 1; var mantissa = buf[offset + 14] & 1; for (var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return (buf[offset + 15] & 128 ? -mantissa : mantissa) * Math.pow(10, exp - 6176); -}; +} function parse_varint49(buf, ptr) { var l = ptr ? ptr[0] : 0; var usz = buf[l] & 127; @@ -21935,6 +21945,43 @@ function parse_varint49(buf, ptr) { ptr[0] = l; return usz; } +function write_varint49(v) { + var usz = new Uint8Array(7); + usz[0] = v & 127; + var L = 1; + sz: + if (v > 127) { + usz[L - 1] |= 128; + usz[L] = v >> 7 & 127; + ++L; + if (v <= 16383) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 14 & 127; + ++L; + if (v <= 2097151) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 21 & 127; + ++L; + if (v <= 268435455) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 256 >>> 21 & 127; + ++L; + if (v <= 34359738367) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 65536 >>> 21 & 127; + ++L; + if (v <= 4398046511103) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 16777216 >>> 21 & 127; + ++L; + } + return usz.slice(0, L); +} function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; varint: @@ -22103,7 +22150,7 @@ function parse_snappy_chunk(type, buf) { throw new Error("Unexpected length: ".concat(o.length, " != ").concat(usz)); return o; } -function deframe(buf) { +function decompress_iwa_file(buf) { var out = []; var l = 0; while (l < buf.length) { @@ -22117,17 +22164,52 @@ function deframe(buf) { throw new Error("data is not a valid framed stream!"); return u8concat(out); } -function parse_old_storage(buf, sst, rsst) { +function compress_iwa_file(buf) { + var out = []; + var l = 0; + while (l < buf.length) { + var c = Math.min(buf.length - l, 268435455); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + if (c <= 60) { + L++; + out.push(new Uint8Array([c - 1 << 2])); + } else if (c <= 256) { + L += 2; + out.push(new Uint8Array([240, c - 1 & 255])); + } else if (c <= 65536) { + L += 3; + out.push(new Uint8Array([244, c - 1 & 255, c - 1 >> 8 & 255])); + } else if (c <= 16777216) { + L += 4; + out.push(new Uint8Array([248, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255])); + } else if (c <= 4294967296) { + L += 5; + out.push(new Uint8Array([252, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255, c - 1 >>> 24 & 255])); + } + out.push(buf.slice(l, l + c)); + L += c; + frame[0] = 0; + frame[1] = L & 255; + frame[2] = L >> 8 & 255; + frame[3] = L >> 16 & 255; + l += c; + } + return u8concat(out); +} +function parse_old_storage(buf, sst, rsst, v) { var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 3470) * 4; + var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if (flags & 512) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 12288) * 4; + data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4; if (flags & 16) { sidx = dv.getUint32(data_offset, true); data_offset += 4; @@ -22141,7 +22223,7 @@ function parse_old_storage(buf, sst, rsst) { data_offset += 8; } var ret; - switch (ctype) { + switch (buf[2]) { case 0: break; case 2: @@ -22181,7 +22263,6 @@ function parse_old_storage(buf, sst, rsst) { } function parse_storage(buf, sst, rsst) { var dv = u8_to_dataview(buf); - var ctype = buf[1]; var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -22206,7 +22287,7 @@ function parse_storage(buf, sst, rsst) { data_offset += 4; } var ret; - switch (ctype) { + switch (buf[1]) { case 0: break; case 2: @@ -22232,22 +22313,24 @@ function parse_storage(buf, sst, rsst) { if (ridx > -1) ret = { t: "s", v: rsst[ridx] }; else - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } break; case 10: ret = { t: "n", v: d128 }; break; default: - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } return ret; } function parse_cell_storage(buf, sst, rsst) { switch (buf[0]) { + case 0: + case 1: + case 2: case 3: - case 4: - return parse_old_storage(buf, sst, rsst); + return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: @@ -22288,47 +22371,57 @@ function parse_TST_TableDataList(M, root) { }); return data; } -function parse_TST_TileRowInfo(u8) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; +function parse_TST_TileRowInfo(u8, type) { + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = (_b = (_a = pb[3]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data; - var pre_bnc_offsets = ((_d = (_c = pb[4]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && u8_to_dataview(pb[4][0].data); - var storage = (_f = (_e = pb[6]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; - var storage_offsets = ((_h = (_g = pb[7]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data) && u8_to_dataview(pb[7][0].data); - var wide_offsets = ((_j = (_i = pb[8]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + var wide_offsets = ((_b = (_a = pb[8]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var used_storage_u8, used_storage; + if (((_d = (_c = pb[7]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && type != 0) { + used_storage_u8 = (_f = (_e = pb[7]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; + used_storage = (_h = (_g = pb[6]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data; + } else if (((_j = (_i = pb[4]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && type != 1) { + used_storage_u8 = (_l = (_k = pb[4]) == null ? void 0 : _k[0]) == null ? void 0 : _l.data; + used_storage = (_n = (_m = pb[3]) == null ? void 0 : _m[0]) == null ? void 0 : _n.data; + } else + throw "NUMBERS Tile missing ".concat(type, " cell storage"); var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for (var C = 0; C < pre_bnc_offsets.byteLength / 2; ++C) { - if (storage && storage_offsets) { - off = storage_offsets.getUint16(C * 2, true) * width; - if (off < storage.length) { - cells[C] = storage.subarray(off, storage_offsets.getUint16(C * 2 + 2, true) * width); - continue; - } - } - if (pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C * 2, true) * width; - if (off < pre_bnc.length) - cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C * 2 + 2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets = []; + for (var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C * 2, true); + if (off < 65535) + offsets.push([C, off]); } + if (offsets.length != cnt) + throw "Expected ".concat(cnt, " cells, found ").concat(offsets.length); + var cells = []; + for (C = 0; C < offsets.length - 1; ++C) + cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C + 1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R: R, cells: cells }; } function parse_TST_Tile(M, root) { + var _a; var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce(function(acc, x) { - if (!acc[x.R]) - acc[x.R] = []; - x.cells.forEach(function(cell, C) { - if (acc[x.R][C]) - throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); - acc[x.R][C] = cell; - }); - return acc; - }, []); + var storage = ((_a = pb == null ? void 0 : pb[7]) == null ? void 0 : _a[0]) ? varint_to_i32(pb[7][0].data) >>> 0 > 0 ? 1 : 0 : -1; + var ri = mappa(pb[5], function(u8) { + return parse_TST_TileRowInfo(u8, storage); + }); + return { + nrows: varint_to_i32(pb[4][0].data) >>> 0, + data: ri.reduce(function(acc, x) { + if (!acc[x.R]) + acc[x.R] = []; + x.cells.forEach(function(cell, C) { + if (acc[x.R][C]) + throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); + acc[x.R][C] = cell; + }); + return acc; + }, []) + }; } function parse_TST_TableModelArchive(M, root, ws) { var _a; @@ -22341,33 +22434,28 @@ function parse_TST_TableModelArchive(M, root, ws) { if (range.e.c < 0) throw new Error("Invalid col varint ".concat(pb[7][0].data)); ws["!ref"] = encode_range(range); - { - var store = parse_shallow(pb[4][0].data); - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - var tile = parse_shallow(store[3][0].data); - var tiles = []; - tile[1].forEach(function(t) { - var tl = parse_shallow(t.data); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if (mtype != 6002) - throw new Error("6001 unexpected reference to ".concat(mtype)); - tiles.push({ id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; + var tile = parse_shallow(store[3][0].data); + var _R = 0; + tile[1].forEach(function(t) { + var tl = parse_shallow(t.data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if (mtype != 6002) + throw new Error("6001 unexpected reference to ".concat(mtype)); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach(function(row, R) { + row.forEach(function(buf, C) { + var addr = encode_cell({ r: _R + R, c: C }); + var res = parse_cell_storage(buf, sst, rsst); + if (res) + ws[addr] = res; }); - tiles.forEach(function(tile2) { - tile2.ref.forEach(function(row, R) { - row.forEach(function(buf, C) { - var addr = encode_cell({ r: R, c: C }); - var res = parse_cell_storage(buf, sst, rsst); - if (res) - ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } function parse_TST_TableInfoArchive(M, root) { var pb = parse_shallow(root.data); @@ -22405,8 +22493,8 @@ function parse_TN_DocumentArchive(M, root) { var mtype = varint_to_i32(m.meta[1][0].data); if (mtype == 2) { var root2 = parse_TN_SheetArchive(M, m); - root2.sheets.forEach(function(sheet) { - book_append_sheet(out, sheet, root2.name); + root2.sheets.forEach(function(sheet, idx) { + book_append_sheet(out, sheet, idx == 0 ? root2.name : root2.name + "_" + idx, true); }); } }); @@ -22416,7 +22504,8 @@ function parse_TN_DocumentArchive(M, root) { return out; } function parse_numbers_iwa(cfb) { - var out = []; + var _a, _b, _c, _d; + var out = {}, indices = []; cfb.FullPaths.forEach(function(p) { if (p.match(/\.iwpv2/)) throw new Error("Unsupported password protection"); @@ -22426,7 +22515,7 @@ function parse_numbers_iwa(cfb) { return; var o; try { - o = deframe(s.content); + o = decompress_iwa_file(s.content); } catch (e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } @@ -22437,23 +22526,25 @@ function parse_numbers_iwa(cfb) { return console.log("## " + (e.message || e)); } packets.forEach(function(packet) { - out[+packet.id] = packet.messages; + out[packet.id] = packet.messages; + indices.push(packet.id); }); }); - if (!out.length) + if (!indices.length) throw new Error("File has no messages"); - var docroot; - out.forEach(function(iwams) { - iwams.forEach(function(iwam) { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if (mtype == 1) { - if (!docroot) - docroot = iwam; - else - throw new Error("Document has multiple roots"); - } + var docroot = ((_d = (_c = (_b = (_a = out == null ? void 0 : out[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.meta) == null ? void 0 : _c[1]) == null ? void 0 : _d[0].data) && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if (!docroot) + indices.forEach(function(idx) { + out[idx].forEach(function(iwam) { + var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; + if (mtype == 1) { + if (!docroot) + docroot = iwam; + else + throw new Error("Document has multiple roots"); + } + }); }); - }); if (!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); @@ -23685,14 +23776,22 @@ function book_new() { } /* add a worksheet to the end of a given workbook */ -function book_append_sheet(wb, ws, name) { - if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; +function book_append_sheet(wb, ws, name, roll) { + var i = 1; + if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets"); + if(roll && wb.SheetNames.indexOf(name) >= 0) { + var m = name.match(/(^.*?)(\d+)$/); + i = m && +m[2] || 0; + var root = m && m[1] || name; + for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break; + } check_ws_name(name); if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!"); wb.SheetNames.push(name); wb.Sheets[name] = ws; + return name; } /* set sheet visibility (visible/hidden/very hidden) */ diff --git a/xlsx.mjs b/xlsx.mjs index 9e6b6d4..5cdf2ff 100644 --- a/xlsx.mjs +++ b/xlsx.mjs @@ -5360,7 +5360,6 @@ function write_rels(rels)/*:string*/ { return o.join(""); } -var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS]; function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ { if(!relobj) relobj = {}; if(!rels['!id']) rels['!id'] = {}; @@ -5371,7 +5370,7 @@ function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/) relobj.Type = type; relobj.Target = f; if(targetmode) relobj.TargetMode = targetmode; - else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; + else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External"; if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId); rels['!id'][relobj.Id] = relobj; rels[('/' + relobj.Target).replace("//","/")] = relobj; @@ -11480,6 +11479,7 @@ function parse_xlmeta_xml(data, name, opts) { return out; var pass = false; var metatype = 2; + var lastmeta; data.replace(tagregex, function(x) { var y = parsexmltag(x); switch (strip_ns(y[0])) { @@ -11497,6 +11497,9 @@ function parse_xlmeta_xml(data, name, opts) { case "": break; case "": break; @@ -11535,6 +11538,13 @@ function parse_xlmeta_xml(data, name, opts) { case "": pass = false; break; + case "> 1 & 1431655765; x = (x & 858993459) + (x >> 2 & 858993459); return (x + (x >> 4) & 252645135) * 16843009 >>> 24; -}; -var readDecimal128LE = function(buf, offset) { +} +function readDecimal128LE(buf, offset) { var exp = (buf[offset + 15] & 127) << 7 | buf[offset + 14] >> 1; var mantissa = buf[offset + 14] & 1; for (var j = offset + 13; j >= offset; --j) mantissa = mantissa * 256 + buf[j]; return (buf[offset + 15] & 128 ? -mantissa : mantissa) * Math.pow(10, exp - 6176); -}; +} function parse_varint49(buf, ptr) { var l = ptr ? ptr[0] : 0; var usz = buf[l] & 127; @@ -22045,6 +22055,43 @@ function parse_varint49(buf, ptr) { ptr[0] = l; return usz; } +function write_varint49(v) { + var usz = new Uint8Array(7); + usz[0] = v & 127; + var L = 1; + sz: + if (v > 127) { + usz[L - 1] |= 128; + usz[L] = v >> 7 & 127; + ++L; + if (v <= 16383) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 14 & 127; + ++L; + if (v <= 2097151) + break sz; + usz[L - 1] |= 128; + usz[L] = v >> 21 & 127; + ++L; + if (v <= 268435455) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 256 >>> 21 & 127; + ++L; + if (v <= 34359738367) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 65536 >>> 21 & 127; + ++L; + if (v <= 4398046511103) + break sz; + usz[L - 1] |= 128; + usz[L] = v / 16777216 >>> 21 & 127; + ++L; + } + return usz.slice(0, L); +} function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; varint: @@ -22213,7 +22260,7 @@ function parse_snappy_chunk(type, buf) { throw new Error("Unexpected length: ".concat(o.length, " != ").concat(usz)); return o; } -function deframe(buf) { +function decompress_iwa_file(buf) { var out = []; var l = 0; while (l < buf.length) { @@ -22227,17 +22274,52 @@ function deframe(buf) { throw new Error("data is not a valid framed stream!"); return u8concat(out); } -function parse_old_storage(buf, sst, rsst) { +function compress_iwa_file(buf) { + var out = []; + var l = 0; + while (l < buf.length) { + var c = Math.min(buf.length - l, 268435455); + var frame = new Uint8Array(4); + out.push(frame); + var usz = write_varint49(c); + var L = usz.length; + out.push(usz); + if (c <= 60) { + L++; + out.push(new Uint8Array([c - 1 << 2])); + } else if (c <= 256) { + L += 2; + out.push(new Uint8Array([240, c - 1 & 255])); + } else if (c <= 65536) { + L += 3; + out.push(new Uint8Array([244, c - 1 & 255, c - 1 >> 8 & 255])); + } else if (c <= 16777216) { + L += 4; + out.push(new Uint8Array([248, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255])); + } else if (c <= 4294967296) { + L += 5; + out.push(new Uint8Array([252, c - 1 & 255, c - 1 >> 8 & 255, c - 1 >> 16 & 255, c - 1 >>> 24 & 255])); + } + out.push(buf.slice(l, l + c)); + L += c; + frame[0] = 0; + frame[1] = L & 255; + frame[2] = L >> 8 & 255; + frame[3] = L >> 16 & 255; + l += c; + } + return u8concat(out); +} +function parse_old_storage(buf, sst, rsst, v) { var dv = u8_to_dataview(buf); - var ctype = buf[buf[0] == 4 ? 1 : 2]; var flags = dv.getUint32(4, true); - var data_offset = 12 + popcnt(flags & 3470) * 4; + var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4; var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1); if (flags & 512) { ridx = dv.getUint32(data_offset, true); data_offset += 4; } - data_offset += popcnt(flags & 12288) * 4; + data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4; if (flags & 16) { sidx = dv.getUint32(data_offset, true); data_offset += 4; @@ -22251,7 +22333,7 @@ function parse_old_storage(buf, sst, rsst) { data_offset += 8; } var ret; - switch (ctype) { + switch (buf[2]) { case 0: break; case 2: @@ -22291,7 +22373,6 @@ function parse_old_storage(buf, sst, rsst) { } function parse_storage(buf, sst, rsst) { var dv = u8_to_dataview(buf); - var ctype = buf[1]; var flags = dv.getUint32(8, true); var data_offset = 12; var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); @@ -22316,7 +22397,7 @@ function parse_storage(buf, sst, rsst) { data_offset += 4; } var ret; - switch (ctype) { + switch (buf[1]) { case 0: break; case 2: @@ -22342,22 +22423,24 @@ function parse_storage(buf, sst, rsst) { if (ridx > -1) ret = { t: "s", v: rsst[ridx] }; else - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } break; case 10: ret = { t: "n", v: d128 }; break; default: - throw new Error("Unsupported cell type ".concat(ctype, " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf.slice(0, 4))); } return ret; } function parse_cell_storage(buf, sst, rsst) { switch (buf[0]) { + case 0: + case 1: + case 2: case 3: - case 4: - return parse_old_storage(buf, sst, rsst); + return parse_old_storage(buf, sst, rsst, buf[0]); case 5: return parse_storage(buf, sst, rsst); default: @@ -22398,47 +22481,57 @@ function parse_TST_TableDataList(M, root) { }); return data; } -function parse_TST_TileRowInfo(u8) { - var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; +function parse_TST_TileRowInfo(u8, type) { + var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; var pb = parse_shallow(u8); var R = varint_to_i32(pb[1][0].data) >>> 0; - var pre_bnc = (_b = (_a = pb[3]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data; - var pre_bnc_offsets = ((_d = (_c = pb[4]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && u8_to_dataview(pb[4][0].data); - var storage = (_f = (_e = pb[6]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; - var storage_offsets = ((_h = (_g = pb[7]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data) && u8_to_dataview(pb[7][0].data); - var wide_offsets = ((_j = (_i = pb[8]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var cnt = varint_to_i32(pb[2][0].data) >>> 0; + var wide_offsets = ((_b = (_a = pb[8]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data) && varint_to_i32(pb[8][0].data) > 0 || false; + var used_storage_u8, used_storage; + if (((_d = (_c = pb[7]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) && type != 0) { + used_storage_u8 = (_f = (_e = pb[7]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data; + used_storage = (_h = (_g = pb[6]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data; + } else if (((_j = (_i = pb[4]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data) && type != 1) { + used_storage_u8 = (_l = (_k = pb[4]) == null ? void 0 : _k[0]) == null ? void 0 : _l.data; + used_storage = (_n = (_m = pb[3]) == null ? void 0 : _m[0]) == null ? void 0 : _n.data; + } else + throw "NUMBERS Tile missing ".concat(type, " cell storage"); var width = wide_offsets ? 4 : 1; - var cells = []; - var off = 0; - for (var C = 0; C < pre_bnc_offsets.byteLength / 2; ++C) { - if (storage && storage_offsets) { - off = storage_offsets.getUint16(C * 2, true) * width; - if (off < storage.length) { - cells[C] = storage.subarray(off, storage_offsets.getUint16(C * 2 + 2, true) * width); - continue; - } - } - if (pre_bnc && pre_bnc_offsets) { - off = pre_bnc_offsets.getUint16(C * 2, true) * width; - if (off < pre_bnc.length) - cells[C] = pre_bnc.subarray(off, pre_bnc_offsets.getUint16(C * 2 + 2, true) * width); - } + var used_storage_offsets = u8_to_dataview(used_storage_u8); + var offsets = []; + for (var C = 0; C < used_storage_u8.length / 2; ++C) { + var off = used_storage_offsets.getUint16(C * 2, true); + if (off < 65535) + offsets.push([C, off]); } + if (offsets.length != cnt) + throw "Expected ".concat(cnt, " cells, found ").concat(offsets.length); + var cells = []; + for (C = 0; C < offsets.length - 1; ++C) + cells[offsets[C][0]] = used_storage.subarray(offsets[C][1] * width, offsets[C + 1][1] * width); + cells[offsets[offsets.length - 1][0]] = used_storage.subarray(offsets[offsets.length - 1][1] * width); return { R: R, cells: cells }; } function parse_TST_Tile(M, root) { + var _a; var pb = parse_shallow(root.data); - var ri = mappa(pb[5], parse_TST_TileRowInfo); - return ri.reduce(function(acc, x) { - if (!acc[x.R]) - acc[x.R] = []; - x.cells.forEach(function(cell, C) { - if (acc[x.R][C]) - throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); - acc[x.R][C] = cell; - }); - return acc; - }, []); + var storage = ((_a = pb == null ? void 0 : pb[7]) == null ? void 0 : _a[0]) ? varint_to_i32(pb[7][0].data) >>> 0 > 0 ? 1 : 0 : -1; + var ri = mappa(pb[5], function(u8) { + return parse_TST_TileRowInfo(u8, storage); + }); + return { + nrows: varint_to_i32(pb[4][0].data) >>> 0, + data: ri.reduce(function(acc, x) { + if (!acc[x.R]) + acc[x.R] = []; + x.cells.forEach(function(cell, C) { + if (acc[x.R][C]) + throw new Error("Duplicate cell r=".concat(x.R, " c=").concat(C)); + acc[x.R][C] = cell; + }); + return acc; + }, []) + }; } function parse_TST_TableModelArchive(M, root, ws) { var _a; @@ -22451,33 +22544,28 @@ function parse_TST_TableModelArchive(M, root, ws) { if (range.e.c < 0) throw new Error("Invalid col varint ".concat(pb[7][0].data)); ws["!ref"] = encode_range(range); - { - var store = parse_shallow(pb[4][0].data); - var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; - { - var tile = parse_shallow(store[3][0].data); - var tiles = []; - tile[1].forEach(function(t) { - var tl = parse_shallow(t.data); - var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; - var mtype = varint_to_i32(ref.meta[1][0].data); - if (mtype != 6002) - throw new Error("6001 unexpected reference to ".concat(mtype)); - tiles.push({ id: varint_to_i32(tl[1][0].data), ref: parse_TST_Tile(M, ref) }); + var store = parse_shallow(pb[4][0].data); + var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : []; + var tile = parse_shallow(store[3][0].data); + var _R = 0; + tile[1].forEach(function(t) { + var tl = parse_shallow(t.data); + var ref = M[parse_TSP_Reference(tl[2][0].data)][0]; + var mtype = varint_to_i32(ref.meta[1][0].data); + if (mtype != 6002) + throw new Error("6001 unexpected reference to ".concat(mtype)); + var _tile = parse_TST_Tile(M, ref); + _tile.data.forEach(function(row, R) { + row.forEach(function(buf, C) { + var addr = encode_cell({ r: _R + R, c: C }); + var res = parse_cell_storage(buf, sst, rsst); + if (res) + ws[addr] = res; }); - tiles.forEach(function(tile2) { - tile2.ref.forEach(function(row, R) { - row.forEach(function(buf, C) { - var addr = encode_cell({ r: R, c: C }); - var res = parse_cell_storage(buf, sst, rsst); - if (res) - ws[addr] = res; - }); - }); - }); - } - } + }); + _R += _tile.nrows; + }); } function parse_TST_TableInfoArchive(M, root) { var pb = parse_shallow(root.data); @@ -22515,8 +22603,8 @@ function parse_TN_DocumentArchive(M, root) { var mtype = varint_to_i32(m.meta[1][0].data); if (mtype == 2) { var root2 = parse_TN_SheetArchive(M, m); - root2.sheets.forEach(function(sheet) { - book_append_sheet(out, sheet, root2.name); + root2.sheets.forEach(function(sheet, idx) { + book_append_sheet(out, sheet, idx == 0 ? root2.name : root2.name + "_" + idx, true); }); } }); @@ -22526,7 +22614,8 @@ function parse_TN_DocumentArchive(M, root) { return out; } function parse_numbers_iwa(cfb) { - var out = []; + var _a, _b, _c, _d; + var out = {}, indices = []; cfb.FullPaths.forEach(function(p) { if (p.match(/\.iwpv2/)) throw new Error("Unsupported password protection"); @@ -22536,7 +22625,7 @@ function parse_numbers_iwa(cfb) { return; var o; try { - o = deframe(s.content); + o = decompress_iwa_file(s.content); } catch (e) { return console.log("?? " + s.content.length + " " + (e.message || e)); } @@ -22547,23 +22636,25 @@ function parse_numbers_iwa(cfb) { return console.log("## " + (e.message || e)); } packets.forEach(function(packet) { - out[+packet.id] = packet.messages; + out[packet.id] = packet.messages; + indices.push(packet.id); }); }); - if (!out.length) + if (!indices.length) throw new Error("File has no messages"); - var docroot; - out.forEach(function(iwams) { - iwams.forEach(function(iwam) { - var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; - if (mtype == 1) { - if (!docroot) - docroot = iwam; - else - throw new Error("Document has multiple roots"); - } + var docroot = ((_d = (_c = (_b = (_a = out == null ? void 0 : out[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.meta) == null ? void 0 : _c[1]) == null ? void 0 : _d[0].data) && varint_to_i32(out[1][0].meta[1][0].data) == 1 && out[1][0]; + if (!docroot) + indices.forEach(function(idx) { + out[idx].forEach(function(iwam) { + var mtype = varint_to_i32(iwam.meta[1][0].data) >>> 0; + if (mtype == 1) { + if (!docroot) + docroot = iwam; + else + throw new Error("Document has multiple roots"); + } + }); }); - }); if (!docroot) throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(out, docroot); @@ -23806,14 +23897,22 @@ function book_new()/*:Workbook*/ { } /* add a worksheet to the end of a given workbook */ -function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) { - if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; +function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ { + var i = 1; + if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets"); + if(roll && wb.SheetNames.indexOf(name) >= 0) { + var m = name.match(/(^.*?)(\d+)$/); + i = m && +m[2] || 0; + var root = m && m[1] || name; + for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break; + } check_ws_name(name); if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!"); wb.SheetNames.push(name); wb.Sheets[name] = ws; + return name; } /* set sheet visibility (visible/hidden/very hidden) */