Skip to content

Commit

Permalink
version bump 0.15.6: niggles from 2012
Browse files Browse the repository at this point in the history
- CFB prevent infinite loop (h/t @rossj)
- pass updated eslint checks (fixes SheetJS#1726 h/t @BjoernRave)
- defined name proper encoding (fixes SheetJS#1785 h/t @laohe98)
- correct theme color order (fixes SheetJS#389 h/t @foreverpw)
- ODS / XLML more aggressive flagging of stub cells
- cellStyles implies sheetStubs
- updated SSF to 0.10.3
  • Loading branch information
SheetJSDev committed Mar 15, 2020
1 parent a81bb78 commit 0a57229
Show file tree
Hide file tree
Showing 45 changed files with 722 additions and 302 deletions.
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.

## v0.15.6

* CFB prevent infinite loop
* ODS empty cells marked as stub (type "z")
* `cellStyles` option implies `sheetStubs`

## v0.15.5

* `sheets` parse option to specify which sheets to parse

## v0.15.4

* AOA utilities properly preserve number formats
* Number formats captured in stub cells

## v0.15.3

* Properties and Custom Properties properly XML-encoded

## v0.15.2

- `sheet_get_cell` utility function
- `sheet_to_json` explicitly support `null` as alias for default behavior
- `encode_col` throw on negative column index
- HTML properly handle whitespace around tags in a run
- HTML use `id` option on write
- Files starting with `0x09` followed by a display character are now TSV files
- XLS parse references col/row indices mod by the correct number for BIFF ver
- XLSX comments moved to avoid overlapping cell
- XLSB outline level
- AutoFilter update `_FilterDatabase` defined name on write
- XLML skip CDATA blocks

## v0.15.1 (2019-08-14)

* XLSX ignore XML artifacts
Expand Down
13 changes: 7 additions & 6 deletions bin/xlsx.njs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ if(program.all) {
opts.sheetStubs = true;
opts.cellDates = true;
wopts.cellStyles = true;
wopts.sheetStubs = true;
wopts.bookVBA = true;
}
if(program.sparse) opts.dense = false; else opts.dense = true;
Expand Down Expand Up @@ -165,26 +166,26 @@ if(program.dump) {
process.exit(0);
}
if(program.props) {
dump_props(wb);
if(wb) dump_props(wb);
process.exit(0);
}

/* full workbook formats */
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });

wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });

var target_sheet = sheetname || '';
if(target_sheet === '') {
if(program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[program.sheetIndex];
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
else target_sheet = (wb.SheetNames||[""])[0];
}

Expand Down Expand Up @@ -269,13 +270,13 @@ function dump_props(wb/*:Workbook*/) {
if(wb.Props) {
Keys = Object.keys(wb.Props);
for(pi = 0; pi < Keys.length; ++pi) {
if(Keys.hasOwnProperty(Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
if(wb.Custprops) {
Keys = Object.keys(wb.Custprops);
for(pi = 0; pi < Keys.length; ++pi) {
if(Keys.hasOwnProperty(Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bits/01_version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
XLSX.version = '0.15.5';
XLSX.version = '0.15.6';
7 changes: 4 additions & 3 deletions bits/10_ssf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*jshint -W041 */
var SSF/*:SSFModule*/ = ({}/*:any*/);
var make_ssf = function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.10.2';
SSF.version = '0.10.3';
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
Expand Down Expand Up @@ -169,7 +169,7 @@ function general_fmt(v/*:any*/, opts/*:any*/) {
switch(typeof v) {
case 'string': return v;
case 'boolean': return v ? "TRUE" : "FALSE";
case 'number': return (v|0) === v ? general_fmt_int(v) : general_fmt_num(v);
case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
case 'undefined': return "";
case 'object':
if(v == null) return "";
Expand Down Expand Up @@ -552,7 +552,7 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
case '@': ++i; break;
Expand Down Expand Up @@ -661,6 +661,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
out[out.length] = {t:'D', v:o}; break;
case ' ': out[out.length] = {t:c, v:c}; ++i; break;
case "$": out[out.length] = {t:'t', v:'$'}; ++i; break;
default:
if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
out[out.length] = {t:'t', v:c}; ++i; break;
Expand Down
7 changes: 5 additions & 2 deletions bits/18_cfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ declare var new_unsafe_buf:any;
/* vim: set ts=2: */
/*jshint eqnull:true */
/*exported CFB */
/*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */
/*global Uint8Array:false, Uint16Array:false */

/*::
declare var DO_NOT_EXPORT_CFB:?boolean;
Expand Down Expand Up @@ -142,7 +142,7 @@ CRC32.str = crc32_str;
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.1.3';
exports.version = '1.1.4';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
Expand Down Expand Up @@ -473,7 +473,9 @@ function make_sector_list(sectors/*:Array<RawBytes>*/, dir_start/*:number*/, fat
k = (i + dir_start); if(k >= sl) k-=sl;
if(chkd[k]) continue;
buf_chain = [];
var seen = [];
for(j=k; j>=0;) {
seen[j] = true;
chkd[j] = true;
buf[buf.length] = j;
buf_chain.push(sectors[j]);
Expand All @@ -482,6 +484,7 @@ function make_sector_list(sectors/*:Array<RawBytes>*/, dir_start/*:number*/, fat
if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
if(!sectors[addr]) break;
j = __readInt32LE(sectors[addr], jj);
if(seen[j]) break;
}
sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/);
}
Expand Down
2 changes: 1 addition & 1 deletion bits/19_fsutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function blobify(data) {
}
/* write or download file */
function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
/*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
var data = (enc == "utf8") ? utf8write(payload) : payload;
/*:: declare var IE_SaveFile: any; */
Expand Down
4 changes: 2 additions & 2 deletions bits/20_jsutils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function keys(o/*:any*/)/*:Array<any>*/ {
var ks = Object.keys(o), o2 = [];
for(var i = 0; i < ks.length; ++i) if(o.hasOwnProperty(ks[i])) o2.push(ks[i]);
for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
return o2;
}

Expand Down Expand Up @@ -106,7 +106,7 @@ function dup(o/*:any*/)/*:any*/ {
if(typeof o != 'object' || o == null) return o;
if(o instanceof Date) return new Date(o.getTime());
var out = {};
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
return out;
}

Expand Down
4 changes: 2 additions & 2 deletions bits/22_xmlutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ var rencoding = evert(encodings);
// TODO: CP remap (need to read file version to determine OS)
var unescapexml/*:StringConv*/ = (function() {
/* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g, coderegex = /_x([\da-fA-F]{4})_/g;
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
Expand Down Expand Up @@ -175,7 +175,7 @@ var htmldecode/*:{(s:string):string}*/ = (function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; });
].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
return function htmldecode(str/*:string*/)/*:string*/ {
var o = str
// Remove new lines and spaces from start of content
Expand Down
2 changes: 1 addition & 1 deletion bits/25_cellutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function encode_range_xls(r, opts)/*:string*/ {
}
}
if(r.s.c == 0 && !r.s.cRel) {
if(r.e.c == (opts.biff >= 12 ? 0xFFFF : 0xFF) && !r.e.cRel) {
if(r.e.c == (opts.biff >= 12 ? 0x3FFF : 0xFF) && !r.e.cRel) {
return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
}
}
Expand Down
25 changes: 25 additions & 0 deletions bits/28_binstructs.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ function write_XLWideString(data/*:string*/, o) {
return _null ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.5.91 */
//function parse_LPWideString(data/*::, length*/)/*:string*/ {
// var cchCharacters = data.read_shift(2);
// return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, "utf16le");
//}

/* [MS-XLSB] 2.5.143 */
function parse_StrRun(data) {
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
Expand Down Expand Up @@ -149,6 +155,25 @@ function write_RfX(r/*:Range*/, o) {
var parse_UncheckedRfX = parse_RfX;
var write_UncheckedRfX = write_RfX;

/* [MS-XLSB] 2.5.155 UncheckedSqRfX */
//function parse_UncheckedSqRfX(data) {
// var cnt = data.read_shift(4);
// var out = [];
// for(var i = 0; i < cnt; ++i) {
// var rng = parse_UncheckedRfX(data);
// out.push(encode_range(rng));
// }
// return out.join(",");
//}
//function write_UncheckedSqRfX(sqrfx/*:string*/) {
// var parts = sqrfx.split(/\s*,\s*/);
// var o = new_buf(4); o.write_shift(4, parts.length);
// var out = [o];
// parts.forEach(function(rng) {
// out.push(write_UncheckedRfX(safe_decode_range(rng)));
// });
// return bconcat(out);
//}

/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
Expand Down
2 changes: 1 addition & 1 deletion bits/29_xlsenum.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ var SpecialProperties = {
};

(function() {
for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
for(var y in SpecialProperties) if(Object.prototype.hasOwnProperty.call(SpecialProperties, y))
DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
})();

Expand Down
6 changes: 3 additions & 3 deletions bits/36_xlsprops.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function xlml_write_custprops(Props, Custprops/*::, opts*/) {
var o/*:Array<string>*/ = [];
if(Props) keys(Props).forEach(function(k) {
/*:: if(!Props) return; */
if(!Props.hasOwnProperty(k)) return;
if(!Object.prototype.hasOwnProperty.call(Props, k)) return;
for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
Expand All @@ -77,8 +77,8 @@ function xlml_write_custprops(Props, Custprops/*::, opts*/) {
});
if(Custprops) keys(Custprops).forEach(function(k) {
/*:: if(!Custprops) return; */
if(!Custprops.hasOwnProperty(k)) return;
if(Props && Props.hasOwnProperty(k)) return;
if(!Object.prototype.hasOwnProperty.call(Custprops, k)) return;
if(Props && Object.prototype.hasOwnProperty.call(Props, k)) return;
var m = Custprops[k];
var t = "string";
if(typeof m == 'number') { t = "float"; m = String(m); }
Expand Down
2 changes: 1 addition & 1 deletion bits/39_xlsbiff.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ function write_Window1(/*::opts*/) {
}
/* [MS-XLS] 2.4.346 TODO */
function parse_Window2(blob, length, opts) {
if(opts && opts.biff >= 2 && opts.biff < 8) return {};
if(opts && opts.biff >= 2 && opts.biff < 5) return {};
var f = blob.read_shift(2);
return { RTL: f & 0x40 };
}
Expand Down
4 changes: 2 additions & 2 deletions bits/40_harb.js
Original file line number Diff line number Diff line change
Expand Up @@ -790,13 +790,13 @@ var PRN = (function() {
}

cc = [];
for(end in cnt) if ( cnt.hasOwnProperty(end) ) {
for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
cc.push([ cnt[end], end ]);
}

if ( !cc.length ) {
cnt = guess_sep_weights;
for(end in cnt) if ( cnt.hasOwnProperty(end) ) {
for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
cc.push([ cnt[end], end ]);
}
}
Expand Down
4 changes: 2 additions & 2 deletions bits/47_styxml.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function parse_fonts(t, styles, themes, opts) {
break;

/* 18.8.29 name CT_FontName */
case '<name': if(y.val) font.name = y.val; break;
case '<name': if(y.val) font.name = utf8read(y.val); break;
case '<name/>': case '</name>': break;

/* 18.8.2 b CT_BooleanProperty */
Expand Down Expand Up @@ -396,11 +396,11 @@ return function parse_sty_xml(data, themes, opts) {
if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);

/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */

/* 18.8.10 cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);

/* 18.8.8 cellStyles CT_CellStyles ? */
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */
/* 18.8.11 colors CT_Colors ? */
Expand Down
9 changes: 8 additions & 1 deletion bits/49_theme.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";

/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
var XLSXThemeClrScheme = [
'</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
'</a:accent1>', '</a:accent2>', '</a:accent3>',
'</a:accent4>', '</a:accent5>', '</a:accent6>',
'</a:hlink>', '</a:folHlink>'
];
/* 20.1.6.2 clrScheme CT_ColorScheme */
function parse_clrScheme(t, themes, opts) {
themes.themeElements.clrScheme = [];
Expand Down Expand Up @@ -43,7 +50,7 @@ function parse_clrScheme(t, themes, opts) {
case '<a:hlink>': case '</a:hlink>':
case '<a:folHlink>': case '</a:folHlink>':
if (y[0].charAt(1) === '/') {
themes.themeElements.clrScheme.push(color);
themes.themeElements.clrScheme[XLSXThemeClrScheme.indexOf(y[0])] = color;
color = {};
} else {
color.name = y[0].slice(3, y[0].length - 1);
Expand Down
2 changes: 1 addition & 1 deletion bits/61_fcommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var rc_to_a1 = (function(){
};
})();

var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
var a1_to_rc =(function(){
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
Expand Down
4 changes: 2 additions & 2 deletions bits/66_wscommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var browser_has_Map = typeof Map !== 'undefined';
function get_sst_id(sst/*:SST*/, str/*:string*/, rev)/*:number*/ {
var i = 0, len = sst.length;
if(rev) {
if(browser_has_Map ? rev.has(str) : rev.hasOwnProperty(str)) {
if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
var revarr = browser_has_Map ? rev.get(str) : rev[str];
for(; i < revarr.length; ++i) {
if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
Expand All @@ -27,7 +27,7 @@ function get_sst_id(sst/*:SST*/, str/*:string*/, rev)/*:number*/ {
if(!rev.has(str)) rev.set(str, []);
rev.get(str).push(len);
} else {
if(!rev.hasOwnProperty(str)) rev[str] = [];
if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
rev[str].push(len);
}
}
Expand Down
2 changes: 1 addition & 1 deletion bits/72_wbxml.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
if(n.Hidden) d.hidden = "1";
if(!n.Ref) return;
o[o.length] = writextag('definedName', String(n.Ref).replace(/</g, "&lt;").replace(/>/g, "&gt;"), d);
o[o.length] = writextag('definedName', escapexml(n.Ref), d);
});
o[o.length] = "</definedNames>";
}
Expand Down
Loading

0 comments on commit 0a57229

Please sign in to comment.