提交 5b67ac08 编写于 作者: S SheetJS

version bump 0.11.2: proper plaintext parsing

- dollar currencies and percentages properly detected as numbers
- parse potential CDATA segments in XLSX (fixes #775 h/t @awb99)
- IE8 issues with regex
- altjs demos

Issues:
- fixes #673 h/t @huhm
- fixes #748 h/t @sangpuion
- fixes #749 h/t @GreggOD
- fixes #772 h/t @sangpuion @jyyan
上级 9ba09bab
......@@ -167,19 +167,25 @@ CDNjs automatically pulls the latest version and makes all versions available at
The `demos` directory includes sample projects for:
**Frameworks**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`browserify`](demos/browserify/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Adobe ExtendScript`](demos/extendscript/)
- [`meteor`](demos/meteor/)
- [`phantomjs`](demos/phantomjs/)
- [`vue 2`](demos/vue/)
**JS Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`vue 2`](demos/vue/)
- [`webpack`](demos/webpack/)
**JS Platforms and Integrations**
- [`Adobe ExtendScript`](demos/extendscript/)
- [`phantomjs`](demos/phantomjs/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Other JS engines`](demos/altjs/)
### Optional Modules
<details>
......
XLSX.version = '0.11.1';
XLSX.version = '0.11.2';
......@@ -72,7 +72,7 @@ function parse_isodur(s) {
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
var good_pd = good_pd_date.getFullYear() == 2017;
/* parses aa date as a local date */
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
if(good_pd) {
......@@ -88,7 +88,9 @@ function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
d.setFullYear(d.getFullYear() + 100); return d;
}
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
return new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
return out;
}
function cc2str(arr/*:Array<number>*/)/*:string*/ {
......@@ -117,8 +119,11 @@ function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length
function fuzzynum(s/*:string*/)/*:number*/ {
var v/*:number*/ = Number(s);
if(!isNaN(v)) return v;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"");
if(!isNaN(v = Number(ss))) return v;
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
function fuzzydate(s/*:string*/)/*:Date*/ {
......@@ -128,7 +133,14 @@ function fuzzydate(s/*:string*/)/*:Date*/ {
if(y < 0 || y > 8099) return n;
if((m > 0 || d > 1) && y != 101) return o;
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
if(!s.match(/[a-zA-Z]/)) return o;
if(s.match(/[^-0-9:,\/\\]/)) return o;
return n;
}
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
if(safe_split_regex || typeof re == "string") return str.split(re);
var p = str.split(re), o = [p[0]];
for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
return o;
}
......@@ -44,8 +44,10 @@ 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;
return function unescapexml(text/*:string*/)/*:string*/ {
var s = text + '';
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));});
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));});
var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
};
})();
......
......@@ -8,7 +8,7 @@ var HTML_ = (function() {
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = str.slice(i, j).split(/(:?<tr[^>]*>)/i);
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges = [], midx = 0;
......
jvm-npm.js
sheetjs.*
.PHONY: all
all: duktape nashorn
.PHONY: base
base:
if [ ! -e sheetjs.xlsx ]; then node ../../tests/write.js; fi
.PHONY: duktape
duktape: base ## duktape / skookum demo
sjs skookum.js
.PHONY: nashorn
nashorn: base ## nashorn demo
if [ ! -e jvm-npm.js ]; then curl -O https://rawgit.com/nodyn/jvm-npm/master/src/main/javascript/jvm-npm.js; fi
jjs nashorn.js
# Other JS Engines and Deployments
There are many JS engines and deployments outside of web browsers. NodeJS is the
most popular deployment, but there are many others for special use cases. Some
optimize for low overhead and others optimize for ease of embedding within other
applications. Since it was designed for ES3 engines, the library can be used in
those settings! This demo tries to demonstrate a few alternative deployments.
## Nashorn
Nashorn ships with Java 8. It includes a command-line tool `jjs` for running JS
scripts. It is somewhat limited but does offer access to the full Java runtime.
`jjs` does not provide a CommonJS `require` implementation. This demo uses a
[`shim`](https://rawgit.com/nodyn/jvm-npm/master/src/main/javascript/jvm-npm.js)
and manually requires the library.
The Java `nio` API provides the `Files.readAllBytes` method to read a file into
a byte array. To use in `XLSX.read`, the demo copies the bytes into a plain JS
array and calls `XLSX.read` with type `"array"`.
## duktape and skookum
[Duktape](http://duktape.org/) is an embeddable JS engine written in C. The
amalgamation makes integration extremely simple! Duktape understands the source
code and can process binary strings out the box, but does not provide I/O or
other standard library features.
To demonstrate compatibility with duktape, this demo uses the JS runtime from
[Skookum JS](https://github.com/saghul/sjs). Built upon the duktape engine, it
adds a simple I/O interface to enable reading from files.
#!/usr/bin/env jjs
/* read file */
var path = java.nio.file.Paths.get('sheetjs.xlsx');
var fileArray = java.nio.file.Files.readAllBytes(path);
/* convert to plain JS array */
function b2a(b) {
var out = new Array(b.length);
for(var i = 0; i < out.length; i++) out[i] = b[i];
return out;
}
var u8a = b2a(fileArray);
/* load module */
load('./jvm-npm.js');
JSZip = require('../../jszip.js');
cptable = require('../../dist/cpexcel.js');
XLSX = require('../../xlsx.js');
/* read file */
var wb = XLSX.read(u8a, {type:"array"});
/* get first worksheet */
var ws = wb.Sheets[wb.SheetNames[0]];
var js = XLSX.utils.sheet_to_json(ws, {header:1});
/* print out every line */
js.forEach(function(l) { java.lang.System.out.println(JSON.stringify(l)); });
#!/usr/bin/env sjs
var XLSX = require('../../xlsx.js');
var io = require('io');
var file = io.open("sheetjs.xlsx", "rb");
var strs = [], str = "";
while((str = file.read()).length > 0) strs.push(str);
var data = (Buffer.concat(strs.map(function(x) { return new Buffer(x); })));
var wb = XLSX.read(data, {type:"buffer"});
console.log(wb.Sheets[wb.SheetNames[0]]);
......@@ -105,6 +105,8 @@ function process_wb(wb) {
var data = XLSX.utils.sheet_to_json(ws, {header:1});
if(!cDg) cDg = canvasDatagrid({ parentNode:document.getElementById('htmlout'), data:data });
else cDg.data = data;
var range = XLSX.utils.decode_range(ws['!ref']);
for(var i = range.s.c; i <= range.e.c; ++i) cDg.schema[i - range.s.c].title = XLSX.utils.encode_col(i);
document.getElementById('xport').disabled = false;
if(typeof console !== 'undefined') console.log("output", new Date());
}
......
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
......@@ -25,19 +25,25 @@ CDNjs automatically pulls the latest version and makes all versions available at
The `demos` directory includes sample projects for:
**Frameworks**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`browserify`](demos/browserify/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Adobe ExtendScript`](demos/extendscript/)
- [`meteor`](demos/meteor/)
- [`phantomjs`](demos/phantomjs/)
- [`vue 2`](demos/vue/)
**JS Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`vue 2`](demos/vue/)
- [`webpack`](demos/webpack/)
**JS Platforms and Integrations**
- [`Adobe ExtendScript`](demos/extendscript/)
- [`phantomjs`](demos/phantomjs/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Other JS engines`](demos/altjs/)
### Optional Modules
<details>
......
......@@ -161,19 +161,25 @@ CDNjs automatically pulls the latest version and makes all versions available at
The `demos` directory includes sample projects for:
**Frameworks**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`browserify`](demos/browserify/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Adobe ExtendScript`](demos/extendscript/)
- [`meteor`](demos/meteor/)
- [`phantomjs`](demos/phantomjs/)
- [`vue 2`](demos/vue/)
**JS Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`vue 2`](demos/vue/)
- [`webpack`](demos/webpack/)
**JS Platforms and Integrations**
- [`Adobe ExtendScript`](demos/extendscript/)
- [`phantomjs`](demos/phantomjs/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Other JS engines`](demos/altjs/)
### Optional Modules
......
{
"name": "xlsx",
"version": "0.11.1",
"version": "0.11.2",
"author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLS/XML) ODS and other spreadsheet format (CSV/DIF/DBF/SYLK) parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "csv", "dbf", "dif", "sylk", "office", "spreadsheet" ],
......
......@@ -568,14 +568,14 @@ describe('input formats', function() {
X.read(fs.readFileSync(paths.cstxlsb, 'base64'), {type: 'base64'});
});
var k = browser ? 'array' : 'buffer';
(typeof UInt8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, 'buffer'), {type: k});
X.read(fs.readFileSync(paths.cstxml, 'buffer'), {type: k});
X.read(fs.readFileSync(paths.cstods, 'buffer'), {type: k});
X.read(fs.readFileSync(paths.cstxlsx, 'buffer'), {type: k});
X.read(fs.readFileSync(paths.cstxlsb, 'buffer'), {type: k});
});
(typeof UInt8Array !== 'undefined' ? it : it.skip)('should read array', function() {
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxml, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstods, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxlsx, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxlsb, browser ? 'buffer' : null), {type: k});
});
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() {
X.read(fs.readFileSync(paths.cstxls, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstxml, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstxlsx, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
......@@ -1847,26 +1847,34 @@ describe('csv', function() {
describe('HTML', function() {
describe('input', function(){
var b = "<table><tr><td>1</td><td>4,001</td></tr><tr><td>$41.08</td></tr></table>";
var b = "<table><tr><td>-0.08</td><td>4,001</td><td>\u00e3\u0081\u0082 1</td></tr><tr><td>$41.08</td><td>11%</td></tr></table>";
it('should generate numbers by default', function() {
var sheet = X.read(b, {type:"binary"}).Sheets.Sheet1
var sheet = X.read(b, {type:"binary"}).Sheets.Sheet1;
var cell = get_cell(sheet, "A1");
assert.equal(cell.v, 1);
assert.equal(cell.v, -0.08);
assert.equal(cell.t, 'n');
cell = get_cell(sheet, "B1");
assert.equal(cell.v, 4001);
cell = get_cell(sheet, "C1");
assert.equal(cell.v, "あ 1");
cell = get_cell(sheet, "A2");
assert.equal(cell.v, 41.08);
cell = get_cell(sheet, "B2");
assert.equal(cell.v, .11);
});
it('should generate strings if raw option is passed', function() {
var sheet = X.read(b, {type:"binary", raw:true}).Sheets.Sheet1
var sheet = X.read(b, {type:"binary", raw:true}).Sheets.Sheet1;
var cell = get_cell(sheet, "A1");
assert.equal(cell.v, "1");
assert.equal(cell.v, "-0.08");
assert.equal(cell.t, 's');
cell = get_cell(sheet, "B1");
assert.equal(cell.v, "4,001");
cell = get_cell(sheet, "C1");
assert.equal(cell.v, "あ 1");
cell = get_cell(sheet, "A2");
assert.equal(cell.v, "$41.08");
cell = get_cell(sheet, "B2");
assert.equal(cell.v, "11%");
});
});
});
......
此差异由.gitattributes 抑制。
Makefile
*xlsx*.ts
doc.ts
write.ts
tslint.json
......@@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.11.1';
XLSX.version = '0.11.2';
var current_codepage = 1200;
/*:: declare var cptable:any; */
/*global cptable:true */
......@@ -1539,7 +1539,7 @@ function parse_isodur(s) {
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
var good_pd = good_pd_date.getFullYear() == 2017;
/* parses aa date as a local date */
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
if(good_pd) {
......@@ -1555,7 +1555,9 @@ function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
d.setFullYear(d.getFullYear() + 100); return d;
}
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
return new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
return out;
}
function cc2str(arr/*:Array<number>*/)/*:string*/ {
......@@ -1584,8 +1586,11 @@ function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length
function fuzzynum(s/*:string*/)/*:number*/ {
var v/*:number*/ = Number(s);
if(!isNaN(v)) return v;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"");
if(!isNaN(v = Number(ss))) return v;
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
function fuzzydate(s/*:string*/)/*:Date*/ {
......@@ -1595,10 +1600,17 @@ function fuzzydate(s/*:string*/)/*:Date*/ {
if(y < 0 || y > 8099) return n;
if((m > 0 || d > 1) && y != 101) return o;
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
if(!s.match(/[a-zA-Z]/)) return o;
if(s.match(/[^-0-9:,\/\\]/)) return o;
return n;
}
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
if(safe_split_regex || typeof re == "string") return str.split(re);
var p = str.split(re), o = [p[0]];
for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
return o;
}
function getdatastr(data)/*:?string*/ {
if(!data) return null;
if(data.data) return debom(data.data);
......@@ -1720,8 +1732,10 @@ 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;
return function unescapexml(text/*:string*/)/*:string*/ {
var s = text + '';
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));});
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));});
var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
};
})();
......@@ -16369,7 +16383,7 @@ var HTML_ = (function() {
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = str.slice(i, j).split(/(:?<tr[^>]*>)/i);
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges = [], midx = 0;
......
此差异由.gitattributes 抑制。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册