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.
@@ -157,10 +157,10 @@ var DO_NOT_EXPORT_CODEPAGE = true;
157
157
  /*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
158
158
  /* vim: set ts=2: */
159
159
  /*exported XLSX */
160
- /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false */
160
+ /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false, Int8Array:false */
161
161
  var XLSX = {};
162
162
  function make_xlsx_lib(XLSX){
163
- XLSX.version = '0.21.2';
163
+ XLSX.version = '0.21.4';
164
164
  var current_codepage = 1200, current_ansi = 1252;
165
165
  /*global cptable:true, window */
166
166
  var $cptable;
@@ -314,9 +314,9 @@ function Base64_decode(input) {
314
314
  var o = "";
315
315
  var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
316
316
  if (input.slice(0, 5) == "data:") {
317
- var i = input.slice(0, 1024).indexOf(";base64,");
318
- if (i > -1)
319
- input = input.slice(i + 8);
317
+ var sep = input.slice(0, 1024).indexOf(";base64,");
318
+ if (sep > -1)
319
+ input = input.slice(sep + 8);
320
320
  }
321
321
  input = input.replace(/[^\w\+\/\=]/g, "");
322
322
  for (var i = 0; i < input.length; ) {
@@ -3388,7 +3388,7 @@ function blobify(data) {
3388
3388
  }
3389
3389
  /* write or download file */
3390
3390
  function write_dl(fname, payload, enc) {
3391
- /*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
3391
+ /*global IE_SaveFile, navigator, saveAs, document, chrome */
3392
3392
  if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
3393
3393
  if(typeof Deno !== 'undefined') {
3394
3394
  /* in this spot, it's safe to assume typed arrays and TextEncoder/TextDecoder exist */
@@ -4028,7 +4028,7 @@ function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
4028
4028
  var htmlcharegex = /[\u0000-\u001f]/g;
4029
4029
  function escapehtml(text){
4030
4030
  var s = text + '';
4031
- 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) + ";"; });
4031
+ 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) + ";"; });
4032
4032
  }
4033
4033
 
4034
4034
  function escapexlml(text){
@@ -4036,6 +4036,19 @@ function escapexlml(text){
4036
4036
  return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
4037
4037
  }
4038
4038
 
4039
+ /* Extract text from XML fragments in linear time. This is a parser helper,
4040
+ * not an HTML sanitizer: text is escaped separately at HTML output boundaries. */
4041
+ function strip_xml_tags(text) {
4042
+ var str = String(text), out = [], inTag = false;
4043
+ for(var i = 0; i < str.length; ++i) {
4044
+ var cc = str.charCodeAt(i);
4045
+ if(!inTag && cc == 60 /* < */) inTag = true;
4046
+ else if(inTag && cc == 62 /* > */) inTag = false;
4047
+ else if(!inTag) out.push(str.charAt(i));
4048
+ }
4049
+ return out.join("");
4050
+ }
4051
+
4039
4052
  /* TODO: handle codepages */
4040
4053
  var xlml_fixstr = (function() {
4041
4054
  var entregex = /&#(\d+);/g;
@@ -4142,8 +4155,8 @@ var htmldecode = (function() {
4142
4155
  .replace(/[\t\n\r ]+/g, " ")
4143
4156
  // Replace <br> tags with new lines
4144
4157
  .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
4145
- // Strip HTML elements
4146
- .replace(/<[^<>]*>/g,"");
4158
+ ;
4159
+ o = strip_xml_tags(o);
4147
4160
  for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
4148
4161
  return o;
4149
4162
  };
@@ -4714,9 +4727,25 @@ function format_cell(cell, v, o) {
4714
4727
  return safe_format_cell(cell, v);
4715
4728
  }
4716
4729
 
4730
+ /* Worksheet names are document-controlled. A normal object treats
4731
+ * "__proto__" as a setter, so all workbook sheet maps must use an own-property
4732
+ * preserving dictionary and all lookups must reject inherited properties. */
4733
+ function sheet_map_new() {
4734
+ return Object.create ? Object.create(null) : {};
4735
+ }
4736
+ function sheet_map_set(sheets, name, sheet) {
4737
+ if(name == "__proto__" && Object.defineProperty) Object.defineProperty(sheets, name, {
4738
+ value: sheet, configurable: true, enumerable: true, writable: true
4739
+ });
4740
+ else sheets[name] = sheet;
4741
+ }
4742
+ function sheet_map_get(sheets, name) {
4743
+ return sheets != null && Object.prototype.hasOwnProperty.call(sheets, name) ? sheets[name] : void 0;
4744
+ }
4745
+
4717
4746
  function sheet_to_workbook(sheet, opts) {
4718
4747
  var n = opts && opts.sheet ? opts.sheet : "Sheet1";
4719
- var sheets = {}; sheets[n] = sheet;
4748
+ var sheets = sheet_map_new(); sheet_map_set(sheets, n, sheet);
4720
4749
  return { SheetNames: [n], Sheets: sheets };
4721
4750
  }
4722
4751
 
@@ -5802,6 +5831,7 @@ var RELS = ({
5802
5831
  MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
5803
5832
  IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
5804
5833
  DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
5834
+ TABLE: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
5805
5835
  XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
5806
5836
  TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
5807
5837
  PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
@@ -6389,8 +6419,8 @@ function parse_TypedPropertyValue(blob, type, _opts) {
6389
6419
  case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
6390
6420
  case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
6391
6421
  case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
6392
- case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
6393
- case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
6422
+ case 0x1E /*VT_LPSTR*/: blob.l += 4; return parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1");
6423
+ case 0x1F /*VT_LPWSTR*/: blob.l += 4; return parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1");
6394
6424
  case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
6395
6425
  case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
6396
6426
  case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
@@ -6899,7 +6929,6 @@ function parse_LongRGBA(blob) { var r = blob.read_shift(1), g = blob.read_shift(
6899
6929
  /* 2.5.177 LongRGB */
6900
6930
  function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
6901
6931
 
6902
-
6903
6932
  /* [MS-XLS] 2.5.19 */
6904
6933
  function parse_XLSCell(blob, length, opts) {
6905
6934
  var rw = blob.read_shift(2); // 0-indexed
@@ -8361,7 +8390,7 @@ function dbf_to_workbook(buf, opts) {
8361
8390
  o.bookType = "dbf";
8362
8391
  return o;
8363
8392
  } catch(e) { if(opts && opts.WTF) throw e; }
8364
- return ({SheetNames:[],Sheets:{}});
8393
+ return ({SheetNames:[],Sheets:sheet_map_new()});
8365
8394
  }
8366
8395
 
8367
8396
  var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
@@ -9257,7 +9286,7 @@ function read_wb_TABL(d, opts) {
9257
9286
  try {
9258
9287
  var out = DIF.to_workbook(d, o);
9259
9288
  if(!out || !out.Sheets) throw "DIF bad workbook";
9260
- var ws = out.Sheets[out.SheetNames[0]];
9289
+ var ws = sheet_map_get(out.Sheets, out.SheetNames[0]);
9261
9290
  if(!ws || !ws["!ref"]) throw "DIF empty worksheet";
9262
9291
  o.WTF = OLD_WTF;
9263
9292
  return out;
@@ -9313,7 +9342,7 @@ var WK_ = (function() {
9313
9342
  var o = opts || {};
9314
9343
  if(DENSE != null && o.dense == null) o.dense = DENSE;
9315
9344
  var s = ({}), n = "Sheet1", next_n = "", sidx = 0;
9316
- var sheets = {}, snames = [], realnames = [], sdata = [];
9345
+ var sheets = sheet_map_new(), snames = [], realnames = [], sdata = [];
9317
9346
  if(o.dense) sdata = s["!data"] = [];
9318
9347
 
9319
9348
  var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9358,7 +9387,7 @@ var WK_ = (function() {
9358
9387
  if(o.qpro) {
9359
9388
  if(val[3] > sidx) {
9360
9389
  s["!ref"] = encode_range(refguess);
9361
- sheets[n] = s;
9390
+ sheet_map_set(sheets, n, s);
9362
9391
  snames.push(n);
9363
9392
  s = ({}); if(o.dense) sdata = s["!data"] = [];
9364
9393
  refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9409,7 +9438,7 @@ var WK_ = (function() {
9409
9438
  case 0x28: /* FORMULA28 */
9410
9439
  if(val[3] > sidx) {
9411
9440
  s["!ref"] = encode_range(refguess);
9412
- sheets[n] = s;
9441
+ sheet_map_set(sheets, n, s);
9413
9442
  snames.push(n);
9414
9443
  s = ({}); if(o.dense) sdata = s["!data"] = [];
9415
9444
  refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
@@ -9432,17 +9461,17 @@ var WK_ = (function() {
9432
9461
  }}, o);
9433
9462
  } else throw new Error("Unrecognized LOTUS BOF " + d[2]);
9434
9463
  s["!ref"] = encode_range(refguess);
9435
- sheets[next_n || n] = s;
9464
+ sheet_map_set(sheets, next_n || n, s);
9436
9465
  snames.push(next_n || n);
9437
9466
  if(!realnames.length) return { SheetNames: snames, Sheets: sheets };
9438
- var osheets = {}, rnames = [];
9467
+ var osheets = sheet_map_new(), rnames = [];
9439
9468
  /* TODO: verify no collisions */
9440
- for(var i = 0; i < realnames.length; ++i) if(sheets[snames[i]]) {
9469
+ for(var i = 0; i < realnames.length; ++i) if(sheet_map_get(sheets, snames[i])) {
9441
9470
  rnames.push(realnames[i] || snames[i]);
9442
- osheets[realnames[i]] = sheets[realnames[i]] || sheets[snames[i]];
9471
+ sheet_map_set(osheets, realnames[i] || snames[i], sheet_map_get(sheets, realnames[i]) || sheet_map_get(sheets, snames[i]));
9443
9472
  } else {
9444
9473
  rnames.push(realnames[i]);
9445
- osheets[realnames[i]] = ({ "!ref": "A1" });
9474
+ sheet_map_set(osheets, realnames[i], ({ "!ref": "A1" }));
9446
9475
  }
9447
9476
  return { SheetNames: rnames, Sheets: osheets };
9448
9477
  }
@@ -9496,11 +9525,11 @@ var WK_ = (function() {
9496
9525
 
9497
9526
  write_biff_rec(ba, 0x00, write_BOF_WK3(wb));
9498
9527
 
9499
- 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++));
9528
+ 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++));
9500
9529
 
9501
9530
  var wsidx = 0;
9502
9531
  for(i = 0; i < wb.SheetNames.length; ++i) {
9503
- var ws = wb.Sheets[wb.SheetNames[i]];
9532
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
9504
9533
  if(!ws || !ws["!ref"]) continue;
9505
9534
  var range = safe_decode_range(ws["!ref"]);
9506
9535
  var dense = ws["!data"] != null;
@@ -9545,7 +9574,7 @@ var WK_ = (function() {
9545
9574
  var rows = 0, cols = 0, wscnt = 0;
9546
9575
  for(var i = 0; i < wb.SheetNames.length; ++i) {
9547
9576
  var name = wb.SheetNames[i];
9548
- var ws = wb.Sheets[name];
9577
+ var ws = sheet_map_get(wb.Sheets, name);
9549
9578
  if(!ws || !ws["!ref"]) continue;
9550
9579
  ++wscnt;
9551
9580
  var range = decode_range(ws["!ref"]);
@@ -10273,7 +10302,7 @@ var WK_ = (function() {
10273
10302
  var SST = [], sname = "", formulae = [];
10274
10303
  var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
10275
10304
  var cnt = 0, type = 0, C = 0, R = 0;
10276
- var wb = { SheetNames: [], Sheets: {} };
10305
+ var wb = { SheetNames: [], Sheets: sheet_map_new() };
10277
10306
  var FMTS = [];
10278
10307
  outer: while(d.l < d.length) {
10279
10308
  var RT = d.read_shift(2), length = d.read_shift(2);
@@ -10577,13 +10606,13 @@ var parse_rs = (function() {
10577
10606
 
10578
10607
  /* Parse a list of <r> tags */
10579
10608
  var rs_to_html = (function parse_rs_factory() {
10580
- var nlregex = /(\r\n|\n)/g;
10581
10609
  function parse_rpr2(font, intro, outro) {
10582
10610
  var style = [];
10583
10611
 
10584
10612
  if(font.u) style.push("text-decoration: underline;");
10585
- if(font.uval) style.push("text-underline-style:" + font.uval + ";");
10586
- if(font.sz) style.push("font-size:" + font.sz + "pt;");
10613
+ if(font.uval && /^(?:single|double|single-accounting|double-accounting)$/.test(font.uval)) style.push("text-underline-style:" + font.uval + ";");
10614
+ var sz = +font.sz;
10615
+ if(isFinite(sz) && sz > 0) style.push("font-size:" + Math.min(sz, 409) + "pt;");
10587
10616
  if(font.outline) style.push("text-effect: outline;");
10588
10617
  if(font.shadow) style.push("text-shadow: auto;");
10589
10618
  intro.push('<span style="' + style.join("") + '">');
@@ -10608,7 +10637,7 @@ var rs_to_html = (function parse_rs_factory() {
10608
10637
 
10609
10638
  if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
10610
10639
 
10611
- return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
10640
+ return terms[0].join("") + escapehtml(terms[1]) + terms[2].join("");
10612
10641
  }
10613
10642
 
10614
10643
  return function parse_rs(rs) {
@@ -11266,6 +11295,9 @@ function resolve_style_obj_color(obj, themes) {
11266
11295
 
11267
11296
  /* 18.3.1.13 width calculations */
11268
11297
  /* [MS-OI29500] 2.1.595 Column Width & Formatting */
11298
+ /* The file format does not store MDW directly. Seven is the Office-compatible
11299
+ * fallback when Normal-font metrics are unavailable. A single stored column
11300
+ * width is ambiguous and must not change the scale for the rest of a sheet. */
11269
11301
  var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
11270
11302
  function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
11271
11303
  function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
@@ -11342,6 +11374,15 @@ function style_font_family(style) {
11342
11374
  var font = style && style.font || {};
11343
11375
  return font.name || "Calibri";
11344
11376
  }
11377
+ function css_string_escape(value, quote) {
11378
+ var str = String(value), out = [];
11379
+ for(var i = 0; i < str.length; ++i) {
11380
+ var cc = str.charCodeAt(i), ch = str.charAt(i);
11381
+ if(ch == quote || ch == "\\" || cc < 32 || cc == 127 || ch == "<" || ch == ">" || ch == "&") out.push("\\" + cc.toString(16) + " ");
11382
+ else out.push(ch);
11383
+ }
11384
+ return out.join("");
11385
+ }
11345
11386
  function css_font_from_style(style) {
11346
11387
  var font = style && style.font || {};
11347
11388
  var parts = [];
@@ -11349,7 +11390,8 @@ function css_font_from_style(style) {
11349
11390
  if(font.bold) parts.push("bold");
11350
11391
  parts.push(style_font_size_pt(style) + "pt");
11351
11392
  var name = style_font_family(style);
11352
- if(/[,\s'"]/.test(name)) name = '"' + String(name).replace(/"/g, '\\"') + '"';
11393
+ if(/[,\s'"]/.test(name)) name = '"' + css_string_escape(name, '"') + '"';
11394
+ else name = css_string_escape(name, '"');
11353
11395
  parts.push(name);
11354
11396
  return parts.join(" ");
11355
11397
  }
@@ -12089,6 +12131,47 @@ function parse_dxfs(t, styles, themes, opts) {
12089
12131
  });
12090
12132
  }
12091
12133
 
12134
+ function parse_tableStyles(t, styles, opts) {
12135
+ styles.TableStyles = {styles:[]};
12136
+ var tableStyle = null, pass = false;
12137
+ (t.match(tagregex)||[]).forEach(function(x) {
12138
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
12139
+ switch(tag) {
12140
+ case '<tableStyles': case '<tableStyles>':
12141
+ if(y.defaultTableStyle) styles.TableStyles.defaultTableStyle = utf8read(unescapexml(y.defaultTableStyle));
12142
+ if(y.defaultPivotStyle) styles.TableStyles.defaultPivotStyle = utf8read(unescapexml(y.defaultPivotStyle));
12143
+ break;
12144
+ case '<tableStyles/>': case '</tableStyles>': break;
12145
+ case '<tableStyle': case '<tableStyle>': case '<tableStyle/>':
12146
+ if(styles.TableStyles.styles.length >= TABLE_STYLE_MAX_TABLES) {
12147
+ tableStyle = null;
12148
+ break;
12149
+ }
12150
+ tableStyle = {
12151
+ name:utf8read(unescapexml(y.name || "")),
12152
+ pivot:y.pivot != null ? parsexmlbool(y.pivot) : false,
12153
+ table:y.table != null ? parsexmlbool(y.table) : true,
12154
+ elements:[]
12155
+ };
12156
+ styles.TableStyles.styles.push(tableStyle);
12157
+ if(tag.slice(-2) == "/>") tableStyle = null;
12158
+ break;
12159
+ case '</tableStyle>': tableStyle = null; break;
12160
+ case '<tableStyleElement': case '<tableStyleElement>': case '<tableStyleElement/>':
12161
+ if(tableStyle && tableStyle.elements.length < 64 && table_style_element_type(y.type) && y.dxfId != null) tableStyle.elements.push({
12162
+ type:y.type,
12163
+ dxfId:parseInt(y.dxfId, 10),
12164
+ size:y.size != null ? Math.max(1, parseInt(y.size, 10) || 1) : 1
12165
+ });
12166
+ break;
12167
+ case '<extLst': case '<extLst>': case '</extLst>': break;
12168
+ case '<ext': pass = true; break;
12169
+ case '</ext>': pass = false; break;
12170
+ default: if(opts && opts.WTF && !pass) throw new Error('unrecognized ' + y[0] + ' in tableStyles');
12171
+ }
12172
+ });
12173
+ }
12174
+
12092
12175
  function parse_colors(t, styles, themes, opts) {
12093
12176
  styles.Colors = {indexedColors:[], mruColors:[], themeColors:[]};
12094
12177
  var target = null, pass = false;
@@ -12167,6 +12250,7 @@ return function parse_sty_xml(data, themes, opts) {
12167
12250
  if((t=str_match_xml_ns(data, "dxfs"))) parse_dxfs(t[0], styles, themes, opts);
12168
12251
 
12169
12252
  /* 18.8.42 tableStyles CT_TableStyles ? */
12253
+ if((t=str_match_xml_ns(data, "tableStyles"))) parse_tableStyles(t[0], styles, opts);
12170
12254
  /* 18.8.11 colors CT_Colors ? */
12171
12255
  if((t=str_match_xml_ns(data, "colors"))) parse_colors(t[0], styles, themes, opts);
12172
12256
 
@@ -13330,7 +13414,7 @@ function parse_drawing_anchor(data) {
13330
13414
  function parse_drawing_text(data) {
13331
13415
  var out = [];
13332
13416
  (data.match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) {
13333
- out.push(unescapexml(t.replace(/<[^>]*>/g, "")));
13417
+ out.push(unescapexml(strip_xml_tags(t)));
13334
13418
  });
13335
13419
  return out.join("");
13336
13420
  }
@@ -16692,7 +16776,11 @@ function validate_merges(ws, opts) {
16692
16776
  errors.push({code:"E_MERGE_OVERLAP", message:"Merge ranges overlap", index:i, other:j, range:enc, otherRange:encode_range(merges[j])});
16693
16777
  }
16694
16778
  }
16695
- if(errors.length && opts && opts.WTF) throw new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16779
+ if(errors.length && opts && opts.WTF) {
16780
+ var err = new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16781
+ err.code = errors[0].code;
16782
+ throw err;
16783
+ }
16696
16784
  return errors;
16697
16785
  }
16698
16786
 
@@ -16702,6 +16790,312 @@ function check_ws(ws, sname, i) {
16702
16790
  if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
16703
16791
  }
16704
16792
  }
16793
+ var TABLE_STYLE_MAX_TABLES = 1024;
16794
+ var TABLE_STYLE_MAX_COLUMNS = 16384;
16795
+ var TABLE_STYLE_MAX_XML_LENGTH = 5 * 1024 * 1024;
16796
+ var TABLE_STYLE_ELEMENT_TYPES = {
16797
+ wholeTable:true, headerRow:true, totalRow:true,
16798
+ firstColumn:true, lastColumn:true,
16799
+ firstRowStripe:true, secondRowStripe:true,
16800
+ firstColumnStripe:true, secondColumnStripe:true,
16801
+ firstHeaderCell:true, lastHeaderCell:true,
16802
+ firstTotalCell:true, lastTotalCell:true
16803
+ };
16804
+
16805
+ function table_style_safe_key(key) {
16806
+ return key != "__proto__" && key != "constructor" && key != "prototype";
16807
+ }
16808
+
16809
+ function table_style_element_type(type) {
16810
+ return Object.prototype.hasOwnProperty.call(TABLE_STYLE_ELEMENT_TYPES, type);
16811
+ }
16812
+
16813
+ function table_style_attr(y, name) {
16814
+ if(y[name] != null) return y[name];
16815
+ return y[name.toLowerCase()];
16816
+ }
16817
+
16818
+ function table_style_bool(y, name, fallback) {
16819
+ var value = table_style_attr(y, name);
16820
+ return value == null ? fallback : parsexmlbool(value);
16821
+ }
16822
+
16823
+ function table_style_int(y, name) {
16824
+ var value = table_style_attr(y, name);
16825
+ if(value == null || value === "") return void 0;
16826
+ value = parseInt(value, 10);
16827
+ return isFinite(value) && value >= 0 ? value : void 0;
16828
+ }
16829
+
16830
+ function table_style_merge(target, source) {
16831
+ if(!source) return target;
16832
+ if(!target) target = {};
16833
+ keys(source).forEach(function(k) {
16834
+ if(!table_style_safe_key(k)) return;
16835
+ var value = source[k];
16836
+ if(value && typeof value == "object" && !Array.isArray(value)) {
16837
+ target[k] = table_style_merge(
16838
+ target[k] && typeof target[k] == "object" && !Array.isArray(target[k]) ? table_style_merge({}, target[k]) : {},
16839
+ value
16840
+ );
16841
+ } else target[k] = value;
16842
+ });
16843
+ return target;
16844
+ }
16845
+
16846
+ function table_style_color(themes, theme, tint) {
16847
+ return style_color_from_attrs({theme:String(theme), tint:String(tint || 0)}, themes);
16848
+ }
16849
+
16850
+ function table_style_fill(color) {
16851
+ return {fill:{patternType:"solid", fgColor:color}};
16852
+ }
16853
+
16854
+ function table_style_font(color, bold) {
16855
+ var font = {};
16856
+ if(color) font.color = color;
16857
+ if(bold) font.bold = 1;
16858
+ return {font:font};
16859
+ }
16860
+
16861
+ function table_style_border(side, color, style) {
16862
+ var border = {}, out = {border:border};
16863
+ border[side] = {style:style || "thin", color:color};
16864
+ return out;
16865
+ }
16866
+
16867
+ function table_style_accent(themes, index) {
16868
+ var position = (index - 1) % 7;
16869
+ /* The first style in each seven-style family is neutral. The remaining
16870
+ * six entries use the workbook's accent1..accent6 colors. */
16871
+ return table_style_color(themes, position ? 3 + position : 1, 0);
16872
+ }
16873
+
16874
+ function built_in_table_style_rules(name, themes) {
16875
+ var match = /^TableStyle(Light|Medium|Dark)(\d+)$/i.exec(name || "");
16876
+ if(!match) return null;
16877
+ var family = match[1].toLowerCase(), index = parseInt(match[2], 10);
16878
+ var maximum = family == "light" ? 21 : family == "medium" ? 28 : 11;
16879
+ if(index < 1 || index > maximum) return null;
16880
+ var accent = table_style_accent(themes, index);
16881
+ var white = table_style_color(themes, 0, 0);
16882
+ var dark = table_style_color(themes, 1, 0);
16883
+ var rules = {};
16884
+
16885
+ if(family == "light") {
16886
+ rules.headerRow = table_style_merge(
16887
+ table_style_font(accent, true),
16888
+ table_style_border("bottom", accent, "medium")
16889
+ );
16890
+ rules.totalRow = table_style_merge(
16891
+ table_style_font(accent, true),
16892
+ table_style_border("top", accent, "double")
16893
+ );
16894
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16895
+ rules.firstColumnStripe = rules.firstRowStripe;
16896
+ } else if(family == "medium") {
16897
+ var group = Math.floor((index - 1) / 7);
16898
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16899
+ rules.totalRow = table_style_merge(
16900
+ table_style_font(accent, true),
16901
+ table_style_border("top", accent, "double")
16902
+ );
16903
+ if(group == 1) {
16904
+ /* Medium 8..14 use two theme-derived body fills. This is the family
16905
+ * used by Excel's TableStyleMedium13. */
16906
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16907
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.6));
16908
+ rules.firstColumnStripe = rules.firstRowStripe;
16909
+ } else if(group == 2) {
16910
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16911
+ rules.firstColumnStripe = rules.firstRowStripe;
16912
+ rules.wholeTable = table_style_border("bottom", table_style_color(themes, accent.theme, 0.4), "thin");
16913
+ } else if(group == 3) {
16914
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16915
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.7));
16916
+ rules.firstColumnStripe = rules.firstRowStripe;
16917
+ } else {
16918
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16919
+ rules.firstColumnStripe = rules.firstRowStripe;
16920
+ }
16921
+ } else {
16922
+ rules.wholeTable = table_style_merge(table_style_fill(dark), table_style_font(white, false));
16923
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16924
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, -0.35));
16925
+ rules.firstColumnStripe = rules.firstRowStripe;
16926
+ rules.totalRow = table_style_merge(
16927
+ table_style_font(white, true),
16928
+ table_style_border("top", accent, "double")
16929
+ );
16930
+ }
16931
+
16932
+ rules.firstColumn = table_style_font(null, true);
16933
+ rules.lastColumn = table_style_font(null, true);
16934
+ return rules;
16935
+ }
16936
+
16937
+ function custom_table_style_rules(name, styles) {
16938
+ var tableStyles = styles && styles.TableStyles;
16939
+ if(!tableStyles || !tableStyles.styles) return null;
16940
+ for(var i = 0; i < tableStyles.styles.length; ++i) {
16941
+ var tableStyle = tableStyles.styles[i];
16942
+ if(tableStyle.name != name) continue;
16943
+ var rules = Object.create(null);
16944
+ (tableStyle.elements || []).forEach(function(element) {
16945
+ if(!table_style_element_type(element.type)) return;
16946
+ var dxf = styles.Dxfs && styles.Dxfs[element.dxfId];
16947
+ if(dxf) rules[element.type] = {style:dup(dxf), size:element.size || 1};
16948
+ });
16949
+ return rules;
16950
+ }
16951
+ return null;
16952
+ }
16953
+
16954
+ function parse_table_xml(data, path, themes, styles, opts) {
16955
+ if(!data || data.length > TABLE_STYLE_MAX_XML_LENGTH) return null;
16956
+ data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
16957
+ var table = {columns:[]}, column = null, pass = false;
16958
+ (data.match(tagregex)||[]).forEach(function(x) {
16959
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
16960
+ switch(tag) {
16961
+ case '<table': case '<table>':
16962
+ table.id = table_style_int(y, "id");
16963
+ table.name = utf8read(unescapexml(table_style_attr(y, "name") || ""));
16964
+ table.displayName = utf8read(unescapexml(table_style_attr(y, "displayName") || table.name));
16965
+ table.ref = table_style_attr(y, "ref") || "";
16966
+ table.headerRowCount = table_style_int(y, "headerRowCount");
16967
+ table.totalsRowCount = table_style_int(y, "totalsRowCount");
16968
+ table.totalsRowShown = table_style_bool(y, "totalsRowShown", false);
16969
+ table.headerRowDxfId = table_style_int(y, "headerRowDxfId");
16970
+ table.dataDxfId = table_style_int(y, "dataDxfId");
16971
+ table.totalsRowDxfId = table_style_int(y, "totalsRowDxfId");
16972
+ table.path = path;
16973
+ break;
16974
+ case '<tableColumn': case '<tableColumn>': case '<tableColumn/>':
16975
+ if(table.columns.length >= TABLE_STYLE_MAX_COLUMNS) {
16976
+ column = null;
16977
+ break;
16978
+ }
16979
+ column = {
16980
+ id:table_style_int(y, "id"),
16981
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16982
+ headerRowDxfId:table_style_int(y, "headerRowDxfId"),
16983
+ dataDxfId:table_style_int(y, "dataDxfId"),
16984
+ totalsRowDxfId:table_style_int(y, "totalsRowDxfId")
16985
+ };
16986
+ table.columns.push(column);
16987
+ if(tag.slice(-2) == "/>" ) column = null;
16988
+ break;
16989
+ case '</tableColumn>': column = null; break;
16990
+ case '<tableStyleInfo': case '<tableStyleInfo>': case '<tableStyleInfo/>':
16991
+ table.styleInfo = {
16992
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16993
+ showFirstColumn:table_style_bool(y, "showFirstColumn", false),
16994
+ showLastColumn:table_style_bool(y, "showLastColumn", false),
16995
+ showRowStripes:table_style_bool(y, "showRowStripes", false),
16996
+ showColumnStripes:table_style_bool(y, "showColumnStripes", false)
16997
+ };
16998
+ break;
16999
+ case '<extLst': case '<extLst>': case '</extLst>': break;
17000
+ case '<ext': pass = true; break;
17001
+ case '</ext>': pass = false; break;
17002
+ default: if(opts && opts.WTF && !pass) {
17003
+ /* Table formulas and filter metadata are intentionally preserved by
17004
+ * the raw XML parser but do not affect visual style resolution. */
17005
+ if(/^<\/?(?:tableColumns|autoFilter|sortState|calculatedColumnFormula|totalsRowFormula|xmlColumnPr)/.test(tag)) break;
17006
+ }
17007
+ }
17008
+ });
17009
+ if(!table.ref) return null;
17010
+ try {
17011
+ table.range = safe_decode_range(table.ref);
17012
+ if(table.range.s.r < 0 || table.range.s.c < 0 || table.range.e.r > 1048575 || table.range.e.c > 16383) return null;
17013
+ } catch(e) { return null; }
17014
+ var styleName = table.styleInfo && table.styleInfo.name;
17015
+ table.styleRules = custom_table_style_rules(styleName, styles) || built_in_table_style_rules(styleName, themes) || {};
17016
+ table.dxfs = styles && styles.Dxfs ? styles.Dxfs : [];
17017
+ return table;
17018
+ }
17019
+
17020
+ function parse_sheet_tables(sheet, zip, path, rels, opts, themes, styles) {
17021
+ if(!sheet || !rels || !rels['!id'] || !opts || !opts.cellStyles) return;
17022
+ var tables = [], seen = Object.create(null);
17023
+ keys(rels['!id']).forEach(function(id) {
17024
+ if(tables.length >= TABLE_STYLE_MAX_TABLES) return;
17025
+ var rel = rels['!id'][id];
17026
+ if(!rel || rel.TargetMode == "External" || typeof rel.Target != "string" || !rel.Target ||
17027
+ (rel.Type != RELS.TABLE && !/\/table$/.test(rel.Type || ""))) return;
17028
+ var tablePath = resolve_path(rel.Target, path);
17029
+ if(seen[tablePath]) return;
17030
+ seen[tablePath] = true;
17031
+ var table = parse_table_xml(getzipstr(zip, tablePath, true), tablePath, themes, styles, opts);
17032
+ if(table) tables.push(table);
17033
+ });
17034
+ if(tables.length) sheet['!tables'] = tables;
17035
+ }
17036
+
17037
+ function table_style_rule_value(rule) {
17038
+ return rule && rule.style ? rule.style : rule;
17039
+ }
17040
+
17041
+ function table_style_stripe_rule(first, second, offset) {
17042
+ var firstSize = first && first.size || 1, secondSize = second && second.size || 1;
17043
+ var period = firstSize + secondSize;
17044
+ if(!period) return null;
17045
+ return offset % period < firstSize ? first : second;
17046
+ }
17047
+
17048
+ function table_style_dxf(table, id) {
17049
+ return id == null || !table.dxfs ? null : table.dxfs[id];
17050
+ }
17051
+
17052
+ function resolve_table_cell_style(ws, row, col, baseStyle) {
17053
+ var tables = ws && ws['!tables'];
17054
+ var resolved = baseStyle ? table_style_merge({}, baseStyle) : {};
17055
+ if(!tables || !tables.length) return keys(resolved).length ? resolved : void 0;
17056
+ for(var i = 0; i < tables.length; ++i) {
17057
+ var table = tables[i], range = table.range;
17058
+ if(!range || row < range.s.r || row > range.e.r || col < range.s.c || col > range.e.c) continue;
17059
+ var rules = table.styleRules || {}, info = table.styleInfo || {};
17060
+ var rowOffset = row - range.s.r, colOffset = col - range.s.c;
17061
+ var headerRows = table.headerRowCount == null ? 1 : table.headerRowCount;
17062
+ var totalRows = table.totalsRowCount != null ? table.totalsRowCount : table.totalsRowShown ? 1 : 0;
17063
+ var dataStart = headerRows, dataEnd = range.e.r - range.s.r - totalRows;
17064
+ var isHeader = rowOffset < headerRows;
17065
+ var isTotal = totalRows > 0 && rowOffset > dataEnd;
17066
+ var dataOffset = rowOffset - dataStart;
17067
+ var column = table.columns && table.columns[colOffset];
17068
+
17069
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.wholeTable));
17070
+ if(!isHeader && !isTotal && dataOffset >= 0) {
17071
+ if(info.showRowStripes) resolved = table_style_merge(resolved, table_style_rule_value(
17072
+ table_style_stripe_rule(rules.firstRowStripe, rules.secondRowStripe, dataOffset)
17073
+ ));
17074
+ if(info.showColumnStripes) resolved = table_style_merge(resolved, table_style_rule_value(
17075
+ table_style_stripe_rule(rules.firstColumnStripe, rules.secondColumnStripe, colOffset)
17076
+ ));
17077
+ }
17078
+ if(info.showFirstColumn && col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstColumn));
17079
+ if(info.showLastColumn && col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastColumn));
17080
+ if(isHeader) {
17081
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.headerRow));
17082
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstHeaderCell));
17083
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastHeaderCell));
17084
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.headerRowDxfId));
17085
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.headerRowDxfId));
17086
+ } else if(isTotal) {
17087
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.totalRow));
17088
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstTotalCell));
17089
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastTotalCell));
17090
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.totalsRowDxfId));
17091
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.totalsRowDxfId));
17092
+ } else {
17093
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.dataDxfId));
17094
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.dataDxfId));
17095
+ }
17096
+ }
17097
+ return keys(resolved).length ? resolved : void 0;
17098
+ }
16705
17099
  function parse_ws_xml_dim(ws, s) {
16706
17100
  var d = safe_decode_range(s);
16707
17101
  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);
@@ -16710,7 +17104,25 @@ var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
16710
17104
  var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
16711
17105
  var dimregex = /"(\w*:\w*)"/;
16712
17106
  var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
16713
- var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
17107
+ function match_ws_xml_autofilter(data) {
17108
+ var paired = str_match_xml_ns(data, "autoFilter");
17109
+ if(paired) return paired[0];
17110
+ var start = 0;
17111
+ while((start = data.indexOf("<", start)) != -1) {
17112
+ var end = data.indexOf(">", start + 1);
17113
+ if(end == -1) return null;
17114
+ var tag = data.slice(start + 1, end), p = 0;
17115
+ while(p < tag.length && tag.charCodeAt(p) <= 32) ++p;
17116
+ var nameEnd = p;
17117
+ while(nameEnd < tag.length && tag.charCodeAt(nameEnd) > 32 && tag.charAt(nameEnd) != "/") ++nameEnd;
17118
+ var name = tag.slice(p, nameEnd), colon = name.indexOf(":");
17119
+ if(colon != -1) name = name.slice(colon + 1);
17120
+ var tail = tag.slice(nameEnd).trim();
17121
+ if(name == "autoFilter" && tail.charAt(tail.length - 1) == "/") return data.slice(start, end + 1);
17122
+ start = end + 1;
17123
+ }
17124
+ return null;
17125
+ }
16714
17126
  var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
16715
17127
  var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
16716
17128
 
@@ -16759,8 +17171,8 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16759
17171
  if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
16760
17172
 
16761
17173
  /* 18.3.1.2 autoFilter CT_AutoFilter */
16762
- var afilter = data2.match(afregex);
16763
- if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
17174
+ var afilter = match_ws_xml_autofilter(data2);
17175
+ if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter);
16764
17176
 
16765
17177
  /* 18.3.1.55 mergeCells CT_MergeCells */
16766
17178
  var merges = [];
@@ -16798,7 +17210,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16798
17210
  if(columns.length > 0) s["!cols"] = columns;
16799
17211
  if(merges.length > 0) {
16800
17212
  s["!merges"] = merges;
16801
- var mergeErrors = validate_merges(s, {WTF: !!(opts && (opts.WTF || opts.validateMerges))});
17213
+ var mergeErrors = validate_merges(s, {WTF: !!(opts && opts.validateMerges)});
16802
17214
  if(mergeErrors.length) s["!mergeErrors"] = mergeErrors;
16803
17215
  }
16804
17216
  if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
@@ -16913,7 +17325,8 @@ function parse_ws_xml_cols(columns, cols) {
16913
17325
  var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
16914
17326
  if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
16915
17327
  delete coll.min; delete coll.max; coll.width = +coll.width;
16916
- /* OOXML widths share the workbook Normal-font MDW; do not infer a different scale per sheet. */
17328
+ /* OOXML widths share the workbook Normal-font MDW. Do not infer it from
17329
+ * one ambiguous stored width or leak another worksheet's scale. */
16917
17330
  if(!seencol && coll.width) { seencol = true; MDW = DEF_MDW; }
16918
17331
  process_col(coll);
16919
17332
  while(colm <= colM) columns[colm++] = dup(coll);
@@ -17285,7 +17698,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17285
17698
  'xmlns:r': XMLNS.r
17286
17699
  })];
17287
17700
  var s = wb.SheetNames[idx], sidx = 0, rdata = "";
17288
- var ws = wb.Sheets[s];
17701
+ var ws = sheet_map_get(wb.Sheets, s);
17289
17702
  if(ws == null) ws = {};
17290
17703
  var ref = ws['!ref'] || 'A1';
17291
17704
  var range = safe_decode_range(ref);
@@ -17336,7 +17749,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17336
17749
  /* customSheetViews */
17337
17750
 
17338
17751
  if(ws['!merges'] != null && ws['!merges'].length > 0) {
17339
- validate_merges(ws, {WTF:true});
17752
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
17340
17753
  o[o.length] = (write_ws_xml_merges(ws['!merges']));
17341
17754
  }
17342
17755
 
@@ -18398,7 +18811,7 @@ function write_SHEETPROTECT(ba, ws) {
18398
18811
 
18399
18812
  function write_ws_bin(idx, opts, wb, rels) {
18400
18813
  var ba = buf_array();
18401
- var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
18814
+ var s = wb.SheetNames[idx], ws = sheet_map_get(wb.Sheets, s) || {};
18402
18815
  var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
18403
18816
  var r = safe_decode_range(ws['!ref'] || "A1");
18404
18817
  if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
@@ -18466,7 +18879,7 @@ function parse_Cache(data) {
18466
18879
  /* 21.2.2.71 formatCode CT_Xstring */
18467
18880
  var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
18468
18881
 
18469
- (str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
18882
+ (str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = strip_xml_tags(F); });
18470
18883
 
18471
18884
  return [col, nf, f];
18472
18885
  }
@@ -18483,7 +18896,7 @@ function parse_chart_cache(data) {
18483
18896
  return {values:s[0], formatCode:s[1], formula:s[2]};
18484
18897
  }
18485
18898
  var f = (str_match_ng(data, "<c:f>", "</c:f>")||[])[0];
18486
- return {values:[], formula:f ? f.replace(/<[^<>]*>/g,"") : void 0};
18899
+ return {values:[], formula:f ? strip_xml_tags(f) : void 0};
18487
18900
  }
18488
18901
 
18489
18902
  function parse_chart_tx(data) {
@@ -18515,7 +18928,7 @@ function parse_chart_title(data) {
18515
18928
  var title = str_match_xml_ns(data, "title");
18516
18929
  if(!title) return "";
18517
18930
  var out = [];
18518
- (title[0].match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) { out.push(unescapexml(t.replace(/<[^>]*>/g, ""))); });
18931
+ (title[0].match(/<a:t\b[^>]*>[\s\S]*?<\/a:t>/g)||[]).forEach(function(t) { out.push(unescapexml(strip_xml_tags(t))); });
18519
18932
  return out.join("");
18520
18933
  }
18521
18934
 
@@ -18820,9 +19233,12 @@ function check_wb(wb) {
18820
19233
  if(!wb.SheetNames.length) throw new Error("Workbook is empty");
18821
19234
  var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
18822
19235
  check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
18823
- for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
19236
+ for(var i = 0; i < wb.SheetNames.length; ++i) {
19237
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
19238
+ check_ws(ws, wb.SheetNames[i], i);
19239
+ }
18824
19240
  wb.SheetNames.forEach(function(n, i) {
18825
- var ws = wb.Sheets[n];
19241
+ var ws = sheet_map_get(wb.Sheets, n);
18826
19242
  if(!ws || !ws["!autofilter"]) return;
18827
19243
  var DN;
18828
19244
  if(!wb.Workbook) wb.Workbook = {};
@@ -19607,7 +20023,7 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o
19607
20023
  break;
19608
20024
  case 'String':
19609
20025
  cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
19610
- cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
20026
+ cell.v = (xml.indexOf("<") > -1 ? strip_xml_tags(unescapexml(ss||xml)) : cell.r); // todo: BR etc
19611
20027
  break;
19612
20028
  case 'DateTime':
19613
20029
  if(xml.slice(-1) != "Z") xml += "Z";
@@ -19702,7 +20118,7 @@ function parse_xlml_xml(d, _opts) {
19702
20118
  var Rn;
19703
20119
  var state = [], tmp;
19704
20120
  if(DENSE != null && opts.dense == null) opts.dense = DENSE;
19705
- var sheets = {}, sheetnames = [], cursheet = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
20121
+ var sheets = sheet_map_new(), sheetnames = [], cursheet = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
19706
20122
  var cell = ({}), row = {};// eslint-disable-line no-unused-vars
19707
20123
  var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
19708
20124
  var c = 0, r = 0;
@@ -19808,7 +20224,7 @@ for(var cma = c; cma <= cc; ++cma) {
19808
20224
  if(merges.length) cursheet["!merges"] = merges;
19809
20225
  if(cstys.length > 0) cursheet["!cols"] = cstys;
19810
20226
  if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
19811
- sheets[sheetname] = cursheet;
20227
+ sheet_map_set(sheets, sheetname, cursheet);
19812
20228
  } else {
19813
20229
  refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
19814
20230
  r = c = 0;
@@ -20709,7 +21125,7 @@ function write_ws_xlml_table(ws, opts, idx, wb) {
20709
21125
  function write_ws_xlml(idx, opts, wb) {
20710
21126
  var o = [];
20711
21127
  var s = wb.SheetNames[idx];
20712
- var ws = wb.Sheets[s];
21128
+ var ws = sheet_map_get(wb.Sheets, s);
20713
21129
 
20714
21130
  var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
20715
21131
  if(t.length > 0) o.push("<Names>" + t + "</Names>");
@@ -20941,7 +21357,7 @@ var parse_BIFFSurface = make_BIFFChartType("surfaceChart");
20941
21357
  // 2.3.2
20942
21358
  function parse_workbook(blob, options) {
20943
21359
  var wb = ({opts:{}});
20944
- var Sheets = {};
21360
+ var Sheets = sheet_map_new();
20945
21361
  if(DENSE != null && options.dense == null) options.dense = DENSE;
20946
21362
  var out = ({}); if(options.dense) out["!data"] = [];
20947
21363
  var Directory = {};
@@ -21236,7 +21652,7 @@ function parse_workbook(blob, options) {
21236
21652
  };
21237
21653
  var finalize_sheet_visuals = function finalizesheetvisuals(ws) {
21238
21654
  if(ws["!merges"] && ws["!merges"].length) {
21239
- var mergeErrors = validate_merges(ws, {WTF: !!(options && (options.WTF || options.validateMerges))});
21655
+ var mergeErrors = validate_merges(ws, {WTF: !!(options && options.validateMerges)});
21240
21656
  if(mergeErrors.length) ws["!mergeErrors"] = mergeErrors;
21241
21657
  }
21242
21658
  if(drawings && (drawings.images.length || drawings.shapes.length || drawings.charts.length || drawings.raw.length)) ws["!drawings"] = drawings;
@@ -21382,7 +21798,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
21382
21798
  finalize_sheet_visuals(out);
21383
21799
  Workbook.Sheets.push(wsprops);
21384
21800
  }
21385
- if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
21801
+ if(cur_sheet === "") Preamble = out; else sheet_map_set(Sheets, cur_sheet, out);
21386
21802
  out = ({}); if(options.dense) out["!data"] = [];
21387
21803
  } break;
21388
21804
  case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
@@ -21681,10 +22097,13 @@ if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
21681
22097
  if(!wb.SheetNames.length && Preamble["!ref"]) {
21682
22098
  wb.SheetNames.push("Sheet1");
21683
22099
  /*jshint -W069 */
21684
- if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
22100
+ if(wb.Sheets) sheet_map_set(wb.Sheets, "Sheet1", Preamble);
21685
22101
  /*jshint +W069 */
21686
22102
  } else wb.Preamble=Preamble;
21687
- if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
22103
+ if(wb.Sheets) FilterDatabases.forEach(function(r,i) {
22104
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
22105
+ if(ws) ws['!autofilter'] = r;
22106
+ });
21688
22107
  wb.Strings = sst;
21689
22108
  wb.SSF = dup(table_fmt);
21690
22109
  if(opts.enc) wb.Encryption = opts.enc;
@@ -23309,7 +23728,7 @@ function write_biff2_buf(wb, opts) {
23309
23728
  o.cellXfs = [{numFmtId: 0}];
23310
23729
  o._BIFF2FmtTable = ["General"]; o._Fonts = [];
23311
23730
  var body = buf_array();
23312
- write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
23731
+ write_ws_biff2(body, sheet_map_get(wb.Sheets, wb.SheetNames[idx]), idx, o, wb);
23313
23732
 
23314
23733
  o._BIFF2FmtTable.forEach(function(f) {
23315
23734
  if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
@@ -23719,7 +24138,7 @@ function write_ws_biff8_cell(ba, cell, R, C, opts, date1904) {
23719
24138
  /* [MS-XLS] 2.1.7.20.5 */
23720
24139
  function write_ws_biff8(idx, opts, wb) {
23721
24140
  var ba = buf_array();
23722
- var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
24141
+ var s = wb.SheetNames[idx], ws = sheet_map_get(wb.Sheets, s) || {};
23723
24142
  var _WB = ((wb||{}).Workbook||{});
23724
24143
  var _sheet = ((_WB.Sheets||[])[idx]||{});
23725
24144
  var dense = ws["!data"] != null;
@@ -23788,7 +24207,7 @@ function write_ws_biff8(idx, opts, wb) {
23788
24207
  if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
23789
24208
  /* ... */
23790
24209
  if(b8 && (ws['!merges']||[]).length) {
23791
- validate_merges(ws, {WTF:true});
24210
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
23792
24211
  write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
23793
24212
  }
23794
24213
  /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
@@ -23918,7 +24337,7 @@ function write_biff8_buf(wb, opts) {
23918
24337
 
23919
24338
  function write_biff_buf(wb, opts) {
23920
24339
  for(var i = 0; i <= wb.SheetNames.length; ++i) {
23921
- var ws = wb.Sheets[wb.SheetNames[i]];
24340
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
23922
24341
  if(!ws || !ws["!ref"]) continue;
23923
24342
  var range = decode_range(ws["!ref"]);
23924
24343
  if(range.e.c > 255) { // note: 255 is IV
@@ -24000,15 +24419,66 @@ function html_to_sheet(str, _opts) {
24000
24419
  return ws;
24001
24420
  }
24002
24421
 
24003
- function cssesc(x) { return escapexml(String(x).replace(/"/g, "'")); }
24004
24422
  function css_color(color) {
24005
24423
  if(!color) return "";
24006
- if(color.rgb) return "#" + String(color.rgb).slice(-6);
24424
+ if(color.rgb && /^[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?$/.test(String(color.rgb))) return "#" + String(color.rgb).slice(-6);
24007
24425
  return "";
24008
24426
  }
24009
24427
  function css_font_family(name) {
24010
24428
  if(!name) return "";
24011
- return "'" + cssesc(name).replace(/'/g, "\\'") + "'";
24429
+ return "'" + css_string_escape(name, "'") + "'";
24430
+ }
24431
+
24432
+ function html_attr_escape(value) {
24433
+ return String(value).replace(/[&<>"']/g, function(ch) {
24434
+ return ch == "&" ? "&amp;" : ch == "<" ? "&lt;" : ch == ">" ? "&gt;" : ch == '"' ? "&quot;" : "&#39;";
24435
+ });
24436
+ }
24437
+ function html_writextag(tag, content, attrs) {
24438
+ var out = ["<", tag];
24439
+ if(attrs) keys(attrs).forEach(function(key) { out.push(" ", key, '="', html_attr_escape(attrs[key]), '"'); });
24440
+ if(content == null) { out.push("/>"); return out.join(""); }
24441
+ out.push(">", content, "</", tag, ">");
24442
+ return out.join("");
24443
+ }
24444
+ function safe_html_href(value) {
24445
+ var href = String(value == null ? "" : value).trim();
24446
+ if(!href || href.slice(0, 2) == "//") return null;
24447
+ var colon = href.indexOf(":"), prefix = colon == -1 ? "" : href.slice(0, colon), compact = "";
24448
+ for(var i = 0; i < prefix.length; ++i) if(prefix.charCodeAt(i) > 32 && prefix.charCodeAt(i) != 127) compact += prefix.charAt(i);
24449
+ if(colon != -1 && !/^(?:https?|mailto|tel)$/i.test(compact)) return null;
24450
+ return href;
24451
+ }
24452
+ function safe_html_image_src(value) {
24453
+ var src = String(value == null ? "" : value);
24454
+ return /^data:image\/[A-Za-z0-9.+-]+;base64,[A-Za-z0-9+/=\r\n]+$/.test(src) ? src : null;
24455
+ }
24456
+ function sanitize_cell_html(value) {
24457
+ var html = String(value == null ? "" : value), out = [], pos = 0;
24458
+ while(pos < html.length) {
24459
+ var start = html.indexOf("<", pos);
24460
+ if(start == -1) { out.push(html.slice(pos)); break; }
24461
+ out.push(html.slice(pos, start));
24462
+ var end = html.indexOf(">", start + 1);
24463
+ if(end == -1) { out.push("&lt;", html.slice(start + 1)); break; }
24464
+ var raw = html.slice(start + 1, end).trim(), lower = raw.toLowerCase();
24465
+ if(/^(?:\/?(?:b|i|s|sup|sub)|br\s*\/?)$/.test(lower)) out.push("<", lower == "br" ? "br/" : lower, ">");
24466
+ else if(lower == "/span") out.push("</span>");
24467
+ else if(lower.slice(0, 12) == 'span style="' && raw.charAt(raw.length - 1) == '"') {
24468
+ var declarations = raw.slice(12, -1).split(";"), safe = [];
24469
+ declarations.forEach(function(decl) {
24470
+ var colon = decl.indexOf(":"), key = colon == -1 ? "" : decl.slice(0, colon).trim().toLowerCase(), val = colon == -1 ? "" : decl.slice(colon + 1).trim().toLowerCase();
24471
+ if(key == "text-decoration" && val == "underline") safe.push("text-decoration:underline");
24472
+ else if(key == "text-underline-style" && /^(?:single|double|single-accounting|double-accounting)$/.test(val)) safe.push("text-underline-style:" + val);
24473
+ else if(key == "font-size" && /^\d+(?:\.\d+)?pt$/.test(val)) safe.push("font-size:" + val);
24474
+ else if(key == "text-effect" && val == "outline") safe.push("text-effect:outline");
24475
+ else if(key == "text-shadow" && val == "auto") safe.push("text-shadow:auto");
24476
+ });
24477
+ out.push('<span style="', safe.join(";"), safe.length ? ";" : "", '">');
24478
+ } else out.push(html_attr_escape(html.slice(start, end + 1)));
24479
+ pos = end + 1;
24480
+ }
24481
+ return out.join("");
24012
24482
  }
24013
24483
  function html_border_style(style) {
24014
24484
  switch(style) {
@@ -24037,7 +24507,8 @@ function html_cell_style(cell, opts) {
24037
24507
  var s = cell.s, css = [];
24038
24508
  var font = s.font || {};
24039
24509
  if(font.name) css.push("font-family:" + css_font_family(font.name));
24040
- if(font.sz) css.push("font-size:" + font.sz + "pt");
24510
+ var fontSize = +font.sz;
24511
+ if(isFinite(fontSize) && fontSize > 0) css.push("font-size:" + Math.min(fontSize, 409) + "pt");
24041
24512
  if(font.bold) css.push("font-weight:bold");
24042
24513
  if(font.italic) css.push("font-style:italic");
24043
24514
  var deco = [];
@@ -24050,8 +24521,9 @@ function html_cell_style(cell, opts) {
24050
24521
  if(fill.patternType != "none" && fill.patternType != "gray125") fillColor = css_color(fill.fgColor) || css_color(fill.bgColor);
24051
24522
  if(fillColor) css.push("background-color:" + fillColor);
24052
24523
  var alignment = s.alignment || {};
24053
- if(alignment.horizontal) css.push("text-align:" + alignment.horizontal);
24054
- if(alignment.vertical) css.push("vertical-align:" + alignment.vertical);
24524
+ if(/^(?:left|right|center|justify|fill|distributed)$/.test(alignment.horizontal || "")) css.push("text-align:" + alignment.horizontal);
24525
+ var vertical = alignment.vertical == "center" ? "middle" : alignment.vertical;
24526
+ if(/^(?:top|middle|bottom|baseline)$/.test(vertical || "")) css.push("vertical-align:" + vertical);
24055
24527
  if(alignment.textRotation != null && alignment.textRotation !== 0) {
24056
24528
  var deg = alignment.textRotation == 255 ? 90 : alignment.textRotation > 90 ? 90 - alignment.textRotation : alignment.textRotation;
24057
24529
  css.push("transform:rotate(" + deg + "deg)");
@@ -24124,13 +24596,14 @@ function make_html_row(ws, r, R, o) {
24124
24596
  if(cols[C] && cols[C].s) extend_style_obj(inherited, cols[C].s);
24125
24597
  if(row && row.s) extend_style_obj(inherited, row.s);
24126
24598
  if(cell && cell.s) extend_style_obj(inherited, cell.s);
24599
+ inherited = resolve_table_cell_style(ws, R, C, inherited) || inherited;
24127
24600
  if(keys(inherited).length) {
24128
24601
  stylecell = cell ? dup(cell) : {t:'z'};
24129
24602
  stylecell.s = inherited;
24130
24603
  }
24131
24604
  }
24132
24605
  /* TODO: html entities */
24133
- var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
24606
+ var w = (cell && cell.v != null) && (cell.h ? sanitize_cell_html(cell.h) : escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
24134
24607
  sp = ({});
24135
24608
  if(RS > 1) sp.rowspan = RS;
24136
24609
  if(CS > 1) sp.colspan = CS;
@@ -24138,17 +24611,18 @@ function make_html_row(ws, r, R, o) {
24138
24611
  else if(cell) {
24139
24612
  sp["data-t"] = cell && cell.t || 'z';
24140
24613
  // note: data-v is unaffected by the timezone interpretation
24141
- if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
24614
+ if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
24142
24615
  if(cell.z != null) sp["data-z"] = cell.z;
24143
- if(cell.f != null) sp["data-f"] = escapehtml(cell.f);
24144
- 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>';
24616
+ if(cell.f != null) sp["data-f"] = cell.f;
24617
+ var href = cell.l && safe_html_href(cell.l.Target);
24618
+ if(href) w = '<a href="' + html_attr_escape(href) +'">' + w + '</a>';
24145
24619
  }
24146
24620
  var cstyle = html_cell_style(stylecell, o);
24147
24621
  var lstyle = html_cell_layout_style(stylecell, o, C, CS, cols);
24148
24622
  if(lstyle) cstyle = cstyle ? cstyle + ";" + lstyle : lstyle;
24149
24623
  if(cstyle) sp.style = cstyle;
24150
24624
  sp.id = (o.id || "sjs") + "-" + coord;
24151
- oo.push(writextag('td', w, sp));
24625
+ oo.push(html_writextag('td', w, sp));
24152
24626
  }
24153
24627
  var rsp = ({}), rstyle = [];
24154
24628
  if(row) {
@@ -24156,7 +24630,7 @@ function make_html_row(ws, r, R, o) {
24156
24630
  if(o.browserPixels) rstyle.push("height:" + html_row_height(row) + "px");
24157
24631
  }
24158
24632
  if(rstyle.length) rsp.style = rstyle.join(";");
24159
- return writextag('tr', oo.join(""), rsp);
24633
+ return html_writextag('tr', oo.join(""), rsp);
24160
24634
  }
24161
24635
 
24162
24636
  var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
@@ -24292,8 +24766,10 @@ function render_html_drawings(ws, opts) {
24292
24766
  var out = [], drawings = ws["!drawings"] || {}, charts = ws["!charts"] || [];
24293
24767
  if(opts && opts.drawings && drawings.images) drawings.images.forEach(function(img) {
24294
24768
  if(!img || !img.dataURI) return;
24769
+ var src = safe_html_image_src(img.dataURI);
24770
+ if(!src) return;
24295
24771
  var pos = html_anchor_pos(ws, img.anchor, opts);
24296
- out.push('<img class="sjs-drawing-image" src="' + img.dataURI + '" style="' + html_abs_style(pos) + '"/>');
24772
+ out.push('<img class="sjs-drawing-image" src="' + html_attr_escape(src) + '" style="' + html_abs_style(pos) + '"/>');
24297
24773
  });
24298
24774
  if(opts && opts.charts) charts.forEach(function(chart) {
24299
24775
  var pos = html_anchor_pos(ws, chart.anchor, opts);
@@ -24308,7 +24784,7 @@ function make_html_preamble(ws, R, o) {
24308
24784
  if(o && o.id) tattr.id = o.id;
24309
24785
  if(o && (o.browserPixels || o.autoFit)) tstyle.push("border-collapse:collapse;table-layout:fixed");
24310
24786
  if(tstyle.length) tattr.style = tstyle.join(";");
24311
- var table = writextag("table", "", tattr).replace(/<\/table>$/, "");
24787
+ var table = html_writextag("table", "", tattr).replace(/<\/table>$/, "");
24312
24788
  var cols = o && o._htmlCols || ws["!cols"];
24313
24789
  if(o && (o.browserPixels || o.autoFit) && cols) {
24314
24790
  out.push("<colgroup>");
@@ -24316,7 +24792,7 @@ function make_html_preamble(ws, R, o) {
24316
24792
  var col = cols[C], style = [];
24317
24793
  style.push("width:" + html_col_width(col) + "px");
24318
24794
  if(col && col.hidden) style.push("display:none");
24319
- out.push(writextag("col", null, {style:style.join(";")}));
24795
+ out.push(html_writextag("col", null, {style:style.join(";")}));
24320
24796
  }
24321
24797
  out.push("</colgroup>");
24322
24798
  }
@@ -24483,7 +24959,7 @@ function parse_text_p(text) {
24483
24959
  .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
24484
24960
  .replace(/<text:tab[^<>]*\/>/g,"\t")
24485
24961
  .replace(/<text:line-break\/>/g,"\n");
24486
- var v = unescapexml(fixed.replace(/<[^<>]*>/g,""));
24962
+ var v = unescapexml(strip_xml_tags(fixed));
24487
24963
 
24488
24964
  return [v];
24489
24965
  }
@@ -24720,7 +25196,7 @@ function parse_content_xml(d, _opts, _nfm) {
24720
25196
  var nfidx, NF = "", pidx = 0;
24721
25197
  var sheetag;
24722
25198
  var rowtag;
24723
- var Sheets = {}, SheetNames = [];
25199
+ var Sheets = sheet_map_new(), SheetNames = [];
24724
25200
  var ws = ({}); if(opts.dense) ws["!data"] = [];
24725
25201
  var Rn, q;
24726
25202
  var ctag = ({value:""}), ctag2 = ({});
@@ -24757,7 +25233,7 @@ function parse_content_xml(d, _opts, _nfm) {
24757
25233
  sheetag.name = sheetag['名称'] || sheetag.name;
24758
25234
  if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
24759
25235
  SheetNames.push(sheetag.name);
24760
- Sheets[sheetag.name] = ws;
25236
+ sheet_map_set(Sheets, sheetag.name, ws);
24761
25237
  WB.Sheets.push({
24762
25238
  /* TODO: CodeName */
24763
25239
  Hidden: (tstyles[sheetag["style-name"]] && tstyles[sheetag["style-name"]]["display"] ? (parsexmlbool(tstyles[sheetag["style-name"]]["display"]) ? 0 : 1) : 0)
@@ -25113,7 +25589,9 @@ function parse_content_xml(d, _opts, _nfm) {
25113
25589
  if(Rn[1]==='/') break;
25114
25590
  try {
25115
25591
  _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
25116
- Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
25592
+ if(Object.prototype.hasOwnProperty.call(Sheets, _Ref[0]) && Sheets[_Ref[0]]) {
25593
+ Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
25594
+ }
25117
25595
  } catch(e) {/* empty */}
25118
25596
  break;
25119
25597
 
@@ -25623,7 +26101,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25623
26101
 
25624
26102
  /* column styles */
25625
26103
  var cidx = 0;
25626
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
26104
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25627
26105
  if(!ws) return;
25628
26106
  if(ws["!cols"]) {
25629
26107
  for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
@@ -25642,7 +26120,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25642
26120
 
25643
26121
  /* row styles */
25644
26122
  var ridx = 0;
25645
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
26123
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25646
26124
  if(!ws) return;
25647
26125
  if(ws["!rows"]) {
25648
26126
  for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
@@ -25675,7 +26153,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25675
26153
  /* number formats, table cells, text */
25676
26154
  var nfs = {};
25677
26155
  var nfi = 69;
25678
- wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
26156
+ wb.SheetNames.map(function(n) { return sheet_map_get(wb.Sheets, n); }).forEach(function(ws) {
25679
26157
  if(!ws) return;
25680
26158
  var dense = (ws["!data"] != null);
25681
26159
  if(!ws["!ref"]) return;
@@ -25758,7 +26236,7 @@ var write_content_ods = /* @__PURE__ */(function() {
25758
26236
  o.push(' <office:body>\n');
25759
26237
  o.push(' <office:spreadsheet>\n');
25760
26238
  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');
25761
- 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));
26239
+ 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));
25762
26240
  if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
25763
26241
  o.push(' </office:spreadsheet>\n');
25764
26242
  o.push(' </office:body>\n');
@@ -25810,7 +26288,6 @@ function write_ods(wb, opts) {
25810
26288
 
25811
26289
  return zip;
25812
26290
  }
25813
-
25814
26291
  /*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
25815
26292
  var subarray = function() {
25816
26293
  try {
@@ -27328,7 +27805,7 @@ function write_numbers_iwa(wb, opts) {
27328
27805
  docroot = numbers_iwa_find(cfb, deps, 1);
27329
27806
  sheetrefs = mappa(parse_shallow(docroot.messages[0].data)[1], parse_TSP_Reference);
27330
27807
  }
27331
- write_numbers_ws(cfb, deps, wb.Sheets[name], name, idx, sheetrefs[idx]);
27808
+ write_numbers_ws(cfb, deps, sheet_map_get(wb.Sheets, name), name, idx, sheetrefs[idx]);
27332
27809
  });
27333
27810
  return cfb;
27334
27811
  }
@@ -28246,7 +28723,8 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28246
28723
  case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
28247
28724
  default: throw new Error("Unrecognized sheet type " + stype);
28248
28725
  }
28249
- sheets[sheet] = _ws;
28726
+ if(stype == "sheet") parse_sheet_tables(_ws, zip, path, sheetRels[sheet], opts, themes, styles);
28727
+ sheet_map_set(sheets, sheet, _ws);
28250
28728
 
28251
28729
  /* scan rels for comments and threaded comments */
28252
28730
  var comments = [], tcomments = [];
@@ -28266,7 +28744,9 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28266
28744
  if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
28267
28745
  if(stype == "sheet") parse_sheet_drawing(_ws, stype, zip, path, idx, opts, wb);
28268
28746
  parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
28269
- } catch(e) { if(opts.WTF) throw e; }
28747
+ } catch(e) {
28748
+ if(opts.WTF || (opts.validateMerges && e && /^E_MERGE_/.test(e.code))) throw e;
28749
+ }
28270
28750
  }
28271
28751
 
28272
28752
  function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
@@ -28369,7 +28849,7 @@ function parse_zip(zip, opts) {
28369
28849
  if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
28370
28850
  if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
28371
28851
  }
28372
- sheets = {};
28852
+ sheets = sheet_map_new();
28373
28853
 
28374
28854
  var deps = {};
28375
28855
  if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
@@ -28569,7 +29049,7 @@ f = "docProps/app.xml";
28569
29049
 
28570
29050
  for(rId=1;rId <= wb.SheetNames.length; ++rId) {
28571
29051
  var wsrels = {'!id':{}};
28572
- var ws = wb.Sheets[wb.SheetNames[rId-1]];
29052
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[rId-1]);
28573
29053
  var _type = (ws || {})["!type"] || "sheet";
28574
29054
  switch(_type) {
28575
29055
  case "chart":
@@ -28724,7 +29204,7 @@ f = "docProps/app.xml";
28724
29204
 
28725
29205
  for(rId=1;rId <= wb.SheetNames.length; ++rId) {
28726
29206
  var wsrels = {'!id':{}};
28727
- var ws = wb.Sheets[wb.SheetNames[rId-1]];
29207
+ var ws = sheet_map_get(wb.Sheets, wb.SheetNames[rId-1]);
28728
29208
  var _type = (ws || {})["!type"] || "sheet";
28729
29209
  switch(_type) {
28730
29210
  case "chart":
@@ -28820,7 +29300,6 @@ f = "docProps/app.xml";
28820
29300
  delete opts.revssf; delete opts.ssf;
28821
29301
  return zip;
28822
29302
  }
28823
-
28824
29303
  function firstbyte(f,o) {
28825
29304
  var x = "";
28826
29305
  switch((o||{}).type || "base64") {
@@ -29089,18 +29568,18 @@ function writeSync(wb, opts) {
29089
29568
  case 'xml':
29090
29569
  case 'xlml': return write_string_type(write_xlml(wb, o), o);
29091
29570
  case 'slk':
29092
- case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
29571
+ case 'sylk': return write_string_type(SYLK.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o, wb), o);
29093
29572
  case 'htm':
29094
- case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
29095
- case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
29096
- case 'csv': return write_string_type(sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o), o, "\ufeff");
29097
- case 'dif': return write_string_type(DIF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
29098
- case 'dbf': return write_binary_type(DBF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
29099
- case 'prn': return write_string_type(PRN.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
29100
- case 'rtf': return write_string_type(sheet_to_rtf(wb.Sheets[wb.SheetNames[idx]], o), o);
29101
- case 'eth': return write_string_type(ETH.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
29573
+ case 'html': return write_string_type(sheet_to_html(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29574
+ case 'txt': return write_stxt_type(sheet_to_txt(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29575
+ case 'csv': return write_string_type(sheet_to_csv(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o, "\ufeff");
29576
+ case 'dif': return write_string_type(DIF.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29577
+ case 'dbf': return write_binary_type(DBF.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29578
+ case 'prn': return write_string_type(PRN.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29579
+ case 'rtf': return write_string_type(sheet_to_rtf(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29580
+ case 'eth': return write_string_type(ETH.from_sheet(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29102
29581
  case 'fods': return write_string_type(write_ods(wb, o), o);
29103
- case 'wk1': return write_binary_type(WK_.sheet_to_wk1(wb.Sheets[wb.SheetNames[idx]], o), o);
29582
+ case 'wk1': return write_binary_type(WK_.sheet_to_wk1(sheet_map_get(wb.Sheets, wb.SheetNames[idx]), o), o);
29104
29583
  case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
29105
29584
  case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
29106
29585
  case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
@@ -29360,6 +29839,7 @@ function sheet_add_json(_ws, js, opts) {
29360
29839
  var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
29361
29840
  _R = _origin.r; _C = _origin.c;
29362
29841
  }
29842
+ if(!isFinite(_R) || _R !== Math.floor(_R) || _R < -1 || !isFinite(_C) || _C !== Math.floor(_C) || _C < 0) throw new Error("Invalid origin");
29363
29843
  }
29364
29844
  var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
29365
29845
  if(ws['!ref']) {
@@ -29451,7 +29931,7 @@ function wb_sheet_idx(wb, sh) {
29451
29931
 
29452
29932
  /* simple blank or single-sheet workbook object */
29453
29933
  function book_new(ws, wsname) {
29454
- var wb = { SheetNames: [], Sheets: {} };
29934
+ var wb = { SheetNames: [], Sheets: sheet_map_new() };
29455
29935
  if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
29456
29936
  return wb;
29457
29937
  }
@@ -29471,7 +29951,7 @@ function book_append_sheet(wb, ws, name, roll) {
29471
29951
  if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
29472
29952
 
29473
29953
  wb.SheetNames.push(name);
29474
- wb.Sheets[name] = ws;
29954
+ sheet_map_set(wb.Sheets, name, ws);
29475
29955
  return name;
29476
29956
  }
29477
29957
 
@@ -29538,7 +30018,6 @@ function sheet_set_array_formula(ws, range, formula, dynamic) {
29538
30018
  ws["!ref"] = encode_range(wsr);
29539
30019
  return ws;
29540
30020
  }
29541
-
29542
30021
  var utils = {
29543
30022
  encode_col: encode_col,
29544
30023
  encode_row: encode_row,
@@ -29568,6 +30047,7 @@ var utils = {
29568
30047
  measure_text_width: measure_text_width,
29569
30048
  auto_fit_columns: auto_fit_columns,
29570
30049
  autofit_columns: auto_fit_columns,
30050
+ resolve_table_cell_style: resolve_table_cell_style,
29571
30051
  col_width_to_px: width2px,
29572
30052
  px_to_col_width: function(px) { return char2width(px2char(px)); },
29573
30053
  row_height_to_px: pt2px_browser,
@@ -29695,7 +30175,7 @@ function write_json_stream(sheet, opts) {
29695
30175
  if ((rowinfo[R]||{}).hidden) {
29696
30176
  ++R;
29697
30177
  continue;
29698
- };
30178
+ }
29699
30179
  var row = make_json_row(sheet, r, R, cols, header, hdr, o);
29700
30180
  ++R;
29701
30181
  if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
@@ -29724,7 +30204,7 @@ function write_xlml_stream(wb, o) {
29724
30204
 
29725
30205
  /* do one pass to determine styles since they must be added before tables */
29726
30206
  wb.SheetNames.forEach(function(n) {
29727
- var ws = wb.Sheets[n];
30207
+ var ws = sheet_map_get(wb.Sheets, n);
29728
30208
  if(!ws || !ws["!ref"]) return;
29729
30209
  var range = decode_range(ws["!ref"]);
29730
30210
  var dense = ws["!data"] != null;
@@ -29744,7 +30224,7 @@ function write_xlml_stream(wb, o) {
29744
30224
  });
29745
30225
  var sty = write_sty_xlml(wb, opts);
29746
30226
 
29747
- var stage = 0, wsidx = 0, ws = wb.Sheets[wb.SheetNames[wsidx]], range = safe_decode_range(ws), R = -1, T = false;
30227
+ var stage = 0, wsidx = 0, ws = sheet_map_get(wb.Sheets, wb.SheetNames[wsidx]), range = safe_decode_range(ws), R = -1, T = false;
29748
30228
 
29749
30229
  var marr = [], mi = 0, dense = false, darr = [], addr = {r:0,c:0};
29750
30230
 
@@ -29784,7 +30264,7 @@ function write_xlml_stream(wb, o) {
29784
30264
 
29785
30265
  stream.push("<Worksheet" + wxt_helper({ "ss:Name": escapexml(wb.SheetNames[wsidx])}) + ">");
29786
30266
 
29787
- ws = wb.Sheets[wb.SheetNames[wsidx]];
30267
+ ws = sheet_map_get(wb.Sheets, wb.SheetNames[wsidx]);
29788
30268
  if(!ws) { stream.push("</Worksheet>"); return void ++wsidx; }
29789
30269
 
29790
30270
  var names = write_ws_xlml_names(ws, opts, wsidx, wb);