diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7c3612..350b601 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ 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.
+* Sheet Visibility for ODS / FODS (h/t @edemaine)
+* HTML DOM ingress support formulae (`data-f`)
+* Proper handling of XLSX encoded entities (h/t @inreoh)
+
## v0.20.3
* Correct parsing of NUMBERS and ODS merge cells (h/t @s-ashwin)
diff --git a/bits/22_xmlutils.js b/bits/22_xmlutils.js
index bf0d9ea..fb4e5ef 100644
--- a/bits/22_xmlutils.js
+++ b/bits/22_xmlutils.js
@@ -67,7 +67,7 @@ var rencoding = /*#__PURE__*/evert(encodings);
// TODO: CP remap (need to read file version to determine OS)
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
/* 22.4.2.4 bstr (Basic String) */
- var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
+ var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/g;
function raw_unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
diff --git a/bits/79_html.js b/bits/79_html.js
index b271a84..5143a68 100644
--- a/bits/79_html.js
+++ b/bits/79_html.js
@@ -92,6 +92,7 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
// note: data-v is unaffected by the timezone interpretation
if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
if(cell.z != null) sp["data-z"] = cell.z;
+ if(cell.f != null) sp["data-f"] = escapehtml(cell.f);
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '' + w + '';
}
sp.id = (o.id || "sjs") + "-" + coord;
@@ -179,6 +180,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
if (opts.display && is_dom_element_hidden(elt)) continue;
var v/*:?string*/ = elt.hasAttribute('data-v') ? elt.getAttribute('data-v') : elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML);
var z/*:?string*/ = elt.getAttribute('data-z') || elt.getAttribute('z');
+ var f/*:?string*/ = elt.hasAttribute('data-f') ? elt.getAttribute('data-f') : elt.hasAttribute('f') ? elt.getAttribute('f') : null;
for(midx = 0; midx < merges.length; ++midx) {
var m/*:Range*/ = merges[midx];
if(m.s.c == C + or_C && m.s.r < R + or_R && R + or_R <= m.e.r) { C = m.e.c+1 - or_C; midx = -1; }
@@ -210,6 +212,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
}
if(l && l.charAt(0) != "#" && l.slice(0, 11).toLowerCase() != 'javascript:') o.l = ({ Target: l });
+ if(f != null) o.f = f;
if(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][R + or_R][C + or_C] = o; }
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
if(range.e.c < C + or_C) range.e.c = C + or_C;
diff --git a/bits/80_parseods.js b/bits/80_parseods.js
index 769d88e..ff1718b 100644
--- a/bits/80_parseods.js
+++ b/bits/80_parseods.js
@@ -252,11 +252,11 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
var textR = [], oldtextR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
- var number_format_map = _nfm || {}, styles = {};
+ var number_format_map = _nfm || {}, styles = {}, tstyles = {};
var merges/*:Array*/ = [], mrange = {}, mR = 0, mC = 0;
var rowinfo/*:Array*/ = [], rowpeat = 1, colpeat = 1;
var arrayf/*:Array<[Range, string]>*/ = [];
- var WB = {Names:[], WBProps:{}};
+ var WB = {Names:[], WBProps:{}, Sheets:[]};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments/*:Array*/ = [], comment/*:Comment*/ = ({}/*:any*/);
@@ -282,6 +282,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
+ WB.Sheets.push({
+ /* TODO: CodeName */
+ Hidden: (tstyles[sheetag["style-name"]] && tstyles[sheetag["style-name"]]["display"] ? (parsexmlbool(tstyles[sheetag["style-name"]]["display"]) ? 0 : 1) : 0)
+ });
intable = false;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
@@ -529,12 +533,16 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'style': { // 16.2
var styletag = parsexmltag(Rn[0], false);
if(styletag["family"] == "table-cell" && number_format_map[styletag["data-style-name"]]) styles[styletag["name"]] = number_format_map[styletag["data-style-name"]];
+ else if(styletag["family"] == "table") tstyles[styletag["name"]] = styletag;
} break;
case 'map': break; // 16.3
case 'font-face': break; // 16.21
case 'paragraph-properties': break; // 17.6
- case 'table-properties': break; // 17.15
+ case 'table-properties': { // 17.15
+ var proptag = parsexmltag(Rn[0], false);
+ if(styletag && styletag.family == "table") styletag.display = proptag.display;
+ } break;
case 'table-column-properties': break; // 17.16
case 'table-row-properties': break; // 17.17
case 'table-cell-properties': break; // 17.18
diff --git a/bits/81_writeods.js b/bits/81_writeods.js
index 997f42f..d6386db 100644
--- a/bits/81_writeods.js
+++ b/bits/81_writeods.js
@@ -214,7 +214,9 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
/* Section 9 Tables */
var o/*:Array*/ = [];
- o.push(' \n');
+ var tstyle = "ta1";
+ if(((((wb||{}).Workbook||{}).Sheets||[])[i]||{}).Hidden) tstyle = "ta2";
+ o.push(' \n');
var R=0,C=0, range = decode_range(ws['!ref']||"A1");
var marr/*:Array*/ = ws['!merges'] || [], mi = 0;
var dense = ws["!data"] != null;
@@ -362,6 +364,9 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
o.push(' \n');
o.push(' \n');
o.push(' \n');
+ o.push(' \n');
+ o.push(' \n');
+ o.push(' \n');
o.push(' \n');
o.push(' \n');
diff --git a/package.json b/package.json
index 3d78bd0..d84c746 100644
--- a/package.json
+++ b/package.json
@@ -142,10 +142,7 @@
"url": "https://git.sheetjs.com/SheetJS/sheetjs"
},
"scripts": {
- "pretest": "npm run lint",
- "test": "npm run tests-only",
- "pretest-only": "git submodule init && git submodule update",
- "tests-only": "make travis",
+ "test": "make travis",
"build": "make",
"lint": "make fullint",
"dtslint": "dtslint types"
diff --git a/test.js b/test.js
index baca005..0a3853b 100644
--- a/test.js
+++ b/test.js
@@ -1772,8 +1772,8 @@ describe('roundtrip features', function() {
['xlsx', paths.svxlsx],
['xlsb', paths.svxlsb],
['xls', paths.svxls],
- ['biff5', paths.svxls5]
- // ['ods', paths.svods]
+ ['biff5', paths.svxls5],
+ ['ods', paths.svods]
].forEach(function(w) {
it(w[0], function() {
var wb1 = X.read(fs.readFileSync(w[1]), {type:TYPE});
@@ -1783,7 +1783,9 @@ describe('roundtrip features', function() {
assert.equal(wbs1.length, wbs2.length);
for(var i = 0; i < wbs1.length; ++i) {
assert.equal(wbs1[i].name, wbs2[i].name);
- assert.equal(wbs1[i].Hidden, wbs2[i].Hidden);
+ /* NOTE: ODS does not support the equivalent of "Very Hidden" */
+ if(w[0] != "ods") assert.equal(wbs1[i].Hidden, wbs2[i].Hidden);
+ else assert.equal(!!wbs1[i].Hidden, !!wbs2[i].Hidden);
}
});
});