version bump 0.9.4

- changed regexes to handle odd XML (fixes #191 h/t @chk- @imsaquib)
- XLML roundtrip 1252 encoding
- browser core tests added to main repo
This commit is contained in:
SheetJS 2017-03-20 17:42:12 -04:00
parent 245dd7fd82
commit 3cacfc406c
24 changed files with 7666 additions and 222 deletions

@ -1022,7 +1022,10 @@ $ make lint # JSHint and JSCS checks
$ make flow # make lint + Flow checking
```
To run the in-browser tests, clone the repo for
The core in-browser tests are available at `tests/test.html` within this repo.
Start a local server and navigate to that directory to run the tests.
To run the full in-browser tests, clone the repo for
[oss.sheetjs.com](https://github.com/SheetJS/SheetJS.github.io) and replace
the xlsx.js file (then fire up the browser and go to `stress.html`):

@ -1 +1 @@
XLSX.version = '0.9.3';
XLSX.version = '0.9.4';

@ -2,11 +2,11 @@ function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
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);
}
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var hlinkregex = /<(?:\w*:)?hyperlink [^>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
var colregex = /<(?:\w*:)?col[^>]*[\/]?>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;

@ -797,7 +797,14 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
case 's': t = 'String'; p = escapexml(cell.v||""); break;
}
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(__i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
return writextag("Cell", m, attr);
}

24
dist/xlsx.core.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

24
dist/xlsx.full.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

670
dist/xlsx.js vendored

File diff suppressed because it is too large Load Diff

23
dist/xlsx.min.js vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map vendored

File diff suppressed because one or more lines are too long

@ -27,7 +27,10 @@ $ make lint # JSHint and JSCS checks
$ make flow # make lint + Flow checking
```
To run the in-browser tests, clone the repo for
The core in-browser tests are available at `tests/test.html` within this repo.
Start a local server and navigate to that directory to run the tests.
To run the full in-browser tests, clone the repo for
[oss.sheetjs.com](https://github.com/SheetJS/SheetJS.github.io) and replace
the xlsx.js file (then fire up the browser and go to `stress.html`):

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.9.3",
"version": "0.9.4",
"author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS (ODS/FODS/UOS) spreadsheet parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],

1152
tests/core.js Normal file

File diff suppressed because it is too large Load Diff

46
tests/fixtures.js Normal file

File diff suppressed because one or more lines are too long

45
tests/fs_.js Normal file

@ -0,0 +1,45 @@
var assert = function(bool) { if(!bool) { throw new Error("failed assert"); } };
assert.deepEqualArray = function(x,y) {
if(x.length != y.length) throw new Error("Length mismatch: " + x.length + " != " + y.length);
for(var i = 0; i < x.length; ++i) assert.deepEqual(x[i], y[i]);
};
assert.deepEqual = function(x,y) {
if(x == y) return true;
if(Array.isArray(x) && Array.isArray(y) && x.length > 5) return assert.deepEqualArray(x,y);
if(typeof x != 'object' || typeof y != 'object') throw new Error(x + " !== " + y);
Object.keys(x).forEach(function(k) { assert.deepEqual(x[k], y[k]); });
Object.keys(y).forEach(function(k) { assert.deepEqual(x[k], y[k]); });
};
assert.notEqual = function(x,y) { if(x == y) throw new Error(x + " == " + y); };
assert.equal = function(x,y) { if(x != y) throw new Error(x + " !== " + y); };
assert.throws = function(cb) { var pass = true; try { cb(); pass = false; } catch(e) { } if(!pass) throw new Error("Function did not throw"); };
assert.doesNotThrow = function(cb) { var pass = true; try { cb(); } catch(e) { pass = false; } if(!pass) throw new Error("Function did throw"); };
function require(s) {
switch(s) {
case 'fs': return fs;
case 'assert': return assert;
case './': return XLSX;
}
if(s.slice(-5) == ".json") return JSON.parse(fs.readFileSync(s));
}
var fs = {};
fs.existsSync = function(p) { return !!fs[p]; };
fs.readdirSync = function(p) { return Object.keys(fs).filter(function(n) {
return fs.hasOwnProperty(n) && n.slice(-4) != "Sync"; });
};
fs.readFileSync = function(f, enc) {
if(!fs[f]) throw "File not found: " + f;
switch(enc) {
case 'base64': return fs[f];
case 'buffer':
var o = atob(fs[f]), oo = [];
for(var i = 0; i < o.length; ++i) oo[i] = o.charCodeAt(i);
return oo;
default: return atob(fs[f]);
}
};
fs.writeFileSync = function(f, d) { fs[f] = d; };

2
tests/make_fixtures.js Normal file

@ -0,0 +1,2 @@
#!/usr/bin/env node
fs.writeFileSync('tests/fixtures.js', Object.keys(paths).concat(['multiformat.lst', './misc/ssf.json', './test_files/biff5/number_format_greek.xls']).map(function(x) { return paths[x] || x; }).map(function(x) { return [x, fs.readFileSync(x).toString('base64')]}).map(function(w) { return "fs['" + w[0] + "'] = '" + w[1] + "';\n"; }).join(""));

260
tests/mocha.css Normal file

@ -0,0 +1,260 @@
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul, #mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1, #mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #C09853;
}
#mocha .test.pass.slow .duration {
background: #B94A48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: white;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd }
#mocha code .init { color: #2F6FAD }
#mocha code .string { color: #5890AD }
#mocha code .keyword { color: #8A6343 }
#mocha code .number { color: #2F6FAD }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}

5554
tests/mocha.js Normal file

File diff suppressed because it is too large Load Diff

1
tests/shim.js Symbolic link

@ -0,0 +1 @@
../shim.js

17
tests/xhr-hack.js Normal file

@ -0,0 +1,17 @@
var IEBinaryToArray_ByteStr_Script =
"<!-- IEBinaryToArray_ByteStr -->\r\n"+
"<script type='text/vbscript'>\r\n"+
"Function IEBinaryToArray_ByteStr(Binary) : IEBinaryToArray_ByteStr = CStr(Binary) : End Function\r\n"+
"Function IEBinaryToArray_ByteStr_Last(Binary)\r\n"+
" Dim lastIndex\r\n"+
" lastIndex = LenB(Binary)\r\n"+
" if lastIndex mod 2 Then\r\n"+
" IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )\r\n"+
" Else\r\n"+
" IEBinaryToArray_ByteStr_Last = "+'""'+"\r\n"+
" End If\r\n"+
"End Function\r\n"+
"</script>\r\n";
document.write(IEBinaryToArray_ByteStr_Script);

1
tests/xlsx.full.min.js vendored Symbolic link

@ -0,0 +1 @@
../dist/xlsx.full.min.js

@ -5,7 +5,7 @@
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.9.3';
XLSX.version = '0.9.4';
var current_codepage = 1200, current_cptable;
/*:: declare var cptable:any; */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -8496,11 +8496,11 @@ function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
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);
}
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var hlinkregex = /<(?:\w*:)?hyperlink [^>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
var colregex = /<(?:\w*:)?col[^>]*[\/]?>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
@ -10793,7 +10793,14 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
case 's': t = 'String'; p = escapexml(cell.v||""); break;
}
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(__i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
return writextag("Cell", m, attr);
}

17
xlsx.js

@ -5,7 +5,7 @@
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.9.3';
XLSX.version = '0.9.4';
var current_codepage = 1200, current_cptable;
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
@ -8443,11 +8443,11 @@ function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
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);
}
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var hlinkregex = /<(?:\w*:)?hyperlink [^>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
var colregex = /<(?:\w*:)?col[^>]*[\/]?>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data, opts, rels, wb, themes, styles) {
if(!data) return data;
@ -10736,7 +10736,14 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
case 's': t = 'String'; p = escapexml(cell.v||""); break;
}
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(__i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
return writextag("Cell", m, attr);
}