styled-exceljs 0.21.2 → 0.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/xlsx.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
2
2
  /* vim: set ts=2: */
3
3
  /*exported XLSX */
4
- /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false */
4
+ /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false, Int8Array:false */
5
5
  var XLSX = {};
6
6
  function make_xlsx_lib(XLSX){
7
- XLSX.version = '0.21.2';
7
+ XLSX.version = '0.21.4';
8
8
  var current_codepage = 1200, current_ansi = 1252;
9
9
  /*global cptable:true, window */
10
10
  var $cptable;
@@ -158,9 +158,9 @@ function Base64_decode(input) {
158
158
  var o = "";
159
159
  var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
160
160
  if (input.slice(0, 5) == "data:") {
161
- var i = input.slice(0, 1024).indexOf(";base64,");
162
- if (i > -1)
163
- input = input.slice(i + 8);
161
+ var sep = input.slice(0, 1024).indexOf(";base64,");
162
+ if (sep > -1)
163
+ input = input.slice(sep + 8);
164
164
  }
165
165
  input = input.replace(/[^\w\+\/\=]/g, "");
166
166
  for (var i = 0; i < input.length; ) {
@@ -3232,7 +3232,7 @@ function blobify(data) {
3232
3232
  }
3233
3233
  /* write or download file */
3234
3234
  function write_dl(fname, payload, enc) {
3235
- /*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
3235
+ /*global IE_SaveFile, navigator, saveAs, document, chrome */
3236
3236
  if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
3237
3237
  if(typeof Deno !== 'undefined') {
3238
3238
  /* in this spot, it's safe to assume typed arrays and TextEncoder/TextDecoder exist */
@@ -3872,7 +3872,7 @@ function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
3872
3872
  var htmlcharegex = /[\u0000-\u001f]/g;
3873
3873
  function escapehtml(text){
3874
3874
  var s = text + '';
3875
- return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
3875
+ return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\r\n|\r|\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
3876
3876
  }
3877
3877
 
3878
3878
  function escapexlml(text){
@@ -3880,6 +3880,19 @@ function escapexlml(text){
3880
3880
  return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
3881
3881
  }
3882
3882
 
3883
+ /* Extract text from XML fragments in linear time. This is a parser helper,
3884
+ * not an HTML sanitizer: text is escaped separately at HTML output boundaries. */
3885
+ function strip_xml_tags(text) {
3886
+ var str = String(text), out = [], inTag = false;
3887
+ for(var i = 0; i < str.length; ++i) {
3888
+ var cc = str.charCodeAt(i);
3889
+ if(!inTag && cc == 60 /* < */) inTag = true;
3890
+ else if(inTag && cc == 62 /* > */) inTag = false;
3891
+ else if(!inTag) out.push(str.charAt(i));
3892
+ }
3893
+ return out.join("");
3894
+ }
3895
+
3883
3896
  /* TODO: handle codepages */
3884
3897
  var xlml_fixstr = (function() {
3885
3898
  var entregex = /&#(\d+);/g;
@@ -3986,8 +3999,8 @@ var htmldecode = (function() {
3986
3999
  .replace(/[\t\n\r ]+/g, " ")
3987
4000
  // Replace <br> tags with new lines
3988
4001
  .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
3989
- // Strip HTML elements
3990
- .replace(/<[^<>]*>/g,"");
4002
+ ;
4003
+ o = strip_xml_tags(o);
3991
4004
  for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
3992
4005
  return o;
3993
4006
  };
@@ -4558,9 +4571,25 @@ function format_cell(cell, v, o) {
4558
4571
  return safe_format_cell(cell, v);
4559
4572
  }
4560
4573
 
4574
+ /* Worksheet names are document-controlled. A normal object treats
4575
+ * "__proto__" as a setter, so all workbook sheet maps must use an own-property
4576
+ * preserving dictionary and all lookups must reject inherited properties. */
4577
+ function sheet_map_new() {
4578
+ return Object.create ? Object.create(null) : {};
4579
+ }
4580
+ function sheet_map_set(sheets, name, sheet) {
4581
+ if(name == "__proto__" && Object.defineProperty) Object.defineProperty(sheets, name, {
4582
+ value: sheet, configurable: true, enumerable: true, writable: true
4583
+ });
4584
+ else sheets[name] = sheet;
4585
+ }
4586
+ function sheet_map_get(sheets, name) {
4587
+ return sheets != null && Object.prototype.hasOwnProperty.call(sheets, name) ? sheets[name] : void 0;
4588
+ }
4589
+
4561
4590
  function sheet_to_workbook(sheet, opts) {
4562
4591
  var n = opts && opts.sheet ? opts.sheet : "Sheet1";
4563
- var sheets = {}; sheets[n] = sheet;
4592
+ var sheets = sheet_map_new(); sheet_map_set(sheets, n, sheet);
4564
4593
  return { SheetNames: [n], Sheets: sheets };
4565
4594
  }
4566
4595
 
@@ -5646,6 +5675,7 @@ var RELS = ({
5646
5675
  MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
5647
5676
  IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
5648
5677
  DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
5678
+ TABLE: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
5649
5679
  XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
5650
5680
  TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
5651
5681
  PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
@@ -6233,8 +6263,8 @@ function parse_TypedPropertyValue(blob, type, _opts) {
6233
6263
  case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
6234
6264
  case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
6235
6265
  case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
6236
- case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
6237
- case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
6266
+ case 0x1E /*VT_LPSTR*/: blob.l += 4; return parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1");
6267
+ case 0x1F /*VT_LPWSTR*/: blob.l += 4; return parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1");
6238
6268
  case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
6239
6269
  case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
6240
6270
  case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
@@ -6743,7 +6773,6 @@ function parse_LongRGBA(blob) { var r = blob.read_shift(1), g = blob.read_shift(
6743
6773
  /* 2.5.177 LongRGB */
6744
6774
  function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
6745
6775
 
6746
-
6747
6776
  /* [MS-XLS] 2.5.19 */
6748
6777
  function parse_XLSCell(blob, length, opts) {
6749
6778
  var rw = blob.read_shift(2); // 0-indexed
@@ -8205,7 +8234,7 @@ function dbf_to_workbook(buf, opts) {
8205
8234
  o.bookType = "dbf";
8206
8235
  return o;
8207
8236
  } catch(e) { if(opts && opts.WTF) throw e; }
8208
- return ({SheetNames:[],Sheets:{}});
8237
+ return ({SheetNames:[],Sheets:sheet_map_new()});
8209
8238
  }
8210
8239
 
8211
8240
  var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
@@ -9101,7 +9130,7 @@ function read_wb_TABL(d, opts) {
9101
9130
  try {
9102
9131
  var out = DIF.to_workbook(d, o);
9103
9132
  if(!out || !out.Sheets) throw "DIF bad workbook";
9104
- var ws = out.Sheets[out.SheetNames[0]];
9133
+ var ws = sheet_map_get(out.Sheets, out.SheetNames[0]);
9105
9134
  if(!ws || !ws["!ref"]) throw "DIF empty worksheet";
9106
9135
  o.WTF = OLD_WTF;
9107
9136
  return out;
@@ -9157,7 +9186,7 @@ var WK_ = (function() {
9157
9186
  var o = opts || {};
9158
9187
  if(DENSE != null && o.dense == null) o.dense = DENSE;
9159
9188
  var s = ({}), n = "Sheet1", next_n = "", sidx = 0;
9160
- var sheets = {}, snames = [], realnames = [], sdata = [];
9189
+ var sheets = sheet_map_new(), snames = [], realnames = [], sdata = [];
9161
9190
  if(o.dense) sdata = s["!data"] = [];
9162
9191
 
9163
9192
  var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9202,7 +9231,7 @@ var WK_ = (function() {
9202
9231
  if(o.qpro) {
9203
9232
  if(val[3] > sidx) {
9204
9233
  s["!ref"] = encode_range(refguess);
9205
- sheets[n] = s;
9234
+ sheet_map_set(sheets, n, s);
9206
9235
  snames.push(n);
9207
9236
  s = ({}); if(o.dense) sdata = s["!data"] = [];
9208
9237
  refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9253,7 +9282,7 @@ var WK_ = (function() {
9253
9282
  case 0x28: /* FORMULA28 */
9254
9283
  if(val[3] > sidx) {
9255
9284
  s["!ref"] = encode_range(refguess);
9256
- sheets[n] = s;
9285
+ sheet_map_set(sheets, n, s);
9257
9286
  snames.push(n);
9258
9287
  s = ({}); if(o.dense) sdata = s["!data"] = [];
9259
9288
  refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9276,17 +9305,17 @@ var WK_ = (function() {
9276
9305
  }}, o);
9277
9306
  } else throw new Error("Unrecognized LOTUS BOF " + d[2]);
9278
9307
  s["!ref"] = encode_range(refguess);
9279
- sheets[next_n || n] = s;
9308
+ sheet_map_set(sheets, next_n || n, s);
9280
9309
  snames.push(next_n || n);
9281
9310
  if(!realnames.length) return { SheetNames: snames, Sheets: sheets };
9282
- var osheets = {}, rnames = [];
9311
+ var osheets = sheet_map_new(), rnames = [];
9283
9312
  /* TODO: verify no collisions */
9284
- for(var i = 0; i < realnames.length; ++i) if(sheets[snames[i]]) {
9313
+ for(var i = 0; i < realnames.length; ++i) if(sheet_map_get(sheets, snames[i])) {
9285
9314
  rnames.push(realnames[i] || snames[i]);
9286
- osheets[realnames[i]] = sheets[realnames[i]] || sheets[snames[i]];
9315
+ sheet_map_set(osheets, realnames[i] || snames[i], sheet_map_get(sheets, realnames[i]) || sheet_map_get(sheets, snames[i]));
9287
9316
  } else {
9288
9317
  rnames.push(realnames[i]);
9289
- osheets[realnames[i]] = ({ "!ref": "A1" });
9318
+ sheet_map_set(osheets, realnames[i], ({ "!ref": "A1" }));
9290
9319
  }
9291
9320
  return { SheetNames: rnames, Sheets: osheets };
9292
9321
  }
@@ -9340,11 +9369,11 @@ var WK_ = (function() {
9340
9369
 
9341
9370
  write_biff_rec(ba, 0x00, write_BOF_WK3(wb));
9342
9371
 
9343
- for(var i = 0, cnt = 0; i < wb.SheetNames.length; ++i) if((wb.Sheets[wb.SheetNames[i]] || {})["!ref"]) write_biff_rec(ba, 0x1b, write_XFORMAT_SHEETNAME(wb.SheetNames[i], cnt++));
9372
+ for(var i = 0, cnt = 0; i < wb.SheetNames.length; ++i) if((sheet_map_get(wb.Sheets, wb.SheetNames[i]) || {})["!ref"]) write_biff_rec(ba, 0x1b, write_XFORMAT_SHEETNAME(wb.SheetNames[i], cnt++));
9344
9373
 
9345
9374
  var wsidx = 0;
9346
9375
  for(i = 0; i < wb.SheetNames.length; ++i) {
9347
- var ws = wb.Sheets[wb.SheetNames[i]];
9376
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
9348
9377
  if(!ws || !ws["!ref"]) continue;
9349
9378
  var range = safe_decode_range(ws["!ref"]);
9350
9379
  var dense = ws["!data"] != null;
@@ -9389,7 +9418,7 @@ var WK_ = (function() {
9389
9418
  var rows = 0, cols = 0, wscnt = 0;
9390
9419
  for(var i = 0; i < wb.SheetNames.length; ++i) {
9391
9420
  var name = wb.SheetNames[i];
9392
- var ws = wb.Sheets[name];
9421
+ var ws = sheet_map_get(wb.Sheets, name);
9393
9422
  if(!ws || !ws["!ref"]) continue;
9394
9423
  ++wscnt;
9395
9424
  var range = decode_range(ws["!ref"]);
@@ -10117,7 +10146,7 @@ var WK_ = (function() {
10117
10146
  var SST = [], sname = "", formulae = [];
10118
10147
  var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
10119
10148
  var cnt = 0, type = 0, C = 0, R = 0;
10120
- var wb = { SheetNames: [], Sheets: {} };
10149
+ var wb = { SheetNames: [], Sheets: sheet_map_new() };
10121
10150
  var FMTS = [];
10122
10151
  outer: while(d.l < d.length) {
10123
10152
  var RT = d.read_shift(2), length = d.read_shift(2);
@@ -10421,13 +10450,13 @@ var parse_rs = (function() {
10421
10450
 
10422
10451
  /* Parse a list of <r> tags */
10423
10452
  var rs_to_html = (function parse_rs_factory() {
10424
- var nlregex = /(\r\n|\n)/g;
10425
10453
  function parse_rpr2(font, intro, outro) {
10426
10454
  var style = [];
10427
10455
 
10428
10456
  if(font.u) style.push("text-decoration: underline;");
10429
- if(font.uval) style.push("text-underline-style:" + font.uval + ";");
10430
- if(font.sz) style.push("font-size:" + font.sz + "pt;");
10457
+ if(font.uval && /^(?:single|double|single-accounting|double-accounting)$/.test(font.uval)) style.push("text-underline-style:" + font.uval + ";");
10458
+ var sz = +font.sz;
10459
+ if(isFinite(sz) && sz > 0) style.push("font-size:" + Math.min(sz, 409) + "pt;");
10431
10460
  if(font.outline) style.push("text-effect: outline;");
10432
10461
  if(font.shadow) style.push("text-shadow: auto;");
10433
10462
  intro.push('<span style="' + style.join("") + '">');
@@ -10452,7 +10481,7 @@ var rs_to_html = (function parse_rs_factory() {
10452
10481
 
10453
10482
  if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
10454
10483
 
10455
- return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
10484
+ return terms[0].join("") + escapehtml(terms[1]) + terms[2].join("");
10456
10485
  }
10457
10486
 
10458
10487
  return function parse_rs(rs) {
@@ -11110,6 +11139,9 @@ function resolve_style_obj_color(obj, themes) {
11110
11139
 
11111
11140
  /* 18.3.1.13 width calculations */
11112
11141
  /* [MS-OI29500] 2.1.595 Column Width & Formatting */
11142
+ /* The file format does not store MDW directly. Seven is the Office-compatible
11143
+ * fallback when Normal-font metrics are unavailable. A single stored column
11144
+ * width is ambiguous and must not change the scale for the rest of a sheet. */
11113
11145
  var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
11114
11146
  function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
11115
11147
  function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
@@ -11186,6 +11218,15 @@ function style_font_family(style) {
11186
11218
  var font = style && style.font || {};
11187
11219
  return font.name || "Calibri";
11188
11220
  }
11221
+ function css_string_escape(value, quote) {
11222
+ var str = String(value), out = [];
11223
+ for(var i = 0; i < str.length; ++i) {
11224
+ var cc = str.charCodeAt(i), ch = str.charAt(i);
11225
+ if(ch == quote || ch == "\\" || cc < 32 || cc == 127 || ch == "<" || ch == ">" || ch == "&") out.push("\\" + cc.toString(16) + " ");
11226
+ else out.push(ch);
11227
+ }
11228
+ return out.join("");
11229
+ }
11189
11230
  function css_font_from_style(style) {
11190
11231
  var font = style && style.font || {};
11191
11232
  var parts = [];
@@ -11193,7 +11234,8 @@ function css_font_from_style(style) {
11193
11234
  if(font.bold) parts.push("bold");
11194
11235
  parts.push(style_font_size_pt(style) + "pt");
11195
11236
  var name = style_font_family(style);
11196
- if(/[,\s'"]/.test(name)) name = '"' + String(name).replace(/"/g, '\\"') + '"';
11237
+ if(/[,\s'"]/.test(name)) name = '"' + css_string_escape(name, '"') + '"';
11238
+ else name = css_string_escape(name, '"');
11197
11239
  parts.push(name);
11198
11240
  return parts.join(" ");
11199
11241
  }
@@ -11933,6 +11975,47 @@ function parse_dxfs(t, styles, themes, opts) {
11933
11975
  });
11934
11976
  }
11935
11977
 
11978
+ function parse_tableStyles(t, styles, opts) {
11979
+ styles.TableStyles = {styles:[]};
11980
+ var tableStyle = null, pass = false;
11981
+ (t.match(tagregex)||[]).forEach(function(x) {
11982
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
11983
+ switch(tag) {
11984
+ case '<tableStyles': case '<tableStyles>':
11985
+ if(y.defaultTableStyle) styles.TableStyles.defaultTableStyle = utf8read(unescapexml(y.defaultTableStyle));
11986
+ if(y.defaultPivotStyle) styles.TableStyles.defaultPivotStyle = utf8read(unescapexml(y.defaultPivotStyle));
11987
+ break;
11988
+ case '<tableStyles/>': case '</tableStyles>': break;
11989
+ case '<tableStyle': case '<tableStyle>': case '<tableStyle/>':
11990
+ if(styles.TableStyles.styles.length >= TABLE_STYLE_MAX_TABLES) {
11991
+ tableStyle = null;
11992
+ break;
11993
+ }
11994
+ tableStyle = {
11995
+ name:utf8read(unescapexml(y.name || "")),
11996
+ pivot:y.pivot != null ? parsexmlbool(y.pivot) : false,
11997
+ table:y.table != null ? parsexmlbool(y.table) : true,
11998
+ elements:[]
11999
+ };
12000
+ styles.TableStyles.styles.push(tableStyle);
12001
+ if(tag.slice(-2) == "/>") tableStyle = null;
12002
+ break;
12003
+ case '</tableStyle>': tableStyle = null; break;
12004
+ case '<tableStyleElement': case '<tableStyleElement>': case '<tableStyleElement/>':
12005
+ if(tableStyle && tableStyle.elements.length < 64 && table_style_element_type(y.type) && y.dxfId != null) tableStyle.elements.push({
12006
+ type:y.type,
12007
+ dxfId:parseInt(y.dxfId, 10),
12008
+ size:y.size != null ? Math.max(1, parseInt(y.size, 10) || 1) : 1
12009
+ });
12010
+ break;
12011
+ case '<extLst': case '<extLst>': case '</extLst>': break;
12012
+ case '<ext': pass = true; break;
12013
+ case '</ext>': pass = false; break;
12014
+ default: if(opts && opts.WTF && !pass) throw new Error('unrecognized ' + y[0] + ' in tableStyles');
12015
+ }
12016
+ });
12017
+ }
12018
+
11936
12019
  function parse_colors(t, styles, themes, opts) {
11937
12020
  styles.Colors = {indexedColors:[], mruColors:[], themeColors:[]};
11938
12021
  var target = null, pass = false;
@@ -12011,6 +12094,7 @@ return function parse_sty_xml(data, themes, opts) {
12011
12094
  if((t=str_match_xml_ns(data, "dxfs"))) parse_dxfs(t[0], styles, themes, opts);
12012
12095
 
12013
12096
  /* 18.8.42 tableStyles CT_TableStyles ? */
12097
+ if((t=str_match_xml_ns(data, "tableStyles"))) parse_tableStyles(t[0], styles, opts);
12014
12098
  /* 18.8.11 colors CT_Colors ? */
12015
12099
  if((t=str_match_xml_ns(data, "colors"))) parse_colors(t[0], styles, themes, opts);
12016
12100
 
@@ -13174,7 +13258,7 @@ function parse_drawing_anchor(data) {
13174
13258
  function parse_drawing_text(data) {
13175
13259
  var out = [];
13176
13260
  (data.match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) {
13177
- out.push(unescapexml(t.replace(/<[^>]*>/g, "")));
13261
+ out.push(unescapexml(strip_xml_tags(t)));
13178
13262
  });
13179
13263
  return out.join("");
13180
13264
  }
@@ -16536,7 +16620,11 @@ function validate_merges(ws, opts) {
16536
16620
  errors.push({code:"E_MERGE_OVERLAP", message:"Merge ranges overlap", index:i, other:j, range:enc, otherRange:encode_range(merges[j])});
16537
16621
  }
16538
16622
  }
16539
- if(errors.length && opts && opts.WTF) throw new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16623
+ if(errors.length && opts && opts.WTF) {
16624
+ var err = new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16625
+ err.code = errors[0].code;
16626
+ throw err;
16627
+ }
16540
16628
  return errors;
16541
16629
  }
16542
16630
 
@@ -16546,6 +16634,312 @@ function check_ws(ws, sname, i) {
16546
16634
  if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
16547
16635
  }
16548
16636
  }
16637
+ var TABLE_STYLE_MAX_TABLES = 1024;
16638
+ var TABLE_STYLE_MAX_COLUMNS = 16384;
16639
+ var TABLE_STYLE_MAX_XML_LENGTH = 5 * 1024 * 1024;
16640
+ var TABLE_STYLE_ELEMENT_TYPES = {
16641
+ wholeTable:true, headerRow:true, totalRow:true,
16642
+ firstColumn:true, lastColumn:true,
16643
+ firstRowStripe:true, secondRowStripe:true,
16644
+ firstColumnStripe:true, secondColumnStripe:true,
16645
+ firstHeaderCell:true, lastHeaderCell:true,
16646
+ firstTotalCell:true, lastTotalCell:true
16647
+ };
16648
+
16649
+ function table_style_safe_key(key) {
16650
+ return key != "__proto__" && key != "constructor" && key != "prototype";
16651
+ }
16652
+
16653
+ function table_style_element_type(type) {
16654
+ return Object.prototype.hasOwnProperty.call(TABLE_STYLE_ELEMENT_TYPES, type);
16655
+ }
16656
+
16657
+ function table_style_attr(y, name) {
16658
+ if(y[name] != null) return y[name];
16659
+ return y[name.toLowerCase()];
16660
+ }
16661
+
16662
+ function table_style_bool(y, name, fallback) {
16663
+ var value = table_style_attr(y, name);
16664
+ return value == null ? fallback : parsexmlbool(value);
16665
+ }
16666
+
16667
+ function table_style_int(y, name) {
16668
+ var value = table_style_attr(y, name);
16669
+ if(value == null || value === "") return void 0;
16670
+ value = parseInt(value, 10);
16671
+ return isFinite(value) && value >= 0 ? value : void 0;
16672
+ }
16673
+
16674
+ function table_style_merge(target, source) {
16675
+ if(!source) return target;
16676
+ if(!target) target = {};
16677
+ keys(source).forEach(function(k) {
16678
+ if(!table_style_safe_key(k)) return;
16679
+ var value = source[k];
16680
+ if(value && typeof value == "object" && !Array.isArray(value)) {
16681
+ target[k] = table_style_merge(
16682
+ target[k] && typeof target[k] == "object" && !Array.isArray(target[k]) ? table_style_merge({}, target[k]) : {},
16683
+ value
16684
+ );
16685
+ } else target[k] = value;
16686
+ });
16687
+ return target;
16688
+ }
16689
+
16690
+ function table_style_color(themes, theme, tint) {
16691
+ return style_color_from_attrs({theme:String(theme), tint:String(tint || 0)}, themes);
16692
+ }
16693
+
16694
+ function table_style_fill(color) {
16695
+ return {fill:{patternType:"solid", fgColor:color}};
16696
+ }
16697
+
16698
+ function table_style_font(color, bold) {
16699
+ var font = {};
16700
+ if(color) font.color = color;
16701
+ if(bold) font.bold = 1;
16702
+ return {font:font};
16703
+ }
16704
+
16705
+ function table_style_border(side, color, style) {
16706
+ var border = {}, out = {border:border};
16707
+ border[side] = {style:style || "thin", color:color};
16708
+ return out;
16709
+ }
16710
+
16711
+ function table_style_accent(themes, index) {
16712
+ var position = (index - 1) % 7;
16713
+ /* The first style in each seven-style family is neutral. The remaining
16714
+ * six entries use the workbook's accent1..accent6 colors. */
16715
+ return table_style_color(themes, position ? 3 + position : 1, 0);
16716
+ }
16717
+
16718
+ function built_in_table_style_rules(name, themes) {
16719
+ var match = /^TableStyle(Light|Medium|Dark)(\d+)$/i.exec(name || "");
16720
+ if(!match) return null;
16721
+ var family = match[1].toLowerCase(), index = parseInt(match[2], 10);
16722
+ var maximum = family == "light" ? 21 : family == "medium" ? 28 : 11;
16723
+ if(index < 1 || index > maximum) return null;
16724
+ var accent = table_style_accent(themes, index);
16725
+ var white = table_style_color(themes, 0, 0);
16726
+ var dark = table_style_color(themes, 1, 0);
16727
+ var rules = {};
16728
+
16729
+ if(family == "light") {
16730
+ rules.headerRow = table_style_merge(
16731
+ table_style_font(accent, true),
16732
+ table_style_border("bottom", accent, "medium")
16733
+ );
16734
+ rules.totalRow = table_style_merge(
16735
+ table_style_font(accent, true),
16736
+ table_style_border("top", accent, "double")
16737
+ );
16738
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16739
+ rules.firstColumnStripe = rules.firstRowStripe;
16740
+ } else if(family == "medium") {
16741
+ var group = Math.floor((index - 1) / 7);
16742
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16743
+ rules.totalRow = table_style_merge(
16744
+ table_style_font(accent, true),
16745
+ table_style_border("top", accent, "double")
16746
+ );
16747
+ if(group == 1) {
16748
+ /* Medium 8..14 use two theme-derived body fills. This is the family
16749
+ * used by Excel's TableStyleMedium13. */
16750
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16751
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.6));
16752
+ rules.firstColumnStripe = rules.firstRowStripe;
16753
+ } else if(group == 2) {
16754
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16755
+ rules.firstColumnStripe = rules.firstRowStripe;
16756
+ rules.wholeTable = table_style_border("bottom", table_style_color(themes, accent.theme, 0.4), "thin");
16757
+ } else if(group == 3) {
16758
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16759
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.7));
16760
+ rules.firstColumnStripe = rules.firstRowStripe;
16761
+ } else {
16762
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16763
+ rules.firstColumnStripe = rules.firstRowStripe;
16764
+ }
16765
+ } else {
16766
+ rules.wholeTable = table_style_merge(table_style_fill(dark), table_style_font(white, false));
16767
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16768
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, -0.35));
16769
+ rules.firstColumnStripe = rules.firstRowStripe;
16770
+ rules.totalRow = table_style_merge(
16771
+ table_style_font(white, true),
16772
+ table_style_border("top", accent, "double")
16773
+ );
16774
+ }
16775
+
16776
+ rules.firstColumn = table_style_font(null, true);
16777
+ rules.lastColumn = table_style_font(null, true);
16778
+ return rules;
16779
+ }
16780
+
16781
+ function custom_table_style_rules(name, styles) {
16782
+ var tableStyles = styles && styles.TableStyles;
16783
+ if(!tableStyles || !tableStyles.styles) return null;
16784
+ for(var i = 0; i < tableStyles.styles.length; ++i) {
16785
+ var tableStyle = tableStyles.styles[i];
16786
+ if(tableStyle.name != name) continue;
16787
+ var rules = Object.create(null);
16788
+ (tableStyle.elements || []).forEach(function(element) {
16789
+ if(!table_style_element_type(element.type)) return;
16790
+ var dxf = styles.Dxfs && styles.Dxfs[element.dxfId];
16791
+ if(dxf) rules[element.type] = {style:dup(dxf), size:element.size || 1};
16792
+ });
16793
+ return rules;
16794
+ }
16795
+ return null;
16796
+ }
16797
+
16798
+ function parse_table_xml(data, path, themes, styles, opts) {
16799
+ if(!data || data.length > TABLE_STYLE_MAX_XML_LENGTH) return null;
16800
+ data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
16801
+ var table = {columns:[]}, column = null, pass = false;
16802
+ (data.match(tagregex)||[]).forEach(function(x) {
16803
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
16804
+ switch(tag) {
16805
+ case '<table': case '<table>':
16806
+ table.id = table_style_int(y, "id");
16807
+ table.name = utf8read(unescapexml(table_style_attr(y, "name") || ""));
16808
+ table.displayName = utf8read(unescapexml(table_style_attr(y, "displayName") || table.name));
16809
+ table.ref = table_style_attr(y, "ref") || "";
16810
+ table.headerRowCount = table_style_int(y, "headerRowCount");
16811
+ table.totalsRowCount = table_style_int(y, "totalsRowCount");
16812
+ table.totalsRowShown = table_style_bool(y, "totalsRowShown", false);
16813
+ table.headerRowDxfId = table_style_int(y, "headerRowDxfId");
16814
+ table.dataDxfId = table_style_int(y, "dataDxfId");
16815
+ table.totalsRowDxfId = table_style_int(y, "totalsRowDxfId");
16816
+ table.path = path;
16817
+ break;
16818
+ case '<tableColumn': case '<tableColumn>': case '<tableColumn/>':
16819
+ if(table.columns.length >= TABLE_STYLE_MAX_COLUMNS) {
16820
+ column = null;
16821
+ break;
16822
+ }
16823
+ column = {
16824
+ id:table_style_int(y, "id"),
16825
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16826
+ headerRowDxfId:table_style_int(y, "headerRowDxfId"),
16827
+ dataDxfId:table_style_int(y, "dataDxfId"),
16828
+ totalsRowDxfId:table_style_int(y, "totalsRowDxfId")
16829
+ };
16830
+ table.columns.push(column);
16831
+ if(tag.slice(-2) == "/>" ) column = null;
16832
+ break;
16833
+ case '</tableColumn>': column = null; break;
16834
+ case '<tableStyleInfo': case '<tableStyleInfo>': case '<tableStyleInfo/>':
16835
+ table.styleInfo = {
16836
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16837
+ showFirstColumn:table_style_bool(y, "showFirstColumn", false),
16838
+ showLastColumn:table_style_bool(y, "showLastColumn", false),
16839
+ showRowStripes:table_style_bool(y, "showRowStripes", false),
16840
+ showColumnStripes:table_style_bool(y, "showColumnStripes", false)
16841
+ };
16842
+ break;
16843
+ case '<extLst': case '<extLst>': case '</extLst>': break;
16844
+ case '<ext': pass = true; break;
16845
+ case '</ext>': pass = false; break;
16846
+ default: if(opts && opts.WTF && !pass) {
16847
+ /* Table formulas and filter metadata are intentionally preserved by
16848
+ * the raw XML parser but do not affect visual style resolution. */
16849
+ if(/^<\/?(?:tableColumns|autoFilter|sortState|calculatedColumnFormula|totalsRowFormula|xmlColumnPr)/.test(tag)) break;
16850
+ }
16851
+ }
16852
+ });
16853
+ if(!table.ref) return null;
16854
+ try {
16855
+ table.range = safe_decode_range(table.ref);
16856
+ if(table.range.s.r < 0 || table.range.s.c < 0 || table.range.e.r > 1048575 || table.range.e.c > 16383) return null;
16857
+ } catch(e) { return null; }
16858
+ var styleName = table.styleInfo && table.styleInfo.name;
16859
+ table.styleRules = custom_table_style_rules(styleName, styles) || built_in_table_style_rules(styleName, themes) || {};
16860
+ table.dxfs = styles && styles.Dxfs ? styles.Dxfs : [];
16861
+ return table;
16862
+ }
16863
+
16864
+ function parse_sheet_tables(sheet, zip, path, rels, opts, themes, styles) {
16865
+ if(!sheet || !rels || !rels['!id'] || !opts || !opts.cellStyles) return;
16866
+ var tables = [], seen = Object.create(null);
16867
+ keys(rels['!id']).forEach(function(id) {
16868
+ if(tables.length >= TABLE_STYLE_MAX_TABLES) return;
16869
+ var rel = rels['!id'][id];
16870
+ if(!rel || rel.TargetMode == "External" || typeof rel.Target != "string" || !rel.Target ||
16871
+ (rel.Type != RELS.TABLE && !/\/table$/.test(rel.Type || ""))) return;
16872
+ var tablePath = resolve_path(rel.Target, path);
16873
+ if(seen[tablePath]) return;
16874
+ seen[tablePath] = true;
16875
+ var table = parse_table_xml(getzipstr(zip, tablePath, true), tablePath, themes, styles, opts);
16876
+ if(table) tables.push(table);
16877
+ });
16878
+ if(tables.length) sheet['!tables'] = tables;
16879
+ }
16880
+
16881
+ function table_style_rule_value(rule) {
16882
+ return rule && rule.style ? rule.style : rule;
16883
+ }
16884
+
16885
+ function table_style_stripe_rule(first, second, offset) {
16886
+ var firstSize = first && first.size || 1, secondSize = second && second.size || 1;
16887
+ var period = firstSize + secondSize;
16888
+ if(!period) return null;
16889
+ return offset % period < firstSize ? first : second;
16890
+ }
16891
+
16892
+ function table_style_dxf(table, id) {
16893
+ return id == null || !table.dxfs ? null : table.dxfs[id];
16894
+ }
16895
+
16896
+ function resolve_table_cell_style(ws, row, col, baseStyle) {
16897
+ var tables = ws && ws['!tables'];
16898
+ var resolved = baseStyle ? table_style_merge({}, baseStyle) : {};
16899
+ if(!tables || !tables.length) return keys(resolved).length ? resolved : void 0;
16900
+ for(var i = 0; i < tables.length; ++i) {
16901
+ var table = tables[i], range = table.range;
16902
+ if(!range || row < range.s.r || row > range.e.r || col < range.s.c || col > range.e.c) continue;
16903
+ var rules = table.styleRules || {}, info = table.styleInfo || {};
16904
+ var rowOffset = row - range.s.r, colOffset = col - range.s.c;
16905
+ var headerRows = table.headerRowCount == null ? 1 : table.headerRowCount;
16906
+ var totalRows = table.totalsRowCount != null ? table.totalsRowCount : table.totalsRowShown ? 1 : 0;
16907
+ var dataStart = headerRows, dataEnd = range.e.r - range.s.r - totalRows;
16908
+ var isHeader = rowOffset < headerRows;
16909
+ var isTotal = totalRows > 0 && rowOffset > dataEnd;
16910
+ var dataOffset = rowOffset - dataStart;
16911
+ var column = table.columns && table.columns[colOffset];
16912
+
16913
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.wholeTable));
16914
+ if(!isHeader && !isTotal && dataOffset >= 0) {
16915
+ if(info.showRowStripes) resolved = table_style_merge(resolved, table_style_rule_value(
16916
+ table_style_stripe_rule(rules.firstRowStripe, rules.secondRowStripe, dataOffset)
16917
+ ));
16918
+ if(info.showColumnStripes) resolved = table_style_merge(resolved, table_style_rule_value(
16919
+ table_style_stripe_rule(rules.firstColumnStripe, rules.secondColumnStripe, colOffset)
16920
+ ));
16921
+ }
16922
+ if(info.showFirstColumn && col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstColumn));
16923
+ if(info.showLastColumn && col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastColumn));
16924
+ if(isHeader) {
16925
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.headerRow));
16926
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstHeaderCell));
16927
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastHeaderCell));
16928
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.headerRowDxfId));
16929
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.headerRowDxfId));
16930
+ } else if(isTotal) {
16931
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.totalRow));
16932
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstTotalCell));
16933
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastTotalCell));
16934
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.totalsRowDxfId));
16935
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.totalsRowDxfId));
16936
+ } else {
16937
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.dataDxfId));
16938
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.dataDxfId));
16939
+ }
16940
+ }
16941
+ return keys(resolved).length ? resolved : void 0;
16942
+ }
16549
16943
  function parse_ws_xml_dim(ws, s) {
16550
16944
  var d = safe_decode_range(s);
16551
16945
  if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
@@ -16554,7 +16948,25 @@ var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
16554
16948
  var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
16555
16949
  var dimregex = /"(\w*:\w*)"/;
16556
16950
  var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
16557
- var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
16951
+ function match_ws_xml_autofilter(data) {
16952
+ var paired = str_match_xml_ns(data, "autoFilter");
16953
+ if(paired) return paired[0];
16954
+ var start = 0;
16955
+ while((start = data.indexOf("<", start)) != -1) {
16956
+ var end = data.indexOf(">", start + 1);
16957
+ if(end == -1) return null;
16958
+ var tag = data.slice(start + 1, end), p = 0;
16959
+ while(p < tag.length && tag.charCodeAt(p) <= 32) ++p;
16960
+ var nameEnd = p;
16961
+ while(nameEnd < tag.length && tag.charCodeAt(nameEnd) > 32 && tag.charAt(nameEnd) != "/") ++nameEnd;
16962
+ var name = tag.slice(p, nameEnd), colon = name.indexOf(":");
16963
+ if(colon != -1) name = name.slice(colon + 1);
16964
+ var tail = tag.slice(nameEnd).trim();
16965
+ if(name == "autoFilter" && tail.charAt(tail.length - 1) == "/") return data.slice(start, end + 1);
16966
+ start = end + 1;
16967
+ }
16968
+ return null;
16969
+ }
16558
16970
  var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
16559
16971
  var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
16560
16972
 
@@ -16603,8 +17015,8 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16603
17015
  if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
16604
17016
 
16605
17017
  /* 18.3.1.2 autoFilter CT_AutoFilter */
16606
- var afilter = data2.match(afregex);
16607
- if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
17018
+ var afilter = match_ws_xml_autofilter(data2);
17019
+ if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter);
16608
17020
 
16609
17021
  /* 18.3.1.55 mergeCells CT_MergeCells */
16610
17022
  var merges = [];
@@ -16642,7 +17054,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16642
17054
  if(columns.length > 0) s["!cols"] = columns;
16643
17055
  if(merges.length > 0) {
16644
17056
  s["!merges"] = merges;
16645
- var mergeErrors = validate_merges(s, {WTF: !!(opts && (opts.WTF || opts.validateMerges))});
17057
+ var mergeErrors = validate_merges(s, {WTF: !!(opts && opts.validateMerges)});
16646
17058
  if(mergeErrors.length) s["!mergeErrors"] = mergeErrors;
16647
17059
  }
16648
17060
  if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
@@ -16757,7 +17169,8 @@ function parse_ws_xml_cols(columns, cols) {
16757
17169
  var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
16758
17170
  if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
16759
17171
  delete coll.min; delete coll.max; coll.width = +coll.width;
16760
- /* OOXML widths share the workbook Normal-font MDW; do not infer a different scale per sheet. */
17172
+ /* OOXML widths share the workbook Normal-font MDW. Do not infer it from
17173
+ * one ambiguous stored width or leak another worksheet's scale. */
16761
17174
  if(!seencol && coll.width) { seencol = true; MDW = DEF_MDW; }
16762
17175
  process_col(coll);
16763
17176
  while(colm <= colM) columns[colm++] = dup(coll);
@@ -17129,7 +17542,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17129
17542
  'xmlns:r': XMLNS.r
17130
17543
  })];
17131
17544
  var s = wb.SheetNames[idx], sidx = 0, rdata = "";
17132
- var ws = wb.Sheets[s];
17545
+ var ws = sheet_map_get(wb.Sheets, s);
17133
17546
  if(ws == null) ws = {};
17134
17547
  var ref = ws['!ref'] || 'A1';
17135
17548
  var range = safe_decode_range(ref);
@@ -17180,7 +17593,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17180
17593
  /* customSheetViews */
17181
17594
 
17182
17595
  if(ws['!merges'] != null && ws['!merges'].length > 0) {
17183
- validate_merges(ws, {WTF:true});
17596
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
17184
17597
  o[o.length] = (write_ws_xml_merges(ws['!merges']));
17185
17598
  }
17186
17599
 
@@ -18242,7 +18655,7 @@ function write_SHEETPROTECT(ba, ws) {
18242
18655
 
18243
18656
  function write_ws_bin(idx, opts, wb, rels) {
18244
18657
  var ba = buf_array();
18245
- var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
18658
+ var s = wb.SheetNames[idx], ws = sheet_map_get(wb.Sheets, s) || {};
18246
18659
  var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
18247
18660
  var r = safe_decode_range(ws['!ref'] || "A1");
18248
18661
  if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
@@ -18310,7 +18723,7 @@ function parse_Cache(data) {
18310
18723
  /* 21.2.2.71 formatCode CT_Xstring */
18311
18724
  var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
18312
18725
 
18313
- (str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
18726
+ (str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = strip_xml_tags(F); });
18314
18727
 
18315
18728
  return [col, nf, f];
18316
18729
  }
@@ -18327,7 +18740,7 @@ function parse_chart_cache(data) {
18327
18740
  return {values:s[0], formatCode:s[1], formula:s[2]};
18328
18741
  }
18329
18742
  var f = (str_match_ng(data, "<c:f>", "</c:f>")||[])[0];
18330
- return {values:[], formula:f ? f.replace(/<[^<>]*>/g,"") : void 0};
18743
+ return {values:[], formula:f ? strip_xml_tags(f) : void 0};
18331
18744
  }
18332
18745
 
18333
18746
  function parse_chart_tx(data) {
@@ -18359,7 +18772,7 @@ function parse_chart_title(data) {
18359
18772
  var title = str_match_xml_ns(data, "title");
18360
18773
  if(!title) return "";
18361
18774
  var out = [];
18362
- (title[0].match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) { out.push(unescapexml(t.replace(/<[^>]*>/g, ""))); });
18775
+ (title[0].match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) { out.push(unescapexml(strip_xml_tags(t))); });
18363
18776
  return out.join("");
18364
18777
  }
18365
18778
 
@@ -18664,9 +19077,12 @@ function check_wb(wb) {
18664
19077
  if(!wb.SheetNames.length) throw new Error("Workbook is empty");
18665
19078
  var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
18666
19079
  check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
18667
- for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
19080
+ for(var i = 0; i < wb.SheetNames.length; ++i) {
19081
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
19082
+ check_ws(ws, wb.SheetNames[i], i);
19083
+ }
18668
19084
  wb.SheetNames.forEach(function(n, i) {
18669
- var ws = wb.Sheets[n];
19085
+ var ws = sheet_map_get(wb.Sheets, n);
18670
19086
  if(!ws || !ws["!autofilter"]) return;
18671
19087
  var DN;
18672
19088
  if(!wb.Workbook) wb.Workbook = {};
@@ -19451,7 +19867,7 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o
19451
19867
  break;
19452
19868
  case 'String':
19453
19869
  cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
19454
- cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
19870
+ cell.v = (xml.indexOf("<") > -1 ? strip_xml_tags(unescapexml(ss||xml)) : cell.r); // todo: BR etc
19455
19871
  break;
19456
19872
  case 'DateTime':
19457
19873
  if(xml.slice(-1) != "Z") xml += "Z";
@@ -19546,7 +19962,7 @@ function parse_xlml_xml(d, _opts) {
19546
19962
  var Rn;
19547
19963
  var state = [], tmp;
19548
19964
  if(DENSE != null && opts.dense == null) opts.dense = DENSE;
19549
- var sheets = {}, sheetnames = [], cursheet = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
19965
+ var sheets = sheet_map_new(), sheetnames = [], cursheet = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
19550
19966
  var cell = ({}), row = {};// eslint-disable-line no-unused-vars
19551
19967
  var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
19552
19968
  var c = 0, r = 0;
@@ -19652,7 +20068,7 @@ for(var cma = c; cma <= cc; ++cma) {
19652
20068
  if(merges.length) cursheet["!merges"] = merges;
19653
20069
  if(cstys.length > 0) cursheet["!cols"] = cstys;
19654
20070
  if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
19655
- sheets[sheetname] = cursheet;
20071
+ sheet_map_set(sheets, sheetname, cursheet);
19656
20072
  } else {
19657
20073
  refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
19658
20074
  r = c = 0;
@@ -20553,7 +20969,7 @@ function write_ws_xlml_table(ws, opts, idx, wb) {
20553
20969
  function write_ws_xlml(idx, opts, wb) {
20554
20970
  var o = [];
20555
20971
  var s = wb.SheetNames[idx];
20556
- var ws = wb.Sheets[s];
20972
+ var ws = sheet_map_get(wb.Sheets, s);
20557
20973
 
20558
20974
  var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
20559
20975
  if(t.length > 0) o.push("<Names>" + t + "</Names>");
@@ -20785,7 +21201,7 @@ var parse_BIFFSurface = make_BIFFChartType("surfaceChart");
20785
21201
  // 2.3.2
20786
21202
  function parse_workbook(blob, options) {
20787
21203
  var wb = ({opts:{}});
20788
- var Sheets = {};
21204
+ var Sheets = sheet_map_new();
20789
21205
  if(DENSE != null && options.dense == null) options.dense = DENSE;
20790
21206
  var out = ({}); if(options.dense) out["!data"] = [];
20791
21207
  var Directory = {};
@@ -21080,7 +21496,7 @@ function parse_workbook(blob, options) {
21080
21496
  };
21081
21497
  var finalize_sheet_visuals = function finalizesheetvisuals(ws) {
21082
21498
  if(ws["!merges"] && ws["!merges"].length) {
21083
- var mergeErrors = validate_merges(ws, {WTF: !!(options && (options.WTF || options.validateMerges))});
21499
+ var mergeErrors = validate_merges(ws, {WTF: !!(options && options.validateMerges)});
21084
21500
  if(mergeErrors.length) ws["!mergeErrors"] = mergeErrors;
21085
21501
  }
21086
21502
  if(drawings && (drawings.images.length || drawings.shapes.length || drawings.charts.length || drawings.raw.length)) ws["!drawings"] = drawings;
@@ -21226,7 +21642,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
21226
21642
  finalize_sheet_visuals(out);
21227
21643
  Workbook.Sheets.push(wsprops);
21228
21644
  }
21229
- if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
21645
+ if(cur_sheet === "") Preamble = out; else sheet_map_set(Sheets, cur_sheet, out);
21230
21646
  out = ({}); if(options.dense) out["!data"] = [];
21231
21647
  } break;
21232
21648
  case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
@@ -21525,10 +21941,13 @@ if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
21525
21941
  if(!wb.SheetNames.length && Preamble["!ref"]) {
21526
21942
  wb.SheetNames.push("Sheet1");
21527
21943
  /*jshint -W069 */
21528
- if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
21944
+ if(wb.Sheets) sheet_map_set(wb.Sheets, "Sheet1", Preamble);
21529
21945
  /*jshint +W069 */
21530
21946
  } else wb.Preamble=Preamble;
21531
- if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
21947
+ if(wb.Sheets) FilterDatabases.forEach(function(r,i) {
21948
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
21949
+ if(ws) ws['!autofilter'] = r;
21950
+ });
21532
21951
  wb.Strings = sst;
21533
21952
  wb.SSF = dup(table_fmt);
21534
21953
  if(opts.enc) wb.Encryption = opts.enc;
@@ -23153,7 +23572,7 @@ function write_biff2_buf(wb, opts) {
23153
23572
  o.cellXfs = [{numFmtId: 0}];
23154
23573
  o._BIFF2FmtTable = ["General"]; o._Fonts = [];
23155
23574
  var body = buf_array();
23156
- write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
23575
+ write_ws_biff2(body, sheet_map_get(wb.Sheets, wb.SheetNames[idx]), idx, o, wb);
23157
23576
 
23158
23577
  o._BIFF2FmtTable.forEach(function(f) {
23159
23578
  if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
@@ -23563,7 +23982,7 @@ function write_ws_biff8_cell(ba, cell, R, C, opts, date1904) {
23563
23982
  /* [MS-XLS] 2.1.7.20.5 */
23564
23983
  function write_ws_biff8(idx, opts, wb) {
23565
23984
  var ba = buf_array();
23566
- var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
23985
+ var s = wb.SheetNames[idx], ws = sheet_map_get(wb.Sheets, s) || {};
23567
23986
  var _WB = ((wb||{}).Workbook||{});
23568
23987
  var _sheet = ((_WB.Sheets||[])[idx]||{});
23569
23988
  var dense = ws["!data"] != null;
@@ -23632,7 +24051,7 @@ function write_ws_biff8(idx, opts, wb) {
23632
24051
  if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
23633
24052
  /* ... */
23634
24053
  if(b8 && (ws['!merges']||[]).length) {
23635
- validate_merges(ws, {WTF:true});
24054
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
23636
24055
  write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
23637
24056
  }
23638
24057
  /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
@@ -23762,7 +24181,7 @@ function write_biff8_buf(wb, opts) {
23762
24181
 
23763
24182
  function write_biff_buf(wb, opts) {
23764
24183
  for(var i = 0; i <= wb.SheetNames.length; ++i) {
23765
- var ws = wb.Sheets[wb.SheetNames[i]];
24184
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
23766
24185
  if(!ws || !ws["!ref"]) continue;
23767
24186
  var range = decode_range(ws["!ref"]);
23768
24187
  if(range.e.c > 255) { // note: 255 is IV
@@ -23844,15 +24263,66 @@ function html_to_sheet(str, _opts) {
23844
24263
  return ws;
23845
24264
  }
23846
24265
 
23847
- function cssesc(x) { return escapexml(String(x).replace(/"/g, "'")); }
23848
24266
  function css_color(color) {
23849
24267
  if(!color) return "";
23850
- if(color.rgb) return "#" + String(color.rgb).slice(-6);
24268
+ if(color.rgb && /^[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?$/.test(String(color.rgb))) return "#" + String(color.rgb).slice(-6);
23851
24269
  return "";
23852
24270
  }
23853
24271
  function css_font_family(name) {
23854
24272
  if(!name) return "";
23855
- return "'" + cssesc(name).replace(/'/g, "\\'") + "'";
24273
+ return "'" + css_string_escape(name, "'") + "'";
24274
+ }
24275
+
24276
+ function html_attr_escape(value) {
24277
+ return String(value).replace(/[&<>"']/g, function(ch) {
24278
+ return ch == "&" ? "&amp;" : ch == "<" ? "&lt;" : ch == ">" ? "&gt;" : ch == '"' ? "&quot;" : "&#39;";
24279
+ });
24280
+ }
24281
+ function html_writextag(tag, content, attrs) {
24282
+ var out = ["<", tag];
24283
+ if(attrs) keys(attrs).forEach(function(key) { out.push(" ", key, '="', html_attr_escape(attrs[key]), '"'); });
24284
+ if(content == null) { out.push("/>"); return out.join(""); }
24285
+ out.push(">", content, "</", tag, ">");
24286
+ return out.join("");
24287
+ }
24288
+ function safe_html_href(value) {
24289
+ var href = String(value == null ? "" : value).trim();
24290
+ if(!href || href.slice(0, 2) == "//") return null;
24291
+ var colon = href.indexOf(":"), prefix = colon == -1 ? "" : href.slice(0, colon), compact = "";
24292
+ for(var i = 0; i < prefix.length; ++i) if(prefix.charCodeAt(i) > 32 && prefix.charCodeAt(i) != 127) compact += prefix.charAt(i);
24293
+ if(colon != -1 && !/^(?:https?|mailto|tel)$/i.test(compact)) return null;
24294
+ return href;
24295
+ }
24296
+ function safe_html_image_src(value) {
24297
+ var src = String(value == null ? "" : value);
24298
+ return /^data:image\/[A-Za-z0-9.+-]+;base64,[A-Za-z0-9+/=\r\n]+$/.test(src) ? src : null;
24299
+ }
24300
+ function sanitize_cell_html(value) {
24301
+ var html = String(value == null ? "" : value), out = [], pos = 0;
24302
+ while(pos < html.length) {
24303
+ var start = html.indexOf("<", pos);
24304
+ if(start == -1) { out.push(html.slice(pos)); break; }
24305
+ out.push(html.slice(pos, start));
24306
+ var end = html.indexOf(">", start + 1);
24307
+ if(end == -1) { out.push("&lt;", html.slice(start + 1)); break; }
24308
+ var raw = html.slice(start + 1, end).trim(), lower = raw.toLowerCase();
24309
+ if(/^(?:\/?(?:b|i|s|sup|sub)|br\s*\/?)$/.test(lower)) out.push("<", lower == "br" ? "br/" : lower, ">");
24310
+ else if(lower == "/span") out.push("</span>");
24311
+ else if(lower.slice(0, 12) == 'span style="' && raw.charAt(raw.length - 1) == '"') {
24312
+ var declarations = raw.slice(12, -1).split(";"), safe = [];
24313
+ declarations.forEach(function(decl) {
24314
+ var colon = decl.indexOf(":"), key = colon == -1 ? "" : decl.slice(0, colon).trim().toLowerCase(), val = colon == -1 ? "" : decl.slice(colon + 1).trim().toLowerCase();
24315
+ if(key == "text-decoration" && val == "underline") safe.push("text-decoration:underline");
24316
+ else if(key == "text-underline-style" && /^(?:single|double|single-accounting|double-accounting)$/.test(val)) safe.push("text-underline-style:" + val);
24317
+ else if(key == "font-size" && /^\d+(?:\.\d+)?pt$/.test(val)) safe.push("font-size:" + val);
24318
+ else if(key == "text-effect" && val == "outline") safe.push("text-effect:outline");
24319
+ else if(key == "text-shadow" && val == "auto") safe.push("text-shadow:auto");
24320
+ });
24321
+ out.push('<span style="', safe.join(";"), safe.length ? ";" : "", '">');
24322
+ } else out.push(html_attr_escape(html.slice(start, end + 1)));
24323
+ pos = end + 1;
24324
+ }
24325
+ return out.join("");
23856
24326
  }
23857
24327
  function html_border_style(style) {
23858
24328
  switch(style) {
@@ -23881,7 +24351,8 @@ function html_cell_style(cell, opts) {
23881
24351
  var s = cell.s, css = [];
23882
24352
  var font = s.font || {};
23883
24353
  if(font.name) css.push("font-family:" + css_font_family(font.name));
23884
- if(font.sz) css.push("font-size:" + font.sz + "pt");
24354
+ var fontSize = +font.sz;
24355
+ if(isFinite(fontSize) && fontSize > 0) css.push("font-size:" + Math.min(fontSize, 409) + "pt");
23885
24356
  if(font.bold) css.push("font-weight:bold");
23886
24357
  if(font.italic) css.push("font-style:italic");
23887
24358
  var deco = [];
@@ -23894,8 +24365,9 @@ function html_cell_style(cell, opts) {
23894
24365
  if(fill.patternType != "none" && fill.patternType != "gray125") fillColor = css_color(fill.fgColor) || css_color(fill.bgColor);
23895
24366
  if(fillColor) css.push("background-color:" + fillColor);
23896
24367
  var alignment = s.alignment || {};
23897
- if(alignment.horizontal) css.push("text-align:" + alignment.horizontal);
23898
- if(alignment.vertical) css.push("vertical-align:" + alignment.vertical);
24368
+ if(/^(?:left|right|center|justify|fill|distributed)$/.test(alignment.horizontal || "")) css.push("text-align:" + alignment.horizontal);
24369
+ var vertical = alignment.vertical == "center" ? "middle" : alignment.vertical;
24370
+ if(/^(?:top|middle|bottom|baseline)$/.test(vertical || "")) css.push("vertical-align:" + vertical);
23899
24371
  if(alignment.textRotation != null && alignment.textRotation !== 0) {
23900
24372
  var deg = alignment.textRotation == 255 ? 90 : alignment.textRotation > 90 ? 90 - alignment.textRotation : alignment.textRotation;
23901
24373
  css.push("transform:rotate(" + deg + "deg)");
@@ -23968,13 +24440,14 @@ function make_html_row(ws, r, R, o) {
23968
24440
  if(cols[C] && cols[C].s) extend_style_obj(inherited, cols[C].s);
23969
24441
  if(row && row.s) extend_style_obj(inherited, row.s);
23970
24442
  if(cell && cell.s) extend_style_obj(inherited, cell.s);
24443
+ inherited = resolve_table_cell_style(ws, R, C, inherited) || inherited;
23971
24444
  if(keys(inherited).length) {
23972
24445
  stylecell = cell ? dup(cell) : {t:'z'};
23973
24446
  stylecell.s = inherited;
23974
24447
  }
23975
24448
  }
23976
24449
  /* TODO: html entities */
23977
- var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
24450
+ var w = (cell && cell.v != null) && (cell.h ? sanitize_cell_html(cell.h) : escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
23978
24451
  sp = ({});
23979
24452
  if(RS > 1) sp.rowspan = RS;
23980
24453
  if(CS > 1) sp.colspan = CS;
@@ -23982,17 +24455,18 @@ function make_html_row(ws, r, R, o) {
23982
24455
  else if(cell) {
23983
24456
  sp["data-t"] = cell && cell.t || 'z';
23984
24457
  // note: data-v is unaffected by the timezone interpretation
23985
- if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
24458
+ if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
23986
24459
  if(cell.z != null) sp["data-z"] = cell.z;
23987
- if(cell.f != null) sp["data-f"] = escapehtml(cell.f);
23988
- if(cell.l && (cell.l.Target || "#").charAt(0) != "#" && (!o.sanitizeLinks || (cell.l.Target || "").slice(0, 11).toLowerCase() != 'javascript:')) w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
24460
+ if(cell.f != null) sp["data-f"] = cell.f;
24461
+ var href = cell.l && safe_html_href(cell.l.Target);
24462
+ if(href) w = '<a href="' + html_attr_escape(href) +'">' + w + '</a>';
23989
24463
  }
23990
24464
  var cstyle = html_cell_style(stylecell, o);
23991
24465
  var lstyle = html_cell_layout_style(stylecell, o, C, CS, cols);
23992
24466
  if(lstyle) cstyle = cstyle ? cstyle + ";" + lstyle : lstyle;
23993
24467
  if(cstyle) sp.style = cstyle;
23994
24468
  sp.id = (o.id || "sjs") + "-" + coord;
23995
- oo.push(writextag('td', w, sp));
24469
+ oo.push(html_writextag('td', w, sp));
23996
24470
  }
23997
24471
  var rsp = ({}), rstyle = [];
23998
24472
  if(row) {
@@ -24000,7 +24474,7 @@ function make_html_row(ws, r, R, o) {
24000
24474
  if(o.browserPixels) rstyle.push("height:" + html_row_height(row) + "px");
24001
24475
  }
24002
24476
  if(rstyle.length) rsp.style = rstyle.join(";");
24003
- return writextag('tr', oo.join(""), rsp);
24477
+ return html_writextag('tr', oo.join(""), rsp);
24004
24478
  }
24005
24479
 
24006
24480
  var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
@@ -24136,8 +24610,10 @@ function render_html_drawings(ws, opts) {
24136
24610
  var out = [], drawings = ws["!drawings"] || {}, charts = ws["!charts"] || [];
24137
24611
  if(opts && opts.drawings && drawings.images) drawings.images.forEach(function(img) {
24138
24612
  if(!img || !img.dataURI) return;
24613
+ var src = safe_html_image_src(img.dataURI);
24614
+ if(!src) return;
24139
24615
  var pos = html_anchor_pos(ws, img.anchor, opts);
24140
- out.push('<img class="sjs-drawing-image" src="' + img.dataURI + '" style="' + html_abs_style(pos) + '"/>');
24616
+ out.push('<img class="sjs-drawing-image" src="' + html_attr_escape(src) + '" style="' + html_abs_style(pos) + '"/>');
24141
24617
  });
24142
24618
  if(opts && opts.charts) charts.forEach(function(chart) {
24143
24619
  var pos = html_anchor_pos(ws, chart.anchor, opts);
@@ -24152,7 +24628,7 @@ function make_html_preamble(ws, R, o) {
24152
24628
  if(o && o.id) tattr.id = o.id;
24153
24629
  if(o && (o.browserPixels || o.autoFit)) tstyle.push("border-collapse:collapse;table-layout:fixed");
24154
24630
  if(tstyle.length) tattr.style = tstyle.join(";");
24155
- var table = writextag("table", "", tattr).replace(/<\/table>$/, "");
24631
+ var table = html_writextag("table", "", tattr).replace(/<\/table>$/, "");
24156
24632
  var cols = o && o._htmlCols || ws["!cols"];
24157
24633
  if(o && (o.browserPixels || o.autoFit) && cols) {
24158
24634
  out.push("<colgroup>");
@@ -24160,7 +24636,7 @@ function make_html_preamble(ws, R, o) {
24160
24636
  var col = cols[C], style = [];
24161
24637
  style.push("width:" + html_col_width(col) + "px");
24162
24638
  if(col && col.hidden) style.push("display:none");
24163
- out.push(writextag("col", null, {style:style.join(";")}));
24639
+ out.push(html_writextag("col", null, {style:style.join(";")}));
24164
24640
  }
24165
24641
  out.push("</colgroup>");
24166
24642
  }
@@ -24327,7 +24803,7 @@ function parse_text_p(text) {
24327
24803
  .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
24328
24804
  .replace(/<text:tab[^<>]*\/>/g,"\t")
24329
24805
  .replace(/<text:line-break\/>/g,"\n");
24330
- var v = unescapexml(fixed.replace(/<[^<>]*>/g,""));
24806
+ var v = unescapexml(strip_xml_tags(fixed));
24331
24807
 
24332
24808
  return [v];
24333
24809
  }
@@ -24564,7 +25040,7 @@ function parse_content_xml(d, _opts, _nfm) {
24564
25040
  var nfidx, NF = "", pidx = 0;
24565
25041
  var sheetag;
24566
25042
  var rowtag;
24567
- var Sheets = {}, SheetNames = [];
25043
+ var Sheets = sheet_map_new(), SheetNames = [];
24568
25044
  var ws = ({}); if(opts.dense) ws["!data"] = [];
24569
25045
  var Rn, q;
24570
25046
  var ctag = ({value:""}), ctag2 = ({});
@@ -24601,7 +25077,7 @@ function parse_content_xml(d, _opts, _nfm) {
24601
25077
  sheetag.name = sheetag['名称'] || sheetag.name;
24602
25078
  if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
24603
25079
  SheetNames.push(sheetag.name);
24604
- Sheets[sheetag.name] = ws;
25080
+ sheet_map_set(Sheets, sheetag.name, ws);
24605
25081
  WB.Sheets.push({
24606
25082
  /* TODO: CodeName */
24607
25083
  Hidden: (tstyles[sheetag["style-name"]] && tstyles[sheetag["style-name"]]["display"] ? (parsexmlbool(tstyles[sheetag["style-name"]]["display"]) ? 0 : 1) : 0)
@@ -24957,7 +25433,9 @@ function parse_content_xml(d, _opts, _nfm) {
24957
25433
  if(Rn[1]==='/') break;
24958
25434
  try {
24959
25435
  _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
24960
- Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
25436
+ if(Object.prototype.hasOwnProperty.call(Sheets, _Ref[0]) && Sheets[_Ref[0]]) {
25437
+ Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
25438
+ }
24961
25439
  } catch(e) {/* empty */}
24962
25440
  break;
24963
25441
 
@@ -25467,7 +25945,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25467
25945
 
25468
25946
  /* column styles */
25469
25947
  var cidx = 0;
25470
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
25948
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25471
25949
  if(!ws) return;
25472
25950
  if(ws["!cols"]) {
25473
25951
  for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
@@ -25486,7 +25964,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25486
25964
 
25487
25965
  /* row styles */
25488
25966
  var ridx = 0;
25489
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
25967
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25490
25968
  if(!ws) return;
25491
25969
  if(ws["!rows"]) {
25492
25970
  for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
@@ -25519,7 +25997,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25519
25997
  /* number formats, table cells, text */
25520
25998
  var nfs = {};
25521
25999
  var nfi = 69;
25522
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
26000
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25523
26001
  if(!ws) return;
25524
26002
  var dense = (ws["!data"] != null);
25525
26003
  if(!ws["!ref"]) return;
@@ -25602,7 +26080,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25602
26080
  o.push(' <office:body>\n');
25603
26081
  o.push(' <office:spreadsheet>\n');
25604
26082
  if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
25605
- for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
26083
+ for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(sheet_map_get(wb.Sheets, wb.SheetNames[i]), wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
25606
26084
  if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
25607
26085
  o.push(' </office:spreadsheet>\n');
25608
26086
  o.push(' </office:body>\n');
@@ -25654,7 +26132,6 @@ function write_ods(wb, opts) {
25654
26132
 
25655
26133
  return zip;
25656
26134
  }
25657
-
25658
26135
  /*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
25659
26136
  var subarray = function() {
25660
26137
  try {
@@ -27172,7 +27649,7 @@ function write_numbers_iwa(wb, opts) {
27172
27649
  docroot = numbers_iwa_find(cfb, deps, 1);
27173
27650
  sheetrefs = mappa(parse_shallow(docroot.messages[0].data)[1], parse_TSP_Reference);
27174
27651
  }
27175
- write_numbers_ws(cfb, deps, wb.Sheets[name], name, idx, sheetrefs[idx]);
27652
+ write_numbers_ws(cfb, deps, sheet_map_get(wb.Sheets, name), name, idx, sheetrefs[idx]);
27176
27653
  });
27177
27654
  return cfb;
27178
27655
  }
@@ -28090,7 +28567,8 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28090
28567
  case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
28091
28568
  default: throw new Error("Unrecognized sheet type " + stype);
28092
28569
  }
28093
- sheets[sheet] = _ws;
28570
+ if(stype == "sheet") parse_sheet_tables(_ws, zip, path, sheetRels[sheet], opts, themes, styles);
28571
+ sheet_map_set(sheets, sheet, _ws);
28094
28572
 
28095
28573
  /* scan rels for comments and threaded comments */
28096
28574
  var comments = [], tcomments = [];
@@ -28110,7 +28588,9 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28110
28588
  if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
28111
28589
  if(stype == "sheet") parse_sheet_drawing(_ws, stype, zip, path, idx, opts, wb);
28112
28590
  parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
28113
- } catch(e) { if(opts.WTF) throw e; }
28591
+ } catch(e) {
28592
+ if(opts.WTF || (opts.validateMerges && e && /^E_MERGE_/.test(e.code))) throw e;
28593
+ }
28114
28594
  }
28115
28595
 
28116
28596
  function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
@@ -28213,7 +28693,7 @@ function parse_zip(zip, opts) {
28213
28693
  if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
28214
28694
  if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
28215
28695
  }
28216
- sheets = {};
28696
+ sheets = sheet_map_new();
28217
28697
 
28218
28698
  var deps = {};
28219
28699
  if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
@@ -28413,7 +28893,7 @@ f = "docProps/app.xml";
28413
28893
 
28414
28894
  for(rId=1;rId <= wb.SheetNames.length; ++rId) {
28415
28895
  var wsrels = {'!id':{}};
28416
- var ws = wb.Sheets[wb.SheetNames[rId-1]];
28896
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[rId-1]);
28417
28897
  var _type = (ws || {})["!type"] || "sheet";
28418
28898
  switch(_type) {
28419
28899
  case "chart":
@@ -28568,7 +29048,7 @@ f = "docProps/app.xml";
28568
29048
 
28569
29049
  for(rId=1;rId <= wb.SheetNames.length; ++rId) {
28570
29050
  var wsrels = {'!id':{}};
28571
- var ws = wb.Sheets[wb.SheetNames[rId-1]];
29051
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[rId-1]);
28572
29052
  var _type = (ws || {})["!type"] || "sheet";
28573
29053
  switch(_type) {
28574
29054
  case "chart":
@@ -28664,7 +29144,6 @@ f = "docProps/app.xml";
28664
29144
  delete opts.revssf; delete opts.ssf;
28665
29145
  return zip;
28666
29146
  }
28667
-
28668
29147
  function firstbyte(f,o) {
28669
29148
  var x = "";
28670
29149
  switch((o||{}).type || "base64") {
@@ -28933,18 +29412,18 @@ function writeSync(wb, opts) {
28933
29412
  case 'xml':
28934
29413
  case 'xlml': return write_string_type(write_xlml(wb, o), o);
28935
29414
  case 'slk':
28936
- case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
29415
+ case 'sylk': return write_string_type(SYLK.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o, wb), o);
28937
29416
  case 'htm':
28938
- case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
28939
- case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
28940
- case 'csv': return write_string_type(sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o), o, "\ufeff");
28941
- case 'dif': return write_string_type(DIF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
28942
- case 'dbf': return write_binary_type(DBF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
28943
- case 'prn': return write_string_type(PRN.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
28944
- case 'rtf': return write_string_type(sheet_to_rtf(wb.Sheets[wb.SheetNames[idx]], o), o);
28945
- case 'eth': return write_string_type(ETH.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
29417
+ case 'html': return write_string_type(sheet_to_html(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29418
+ case 'txt': return write_stxt_type(sheet_to_txt(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29419
+ case 'csv': return write_string_type(sheet_to_csv(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o, "\ufeff");
29420
+ case 'dif': return write_string_type(DIF.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29421
+ case 'dbf': return write_binary_type(DBF.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29422
+ case 'prn': return write_string_type(PRN.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29423
+ case 'rtf': return write_string_type(sheet_to_rtf(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29424
+ case 'eth': return write_string_type(ETH.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
28946
29425
  case 'fods': return write_string_type(write_ods(wb, o), o);
28947
- case 'wk1': return write_binary_type(WK_.sheet_to_wk1(wb.Sheets[wb.SheetNames[idx]], o), o);
29426
+ case 'wk1': return write_binary_type(WK_.sheet_to_wk1(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
28948
29427
  case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
28949
29428
  case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
28950
29429
  case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
@@ -29204,6 +29683,7 @@ function sheet_add_json(_ws, js, opts) {
29204
29683
  var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
29205
29684
  _R = _origin.r; _C = _origin.c;
29206
29685
  }
29686
+ if(!isFinite(_R) || _R !== Math.floor(_R) || _R < -1 || !isFinite(_C) || _C !== Math.floor(_C) || _C < 0) throw new Error("Invalid origin");
29207
29687
  }
29208
29688
  var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
29209
29689
  if(ws['!ref']) {
@@ -29295,7 +29775,7 @@ function wb_sheet_idx(wb, sh) {
29295
29775
 
29296
29776
  /* simple blank or single-sheet workbook object */
29297
29777
  function book_new(ws, wsname) {
29298
- var wb = { SheetNames: [], Sheets: {} };
29778
+ var wb = { SheetNames: [], Sheets: sheet_map_new() };
29299
29779
  if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
29300
29780
  return wb;
29301
29781
  }
@@ -29315,7 +29795,7 @@ function book_append_sheet(wb, ws, name, roll) {
29315
29795
  if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
29316
29796
 
29317
29797
  wb.SheetNames.push(name);
29318
- wb.Sheets[name] = ws;
29798
+ sheet_map_set(wb.Sheets, name, ws);
29319
29799
  return name;
29320
29800
  }
29321
29801
 
@@ -29382,7 +29862,6 @@ function sheet_set_array_formula(ws, range, formula, dynamic) {
29382
29862
  ws["!ref"] = encode_range(wsr);
29383
29863
  return ws;
29384
29864
  }
29385
-
29386
29865
  var utils = {
29387
29866
  encode_col: encode_col,
29388
29867
  encode_row: encode_row,
@@ -29412,6 +29891,7 @@ var utils = {
29412
29891
  measure_text_width: measure_text_width,
29413
29892
  auto_fit_columns: auto_fit_columns,
29414
29893
  autofit_columns: auto_fit_columns,
29894
+ resolve_table_cell_style: resolve_table_cell_style,
29415
29895
  col_width_to_px: width2px,
29416
29896
  px_to_col_width: function(px) { return char2width(px2char(px)); },
29417
29897
  row_height_to_px: pt2px_browser,
@@ -29539,7 +30019,7 @@ function write_json_stream(sheet, opts) {
29539
30019
  if ((rowinfo[R]||{}).hidden) {
29540
30020
  ++R;
29541
30021
  continue;
29542
- };
30022
+ }
29543
30023
  var row = make_json_row(sheet, r, R, cols, header, hdr, o);
29544
30024
  ++R;
29545
30025
  if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
@@ -29568,7 +30048,7 @@ function write_xlml_stream(wb, o) {
29568
30048
 
29569
30049
  /* do one pass to determine styles since they must be added before tables */
29570
30050
  wb.SheetNames.forEach(function(n) {
29571
- var ws = wb.Sheets[n];
30051
+ var ws = sheet_map_get(wb.Sheets, n);
29572
30052
  if(!ws || !ws["!ref"]) return;
29573
30053
  var range = decode_range(ws["!ref"]);
29574
30054
  var dense = ws["!data"] != null;
@@ -29588,7 +30068,7 @@ function write_xlml_stream(wb, o) {
29588
30068
  });
29589
30069
  var sty = write_sty_xlml(wb, opts);
29590
30070
 
29591
- var stage = 0, wsidx = 0, ws = wb.Sheets[wb.SheetNames[wsidx]], range = safe_decode_range(ws), R = -1, T = false;
30071
+ var stage = 0, wsidx = 0, ws = sheet_map_get(wb.Sheets, wb.SheetNames[wsidx]), range = safe_decode_range(ws), R = -1, T = false;
29592
30072
 
29593
30073
  var marr = [], mi = 0, dense = false, darr = [], addr = {r:0,c:0};
29594
30074
 
@@ -29628,7 +30108,7 @@ function write_xlml_stream(wb, o) {
29628
30108
 
29629
30109
  stream.push("<Worksheet" + wxt_helper({ "ss:Name": escapexml(wb.SheetNames[wsidx])}) + ">");
29630
30110
 
29631
- ws = wb.Sheets[wb.SheetNames[wsidx]];
30111
+ ws = sheet_map_get(wb.Sheets, wb.SheetNames[wsidx]);
29632
30112
  if(!ws) { stream.push("</Worksheet>"); return void ++wsidx; }
29633
30113
 
29634
30114
  var names = write_ws_xlml_names(ws, opts, wsidx, wb);