From c654a2656b81548524b823a94c90f37950049fc1 Mon Sep 17 00:00:00 2001 From: reviewher Date: Thu, 11 Jan 2018 03:01:25 -0500 Subject: [PATCH] archaic browser compatibility and testing IE11 Compatibility View levels 5 and 7 (see #952) Firefox 5.0+ passes browser test (see #950) --- bits/02_codepage.js | 8 +- bits/05_buf.js | 9 +++ bits/20_jsutils.js | 5 +- bits/22_xmlutils.js | 12 +-- bits/28_binstructs.js | 6 +- bits/31_rels.js | 2 +- bits/33_coreprops.js | 2 +- bits/35_custprops.js | 4 +- bits/38_xlstypes.js | 5 +- bits/40_harb.js | 38 ++++----- bits/41_lotus.js | 4 +- bits/42_sstxml.js | 2 +- bits/46_stycommon.js | 6 +- bits/49_theme.js | 2 +- bits/62_fxls.js | 6 +- bits/65_fods.js | 6 +- bits/67_wsxml.js | 22 ++--- bits/68_wsbin.js | 2 +- bits/72_wbxml.js | 2 +- bits/73_wbbin.js | 2 +- bits/75_xlml.js | 24 +++--- bits/79_html.js | 4 +- bits/81_writeods.js | 2 +- bits/87_read.js | 8 +- test.js | 29 ++++--- tests/core.js | 29 ++++--- xlsx.flow.js | 183 +++++++++++++++++++++++------------------- xlsx.js | 182 ++++++++++++++++++++++------------------- 28 files changed, 335 insertions(+), 271 deletions(-) diff --git a/bits/02_codepage.js b/bits/02_codepage.js index 9c4b3de..56e88ce 100644 --- a/bits/02_codepage.js +++ b/bits/02_codepage.js @@ -52,9 +52,9 @@ function utf16beread(data/*:string*/)/*:string*/ { var debom = function(data/*:string*/)/*:string*/ { var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1); - if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.substr(2)); - if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.substr(2)); - if(c1 == 0xFEFF) return data.substr(1); + if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2)); + if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2)); + if(c1 == 0xFEFF) return data.slice(1); return data; }; @@ -62,7 +62,7 @@ var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCo if(typeof cptable !== 'undefined') { set_cp = function(cp/*:number*/) { current_codepage = cp; }; debom = function(data/*:string*/) { - if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); } + if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); } return data; }; _getchar = function _gc2(x/*:number*/)/*:string*/ { diff --git a/bits/05_buf.js b/bits/05_buf.js index c0722c5..5efd3fc 100644 --- a/bits/05_buf.js +++ b/bits/05_buf.js @@ -24,6 +24,15 @@ function arr2str(data/*:any*/)/*:string*/ { var o/*:Array*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); } +function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array*/ { + if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported"); + if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data)); + /*:: if(data instanceof ArrayBuffer) throw new Error("unreachable"); */ + var o = new Array(data.length); + for(var i = 0; i < data.length; ++i) o[i] = data[i]; + return o; +} + var bconcat = function(bufs) { return [].concat.apply([], bufs); }; var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g; diff --git a/bits/20_jsutils.js b/bits/20_jsutils.js index df2571f..4e321c5 100644 --- a/bits/20_jsutils.js +++ b/bits/20_jsutils.js @@ -49,9 +49,9 @@ function parse_isodur(s) { if(!m[i]) continue; mt = 1; if(i > 3) time = true; - switch(m[i].substr(m[i].length-1)) { + switch(m[i].slice(m[i].length-1)) { case 'Y': - throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1)); + throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1)); case 'D': mt *= 24; /* falls through */ case 'H': mt *= 60; @@ -100,6 +100,7 @@ function cc2str(arr/*:Array*/)/*:string*/ { function dup(o/*:any*/)/*:any*/ { if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o)); if(typeof o != 'object' || o == null) return o; + if(o instanceof Date) return new Date(o.getTime()); var out = {}; for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); return out; diff --git a/bits/22_xmlutils.js b/bits/22_xmlutils.js index 40ff850..d3e2224 100644 --- a/bits/22_xmlutils.js +++ b/bits/22_xmlutils.js @@ -7,24 +7,24 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ { var z = ({}/*:any*/); var eq = 0, c = 0; for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; - if(!skip_root) z[0] = tag.substr(0, eq); + if(!skip_root) z[0] = tag.slice(0, eq); if(eq === tag.length) return z; var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1; if(m) for(i = 0; i != m.length; ++i) { cc = m[i]; for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; - q = cc.substr(0,c).trim(); + q = cc.slice(0,c).trim(); while(cc.charCodeAt(c+1) == 32) ++c; quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0; - v = cc.substring(c+1+quot, cc.length-quot); + v = cc.slice(c+1+quot, cc.length-quot); for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; if(j===q.length) { - if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods + if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods z[q] = v; } else { - var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1); - if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods + var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1); + if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods z[k] = v; } } diff --git a/bits/28_binstructs.js b/bits/28_binstructs.js index 3a3b004..a826c4d 100644 --- a/bits/28_binstructs.js +++ b/bits/28_binstructs.js @@ -227,9 +227,9 @@ function write_BrtColor(color, o) { o.write_shift(1, 0); } else { var rgb = (color.rgb || 'FFFFFF'); - o.write_shift(1, parseInt(rgb.substr(0,2),16)); - o.write_shift(1, parseInt(rgb.substr(2,2),16)); - o.write_shift(1, parseInt(rgb.substr(4,2),16)); + o.write_shift(1, parseInt(rgb.slice(0,2),16)); + o.write_shift(1, parseInt(rgb.slice(2,4),16)); + o.write_shift(1, parseInt(rgb.slice(4,6),16)); o.write_shift(1, 0xFF); } return o; diff --git a/bits/31_rels.js b/bits/31_rels.js index 195bbce..911f286 100644 --- a/bits/31_rels.js +++ b/bits/31_rels.js @@ -10,7 +10,7 @@ var RELS = ({ /* 9.3.3 Representing Relationships */ function get_rels_path(file/*:string*/)/*:string*/ { var n = file.lastIndexOf("/"); - return file.substr(0,n+1) + '_rels/' + file.substr(n+1) + ".rels"; + return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels"; } function parse_rels(data/*:?string*/, currentFilePath/*:string*/) { diff --git a/bits/33_coreprops.js b/bits/33_coreprops.js index ac50253..d11a8fd 100644 --- a/bits/33_coreprops.js +++ b/bits/33_coreprops.js @@ -25,7 +25,7 @@ var CORE_PROPS_REGEX/*:Array*/ = (function() { var r = new Array(CORE_PROPS.length); for(var i = 0; i < CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; - var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1); + var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1); r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">"); } return r; diff --git a/bits/35_custprops.js b/bits/35_custprops.js index 214ad4b..fd6adcd 100644 --- a/bits/35_custprops.js +++ b/bits/35_custprops.js @@ -15,7 +15,7 @@ function parse_cust_props(data/*:string*/, opts) { case '': name = null; break; default: if (x.indexOf(''); - var type = toks[0].substring(4), text = toks[1]; + var type = toks[0].slice(4), text = toks[1]; /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */ switch(type) { case 'lpstr': case 'bstr': case 'lpwstr': @@ -40,7 +40,7 @@ function parse_cust_props(data/*:string*/, opts) { if(type.slice(-1) == '/') break; if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); } - } else if(x.substr(0,2) === "= 2 && opts.biff <= 5) encoding = 'cpstr'; var o = cch ? blob.read_shift(cch, encoding) : ""; current_codepage = cp; return o; @@ -342,7 +343,7 @@ function parse_XLUnicodeRichExtendedString(blob) { function parse_XLUnicodeStringNoCch(blob, cch, opts) { var retval; if(opts) { - if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont'); + if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr'); if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont'); } var fHighByte = blob.read_shift(1); @@ -362,7 +363,7 @@ function parse_XLUnicodeString2(blob, length, opts) { if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts); var cch = blob.read_shift(1); if(cch === 0) { blob.l++; return ""; } - return blob.read_shift(cch, opts.biff == 4 ? 'cpstr' : 'sbcs-cont'); + return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont'); } /* TODO: BIFF5 and lower, codepage awareness */ function write_XLUnicodeString(str, opts, o) { diff --git a/bits/40_harb.js b/bits/40_harb.js index 13d65ef..7e86da9 100644 --- a/bits/40_harb.js +++ b/bits/40_harb.js @@ -149,7 +149,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ { out[R][C] = out[R][C].trim(); break; case 'D': - if(s.length === 8) out[R][C] = new Date(+s.substr(0,4), +s.substr(4,2)-1, +s.substr(6,2)); + if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8)); else out[R][C] = s; break; case 'F': out[R][C] = parseFloat(s.trim()); break; @@ -325,18 +325,18 @@ var SYLK = (function() { case 'O': break; /* options? */ case 'P': if(record[1].charAt(0) == 'P') - formats.push(rstr.substr(3).replace(/;;/g, ";")); + formats.push(rstr.slice(3).replace(/;;/g, ";")); break; case 'C': for(rj=1; rj 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); } else if(Mval === 0) rowinfo[R].hidden = true; @@ -506,7 +506,7 @@ var DIF = (function() { else arr[R][C] = value; ++C; break; case 1: - data = data.substr(1,data.length-2); + data = data.slice(1,data.length-1); arr[R][C++] = data !== '' ? data : null; break; } @@ -761,8 +761,8 @@ var PRN = (function() { var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/); - if(str.substr(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.substr(6); } - else sep = guess_sep(str.substr(0,1024)); + if(str.slice(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.slice(6); } + else sep = guess_sep(str.slice(0,1024)); var R = 0, C = 0, v = 0; var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0; str = str.replace(/\r\n/mg, "\n"); @@ -776,7 +776,7 @@ var PRN = (function() { else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; } else if(s.charCodeAt(0) == 0x3D) { if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } - else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } + else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); } else { cell.t = 's'; cell.v = s; } } else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } @@ -846,7 +846,7 @@ var PRN = (function() { var coord = encode_cell({r:R,c:C}); cell = dense ? (ws[R]||[])[C] : ws[coord]; if(!cell || cell.v == null) { oo.push(" "); continue; } - var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10); + var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10); while(w.length < 10) w += " "; oo.push(w + (C === 0 ? " " : "")); } diff --git a/bits/41_lotus.js b/bits/41_lotus.js index c9d3434..5e84b5f 100644 --- a/bits/41_lotus.js +++ b/bits/41_lotus.js @@ -45,7 +45,7 @@ var WK_ = (function() { break; case 0x06: refguess = val; break; /* RANGE */ case 0x0F: /* LABEL */ - if(!o.qpro) val[1].v = val[1].v.substr(1); + if(!o.qpro) val[1].v = val[1].v.slice(1); /* falls through */ case 0x0D: /* INTEGER */ case 0x0E: /* NUMBER */ @@ -63,7 +63,7 @@ var WK_ = (function() { break; } else switch(RT) { case 0x16: /* LABEL16 */ - val[1].v = val[1].v.substr(1); + val[1].v = val[1].v.slice(1); /* falls through */ case 0x17: /* NUMBER17 */ case 0x18: /* NUMBER18 */ diff --git a/bits/42_sstxml.js b/bits/42_sstxml.js index c36cb2f..bb9aac0 100644 --- a/bits/42_sstxml.js +++ b/bits/42_sstxml.js @@ -82,7 +82,7 @@ var parse_rs = (function parse_rs_factory() { /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */ case '255?255:rgb[i]<0?0:rgb[i]); - return o.toString(16).toUpperCase().substr(1); + return o.toString(16).toUpperCase().slice(1); } function rgb2HSL(rgb) { diff --git a/bits/49_theme.js b/bits/49_theme.js index 2d21318..49f7785 100644 --- a/bits/49_theme.js +++ b/bits/49_theme.js @@ -46,7 +46,7 @@ function parse_clrScheme(t, themes, opts) { themes.themeElements.clrScheme.push(color); color = {}; } else { - color.name = y[0].substring(3, y[0].length - 1); + color.name = y[0].slice(3, y[0].length - 1); } break; diff --git a/bits/62_fxls.js b/bits/62_fxls.js index b8d02cf..9d9a4f9 100644 --- a/bits/62_fxls.js +++ b/bits/62_fxls.js @@ -690,8 +690,8 @@ var PtgBinOp = { PtgPower: "^", PtgSub: "-" }; -function formula_quote_sheet_name(sname/*:string*/)/*:string*/ { - if(!sname) throw new Error("empty sheet name"); +function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { + if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); if(sname.indexOf(" ") > -1) return "'" + sname + "'"; return sname; } @@ -730,7 +730,7 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { } } function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ { - return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts)); + return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts); } function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, opts)/*:string*/ { var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; diff --git a/bits/65_fods.js b/bits/65_fods.js index 7e4deb6..e8af5cd 100644 --- a/bits/65_fods.js +++ b/bits/65_fods.js @@ -1,10 +1,10 @@ /* Part 3 TODO: actually parse formulae */ function ods_to_csf_formula(f/*:string*/)/*:string*/ { - if(f.substr(0,3) == "of:") f = f.substr(3); + if(f.slice(0,3) == "of:") f = f.slice(3); /* 5.2 Basic Expressions */ if(f.charCodeAt(0) == 61) { - f = f.substr(1); - if(f.charCodeAt(0) == 61) f = f.substr(1); + f = f.slice(1); + if(f.charCodeAt(0) == 61) f = f.slice(1); } f = f.replace(/COM\.MICROSOFT\./g, ""); /* Part 3 Section 5.8 References */ diff --git a/bits/67_wsxml.js b/bits/67_wsxml.js index 10dc5be..95a03f0 100644 --- a/bits/67_wsxml.js +++ b/bits/67_wsxml.js @@ -23,8 +23,8 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro var data1 = "", data2 = ""; var mtch/*:?any*/ = data.match(sheetdataregex); if(mtch) { - data1 = data.substr(0, mtch.index); - data2 = data.substr(mtch.index + mtch[0].length); + data1 = data.slice(0, mtch.index); + data2 = data.slice(mtch.index + mtch[0].length); } else data1 = data2 = data; /* 18.3.1.82 sheetPr CT_SheetPr */ @@ -35,7 +35,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro // $FlowIgnore var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index; if(ridx > 0) { - var ref = data1.substr(ridx,50).match(dimregex); + var ref = data1.slice(ridx,ridx+50).match(dimregex); if(ref) parse_ws_xml_dim(s, ref[1]); } @@ -62,7 +62,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro var merges/*:Array*/ = []; var _merge = data2.match(mergecregex); if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx) - merges[ridx] = safe_decode_range(_merge[ridx].substr(_merge[ridx].indexOf("\"")+1)); + merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1)); /* 18.3.1.48 hyperlinks CT_Hyperlinks */ var hlink = data2.match(hlinkregex); @@ -252,7 +252,7 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb)/*:string*/ { } if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } if(cell.f) { - var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; + var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); } if(cell.l) ws['!links'].push([ref, cell.l]); @@ -283,7 +283,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th /* 18.3.1.73 row CT_Row */ for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; - tag = parsexmltag(x.substr(0,ri), true); + tag = parsexmltag(x.slice(0,ri), true); tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; if(opts.sheetRows && opts.sheetRows < tagr) continue; if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; @@ -298,12 +298,12 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th } /* 18.3.1.4 c CT_Cell */ - cells = x.substr(ri).split(cellregex); + cells = x.slice(ri).split(cellregex); for(ri = 0; ri != cells.length; ++ri) { x = cells[ri].trim(); if(x.length === 0) continue; cref = x.match(rregex); idx = ri; i=0; cc=0; - x = "":"") + x; + x = "":"") + x; if(cref != null && cref.length === 2) { idx = 0; d=cref[1]; for(i=0; i != d.length; ++i) { @@ -314,9 +314,9 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th tagc = idx; } else ++tagc; for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i; - tag = parsexmltag(x.substr(0,i), true); + tag = parsexmltag(x.slice(0,i), true); if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc}); - d = x.substr(i); + d = x.slice(i); p = ({t:""}/*:any*/); if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); @@ -528,7 +528,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ { rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK); rel["r:id"] = "rId"+rId; } - if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.substr(relc+1)); + if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1)); if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip); o[o.length] = writextag("hyperlink",null,rel); }); diff --git a/bits/68_wsbin.js b/bits/68_wsbin.js index 360f6d0..ded54e5 100644 --- a/bits/68_wsbin.js +++ b/bits/68_wsbin.js @@ -270,7 +270,7 @@ function write_BrtHLink(l, rId) { write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o); write_RelID("rId" + rId, o); var locidx = l[1].Target.indexOf("#"); - var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1); + var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1); write_XLWideString(loc || "", o); write_XLWideString(l[1].Tooltip || "", o); write_XLWideString("", o); diff --git a/bits/72_wbxml.js b/bits/72_wbxml.js index 477fb0d..9bbf262 100644 --- a/bits/72_wbxml.js +++ b/bits/72_wbxml.js @@ -189,7 +189,7 @@ function write_wb_xml(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:string*/ { o[o.length] = ""; var sheets = wb.Workbook && wb.Workbook.Sheets || []; for(var i = 0; i != wb.SheetNames.length; ++i) { - var sht = ({name:escapexml(wb.SheetNames[i].substr(0,31))}/*:any*/); + var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/); sht.sheetId = ""+(i+1); sht["r:id"] = "rId"+(i+1); if(sheets[i]) switch(sheets[i].Hidden) { diff --git a/bits/73_wbbin.js b/bits/73_wbbin.js index 6a36f4a..87b3655 100644 --- a/bits/73_wbbin.js +++ b/bits/73_wbbin.js @@ -12,7 +12,7 @@ function write_BrtBundleSh(data, o) { o.write_shift(4, data.Hidden); o.write_shift(4, data.iTabID); write_RelID(data.strRelID, o); - write_XLWideString(data.name.substr(0,31), o); + write_XLWideString(data.name.slice(0,31), o); return o.length > o.l ? o.slice(0, o.l) : o; } diff --git a/bits/75_xlml.js b/bits/75_xlml.js index 27e9e66..2c157ca 100644 --- a/bits/75_xlml.js +++ b/bits/75_xlml.js @@ -9,11 +9,11 @@ function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) { if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); /*:: if(!y || !y[2]) continue; */ - if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -26,11 +26,11 @@ function xlml_parsexmltagobj(tag/*:string*/) { if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); /*:: if(!y || !y[2]) continue; */ - if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -130,7 +130,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a if(cell.Formula) { var fstr = unescapexml(cell.Formula); /* strictly speaking, the leading = is required but some writers omit */ - if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.substr(1); + if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1); cell.f = rc_to_a1(fstr, base); delete cell.Formula; if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base); @@ -334,7 +334,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { var _NamedRange = parsexmltag(Rn[0]); var _DefinedName/*:DefinedName*/ = ({ Name: _NamedRange.Name, - Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) + Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) }/*:any*/); if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; /*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName); @@ -1017,8 +1017,8 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, var attr = {}; if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); - if(cell.F && cell.F.substr(0, ref.length) == ref) { - var end = decode_cell(cell.F.substr(ref.length + 1)); + if(cell.F && cell.F.slice(0, ref.length) == ref) { + var end = decode_cell(cell.F.slice(ref.length + 1)); attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); } diff --git a/bits/79_html.js b/bits/79_html.js index e3a7b97..5077e75 100644 --- a/bits/79_html.js +++ b/bits/79_html.js @@ -14,13 +14,13 @@ var HTML_ = (function() { var merges/*:Array*/ = [], midx = 0; for(i = 0; i < rows.length; ++i) { var row = rows[i].trim(); - var hd = row.substr(0,3).toLowerCase(); + var hd = row.slice(0,3).toLowerCase(); if(hd == "/i); for(j = 0; j < cells.length; ++j) { var cell = cells[j].trim(); - if(cell.substr(0,3).toLowerCase() != "")) > -1) m = m.slice(cc+1); diff --git a/bits/81_writeods.js b/bits/81_writeods.js index 10a69d3..95720e1 100644 --- a/bits/81_writeods.js +++ b/bits/81_writeods.js @@ -58,7 +58,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() { if(cell && cell.f) { ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); if(cell.F) { - if(cell.F.substr(0, ref.length) == ref) { + if(cell.F.slice(0, ref.length) == ref) { var _Fref = decode_range(cell.F); ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1); ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1); diff --git a/bits/87_read.js b/bits/87_read.js index b78e9d7..b88bb5c 100644 --- a/bits/87_read.js +++ b/bits/87_read.js @@ -2,7 +2,7 @@ function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array*/ { var x = ""; switch((o||{}).type || "base64") { case 'buffer': return [f[0], f[1], f[2], f[3]]; - case 'base64': x = Base64.decode(f.substr(0,24)); break; + case 'base64': x = Base64.decode(f.slice(0,24)); break; case 'binary': x = f; break; case 'array': return [f[0], f[1], f[2], f[3]]; default: throw new Error("Unrecognized type " + (o && o.type || "undefined")); @@ -79,6 +79,12 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); } + if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array) { + // $FlowIgnore + var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar"; + // $FlowIgnore + if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);} + } switch((n = firstbyte(d, o))[0]) { case 0xD0: return read_cfb(CFB.read(d, o), o); case 0x09: return parse_xlscfb(d, o); diff --git a/test.js b/test.js index 2768da9..9771b4f 100644 --- a/test.js +++ b/test.js @@ -269,7 +269,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin }); }); }); - describe(x + ext + ' should generate correct JSON output', function() { + if(typeof JSON !== 'undefined') describe(x + ext + ' should generate correct JSON output', function() { wb.SheetNames.forEach(function(ws, i) { var rawjson = getfile(dir, x, i, ".rawjson"); if(fs.existsSync(rawjson)) it('#' + i + ' (' + ws + ')', function() { @@ -601,15 +601,21 @@ describe('input formats', function() { it('should read base64 strings', function() { artifax.forEach(function(p) { X.read(fs.readFileSync(p, 'base64'), {type: 'base64'}); }); }); - var k = browser ? 'array' : 'buffer'; - (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() { artifax.forEach(function(p) { - X.read(fs.readFileSync(p, browser ? 'buffer' : null), {type: k}); - }); }); (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() { artifax.forEach(function(p) { - X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); + X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); + }); }); + ((browser || typeof Buffer === 'undefined') ? it.skip : it)('should read Buffers', function() { artifax.forEach(function(p) { + X.read(fs.readFileSync(p), {type: 'buffer'}); + }); }); + (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) { + var payload = fs.readFileSync(p, browser ? 'buffer' : null); + var ab = new ArrayBuffer(payload.length), vu = new Uint8Array(ab); + for(var i = 0; i < payload.length; ++i) vu[i] = payload[i]; + X.read(ab, {type: 'array'}); + X.read(vu, {type: 'array'}); }); }); it('should throw if format is unknown', function() { artifax.forEach(function(p) { - assert.throws(function() { X.read(fs.readFileSync(p), {type: 'dafuq'}); }); + assert.throws(function() { X.read(fs.readFileSync(p), {type: 'dafuq'}); }); }); }); var T = browser ? 'base64' : 'buffer'; @@ -1011,8 +1017,8 @@ describe('parse features', function() { var wb1, wb2; var bef = (function() { X = require(modp); - wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); - wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); + wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); + wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); }); if(typeof before != 'undefined') before(bef); else it('before', bef); @@ -1127,7 +1133,7 @@ describe('parse features', function() { var wbs=[]; var bef = (function() { if(!fs.existsSync(paths.pmxls)) return; - wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); + wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); }); if(typeof before != 'undefined') before(bef); else it('before', bef); @@ -1550,6 +1556,7 @@ describe('invalid files', function() { describe('json output', function() { function seeker(json, keys, val) { + if(typeof keys == "string") keys = keys.split(""); for(var i = 0; i != json.length; ++i) { for(var j = 0; j != keys.length; ++j) { if(json[i][keys[j]] === val) throw new Error("found " + val + " in row " + i + " key " + keys[j]); @@ -2031,7 +2038,7 @@ describe('corner cases', function() { assert.doesNotThrow(function(x) { return X.SSF.format(f, 12345.6789);}); }); }); - it('SSF oddities', function() { + if(typeof JSON !== 'undefined') it('SSF oddities', function() { // $FlowIgnore var ssfdata = require('./misc/ssf.json'); var cb = function(d, j) { return function() { return X.SSF.format(d[0], d[j][0]); }; }; diff --git a/tests/core.js b/tests/core.js index 2768da9..9771b4f 100644 --- a/tests/core.js +++ b/tests/core.js @@ -269,7 +269,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin }); }); }); - describe(x + ext + ' should generate correct JSON output', function() { + if(typeof JSON !== 'undefined') describe(x + ext + ' should generate correct JSON output', function() { wb.SheetNames.forEach(function(ws, i) { var rawjson = getfile(dir, x, i, ".rawjson"); if(fs.existsSync(rawjson)) it('#' + i + ' (' + ws + ')', function() { @@ -601,15 +601,21 @@ describe('input formats', function() { it('should read base64 strings', function() { artifax.forEach(function(p) { X.read(fs.readFileSync(p, 'base64'), {type: 'base64'}); }); }); - var k = browser ? 'array' : 'buffer'; - (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() { artifax.forEach(function(p) { - X.read(fs.readFileSync(p, browser ? 'buffer' : null), {type: k}); - }); }); (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() { artifax.forEach(function(p) { - X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); + X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); + }); }); + ((browser || typeof Buffer === 'undefined') ? it.skip : it)('should read Buffers', function() { artifax.forEach(function(p) { + X.read(fs.readFileSync(p), {type: 'buffer'}); + }); }); + (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) { + var payload = fs.readFileSync(p, browser ? 'buffer' : null); + var ab = new ArrayBuffer(payload.length), vu = new Uint8Array(ab); + for(var i = 0; i < payload.length; ++i) vu[i] = payload[i]; + X.read(ab, {type: 'array'}); + X.read(vu, {type: 'array'}); }); }); it('should throw if format is unknown', function() { artifax.forEach(function(p) { - assert.throws(function() { X.read(fs.readFileSync(p), {type: 'dafuq'}); }); + assert.throws(function() { X.read(fs.readFileSync(p), {type: 'dafuq'}); }); }); }); var T = browser ? 'base64' : 'buffer'; @@ -1011,8 +1017,8 @@ describe('parse features', function() { var wb1, wb2; var bef = (function() { X = require(modp); - wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); - wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); + wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); + wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); }); if(typeof before != 'undefined') before(bef); else it('before', bef); @@ -1127,7 +1133,7 @@ describe('parse features', function() { var wbs=[]; var bef = (function() { if(!fs.existsSync(paths.pmxls)) return; - wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); }); + wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); }); }); if(typeof before != 'undefined') before(bef); else it('before', bef); @@ -1550,6 +1556,7 @@ describe('invalid files', function() { describe('json output', function() { function seeker(json, keys, val) { + if(typeof keys == "string") keys = keys.split(""); for(var i = 0; i != json.length; ++i) { for(var j = 0; j != keys.length; ++j) { if(json[i][keys[j]] === val) throw new Error("found " + val + " in row " + i + " key " + keys[j]); @@ -2031,7 +2038,7 @@ describe('corner cases', function() { assert.doesNotThrow(function(x) { return X.SSF.format(f, 12345.6789);}); }); }); - it('SSF oddities', function() { + if(typeof JSON !== 'undefined') it('SSF oddities', function() { // $FlowIgnore var ssfdata = require('./misc/ssf.json'); var cb = function(d, j) { return function() { return X.SSF.format(d[0], d[j][0]); }; }; diff --git a/xlsx.flow.js b/xlsx.flow.js index ff4442a..38127af 100644 --- a/xlsx.flow.js +++ b/xlsx.flow.js @@ -59,9 +59,9 @@ function utf16beread(data/*:string*/)/*:string*/ { var debom = function(data/*:string*/)/*:string*/ { var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1); - if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.substr(2)); - if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.substr(2)); - if(c1 == 0xFEFF) return data.substr(1); + if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2)); + if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2)); + if(c1 == 0xFEFF) return data.slice(1); return data; }; @@ -69,7 +69,7 @@ var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCo if(typeof cptable !== 'undefined') { set_cp = function(cp/*:number*/) { current_codepage = cp; }; debom = function(data/*:string*/) { - if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); } + if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); } return data; }; _getchar = function _gc2(x/*:number*/)/*:string*/ { @@ -146,6 +146,15 @@ function arr2str(data/*:any*/)/*:string*/ { var o/*:Array*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); } +function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array*/ { + if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported"); + if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data)); + /*:: if(data instanceof ArrayBuffer) throw new Error("unreachable"); */ + var o = new Array(data.length); + for(var i = 0; i < data.length; ++i) o[i] = data[i]; + return o; +} + var bconcat = function(bufs) { return [].concat.apply([], bufs); }; var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g; @@ -1892,9 +1901,9 @@ function parse_isodur(s) { if(!m[i]) continue; mt = 1; if(i > 3) time = true; - switch(m[i].substr(m[i].length-1)) { + switch(m[i].slice(m[i].length-1)) { case 'Y': - throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1)); + throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1)); case 'D': mt *= 24; /* falls through */ case 'H': mt *= 60; @@ -1943,6 +1952,7 @@ function cc2str(arr/*:Array*/)/*:string*/ { function dup(o/*:any*/)/*:any*/ { if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o)); if(typeof o != 'object' || o == null) return o; + if(o instanceof Date) return new Date(o.getTime()); var out = {}; for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); return out; @@ -2063,24 +2073,24 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ { var z = ({}/*:any*/); var eq = 0, c = 0; for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; - if(!skip_root) z[0] = tag.substr(0, eq); + if(!skip_root) z[0] = tag.slice(0, eq); if(eq === tag.length) return z; var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1; if(m) for(i = 0; i != m.length; ++i) { cc = m[i]; for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; - q = cc.substr(0,c).trim(); + q = cc.slice(0,c).trim(); while(cc.charCodeAt(c+1) == 32) ++c; quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0; - v = cc.substring(c+1+quot, cc.length-quot); + v = cc.slice(c+1+quot, cc.length-quot); for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; if(j===q.length) { - if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods + if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods z[q] = v; } else { - var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1); - if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods + var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1); + if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods z[k] = v; } } @@ -3061,9 +3071,9 @@ function write_BrtColor(color, o) { o.write_shift(1, 0); } else { var rgb = (color.rgb || 'FFFFFF'); - o.write_shift(1, parseInt(rgb.substr(0,2),16)); - o.write_shift(1, parseInt(rgb.substr(2,2),16)); - o.write_shift(1, parseInt(rgb.substr(4,2),16)); + o.write_shift(1, parseInt(rgb.slice(0,2),16)); + o.write_shift(1, parseInt(rgb.slice(2,4),16)); + o.write_shift(1, parseInt(rgb.slice(4,6),16)); o.write_shift(1, 0xFF); } return o; @@ -3697,7 +3707,7 @@ var RELS = ({ /* 9.3.3 Representing Relationships */ function get_rels_path(file/*:string*/)/*:string*/ { var n = file.lastIndexOf("/"); - return file.substr(0,n+1) + '_rels/' + file.substr(n+1) + ".rels"; + return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels"; } function parse_rels(data/*:?string*/, currentFilePath/*:string*/) { @@ -3844,7 +3854,7 @@ var CORE_PROPS_REGEX/*:Array*/ = (function() { var r = new Array(CORE_PROPS.length); for(var i = 0; i < CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; - var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1); + var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1); r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">"); } return r; @@ -4024,7 +4034,7 @@ function parse_cust_props(data/*:string*/, opts) { case '': name = null; break; default: if (x.indexOf(''); - var type = toks[0].substring(4), text = toks[1]; + var type = toks[0].slice(4), text = toks[1]; /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */ switch(type) { case 'lpstr': case 'bstr': case 'lpwstr': @@ -4049,7 +4059,7 @@ function parse_cust_props(data/*:string*/, opts) { if(type.slice(-1) == '/') break; if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); } - } else if(x.substr(0,2) === "= 2 && opts.biff <= 5) encoding = 'cpstr'; var o = cch ? blob.read_shift(cch, encoding) : ""; current_codepage = cp; return o; @@ -4511,7 +4522,7 @@ function parse_XLUnicodeRichExtendedString(blob) { function parse_XLUnicodeStringNoCch(blob, cch, opts) { var retval; if(opts) { - if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont'); + if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr'); if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont'); } var fHighByte = blob.read_shift(1); @@ -4531,7 +4542,7 @@ function parse_XLUnicodeString2(blob, length, opts) { if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts); var cch = blob.read_shift(1); if(cch === 0) { blob.l++; return ""; } - return blob.read_shift(cch, opts.biff == 4 ? 'cpstr' : 'sbcs-cont'); + return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont'); } /* TODO: BIFF5 and lower, codepage awareness */ function write_XLUnicodeString(str, opts, o) { @@ -5828,7 +5839,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ { out[R][C] = out[R][C].trim(); break; case 'D': - if(s.length === 8) out[R][C] = new Date(+s.substr(0,4), +s.substr(4,2)-1, +s.substr(6,2)); + if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8)); else out[R][C] = s; break; case 'F': out[R][C] = parseFloat(s.trim()); break; @@ -6004,18 +6015,18 @@ var SYLK = (function() { case 'O': break; /* options? */ case 'P': if(record[1].charAt(0) == 'P') - formats.push(rstr.substr(3).replace(/;;/g, ";")); + formats.push(rstr.slice(3).replace(/;;/g, ";")); break; case 'C': for(rj=1; rj 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); } else if(Mval === 0) rowinfo[R].hidden = true; @@ -6185,7 +6196,7 @@ var DIF = (function() { else arr[R][C] = value; ++C; break; case 1: - data = data.substr(1,data.length-2); + data = data.slice(1,data.length-1); arr[R][C++] = data !== '' ? data : null; break; } @@ -6440,8 +6451,8 @@ var PRN = (function() { var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/); - if(str.substr(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.substr(6); } - else sep = guess_sep(str.substr(0,1024)); + if(str.slice(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.slice(6); } + else sep = guess_sep(str.slice(0,1024)); var R = 0, C = 0, v = 0; var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0; str = str.replace(/\r\n/mg, "\n"); @@ -6455,7 +6466,7 @@ var PRN = (function() { else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; } else if(s.charCodeAt(0) == 0x3D) { if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } - else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } + else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); } else { cell.t = 's'; cell.v = s; } } else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } @@ -6525,7 +6536,7 @@ var PRN = (function() { var coord = encode_cell({r:R,c:C}); cell = dense ? (ws[R]||[])[C] : ws[coord]; if(!cell || cell.v == null) { oo.push(" "); continue; } - var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10); + var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10); while(w.length < 10) w += " "; oo.push(w + (C === 0 ? " " : "")); } @@ -6602,7 +6613,7 @@ var WK_ = (function() { break; case 0x06: refguess = val; break; /* RANGE */ case 0x0F: /* LABEL */ - if(!o.qpro) val[1].v = val[1].v.substr(1); + if(!o.qpro) val[1].v = val[1].v.slice(1); /* falls through */ case 0x0D: /* INTEGER */ case 0x0E: /* NUMBER */ @@ -6620,7 +6631,7 @@ var WK_ = (function() { break; } else switch(RT) { case 0x16: /* LABEL16 */ - val[1].v = val[1].v.substr(1); + val[1].v = val[1].v.slice(1); /* falls through */ case 0x17: /* NUMBER17 */ case 0x18: /* NUMBER18 */ @@ -6969,7 +6980,7 @@ var parse_rs = (function parse_rs_factory() { /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */ case '255?255:rgb[i]<0?0:rgb[i]); - return o.toString(16).toUpperCase().substr(1); + return o.toString(16).toUpperCase().slice(1); } function rgb2HSL(rgb) { @@ -8462,7 +8473,7 @@ function parse_clrScheme(t, themes, opts) { themes.themeElements.clrScheme.push(color); color = {}; } else { - color.name = y[0].substring(3, y[0].length - 1); + color.name = y[0].slice(3, y[0].length - 1); } break; @@ -9924,8 +9935,8 @@ var PtgBinOp = { PtgPower: "^", PtgSub: "-" }; -function formula_quote_sheet_name(sname/*:string*/)/*:string*/ { - if(!sname) throw new Error("empty sheet name"); +function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { + if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); if(sname.indexOf(" ") > -1) return "'" + sname + "'"; return sname; } @@ -9964,7 +9975,7 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { } } function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ { - return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts)); + return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts); } function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, opts)/*:string*/ { var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; @@ -11614,11 +11625,11 @@ var XLSXFutureFunctions = { /* Part 3 TODO: actually parse formulae */ function ods_to_csf_formula(f/*:string*/)/*:string*/ { - if(f.substr(0,3) == "of:") f = f.substr(3); + if(f.slice(0,3) == "of:") f = f.slice(3); /* 5.2 Basic Expressions */ if(f.charCodeAt(0) == 61) { - f = f.substr(1); - if(f.charCodeAt(0) == 61) f = f.substr(1); + f = f.slice(1); + if(f.charCodeAt(0) == 61) f = f.slice(1); } f = f.replace(/COM\.MICROSOFT\./g, ""); /* Part 3 Section 5.8 References */ @@ -11769,8 +11780,8 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro var data1 = "", data2 = ""; var mtch/*:?any*/ = data.match(sheetdataregex); if(mtch) { - data1 = data.substr(0, mtch.index); - data2 = data.substr(mtch.index + mtch[0].length); + data1 = data.slice(0, mtch.index); + data2 = data.slice(mtch.index + mtch[0].length); } else data1 = data2 = data; /* 18.3.1.82 sheetPr CT_SheetPr */ @@ -11781,7 +11792,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro // $FlowIgnore var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index; if(ridx > 0) { - var ref = data1.substr(ridx,50).match(dimregex); + var ref = data1.slice(ridx,ridx+50).match(dimregex); if(ref) parse_ws_xml_dim(s, ref[1]); } @@ -11808,7 +11819,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro var merges/*:Array*/ = []; var _merge = data2.match(mergecregex); if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx) - merges[ridx] = safe_decode_range(_merge[ridx].substr(_merge[ridx].indexOf("\"")+1)); + merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1)); /* 18.3.1.48 hyperlinks CT_Hyperlinks */ var hlink = data2.match(hlinkregex); @@ -11998,7 +12009,7 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb)/*:string*/ { } if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } if(cell.f) { - var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; + var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); } if(cell.l) ws['!links'].push([ref, cell.l]); @@ -12029,7 +12040,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th /* 18.3.1.73 row CT_Row */ for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; - tag = parsexmltag(x.substr(0,ri), true); + tag = parsexmltag(x.slice(0,ri), true); tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; if(opts.sheetRows && opts.sheetRows < tagr) continue; if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; @@ -12044,12 +12055,12 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th } /* 18.3.1.4 c CT_Cell */ - cells = x.substr(ri).split(cellregex); + cells = x.slice(ri).split(cellregex); for(ri = 0; ri != cells.length; ++ri) { x = cells[ri].trim(); if(x.length === 0) continue; cref = x.match(rregex); idx = ri; i=0; cc=0; - x = "":"") + x; + x = "":"") + x; if(cref != null && cref.length === 2) { idx = 0; d=cref[1]; for(i=0; i != d.length; ++i) { @@ -12060,9 +12071,9 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th tagc = idx; } else ++tagc; for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i; - tag = parsexmltag(x.substr(0,i), true); + tag = parsexmltag(x.slice(0,i), true); if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc}); - d = x.substr(i); + d = x.slice(i); p = ({t:""}/*:any*/); if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]); @@ -12274,7 +12285,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ { rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK); rel["r:id"] = "rId"+rId; } - if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.substr(relc+1)); + if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1)); if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip); o[o.length] = writextag("hyperlink",null,rel); }); @@ -12591,7 +12602,7 @@ function write_BrtHLink(l, rId) { write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o); write_RelID("rId" + rId, o); var locidx = l[1].Target.indexOf("#"); - var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1); + var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1); write_XLWideString(loc || "", o); write_XLWideString(l[1].Tooltip || "", o); write_XLWideString("", o); @@ -13634,7 +13645,7 @@ function write_wb_xml(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:string*/ { o[o.length] = ""; var sheets = wb.Workbook && wb.Workbook.Sheets || []; for(var i = 0; i != wb.SheetNames.length; ++i) { - var sht = ({name:escapexml(wb.SheetNames[i].substr(0,31))}/*:any*/); + var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/); sht.sheetId = ""+(i+1); sht["r:id"] = "rId"+(i+1); if(sheets[i]) switch(sheets[i].Hidden) { @@ -13688,7 +13699,7 @@ function write_BrtBundleSh(data, o) { o.write_shift(4, data.Hidden); o.write_shift(4, data.iTabID); write_RelID(data.strRelID, o); - write_XLWideString(data.name.substr(0,31), o); + write_XLWideString(data.name.slice(0,31), o); return o.length > o.l ? o.slice(0, o.l) : o; } @@ -14058,11 +14069,11 @@ function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) { if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); /*:: if(!y || !y[2]) continue; */ - if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -14075,11 +14086,11 @@ function xlml_parsexmltagobj(tag/*:string*/) { if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); /*:: if(!y || !y[2]) continue; */ - if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -14179,7 +14190,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a if(cell.Formula) { var fstr = unescapexml(cell.Formula); /* strictly speaking, the leading = is required but some writers omit */ - if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.substr(1); + if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1); cell.f = rc_to_a1(fstr, base); delete cell.Formula; if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base); @@ -14383,7 +14394,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { var _NamedRange = parsexmltag(Rn[0]); var _DefinedName/*:DefinedName*/ = ({ Name: _NamedRange.Name, - Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) + Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) }/*:any*/); if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; /*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName); @@ -15066,8 +15077,8 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, var attr = {}; if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); - if(cell.F && cell.F.substr(0, ref.length) == ref) { - var end = decode_cell(cell.F.substr(ref.length + 1)); + if(cell.F && cell.F.slice(0, ref.length) == ref) { + var end = decode_cell(cell.F.slice(ref.length + 1)); attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); } @@ -17635,13 +17646,13 @@ var HTML_ = (function() { var merges/*:Array*/ = [], midx = 0; for(i = 0; i < rows.length; ++i) { var row = rows[i].trim(); - var hd = row.substr(0,3).toLowerCase(); + var hd = row.slice(0,3).toLowerCase(); if(hd == "/i); for(j = 0; j < cells.length; ++j) { var cell = cells[j].trim(); - if(cell.substr(0,3).toLowerCase() != "")) > -1) m = m.slice(cc+1); @@ -18393,7 +18404,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() { if(cell && cell.f) { ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); if(cell.F) { - if(cell.F.substr(0, ref.length) == ref) { + if(cell.F.slice(0, ref.length) == ref) { var _Fref = decode_range(cell.F); ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1); ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1); @@ -18973,7 +18984,7 @@ function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array*/ { var x = ""; switch((o||{}).type || "base64") { case 'buffer': return [f[0], f[1], f[2], f[3]]; - case 'base64': x = Base64.decode(f.substr(0,24)); break; + case 'base64': x = Base64.decode(f.slice(0,24)); break; case 'binary': x = f; break; case 'array': return [f[0], f[1], f[2], f[3]]; default: throw new Error("Unrecognized type " + (o && o.type || "undefined")); @@ -19050,6 +19061,12 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); } + if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array) { + // $FlowIgnore + var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar"; + // $FlowIgnore + if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);} + } switch((n = firstbyte(d, o))[0]) { case 0xD0: return read_cfb(CFB.read(d, o), o); case 0x09: return parse_xlscfb(d, o); diff --git a/xlsx.js b/xlsx.js index dc7041b..e5d5255 100644 --- a/xlsx.js +++ b/xlsx.js @@ -58,9 +58,9 @@ function utf16beread(data) { var debom = function(data) { var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1); - if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.substr(2)); - if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.substr(2)); - if(c1 == 0xFEFF) return data.substr(1); + if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2)); + if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2)); + if(c1 == 0xFEFF) return data.slice(1); return data; }; @@ -68,7 +68,7 @@ var _getchar = function _gc1(x) { return String.fromCharCode(x); }; if(typeof cptable !== 'undefined') { set_cp = function(cp) { current_codepage = cp; }; debom = function(data) { - if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); } + if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); } return data; }; _getchar = function _gc2(x) { @@ -145,6 +145,14 @@ function arr2str(data) { var o = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); } +function ab2a(data) { + if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported"); + if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data)); +var o = new Array(data.length); + for(var i = 0; i < data.length; ++i) o[i] = data[i]; + return o; +} + var bconcat = function(bufs) { return [].concat.apply([], bufs); }; var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g; @@ -1822,9 +1830,9 @@ function parse_isodur(s) { if(!m[i]) continue; mt = 1; if(i > 3) time = true; - switch(m[i].substr(m[i].length-1)) { + switch(m[i].slice(m[i].length-1)) { case 'Y': - throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1)); + throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1)); case 'D': mt *= 24; /* falls through */ case 'H': mt *= 60; @@ -1872,6 +1880,7 @@ function cc2str(arr) { function dup(o) { if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o)); if(typeof o != 'object' || o == null) return o; + if(o instanceof Date) return new Date(o.getTime()); var out = {}; for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); return out; @@ -1991,24 +2000,24 @@ function parsexmltag(tag, skip_root) { var z = ({}); var eq = 0, c = 0; for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; - if(!skip_root) z[0] = tag.substr(0, eq); + if(!skip_root) z[0] = tag.slice(0, eq); if(eq === tag.length) return z; var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1; if(m) for(i = 0; i != m.length; ++i) { cc = m[i]; for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; - q = cc.substr(0,c).trim(); + q = cc.slice(0,c).trim(); while(cc.charCodeAt(c+1) == 32) ++c; quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0; - v = cc.substring(c+1+quot, cc.length-quot); + v = cc.slice(c+1+quot, cc.length-quot); for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; if(j===q.length) { - if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods + if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods z[q] = v; } else { - var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1); - if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods + var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1); + if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods z[k] = v; } } @@ -2978,9 +2987,9 @@ function write_BrtColor(color, o) { o.write_shift(1, 0); } else { var rgb = (color.rgb || 'FFFFFF'); - o.write_shift(1, parseInt(rgb.substr(0,2),16)); - o.write_shift(1, parseInt(rgb.substr(2,2),16)); - o.write_shift(1, parseInt(rgb.substr(4,2),16)); + o.write_shift(1, parseInt(rgb.slice(0,2),16)); + o.write_shift(1, parseInt(rgb.slice(2,4),16)); + o.write_shift(1, parseInt(rgb.slice(4,6),16)); o.write_shift(1, 0xFF); } return o; @@ -3614,7 +3623,7 @@ var RELS = ({ /* 9.3.3 Representing Relationships */ function get_rels_path(file) { var n = file.lastIndexOf("/"); - return file.substr(0,n+1) + '_rels/' + file.substr(n+1) + ".rels"; + return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels"; } function parse_rels(data, currentFilePath) { @@ -3761,7 +3770,7 @@ var CORE_PROPS_REGEX = (function() { var r = new Array(CORE_PROPS.length); for(var i = 0; i < CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; - var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1); + var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1); r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">"); } return r; @@ -3941,7 +3950,7 @@ function parse_cust_props(data, opts) { case '': name = null; break; default: if (x.indexOf(''); - var type = toks[0].substring(4), text = toks[1]; + var type = toks[0].slice(4), text = toks[1]; /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */ switch(type) { case 'lpstr': case 'bstr': case 'lpwstr': @@ -3966,7 +3975,7 @@ function parse_cust_props(data, opts) { if(type.slice(-1) == '/') break; if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); } - } else if(x.substr(0,2) === "= 2 && opts.biff <= 5) encoding = 'cpstr'; var o = cch ? blob.read_shift(cch, encoding) : ""; current_codepage = cp; return o; @@ -4426,7 +4436,7 @@ function parse_XLUnicodeRichExtendedString(blob) { function parse_XLUnicodeStringNoCch(blob, cch, opts) { var retval; if(opts) { - if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont'); + if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr'); if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont'); } var fHighByte = blob.read_shift(1); @@ -4446,7 +4456,7 @@ function parse_XLUnicodeString2(blob, length, opts) { if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts); var cch = blob.read_shift(1); if(cch === 0) { blob.l++; return ""; } - return blob.read_shift(cch, opts.biff == 4 ? 'cpstr' : 'sbcs-cont'); + return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont'); } /* TODO: BIFF5 and lower, codepage awareness */ function write_XLUnicodeString(str, opts, o) { @@ -5742,7 +5752,7 @@ var fields = [], field = ({}); out[R][C] = out[R][C].trim(); break; case 'D': - if(s.length === 8) out[R][C] = new Date(+s.substr(0,4), +s.substr(4,2)-1, +s.substr(6,2)); + if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8)); else out[R][C] = s; break; case 'F': out[R][C] = parseFloat(s.trim()); break; @@ -5918,18 +5928,18 @@ var SYLK = (function() { case 'O': break; /* options? */ case 'P': if(record[1].charAt(0) == 'P') - formats.push(rstr.substr(3).replace(/;;/g, ";")); + formats.push(rstr.slice(3).replace(/;;/g, ";")); break; case 'C': for(rj=1; rj 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); } else if(Mval === 0) rowinfo[R].hidden = true; @@ -6099,7 +6109,7 @@ var DIF = (function() { else arr[R][C] = value; ++C; break; case 1: - data = data.substr(1,data.length-2); + data = data.slice(1,data.length-1); arr[R][C++] = data !== '' ? data : null; break; } @@ -6354,8 +6364,8 @@ var PRN = (function() { var ws = o.dense ? ([]) : ({}); var range = ({s: {c:0, r:0}, e: {c:0, r:0}}); - if(str.substr(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.substr(6); } - else sep = guess_sep(str.substr(0,1024)); + if(str.slice(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.slice(6); } + else sep = guess_sep(str.slice(0,1024)); var R = 0, C = 0, v = 0; var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0; str = str.replace(/\r\n/mg, "\n"); @@ -6369,7 +6379,7 @@ var PRN = (function() { else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; } else if(s.charCodeAt(0) == 0x3D) { if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } - else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } + else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); } else { cell.t = 's'; cell.v = s; } } else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } @@ -6439,7 +6449,7 @@ var PRN = (function() { var coord = encode_cell({r:R,c:C}); cell = dense ? (ws[R]||[])[C] : ws[coord]; if(!cell || cell.v == null) { oo.push(" "); continue; } - var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10); + var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10); while(w.length < 10) w += " "; oo.push(w + (C === 0 ? " " : "")); } @@ -6516,7 +6526,7 @@ var WK_ = (function() { break; case 0x06: refguess = val; break; /* RANGE */ case 0x0F: /* LABEL */ - if(!o.qpro) val[1].v = val[1].v.substr(1); + if(!o.qpro) val[1].v = val[1].v.slice(1); /* falls through */ case 0x0D: /* INTEGER */ case 0x0E: /* NUMBER */ @@ -6534,7 +6544,7 @@ var WK_ = (function() { break; } else switch(RT) { case 0x16: /* LABEL16 */ - val[1].v = val[1].v.substr(1); + val[1].v = val[1].v.slice(1); /* falls through */ case 0x17: /* NUMBER17 */ case 0x18: /* NUMBER18 */ @@ -6883,7 +6893,7 @@ var parse_rs = (function parse_rs_factory() { /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */ case '255?255:rgb[i]<0?0:rgb[i]); - return o.toString(16).toUpperCase().substr(1); + return o.toString(16).toUpperCase().slice(1); } function rgb2HSL(rgb) { @@ -8373,7 +8383,7 @@ function parse_clrScheme(t, themes, opts) { themes.themeElements.clrScheme.push(color); color = {}; } else { - color.name = y[0].substring(3, y[0].length - 1); + color.name = y[0].slice(3, y[0].length - 1); } break; @@ -9834,8 +9844,8 @@ var PtgBinOp = { PtgPower: "^", PtgSub: "-" }; -function formula_quote_sheet_name(sname) { - if(!sname) throw new Error("empty sheet name"); +function formula_quote_sheet_name(sname, opts) { + if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); if(sname.indexOf(" ") > -1) return "'" + sname + "'"; return sname; } @@ -9874,7 +9884,7 @@ function get_ixti_raw(supbooks, ixti, opts) { } } function get_ixti(supbooks, ixti, opts) { - return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts)); + return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts); } function stringify_formula(formula/*Array*/, range, cell, supbooks, opts) { var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; @@ -11524,11 +11534,11 @@ var XLSXFutureFunctions = { /* Part 3 TODO: actually parse formulae */ function ods_to_csf_formula(f) { - if(f.substr(0,3) == "of:") f = f.substr(3); + if(f.slice(0,3) == "of:") f = f.slice(3); /* 5.2 Basic Expressions */ if(f.charCodeAt(0) == 61) { - f = f.substr(1); - if(f.charCodeAt(0) == 61) f = f.substr(1); + f = f.slice(1); + if(f.charCodeAt(0) == 61) f = f.slice(1); } f = f.replace(/COM\.MICROSOFT\./g, ""); /* Part 3 Section 5.8 References */ @@ -11679,8 +11689,8 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) { var data1 = "", data2 = ""; var mtch = data.match(sheetdataregex); if(mtch) { - data1 = data.substr(0, mtch.index); - data2 = data.substr(mtch.index + mtch[0].length); + data1 = data.slice(0, mtch.index); + data2 = data.slice(mtch.index + mtch[0].length); } else data1 = data2 = data; /* 18.3.1.82 sheetPr CT_SheetPr */ @@ -11691,7 +11701,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) { // $FlowIgnore var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index; if(ridx > 0) { - var ref = data1.substr(ridx,50).match(dimregex); + var ref = data1.slice(ridx,ridx+50).match(dimregex); if(ref) parse_ws_xml_dim(s, ref[1]); } @@ -11718,7 +11728,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) { var merges = []; var _merge = data2.match(mergecregex); if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx) - merges[ridx] = safe_decode_range(_merge[ridx].substr(_merge[ridx].indexOf("\"")+1)); + merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1)); /* 18.3.1.48 hyperlinks CT_Hyperlinks */ var hlink = data2.match(hlinkregex); @@ -11908,7 +11918,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) { } if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } if(cell.f) { - var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; + var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); } if(cell.l) ws['!links'].push([ref, cell.l]); @@ -11939,7 +11949,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { /* 18.3.1.73 row CT_Row */ for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; - tag = parsexmltag(x.substr(0,ri), true); + tag = parsexmltag(x.slice(0,ri), true); tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; if(opts.sheetRows && opts.sheetRows < tagr) continue; if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; @@ -11954,12 +11964,12 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { } /* 18.3.1.4 c CT_Cell */ - cells = x.substr(ri).split(cellregex); + cells = x.slice(ri).split(cellregex); for(ri = 0; ri != cells.length; ++ri) { x = cells[ri].trim(); if(x.length === 0) continue; cref = x.match(rregex); idx = ri; i=0; cc=0; - x = "":"") + x; + x = "":"") + x; if(cref != null && cref.length === 2) { idx = 0; d=cref[1]; for(i=0; i != d.length; ++i) { @@ -11970,9 +11980,9 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { tagc = idx; } else ++tagc; for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i; - tag = parsexmltag(x.substr(0,i), true); + tag = parsexmltag(x.slice(0,i), true); if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc}); - d = x.substr(i); + d = x.slice(i); p = ({t:""}); if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]); @@ -12184,7 +12194,7 @@ function write_ws_xml(idx, opts, wb, rels) { rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK); rel["r:id"] = "rId"+rId; } - if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.substr(relc+1)); + if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1)); if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip); o[o.length] = writextag("hyperlink",null,rel); }); @@ -12501,7 +12511,7 @@ function write_BrtHLink(l, rId) { write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o); write_RelID("rId" + rId, o); var locidx = l[1].Target.indexOf("#"); - var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1); + var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1); write_XLWideString(loc || "", o); write_XLWideString(l[1].Tooltip || "", o); write_XLWideString("", o); @@ -13541,7 +13551,7 @@ if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.Cod o[o.length] = ""; var sheets = wb.Workbook && wb.Workbook.Sheets || []; for(var i = 0; i != wb.SheetNames.length; ++i) { - var sht = ({name:escapexml(wb.SheetNames[i].substr(0,31))}); + var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}); sht.sheetId = ""+(i+1); sht["r:id"] = "rId"+(i+1); if(sheets[i]) switch(sheets[i].Hidden) { @@ -13595,7 +13605,7 @@ function write_BrtBundleSh(data, o) { o.write_shift(4, data.Hidden); o.write_shift(4, data.iTabID); write_RelID(data.strRelID, o); - write_XLWideString(data.name.substr(0,31), o); + write_XLWideString(data.name.slice(0,31), o); return o.length > o.l ? o.slice(0, o.l) : o; } @@ -13964,11 +13974,11 @@ function xlml_parsexmltag(tag, skip_root) { var m = tag.match(attregexg2), y, j, w, i; if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); -if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); +if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -13980,11 +13990,11 @@ function xlml_parsexmltagobj(tag) { var m = tag.match(attregexg2), y, j, w, i; if(m) for(i = 0; i != m.length; ++i) { y = m[i].match(attregex2); -if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2); +if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); else { - if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6); - else w = y[1].substr(j+1); - z[w] = y[2].substr(1,y[2].length-2); + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); } } return z; @@ -14084,7 +14094,7 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o if(cell.Formula) { var fstr = unescapexml(cell.Formula); /* strictly speaking, the leading = is required but some writers omit */ - if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.substr(1); + if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1); cell.f = rc_to_a1(fstr, base); delete cell.Formula; if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base); @@ -14287,7 +14297,7 @@ for(var cma = c; cma <= cc; ++cma) { var _NamedRange = parsexmltag(Rn[0]); var _DefinedName = ({ Name: _NamedRange.Name, - Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0}) + Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) }); if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; Workbook.Names.push(_DefinedName); @@ -14966,8 +14976,8 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ var attr = {}; if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); - if(cell.F && cell.F.substr(0, ref.length) == ref) { - var end = decode_cell(cell.F.substr(ref.length + 1)); + if(cell.F && cell.F.slice(0, ref.length) == ref) { + var end = decode_cell(cell.F.slice(ref.length + 1)); attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); } @@ -17531,13 +17541,13 @@ var HTML_ = (function() { var merges = [], midx = 0; for(i = 0; i < rows.length; ++i) { var row = rows[i].trim(); - var hd = row.substr(0,3).toLowerCase(); + var hd = row.slice(0,3).toLowerCase(); if(hd == "/i); for(j = 0; j < cells.length; ++j) { var cell = cells[j].trim(); - if(cell.substr(0,3).toLowerCase() != "")) > -1) m = m.slice(cc+1); @@ -18289,7 +18299,7 @@ var write_content_ods = (function() { if(cell && cell.f) { ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); if(cell.F) { - if(cell.F.substr(0, ref.length) == ref) { + if(cell.F.slice(0, ref.length) == ref) { var _Fref = decode_range(cell.F); ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1); ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1); @@ -18864,7 +18874,7 @@ function firstbyte(f,o) { var x = ""; switch((o||{}).type || "base64") { case 'buffer': return [f[0], f[1], f[2], f[3]]; - case 'base64': x = Base64.decode(f.substr(0,24)); break; + case 'base64': x = Base64.decode(f.slice(0,24)); break; case 'binary': x = f; break; case 'array': return [f[0], f[1], f[2], f[3]]; default: throw new Error("Unrecognized type " + (o && o.type || "undefined")); @@ -18940,6 +18950,12 @@ function readSync(data, opts) { if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); } + if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array) { + // $FlowIgnore + var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar"; + // $FlowIgnore + if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);} + } switch((n = firstbyte(d, o))[0]) { case 0xD0: return read_cfb(CFB.read(d, o), o); case 0x09: return parse_xlscfb(d, o);