styled-exceljs 0.21.3 → 0.21.5

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.
@@ -160,7 +160,7 @@ var DO_NOT_EXPORT_CODEPAGE = true;
160
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.3';
163
+ XLSX.version = '0.21.5';
164
164
  var current_codepage = 1200, current_ansi = 1252;
165
165
  /*global cptable:true, window */
166
166
  var $cptable;
@@ -1819,8 +1819,12 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
1819
1819
  /** Chains */
1820
1820
  var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
1821
1821
 
1822
- if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
1823
- if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
1822
+ if(!sector_list[dir_start]) throw new Error("CFB directory chain is missing");
1823
+ sector_list[dir_start].name = "!Directory";
1824
+ /* A stale MiniFAT location is irrelevant when no live entry uses mini streams.
1825
+ * Validate required chains when reading their live directory entries. */
1826
+ if(nmfs > 0 && sector_list[minifat_start]) sector_list[minifat_start].name = "!MiniFAT";
1827
+ if(!sector_list[fat_addrs[0]]) throw new Error("CFB FAT chain is missing");
1824
1828
  sector_list[fat_addrs[0]].name = "!FAT";
1825
1829
  sector_list.fat_addrs = fat_addrs;
1826
1830
  sector_list.ssz = ssz;
@@ -2032,10 +2036,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil
2032
2036
  if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
2033
2037
  o.start = blob.read_shift(4, 'i');
2034
2038
  o.size = blob.read_shift(4, 'i');
2039
+ if(o.type === 0) { o.size = 0; o.start = ENDOFCHAIN; }
2035
2040
  if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
2036
2041
  if(o.type === 5) { /* root */
2037
- minifat_store = o.start;
2038
- if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
2042
+ minifat_store = o.size > 0 ? o.start : ENDOFCHAIN;
2043
+ if(o.size > 0 && nmfs > 0) {
2044
+ if(!sector_list[minifat_store]) throw new Error("CFB root mini stream is missing");
2045
+ sector_list[minifat_store].name = "!StreamData";
2046
+ }
2039
2047
  /*minifat_size = o.size;*/
2040
2048
  } else if(o.size >= 4096 /* MSCSZ */) {
2041
2049
  o.storage = 'fat';
@@ -2045,8 +2053,11 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil
2045
2053
  } else {
2046
2054
  o.storage = 'minifat';
2047
2055
  if(o.size < 0) o.size = 0;
2048
- else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
2049
- o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
2056
+ else if(o.type === 2 && o.size > 0) {
2057
+ if(nmfs < 1 || !sector_list[mini]) throw new Error("CFB MiniFAT chain is missing for stream: " + o.name);
2058
+ if(!sector_list[minifat_store]) throw new Error("CFB root mini stream is missing");
2059
+ o.content = get_mfat_entry(o, sector_list[minifat_store].data, sector_list[mini].data);
2060
+ if(o.content.length !== o.size) throw new Error("CFB mini stream is truncated: " + o.name);
2050
2061
  }
2051
2062
  }
2052
2063
  if(o.content) prep_blob(o.content, 0);
@@ -3376,7 +3387,6 @@ exports.utils = {
3376
3387
 
3377
3388
  return exports;
3378
3389
  })();
3379
-
3380
3390
  var _fs;
3381
3391
  function set_fs(fs) { _fs = fs; }
3382
3392
 
@@ -4028,7 +4038,7 @@ function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
4028
4038
  var htmlcharegex = /[\u0000-\u001f]/g;
4029
4039
  function escapehtml(text){
4030
4040
  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) + ";"; });
4041
+ 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
4042
  }
4033
4043
 
4034
4044
  function escapexlml(text){
@@ -5831,6 +5841,7 @@ var RELS = ({
5831
5841
  MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
5832
5842
  IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
5833
5843
  DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
5844
+ TABLE: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
5834
5845
  XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
5835
5846
  TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
5836
5847
  PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
@@ -11294,6 +11305,9 @@ function resolve_style_obj_color(obj, themes) {
11294
11305
 
11295
11306
  /* 18.3.1.13 width calculations */
11296
11307
  /* [MS-OI29500] 2.1.595 Column Width & Formatting */
11308
+ /* The file format does not store MDW directly. Seven is the Office-compatible
11309
+ * fallback when Normal-font metrics are unavailable. A single stored column
11310
+ * width is ambiguous and must not change the scale for the rest of a sheet. */
11297
11311
  var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
11298
11312
  function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
11299
11313
  function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
@@ -12127,6 +12141,47 @@ function parse_dxfs(t, styles, themes, opts) {
12127
12141
  });
12128
12142
  }
12129
12143
 
12144
+ function parse_tableStyles(t, styles, opts) {
12145
+ styles.TableStyles = {styles:[]};
12146
+ var tableStyle = null, pass = false;
12147
+ (t.match(tagregex)||[]).forEach(function(x) {
12148
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
12149
+ switch(tag) {
12150
+ case '<tableStyles': case '<tableStyles>':
12151
+ if(y.defaultTableStyle) styles.TableStyles.defaultTableStyle = utf8read(unescapexml(y.defaultTableStyle));
12152
+ if(y.defaultPivotStyle) styles.TableStyles.defaultPivotStyle = utf8read(unescapexml(y.defaultPivotStyle));
12153
+ break;
12154
+ case '<tableStyles/>': case '</tableStyles>': break;
12155
+ case '<tableStyle': case '<tableStyle>': case '<tableStyle/>':
12156
+ if(styles.TableStyles.styles.length >= TABLE_STYLE_MAX_TABLES) {
12157
+ tableStyle = null;
12158
+ break;
12159
+ }
12160
+ tableStyle = {
12161
+ name:utf8read(unescapexml(y.name || "")),
12162
+ pivot:y.pivot != null ? parsexmlbool(y.pivot) : false,
12163
+ table:y.table != null ? parsexmlbool(y.table) : true,
12164
+ elements:[]
12165
+ };
12166
+ styles.TableStyles.styles.push(tableStyle);
12167
+ if(tag.slice(-2) == "/>") tableStyle = null;
12168
+ break;
12169
+ case '</tableStyle>': tableStyle = null; break;
12170
+ case '<tableStyleElement': case '<tableStyleElement>': case '<tableStyleElement/>':
12171
+ if(tableStyle && tableStyle.elements.length < 64 && table_style_element_type(y.type) && y.dxfId != null) tableStyle.elements.push({
12172
+ type:y.type,
12173
+ dxfId:parseInt(y.dxfId, 10),
12174
+ size:y.size != null ? Math.max(1, parseInt(y.size, 10) || 1) : 1
12175
+ });
12176
+ break;
12177
+ case '<extLst': case '<extLst>': case '</extLst>': break;
12178
+ case '<ext': pass = true; break;
12179
+ case '</ext>': pass = false; break;
12180
+ default: if(opts && opts.WTF && !pass) throw new Error('unrecognized ' + y[0] + ' in tableStyles');
12181
+ }
12182
+ });
12183
+ }
12184
+
12130
12185
  function parse_colors(t, styles, themes, opts) {
12131
12186
  styles.Colors = {indexedColors:[], mruColors:[], themeColors:[]};
12132
12187
  var target = null, pass = false;
@@ -12205,6 +12260,7 @@ return function parse_sty_xml(data, themes, opts) {
12205
12260
  if((t=str_match_xml_ns(data, "dxfs"))) parse_dxfs(t[0], styles, themes, opts);
12206
12261
 
12207
12262
  /* 18.8.42 tableStyles CT_TableStyles ? */
12263
+ if((t=str_match_xml_ns(data, "tableStyles"))) parse_tableStyles(t[0], styles, opts);
12208
12264
  /* 18.8.11 colors CT_Colors ? */
12209
12265
  if((t=str_match_xml_ns(data, "colors"))) parse_colors(t[0], styles, themes, opts);
12210
12266
 
@@ -16730,7 +16786,11 @@ function validate_merges(ws, opts) {
16730
16786
  errors.push({code:"E_MERGE_OVERLAP", message:"Merge ranges overlap", index:i, other:j, range:enc, otherRange:encode_range(merges[j])});
16731
16787
  }
16732
16788
  }
16733
- if(errors.length && opts && opts.WTF) throw new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16789
+ if(errors.length && opts && opts.WTF) {
16790
+ var err = new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16791
+ err.code = errors[0].code;
16792
+ throw err;
16793
+ }
16734
16794
  return errors;
16735
16795
  }
16736
16796
 
@@ -16740,6 +16800,312 @@ function check_ws(ws, sname, i) {
16740
16800
  if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
16741
16801
  }
16742
16802
  }
16803
+ var TABLE_STYLE_MAX_TABLES = 1024;
16804
+ var TABLE_STYLE_MAX_COLUMNS = 16384;
16805
+ var TABLE_STYLE_MAX_XML_LENGTH = 5 * 1024 * 1024;
16806
+ var TABLE_STYLE_ELEMENT_TYPES = {
16807
+ wholeTable:true, headerRow:true, totalRow:true,
16808
+ firstColumn:true, lastColumn:true,
16809
+ firstRowStripe:true, secondRowStripe:true,
16810
+ firstColumnStripe:true, secondColumnStripe:true,
16811
+ firstHeaderCell:true, lastHeaderCell:true,
16812
+ firstTotalCell:true, lastTotalCell:true
16813
+ };
16814
+
16815
+ function table_style_safe_key(key) {
16816
+ return key != "__proto__" && key != "constructor" && key != "prototype";
16817
+ }
16818
+
16819
+ function table_style_element_type(type) {
16820
+ return Object.prototype.hasOwnProperty.call(TABLE_STYLE_ELEMENT_TYPES, type);
16821
+ }
16822
+
16823
+ function table_style_attr(y, name) {
16824
+ if(y[name] != null) return y[name];
16825
+ return y[name.toLowerCase()];
16826
+ }
16827
+
16828
+ function table_style_bool(y, name, fallback) {
16829
+ var value = table_style_attr(y, name);
16830
+ return value == null ? fallback : parsexmlbool(value);
16831
+ }
16832
+
16833
+ function table_style_int(y, name) {
16834
+ var value = table_style_attr(y, name);
16835
+ if(value == null || value === "") return void 0;
16836
+ value = parseInt(value, 10);
16837
+ return isFinite(value) && value >= 0 ? value : void 0;
16838
+ }
16839
+
16840
+ function table_style_merge(target, source) {
16841
+ if(!source) return target;
16842
+ if(!target) target = {};
16843
+ keys(source).forEach(function(k) {
16844
+ if(!table_style_safe_key(k)) return;
16845
+ var value = source[k];
16846
+ if(value && typeof value == "object" && !Array.isArray(value)) {
16847
+ target[k] = table_style_merge(
16848
+ target[k] && typeof target[k] == "object" && !Array.isArray(target[k]) ? table_style_merge({}, target[k]) : {},
16849
+ value
16850
+ );
16851
+ } else target[k] = value;
16852
+ });
16853
+ return target;
16854
+ }
16855
+
16856
+ function table_style_color(themes, theme, tint) {
16857
+ return style_color_from_attrs({theme:String(theme), tint:String(tint || 0)}, themes);
16858
+ }
16859
+
16860
+ function table_style_fill(color) {
16861
+ return {fill:{patternType:"solid", fgColor:color}};
16862
+ }
16863
+
16864
+ function table_style_font(color, bold) {
16865
+ var font = {};
16866
+ if(color) font.color = color;
16867
+ if(bold) font.bold = 1;
16868
+ return {font:font};
16869
+ }
16870
+
16871
+ function table_style_border(side, color, style) {
16872
+ var border = {}, out = {border:border};
16873
+ border[side] = {style:style || "thin", color:color};
16874
+ return out;
16875
+ }
16876
+
16877
+ function table_style_accent(themes, index) {
16878
+ var position = (index - 1) % 7;
16879
+ /* The first style in each seven-style family is neutral. The remaining
16880
+ * six entries use the workbook's accent1..accent6 colors. */
16881
+ return table_style_color(themes, position ? 3 + position : 1, 0);
16882
+ }
16883
+
16884
+ function built_in_table_style_rules(name, themes) {
16885
+ var match = /^TableStyle(Light|Medium|Dark)(\d+)$/i.exec(name || "");
16886
+ if(!match) return null;
16887
+ var family = match[1].toLowerCase(), index = parseInt(match[2], 10);
16888
+ var maximum = family == "light" ? 21 : family == "medium" ? 28 : 11;
16889
+ if(index < 1 || index > maximum) return null;
16890
+ var accent = table_style_accent(themes, index);
16891
+ var white = table_style_color(themes, 0, 0);
16892
+ var dark = table_style_color(themes, 1, 0);
16893
+ var rules = {};
16894
+
16895
+ if(family == "light") {
16896
+ rules.headerRow = table_style_merge(
16897
+ table_style_font(accent, true),
16898
+ table_style_border("bottom", accent, "medium")
16899
+ );
16900
+ rules.totalRow = table_style_merge(
16901
+ table_style_font(accent, true),
16902
+ table_style_border("top", accent, "double")
16903
+ );
16904
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16905
+ rules.firstColumnStripe = rules.firstRowStripe;
16906
+ } else if(family == "medium") {
16907
+ var group = Math.floor((index - 1) / 7);
16908
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16909
+ rules.totalRow = table_style_merge(
16910
+ table_style_font(accent, true),
16911
+ table_style_border("top", accent, "double")
16912
+ );
16913
+ if(group == 1) {
16914
+ /* Medium 8..14 use two theme-derived body fills. This is the family
16915
+ * used by Excel's TableStyleMedium13. */
16916
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16917
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.6));
16918
+ rules.firstColumnStripe = rules.firstRowStripe;
16919
+ } else if(group == 2) {
16920
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16921
+ rules.firstColumnStripe = rules.firstRowStripe;
16922
+ rules.wholeTable = table_style_border("bottom", table_style_color(themes, accent.theme, 0.4), "thin");
16923
+ } else if(group == 3) {
16924
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16925
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.7));
16926
+ rules.firstColumnStripe = rules.firstRowStripe;
16927
+ } else {
16928
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16929
+ rules.firstColumnStripe = rules.firstRowStripe;
16930
+ }
16931
+ } else {
16932
+ rules.wholeTable = table_style_merge(table_style_fill(dark), table_style_font(white, false));
16933
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16934
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, -0.35));
16935
+ rules.firstColumnStripe = rules.firstRowStripe;
16936
+ rules.totalRow = table_style_merge(
16937
+ table_style_font(white, true),
16938
+ table_style_border("top", accent, "double")
16939
+ );
16940
+ }
16941
+
16942
+ rules.firstColumn = table_style_font(null, true);
16943
+ rules.lastColumn = table_style_font(null, true);
16944
+ return rules;
16945
+ }
16946
+
16947
+ function custom_table_style_rules(name, styles) {
16948
+ var tableStyles = styles && styles.TableStyles;
16949
+ if(!tableStyles || !tableStyles.styles) return null;
16950
+ for(var i = 0; i < tableStyles.styles.length; ++i) {
16951
+ var tableStyle = tableStyles.styles[i];
16952
+ if(tableStyle.name != name) continue;
16953
+ var rules = Object.create(null);
16954
+ (tableStyle.elements || []).forEach(function(element) {
16955
+ if(!table_style_element_type(element.type)) return;
16956
+ var dxf = styles.Dxfs && styles.Dxfs[element.dxfId];
16957
+ if(dxf) rules[element.type] = {style:dup(dxf), size:element.size || 1};
16958
+ });
16959
+ return rules;
16960
+ }
16961
+ return null;
16962
+ }
16963
+
16964
+ function parse_table_xml(data, path, themes, styles, opts) {
16965
+ if(!data || data.length > TABLE_STYLE_MAX_XML_LENGTH) return null;
16966
+ data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
16967
+ var table = {columns:[]}, column = null, pass = false;
16968
+ (data.match(tagregex)||[]).forEach(function(x) {
16969
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
16970
+ switch(tag) {
16971
+ case '<table': case '<table>':
16972
+ table.id = table_style_int(y, "id");
16973
+ table.name = utf8read(unescapexml(table_style_attr(y, "name") || ""));
16974
+ table.displayName = utf8read(unescapexml(table_style_attr(y, "displayName") || table.name));
16975
+ table.ref = table_style_attr(y, "ref") || "";
16976
+ table.headerRowCount = table_style_int(y, "headerRowCount");
16977
+ table.totalsRowCount = table_style_int(y, "totalsRowCount");
16978
+ table.totalsRowShown = table_style_bool(y, "totalsRowShown", false);
16979
+ table.headerRowDxfId = table_style_int(y, "headerRowDxfId");
16980
+ table.dataDxfId = table_style_int(y, "dataDxfId");
16981
+ table.totalsRowDxfId = table_style_int(y, "totalsRowDxfId");
16982
+ table.path = path;
16983
+ break;
16984
+ case '<tableColumn': case '<tableColumn>': case '<tableColumn/>':
16985
+ if(table.columns.length >= TABLE_STYLE_MAX_COLUMNS) {
16986
+ column = null;
16987
+ break;
16988
+ }
16989
+ column = {
16990
+ id:table_style_int(y, "id"),
16991
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16992
+ headerRowDxfId:table_style_int(y, "headerRowDxfId"),
16993
+ dataDxfId:table_style_int(y, "dataDxfId"),
16994
+ totalsRowDxfId:table_style_int(y, "totalsRowDxfId")
16995
+ };
16996
+ table.columns.push(column);
16997
+ if(tag.slice(-2) == "/>" ) column = null;
16998
+ break;
16999
+ case '</tableColumn>': column = null; break;
17000
+ case '<tableStyleInfo': case '<tableStyleInfo>': case '<tableStyleInfo/>':
17001
+ table.styleInfo = {
17002
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
17003
+ showFirstColumn:table_style_bool(y, "showFirstColumn", false),
17004
+ showLastColumn:table_style_bool(y, "showLastColumn", false),
17005
+ showRowStripes:table_style_bool(y, "showRowStripes", false),
17006
+ showColumnStripes:table_style_bool(y, "showColumnStripes", false)
17007
+ };
17008
+ break;
17009
+ case '<extLst': case '<extLst>': case '</extLst>': break;
17010
+ case '<ext': pass = true; break;
17011
+ case '</ext>': pass = false; break;
17012
+ default: if(opts && opts.WTF && !pass) {
17013
+ /* Table formulas and filter metadata are intentionally preserved by
17014
+ * the raw XML parser but do not affect visual style resolution. */
17015
+ if(/^<\/?(?:tableColumns|autoFilter|sortState|calculatedColumnFormula|totalsRowFormula|xmlColumnPr)/.test(tag)) break;
17016
+ }
17017
+ }
17018
+ });
17019
+ if(!table.ref) return null;
17020
+ try {
17021
+ table.range = safe_decode_range(table.ref);
17022
+ if(table.range.s.r < 0 || table.range.s.c < 0 || table.range.e.r > 1048575 || table.range.e.c > 16383) return null;
17023
+ } catch(e) { return null; }
17024
+ var styleName = table.styleInfo && table.styleInfo.name;
17025
+ table.styleRules = custom_table_style_rules(styleName, styles) || built_in_table_style_rules(styleName, themes) || {};
17026
+ table.dxfs = styles && styles.Dxfs ? styles.Dxfs : [];
17027
+ return table;
17028
+ }
17029
+
17030
+ function parse_sheet_tables(sheet, zip, path, rels, opts, themes, styles) {
17031
+ if(!sheet || !rels || !rels['!id'] || !opts || !opts.cellStyles) return;
17032
+ var tables = [], seen = Object.create(null);
17033
+ keys(rels['!id']).forEach(function(id) {
17034
+ if(tables.length >= TABLE_STYLE_MAX_TABLES) return;
17035
+ var rel = rels['!id'][id];
17036
+ if(!rel || rel.TargetMode == "External" || typeof rel.Target != "string" || !rel.Target ||
17037
+ (rel.Type != RELS.TABLE && !/\/table$/.test(rel.Type || ""))) return;
17038
+ var tablePath = resolve_path(rel.Target, path);
17039
+ if(seen[tablePath]) return;
17040
+ seen[tablePath] = true;
17041
+ var table = parse_table_xml(getzipstr(zip, tablePath, true), tablePath, themes, styles, opts);
17042
+ if(table) tables.push(table);
17043
+ });
17044
+ if(tables.length) sheet['!tables'] = tables;
17045
+ }
17046
+
17047
+ function table_style_rule_value(rule) {
17048
+ return rule && rule.style ? rule.style : rule;
17049
+ }
17050
+
17051
+ function table_style_stripe_rule(first, second, offset) {
17052
+ var firstSize = first && first.size || 1, secondSize = second && second.size || 1;
17053
+ var period = firstSize + secondSize;
17054
+ if(!period) return null;
17055
+ return offset % period < firstSize ? first : second;
17056
+ }
17057
+
17058
+ function table_style_dxf(table, id) {
17059
+ return id == null || !table.dxfs ? null : table.dxfs[id];
17060
+ }
17061
+
17062
+ function resolve_table_cell_style(ws, row, col, baseStyle) {
17063
+ var tables = ws && ws['!tables'];
17064
+ var resolved = baseStyle ? table_style_merge({}, baseStyle) : {};
17065
+ if(!tables || !tables.length) return keys(resolved).length ? resolved : void 0;
17066
+ for(var i = 0; i < tables.length; ++i) {
17067
+ var table = tables[i], range = table.range;
17068
+ if(!range || row < range.s.r || row > range.e.r || col < range.s.c || col > range.e.c) continue;
17069
+ var rules = table.styleRules || {}, info = table.styleInfo || {};
17070
+ var rowOffset = row - range.s.r, colOffset = col - range.s.c;
17071
+ var headerRows = table.headerRowCount == null ? 1 : table.headerRowCount;
17072
+ var totalRows = table.totalsRowCount != null ? table.totalsRowCount : table.totalsRowShown ? 1 : 0;
17073
+ var dataStart = headerRows, dataEnd = range.e.r - range.s.r - totalRows;
17074
+ var isHeader = rowOffset < headerRows;
17075
+ var isTotal = totalRows > 0 && rowOffset > dataEnd;
17076
+ var dataOffset = rowOffset - dataStart;
17077
+ var column = table.columns && table.columns[colOffset];
17078
+
17079
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.wholeTable));
17080
+ if(!isHeader && !isTotal && dataOffset >= 0) {
17081
+ if(info.showRowStripes) resolved = table_style_merge(resolved, table_style_rule_value(
17082
+ table_style_stripe_rule(rules.firstRowStripe, rules.secondRowStripe, dataOffset)
17083
+ ));
17084
+ if(info.showColumnStripes) resolved = table_style_merge(resolved, table_style_rule_value(
17085
+ table_style_stripe_rule(rules.firstColumnStripe, rules.secondColumnStripe, colOffset)
17086
+ ));
17087
+ }
17088
+ if(info.showFirstColumn && col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstColumn));
17089
+ if(info.showLastColumn && col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastColumn));
17090
+ if(isHeader) {
17091
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.headerRow));
17092
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstHeaderCell));
17093
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastHeaderCell));
17094
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.headerRowDxfId));
17095
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.headerRowDxfId));
17096
+ } else if(isTotal) {
17097
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.totalRow));
17098
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstTotalCell));
17099
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastTotalCell));
17100
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.totalsRowDxfId));
17101
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.totalsRowDxfId));
17102
+ } else {
17103
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.dataDxfId));
17104
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.dataDxfId));
17105
+ }
17106
+ }
17107
+ return keys(resolved).length ? resolved : void 0;
17108
+ }
16743
17109
  function parse_ws_xml_dim(ws, s) {
16744
17110
  var d = safe_decode_range(s);
16745
17111
  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);
@@ -16854,7 +17220,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16854
17220
  if(columns.length > 0) s["!cols"] = columns;
16855
17221
  if(merges.length > 0) {
16856
17222
  s["!merges"] = merges;
16857
- var mergeErrors = validate_merges(s, {WTF: !!(opts && (opts.WTF || opts.validateMerges))});
17223
+ var mergeErrors = validate_merges(s, {WTF: !!(opts && opts.validateMerges)});
16858
17224
  if(mergeErrors.length) s["!mergeErrors"] = mergeErrors;
16859
17225
  }
16860
17226
  if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
@@ -16969,7 +17335,8 @@ function parse_ws_xml_cols(columns, cols) {
16969
17335
  var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
16970
17336
  if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
16971
17337
  delete coll.min; delete coll.max; coll.width = +coll.width;
16972
- /* OOXML widths share the workbook Normal-font MDW; do not infer a different scale per sheet. */
17338
+ /* OOXML widths share the workbook Normal-font MDW. Do not infer it from
17339
+ * one ambiguous stored width or leak another worksheet's scale. */
16973
17340
  if(!seencol && coll.width) { seencol = true; MDW = DEF_MDW; }
16974
17341
  process_col(coll);
16975
17342
  while(colm <= colM) columns[colm++] = dup(coll);
@@ -17392,7 +17759,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17392
17759
  /* customSheetViews */
17393
17760
 
17394
17761
  if(ws['!merges'] != null && ws['!merges'].length > 0) {
17395
- validate_merges(ws, {WTF:true});
17762
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
17396
17763
  o[o.length] = (write_ws_xml_merges(ws['!merges']));
17397
17764
  }
17398
17765
 
@@ -18878,7 +19245,6 @@ function check_wb(wb) {
18878
19245
  check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
18879
19246
  for(var i = 0; i < wb.SheetNames.length; ++i) {
18880
19247
  var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
18881
- if(!ws) throw new Error("Missing worksheet |" + wb.SheetNames[i] + "|");
18882
19248
  check_ws(ws, wb.SheetNames[i], i);
18883
19249
  }
18884
19250
  wb.SheetNames.forEach(function(n, i) {
@@ -21296,7 +21662,7 @@ function parse_workbook(blob, options) {
21296
21662
  };
21297
21663
  var finalize_sheet_visuals = function finalizesheetvisuals(ws) {
21298
21664
  if(ws["!merges"] && ws["!merges"].length) {
21299
- var mergeErrors = validate_merges(ws, {WTF: !!(options && (options.WTF || options.validateMerges))});
21665
+ var mergeErrors = validate_merges(ws, {WTF: !!(options && options.validateMerges)});
21300
21666
  if(mergeErrors.length) ws["!mergeErrors"] = mergeErrors;
21301
21667
  }
21302
21668
  if(drawings && (drawings.images.length || drawings.shapes.length || drawings.charts.length || drawings.raw.length)) ws["!drawings"] = drawings;
@@ -23851,7 +24217,7 @@ function write_ws_biff8(idx, opts, wb) {
23851
24217
  if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
23852
24218
  /* ... */
23853
24219
  if(b8 && (ws['!merges']||[]).length) {
23854
- validate_merges(ws, {WTF:true});
24220
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
23855
24221
  write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
23856
24222
  }
23857
24223
  /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
@@ -24240,6 +24606,7 @@ function make_html_row(ws, r, R, o) {
24240
24606
  if(cols[C] && cols[C].s) extend_style_obj(inherited, cols[C].s);
24241
24607
  if(row && row.s) extend_style_obj(inherited, row.s);
24242
24608
  if(cell && cell.s) extend_style_obj(inherited, cell.s);
24609
+ inherited = resolve_table_cell_style(ws, R, C, inherited) || inherited;
24243
24610
  if(keys(inherited).length) {
24244
24611
  stylecell = cell ? dup(cell) : {t:'z'};
24245
24612
  stylecell.s = inherited;
@@ -28366,6 +28733,7 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28366
28733
  case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
28367
28734
  default: throw new Error("Unrecognized sheet type " + stype);
28368
28735
  }
28736
+ if(stype == "sheet") parse_sheet_tables(_ws, zip, path, sheetRels[sheet], opts, themes, styles);
28369
28737
  sheet_map_set(sheets, sheet, _ws);
28370
28738
 
28371
28739
  /* scan rels for comments and threaded comments */
@@ -28386,7 +28754,9 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28386
28754
  if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
28387
28755
  if(stype == "sheet") parse_sheet_drawing(_ws, stype, zip, path, idx, opts, wb);
28388
28756
  parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
28389
- } catch(e) { if(opts.WTF) throw e; }
28757
+ } catch(e) {
28758
+ if(opts.WTF || (opts.validateMerges && e && /^E_MERGE_/.test(e.code))) throw e;
28759
+ }
28390
28760
  }
28391
28761
 
28392
28762
  function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
@@ -29687,6 +30057,7 @@ var utils = {
29687
30057
  measure_text_width: measure_text_width,
29688
30058
  auto_fit_columns: auto_fit_columns,
29689
30059
  autofit_columns: auto_fit_columns,
30060
+ resolve_table_cell_style: resolve_table_cell_style,
29690
30061
  col_width_to_px: width2px,
29691
30062
  px_to_col_width: function(px) { return char2width(px2char(px)); },
29692
30063
  row_height_to_px: pt2px_browser,