Skip to content

Commit

Permalink
version bump 0.9.0: merged ODS into XLSX
Browse files Browse the repository at this point in the history
The optional ODS module has been completely merged into xlsx.js and the
corresponding scripts have been removed.  The new xlsx.js file provides
appropriate ODS exports, so fixing is a matter of removing ods.js refs.
  • Loading branch information
SheetJSDev committed Mar 10, 2017
1 parent 7b6fb7b commit 54b528e
Show file tree
Hide file tree
Showing 61 changed files with 2,218 additions and 2,709 deletions.
4 changes: 1 addition & 3 deletions .flowconfig
@@ -1,6 +1,7 @@
[ignore]
.*/node_modules/.*
.*/dist/.*
.*/tmp/.*
.*/test.js

.*/bits/.*
Expand All @@ -11,8 +12,6 @@
.*/demo/browser.js
.*/shim.js

.*/odsbits/.*
.*/ods.js
.*/xlsx.js
.*/xlsxworker.js
.*/xlsxworker1.js
Expand All @@ -27,7 +26,6 @@ xlsxworker.flow.js
xlsxworker1.flow.js
xlsxworker2.flow.js
xlsx.flow.js
ods.flow.js
.*/bin/.*.njs
.*/demo/browser.flow.js

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -18,3 +18,4 @@ tmp
*.htm
*.html
*.sheetjs
*.exe
12 changes: 12 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,12 @@
# CHANGELOG

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.


## 0.9.0 (2017-03-09)

* Removed ods.js source. The xlsx.js source absorbed the ODS logic and exposes
the ODS variable, so projects should remove references to ods.js

25 changes: 14 additions & 11 deletions Makefile
Expand Up @@ -3,7 +3,7 @@ LIB=xlsx
FMT=xlsx xlsm xlsb ods xls xml misc full
REQS=jszip.js
ADDONS=dist/cpexcel.js
AUXTARGETS=ods.js
AUXTARGETS=
CMDS=bin/xlsx.njs
HTMLLINT=index.html

Expand Down Expand Up @@ -62,23 +62,18 @@ dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
cat <(head -n 1 bits/00_header.js) $(REQS) $(ADDONS) $(TARGET) $(AUXTARGETS) > demos/requirejs/$(LIB).full.js

.PHONY: dist-deps
dist-deps: ods.js ## Copy dependencies for distribution
dist-deps: ## Copy dependencies for distribution
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
cp jszip.js dist/jszip.js
cp ods.js dist/ods.js
uglifyjs $(UGLIFYOPTS) ods.js -o dist/ods.min.js --source-map dist/ods.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/ods.min.js

.PHONY: aux
aux: $(AUXTARGETS)

.PHONY: ods
ods: ods.js

ODSDEPS=$(sort $(wildcard odsbits/*.js))
ods.flow.js: $(ODSDEPS) ## Build ODS support library
cat $^ | tr -d '\15\32' > $@
.PHONY: nexe
nexe: xlsx.exe

xlsx.exe: bin/xlsx.js xlsx.js
nexe -i bin/xlsx.njs -o xlsx.exe

## Testing

Expand All @@ -92,6 +87,9 @@ TESTFMT=$(patsubst %,test_%,$(FMT))
$(TESTFMT): test_%:
FMTS=$* make test

.PHONY: demos
demos: demo-browserify demo-webpack demo-requirejs

.PHONY: demo-browserify
demo-browserify: ## Run browserify demo build
make -C demos/browserify
Expand All @@ -102,6 +100,11 @@ demo-webpack: ## Run webpack demo build
make -C demos/webpack
@echo "start a local server and go to demos/webpack/webpack.html"

.PHONY: demo-requirejs
demo-requirejs: ## Run requirejs demo build
make -C demos/requirejs
@echo "start a local server and go to demos/requirejs/requirejs.html"

## Code Checking

.PHONY: lint
Expand Down
2 changes: 0 additions & 2 deletions README.md
Expand Up @@ -67,8 +67,6 @@ be included directly:
```html
<!-- international support from js-codepage -->
<script src="dist/cpexcel.js"></script>
<!-- ODS support -->
<script src="dist/ods.js"></script>
```

An appropriate version for each dependency is included in the dist/ directory.
Expand Down
1 change: 1 addition & 0 deletions bits/00_header.js
Expand Up @@ -2,5 +2,6 @@
/* vim: set ts=2: */
/*jshint -W041 */
/*jshint funcscope:true, eqnull:true */
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
2 changes: 1 addition & 1 deletion bits/01_version.js
@@ -1 +1 @@
XLSX.version = '0.8.8';
XLSX.version = '0.9.0';
27 changes: 27 additions & 0 deletions bits/20_jsutils.js
Expand Up @@ -35,6 +35,33 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
}

/* ISO 8601 Duration */
function parse_isodur(s) {
var sec = 0, mt = 0, time = false;
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
for(var i = 1; i != m.length; ++i) {
if(!m[i]) continue;
mt = 1;
if(i > 3) time = true;
switch(m[i].substr(m[i].length-1)) {
case 'Y':
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
case 'D': mt *= 24;
/* falls through */
case 'H': mt *= 60;
/* falls through */
case 'M':
if(!time) throw new Error("Unsupported ISO Duration Field: M");
else mt *= 60;
/* falls through */
case 'S': break;
}
sec += mt * parseInt(m[i], 10);
}
return sec;
}

function cc2str(arr/*:Array<number>*/)/*:string*/ {
var o = "";
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
Expand Down
1 change: 1 addition & 0 deletions bits/21_ziputils.js
Expand Up @@ -22,6 +22,7 @@ function getdatabin(data) {
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }

/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
/* OASIS does not comment on filename case sensitivity */
function safegetzipfile(zip, file/*:string*/) {
var k = keys(zip.files);
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
Expand Down
15 changes: 11 additions & 4 deletions bits/22_xmlutils.js
@@ -1,4 +1,4 @@
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregexg=/([^\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var tagregex=/<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
Expand All @@ -7,14 +7,21 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
if(!skip_root) z[0] = tag.substr(0, eq);
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i];
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
if(j===q.length) z[q] = v;
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
if(j===q.length) {
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
z[q] = v;
}
else {
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
z[k] = v;
}
}
return z;
}
Expand Down
28 changes: 28 additions & 0 deletions odsbits/30_manifest.js → bits/32_odmanrdf.js
@@ -1,3 +1,4 @@
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
/* Part 3 Section 4 Manifest File */
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
function parse_manifest(d, opts) {
Expand Down Expand Up @@ -27,3 +28,30 @@ function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*:string*/ {
o.push('</manifest:manifest>');
return o.join("");
}

/* Part 3 Section 6 Metadata Manifest File */
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
return [
' <rdf:Description rdf:about="' + file + '">\n',
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
' </rdf:Description>\n'
].join("");
}
function write_rdf_has(base/*:string*/, file/*:string*/) {
return [
' <rdf:Description rdf:about="' + base + '">\n',
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
' </rdf:Description>\n'
].join("");
}
function write_rdf(rdf, opts) {
var o = [XML_HEADER];
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
for(var i = 0; i != rdf.length; ++i) {
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
o.push(write_rdf_has("",rdf[i][0]));
}
o.push(write_rdf_type("","Document", "pkg"));
o.push('</rdf:RDF>');
return o.join("");
}
File renamed without changes.
4 changes: 4 additions & 0 deletions bits/67_wsxml.js
Expand Up @@ -249,6 +249,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
case 'n': p.v = parseFloat(p.v); break;
case 's':
sstr = strs[parseInt(p.v, 10)];
if(typeof p.v == 'undefined') {
if(!opts.sheetStubs) continue;
p.t = "stub";
}
p.v = sstr.t;
p.r = sstr.r;
if(opts.cellHTML) p.h = sstr.h;
Expand Down
7 changes: 5 additions & 2 deletions bits/75_xlml.js
Expand Up @@ -85,6 +85,7 @@ function process_style_xlml(styles, stag, opts) {
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o)/*:Workbook*/ {
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
var interiors = [];
var i = 0;
if(sid === undefined && row) sid = row.StyleID;
if(sid === undefined && csty) sid = csty.StyleID;
while(styles[sid] !== undefined) {
Expand Down Expand Up @@ -150,13 +151,15 @@ function xlml_clean_comment(comment/*:any*/) {
}

function xlml_normalize(d)/*:string*/ {
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
throw new Error("Bad input format: expected Buffer or string");
}

/* TODO: Everything */
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
function parse_xlml_xml(d, opts)/*:Workbook*/ {
var str = debom(xlml_normalize(d));
if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts);
Expand Down
12 changes: 8 additions & 4 deletions odsbits/60_content.js → bits/80_parseods.js
@@ -1,5 +1,9 @@
var parse_content_xml = (function() {

var parse_text_p = function(text, tag) {
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
};

var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
Expand Down Expand Up @@ -35,7 +39,7 @@ var parse_content_xml = (function() {

case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = get_utils().encode_range(range);
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
if(merges.length) ws['!merges'] = merges;
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
SheetNames.push(sheetag.name);
Expand Down Expand Up @@ -76,7 +80,7 @@ var parse_content_xml = (function() {
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
q.F = get_utils().encode_range(mrange);
q.F = encode_range(mrange);
arrayf.push([mrange, q.F]);
}
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
Expand Down Expand Up @@ -119,8 +123,8 @@ var parse_content_xml = (function() {
if(textp) q.w = textp;
if(!isstub || opts.cellStubs) {
if(!(opts.sheetRows && opts.sheetRows < R)) {
ws[get_utils().encode_cell({r:R,c:C})] = q;
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
ws[encode_cell({r:R,c:C})] = q;
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
if(range.e.c <= C) range.e.c = C;
}
} else { C += rept; rept = 0; }
Expand Down
4 changes: 2 additions & 2 deletions odsbits/70_content.js → bits/81_writeods.js
Expand Up @@ -4,13 +4,13 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
/* Section 9 Tables */
var o = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
var R=0,C=0, range = get_utils().decode_range(ws['!ref']);
var R=0,C=0, range = decode_range(ws['!ref']);
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
for(; R <= range.e.r; ++R) {
o.push(' <table:table-row>\n');
for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
for(; C <= range.e.c; ++C) {
var ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref];
var ref = encode_cell({r:R, c:C}), cell = ws[ref];
if(cell) switch(cell.t) {
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
Expand Down
59 changes: 41 additions & 18 deletions bits/83_ods.js
@@ -1,21 +1,44 @@
/* Helper functions to call out to ODS */

function get_ods() {
if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./ods.js');
return ODS;
}
function parse_ods(zip, opts) {
get_ods();
if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
return ODS.parse_ods(zip, opts);
/* Part 3: Packages */
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
opts = opts || ({}/*:any*/);
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipdata(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts);
}
function write_ods(wb, opts) {
get_ods();
if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS");
return ODS.write_ods(wb, opts);
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
return parse_content_xml(data, opts);
}
function parse_fods(data, opts) {
get_ods();
if(typeof ODS === 'undefined' || !ODS.parse_fods) throw new Error("Unsupported ODS");
return ODS.parse_fods(data, opts);

function write_ods(wb/*:any*/, opts/*:any*/) {
if(opts.bookType == "fods") return write_content_xml(wb, opts);

/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip = new jszip();
var f = "";

var manifest/*:Array<Array<string> >*/ = [];
var rdf = [];

/* 3:3.3 and 2:2.2.4 */
f = "mimetype";
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");

/* Part 1 Section 2.2 Documents */
f = "content.xml";
zip.file(f, write_content_xml(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "ContentFile"]);

/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip.file(f, write_rdf(rdf, opts));
manifest.push([f, "application/rdf+xml"]);

/* Part 3 Section 4 Manifest File */
f = "META-INF/manifest.xml";
zip.file(f, write_manifest(manifest, opts));

return zip;
}
3 changes: 3 additions & 0 deletions bits/98_exports.js
@@ -1,4 +1,7 @@
XLSX.parse_xlscfb = parse_xlscfb;
XLSX.parse_ods = parse_ods;
XLSX.parse_fods = parse_fods;
XLSX.write_ods = write_ods;
XLSX.parse_zip = parse_zip;
XLSX.read = readSync; //xlsread
XLSX.readFile = readFileSync; //readFile
Expand Down
3 changes: 3 additions & 0 deletions bits/99_footer.js
@@ -1,2 +1,5 @@
})(typeof exports !== 'undefined' ? exports : XLSX);
/*exported XLS */
var XLS = XLSX;
/*exported ODS */
var ODS = XLSX;

0 comments on commit 54b528e

Please sign in to comment.