Compare commits

...

1 Commits

Author SHA1 Message Date
b4bb01c731 XLSX shared formula shift nit
- hid ODS number format warning behind WTF (fixes #3324 h/t @gboysko)
2025-08-27 21:46:09 -04:00
11 changed files with 98 additions and 51 deletions

@ -151,6 +151,10 @@ test-esm: test.mjs ## Run Node ESM test suite
test.ts: test.mts
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
# NOTE: `bun test test.mjs` does not actually run the tests, hence test.test.mjs
test.test.mjs: test.mjs
cp $< $@
.PHONY: test-bun
test-bun: test.test.mjs ## Run Bun test suite
bun test $<

@ -23,9 +23,10 @@ var rc_to_a1 = /*#__PURE__*/(function(){
};
})();
var crefregex = /(^|[^._A-Z0-9])(\$?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])(\$?)(\d{1,7})(?![_.\(A-Za-z0-9])/g;
/* TODO: check if engines support \b */
var crefregex = /(^|[^._A-Za-z0-9])(\$?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])(\$?)(\d{1,7})(?![_.\(A-Za-z0-9])/g;
try {
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;
crefregex = /(^|[^._A-Za-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;
}catch(e){}
var a1_to_rc = /*#__PURE__*/(function(){
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {

@ -205,7 +205,7 @@ function parse_ods_styles(d/*:string*/, _opts, _nfm) {
// TODO: handle more complex maps
y = parsexmltag(Rn[0], false);
if(unescapexml(y["condition"]) == "value()>=0") NF = number_format_map[y["apply-style-name"]] + ";" + NF;
else console.error("ODS number format may be incorrect: " + y["condition"]);
else if(_opts && _opts.WTF) console.error("ODS number format may be incorrect: " + y["condition"]);
break;
case 'number': // <number:number> 16.29.3

@ -3104,6 +3104,11 @@ describe('corner cases', function() {
}
});
});
(fs.existsSync(dir + 'shared_formula.xlsx') ? it : it.skip)('should properly handle defined names in shared formulae', function() {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
describe('encryption', function() {

5
test.mjs generated

@ -3103,6 +3103,11 @@ describe('corner cases', function() {
}
});
});
(fs.existsSync(dir + 'shared_formula.xlsx') ? it : it.skip)('should properly handle defined names in shared formulae', function() {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
describe('encryption', function() {

@ -9,10 +9,10 @@ declare type EmptyFunc = (() => void) | null;
declare var afterEach:(test:EmptyFunc)=>void;
declare var cptable: any;
*/
import * as assert_ from 'https://deno.land/std/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std/encoding/base64.ts';
import * as assert_ from 'https://deno.land/std@0.169.0/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std@0.169.0/encoding/base64.ts';
const assert: any = {...assert_};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e); }})};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e as string); }})};
assert.doesNotThrow = function(f: ()=>void) { f(); };
assert.equal = assert.assertEquals;
assert.notEqual = assert.assertNotEquals;
@ -36,7 +36,7 @@ function readFileSync2(x: string, e?: ShEncoding): Uint8Array | string {
if(!e) return u8;
switch(e) {
case 'utf-8': return new TextDecoder().decode(u8);
case 'base64': return base64_.encode(u8);
case 'base64': return base64_.encode(u8 as any);
case 'buffer': return u8;
case 'binary': return Array.from({length: u8.length}, (_,i) => String.fromCharCode(u8[i])).join("");
}
@ -2724,7 +2724,7 @@ describe('dense mode', function() {
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.equal(ws["!data"]?.[0][0].v, "Link to Sheet2");
assert.equal(ws["!data"]?.[0]![0]!.v, "Link to Sheet2");
});
if(!browser) artifax.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
@ -2736,7 +2736,7 @@ describe('dense mode', function() {
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.ok(!!ws["!data"]);
assert.ok(ws["!data"]?.[0][0]);
assert.ok(ws["!data"]?.[0]![0]);
});
});
it('aoa_to_sheet', function() {
@ -2744,28 +2744,28 @@ describe('dense mode', function() {
var sp = X.utils.aoa_to_sheet(aoa); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
});
it('json_to_sheet', function() {
var json = [{"SheetJS": 5433795}];
var sp = X.utils.json_to_sheet(json); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_aoa', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_json', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader:true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.ok(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.ok(!ds["A2"]);
});
for(var ofmti = 0; ofmti < ofmt.length; ++ofmti) { var f = ofmt[ofmti];
it('write ' + f, function() {
@ -3022,6 +3022,11 @@ describe('corner cases', function() {
}
});
});
if(fs.existsSync(dir + 'shared_formula.xlsx')) it('should properly handle defined names in shared formulae', function() {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
describe('encryption', function() {
@ -3033,14 +3038,14 @@ describe('encryption', function() {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'Password',WTF:opts.WTF});
throw new Error("incorrect password was accepted");
} catch(e) {
if(e.message != "Password is incorrect") throw e;
if((e as any).message != "Password is incorrect") throw e;
}
});
it('should recognize correct password', function() {
try {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
} catch(e) {
if(e.message == "Password is incorrect") throw e;
if((e as any).message == "Password is incorrect") throw e;
}
});
if(false) it('should decrypt file', function() {

19
test.sh

@ -2,8 +2,12 @@
set -euxo pipefail
TZONES=(America/New_York Europe/London Asia/Seoul America/Los_Angeles Europe/Berlin Asia/Kolkata Asia/Shanghai America/Cancun America/Anchorage America/Barbados Asia/Tokyo America/Cayman Pacific/Honolulu America/Mexico_City Asia/Hong_Kong Europe/Paris Atlantic/Azores)
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
if [ -e datetest.js ]; then
sudo n 20;
nvm use 20
# sudo n 20;
for TZ in ${TZONES[@]}; do
echo "$TZ"
env TZ="$TZ" mocha -R dot datetest.js
@ -11,19 +15,22 @@ if [ -e datetest.js ]; then
fi
# min test
for n in 20 10 0.8 0.10 0.12 4 6 8 12 14 16 18; do
sudo n $n
for n in 20 10 0.8 0.10 0.12 4 6 8 12 14 16 18 22 24; do
nvm use $n
# sudo n $n
env WTF=1 make testdot_misc
for TZ in ${TZONES[@]}; do
sudo n $n
# sudo n $n
nvm use $n
env WTF=1 TZ="$TZ" make testdot_misc
done
done
# full test
for n in 20 10 0.12; do
for n in 24 16 0.12; do
for TZ in America/New_York Asia/Seoul Asia/Kolkata Europe/Paris; do
sudo n $n
# sudo n $n
nvm use $n
env WTF=1 TZ="$TZ" make testdot
done
done

5
test.test.mjs generated

@ -3103,6 +3103,11 @@ describe('corner cases', function() {
}
});
});
(fs.existsSync(dir + 'shared_formula.xlsx') ? it : it.skip)('should properly handle defined names in shared formulae', function() {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
describe('encryption', function() {

33
test.ts

@ -9,10 +9,10 @@ declare type EmptyFunc = (() => void) | null;
declare var afterEach:(test:EmptyFunc)=>void;
declare var cptable: any;
*/
import * as assert_ from 'https://deno.land/std/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std/encoding/base64.ts';
import * as assert_ from 'https://deno.land/std@0.169.0/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std@0.169.0/encoding/base64.ts';
const assert: any = {...assert_};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e); }})};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e as string); }})};
assert.doesNotThrow = function(f: ()=>void) { f(); };
assert.equal = assert.assertEquals;
assert.notEqual = assert.assertNotEquals;
@ -36,7 +36,7 @@ function readFileSync2(x: string, e?: ShEncoding): Uint8Array | string {
if(!e) return u8;
switch(e) {
case 'utf-8': return new TextDecoder().decode(u8);
case 'base64': return base64_.encode(u8);
case 'base64': return base64_.encode(u8 as any);
case 'buffer': return u8;
case 'binary': return Array.from({length: u8.length}, (_,i) => String.fromCharCode(u8[i])).join("");
}
@ -2724,7 +2724,7 @@ Deno.test('dense mode', async function(t) {
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.assert(!ws["A1"]);
assert.equal(ws["!data"]?.[0][0].v, "Link to Sheet2");
assert.equal(ws["!data"]?.[0]![0]!.v, "Link to Sheet2");
});
if(!browser) artifax.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
@ -2736,7 +2736,7 @@ Deno.test('dense mode', async function(t) {
ws = wb.Sheets[wb.SheetNames[0]];
assert.assert(!ws["A1"]);
assert.assert(!!ws["!data"]);
assert.assert(ws["!data"]?.[0][0]);
assert.assert(ws["!data"]?.[0]![0]);
});
});
await t.step('aoa_to_sheet', async function(t) {
@ -2744,28 +2744,28 @@ Deno.test('dense mode', async function(t) {
var sp = X.utils.aoa_to_sheet(aoa); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('json_to_sheet', async function(t) {
var json = [{"SheetJS": 5433795}];
var sp = X.utils.json_to_sheet(json); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('sheet_add_aoa', async function(t) {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('sheet_add_json', async function(t) {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader:true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
for(var ofmti = 0; ofmti < ofmt.length; ++ofmti) { var f = ofmt[ofmti];
await t.step('write ' + f, async function(t) {
@ -3022,6 +3022,11 @@ Deno.test('corner cases', async function(t) {
}
});
});
if(fs.existsSync(dir + 'shared_formula.xlsx')) await t.step('should properly handle defined names in shared formulae', async function(t) {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
Deno.test('encryption', async function(t) {
@ -3033,14 +3038,14 @@ Deno.test('encryption', async function(t) {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'Password',WTF:opts.WTF});
throw new Error("incorrect password was accepted");
} catch(e) {
if(e.message != "Password is incorrect") throw e;
if((e as any).message != "Password is incorrect") throw e;
}
});
await t.step('should recognize correct password', async function(t) {
try {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
} catch(e) {
if(e.message == "Password is incorrect") throw e;
if((e as any).message == "Password is incorrect") throw e;
}
});
if(false) await t.step('should decrypt file', async function(t) {

@ -9,10 +9,10 @@ declare type EmptyFunc = (() => void) | null;
declare var afterEach:(test:EmptyFunc)=>void;
declare var cptable: any;
*/
import * as assert_ from 'https://deno.land/std/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std/encoding/base64.ts';
import * as assert_ from 'https://deno.land/std@0.169.0/testing/asserts.ts';
import * as base64_ from 'https://deno.land/std@0.169.0/encoding/base64.ts';
const assert: any = {...assert_};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e); }})};
assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e as string); }})};
assert.doesNotThrow = function(f: ()=>void) { f(); };
assert.equal = assert.assertEquals;
assert.notEqual = assert.assertNotEquals;
@ -35,7 +35,7 @@ function readFileSync2(x: string, e?: ShEncoding): Uint8Array | string {
if(!e) return u8;
switch(e) {
case 'utf-8': return new TextDecoder().decode(u8);
case 'base64': return base64_.encode(u8);
case 'base64': return base64_.encode(u8 as any);
case 'buffer': return u8;
case 'binary': return Array.from({length: u8.length}, (_,i) => String.fromCharCode(u8[i])).join("");
}
@ -2723,7 +2723,7 @@ Deno.test('dense mode', async function(t) {
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.assert(!ws["A1"]);
assert.equal(ws["!data"]?.[0][0].v, "Link to Sheet2");
assert.equal(ws["!data"]?.[0]![0]!.v, "Link to Sheet2");
});
if(!browser) artifax.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
@ -2735,7 +2735,7 @@ Deno.test('dense mode', async function(t) {
ws = wb.Sheets[wb.SheetNames[0]];
assert.assert(!ws["A1"]);
assert.assert(!!ws["!data"]);
assert.assert(ws["!data"]?.[0][0]);
assert.assert(ws["!data"]?.[0]![0]);
});
});
await t.step('aoa_to_sheet', async function(t) {
@ -2743,28 +2743,28 @@ Deno.test('dense mode', async function(t) {
var sp = X.utils.aoa_to_sheet(aoa); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('json_to_sheet', async function(t) {
var json = [{"SheetJS": 5433795}];
var sp = X.utils.json_to_sheet(json); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('sheet_add_aoa', async function(t) {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
await t.step('sheet_add_json', async function(t) {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader:true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.assert(!sp["!data"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1][0].v, 5433795); assert.assert(!ds["A2"]);
var ds:X.WorkSheet = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: true, dense: true}); assert.equal(ds["!data"]?.[1]![0]!.v, 5433795); assert.assert(!ds["A2"]);
});
for(var ofmti = 0; ofmti < ofmt.length; ++ofmti) { var f = ofmt[ofmti];
await t.step('write ' + f, async function(t) {
@ -3021,6 +3021,11 @@ Deno.test('corner cases', async function(t) {
}
});
});
if(fs.existsSync(dir + 'shared_formula.xlsx')) await t.step('should properly handle defined names in shared formulae', async function(t) {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
Deno.test('encryption', async function(t) {
@ -3032,14 +3037,14 @@ Deno.test('encryption', async function(t) {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'Password',WTF:opts.WTF});
throw new Error("incorrect password was accepted");
} catch(e) {
if(e.message != "Password is incorrect") throw e;
if((e as any).message != "Password is incorrect") throw e;
}
});
await t.step('should recognize correct password', async function(t) {
try {
X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
} catch(e) {
if(e.message == "Password is incorrect") throw e;
if((e as any).message == "Password is incorrect") throw e;
}
});
if(false) await t.step('should decrypt file', async function(t) {

5
tests/core.js generated

@ -3102,6 +3102,11 @@ describe('corner cases', function() {
}
});
});
(fs.existsSync(dir + 'shared_formula.xlsx') ? it : it.skip)('should properly handle defined names in shared formulae', function() {
var wb = X.read(fs.readFileSync(dir + 'shared_formula.xlsx'), {type:TYPE});
var formulae = X.utils.sheet_to_formulae(wb.Sheets[wb.SheetNames[0]]);
assert.equal(formulae[4], 'A5=nvRTX6090');
});
});
describe('encryption', function() {