deno and node ESM tests
This commit is contained in:
parent
46360a180a
commit
fbdd43a3f4
39
.github/workflows/deno.yml
vendored
Normal file
39
.github/workflows/deno.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: 'Tests: deno 1.x'
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
# small test
|
||||
misc:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
FMTS: misc
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: denoland/setup-deno@main
|
||||
with:
|
||||
deno-version: v1.x
|
||||
- uses: ljharb/actions/node/install@main
|
||||
with:
|
||||
node-version: '16.'
|
||||
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
|
||||
- run: sudo chmod a+x /usr/bin/rooster
|
||||
- run: make init
|
||||
- run: 'cd test_files; make all; cd -'
|
||||
- run: deno test --allow-env --allow-read --allow-write test.ts
|
||||
# full test
|
||||
full:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: denoland/setup-deno@main
|
||||
with:
|
||||
deno-version: v1.x
|
||||
- uses: ljharb/actions/node/install@main
|
||||
with:
|
||||
node-version: '16.'
|
||||
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
|
||||
- run: sudo chmod a+x /usr/bin/rooster
|
||||
- run: make init
|
||||
- run: 'cd test_files; make all; cd -'
|
||||
- run: deno test --allow-env --allow-read --allow-write test.ts
|
@ -4,6 +4,11 @@ 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.
|
||||
|
||||
## v0.18.1
|
||||
|
||||
* Removed Node ESM build script and folded into standard ESM build
|
||||
* Removed undocumented aliases including `make_formulae` and `get_formulae`
|
||||
|
||||
## v0.18.0
|
||||
|
||||
* Browser scripts only expose `XLSX` variable
|
||||
|
18
Makefile
18
Makefile
@ -128,6 +128,14 @@ pkg: bin/xlsx.njs xlsx.js ## Build pkg standalone executable
|
||||
test mocha: test.js ## Run test suite
|
||||
mocha -R spec -t 30000
|
||||
|
||||
.PHONY: test-esm
|
||||
test-esm: test.mjs ## Run Node ESM test suite
|
||||
npx mocha -r esm -R spec -t 30000 $<
|
||||
|
||||
.PHONY: test-deno
|
||||
test-deno: test.ts ## Run Deno test suite
|
||||
deno test --allow-env --allow-read --allow-write $<
|
||||
|
||||
#* To run tests for one format, make test_<fmt>
|
||||
#* To run the core test suite, make test_misc
|
||||
TESTFMT=$(patsubst %,test_%,$(FMT))
|
||||
@ -135,6 +143,16 @@ TESTFMT=$(patsubst %,test_%,$(FMT))
|
||||
$(TESTFMT): test_%:
|
||||
FMTS=$* make test
|
||||
|
||||
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
|
||||
.PHONY: $(TESTESMFMT)
|
||||
$(TESTESMFMT): test-esm_%:
|
||||
FMTS=$* make test-esm
|
||||
|
||||
TESTDENOFMT=$(patsubst %,test-deno_%,$(FMT))
|
||||
.PHONY: $(TESTESMFMT)
|
||||
$(TESTDENOFMT): test-deno_%:
|
||||
FMTS=$* make test-deno
|
||||
|
||||
.PHONY: travis
|
||||
travis: ## Run test suite with minimal output
|
||||
mocha -R dot -t 30000
|
||||
|
45
README.md
45
README.md
@ -177,10 +177,15 @@ $ bower install js-xlsx
|
||||
|
||||
**Deno**
|
||||
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is available on deno:
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is hosted by Deno:
|
||||
|
||||
```ts
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
/* load the codepage support library for extended support with older formats */
|
||||
import * as cptable from 'https://deno.land/x/sheetjs/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cptable);
|
||||
```
|
||||
|
||||
**NodeJS**
|
||||
@ -211,7 +216,7 @@ import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cpexcel);
|
||||
```
|
||||
|
||||
**PhotoShop and InDesign**
|
||||
**Photoshop and InDesign**
|
||||
|
||||
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
|
||||
that is included in the `npm` package. It can be directly referenced with a
|
||||
@ -538,9 +543,11 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`webpack 2.x`](demos/webpack/)
|
||||
|
||||
**Platforms and Integrations**
|
||||
- [`deno`](demos/deno/)
|
||||
- [`electron application`](demos/electron/)
|
||||
- [`nw.js application`](demos/nwjs/)
|
||||
- [`Chrome / Chromium extensions`](demos/chrome/)
|
||||
- [`Download a Google Sheet locally`](demos/google-sheet/)
|
||||
- [`Adobe ExtendScript`](demos/extendscript/)
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
@ -609,6 +616,23 @@ const workbook = read(buf);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a Deno application</b> (click to show)</summary>
|
||||
|
||||
`readFile` uses `Deno.readFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
const workbook = XLSX.readFile("test.xlsx");
|
||||
```
|
||||
|
||||
Applications reading files must be invoked with the `--allow-read` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>User-submitted file in a web page ("Drag-and-Drop")</b> (click to show)</summary>
|
||||
|
||||
@ -1467,6 +1491,23 @@ const workbook = writeFileSync("out.xlsb", buf);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a Deno application</b> (click to show)</summary>
|
||||
|
||||
`writeFile` uses `Deno.writeFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
XLSX.writeFile(workbook, "test.xlsx");
|
||||
```
|
||||
|
||||
Applications writing files must be invoked with the `--allow-write` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a PhotoShop or InDesign plugin</b> (click to show)</summary>
|
||||
|
||||
|
@ -66,7 +66,7 @@ function utf8decode(content/*:string*/) {
|
||||
o[widx++] = (128|(c&63));
|
||||
} else if(c >= 0xD800 && c < 0xE000) {
|
||||
c = (c&1023)+64;
|
||||
var d = str.charCodeAt(++ridx)&1023;
|
||||
var d = content.charCodeAt(++ridx)&1023;
|
||||
o[widx++] = (240|((c>>8)&7));
|
||||
o[widx++] = (128|((c>>2)&63));
|
||||
o[widx++] = (128|((d>>6)&15)|((c&3)<<4));
|
||||
|
@ -63,7 +63,7 @@ if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
|
||||
}
|
||||
|
||||
/* from js-xls */
|
||||
if(typeof cptable !== 'undefined') {
|
||||
function cpdoit() {
|
||||
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
|
||||
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
|
||||
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
|
||||
@ -72,6 +72,7 @@ if(typeof cptable !== 'undefined') {
|
||||
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
|
||||
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
|
||||
}
|
||||
if(typeof cptable !== 'undefined') cpdoit();
|
||||
|
||||
var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
|
||||
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+1]*(1<<8))+b[idx]; };
|
||||
|
@ -585,19 +585,19 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
break;
|
||||
case 'header' /*case 'Header'*/:
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
|
||||
cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
|
||||
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].header = +parsexmltag(Rn[0]).Margin;
|
||||
break;
|
||||
case 'footer' /*case 'Footer'*/:
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
|
||||
cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
|
||||
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].footer = +parsexmltag(Rn[0]).Margin;
|
||||
break;
|
||||
case 'pagemargins' /*case 'PageMargins'*/:
|
||||
var pagemargins = parsexmltag(Rn[0]);
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
|
||||
if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
|
||||
if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
|
||||
if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
|
||||
if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
|
||||
if(!isNaN(+pagemargins.Top)) cursheet['!margins'].top = +pagemargins.Top;
|
||||
if(!isNaN(+pagemargins.Left)) cursheet['!margins'].left = +pagemargins.Left;
|
||||
if(!isNaN(+pagemargins.Right)) cursheet['!margins'].right = +pagemargins.Right;
|
||||
if(!isNaN(+pagemargins.Bottom)) cursheet['!margins'].bottom = +pagemargins.Bottom;
|
||||
break;
|
||||
case 'displayrighttoleft' /*case 'DisplayRightToLeft'*/:
|
||||
if(!Workbook.Views) Workbook.Views = [];
|
||||
|
@ -67,6 +67,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
reset_cp();
|
||||
var o = opts||{};
|
||||
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
|
||||
if(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && !o.type) o.type = typeof Deno !== "undefined" ? "buffer" : "array";
|
||||
var d = data, n = [0,0,0,0], str = false;
|
||||
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
|
||||
_ssfopts = {};
|
||||
|
@ -48,7 +48,12 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
|
||||
default: throw new Error("Unrecognized type " + o.type);
|
||||
}
|
||||
var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type, compression: !!o.compression}) : z.generate(oopts);
|
||||
if(typeof Deno !== "undefined" && typeof out == "string") out = new Uint8Array(s2ab(out));
|
||||
if(typeof Deno !== "undefined") {
|
||||
if(typeof out == "string") {
|
||||
if(o.type == "binary" || o.type == "base64") return out;
|
||||
out = new Uint8Array(s2ab(out));
|
||||
}
|
||||
}
|
||||
/*jshint -W083 */
|
||||
if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
|
||||
/*jshint +W083 */
|
||||
@ -72,6 +77,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
|
||||
case "file": return write_dl(opts.file, o, 'utf8');
|
||||
case "buffer": {
|
||||
if(has_buf) return Buffer_from(o, 'utf8');
|
||||
else if(typeof TextEncoder !== "undefined") return new TextEncoder().encode(o);
|
||||
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
|
||||
}
|
||||
}
|
||||
|
@ -252,10 +252,6 @@ var utils/*:any*/ = {
|
||||
decode_cell: decode_cell,
|
||||
decode_range: decode_range,
|
||||
format_cell: format_cell,
|
||||
get_formulae: sheet_to_formulae,
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
sheet_add_dom: sheet_add_dom,
|
||||
|
@ -40,6 +40,7 @@ can be installed with Bash on Windows or with `cygwin`.
|
||||
- [`webpack 2.x`](webpack/)
|
||||
|
||||
**Platforms and Integrations**
|
||||
- [`deno`](deno/)
|
||||
- [`electron application`](electron/)
|
||||
- [`nw.js application`](nwjs/)
|
||||
- [`Chrome / Chromium extensions`](chrome/)
|
||||
|
1
demos/deno/.gitignore
vendored
Normal file
1
demos/deno/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
sheet2csv
|
@ -1,8 +1,13 @@
|
||||
TESTS= x mjs jspm
|
||||
UNSTABLE= node
|
||||
|
||||
.PHONY: test
|
||||
test: $(UNSTABLE) $(TESTS)
|
||||
|
||||
.PHONY: sheet2csv
|
||||
sheet2csv: sheet2csv.ts
|
||||
deno compile -r --allow-read $<
|
||||
|
||||
$(TESTS): %: %.ts doit.ts
|
||||
deno run --allow-read --allow-write $<
|
||||
|
||||
|
@ -37,12 +37,26 @@ Deno.writeFileSync("test.xlsb", u8);
|
||||
|
||||
## Demos
|
||||
|
||||
**Complete Example**
|
||||
|
||||
`sheet2csv.ts` is a complete command-line tool for generating CSV text from
|
||||
workbooks. Building the application is incredibly straightforward:
|
||||
|
||||
```bash
|
||||
$ deno compile -r --allow-read sheet2csv.ts # build the sheet2csv binary
|
||||
$ ./sheet2csv test.xlsx # print the first worksheet as CSV
|
||||
$ ./sheet2csv test.xlsx s5s # print worksheet "s5s" as CSV
|
||||
```
|
||||
|
||||
**Module Import Scenarios**
|
||||
|
||||
All demos attempt to read a file and write a new file. [`doit.ts`](./doit.ts)
|
||||
accepts the `XLSX` module as an argument.
|
||||
|
||||
- `x` imports the ESM build without the codepage library:
|
||||
|
||||
```ts
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs';
|
||||
```
|
||||
|
||||
|
21
demos/deno/sheet2csv.ts
Normal file
21
demos/deno/sheet2csv.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs';
|
||||
import * as cptable from 'https://deno.land/x/sheetjs/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cptable);
|
||||
|
||||
const filename = Deno.args[0];
|
||||
if(!filename) {
|
||||
console.error("usage: sheet2csv <filename> [sheetname]");
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
const workbook = XLSX.readFile(filename);
|
||||
const sheetname = Deno.args[1] || workbook.SheetNames[0];
|
||||
|
||||
if(!workbook.Sheets[sheetname]) {
|
||||
console.error(`error: workbook missing sheet ${sheetname}`);
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
console.log(XLSX.utils.sheet_to_csv(workbook.Sheets[sheetname]));
|
@ -61,10 +61,15 @@ $ bower install js-xlsx
|
||||
|
||||
**Deno**
|
||||
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is available on deno:
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is hosted by Deno:
|
||||
|
||||
```ts
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
/* load the codepage support library for extended support with older formats */
|
||||
import * as cptable from 'https://deno.land/x/sheetjs/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cptable);
|
||||
```
|
||||
|
||||
**NodeJS**
|
||||
@ -95,7 +100,7 @@ import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cpexcel);
|
||||
```
|
||||
|
||||
**PhotoShop and InDesign**
|
||||
**Photoshop and InDesign**
|
||||
|
||||
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
|
||||
that is included in the `npm` package. It can be directly referenced with a
|
||||
|
@ -25,9 +25,11 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`webpack 2.x`](demos/webpack/)
|
||||
|
||||
**Platforms and Integrations**
|
||||
- [`deno`](demos/deno/)
|
||||
- [`electron application`](demos/electron/)
|
||||
- [`nw.js application`](demos/nwjs/)
|
||||
- [`Chrome / Chromium extensions`](demos/chrome/)
|
||||
- [`Download a Google Sheet locally`](demos/google-sheet/)
|
||||
- [`Adobe ExtendScript`](demos/extendscript/)
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
|
@ -56,6 +56,23 @@ const workbook = read(buf);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a Deno application</b> (click to show)</summary>
|
||||
|
||||
`readFile` uses `Deno.readFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
const workbook = XLSX.readFile("test.xlsx");
|
||||
```
|
||||
|
||||
Applications reading files must be invoked with the `--allow-read` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>User-submitted file in a web page ("Drag-and-Drop")</b> (click to show)</summary>
|
||||
|
||||
|
@ -63,6 +63,23 @@ const workbook = writeFileSync("out.xlsb", buf);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a Deno application</b> (click to show)</summary>
|
||||
|
||||
`writeFile` uses `Deno.writeFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
XLSX.writeFile(workbook, "test.xlsx");
|
||||
```
|
||||
|
||||
Applications writing files must be invoked with the `--allow-write` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Local file in a PhotoShop or InDesign plugin</b> (click to show)</summary>
|
||||
|
||||
|
@ -71,5 +71,6 @@ function set_cptable(_cptable) {
|
||||
_getansi = function _ga2(x/*:number*/)/*:string*/ {
|
||||
return cptable.utils.decode(current_ansi, [x])[0];
|
||||
};
|
||||
cpdoit();
|
||||
}
|
||||
export { set_cptable };
|
||||
|
@ -166,10 +166,15 @@ $ bower install js-xlsx
|
||||
|
||||
**Deno**
|
||||
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is available on deno:
|
||||
The [`sheetjs`](https://deno.land/x/sheetjs) package is hosted by Deno:
|
||||
|
||||
```ts
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
/* load the codepage support library for extended support with older formats */
|
||||
import * as cptable from 'https://deno.land/x/sheetjs/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cptable);
|
||||
```
|
||||
|
||||
**NodeJS**
|
||||
@ -200,7 +205,7 @@ import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
|
||||
XLSX.set_cptable(cpexcel);
|
||||
```
|
||||
|
||||
**PhotoShop and InDesign**
|
||||
**Photoshop and InDesign**
|
||||
|
||||
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
|
||||
that is included in the `npm` package. It can be directly referenced with a
|
||||
@ -521,9 +526,11 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`webpack 2.x`](demos/webpack/)
|
||||
|
||||
**Platforms and Integrations**
|
||||
- [`deno`](demos/deno/)
|
||||
- [`electron application`](demos/electron/)
|
||||
- [`nw.js application`](demos/nwjs/)
|
||||
- [`Chrome / Chromium extensions`](demos/chrome/)
|
||||
- [`Download a Google Sheet locally`](demos/google-sheet/)
|
||||
- [`Adobe ExtendScript`](demos/extendscript/)
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
@ -590,6 +597,20 @@ const workbook = read(buf);
|
||||
|
||||
|
||||
|
||||
`readFile` uses `Deno.readFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
const workbook = XLSX.readFile("test.xlsx");
|
||||
```
|
||||
|
||||
Applications reading files must be invoked with the `--allow-read` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
|
||||
|
||||
For modern websites targeting Chrome 76+, `File#arrayBuffer` is recommended:
|
||||
|
||||
```js
|
||||
@ -1382,6 +1403,20 @@ const workbook = writeFileSync("out.xlsb", buf);
|
||||
|
||||
|
||||
|
||||
`writeFile` uses `Deno.writeFileSync` under the hood:
|
||||
|
||||
```js
|
||||
// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
|
||||
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'
|
||||
|
||||
XLSX.writeFile(workbook, "test.xlsx");
|
||||
```
|
||||
|
||||
Applications writing files must be invoked with the `--allow-write` flag. The
|
||||
[`deno` demo](demos/deno/) has more examples
|
||||
|
||||
|
||||
|
||||
`writeFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
|
||||
The specified path should be an absolute path:
|
||||
|
||||
|
24
test.js
24
test.js
@ -27,7 +27,7 @@ var Buffer_from = /*::(*/function(){}/*:: :any)*/;
|
||||
|
||||
if(typeof Buffer !== 'undefined') {
|
||||
var nbfs = !Buffer.from;
|
||||
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
|
||||
if(!nbfs) try { Buffer.from("foo", "utf-8"); } catch(e) { nbfs = true; }
|
||||
Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
|
||||
// $FlowIgnore
|
||||
if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
|
||||
@ -248,7 +248,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin
|
||||
describe(x + ext + ' should generate CSV', function() {
|
||||
wb.SheetNames.forEach(function(ws, i) {
|
||||
it('#' + i + ' (' + ws + ')', function() {
|
||||
X.utils.make_csv(wb.Sheets[ws]);
|
||||
X.utils.sheet_to_csv(wb.Sheets[ws]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -262,7 +262,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin
|
||||
describe(x + ext + ' should generate formulae', function() {
|
||||
wb.SheetNames.forEach(function(ws, i) {
|
||||
it('#' + i + ' (' + ws + ')', function() {
|
||||
X.utils.get_formulae(wb.Sheets[ws]);
|
||||
X.utils.sheet_to_formulae(wb.Sheets[ws]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -289,7 +289,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin
|
||||
var name = getfile(dir, x, i, ".csv");
|
||||
if(fs.existsSync(name)) it('#' + i + ' (' + ws + ')', function() {
|
||||
var file = fs.readFileSync(name, 'utf-8');
|
||||
var csv = X.utils.make_csv(wb.Sheets[ws]);
|
||||
var csv = X.utils.sheet_to_csv(wb.Sheets[ws]);
|
||||
assert.equal(fixcsv(csv), fixcsv(file), "CSV badness");
|
||||
});
|
||||
});
|
||||
@ -299,14 +299,14 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin
|
||||
var rawjson = getfile(dir, x, i, ".rawjson");
|
||||
if(fs.existsSync(rawjson)) it('#' + i + ' (' + ws + ')', function() {
|
||||
var file = fs.readFileSync(rawjson, 'utf-8');
|
||||
var json = X.utils.make_json(wb.Sheets[ws],{raw:true});
|
||||
var json = X.utils.sheet_to_json(wb.Sheets[ws],{raw:true});
|
||||
assert.equal(JSON.stringify(json), fixjson(file), "JSON badness");
|
||||
});
|
||||
|
||||
var jsonf = getfile(dir, x, i, ".json");
|
||||
if(fs.existsSync(jsonf)) it('#' + i + ' (' + ws + ')', function() {
|
||||
var file = fs.readFileSync(jsonf, 'utf-8');
|
||||
var json = X.utils.make_json(wb.Sheets[ws], {raw:false});
|
||||
var json = X.utils.sheet_to_json(wb.Sheets[ws], {raw:false});
|
||||
assert.equal(JSON.stringify(json), fixjson(file), "JSON badness");
|
||||
});
|
||||
});
|
||||
@ -1760,7 +1760,7 @@ describe('json output', function() {
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should use first-row headers and full sheet by default', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {raw: null});
|
||||
var json = X.utils.sheet_to_json(ws, {raw: false});
|
||||
assert.equal(json.length, data.length - 1);
|
||||
assert.equal(json[0][1], "TRUE");
|
||||
assert.equal(json[1][2], "bar");
|
||||
@ -1769,7 +1769,7 @@ describe('json output', function() {
|
||||
assert.throws(function() { seeker(json, [1,2,3], "baz"); });
|
||||
});
|
||||
it('should create array of arrays if header == 1', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:1, raw:""});
|
||||
var json = X.utils.sheet_to_json(ws, {header:1, raw:false});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1][0], "TRUE");
|
||||
assert.equal(json[2][1], "bar");
|
||||
@ -2322,9 +2322,9 @@ describe('corner cases', function() {
|
||||
get_cell(ws,"A1").f = ""; get_cell(ws,"A1").w = "";
|
||||
delete get_cell(ws,"C3").w; delete get_cell(ws,"C3").z; get_cell(ws,"C3").XF = {ifmt:14};
|
||||
get_cell(ws,"A4").t = "e";
|
||||
X.utils.get_formulae(ws);
|
||||
X.utils.make_csv(ws);
|
||||
X.utils.make_json(ws);
|
||||
X.utils.sheet_to_formulae(ws);
|
||||
X.utils.sheet_to_csv(ws);
|
||||
X.utils.sheet_to_json(ws);
|
||||
ws['!cols'] = [ {wch:6}, {wch:7}, {wch:10}, {wch:20} ];
|
||||
|
||||
var wb = {SheetNames:['sheetjs'], Sheets:{sheetjs:ws}};
|
||||
@ -2336,7 +2336,7 @@ describe('corner cases', function() {
|
||||
X.write(wb, {type: "binary", bookType: 'biff5'});
|
||||
X.write(wb, {type: "binary", bookType: 'biff8'});
|
||||
get_cell(ws,"A2").t = "f";
|
||||
assert.throws(function() { X.utils.make_json(ws); });
|
||||
assert.throws(function() { X.utils.sheet_to_json(ws); });
|
||||
});
|
||||
it('SSF', function() {
|
||||
X.SSF.format("General", "dafuq");
|
||||
|
7
types/index.d.ts
vendored
7
types/index.d.ts
vendored
@ -209,7 +209,12 @@ export interface ParsingOptions extends CommonOptions {
|
||||
/** If true, plaintext parsing will not parse values */
|
||||
raw?: boolean;
|
||||
|
||||
/** If true, preserve _xlfn. prefixes in formula function names */
|
||||
xlfn?: boolean;
|
||||
|
||||
dense?: boolean;
|
||||
|
||||
PRN?: boolean;
|
||||
}
|
||||
|
||||
export interface SheetOption {
|
||||
@ -548,7 +553,7 @@ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z';
|
||||
* Type of generated workbook
|
||||
* @default 'xlsx'
|
||||
*/
|
||||
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'xla' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth';
|
||||
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'xla' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'slk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth' | 'dbf';
|
||||
|
||||
/** Comment element */
|
||||
export interface Comment {
|
||||
|
71
xlsx.mjs
generated
71
xlsx.mjs
generated
@ -77,6 +77,7 @@ function set_cptable(_cptable) {
|
||||
_getansi = function _ga2(x/*:number*/)/*:string*/ {
|
||||
return cptable.utils.decode(current_ansi, [x])[0];
|
||||
};
|
||||
cpdoit();
|
||||
}
|
||||
export { set_cptable };
|
||||
var DENSE = null;
|
||||
@ -196,7 +197,7 @@ function utf8decode(content/*:string*/) {
|
||||
o[widx++] = (128|(c&63));
|
||||
} else if(c >= 0xD800 && c < 0xE000) {
|
||||
c = (c&1023)+64;
|
||||
var d = str.charCodeAt(++ridx)&1023;
|
||||
var d = content.charCodeAt(++ridx)&1023;
|
||||
o[widx++] = (240|((c>>8)&7));
|
||||
o[widx++] = (128|((c>>2)&63));
|
||||
o[widx++] = (128|((d>>6)&15)|((c&3)<<4));
|
||||
@ -2799,7 +2800,9 @@ return exports;
|
||||
})();
|
||||
|
||||
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
|
||||
const _fs = void 0;
|
||||
let _fs = void 0;
|
||||
function set_fs(fs) { _fs = fs; }
|
||||
export { set_fs };
|
||||
|
||||
/* normalize data for blob ctor */
|
||||
function blobify(data) {
|
||||
@ -3036,11 +3039,11 @@ function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
|
||||
}
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
if(!data) return null;
|
||||
if(data.content && data.type) return cc2str(data.content, true);
|
||||
if(data.data) return debom(data.data);
|
||||
if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
|
||||
if(data.asBinary) return debom(data.asBinary());
|
||||
if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
|
||||
if(data.content && data.type) return debom(cc2str(data.content));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -3089,6 +3092,12 @@ function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
|
||||
try { return getzipstr(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
function getzipbin(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
|
||||
if(!safe) return getdatabin(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipbin(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
function zipentries(zip) {
|
||||
var k = zip.FullPaths || keys(zip.files), o = [];
|
||||
for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i].replace(/^Root Entry[\/]/, ""));
|
||||
@ -3096,23 +3105,29 @@ function zipentries(zip) {
|
||||
}
|
||||
|
||||
function zip_add_file(zip, path, content) {
|
||||
if(zip.FullPaths) CFB.utils.cfb_add(zip, path, typeof content == "string" ? (has_buf ? Buffer_from(content) : s2a(utf8write(content))) : content);
|
||||
if(zip.FullPaths) {
|
||||
if(typeof content == "string") {
|
||||
var res;
|
||||
if(has_buf) res = Buffer_from(content);
|
||||
/* TODO: investigate performance in Edge 13 */
|
||||
//else if(typeof TextEncoder !== "undefined") res = new TextEncoder().encode(content);
|
||||
else res = utf8decode(content);
|
||||
return CFB.utils.cfb_add(zip, path, res);
|
||||
}
|
||||
CFB.utils.cfb_add(zip, path, content);
|
||||
}
|
||||
else zip.file(path, content);
|
||||
}
|
||||
|
||||
function zip_new() {
|
||||
return CFB.utils.cfb_new();
|
||||
}
|
||||
function zip_new() { return CFB.utils.cfb_new(); }
|
||||
|
||||
function zip_read(d, o) {
|
||||
var zip;
|
||||
switch(o.type) {
|
||||
case "base64": zip = CFB.read(d, { type: "base64" }); break;
|
||||
case "binary": zip = CFB.read(d, { type: "binary" }); break;
|
||||
case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
|
||||
default: throw new Error("Unrecognized type " + o.type);
|
||||
case "base64": return CFB.read(d, { type: "base64" });
|
||||
case "binary": return CFB.read(d, { type: "binary" });
|
||||
case "buffer": case "array": return CFB.read(d, { type: "buffer" });
|
||||
}
|
||||
return zip;
|
||||
throw new Error("Unrecognized type " + o.type);
|
||||
}
|
||||
|
||||
function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
|
||||
@ -3460,7 +3475,7 @@ if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
|
||||
}
|
||||
|
||||
/* from js-xls */
|
||||
if(typeof cptable !== 'undefined') {
|
||||
function cpdoit() {
|
||||
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
|
||||
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
|
||||
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
|
||||
@ -3469,6 +3484,7 @@ if(typeof cptable !== 'undefined') {
|
||||
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
|
||||
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
|
||||
}
|
||||
if(typeof cptable !== 'undefined') cpdoit();
|
||||
|
||||
var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
|
||||
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+1]*(1<<8))+b[idx]; };
|
||||
@ -16988,19 +17004,19 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
break;
|
||||
case 'header' /*case 'Header'*/:
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
|
||||
cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
|
||||
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].header = +parsexmltag(Rn[0]).Margin;
|
||||
break;
|
||||
case 'footer' /*case 'Footer'*/:
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
|
||||
cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
|
||||
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].footer = +parsexmltag(Rn[0]).Margin;
|
||||
break;
|
||||
case 'pagemargins' /*case 'PageMargins'*/:
|
||||
var pagemargins = parsexmltag(Rn[0]);
|
||||
if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
|
||||
if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
|
||||
if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
|
||||
if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
|
||||
if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
|
||||
if(!isNaN(+pagemargins.Top)) cursheet['!margins'].top = +pagemargins.Top;
|
||||
if(!isNaN(+pagemargins.Left)) cursheet['!margins'].left = +pagemargins.Left;
|
||||
if(!isNaN(+pagemargins.Right)) cursheet['!margins'].right = +pagemargins.Right;
|
||||
if(!isNaN(+pagemargins.Bottom)) cursheet['!margins'].bottom = +pagemargins.Bottom;
|
||||
break;
|
||||
case 'displayrighttoleft' /*case 'DisplayRightToLeft'*/:
|
||||
if(!Workbook.Views) Workbook.Views = [];
|
||||
@ -22619,6 +22635,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
reset_cp();
|
||||
var o = opts||{};
|
||||
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
|
||||
if(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && !o.type) o.type = typeof Deno !== "undefined" ? "buffer" : "array";
|
||||
var d = data, n = [0,0,0,0], str = false;
|
||||
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
|
||||
_ssfopts = {};
|
||||
@ -22715,8 +22732,13 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
|
||||
case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
|
||||
default: throw new Error("Unrecognized type " + o.type);
|
||||
}
|
||||
var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type}) : z.generate(oopts);
|
||||
if(typeof Deno !== "undefined" && typeof out == "string") out = new Uint8Array(s2ab(out));
|
||||
var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type, compression: !!o.compression}) : z.generate(oopts);
|
||||
if(typeof Deno !== "undefined") {
|
||||
if(typeof out == "string") {
|
||||
if(o.type == "binary" || o.type == "base64") return out;
|
||||
out = new Uint8Array(s2ab(out));
|
||||
}
|
||||
}
|
||||
/*jshint -W083 */
|
||||
if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
|
||||
/*jshint +W083 */
|
||||
@ -22740,6 +22762,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
|
||||
case "file": return write_dl(opts.file, o, 'utf8');
|
||||
case "buffer": {
|
||||
if(has_buf) return Buffer_from(o, 'utf8');
|
||||
else if(typeof TextEncoder !== "undefined") return new TextEncoder().encode(o);
|
||||
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
|
||||
}
|
||||
}
|
||||
@ -23098,10 +23121,6 @@ var utils/*:any*/ = {
|
||||
decode_cell: decode_cell,
|
||||
decode_range: decode_range,
|
||||
format_cell: format_cell,
|
||||
get_formulae: sheet_to_formulae,
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
sheet_add_dom: sheet_add_dom,
|
||||
|
Loading…
Reference in New Issue
Block a user