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.
package/xlsx.js CHANGED
@@ -4,7 +4,7 @@
4
4
  /*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false, Int8Array:false */
5
5
  var XLSX = {};
6
6
  function make_xlsx_lib(XLSX){
7
- XLSX.version = '0.21.3';
7
+ XLSX.version = '0.21.5';
8
8
  var current_codepage = 1200, current_ansi = 1252;
9
9
  /*global cptable:true, window */
10
10
  var $cptable;
@@ -1663,8 +1663,12 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
1663
1663
  /** Chains */
1664
1664
  var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
1665
1665
 
1666
- if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
1667
- if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
1666
+ if(!sector_list[dir_start]) throw new Error("CFB directory chain is missing");
1667
+ sector_list[dir_start].name = "!Directory";
1668
+ /* A stale MiniFAT location is irrelevant when no live entry uses mini streams.
1669
+ * Validate required chains when reading their live directory entries. */
1670
+ if(nmfs > 0 && sector_list[minifat_start]) sector_list[minifat_start].name = "!MiniFAT";
1671
+ if(!sector_list[fat_addrs[0]]) throw new Error("CFB FAT chain is missing");
1668
1672
  sector_list[fat_addrs[0]].name = "!FAT";
1669
1673
  sector_list.fat_addrs = fat_addrs;
1670
1674
  sector_list.ssz = ssz;
@@ -1876,10 +1880,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil
1876
1880
  if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
1877
1881
  o.start = blob.read_shift(4, 'i');
1878
1882
  o.size = blob.read_shift(4, 'i');
1883
+ if(o.type === 0) { o.size = 0; o.start = ENDOFCHAIN; }
1879
1884
  if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
1880
1885
  if(o.type === 5) { /* root */
1881
- minifat_store = o.start;
1882
- if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
1886
+ minifat_store = o.size > 0 ? o.start : ENDOFCHAIN;
1887
+ if(o.size > 0 && nmfs > 0) {
1888
+ if(!sector_list[minifat_store]) throw new Error("CFB root mini stream is missing");
1889
+ sector_list[minifat_store].name = "!StreamData";
1890
+ }
1883
1891
  /*minifat_size = o.size;*/
1884
1892
  } else if(o.size >= 4096 /* MSCSZ */) {
1885
1893
  o.storage = 'fat';
@@ -1889,8 +1897,11 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil
1889
1897
  } else {
1890
1898
  o.storage = 'minifat';
1891
1899
  if(o.size < 0) o.size = 0;
1892
- else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
1893
- o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
1900
+ else if(o.type === 2 && o.size > 0) {
1901
+ if(nmfs < 1 || !sector_list[mini]) throw new Error("CFB MiniFAT chain is missing for stream: " + o.name);
1902
+ if(!sector_list[minifat_store]) throw new Error("CFB root mini stream is missing");
1903
+ o.content = get_mfat_entry(o, sector_list[minifat_store].data, sector_list[mini].data);
1904
+ if(o.content.length !== o.size) throw new Error("CFB mini stream is truncated: " + o.name);
1894
1905
  }
1895
1906
  }
1896
1907
  if(o.content) prep_blob(o.content, 0);
@@ -3220,7 +3231,6 @@ exports.utils = {
3220
3231
 
3221
3232
  return exports;
3222
3233
  })();
3223
-
3224
3234
  var _fs;
3225
3235
  function set_fs(fs) { _fs = fs; }
3226
3236
 
@@ -3872,7 +3882,7 @@ function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
3872
3882
  var htmlcharegex = /[\u0000-\u001f]/g;
3873
3883
  function escapehtml(text){
3874
3884
  var s = text + '';
3875
- return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
3885
+ return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\r\n|\r|\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
3876
3886
  }
3877
3887
 
3878
3888
  function escapexlml(text){
@@ -5675,6 +5685,7 @@ var RELS = ({
5675
5685
  MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
5676
5686
  IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
5677
5687
  DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
5688
+ TABLE: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
5678
5689
  XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
5679
5690
  TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
5680
5691
  PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
@@ -11138,6 +11149,9 @@ function resolve_style_obj_color(obj, themes) {
11138
11149
 
11139
11150
  /* 18.3.1.13 width calculations */
11140
11151
  /* [MS-OI29500] 2.1.595 Column Width & Formatting */
11152
+ /* The file format does not store MDW directly. Seven is the Office-compatible
11153
+ * fallback when Normal-font metrics are unavailable. A single stored column
11154
+ * width is ambiguous and must not change the scale for the rest of a sheet. */
11141
11155
  var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
11142
11156
  function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
11143
11157
  function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
@@ -11971,6 +11985,47 @@ function parse_dxfs(t, styles, themes, opts) {
11971
11985
  });
11972
11986
  }
11973
11987
 
11988
+ function parse_tableStyles(t, styles, opts) {
11989
+ styles.TableStyles = {styles:[]};
11990
+ var tableStyle = null, pass = false;
11991
+ (t.match(tagregex)||[]).forEach(function(x) {
11992
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
11993
+ switch(tag) {
11994
+ case '<tableStyles': case '<tableStyles>':
11995
+ if(y.defaultTableStyle) styles.TableStyles.defaultTableStyle = utf8read(unescapexml(y.defaultTableStyle));
11996
+ if(y.defaultPivotStyle) styles.TableStyles.defaultPivotStyle = utf8read(unescapexml(y.defaultPivotStyle));
11997
+ break;
11998
+ case '<tableStyles/>': case '</tableStyles>': break;
11999
+ case '<tableStyle': case '<tableStyle>': case '<tableStyle/>':
12000
+ if(styles.TableStyles.styles.length >= TABLE_STYLE_MAX_TABLES) {
12001
+ tableStyle = null;
12002
+ break;
12003
+ }
12004
+ tableStyle = {
12005
+ name:utf8read(unescapexml(y.name || "")),
12006
+ pivot:y.pivot != null ? parsexmlbool(y.pivot) : false,
12007
+ table:y.table != null ? parsexmlbool(y.table) : true,
12008
+ elements:[]
12009
+ };
12010
+ styles.TableStyles.styles.push(tableStyle);
12011
+ if(tag.slice(-2) == "/>") tableStyle = null;
12012
+ break;
12013
+ case '</tableStyle>': tableStyle = null; break;
12014
+ case '<tableStyleElement': case '<tableStyleElement>': case '<tableStyleElement/>':
12015
+ if(tableStyle && tableStyle.elements.length < 64 && table_style_element_type(y.type) && y.dxfId != null) tableStyle.elements.push({
12016
+ type:y.type,
12017
+ dxfId:parseInt(y.dxfId, 10),
12018
+ size:y.size != null ? Math.max(1, parseInt(y.size, 10) || 1) : 1
12019
+ });
12020
+ break;
12021
+ case '<extLst': case '<extLst>': case '</extLst>': break;
12022
+ case '<ext': pass = true; break;
12023
+ case '</ext>': pass = false; break;
12024
+ default: if(opts && opts.WTF && !pass) throw new Error('unrecognized ' + y[0] + ' in tableStyles');
12025
+ }
12026
+ });
12027
+ }
12028
+
11974
12029
  function parse_colors(t, styles, themes, opts) {
11975
12030
  styles.Colors = {indexedColors:[], mruColors:[], themeColors:[]};
11976
12031
  var target = null, pass = false;
@@ -12049,6 +12104,7 @@ return function parse_sty_xml(data, themes, opts) {
12049
12104
  if((t=str_match_xml_ns(data, "dxfs"))) parse_dxfs(t[0], styles, themes, opts);
12050
12105
 
12051
12106
  /* 18.8.42 tableStyles CT_TableStyles ? */
12107
+ if((t=str_match_xml_ns(data, "tableStyles"))) parse_tableStyles(t[0], styles, opts);
12052
12108
  /* 18.8.11 colors CT_Colors ? */
12053
12109
  if((t=str_match_xml_ns(data, "colors"))) parse_colors(t[0], styles, themes, opts);
12054
12110
 
@@ -16574,7 +16630,11 @@ function validate_merges(ws, opts) {
16574
16630
  errors.push({code:"E_MERGE_OVERLAP", message:"Merge ranges overlap", index:i, other:j, range:enc, otherRange:encode_range(merges[j])});
16575
16631
  }
16576
16632
  }
16577
- if(errors.length && opts && opts.WTF) throw new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16633
+ if(errors.length && opts && opts.WTF) {
16634
+ var err = new Error(errors[0].message + " (" + (errors[0].range || errors[0].index) + ")");
16635
+ err.code = errors[0].code;
16636
+ throw err;
16637
+ }
16578
16638
  return errors;
16579
16639
  }
16580
16640
 
@@ -16584,6 +16644,312 @@ function check_ws(ws, sname, i) {
16584
16644
  if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
16585
16645
  }
16586
16646
  }
16647
+ var TABLE_STYLE_MAX_TABLES = 1024;
16648
+ var TABLE_STYLE_MAX_COLUMNS = 16384;
16649
+ var TABLE_STYLE_MAX_XML_LENGTH = 5 * 1024 * 1024;
16650
+ var TABLE_STYLE_ELEMENT_TYPES = {
16651
+ wholeTable:true, headerRow:true, totalRow:true,
16652
+ firstColumn:true, lastColumn:true,
16653
+ firstRowStripe:true, secondRowStripe:true,
16654
+ firstColumnStripe:true, secondColumnStripe:true,
16655
+ firstHeaderCell:true, lastHeaderCell:true,
16656
+ firstTotalCell:true, lastTotalCell:true
16657
+ };
16658
+
16659
+ function table_style_safe_key(key) {
16660
+ return key != "__proto__" && key != "constructor" && key != "prototype";
16661
+ }
16662
+
16663
+ function table_style_element_type(type) {
16664
+ return Object.prototype.hasOwnProperty.call(TABLE_STYLE_ELEMENT_TYPES, type);
16665
+ }
16666
+
16667
+ function table_style_attr(y, name) {
16668
+ if(y[name] != null) return y[name];
16669
+ return y[name.toLowerCase()];
16670
+ }
16671
+
16672
+ function table_style_bool(y, name, fallback) {
16673
+ var value = table_style_attr(y, name);
16674
+ return value == null ? fallback : parsexmlbool(value);
16675
+ }
16676
+
16677
+ function table_style_int(y, name) {
16678
+ var value = table_style_attr(y, name);
16679
+ if(value == null || value === "") return void 0;
16680
+ value = parseInt(value, 10);
16681
+ return isFinite(value) && value >= 0 ? value : void 0;
16682
+ }
16683
+
16684
+ function table_style_merge(target, source) {
16685
+ if(!source) return target;
16686
+ if(!target) target = {};
16687
+ keys(source).forEach(function(k) {
16688
+ if(!table_style_safe_key(k)) return;
16689
+ var value = source[k];
16690
+ if(value && typeof value == "object" && !Array.isArray(value)) {
16691
+ target[k] = table_style_merge(
16692
+ target[k] && typeof target[k] == "object" && !Array.isArray(target[k]) ? table_style_merge({}, target[k]) : {},
16693
+ value
16694
+ );
16695
+ } else target[k] = value;
16696
+ });
16697
+ return target;
16698
+ }
16699
+
16700
+ function table_style_color(themes, theme, tint) {
16701
+ return style_color_from_attrs({theme:String(theme), tint:String(tint || 0)}, themes);
16702
+ }
16703
+
16704
+ function table_style_fill(color) {
16705
+ return {fill:{patternType:"solid", fgColor:color}};
16706
+ }
16707
+
16708
+ function table_style_font(color, bold) {
16709
+ var font = {};
16710
+ if(color) font.color = color;
16711
+ if(bold) font.bold = 1;
16712
+ return {font:font};
16713
+ }
16714
+
16715
+ function table_style_border(side, color, style) {
16716
+ var border = {}, out = {border:border};
16717
+ border[side] = {style:style || "thin", color:color};
16718
+ return out;
16719
+ }
16720
+
16721
+ function table_style_accent(themes, index) {
16722
+ var position = (index - 1) % 7;
16723
+ /* The first style in each seven-style family is neutral. The remaining
16724
+ * six entries use the workbook's accent1..accent6 colors. */
16725
+ return table_style_color(themes, position ? 3 + position : 1, 0);
16726
+ }
16727
+
16728
+ function built_in_table_style_rules(name, themes) {
16729
+ var match = /^TableStyle(Light|Medium|Dark)(\d+)$/i.exec(name || "");
16730
+ if(!match) return null;
16731
+ var family = match[1].toLowerCase(), index = parseInt(match[2], 10);
16732
+ var maximum = family == "light" ? 21 : family == "medium" ? 28 : 11;
16733
+ if(index < 1 || index > maximum) return null;
16734
+ var accent = table_style_accent(themes, index);
16735
+ var white = table_style_color(themes, 0, 0);
16736
+ var dark = table_style_color(themes, 1, 0);
16737
+ var rules = {};
16738
+
16739
+ if(family == "light") {
16740
+ rules.headerRow = table_style_merge(
16741
+ table_style_font(accent, true),
16742
+ table_style_border("bottom", accent, "medium")
16743
+ );
16744
+ rules.totalRow = table_style_merge(
16745
+ table_style_font(accent, true),
16746
+ table_style_border("top", accent, "double")
16747
+ );
16748
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16749
+ rules.firstColumnStripe = rules.firstRowStripe;
16750
+ } else if(family == "medium") {
16751
+ var group = Math.floor((index - 1) / 7);
16752
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16753
+ rules.totalRow = table_style_merge(
16754
+ table_style_font(accent, true),
16755
+ table_style_border("top", accent, "double")
16756
+ );
16757
+ if(group == 1) {
16758
+ /* Medium 8..14 use two theme-derived body fills. This is the family
16759
+ * used by Excel's TableStyleMedium13. */
16760
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16761
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.6));
16762
+ rules.firstColumnStripe = rules.firstRowStripe;
16763
+ } else if(group == 2) {
16764
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16765
+ rules.firstColumnStripe = rules.firstRowStripe;
16766
+ rules.wholeTable = table_style_border("bottom", table_style_color(themes, accent.theme, 0.4), "thin");
16767
+ } else if(group == 3) {
16768
+ rules.wholeTable = table_style_fill(table_style_color(themes, accent.theme, 0.9));
16769
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.7));
16770
+ rules.firstColumnStripe = rules.firstRowStripe;
16771
+ } else {
16772
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, 0.8));
16773
+ rules.firstColumnStripe = rules.firstRowStripe;
16774
+ }
16775
+ } else {
16776
+ rules.wholeTable = table_style_merge(table_style_fill(dark), table_style_font(white, false));
16777
+ rules.headerRow = table_style_merge(table_style_fill(accent), table_style_font(white, true));
16778
+ rules.firstRowStripe = table_style_fill(table_style_color(themes, accent.theme, -0.35));
16779
+ rules.firstColumnStripe = rules.firstRowStripe;
16780
+ rules.totalRow = table_style_merge(
16781
+ table_style_font(white, true),
16782
+ table_style_border("top", accent, "double")
16783
+ );
16784
+ }
16785
+
16786
+ rules.firstColumn = table_style_font(null, true);
16787
+ rules.lastColumn = table_style_font(null, true);
16788
+ return rules;
16789
+ }
16790
+
16791
+ function custom_table_style_rules(name, styles) {
16792
+ var tableStyles = styles && styles.TableStyles;
16793
+ if(!tableStyles || !tableStyles.styles) return null;
16794
+ for(var i = 0; i < tableStyles.styles.length; ++i) {
16795
+ var tableStyle = tableStyles.styles[i];
16796
+ if(tableStyle.name != name) continue;
16797
+ var rules = Object.create(null);
16798
+ (tableStyle.elements || []).forEach(function(element) {
16799
+ if(!table_style_element_type(element.type)) return;
16800
+ var dxf = styles.Dxfs && styles.Dxfs[element.dxfId];
16801
+ if(dxf) rules[element.type] = {style:dup(dxf), size:element.size || 1};
16802
+ });
16803
+ return rules;
16804
+ }
16805
+ return null;
16806
+ }
16807
+
16808
+ function parse_table_xml(data, path, themes, styles, opts) {
16809
+ if(!data || data.length > TABLE_STYLE_MAX_XML_LENGTH) return null;
16810
+ data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
16811
+ var table = {columns:[]}, column = null, pass = false;
16812
+ (data.match(tagregex)||[]).forEach(function(x) {
16813
+ var y = parsexmltag(x), tag = strip_ns(y[0]);
16814
+ switch(tag) {
16815
+ case '<table': case '<table>':
16816
+ table.id = table_style_int(y, "id");
16817
+ table.name = utf8read(unescapexml(table_style_attr(y, "name") || ""));
16818
+ table.displayName = utf8read(unescapexml(table_style_attr(y, "displayName") || table.name));
16819
+ table.ref = table_style_attr(y, "ref") || "";
16820
+ table.headerRowCount = table_style_int(y, "headerRowCount");
16821
+ table.totalsRowCount = table_style_int(y, "totalsRowCount");
16822
+ table.totalsRowShown = table_style_bool(y, "totalsRowShown", false);
16823
+ table.headerRowDxfId = table_style_int(y, "headerRowDxfId");
16824
+ table.dataDxfId = table_style_int(y, "dataDxfId");
16825
+ table.totalsRowDxfId = table_style_int(y, "totalsRowDxfId");
16826
+ table.path = path;
16827
+ break;
16828
+ case '<tableColumn': case '<tableColumn>': case '<tableColumn/>':
16829
+ if(table.columns.length >= TABLE_STYLE_MAX_COLUMNS) {
16830
+ column = null;
16831
+ break;
16832
+ }
16833
+ column = {
16834
+ id:table_style_int(y, "id"),
16835
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16836
+ headerRowDxfId:table_style_int(y, "headerRowDxfId"),
16837
+ dataDxfId:table_style_int(y, "dataDxfId"),
16838
+ totalsRowDxfId:table_style_int(y, "totalsRowDxfId")
16839
+ };
16840
+ table.columns.push(column);
16841
+ if(tag.slice(-2) == "/>" ) column = null;
16842
+ break;
16843
+ case '</tableColumn>': column = null; break;
16844
+ case '<tableStyleInfo': case '<tableStyleInfo>': case '<tableStyleInfo/>':
16845
+ table.styleInfo = {
16846
+ name:utf8read(unescapexml(table_style_attr(y, "name") || "")),
16847
+ showFirstColumn:table_style_bool(y, "showFirstColumn", false),
16848
+ showLastColumn:table_style_bool(y, "showLastColumn", false),
16849
+ showRowStripes:table_style_bool(y, "showRowStripes", false),
16850
+ showColumnStripes:table_style_bool(y, "showColumnStripes", false)
16851
+ };
16852
+ break;
16853
+ case '<extLst': case '<extLst>': case '</extLst>': break;
16854
+ case '<ext': pass = true; break;
16855
+ case '</ext>': pass = false; break;
16856
+ default: if(opts && opts.WTF && !pass) {
16857
+ /* Table formulas and filter metadata are intentionally preserved by
16858
+ * the raw XML parser but do not affect visual style resolution. */
16859
+ if(/^<\/?(?:tableColumns|autoFilter|sortState|calculatedColumnFormula|totalsRowFormula|xmlColumnPr)/.test(tag)) break;
16860
+ }
16861
+ }
16862
+ });
16863
+ if(!table.ref) return null;
16864
+ try {
16865
+ table.range = safe_decode_range(table.ref);
16866
+ if(table.range.s.r < 0 || table.range.s.c < 0 || table.range.e.r > 1048575 || table.range.e.c > 16383) return null;
16867
+ } catch(e) { return null; }
16868
+ var styleName = table.styleInfo && table.styleInfo.name;
16869
+ table.styleRules = custom_table_style_rules(styleName, styles) || built_in_table_style_rules(styleName, themes) || {};
16870
+ table.dxfs = styles && styles.Dxfs ? styles.Dxfs : [];
16871
+ return table;
16872
+ }
16873
+
16874
+ function parse_sheet_tables(sheet, zip, path, rels, opts, themes, styles) {
16875
+ if(!sheet || !rels || !rels['!id'] || !opts || !opts.cellStyles) return;
16876
+ var tables = [], seen = Object.create(null);
16877
+ keys(rels['!id']).forEach(function(id) {
16878
+ if(tables.length >= TABLE_STYLE_MAX_TABLES) return;
16879
+ var rel = rels['!id'][id];
16880
+ if(!rel || rel.TargetMode == "External" || typeof rel.Target != "string" || !rel.Target ||
16881
+ (rel.Type != RELS.TABLE && !/\/table$/.test(rel.Type || ""))) return;
16882
+ var tablePath = resolve_path(rel.Target, path);
16883
+ if(seen[tablePath]) return;
16884
+ seen[tablePath] = true;
16885
+ var table = parse_table_xml(getzipstr(zip, tablePath, true), tablePath, themes, styles, opts);
16886
+ if(table) tables.push(table);
16887
+ });
16888
+ if(tables.length) sheet['!tables'] = tables;
16889
+ }
16890
+
16891
+ function table_style_rule_value(rule) {
16892
+ return rule && rule.style ? rule.style : rule;
16893
+ }
16894
+
16895
+ function table_style_stripe_rule(first, second, offset) {
16896
+ var firstSize = first && first.size || 1, secondSize = second && second.size || 1;
16897
+ var period = firstSize + secondSize;
16898
+ if(!period) return null;
16899
+ return offset % period < firstSize ? first : second;
16900
+ }
16901
+
16902
+ function table_style_dxf(table, id) {
16903
+ return id == null || !table.dxfs ? null : table.dxfs[id];
16904
+ }
16905
+
16906
+ function resolve_table_cell_style(ws, row, col, baseStyle) {
16907
+ var tables = ws && ws['!tables'];
16908
+ var resolved = baseStyle ? table_style_merge({}, baseStyle) : {};
16909
+ if(!tables || !tables.length) return keys(resolved).length ? resolved : void 0;
16910
+ for(var i = 0; i < tables.length; ++i) {
16911
+ var table = tables[i], range = table.range;
16912
+ if(!range || row < range.s.r || row > range.e.r || col < range.s.c || col > range.e.c) continue;
16913
+ var rules = table.styleRules || {}, info = table.styleInfo || {};
16914
+ var rowOffset = row - range.s.r, colOffset = col - range.s.c;
16915
+ var headerRows = table.headerRowCount == null ? 1 : table.headerRowCount;
16916
+ var totalRows = table.totalsRowCount != null ? table.totalsRowCount : table.totalsRowShown ? 1 : 0;
16917
+ var dataStart = headerRows, dataEnd = range.e.r - range.s.r - totalRows;
16918
+ var isHeader = rowOffset < headerRows;
16919
+ var isTotal = totalRows > 0 && rowOffset > dataEnd;
16920
+ var dataOffset = rowOffset - dataStart;
16921
+ var column = table.columns && table.columns[colOffset];
16922
+
16923
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.wholeTable));
16924
+ if(!isHeader && !isTotal && dataOffset >= 0) {
16925
+ if(info.showRowStripes) resolved = table_style_merge(resolved, table_style_rule_value(
16926
+ table_style_stripe_rule(rules.firstRowStripe, rules.secondRowStripe, dataOffset)
16927
+ ));
16928
+ if(info.showColumnStripes) resolved = table_style_merge(resolved, table_style_rule_value(
16929
+ table_style_stripe_rule(rules.firstColumnStripe, rules.secondColumnStripe, colOffset)
16930
+ ));
16931
+ }
16932
+ if(info.showFirstColumn && col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstColumn));
16933
+ if(info.showLastColumn && col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastColumn));
16934
+ if(isHeader) {
16935
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.headerRow));
16936
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstHeaderCell));
16937
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastHeaderCell));
16938
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.headerRowDxfId));
16939
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.headerRowDxfId));
16940
+ } else if(isTotal) {
16941
+ resolved = table_style_merge(resolved, table_style_rule_value(rules.totalRow));
16942
+ if(col == range.s.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.firstTotalCell));
16943
+ if(col == range.e.c) resolved = table_style_merge(resolved, table_style_rule_value(rules.lastTotalCell));
16944
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.totalsRowDxfId));
16945
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.totalsRowDxfId));
16946
+ } else {
16947
+ resolved = table_style_merge(resolved, table_style_dxf(table, table.dataDxfId));
16948
+ resolved = table_style_merge(resolved, table_style_dxf(table, column && column.dataDxfId));
16949
+ }
16950
+ }
16951
+ return keys(resolved).length ? resolved : void 0;
16952
+ }
16587
16953
  function parse_ws_xml_dim(ws, s) {
16588
16954
  var d = safe_decode_range(s);
16589
16955
  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);
@@ -16698,7 +17064,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
16698
17064
  if(columns.length > 0) s["!cols"] = columns;
16699
17065
  if(merges.length > 0) {
16700
17066
  s["!merges"] = merges;
16701
- var mergeErrors = validate_merges(s, {WTF: !!(opts && (opts.WTF || opts.validateMerges))});
17067
+ var mergeErrors = validate_merges(s, {WTF: !!(opts && opts.validateMerges)});
16702
17068
  if(mergeErrors.length) s["!mergeErrors"] = mergeErrors;
16703
17069
  }
16704
17070
  if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
@@ -16813,7 +17179,8 @@ function parse_ws_xml_cols(columns, cols) {
16813
17179
  var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
16814
17180
  if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
16815
17181
  delete coll.min; delete coll.max; coll.width = +coll.width;
16816
- /* OOXML widths share the workbook Normal-font MDW; do not infer a different scale per sheet. */
17182
+ /* OOXML widths share the workbook Normal-font MDW. Do not infer it from
17183
+ * one ambiguous stored width or leak another worksheet's scale. */
16817
17184
  if(!seencol && coll.width) { seencol = true; MDW = DEF_MDW; }
16818
17185
  process_col(coll);
16819
17186
  while(colm <= colM) columns[colm++] = dup(coll);
@@ -17236,7 +17603,7 @@ function write_ws_xml(idx, opts, wb, rels) {
17236
17603
  /* customSheetViews */
17237
17604
 
17238
17605
  if(ws['!merges'] != null && ws['!merges'].length > 0) {
17239
- validate_merges(ws, {WTF:true});
17606
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
17240
17607
  o[o.length] = (write_ws_xml_merges(ws['!merges']));
17241
17608
  }
17242
17609
 
@@ -18722,7 +19089,6 @@ function check_wb(wb) {
18722
19089
  check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
18723
19090
  for(var i = 0; i < wb.SheetNames.length; ++i) {
18724
19091
  var ws = sheet_map_get(wb.Sheets, wb.SheetNames[i]);
18725
- if(!ws) throw new Error("Missing worksheet |" + wb.SheetNames[i] + "|");
18726
19092
  check_ws(ws, wb.SheetNames[i], i);
18727
19093
  }
18728
19094
  wb.SheetNames.forEach(function(n, i) {
@@ -21140,7 +21506,7 @@ function parse_workbook(blob, options) {
21140
21506
  };
21141
21507
  var finalize_sheet_visuals = function finalizesheetvisuals(ws) {
21142
21508
  if(ws["!merges"] && ws["!merges"].length) {
21143
- var mergeErrors = validate_merges(ws, {WTF: !!(options && (options.WTF || options.validateMerges))});
21509
+ var mergeErrors = validate_merges(ws, {WTF: !!(options && options.validateMerges)});
21144
21510
  if(mergeErrors.length) ws["!mergeErrors"] = mergeErrors;
21145
21511
  }
21146
21512
  if(drawings && (drawings.images.length || drawings.shapes.length || drawings.charts.length || drawings.raw.length)) ws["!drawings"] = drawings;
@@ -23695,7 +24061,7 @@ function write_ws_biff8(idx, opts, wb) {
23695
24061
  if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
23696
24062
  /* ... */
23697
24063
  if(b8 && (ws['!merges']||[]).length) {
23698
- validate_merges(ws, {WTF:true});
24064
+ validate_merges(ws, {WTF: !!(opts && opts.validateMerges)});
23699
24065
  write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
23700
24066
  }
23701
24067
  /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
@@ -24084,6 +24450,7 @@ function make_html_row(ws, r, R, o) {
24084
24450
  if(cols[C] && cols[C].s) extend_style_obj(inherited, cols[C].s);
24085
24451
  if(row && row.s) extend_style_obj(inherited, row.s);
24086
24452
  if(cell && cell.s) extend_style_obj(inherited, cell.s);
24453
+ inherited = resolve_table_cell_style(ws, R, C, inherited) || inherited;
24087
24454
  if(keys(inherited).length) {
24088
24455
  stylecell = cell ? dup(cell) : {t:'z'};
24089
24456
  stylecell.s = inherited;
@@ -28210,6 +28577,7 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28210
28577
  case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
28211
28578
  default: throw new Error("Unrecognized sheet type " + stype);
28212
28579
  }
28580
+ if(stype == "sheet") parse_sheet_tables(_ws, zip, path, sheetRels[sheet], opts, themes, styles);
28213
28581
  sheet_map_set(sheets, sheet, _ws);
28214
28582
 
28215
28583
  /* scan rels for comments and threaded comments */
@@ -28230,7 +28598,9 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
28230
28598
  if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
28231
28599
  if(stype == "sheet") parse_sheet_drawing(_ws, stype, zip, path, idx, opts, wb);
28232
28600
  parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
28233
- } catch(e) { if(opts.WTF) throw e; }
28601
+ } catch(e) {
28602
+ if(opts.WTF || (opts.validateMerges && e && /^E_MERGE_/.test(e.code))) throw e;
28603
+ }
28234
28604
  }
28235
28605
 
28236
28606
  function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
@@ -29531,6 +29901,7 @@ var utils = {
29531
29901
  measure_text_width: measure_text_width,
29532
29902
  auto_fit_columns: auto_fit_columns,
29533
29903
  autofit_columns: auto_fit_columns,
29904
+ resolve_table_cell_style: resolve_table_cell_style,
29534
29905
  col_width_to_px: width2px,
29535
29906
  px_to_col_width: function(px) { return char2width(px2char(px)); },
29536
29907
  row_height_to_px: pt2px_browser,