forked from sheetjs/sheetjs
		
	parse ZIP64 length (fixes #2766 h/t @silvialeung)
This commit is contained in:
		
							parent
							
								
									199373e918
								
							
						
					
					
						commit
						045adba80d
					
				@ -211,8 +211,15 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
 | 
			
		||||
					if(flags & 4) p.ctime = blob.read_shift(4);
 | 
			
		||||
				}
 | 
			
		||||
				if(p.mtime) p.mt = new Date(p.mtime*1000);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
			} break;
 | 
			
		||||
			/* ZIP64 Extended Information Field */
 | 
			
		||||
			case 0x0001: {
 | 
			
		||||
				var sz1 = blob.read_shift(4), sz2 = blob.read_shift(4);
 | 
			
		||||
				p.usz = (sz2 * Math.pow(2,32) + sz1);
 | 
			
		||||
				sz1 = blob.read_shift(4); sz2 = blob.read_shift(4);
 | 
			
		||||
				p.csz = (sz2 * Math.pow(2,32) + sz1);
 | 
			
		||||
				// NOTE: volume fields are skipped
 | 
			
		||||
			} break;
 | 
			
		||||
		}
 | 
			
		||||
		blob.l = tgt;
 | 
			
		||||
		o[type] = p;
 | 
			
		||||
@ -1401,6 +1408,11 @@ function parse_zip(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/
 | 
			
		||||
 | 
			
		||||
		var L = blob.l;
 | 
			
		||||
		blob.l = offset + 4;
 | 
			
		||||
		/* ZIP64 lengths */
 | 
			
		||||
		if(EF && EF[0x0001]) {
 | 
			
		||||
			if((EF[0x0001]||{}).usz) usz = EF[0x0001].usz;
 | 
			
		||||
			if((EF[0x0001]||{}).csz) csz = EF[0x0001].csz;
 | 
			
		||||
		}
 | 
			
		||||
		parse_local_file(blob, csz, usz, o, EF);
 | 
			
		||||
		blob.l = L;
 | 
			
		||||
	}
 | 
			
		||||
@ -1430,7 +1442,13 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
 | 
			
		||||
	if(efsz) {
 | 
			
		||||
		var ef = parse_extra_field(/*::(*/blob.slice(blob.l, blob.l + efsz)/*:: :any)*/);
 | 
			
		||||
		if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
 | 
			
		||||
		if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
 | 
			
		||||
		if((ef[0x0001]||{}).usz) _usz = ef[0x0001].usz;
 | 
			
		||||
		if((ef[0x0001]||{}).csz) _csz = ef[0x0001].csz;
 | 
			
		||||
		if(EF) {
 | 
			
		||||
			if((EF[0x5455]||{}).mt) date = EF[0x5455].mt;
 | 
			
		||||
			if((EF[0x0001]||{}).usz) _usz = ef[0x0001].usz;
 | 
			
		||||
			if((EF[0x0001]||{}).csz) _csz = ef[0x0001].csz;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	blob.l += efsz;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,23 +26,23 @@ can be installed with Bash on Windows or with `cygwin`.
 | 
			
		||||
- [`IndexedDB`](https://docs.sheetjs.com/docs/demos/database#indexeddb)
 | 
			
		||||
 | 
			
		||||
**Frameworks**
 | 
			
		||||
- [`Angular 2+ and Ionic`](https://docs.sheetjs.com/docs/demos/angular)
 | 
			
		||||
- [`React`](https://docs.sheetjs.com/docs/demos/react)
 | 
			
		||||
- [`VueJS`](https://docs.sheetjs.com/docs/demos/vue)
 | 
			
		||||
- [`Angular.JS`](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
 | 
			
		||||
- [`Angular 2+ and Ionic`](angular2/)
 | 
			
		||||
- [`Knockout`](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
 | 
			
		||||
- [`React and NextJS`](react/)
 | 
			
		||||
- [`VueJS`](vue/)
 | 
			
		||||
 | 
			
		||||
**Front-End UI Components**
 | 
			
		||||
- [`canvas-datagrid`](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
 | 
			
		||||
- [`x-spreadsheet`](xspreadsheet/)
 | 
			
		||||
- [`react-data-grid`](react/modify/)
 | 
			
		||||
- [`vue3-table-light`](vue/modify/)
 | 
			
		||||
- [`x-spreadsheet`](https://docs.sheetjs.com/docs/demos/grid#x-spreadsheet)
 | 
			
		||||
- [`react-data-grid`](https://docs.sheetjs.com/docs/demos/grid#react-data-grid)
 | 
			
		||||
- [`vue3-table-lite`](https://docs.sheetjs.com/docs/demos/grid#vue3-table-lite)
 | 
			
		||||
- [`angular-ui-grid`](https://docs.sheetjs.com/docs/demos/grid#angular-ui-grid)
 | 
			
		||||
 | 
			
		||||
**Platforms and Integrations**
 | 
			
		||||
- [`Command-Line Tools`](https://docs.sheetjs.com/docs/demos/cli)
 | 
			
		||||
- [`iOS and Android Mobile Applications`](https://docs.sheetjs.com/docs/demos/mobile)
 | 
			
		||||
- [`NodeJS Server-Side Processing`](server/)
 | 
			
		||||
- [`NodeJS Server-Side Processing`](https://docs.sheetjs.com/docs/demos/server#nodejs)
 | 
			
		||||
- [`Content Management and Static Sites`](https://docs.sheetjs.com/docs/demos/content)
 | 
			
		||||
- [`Electron`](https://docs.sheetjs.com/docs/demos/desktop#electron)
 | 
			
		||||
- [`NW.js`](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
 | 
			
		||||
@ -54,8 +54,9 @@ can be installed with Bash on Windows or with `cygwin`.
 | 
			
		||||
- [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/demos/salesforce)
 | 
			
		||||
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/demos/excel)
 | 
			
		||||
- [`Headless Automation`](https://docs.sheetjs.com/docs/demos/headless)
 | 
			
		||||
- [`Swift JSC and Other JavaScript Engines`](https://docs.sheetjs.com/docs/demos/engines)
 | 
			
		||||
- [`"serverless" functions`](function/)
 | 
			
		||||
- [`Other JavaScript Engines`](https://docs.sheetjs.com/docs/demos/engines)
 | 
			
		||||
- [`Azure Functions and Storage`](https://docs.sheetjs.com/docs/demos/azure)
 | 
			
		||||
- [`Amazon Web Services`](https://docs.sheetjs.com/docs/demos/aws)
 | 
			
		||||
- [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/demos/database)
 | 
			
		||||
- [`NoSQL and Unstructured Data Stores`](https://docs.sheetjs.com/docs/demos/nosql)
 | 
			
		||||
- [`Legacy Internet Explorer`](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
 | 
			
		||||
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "project": {
 | 
			
		||||
    "name": "angular2"
 | 
			
		||||
  },
 | 
			
		||||
  "apps": [
 | 
			
		||||
    {
 | 
			
		||||
      "root": "src",
 | 
			
		||||
      "outDir": "dist",
 | 
			
		||||
      "index": "index.html",
 | 
			
		||||
      "main": "main.ts",
 | 
			
		||||
      "polyfills": "polyfills.ts",
 | 
			
		||||
      "test": "test.ts",
 | 
			
		||||
      "tsconfig": "tsconfig.app.json",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "scripts": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "defaults": {
 | 
			
		||||
    "styleExt": "css",
 | 
			
		||||
    "component": {}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
	"parser": "@typescript-eslint/parser",
 | 
			
		||||
	"extends": [
 | 
			
		||||
		"eslint:recommended"
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								demos/angular2/.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/angular2/.gitattributes
									
									
									
									
										vendored
									
									
								
							@ -1 +0,0 @@
 | 
			
		||||
*.*-ng*           linguist-generated=true binary
 | 
			
		||||
							
								
								
									
										8
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,8 +0,0 @@
 | 
			
		||||
dist
 | 
			
		||||
hooks
 | 
			
		||||
SheetJSIonic
 | 
			
		||||
SheetJSNS
 | 
			
		||||
angular.json
 | 
			
		||||
tsconfig.app.json
 | 
			
		||||
src/polyfills.ts
 | 
			
		||||
.angular
 | 
			
		||||
@ -1,34 +0,0 @@
 | 
			
		||||
.PHONY: ng2 ng4 ng5 ng6 ng7 ng8 ng9 ng10 ng11 ng12 ng13
 | 
			
		||||
ng2 ng4 ng5 ng6 ng7 ng8 ng9 ng10 ng11 ng12 ng13:
 | 
			
		||||
	rm -f angular.json tsconfig.app.json src/polyfills.ts
 | 
			
		||||
	cp versions/package.json-$@ package.json
 | 
			
		||||
	if [ -e versions/angular.json-$@ ]; then cp versions/angular.json-$@ angular.json; fi
 | 
			
		||||
	if [ -e versions/tsconfig.app.json-$@ ]; then cp versions/tsconfig.app.json-$@ tsconfig.app.json; fi
 | 
			
		||||
	if [ -e versions/polyfills.ts-$@ ]; then cp versions/polyfills.ts-$@ src/polyfills.ts; fi
 | 
			
		||||
	rm -rf node_modules
 | 
			
		||||
	if [ ! -e node_modules ]; then mkdir node_modules; fi
 | 
			
		||||
	npm install
 | 
			
		||||
	if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi
 | 
			
		||||
	npm run build
 | 
			
		||||
 | 
			
		||||
.PHONY: refresh
 | 
			
		||||
refresh: ## refresh the `xlsx` symlink to force angular to rebuild
 | 
			
		||||
	rm -rf .angular/
 | 
			
		||||
	rm -f node_modules/xlsx
 | 
			
		||||
	cd node_modules; ln -s ../../../ xlsx; cd -
 | 
			
		||||
	touch node_modules/xlsx
 | 
			
		||||
 | 
			
		||||
.PHONY: all
 | 
			
		||||
all:
 | 
			
		||||
	for i in 2 4 5 6 7 8 9 10 11 12 13; do make ng$$i; done
 | 
			
		||||
 | 
			
		||||
.PHONY: ionic
 | 
			
		||||
ionic:
 | 
			
		||||
	bash ./ionic.sh
 | 
			
		||||
 | 
			
		||||
.PHONY: ios android browser
 | 
			
		||||
ios browser: ionic
 | 
			
		||||
	cd SheetJSIonic; ionic cordova emulate $@ </dev/null; cd -
 | 
			
		||||
android: ionic
 | 
			
		||||
	cd SheetJSIonic; ionic cordova prepare $@ </dev/null; ionic cordova emulate $@ </dev/null; cd -
 | 
			
		||||
 | 
			
		||||
@ -1,148 +1,11 @@
 | 
			
		||||
# Angular 2+
 | 
			
		||||
 | 
			
		||||
The ESM build can be imported directly from TS code with:
 | 
			
		||||
[The new demo](https://docs.sheetjs.com/docs/demos/angular) has an updated
 | 
			
		||||
exposition for legacy and modern deployments alike.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
import { read, utils, writeFileXLSX } from 'xlsx';
 | 
			
		||||
```
 | 
			
		||||
The ecosystem demos were grouped by type in the new demo site:
 | 
			
		||||
 | 
			
		||||
This demo uses an array of arrays (type `Array<Array<any>>`) as the core state.
 | 
			
		||||
The component template includes a file input element, a table that updates with
 | 
			
		||||
the data, and a button to export the data.
 | 
			
		||||
 | 
			
		||||
Other scripts in this demo show:
 | 
			
		||||
- `ionic` deployment for iOS, android, and browser
 | 
			
		||||
- `nativescript` deployment for iOS and android
 | 
			
		||||
 | 
			
		||||
## Array of Arrays
 | 
			
		||||
 | 
			
		||||
`Array<Array<any>>` neatly maps to a table with `ngFor`:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<table class="sjs-table">
 | 
			
		||||
  <tr *ngFor="let row of data">
 | 
			
		||||
    <td *ngFor="let val of row">
 | 
			
		||||
      {{val}}
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `aoa_to_sheet` utility function returns a worksheet.  Exporting is simple:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
/* generate worksheet */
 | 
			
		||||
const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data);
 | 
			
		||||
 | 
			
		||||
/* generate workbook and add the worksheet */
 | 
			
		||||
const wb: XLSX.WorkBook = XLSX.utils.book_new();
 | 
			
		||||
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
 | 
			
		||||
 | 
			
		||||
/* save to file */
 | 
			
		||||
XLSX.writeFile(wb, 'SheetJS.xlsx');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`sheet_to_json` with the option `header:1` makes importing simple:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
/* <input type="file" (change)="onFileChange($event)" multiple="false" /> */
 | 
			
		||||
/* ... (within the component class definition) ... */
 | 
			
		||||
  onFileChange(evt: any) {
 | 
			
		||||
    /* wire up file reader */
 | 
			
		||||
    const target: DataTransfer = <DataTransfer>(evt.target);
 | 
			
		||||
    if (target.files.length !== 1) throw new Error('Cannot use multiple files');
 | 
			
		||||
    const reader: FileReader = new FileReader();
 | 
			
		||||
    reader.onload = (e: any) => {
 | 
			
		||||
      /* read workbook */
 | 
			
		||||
      const ab: ArrayBuffer = e.target.result;
 | 
			
		||||
      const wb: XLSX.WorkBook = XLSX.read(ab);
 | 
			
		||||
 | 
			
		||||
      /* grab first sheet */
 | 
			
		||||
      const wsname: string = wb.SheetNames[0];
 | 
			
		||||
      const ws: XLSX.WorkSheet = wb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
      /* save data */
 | 
			
		||||
      this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1}));
 | 
			
		||||
    };
 | 
			
		||||
    reader.readAsArrayBuffer(target.files[0]);
 | 
			
		||||
  }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Switching between Angular versions
 | 
			
		||||
 | 
			
		||||
Modules that work with Angular 2 largely work as-is with Angular 4+.  Switching
 | 
			
		||||
between versions is mostly a matter of installing the correct version of the
 | 
			
		||||
core and associated modules.  This demo includes `package.json-angular#` files
 | 
			
		||||
for every major version of Angular up to 12.
 | 
			
		||||
 | 
			
		||||
To test a particular Angular version, overwrite `package.json`:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# switch to Angular 2
 | 
			
		||||
$ cp package.json-ng2 package.json
 | 
			
		||||
$ npm install
 | 
			
		||||
$ ng serve
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note: when running the demos, Angular 2 requires Node <= 14.  This is due to a
 | 
			
		||||
tooling issue with `ng` and does not affect browser use.
 | 
			
		||||
 | 
			
		||||
## XLSX Symbolic Link
 | 
			
		||||
 | 
			
		||||
In this tree, `node_modules/xlsx` is a link pointing back to the root.  This
 | 
			
		||||
enables testing the development version of the library.  In order to use this
 | 
			
		||||
demo in other applications, add the `xlsx` dependency:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## SystemJS Configuration
 | 
			
		||||
 | 
			
		||||
The default angular-cli configuration requires no additional configuration.
 | 
			
		||||
 | 
			
		||||
Some deployments use the SystemJS loader, which does require configuration.
 | 
			
		||||
[SystemJS](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
 | 
			
		||||
demo in the SheetJS CE docs describe the required settings.
 | 
			
		||||
 | 
			
		||||
## Ionic
 | 
			
		||||
 | 
			
		||||
<img src="screen.png" width="400px"/>
 | 
			
		||||
 | 
			
		||||
Reproducing the full project is a little bit tricky.  The included `ionic.sh`
 | 
			
		||||
script performs the necessary installation steps.
 | 
			
		||||
 | 
			
		||||
`Array<Array<any>>` neatly maps to a table with `ngFor`:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<ion-grid>
 | 
			
		||||
  <ion-row *ngFor="let row of data">
 | 
			
		||||
    <ion-col *ngFor="let val of row">
 | 
			
		||||
      {{val}}
 | 
			
		||||
    </ion-col>
 | 
			
		||||
  </ion-row>
 | 
			
		||||
</ion-grid>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
`@ionic-native/file` reads and writes files on devices. `readAsArrayBuffer`
 | 
			
		||||
returns `ArrayBuffer` objects suitable for `array` type, and `array` type can
 | 
			
		||||
be converted to blobs that can be exported with `writeFile`:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
/* read a workbook */
 | 
			
		||||
const ab: ArrayBuffer = await this.file.readAsArrayBuffer(url, filename);
 | 
			
		||||
const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'array'});
 | 
			
		||||
 | 
			
		||||
/* write a workbook */
 | 
			
		||||
const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
 | 
			
		||||
let blob = new Blob([wbout], {type: 'application/octet-stream'});
 | 
			
		||||
this.file.writeFile(url, filename, blob, {replace: true});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## NativeScript
 | 
			
		||||
 | 
			
		||||
[The new demo](https://docs.sheetjs.com/docs/demos/mobile#nativescript)
 | 
			
		||||
is updated for NativeScript 8 and uses more idiomatic data patterns.
 | 
			
		||||
- [NativeScript](https://docs.sheetjs.com/docs/demos/mobile#nativescript) is now part of "iOS and Android Apps"
 | 
			
		||||
- [Ionic](https://docs.sheetjs.com/docs/demos/mobile#ionic) is now part of "iOS and Android Apps"
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* vim: set ts=2: */
 | 
			
		||||
/* NOTE: this file exists because `File` must be added as a provider */
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { BrowserModule } from '@angular/platform-browser';
 | 
			
		||||
import { RouteReuseStrategy } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { AppComponent } from './app.component';
 | 
			
		||||
import { AppRoutingModule } from './app-routing.module';
 | 
			
		||||
 | 
			
		||||
import { File } from '@ionic-native/file/ngx';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [AppComponent],
 | 
			
		||||
  entryComponents: [],
 | 
			
		||||
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
 | 
			
		||||
  providers: [File, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
 | 
			
		||||
  bootstrap: [AppComponent],
 | 
			
		||||
})
 | 
			
		||||
export class AppModule {}
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
if [ ! -e SheetJSIonic ]; then
 | 
			
		||||
	ionic start SheetJSIonic blank --type angular --cordova --quiet --no-git --no-link --confirm </dev/null
 | 
			
		||||
	cd SheetJSIonic
 | 
			
		||||
	ionic cordova platform add browser --confirm </dev/null
 | 
			
		||||
	ionic cordova platform add ios --confirm </dev/null
 | 
			
		||||
	ionic cordova platform add android --confirm </dev/null
 | 
			
		||||
	ionic cordova plugin add cordova-plugin-file </dev/null
 | 
			
		||||
	npm install --save @ionic-native/core
 | 
			
		||||
	npm install --save @ionic-native/file
 | 
			
		||||
	npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
 | 
			
		||||
	cp ../ionic-app.module.ts src/app/app.module.ts
 | 
			
		||||
	cd -
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cp ionic.ts SheetJSIonic/src/app/home/home.page.ts
 | 
			
		||||
@ -1,126 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* vim: set ts=2: */
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
import { File } from '@ionic-native/file/ngx';
 | 
			
		||||
import * as XLSX from 'xlsx';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type AOA = any[][];
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-home',
 | 
			
		||||
  //templateUrl: 'home.page.html',
 | 
			
		||||
  styleUrls: ['home.page.scss'],
 | 
			
		||||
  template: `
 | 
			
		||||
<ion-header>
 | 
			
		||||
  <ion-toolbar>
 | 
			
		||||
    <ion-title>SheetJS Ionic Demo</ion-title>
 | 
			
		||||
  </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
 | 
			
		||||
<ion-content [fullscreen]="true">
 | 
			
		||||
  <ion-header collapse="condense">
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
      <ion-title>SheetJS Demo</ion-title>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
  </ion-header>
 | 
			
		||||
 | 
			
		||||
  <ion-grid>
 | 
			
		||||
    <ion-row *ngFor="let row of data">
 | 
			
		||||
      <ion-col *ngFor="let val of row">
 | 
			
		||||
        {{val}}
 | 
			
		||||
      </ion-col>
 | 
			
		||||
    </ion-row>
 | 
			
		||||
  </ion-grid>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
<ion-footer padding>
 | 
			
		||||
  <input type="file" (change)="onFileChange($event)" multiple="false" />
 | 
			
		||||
  <button ion-button color="secondary" (click)="import()">Import Data</button>
 | 
			
		||||
  <button ion-button color="secondary" (click)="export()">Export Data</button>
 | 
			
		||||
</ion-footer>
 | 
			
		||||
`
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export class HomePage {
 | 
			
		||||
  data: any[][] = [[1,2,3],[4,5,6]];
 | 
			
		||||
  constructor(public file: File) {}
 | 
			
		||||
 | 
			
		||||
  read(ab: ArrayBuffer) {
 | 
			
		||||
    /* read workbook */
 | 
			
		||||
    const wb: XLSX.WorkBook = XLSX.read(new Uint8Array(ab), {type: 'array'});
 | 
			
		||||
 | 
			
		||||
    /* grab first sheet */
 | 
			
		||||
    const wsname: string = wb.SheetNames[0];
 | 
			
		||||
    const ws: XLSX.WorkSheet = wb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
    /* save data */
 | 
			
		||||
    this.data = (XLSX.utils.sheet_to_json(ws, {header: 1}) as AOA);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  write(): XLSX.WorkBook {
 | 
			
		||||
    /* generate worksheet */
 | 
			
		||||
    const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data);
 | 
			
		||||
 | 
			
		||||
    /* generate workbook and add the worksheet */
 | 
			
		||||
    const wb: XLSX.WorkBook = XLSX.utils.book_new();
 | 
			
		||||
    XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
 | 
			
		||||
 | 
			
		||||
    return wb;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* File Input element for browser */
 | 
			
		||||
  onFileChange(evt: any) {
 | 
			
		||||
    /* wire up file reader */
 | 
			
		||||
    const target: DataTransfer = (evt.target as DataTransfer);
 | 
			
		||||
    if (target.files.length !== 1) { throw new Error('Cannot use multiple files'); }
 | 
			
		||||
    const reader: FileReader = new FileReader();
 | 
			
		||||
    reader.onload = (e: any) => {
 | 
			
		||||
      const ab: ArrayBuffer = e.target.result;
 | 
			
		||||
      this.read(ab);
 | 
			
		||||
    };
 | 
			
		||||
    reader.readAsArrayBuffer(target.files[0]);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Import button for mobile */
 | 
			
		||||
  async import() {
 | 
			
		||||
    try {
 | 
			
		||||
      const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || '';
 | 
			
		||||
      const dentry = await this.file.resolveDirectoryUrl(target);
 | 
			
		||||
      const url: string = dentry.nativeURL || '';
 | 
			
		||||
      alert(`Attempting to read SheetJSIonic.xlsx from ${url}`);
 | 
			
		||||
      const ab: ArrayBuffer = await this.file.readAsArrayBuffer(url, 'SheetJSIonic.xlsx');
 | 
			
		||||
      this.read(ab);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      const m: string = e.message;
 | 
			
		||||
      alert(m.match(/It was determined/) ? 'Use File Input control' : `Error: ${m}`);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Export button */
 | 
			
		||||
  async export() {
 | 
			
		||||
    const wb: XLSX.WorkBook = this.write();
 | 
			
		||||
    const filename = 'SheetJSIonic.xlsx';
 | 
			
		||||
    try {
 | 
			
		||||
      /* generate Blob */
 | 
			
		||||
      const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
 | 
			
		||||
 | 
			
		||||
      /* find appropriate path for mobile */
 | 
			
		||||
      const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || '';
 | 
			
		||||
      const dentry = await this.file.resolveDirectoryUrl(target);
 | 
			
		||||
      const url: string = dentry.nativeURL || '';
 | 
			
		||||
 | 
			
		||||
      /* attempt to save blob to file */
 | 
			
		||||
      await this.file.writeFile(url, filename, wbout, {replace: true});
 | 
			
		||||
      alert(`Wrote to SheetJSIonic.xlsx in ${url}`);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      if(e.message.match(/It was determined/)) {
 | 
			
		||||
        /* in the browser, use writeFile */
 | 
			
		||||
        XLSX.writeFile(wb, filename);
 | 
			
		||||
      } else {
 | 
			
		||||
        alert(`Error: ${e.message}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular13",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~13.2.0",
 | 
			
		||||
    "@angular/common": "~13.2.0",
 | 
			
		||||
    "@angular/compiler": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~13.2.0",
 | 
			
		||||
    "@angular/forms": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~13.2.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~7.5.0",
 | 
			
		||||
    "tslib": "^2.3.0",
 | 
			
		||||
    "zone.js": "~0.11.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~13.2.1",
 | 
			
		||||
    "@angular/cli": "~13.2.1",
 | 
			
		||||
    "@angular/compiler-cli": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "typescript": "~4.5.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 94 KiB  | 
@ -1,28 +0,0 @@
 | 
			
		||||
import { BrowserModule } from '@angular/platform-browser';
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { SheetJSComponent } from './sheetjs.component';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'app-root',
 | 
			
		||||
	template: `<sheetjs></sheetjs>`
 | 
			
		||||
})
 | 
			
		||||
export class AppComponent {
 | 
			
		||||
	title = 'test';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
	declarations: [
 | 
			
		||||
		SheetJSComponent,
 | 
			
		||||
		AppComponent
 | 
			
		||||
	],
 | 
			
		||||
	imports: [
 | 
			
		||||
		BrowserModule
 | 
			
		||||
	],
 | 
			
		||||
	providers: [],
 | 
			
		||||
	bootstrap: [AppComponent]
 | 
			
		||||
})
 | 
			
		||||
export class AppModule { }
 | 
			
		||||
@ -1,64 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* vim: set ts=2: */
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { WorkBook, WorkSheet, WritingOptions, read, writeFileXLSX as writeFile, utils, version, set_cptable } from 'xlsx';
 | 
			
		||||
//import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
 | 
			
		||||
//set_cptable(cpexcel);
 | 
			
		||||
 | 
			
		||||
type AOA = any[][];
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'sheetjs',
 | 
			
		||||
	template: `
 | 
			
		||||
	<pre><b>Version: {{ver}}</b></pre>
 | 
			
		||||
	<input type="file" (change)="onFileChange($event)" multiple="false" />
 | 
			
		||||
	<table class="sjs-table">
 | 
			
		||||
		<tr *ngFor="let row of data">
 | 
			
		||||
			<td *ngFor="let val of row">
 | 
			
		||||
				{{val}}
 | 
			
		||||
			</td>
 | 
			
		||||
		</tr>
 | 
			
		||||
	</table>
 | 
			
		||||
	<button (click)="export()">Export!</button>
 | 
			
		||||
	`
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export class SheetJSComponent {
 | 
			
		||||
	data: AOA = [ [1, 2], [3, 4] ];
 | 
			
		||||
	wopts: WritingOptions = { bookType: 'xlsx', type: 'array' };
 | 
			
		||||
	fileName: string = 'SheetJS.xlsx';
 | 
			
		||||
	ver: string = version;
 | 
			
		||||
 | 
			
		||||
	onFileChange(evt: any) {
 | 
			
		||||
		/* wire up file reader */
 | 
			
		||||
		const target: DataTransfer = <DataTransfer>(evt.target);
 | 
			
		||||
		if (target.files.length !== 1) throw new Error('Cannot use multiple files');
 | 
			
		||||
		const reader: FileReader = new FileReader();
 | 
			
		||||
		reader.onload = (e: any) => {
 | 
			
		||||
			/* read workbook */
 | 
			
		||||
			const ab: ArrayBuffer = e.target.result;
 | 
			
		||||
			const wb: WorkBook = read(ab);
 | 
			
		||||
 | 
			
		||||
			/* grab first sheet */
 | 
			
		||||
			const wsname: string = wb.SheetNames[0];
 | 
			
		||||
			const ws: WorkSheet = wb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
			/* save data */
 | 
			
		||||
			this.data = <AOA>(utils.sheet_to_json(ws, {header: 1}));
 | 
			
		||||
		};
 | 
			
		||||
		reader.readAsArrayBuffer(target.files[0]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	export(): void {
 | 
			
		||||
		/* generate worksheet */
 | 
			
		||||
		const ws: WorkSheet = utils.aoa_to_sheet(this.data);
 | 
			
		||||
 | 
			
		||||
		/* generate workbook and add the worksheet */
 | 
			
		||||
		const wb: WorkBook = utils.book_new();
 | 
			
		||||
		utils.book_append_sheet(wb, ws, 'Sheet1');
 | 
			
		||||
 | 
			
		||||
		/* save to file */
 | 
			
		||||
		writeFile(wb, this.fileName);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: true
 | 
			
		||||
};
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: false
 | 
			
		||||
};
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
	<title>SheetJS + Angular 2+</title>
 | 
			
		||||
  <base href="/">
 | 
			
		||||
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<pre>
 | 
			
		||||
<b><a href="http://sheetjs.com">SheetJS + Angular 2+ demo</a></b>
 | 
			
		||||
 | 
			
		||||
The core library can be used as-is in angular applications.
 | 
			
		||||
The <a href="https://github.com/sheetjs/js-xlsx">Community Edition README</a> details some common use cases.
 | 
			
		||||
We also have some <a href="http://sheetjs.com/demos/">more public demos</a>
 | 
			
		||||
 | 
			
		||||
This demo shows `SheetJSComponent` which provides:
 | 
			
		||||
- File input button with an event handler to parse the workbook
 | 
			
		||||
- `data` property: array of arrays
 | 
			
		||||
- Simple angular table which binds to the `data` property
 | 
			
		||||
- `export` function that exports the `data` property to a new file.
 | 
			
		||||
 | 
			
		||||
<a href="https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls">Sample Spreadsheet</a>
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<app-root></app-root>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 | 
			
		||||
import { AppModule } from './app/app.module';
 | 
			
		||||
platformBrowserDynamic().bootstrapModule(AppModule);
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
/* You can add global styles to this file, and also import other style files */
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "../out-tsc/app",
 | 
			
		||||
    "module": "es2015",
 | 
			
		||||
    "baseUrl": "",
 | 
			
		||||
    "types": []
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "compileOnSave": false,
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./dist/out-tsc",
 | 
			
		||||
    "baseUrl": "src",
 | 
			
		||||
    "sourceMap": true,
 | 
			
		||||
    "declaration": false,
 | 
			
		||||
    "moduleResolution": "node",
 | 
			
		||||
    "emitDecoratorMetadata": true,
 | 
			
		||||
    "experimentalDecorators": true,
 | 
			
		||||
    "target": "es5",
 | 
			
		||||
    "typeRoots": [
 | 
			
		||||
      "node_modules/@types"
 | 
			
		||||
    ],
 | 
			
		||||
    "lib": [
 | 
			
		||||
      "es2016",
 | 
			
		||||
      "dom"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,125 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "aot": true,
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "extractCss": true,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true,
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "2mb",
 | 
			
		||||
                  "maximumError": "5mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "6kb",
 | 
			
		||||
                  "maximumError": "10kb"
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "tsconfig.app.json",
 | 
			
		||||
              "tsconfig.spec.json",
 | 
			
		||||
              "e2e/tsconfig.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,124 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "aot": true,
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true,
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "2mb",
 | 
			
		||||
                  "maximumError": "5mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "6kb",
 | 
			
		||||
                  "maximumError": "10kb"
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "tsconfig.app.json",
 | 
			
		||||
              "tsconfig.spec.json",
 | 
			
		||||
              "e2e/tsconfig.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,106 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {
 | 
			
		||||
        "@schematics/angular:application": {
 | 
			
		||||
          "strict": true
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "500kb",
 | 
			
		||||
                  "maximumError": "2mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "2kb",
 | 
			
		||||
                  "maximumError": "4kb"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "outputHashing": "all"
 | 
			
		||||
            },
 | 
			
		||||
            "development": {
 | 
			
		||||
              "buildOptimizer": false,
 | 
			
		||||
              "optimization": false,
 | 
			
		||||
              "vendorChunk": true,
 | 
			
		||||
              "extractLicenses": false,
 | 
			
		||||
              "sourceMap": true,
 | 
			
		||||
              "namedChunks": true
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          "defaultConfiguration": "production"
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            },
 | 
			
		||||
            "development": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:development"
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          "defaultConfiguration": "development"
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,106 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {
 | 
			
		||||
        "@schematics/angular:application": {
 | 
			
		||||
          "strict": true
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "500kb",
 | 
			
		||||
                  "maximumError": "2mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "2kb",
 | 
			
		||||
                  "maximumError": "4kb"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "outputHashing": "all"
 | 
			
		||||
            },
 | 
			
		||||
            "development": {
 | 
			
		||||
              "buildOptimizer": false,
 | 
			
		||||
              "optimization": false,
 | 
			
		||||
              "vendorChunk": true,
 | 
			
		||||
              "extractLicenses": false,
 | 
			
		||||
              "sourceMap": true,
 | 
			
		||||
              "namedChunks": true
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          "defaultConfiguration": "production"
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            },
 | 
			
		||||
            "development": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:development"
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          "defaultConfiguration": "development"
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,127 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "src/tsconfig.app.json",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "extractCss": true,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "aot": true,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "src/tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "src/karma.conf.js",
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": [],
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "src/tsconfig.app.json",
 | 
			
		||||
              "src/tsconfig.spec.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "sheetjs-e2e": {
 | 
			
		||||
      "root": "e2e/",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": "e2e/tsconfig.e2e.json",
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,136 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "src/tsconfig.app.json",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": [],
 | 
			
		||||
            "es5BrowserSupport": true
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "extractCss": true,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "aot": true,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true,
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "2mb",
 | 
			
		||||
                  "maximumError": "5mb"
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "src/tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "src/karma.conf.js",
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": [],
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "src/tsconfig.app.json",
 | 
			
		||||
              "src/tsconfig.spec.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "sheetjs-e2e": {
 | 
			
		||||
      "root": "e2e/",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "",
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": "e2e/tsconfig.e2e.json",
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,126 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "aot": false,
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "extractCss": true,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "aot": true,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true,
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "2mb",
 | 
			
		||||
                  "maximumError": "5mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "6kb",
 | 
			
		||||
                  "maximumError": "10kb"
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "tsconfig.app.json",
 | 
			
		||||
              "tsconfig.spec.json",
 | 
			
		||||
              "e2e/tsconfig.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,125 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
 | 
			
		||||
  "version": 1,
 | 
			
		||||
  "newProjectRoot": "projects",
 | 
			
		||||
  "projects": {
 | 
			
		||||
    "sheetjs": {
 | 
			
		||||
      "root": "",
 | 
			
		||||
      "sourceRoot": "src",
 | 
			
		||||
      "projectType": "application",
 | 
			
		||||
      "prefix": "app",
 | 
			
		||||
      "schematics": {},
 | 
			
		||||
      "architect": {
 | 
			
		||||
        "build": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:browser",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "outputPath": "dist/sheetjs",
 | 
			
		||||
            "index": "src/index.html",
 | 
			
		||||
            "main": "src/main.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.app.json",
 | 
			
		||||
            "aot": true,
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "fileReplacements": [
 | 
			
		||||
                {
 | 
			
		||||
                  "replace": "src/environments/environment.ts",
 | 
			
		||||
                  "with": "src/environments/environment.prod.ts"
 | 
			
		||||
                }
 | 
			
		||||
              ],
 | 
			
		||||
              "optimization": true,
 | 
			
		||||
              "outputHashing": "all",
 | 
			
		||||
              "sourceMap": false,
 | 
			
		||||
              "extractCss": true,
 | 
			
		||||
              "namedChunks": false,
 | 
			
		||||
              "extractLicenses": true,
 | 
			
		||||
              "vendorChunk": false,
 | 
			
		||||
              "buildOptimizer": true,
 | 
			
		||||
              "budgets": [
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "initial",
 | 
			
		||||
                  "maximumWarning": "2mb",
 | 
			
		||||
                  "maximumError": "5mb"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  "type": "anyComponentStyle",
 | 
			
		||||
                  "maximumWarning": "6kb",
 | 
			
		||||
                  "maximumError": "10kb"
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "serve": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:dev-server",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "browserTarget": "sheetjs:build:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extract-i18n": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:extract-i18n",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "browserTarget": "sheetjs:build"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "test": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:karma",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "main": "src/test.ts",
 | 
			
		||||
            "polyfills": "src/polyfills.ts",
 | 
			
		||||
            "tsConfig": "tsconfig.spec.json",
 | 
			
		||||
            "karmaConfig": "karma.conf.js",
 | 
			
		||||
            "assets": [
 | 
			
		||||
              "src/favicon.ico",
 | 
			
		||||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.css"
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": []
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "lint": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:tslint",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "tsConfig": [
 | 
			
		||||
              "tsconfig.app.json",
 | 
			
		||||
              "tsconfig.spec.json",
 | 
			
		||||
              "e2e/tsconfig.json"
 | 
			
		||||
            ],
 | 
			
		||||
            "exclude": [
 | 
			
		||||
              "**/node_modules/**"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "e2e": {
 | 
			
		||||
          "builder": "@angular-devkit/build-angular:protractor",
 | 
			
		||||
          "options": {
 | 
			
		||||
            "protractorConfig": "e2e/protractor.conf.js",
 | 
			
		||||
            "devServerTarget": "sheetjs:serve"
 | 
			
		||||
          },
 | 
			
		||||
          "configurations": {
 | 
			
		||||
            "production": {
 | 
			
		||||
              "devServerTarget": "sheetjs:serve:production"
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "defaultProject": "sheetjs"
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular10",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~10.2.4",
 | 
			
		||||
    "@angular/common": "~10.2.4",
 | 
			
		||||
    "@angular/compiler": "~10.2.4",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~10.2.4",
 | 
			
		||||
    "@angular/forms": "~10.2.4",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~10.2.4",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~10.2.4",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~10.2.4",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.6.0",
 | 
			
		||||
    "tslib": "^2.0.0",
 | 
			
		||||
    "zone.js": "~0.10.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.1002.3",
 | 
			
		||||
    "@angular/cli": "~10.2.3",
 | 
			
		||||
    "@angular/compiler-cli": "~10.2.4",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
    "ts-node": "~8.3.0",
 | 
			
		||||
    "tslint": "~6.1.0",
 | 
			
		||||
    "typescript": "~4.0.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular11",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~11.2.14",
 | 
			
		||||
    "@angular/common": "~11.2.14",
 | 
			
		||||
    "@angular/compiler": "~11.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~11.2.14",
 | 
			
		||||
    "@angular/forms": "~11.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~11.2.14",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~11.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~11.2.14",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.6.0",
 | 
			
		||||
    "tslib": "^2.0.0",
 | 
			
		||||
    "zone.js": "~0.11.3"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.1102.13",
 | 
			
		||||
    "@angular/cli": "~11.2.14",
 | 
			
		||||
    "@angular/compiler-cli": "~11.2.14",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
    "ts-node": "~8.3.0",
 | 
			
		||||
    "tslint": "~6.1.0",
 | 
			
		||||
    "typescript": "~4.1.5"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular12",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~12.2.0",
 | 
			
		||||
    "@angular/common": "~12.2.0",
 | 
			
		||||
    "@angular/compiler": "~12.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~12.2.0",
 | 
			
		||||
    "@angular/forms": "~12.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~12.2.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~12.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~12.2.0",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.6.0",
 | 
			
		||||
    "tslib": "^2.3.0",
 | 
			
		||||
    "zone.js": "~0.11.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~12.2.7",
 | 
			
		||||
    "@angular/cli": "~12.2.7",
 | 
			
		||||
    "@angular/compiler-cli": "~12.2.0",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "typescript": "~4.3.5"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular13",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~13.2.0",
 | 
			
		||||
    "@angular/common": "~13.2.0",
 | 
			
		||||
    "@angular/compiler": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~13.2.0",
 | 
			
		||||
    "@angular/forms": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~13.2.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~7.5.0",
 | 
			
		||||
    "tslib": "^2.3.0",
 | 
			
		||||
    "zone.js": "~0.11.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~13.2.1",
 | 
			
		||||
    "@angular/cli": "~13.2.1",
 | 
			
		||||
    "@angular/compiler-cli": "~13.2.0",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "typescript": "~4.5.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,37 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular2",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/common": "~2.4.1",
 | 
			
		||||
    "@angular/compiler": "~2.4.1",
 | 
			
		||||
    "@angular/compiler-cli": "^2.4.1",
 | 
			
		||||
    "@angular/core": "~2.4.1",
 | 
			
		||||
    "@angular/forms": "~2.4.1",
 | 
			
		||||
    "@angular/http": "~2.4.1",
 | 
			
		||||
    "@angular/platform-browser": "~2.4.1",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~2.4.1",
 | 
			
		||||
    "@angular/platform-server": "^2.4.1",
 | 
			
		||||
    "@angular/router": "~3.4.0",
 | 
			
		||||
    "core-js": "^2.4.1",
 | 
			
		||||
    "reflect-metadata": "^0.1.8",
 | 
			
		||||
    "rxjs": "^5.0.2",
 | 
			
		||||
    "systemjs": "0.19.40",
 | 
			
		||||
    "zone.js": "^0.7.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular/cli": "1.1.2",
 | 
			
		||||
    "@angular/compiler-cli": "^2.0.0",
 | 
			
		||||
    "@angular/language-service": "^2.0.0",
 | 
			
		||||
    "@types/node": "~6.0.60",
 | 
			
		||||
    "ts-node": "~3.0.4",
 | 
			
		||||
    "tslint": "~5.3.2",
 | 
			
		||||
    "typescript": "~2.3.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular4",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "^4.0.0",
 | 
			
		||||
    "@angular/common": "^4.0.0",
 | 
			
		||||
    "@angular/compiler": "^4.0.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "^4.0.0",
 | 
			
		||||
    "@angular/forms": "^4.0.0",
 | 
			
		||||
    "@angular/http": "^4.0.0",
 | 
			
		||||
    "@angular/platform-browser": "^4.0.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "^4.0.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "^4.0.0",
 | 
			
		||||
    "core-js": "^2.4.1",
 | 
			
		||||
 | 
			
		||||
    "rxjs": "^5.1.0",
 | 
			
		||||
 | 
			
		||||
    "zone.js": "^0.8.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular/cli": "1.1.2",
 | 
			
		||||
    "@angular/compiler-cli": "^4.0.0",
 | 
			
		||||
    "@angular/language-service": "^4.0.0",
 | 
			
		||||
    "@types/node": "~6.0.60",
 | 
			
		||||
    "ts-node": "~3.0.4",
 | 
			
		||||
    "tslint": "~5.3.2",
 | 
			
		||||
    "typescript": "~2.3.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular5",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "^5.0.0",
 | 
			
		||||
    "@angular/common": "^5.0.0",
 | 
			
		||||
    "@angular/compiler": "^5.0.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "^5.0.0",
 | 
			
		||||
    "@angular/forms": "^5.0.0",
 | 
			
		||||
    "@angular/http": "^5.0.0",
 | 
			
		||||
    "@angular/platform-browser": "^5.0.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "^5.0.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "^5.0.0",
 | 
			
		||||
    "core-js": "^2.4.1",
 | 
			
		||||
 | 
			
		||||
    "rxjs": "^5.5.2",
 | 
			
		||||
 | 
			
		||||
    "zone.js": "^0.8.14"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular/cli": "^1.5.3",
 | 
			
		||||
    "@angular/compiler-cli": "^5.0.0",
 | 
			
		||||
    "@angular/language-service": "^5.0.0",
 | 
			
		||||
    "@types/node": "~6.0.60",
 | 
			
		||||
    "ts-node": "~3.2.0",
 | 
			
		||||
    "tslint": "~5.7.0",
 | 
			
		||||
    "typescript": "~2.4.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular6",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "^6.1.0",
 | 
			
		||||
    "@angular/common": "^6.1.0",
 | 
			
		||||
    "@angular/compiler": "^6.1.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "^6.1.0",
 | 
			
		||||
    "@angular/forms": "^6.1.0",
 | 
			
		||||
    "@angular/http": "^6.1.0",
 | 
			
		||||
    "@angular/platform-browser": "^6.1.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "^6.1.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "^6.1.0",
 | 
			
		||||
    "core-js": "^2.5.4",
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.2.0",
 | 
			
		||||
 | 
			
		||||
    "zone.js": "~0.8.26"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.8.0",
 | 
			
		||||
    "@angular/cli": "~6.2.9",
 | 
			
		||||
    "@angular/compiler-cli": "^6.1.0",
 | 
			
		||||
    "@angular/language-service": "^6.1.0",
 | 
			
		||||
    "@types/node": "~8.9.4",
 | 
			
		||||
    "ts-node": "~7.0.0",
 | 
			
		||||
    "tslint": "~5.11.0",
 | 
			
		||||
    "typescript": "~2.9.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular7",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~7.2.0",
 | 
			
		||||
    "@angular/common": "~7.2.0",
 | 
			
		||||
    "@angular/compiler": "~7.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~7.2.0",
 | 
			
		||||
    "@angular/forms": "~7.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~7.2.0",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~7.2.0",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~7.2.0",
 | 
			
		||||
    "core-js": "^2.5.4",
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.3.3",
 | 
			
		||||
    "tslib": "^1.9.0",
 | 
			
		||||
    "zone.js": "~0.8.26"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.13.0",
 | 
			
		||||
    "@angular/cli": "~7.3.10",
 | 
			
		||||
    "@angular/compiler-cli": "~7.2.0",
 | 
			
		||||
    "@angular/language-service": "~7.2.0",
 | 
			
		||||
    "@types/node": "~8.9.4",
 | 
			
		||||
    "ts-node": "~7.0.0",
 | 
			
		||||
    "tslint": "~5.11.0",
 | 
			
		||||
    "typescript": "~3.2.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular8",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~8.2.14",
 | 
			
		||||
    "@angular/common": "~8.2.14",
 | 
			
		||||
    "@angular/compiler": "~8.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~8.2.14",
 | 
			
		||||
    "@angular/forms": "~8.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~8.2.14",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~8.2.14",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~8.2.14",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.4.0",
 | 
			
		||||
    "tslib": "^1.10.0",
 | 
			
		||||
    "zone.js": "~0.9.1"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.803.29",
 | 
			
		||||
    "@angular/cli": "~8.3.29",
 | 
			
		||||
    "@angular/compiler-cli": "~8.2.14",
 | 
			
		||||
    "@angular/language-service": "~8.2.14",
 | 
			
		||||
    "@types/node": "~8.9.4",
 | 
			
		||||
    "ts-node": "~7.0.0",
 | 
			
		||||
    "tslint": "~5.15.0",
 | 
			
		||||
    "typescript": "~3.5.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "angular9",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "ng": "ng",
 | 
			
		||||
    "start": "ng serve",
 | 
			
		||||
    "build": "ng build"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~9.1.13",
 | 
			
		||||
    "@angular/common": "~9.1.13",
 | 
			
		||||
    "@angular/compiler": "~9.1.13",
 | 
			
		||||
 | 
			
		||||
    "@angular/core": "~9.1.13",
 | 
			
		||||
    "@angular/forms": "~9.1.13",
 | 
			
		||||
 | 
			
		||||
    "@angular/platform-browser": "~9.1.13",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~9.1.13",
 | 
			
		||||
 | 
			
		||||
    "@angular/router": "~9.1.13",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    "rxjs": "~6.5.4",
 | 
			
		||||
    "tslib": "^1.10.0",
 | 
			
		||||
    "zone.js": "~0.10.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@angular-devkit/build-angular": "~0.901.15",
 | 
			
		||||
    "@angular/cli": "~9.1.15",
 | 
			
		||||
    "@angular/compiler-cli": "~9.1.13",
 | 
			
		||||
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
    "ts-node": "~8.3.0",
 | 
			
		||||
    "tslint": "~6.1.0",
 | 
			
		||||
    "typescript": "~3.8.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js';
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js';
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import 'core-js/es6/reflect';
 | 
			
		||||
import 'core-js/es7/reflect';
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import 'core-js/es6/reflect';
 | 
			
		||||
import 'core-js/es7/reflect';
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import 'core-js/es6/reflect';
 | 
			
		||||
import 'core-js/es7/reflect';
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import 'core-js/es6/reflect';
 | 
			
		||||
import 'core-js/es7/reflect';
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
import 'core-js/es6/reflect';
 | 
			
		||||
import 'core-js/es7/reflect';
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
import 'zone.js/dist/zone';
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "exclude": [
 | 
			
		||||
    "src/test.ts",
 | 
			
		||||
    "src/**/*.spec.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "./out-tsc/app",
 | 
			
		||||
    "types": []
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "src/main.ts",
 | 
			
		||||
    "src/polyfills.ts"
 | 
			
		||||
  ],
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src/**/*.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
	"env": { "shared-node-browser":true },
 | 
			
		||||
	"parserOptions": {
 | 
			
		||||
		"ecmaVersion": 8
 | 
			
		||||
	},
 | 
			
		||||
	"plugins": [ "html", "json" ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "disabled": false,
 | 
			
		||||
  "bindings": [
 | 
			
		||||
    {
 | 
			
		||||
      "authLevel": "function",
 | 
			
		||||
      "type": "httpTrigger",
 | 
			
		||||
      "direction": "in",
 | 
			
		||||
      "dataType": "binary",
 | 
			
		||||
      "name": "req"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "type": "http",
 | 
			
		||||
      "direction": "out",
 | 
			
		||||
      "name": "res"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
// base64 sheetjs.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost:7262/api/AzureHTTPTrigger
 | 
			
		||||
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
const formidable = require('formidable');
 | 
			
		||||
const Readable = require('stream').Readable;
 | 
			
		||||
var fs = require('fs');
 | 
			
		||||
 | 
			
		||||
/* formidable expects the request object to be a stream */
 | 
			
		||||
const streamify = (req) => {
 | 
			
		||||
	if(typeof req.on !== 'undefined') return req;
 | 
			
		||||
	const s = new Readable();
 | 
			
		||||
	s._read = ()=>{};
 | 
			
		||||
	s.push(new Buffer(req.body));
 | 
			
		||||
	s.push(null);
 | 
			
		||||
	Object.assign(s, req);
 | 
			
		||||
	return s;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = (context, req) => {
 | 
			
		||||
	const form = new formidable.IncomingForm();
 | 
			
		||||
	form.parse(streamify(req), (err, fields, files) => {
 | 
			
		||||
		/* grab the first file */
 | 
			
		||||
		var f = Object.values(files)[0];
 | 
			
		||||
		if(!f) {
 | 
			
		||||
			context.res = { status: 400, body: "Must submit a file for processing!" };
 | 
			
		||||
		} else {
 | 
			
		||||
			/* file is stored in a temp directory, so we can point to that and read it */
 | 
			
		||||
			const wb = XLSX.read(f.path, {type:"file"});
 | 
			
		||||
 | 
			
		||||
			/* convert to specified output type -- default CSV */
 | 
			
		||||
			const ext = (fields.bookType || "csv").toLowerCase();
 | 
			
		||||
			const out = XLSX.write(wb, {type:"string", bookType:ext});
 | 
			
		||||
 | 
			
		||||
			context.res = {
 | 
			
		||||
				status: 200,
 | 
			
		||||
				headers: { "Content-Disposition": `attachment; filename="download.${ext}";` },
 | 
			
		||||
				body: out
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
		context.done();
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										65
									
								
								demos/function/Firebase/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										65
									
								
								demos/function/Firebase/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,65 +0,0 @@
 | 
			
		||||
# Logs
 | 
			
		||||
logs
 | 
			
		||||
*.log
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
yarn-debug.log*
 | 
			
		||||
yarn-error.log*
 | 
			
		||||
firebase-debug.log*
 | 
			
		||||
 | 
			
		||||
# Firebase cache
 | 
			
		||||
.firebase/
 | 
			
		||||
 | 
			
		||||
# Firebase config
 | 
			
		||||
 | 
			
		||||
# Uncomment this if you'd like others to create their own Firebase project.
 | 
			
		||||
# For a team working on the same Firebase project(s), it is recommended to leave
 | 
			
		||||
# it commented so all members can deploy to the same project(s) in .firebaserc.
 | 
			
		||||
.firebaserc
 | 
			
		||||
 | 
			
		||||
# Runtime data
 | 
			
		||||
pids
 | 
			
		||||
*.pid
 | 
			
		||||
*.seed
 | 
			
		||||
*.pid.lock
 | 
			
		||||
 | 
			
		||||
# Directory for instrumented libs generated by jscoverage/JSCover
 | 
			
		||||
lib-cov
 | 
			
		||||
 | 
			
		||||
# Coverage directory used by tools like istanbul
 | 
			
		||||
coverage
 | 
			
		||||
 | 
			
		||||
# nyc test coverage
 | 
			
		||||
.nyc_output
 | 
			
		||||
 | 
			
		||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
 | 
			
		||||
.grunt
 | 
			
		||||
 | 
			
		||||
# Bower dependency directory (https://bower.io/)
 | 
			
		||||
bower_components
 | 
			
		||||
 | 
			
		||||
# node-waf configuration
 | 
			
		||||
.lock-wscript
 | 
			
		||||
 | 
			
		||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
 | 
			
		||||
build/Release
 | 
			
		||||
 | 
			
		||||
# Dependency directories
 | 
			
		||||
node_modules/
 | 
			
		||||
 | 
			
		||||
# Optional npm cache directory
 | 
			
		||||
.npm
 | 
			
		||||
 | 
			
		||||
# Optional eslint cache
 | 
			
		||||
.eslintcache
 | 
			
		||||
 | 
			
		||||
# Optional REPL history
 | 
			
		||||
.node_repl_history
 | 
			
		||||
 | 
			
		||||
# Output of 'npm pack'
 | 
			
		||||
*.tgz
 | 
			
		||||
 | 
			
		||||
# Yarn Integrity file
 | 
			
		||||
.yarn-integrity
 | 
			
		||||
 | 
			
		||||
# dotenv environment variables file
 | 
			
		||||
.env
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
{}
 | 
			
		||||
							
								
								
									
										1
									
								
								demos/function/Firebase/functions/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/function/Firebase/functions/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1 +0,0 @@
 | 
			
		||||
node_modules/
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
const functions = require('firebase-functions');
 | 
			
		||||
const Busboy = require('busboy');
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
 | 
			
		||||
// // Create and Deploy Your First Cloud Functions
 | 
			
		||||
// // https://firebase.google.com/docs/functions/write-firebase-functions
 | 
			
		||||
//
 | 
			
		||||
exports.helloWorld = functions.https.onRequest((request, response) => {
 | 
			
		||||
 response.send("Hello from Firebase!");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
exports.main = functions.https.onRequest((req, res) => {
 | 
			
		||||
  var bb = new Busboy({
 | 
			
		||||
    headers: {
 | 
			
		||||
      'content-type': req.headers['content-type']
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  let fields = {};
 | 
			
		||||
  let files = {};
 | 
			
		||||
  bb.on('field', (fieldname, val) => {
 | 
			
		||||
    fields[fieldname] = val;
 | 
			
		||||
  });
 | 
			
		||||
  bb.on('file', (fieldname, file, filename) => {
 | 
			
		||||
    var buffers = [];
 | 
			
		||||
    file.on('data', (data) => {
 | 
			
		||||
      buffers.push(data);
 | 
			
		||||
    });
 | 
			
		||||
    file.on('end', () => {
 | 
			
		||||
      files[fieldname] = [Buffer.concat(buffers), filename];
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  bb.on('finish', () => {
 | 
			
		||||
    let f = files[Object.keys(files)[0]];
 | 
			
		||||
    const wb = XLSX.read(f[0], { type: "buffer" });
 | 
			
		||||
    // Convert to CSV
 | 
			
		||||
    res.send(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
 | 
			
		||||
  });
 | 
			
		||||
  bb.end(req.body)
 | 
			
		||||
});
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "functions",
 | 
			
		||||
  "description": "Cloud Functions for Firebase",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "serve": "firebase emulators:start --only functions",
 | 
			
		||||
    "shell": "firebase functions:shell",
 | 
			
		||||
    "start": "npm run shell",
 | 
			
		||||
    "deploy": "firebase deploy --only functions",
 | 
			
		||||
    "logs": "firebase functions:log"
 | 
			
		||||
  },
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": "8"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "busboy": "^0.3.1",
 | 
			
		||||
    "firebase-admin": "^8.6.0",
 | 
			
		||||
    "firebase-functions": "^3.3.0",
 | 
			
		||||
    "xlsx": "^0.16.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "firebase-functions-test": "^0.1.6"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true
 | 
			
		||||
}
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
// base64 sheetjs.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost:3000/LambdaProxy
 | 
			
		||||
 | 
			
		||||
'use strict';
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
var Busboy = require('busboy');
 | 
			
		||||
 | 
			
		||||
exports.handler = function(event, context, callback) {
 | 
			
		||||
	/* set up busboy */
 | 
			
		||||
	var ctype = event.headers['Content-Type']||event.headers['content-type'];
 | 
			
		||||
	var bb = new Busboy({headers:{'content-type':ctype}});
 | 
			
		||||
 | 
			
		||||
	/* busboy is evented; accumulate the fields and files manually */
 | 
			
		||||
	var fields = {}, files = {};
 | 
			
		||||
	bb.on('error', function(err) { console.log('err', err); callback(err); });
 | 
			
		||||
	bb.on('field', function(fieldname, val) {fields[fieldname] = val });
 | 
			
		||||
	bb.on('file', function(fieldname, file, filename) {
 | 
			
		||||
		/* concatenate the individual data buffers */
 | 
			
		||||
		var buffers = [];
 | 
			
		||||
		file.on('data', function(data) { buffers.push(data); });
 | 
			
		||||
		file.on('end', function() { files[fieldname] = [Buffer.concat(buffers), filename]; });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	/* on the finish event, all of the fields and files are ready */
 | 
			
		||||
	bb.on('finish', function() {
 | 
			
		||||
		/* grab the first file */
 | 
			
		||||
		var f = files[Object.keys(files)[0]];
 | 
			
		||||
		if(!f) callback(new Error("Must submit a file for processing!"));
 | 
			
		||||
 | 
			
		||||
		/* f[0] is a buffer, convert to string and interpret as Base64 */
 | 
			
		||||
		var wb = XLSX.read(f[0].toString(), {type:"base64"});
 | 
			
		||||
 | 
			
		||||
		/* grab first worksheet and convert to CSV */
 | 
			
		||||
		var ws = wb.Sheets[wb.SheetNames[0]];
 | 
			
		||||
		callback(null, { body: XLSX.utils.sheet_to_csv(ws) });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	bb.end(event.body);
 | 
			
		||||
};
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
AWSTemplateFormatVersion : '2010-09-09'
 | 
			
		||||
Transform: AWS::Serverless-2016-10-31
 | 
			
		||||
 | 
			
		||||
Description: Sample Lambda API Gateway Normalizer
 | 
			
		||||
Resources:
 | 
			
		||||
  LambdaProxy:
 | 
			
		||||
    Type: AWS::Serverless::Function
 | 
			
		||||
    Properties:
 | 
			
		||||
      Runtime: nodejs6.10
 | 
			
		||||
      Handler: index.handler
 | 
			
		||||
      BinaryMediaTypes: '*/*'
 | 
			
		||||
      Events:
 | 
			
		||||
        Api:
 | 
			
		||||
          Type: Api
 | 
			
		||||
          Properties:
 | 
			
		||||
            Path: /LambdaProxy
 | 
			
		||||
            Method: any
 | 
			
		||||
            BinaryMediaTypes: '*/*'
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
.PHONY: aws
 | 
			
		||||
aws: lambda-proxy
 | 
			
		||||
 | 
			
		||||
.PHONY: lambda-proxy
 | 
			
		||||
lambda-proxy:
 | 
			
		||||
	cd LambdaProxy; mkdir -p node_modules; npm install https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz busboy; sam local start-api; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: init-azure
 | 
			
		||||
init-azure:
 | 
			
		||||
	cd AzureHTTPTrigger; mkdir -p node_modules; npm install https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz formidable fs
 | 
			
		||||
 | 
			
		||||
.PHONY: azure
 | 
			
		||||
azure: init-azure
 | 
			
		||||
	func start
 | 
			
		||||
 | 
			
		||||
.PHONY: azure-server
 | 
			
		||||
azure-server:
 | 
			
		||||
	mkdir -p /tmp/azurite
 | 
			
		||||
	azurite -l /tmp/azurite
 | 
			
		||||
 | 
			
		||||
FILES=$(filter-out xlsx.full.min.js,$(wildcard *.js)) $(wildcard *.html)
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint: $(FILES)
 | 
			
		||||
	eslint $(FILES)
 | 
			
		||||
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *.db *.xlsx *.csv
 | 
			
		||||
@ -1,113 +1,9 @@
 | 
			
		||||
# "Serverless" Functions
 | 
			
		||||
 | 
			
		||||
Because the library is pure JS, the hard work of reading and writing files can
 | 
			
		||||
be performed in the client browser or on the server side.  On the server side,
 | 
			
		||||
the mechanical process is essentially independent from the data parsing or
 | 
			
		||||
generation.  As a result, it is sometimes sensible to organize applications so
 | 
			
		||||
that the "last mile" conversion between JSON data and spreadsheet files is
 | 
			
		||||
independent from the main application.
 | 
			
		||||
Cloud services are covered in separate demos:
 | 
			
		||||
 | 
			
		||||
The straightforward architecture would split off the JSON data conversion as a
 | 
			
		||||
separate microservice or application.  Since it is only needed when an import or
 | 
			
		||||
export is requested, and since the process itself is relatively independent from
 | 
			
		||||
the rest of a typical service, a "Serverless" architecture makes a great fit.
 | 
			
		||||
Since the "function" is separate from the rest of the application, it can be
 | 
			
		||||
integrated into a platform built in Java or Go or Python or another language!
 | 
			
		||||
- [AWS](https://docs.sheetjs.com/docs/demos/aws)
 | 
			
		||||
- [Azure](https://docs.sheetjs.com/docs/demos/azure)
 | 
			
		||||
 | 
			
		||||
This demo discusses general architectures and provides examples for popular
 | 
			
		||||
commercial systems and self-hosted alternatives.  The examples are merely
 | 
			
		||||
intended to demonstrate very basic functionality.
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Simple Strategies
 | 
			
		||||
 | 
			
		||||
#### Data Normalization
 | 
			
		||||
 | 
			
		||||
Most programming languages and platforms can process CSV or JSON but can't use
 | 
			
		||||
XLS or XLSX or XLSB directly.  Form data from an HTTP POST request can be parsed
 | 
			
		||||
and contained files can be converted to CSV or JSON.  The `XLSX.stream.to_csv`
 | 
			
		||||
utility can stream rows to a standard HTTP response.  `XLSX.utils.sheet_to_json`
 | 
			
		||||
can generate an array of objects that can be fed to another service.
 | 
			
		||||
 | 
			
		||||
At the simplest level, a file on the filesystem can be converted using the bin
 | 
			
		||||
script that ships with the NodeJS package:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ xlsx /path/to/uploads/file > /tmp/new_csv_file
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
From a utility script, workbooks can be converted in two lines:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var workbook = XLSX.readFile("path/to/file.xlsb");
 | 
			
		||||
XLSX.writeFile(workbook, "output/path/file.csv");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Report Generation
 | 
			
		||||
 | 
			
		||||
For an existing platform that already generates JSON or CSV or HTML output, the
 | 
			
		||||
library can process the data and generate a new file with embellishments. The
 | 
			
		||||
`XLSX.utils.sheet_add_json` and `XLSX.utils.sheet_add_aoa` functions can add
 | 
			
		||||
data rows to an existing worksheet:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var ws = XLSX.utils.aoa_to_sheet([
 | 
			
		||||
	["Company Report"],
 | 
			
		||||
	[],
 | 
			
		||||
	["Item", "Cost"]
 | 
			
		||||
]);
 | 
			
		||||
XLSX.utils.sheet_add_json(ws, [
 | 
			
		||||
	{ item: "Coffee", cost: 5 },
 | 
			
		||||
	{ item: "Cake", cost: 20 }
 | 
			
		||||
], { skipHeader: true, origin: -1, header: ["item", "cost"] });
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Deployment Targets
 | 
			
		||||
 | 
			
		||||
The library is supported in Node versions starting from `0.8` as well as a
 | 
			
		||||
myriad of ES3 and ES5 compatible JS engines.  All major services use Node
 | 
			
		||||
versions beyond major release 4, so there should be no problem directly using
 | 
			
		||||
the library in those environments.
 | 
			
		||||
 | 
			
		||||
Note that most cloud providers proactively convert form data to UTF8 strings.
 | 
			
		||||
This is especially problematic when dealing with XLSX and XLSB files, as they
 | 
			
		||||
naturally contain codes that are not valid UTF8 characters.  As a result, these
 | 
			
		||||
demos specifically handle Base64-encoded files only.  To test on the command
 | 
			
		||||
line, use the `base64` tool to encode data before piping to `curl`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
base64 test.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### AWS Lambda
 | 
			
		||||
 | 
			
		||||
Through the AWS Gateway API, Lambda functions can be triggered on HTTP requests.
 | 
			
		||||
The `LambdaProxy` example reads files from form data and converts to CSV.
 | 
			
		||||
 | 
			
		||||
When deploying on AWS, be sure to `npm install` locally and include the modules
 | 
			
		||||
in the ZIP file.
 | 
			
		||||
 | 
			
		||||
When reading form data, be sure to include the necessary binary types on the AWS API Gateway console.
 | 
			
		||||
To do this, navigate to the "Binary Media Types" section in the settings tab of the console.
 | 
			
		||||
For reading a file, you may need to add `"multipart/form-data"`.
 | 
			
		||||
For downloading a file, you may need to add `"application/vnd.ms-excel"`.
 | 
			
		||||
 | 
			
		||||
#### Azure Functions
 | 
			
		||||
 | 
			
		||||
Azure supports many types of triggers.  The `AzureHTTPTrigger` shows an example
 | 
			
		||||
HTTP trigger that converts the submitted file to CSV.
 | 
			
		||||
 | 
			
		||||
When deploying on Azure, be sure to install the module from the remote console,
 | 
			
		||||
as described in the "Azure Functions JavaScript developer guide".
 | 
			
		||||
 | 
			
		||||
#### Firebase Functions
 | 
			
		||||
 | 
			
		||||
Firebase functions can be triggered via HTTP requests, similar to a REST API.
 | 
			
		||||
In the `Firebase` directory, the example function reads files sent through
 | 
			
		||||
HTTP and converts it to a CSV and sends the response in the form of a string.
 | 
			
		||||
 | 
			
		||||
To run this demo locally, run `npm i -g firebase-tools` to install the
 | 
			
		||||
Firebase CLI and `npm i` to install the dependencies, then `firebase use --add`
 | 
			
		||||
to connect to an existing Firebase project. Run `firebase emulators:start` to
 | 
			
		||||
start the local server.
 | 
			
		||||
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "version": "2.0"
 | 
			
		||||
}
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "IsEncrypted": false,
 | 
			
		||||
  "Values": {
 | 
			
		||||
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
 | 
			
		||||
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true"
 | 
			
		||||
  },
 | 
			
		||||
  "Host": {
 | 
			
		||||
    "LocalHttpPort": 7262,
 | 
			
		||||
    "CORS": "*"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								demos/react/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										4
									
								
								demos/react/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,4 +0,0 @@
 | 
			
		||||
SheetJS
 | 
			
		||||
.next
 | 
			
		||||
static/shim.js
 | 
			
		||||
public/shim.js
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
.PHONY: react
 | 
			
		||||
react: init ## Simple server for react and clones
 | 
			
		||||
	python -mSimpleHTTPServer
 | 
			
		||||
 | 
			
		||||
.PHONY: next
 | 
			
		||||
next: init ## next.js demo
 | 
			
		||||
	next
 | 
			
		||||
 | 
			
		||||
.PHONY: native
 | 
			
		||||
native: ## Build react-native project
 | 
			
		||||
	bash ./native.sh
 | 
			
		||||
 | 
			
		||||
.PHONY: ios
 | 
			
		||||
ios: native ## react-native ios sim
 | 
			
		||||
	cd SheetJS; cd ios; pod install; cd -; react-native run-ios --simulator="iPhone X"; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: android
 | 
			
		||||
android: native ## react-native android sim
 | 
			
		||||
	cd SheetJS; react-native run-android; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: init
 | 
			
		||||
init: ## set up node_modules and symlink
 | 
			
		||||
	mkdir -p node_modules
 | 
			
		||||
	cd node_modules; if [ ! -e xlsx ]; then ln -s ../../../ xlsx; fi; cd -
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
# Additional Notes
 | 
			
		||||
 | 
			
		||||
## Java, React Native, Gradle versions
 | 
			
		||||
 | 
			
		||||
This demo was tested and runs with React Native 0.62.2, Java 11, and Gradle
 | 
			
		||||
3.5.2. Running `make native` will invoke `native.sh`, which uses a fixed version
 | 
			
		||||
of React Native 0.62.2 to build and run the demo.
 | 
			
		||||
 | 
			
		||||
Make sure you have the correct version of Java (11) installed, since 0.62.2 might
 | 
			
		||||
not work with newer versions of Java.
 | 
			
		||||
 | 
			
		||||
## Common Issues
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Add `export JAVA_HOME=<directory>`, replacing `<directory>` with the location of
 | 
			
		||||
your Java install, to your `.bashrc` or any other shell that you are using.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,154 +1,12 @@
 | 
			
		||||
# React
 | 
			
		||||
 | 
			
		||||
The `xlsx.core.min.js` and `xlsx.full.min.js` scripts are designed to be dropped
 | 
			
		||||
into web pages with script tags:
 | 
			
		||||
[The new demo](https://docs.sheetjs.com/docs/demos/react) has an updated
 | 
			
		||||
exposition for legacy and modern deployments alike.
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<script src="xlsx.full.min.js"></script>
 | 
			
		||||
```
 | 
			
		||||
The ecosystem demos were grouped by type in the new demo site:
 | 
			
		||||
 | 
			
		||||
The library can also be imported directly from JSX code with:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { read, utils, writeFileXLSX } from 'xlsx';
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This demo shows a simple React component transpiled in the browser using Babel
 | 
			
		||||
standalone library.  Since there is no standard React table model, this demo
 | 
			
		||||
settles on the array of arrays approach.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Other scripts in this demo show:
 | 
			
		||||
- server-rendered React component (with `next.js`)
 | 
			
		||||
- `react-native` deployment for iOS and android
 | 
			
		||||
- [`react-data-grid` reading, modifying, and writing files](modify/)
 | 
			
		||||
 | 
			
		||||
## How to run
 | 
			
		||||
 | 
			
		||||
Run `make react` to run the browser demo for React, or run `make next` to run
 | 
			
		||||
the server-rendered demo using `next.js`.
 | 
			
		||||
 | 
			
		||||
## Internal State
 | 
			
		||||
 | 
			
		||||
The simplest state representation is an array of arrays.  To avoid having the
 | 
			
		||||
table component depend on the library, the column labels are precomputed.  The
 | 
			
		||||
state in this demo is shaped like the following object:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
{
 | 
			
		||||
  cols: [{ name: "A", key: 0 }, { name: "B", key: 1 }, { name: "C", key: 2 }],
 | 
			
		||||
  data: [
 | 
			
		||||
    [ "id",    "name", "value" ],
 | 
			
		||||
    [    1, "sheetjs",    7262 ],
 | 
			
		||||
    [    2, "js-xlsx",    6969 ]
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`sheet_to_json` and `aoa_to_sheet` utility functions can convert between arrays
 | 
			
		||||
of arrays and worksheets:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* convert from workbook to array of arrays */
 | 
			
		||||
var first_worksheet = workbook.Sheets[workbook.SheetNames[0]];
 | 
			
		||||
var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1});
 | 
			
		||||
 | 
			
		||||
/* convert from array of arrays to workbook */
 | 
			
		||||
var worksheet = XLSX.utils.aoa_to_sheet(data);
 | 
			
		||||
var new_workbook = XLSX.utils.book_new();
 | 
			
		||||
XLSX.utils.book_append_sheet(new_workbook, worksheet, "SheetJS");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The column objects can be generated with the `encode_col` utility function:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function make_cols(refstr/*:string*/) {
 | 
			
		||||
  var o = [];
 | 
			
		||||
  var range = XLSX.utils.decode_range(refstr);
 | 
			
		||||
  for(var i = 0; i <= range.e.c; ++i) {
 | 
			
		||||
    o.push({name: XLSX.utils.encode_col(i), key:i});
 | 
			
		||||
  }
 | 
			
		||||
  return o;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## React Native
 | 
			
		||||
 | 
			
		||||
[The new demo](https://docs.sheetjs.com/docs/demos/mobile#react-native) uses
 | 
			
		||||
up-to-date file I/O and file picker libraries.
 | 
			
		||||
 | 
			
		||||
## Server-Rendered React Components with Next.js
 | 
			
		||||
 | 
			
		||||
The demo reads from `public/sheetjs.xlsx`.  HTML output is generated using
 | 
			
		||||
`XLSX.utils.sheet_to_html` and inserted with `dangerouslySetInnerHTML`:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
export default function Index({html, type}) { return (
 | 
			
		||||
  // ...
 | 
			
		||||
  <div dangerouslySetInnerHTML={{ __html: html }} />
 | 
			
		||||
  // ...
 | 
			
		||||
); }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Next currently offers 3 general strategies for server-side data fetching:
 | 
			
		||||
 | 
			
		||||
#### "Server-Side Rendering" using `getServerSideProps`
 | 
			
		||||
 | 
			
		||||
`/getServerSideProps` reads the file on each request.  The first worksheet is
 | 
			
		||||
converted to HTML:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
export async function getServerSideProps() {
 | 
			
		||||
  const wb = XLSX.readFile(path);
 | 
			
		||||
  return { props: {
 | 
			
		||||
    html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])
 | 
			
		||||
  }};
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### "Static Site Generation" using `getStaticProps`
 | 
			
		||||
 | 
			
		||||
`/getServerSideProps` reads the file at build time.  The first worksheet is
 | 
			
		||||
converted to HTML:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
export async function getStaticProps() {
 | 
			
		||||
  const wb = XLSX.readFile(path);
 | 
			
		||||
  return { props: {
 | 
			
		||||
    html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])
 | 
			
		||||
  }};
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### "Static Site Generation with Dynamic Routes" using `getStaticPaths`
 | 
			
		||||
 | 
			
		||||
`/getStaticPaths` reads the file at build time and generates a list of sheets.
 | 
			
		||||
 | 
			
		||||
`/sheets/[id]` uses `getStaticPaths` to generate a path per sheet index:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
export async function getStaticPaths() {
 | 
			
		||||
  const wb = XLSX.readFile(path);
 | 
			
		||||
  return {
 | 
			
		||||
    paths: wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString()  } })),
 | 
			
		||||
    fallback: false
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
It also uses `getStaticProps` for the actual HTML generation:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
export async function getStaticProps(ctx) {
 | 
			
		||||
  const wb = XLSX.readFile(path);
 | 
			
		||||
  return { props: {
 | 
			
		||||
    html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[ctx.params.id]]),
 | 
			
		||||
  }};
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Additional Notes
 | 
			
		||||
 | 
			
		||||
Some additional notes can be found in [`NOTES.md`](NOTES.md).
 | 
			
		||||
- [server-rendered React components with `next.js`](https://docs.sheetjs.com/docs/demos/content#nextjs) is now part of "Content and Site Generation"
 | 
			
		||||
- [`react-native` deployment for iOS and android](https://docs.sheetjs.com/docs/demos/mobile#react-native) is now part of "iOS and Android Apps"
 | 
			
		||||
- [`react-data-grid` reading, modifying, and writing files](https://docs.sheetjs.com/docs/demo/grid#react-data-grid) is now part of "Data Grids and UI"
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html lang="en" style="height: 100%">
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
<title>SheetJS React Demo</title>
 | 
			
		||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
 | 
			
		||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
 | 
			
		||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
 | 
			
		||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
 | 
			
		||||
<script src="node_modules/xlsx/dist/shim.min.js"></script>
 | 
			
		||||
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
 | 
			
		||||
<style>body, #app { height: 100%; };</style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<div class="container-fluid">
 | 
			
		||||
<h1><a href="http://sheetjs.com">SheetJS React Demo</a></h1>
 | 
			
		||||
<br />
 | 
			
		||||
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
 | 
			
		||||
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues?  Something look weird?  Click here and report an issue</a><br /><br />
 | 
			
		||||
</div>
 | 
			
		||||
<div id="app" class="container-fluid"></div>
 | 
			
		||||
<script type="text/babel" src="sheetjs.js"></script>
 | 
			
		||||
<script type="text/babel">
 | 
			
		||||
	ReactDOM.render( <SheetJSApp />, document.getElementById('app') );
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										23
									
								
								demos/react/modify/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										23
									
								
								demos/react/modify/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,23 +0,0 @@
 | 
			
		||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
 | 
			
		||||
 | 
			
		||||
# dependencies
 | 
			
		||||
/node_modules
 | 
			
		||||
/.pnp
 | 
			
		||||
.pnp.js
 | 
			
		||||
 | 
			
		||||
# testing
 | 
			
		||||
/coverage
 | 
			
		||||
 | 
			
		||||
# production
 | 
			
		||||
/build
 | 
			
		||||
 | 
			
		||||
# misc
 | 
			
		||||
.DS_Store
 | 
			
		||||
.env.local
 | 
			
		||||
.env.development.local
 | 
			
		||||
.env.test.local
 | 
			
		||||
.env.production.local
 | 
			
		||||
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
yarn-debug.log*
 | 
			
		||||
yarn-error.log*
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
# react-modify
 | 
			
		||||
 | 
			
		||||
This demo shows import and export with the `react-data-grid` table component.
 | 
			
		||||
 | 
			
		||||
In the project directory, you can run:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ npm install
 | 
			
		||||
$ npm start
 | 
			
		||||
```
 | 
			
		||||
@ -1,36 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "react-modify-demo",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@types/react": "^17.0.0",
 | 
			
		||||
    "@types/react-dom": "^17.0.0",
 | 
			
		||||
    "react": "^17.0.2",
 | 
			
		||||
    "react-data-grid": "^7.0.0-beta.11",
 | 
			
		||||
    "react-dom": "^17.0.2",
 | 
			
		||||
    "react-scripts": "4.0.3",
 | 
			
		||||
    "typescript": "^4.1.2",
 | 
			
		||||
    "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "react-scripts start",
 | 
			
		||||
    "build": "react-scripts build",
 | 
			
		||||
    "eject": "react-scripts eject"
 | 
			
		||||
  },
 | 
			
		||||
  "eslintConfig": {
 | 
			
		||||
    "extends": [
 | 
			
		||||
      "react-app",
 | 
			
		||||
      "react-app/jest"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "browserslist": {
 | 
			
		||||
    "production": [
 | 
			
		||||
      ">0.2%",
 | 
			
		||||
      "not dead",
 | 
			
		||||
      "not op_mini all"
 | 
			
		||||
    ],
 | 
			
		||||
    "development": [
 | 
			
		||||
      "last 1 chrome version",
 | 
			
		||||
      "last 1 firefox version",
 | 
			
		||||
      "last 1 safari version"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
			
		||||
    <meta name="theme-color" content="#000000" />
 | 
			
		||||
    <meta
 | 
			
		||||
      name="description"
 | 
			
		||||
      content="Web site created using create-react-app"
 | 
			
		||||
    />
 | 
			
		||||
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
 | 
			
		||||
    <!--
 | 
			
		||||
      manifest.json provides metadata used when your web app is installed on a
 | 
			
		||||
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
 | 
			
		||||
    -->
 | 
			
		||||
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
 | 
			
		||||
    <!--
 | 
			
		||||
      Notice the use of %PUBLIC_URL% in the tags above.
 | 
			
		||||
      It will be replaced with the URL of the `public` folder during the build.
 | 
			
		||||
      Only files inside the `public` folder can be referenced from the HTML.
 | 
			
		||||
 | 
			
		||||
      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
 | 
			
		||||
      work correctly both with client-side routing and a non-root public URL.
 | 
			
		||||
      Learn how to configure a non-root public URL by running `npm run build`.
 | 
			
		||||
    -->
 | 
			
		||||
    <title>React App</title>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
			
		||||
    <div id="root"></div>
 | 
			
		||||
    <!--
 | 
			
		||||
      This HTML file is a template.
 | 
			
		||||
      If you open it directly in the browser, you will see an empty page.
 | 
			
		||||
 | 
			
		||||
      You can add webfonts, meta tags, or analytics to this file.
 | 
			
		||||
      The build step will place the bundled scripts into the <body> tag.
 | 
			
		||||
 | 
			
		||||
      To begin the development, run `npm start` or `yarn start`.
 | 
			
		||||
      To create a production bundle, use `npm run build` or `yarn build`.
 | 
			
		||||
    -->
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
@ -1,107 +0,0 @@
 | 
			
		||||
import React, { useState, ChangeEvent } from "react";
 | 
			
		||||
import DataGrid, { TextEditor } from "react-data-grid";
 | 
			
		||||
import { read, utils, WorkSheet, writeFile } from "xlsx";
 | 
			
		||||
 | 
			
		||||
import "../styles/App.css";
 | 
			
		||||
 | 
			
		||||
type Row = any[]; /*{
 | 
			
		||||
  [index: string]: string | number;
 | 
			
		||||
};*/
 | 
			
		||||
 | 
			
		||||
type Column = {
 | 
			
		||||
  key: string;
 | 
			
		||||
  name: string;
 | 
			
		||||
  editor: typeof TextEditor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type DataSet = {
 | 
			
		||||
  [index: string]: WorkSheet;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function getRowsCols(
 | 
			
		||||
  data: DataSet,
 | 
			
		||||
  sheetName: string
 | 
			
		||||
): {
 | 
			
		||||
  rows: Row[];
 | 
			
		||||
  columns: Column[];
 | 
			
		||||
} {
 | 
			
		||||
  const rows: Row[] = utils.sheet_to_json(data[sheetName], {header:1});
 | 
			
		||||
  let columns: Column[] = [];
 | 
			
		||||
 | 
			
		||||
  for (let row of rows) {
 | 
			
		||||
    const keys: string[] = Object.keys(row);
 | 
			
		||||
 | 
			
		||||
    if (keys.length > columns.length) {
 | 
			
		||||
      columns = keys.map((key) => {
 | 
			
		||||
        return { key, name: utils.encode_col(+key), editor: TextEditor };
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return { rows, columns };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
  const [rows, setRows] = useState<Row[]>([]);
 | 
			
		||||
  const [columns, setColumns] = useState<Column[]>([]);
 | 
			
		||||
  const [workBook, setWorkBook] = useState<DataSet>({} as DataSet);
 | 
			
		||||
  const [sheets, setSheets] = useState<string[]>([]);
 | 
			
		||||
  const [current, setCurrent] = useState<string>("");
 | 
			
		||||
 | 
			
		||||
  const exportTypes = ["xlsx", "xlsb", "csv", "html"];
 | 
			
		||||
 | 
			
		||||
  function selectSheet(name: string, reset = true) {
 | 
			
		||||
    if(reset) workBook[current] = utils.json_to_sheet(rows, {
 | 
			
		||||
      header: columns.map((col: Column) => col.key),
 | 
			
		||||
      skipHeader: true
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const { rows: new_rows, columns: new_columns } = getRowsCols(workBook, name);
 | 
			
		||||
 | 
			
		||||
    setRows(new_rows);
 | 
			
		||||
    setColumns(new_columns);
 | 
			
		||||
    setCurrent(name);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async function handleFile(ev: ChangeEvent<HTMLInputElement>): Promise<void> {
 | 
			
		||||
    const file = await ev.target.files?.[0]?.arrayBuffer();
 | 
			
		||||
    const data = read(file);
 | 
			
		||||
 | 
			
		||||
    setWorkBook(data.Sheets);
 | 
			
		||||
    setSheets(data.SheetNames);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function saveFile(ext: string): void {
 | 
			
		||||
    const wb = utils.book_new();
 | 
			
		||||
 | 
			
		||||
    sheets.forEach((n) => {
 | 
			
		||||
      utils.book_append_sheet(wb, workBook[n], n);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    writeFile(wb, "sheet." + ext);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <input type="file" onChange={handleFile} />
 | 
			
		||||
      <div className="flex-cont">
 | 
			
		||||
        {sheets.map((sheet) => (
 | 
			
		||||
          <button key={sheet} onClick={(e) => selectSheet(sheet)}>
 | 
			
		||||
            {sheet}
 | 
			
		||||
          </button>
 | 
			
		||||
        ))}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="flex-cont">
 | 
			
		||||
        <b>Current Sheet: {current}</b>
 | 
			
		||||
      </div>
 | 
			
		||||
      <DataGrid columns={columns} rows={rows} onRowsChange={setRows} />
 | 
			
		||||
      <div className="flex-cont">
 | 
			
		||||
        {exportTypes.map((ext) => (
 | 
			
		||||
          <button key={ext} onClick={() => saveFile(ext)}>
 | 
			
		||||
            export [.{ext}]
 | 
			
		||||
          </button>
 | 
			
		||||
        ))}
 | 
			
		||||
      </div>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -1,12 +0,0 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import ReactDOM from 'react-dom';
 | 
			
		||||
import App from './components/App';
 | 
			
		||||
 | 
			
		||||
import './styles/index.css';
 | 
			
		||||
 | 
			
		||||
ReactDOM.render(
 | 
			
		||||
  <React.StrictMode>
 | 
			
		||||
    <App/>
 | 
			
		||||
  </React.StrictMode>,
 | 
			
		||||
  document.getElementById('root')
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										1
									
								
								demos/react/modify/src/react-app-env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/react/modify/src/react-app-env.d.ts
									
									
									
									
										vendored
									
									
								
							@ -1 +0,0 @@
 | 
			
		||||
/// <reference types="react-scripts" />
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
input {
 | 
			
		||||
  margin: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.flex-cont {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin: 0.5rem;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.flex-cont button {
 | 
			
		||||
    margin: 0.3rem;
 | 
			
		||||
    padding: 0.2rem;
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
 | 
			
		||||
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
 | 
			
		||||
    sans-serif;
 | 
			
		||||
  -webkit-font-smoothing: antialiased;
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "target": "es5",
 | 
			
		||||
    "lib": [
 | 
			
		||||
      "dom",
 | 
			
		||||
      "dom.iterable",
 | 
			
		||||
      "esnext"
 | 
			
		||||
    ],
 | 
			
		||||
    "allowJs": true,
 | 
			
		||||
    "skipLibCheck": true,
 | 
			
		||||
    "esModuleInterop": true,
 | 
			
		||||
    "allowSyntheticDefaultImports": true,
 | 
			
		||||
    "forceConsistentCasingInFileNames": true,
 | 
			
		||||
    "strict": true,
 | 
			
		||||
    "noFallthroughCasesInSwitch": true,
 | 
			
		||||
    "module": "esnext",
 | 
			
		||||
    "moduleResolution": "node",
 | 
			
		||||
    "resolveJsonModule": true,
 | 
			
		||||
    "isolatedModules": true,
 | 
			
		||||
    "noEmit": true,
 | 
			
		||||
    "jsx": "react-jsx"
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "src"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
import * as XLSX from 'xlsx';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
import Head from 'next/head';
 | 
			
		||||
import { readFile, utils } from 'xlsx';
 | 
			
		||||
import { join } from 'path';
 | 
			
		||||
import { cwd } from 'process';
 | 
			
		||||
 | 
			
		||||
export default function Index({html, type}) { return (
 | 
			
		||||
<div>
 | 
			
		||||
  <Head>
 | 
			
		||||
    <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
    <title>SheetJS Next.JS {type} Demo</title>
 | 
			
		||||
    <script src="/shim.js"></script>
 | 
			
		||||
    <style jsx>{`
 | 
			
		||||
      body, #app { height: 100%; };
 | 
			
		||||
    `}</style>
 | 
			
		||||
  </Head>
 | 
			
		||||
  <pre>
 | 
			
		||||
<h3>SheetJS Next.JS {type} Demo</h3>
 | 
			
		||||
This demo reads from /public/sheetjs.xlsx and generates HTML from the first sheet.
 | 
			
		||||
  </pre>
 | 
			
		||||
  <div dangerouslySetInnerHTML={{ __html: html }} />
 | 
			
		||||
</div>
 | 
			
		||||
); }
 | 
			
		||||
 | 
			
		||||
export async function getServerSideProps() {
 | 
			
		||||
  const wb = readFile(join(cwd(), "public", "sheetjs.xlsx"))
 | 
			
		||||
  return {
 | 
			
		||||
    props: {
 | 
			
		||||
      type: "getStaticProps",
 | 
			
		||||
      html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]),
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
import Head from 'next/head';
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { readFile, utils } from 'xlsx';
 | 
			
		||||
import { join } from 'path';
 | 
			
		||||
import { cwd } from 'process';
 | 
			
		||||
 | 
			
		||||
export default function Index({snames, type}) { return (
 | 
			
		||||
<div>
 | 
			
		||||
  <Head>
 | 
			
		||||
    <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
    <title>SheetJS Next.JS {type} Demo</title>
 | 
			
		||||
    <script src="/shim.js"></script>
 | 
			
		||||
    <style jsx>{`
 | 
			
		||||
      body, #app { height: 100%; };
 | 
			
		||||
    `}</style>
 | 
			
		||||
  </Head>
 | 
			
		||||
  <pre>
 | 
			
		||||
<h3>SheetJS Next.JS {type} Demo</h3>
 | 
			
		||||
This demo reads from /public/sheetjs.xlsx.  Each worksheet maps to a path:<br/><br/>
 | 
			
		||||
{snames.map((sname, idx) => (<>
 | 
			
		||||
  <Link key={idx} href="/sheets/[id]" as={`/sheets/${idx}`}><a>{`Sheet index=${idx} name="${sname}"`}</a></Link>
 | 
			
		||||
  <br/>
 | 
			
		||||
  <br/>
 | 
			
		||||
</>))}
 | 
			
		||||
 | 
			
		||||
  </pre>
 | 
			
		||||
</div>
 | 
			
		||||
); }
 | 
			
		||||
 | 
			
		||||
export async function getStaticProps() {
 | 
			
		||||
  const wb = readFile(join(cwd(), "public", "sheetjs.xlsx"))
 | 
			
		||||
  return {
 | 
			
		||||
    props: {
 | 
			
		||||
      type: "getStaticPaths",
 | 
			
		||||
      snames: wb.SheetNames,
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
import Head from 'next/head';
 | 
			
		||||
import { readFile, utils } from 'xlsx';
 | 
			
		||||
import { join } from 'path';
 | 
			
		||||
import { cwd } from 'process';
 | 
			
		||||
 | 
			
		||||
export default function Index({html, type}) { return (
 | 
			
		||||
<div>
 | 
			
		||||
  <Head>
 | 
			
		||||
    <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
    <title>SheetJS Next.JS {type} Demo</title>
 | 
			
		||||
    <script src="/shim.js"></script>
 | 
			
		||||
    <style jsx>{`
 | 
			
		||||
      body, #app { height: 100%; };
 | 
			
		||||
    `}</style>
 | 
			
		||||
  </Head>
 | 
			
		||||
  <pre>
 | 
			
		||||
<h3>SheetJS Next.JS {type} Demo</h3>
 | 
			
		||||
This demo reads from /public/sheetjs.xlsx and generates HTML from the first sheet.
 | 
			
		||||
  </pre>
 | 
			
		||||
  <div dangerouslySetInnerHTML={{ __html: html }} />
 | 
			
		||||
</div>
 | 
			
		||||
); }
 | 
			
		||||
 | 
			
		||||
export async function getStaticProps() {
 | 
			
		||||
  const wb = readFile(join(cwd(), "public", "sheetjs.xlsx"))
 | 
			
		||||
  return {
 | 
			
		||||
    props: {
 | 
			
		||||
      type: "getStaticProps",
 | 
			
		||||
      html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]),
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
import Head from 'next/head';
 | 
			
		||||
 | 
			
		||||
export default function Index() { return (
 | 
			
		||||
<div>
 | 
			
		||||
  <Head>
 | 
			
		||||
    <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
    <title>SheetJS Next.JS Demo</title>
 | 
			
		||||
    <script src="/shim.js"></script>
 | 
			
		||||
    <style jsx>{`
 | 
			
		||||
      body, #app { height: 100%; };
 | 
			
		||||
    `}</style>
 | 
			
		||||
  </Head>
 | 
			
		||||
  <pre>
 | 
			
		||||
<h3>SheetJS Next.JS Demos</h3>
 | 
			
		||||
All demos read from /public/sheetjs.xlsx.<br/>
 | 
			
		||||
<br/>
 | 
			
		||||
- <a href="/getStaticProps">getStaticProps</a><br/>
 | 
			
		||||
<br/>
 | 
			
		||||
- <a href="/getServerSideProps">getServerSideProps</a><br/>
 | 
			
		||||
<br/>
 | 
			
		||||
- <a href="/getStaticPaths">getStaticPaths</a><br/>
 | 
			
		||||
  </pre>
 | 
			
		||||
</div>
 | 
			
		||||
); }
 | 
			
		||||
@ -1,51 +0,0 @@
 | 
			
		||||
import Head from 'next/head';
 | 
			
		||||
import { readFile, utils } from 'xlsx';
 | 
			
		||||
import { join } from 'path';
 | 
			
		||||
import { cwd } from 'process';
 | 
			
		||||
 | 
			
		||||
export default function Index({html, type, name}) { return (
 | 
			
		||||
<div>
 | 
			
		||||
  <Head>
 | 
			
		||||
    <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
    <title>SheetJS Next.JS {type} Demo</title>
 | 
			
		||||
    <script src="/shim.js"></script>
 | 
			
		||||
    <style jsx>{`
 | 
			
		||||
      body, #app { height: 100%; };
 | 
			
		||||
    `}</style>
 | 
			
		||||
  </Head>
 | 
			
		||||
  <pre>
 | 
			
		||||
<h3>SheetJS Next.JS {type} Demo</h3>
 | 
			
		||||
This demo reads from /public/sheetjs.xlsx.<br/>
 | 
			
		||||
<br/>
 | 
			
		||||
<b>{name}</b>
 | 
			
		||||
  </pre>
 | 
			
		||||
  <div dangerouslySetInnerHTML={{ __html: html }} />
 | 
			
		||||
</div>
 | 
			
		||||
); }
 | 
			
		||||
 | 
			
		||||
let cache = [];
 | 
			
		||||
 | 
			
		||||
export async function getStaticProps(ctx) {
 | 
			
		||||
  if(!cache || !cache.length) {
 | 
			
		||||
    const wb = readFile(join(cwd(), "public", "sheetjs.xlsx"));
 | 
			
		||||
    cache = wb.SheetNames.map((name) => ({ name, sheet: wb.Sheets[name] }));
 | 
			
		||||
  }
 | 
			
		||||
  const entry = cache[ctx.params.id];
 | 
			
		||||
  return {
 | 
			
		||||
    props: {
 | 
			
		||||
      type: "getStaticPaths",
 | 
			
		||||
      name: entry.name,
 | 
			
		||||
      id: ctx.params.id.toString(),
 | 
			
		||||
      html: entry.sheet ? utils.sheet_to_html(entry.sheet) : "",
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getStaticPaths() {
 | 
			
		||||
  const wb = readFile(join(cwd(), "public", "sheetjs.xlsx"));
 | 
			
		||||
  cache = wb.SheetNames.map((name) => ({ name, sheet: wb.Sheets[name] }));
 | 
			
		||||
  return {
 | 
			
		||||
    paths: wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString()  } })),
 | 
			
		||||
    fallback: false,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@ -1,144 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* Notes:
 | 
			
		||||
   - usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
 | 
			
		||||
   - xlsx.full.min.js is loaded in the head of the HTML page
 | 
			
		||||
   - this script should be referenced with type="text/babel"
 | 
			
		||||
   - babel.js in-browser transpiler should be loaded before this script
 | 
			
		||||
*/
 | 
			
		||||
function SheetJSApp() {
 | 
			
		||||
	const [data, setData] = React.useState([]);
 | 
			
		||||
	const [cols, setCols] = React.useState([]);
 | 
			
		||||
 | 
			
		||||
	const handleFile = (file) => {
 | 
			
		||||
		const reader = new FileReader();
 | 
			
		||||
		reader.onload = (e) => {
 | 
			
		||||
			/* Parse data */
 | 
			
		||||
			const ab = e.target.result;
 | 
			
		||||
			const wb = XLSX.read(ab, {type:'array'});
 | 
			
		||||
			/* Get first worksheet */
 | 
			
		||||
			const wsname = wb.SheetNames[0];
 | 
			
		||||
			const ws = wb.Sheets[wsname];
 | 
			
		||||
			/* Convert array of arrays */
 | 
			
		||||
			const data = XLSX.utils.sheet_to_json(ws, {header:1});
 | 
			
		||||
			/* Update state */
 | 
			
		||||
			setData(data);
 | 
			
		||||
			setCols(make_cols(ws['!ref']))
 | 
			
		||||
		};
 | 
			
		||||
		reader.readAsArrayBuffer(file);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const exportFile = () => {
 | 
			
		||||
		/* convert state to workbook */
 | 
			
		||||
		const ws = XLSX.utils.aoa_to_sheet(data);
 | 
			
		||||
		const wb = XLSX.utils.book_new();
 | 
			
		||||
		XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
 | 
			
		||||
		/* generate XLSX file and send to client */
 | 
			
		||||
		XLSX.writeFile(wb, "sheetjs.xlsx")
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
	<DragDropFile handleFile={handleFile}>
 | 
			
		||||
		<div className="row"><div className="col-xs-12">
 | 
			
		||||
			<DataInput handleFile={handleFile} />
 | 
			
		||||
		</div></div>
 | 
			
		||||
		<div className="row"><div className="col-xs-12">
 | 
			
		||||
			<button disabled={!data.length} className="btn btn-success" onClick={exportFile}>Export</button>
 | 
			
		||||
		</div></div>
 | 
			
		||||
		<div className="row"><div className="col-xs-12">
 | 
			
		||||
			<OutTable data={data} cols={cols} />
 | 
			
		||||
		</div></div>
 | 
			
		||||
	</DragDropFile>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if(typeof module !== 'undefined') module.exports = SheetJSApp
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Simple HTML5 file drag-and-drop wrapper
 | 
			
		||||
  usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
 | 
			
		||||
    handleFile(file:File):void;
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
function DragDropFile({ handleFile, children }) {
 | 
			
		||||
	const suppress = (e) => { e.stopPropagation(); e.preventDefault(); };
 | 
			
		||||
	const handleDrop = (e) => { e.stopPropagation(); e.preventDefault();
 | 
			
		||||
		const files = e.dataTransfer.files;
 | 
			
		||||
		if(files && files[0]) handleFile(files[0]);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<div
 | 
			
		||||
			onDrop={handleDrop}
 | 
			
		||||
			onDragEnter={suppress}
 | 
			
		||||
			onDragOver={suppress}
 | 
			
		||||
		>
 | 
			
		||||
		{children}
 | 
			
		||||
		</div>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Simple HTML5 file input wrapper
 | 
			
		||||
  usage: <DataInput handleFile={callback} />
 | 
			
		||||
    handleFile(file:File):void;
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
function DataInput({ handleFile }) {
 | 
			
		||||
	const handleChange = (e) => {
 | 
			
		||||
		const files = e.target.files;
 | 
			
		||||
		if(files && files[0]) handleFile(files[0]);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<form className="form-inline">
 | 
			
		||||
			<div className="form-group">
 | 
			
		||||
				<label htmlFor="file">Drag or choose a spreadsheet file</label>
 | 
			
		||||
				<br />
 | 
			
		||||
				<input
 | 
			
		||||
					type="file"
 | 
			
		||||
					className="form-control"
 | 
			
		||||
					id="file"
 | 
			
		||||
					accept={SheetJSFT}
 | 
			
		||||
					onChange={handleChange}
 | 
			
		||||
				/>
 | 
			
		||||
			</div>
 | 
			
		||||
		</form>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Simple HTML Table
 | 
			
		||||
  usage: <OutTable data={data} cols={cols} />
 | 
			
		||||
    data:Array<Array<any> >;
 | 
			
		||||
    cols:Array<{name:string, key:number|string}>;
 | 
			
		||||
*/
 | 
			
		||||
function OutTable({ data, cols }) {
 | 
			
		||||
	return (
 | 
			
		||||
		<div className="table-responsive">
 | 
			
		||||
			<table className="table table-striped">
 | 
			
		||||
				<thead>
 | 
			
		||||
					<tr>{cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
 | 
			
		||||
				</thead>
 | 
			
		||||
				<tbody>
 | 
			
		||||
					{data.map((r,i) => <tr key={i}>
 | 
			
		||||
						{cols.map(c => <td key={c.key}>{ r[c.key] }</td>)}
 | 
			
		||||
					</tr>)}
 | 
			
		||||
				</tbody>
 | 
			
		||||
			</table>
 | 
			
		||||
		</div>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* list of supported file types */
 | 
			
		||||
const SheetJSFT = [
 | 
			
		||||
	"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
 | 
			
		||||
].map(x => `.${x}`).join(",");
 | 
			
		||||
 | 
			
		||||
/* generate an array of column objects */
 | 
			
		||||
const make_cols = refstr => {
 | 
			
		||||
	let o = [], C = XLSX.utils.decode_range(refstr).e.c + 1;
 | 
			
		||||
	for(var i = 0; i < C; ++i) o[i] = {name:XLSX.utils.encode_col(i), key:i}
 | 
			
		||||
	return o;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										2
									
								
								demos/server/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								demos/server/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +0,0 @@
 | 
			
		||||
xlsx.full.min.js
 | 
			
		||||
xlsx-demo
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
.PHONY: init
 | 
			
		||||
init:
 | 
			
		||||
	mkdir -p node_modules
 | 
			
		||||
	cd node_modules; if [ ! -e xlsx ]; then ln -s ../../../ xlsx; fi; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: request
 | 
			
		||||
request: init ## request demo
 | 
			
		||||
	node _request.js
 | 
			
		||||
 | 
			
		||||
.PHONY: express
 | 
			
		||||
express: init ## express demo
 | 
			
		||||
	node express.js
 | 
			
		||||
 | 
			
		||||
.PHONY: koa
 | 
			
		||||
koa: init ## koa demo
 | 
			
		||||
	node koa.js
 | 
			
		||||
 | 
			
		||||
.PHONY: hapi
 | 
			
		||||
hapi: init ## hapi demo
 | 
			
		||||
	cp ../../dist/xlsx.full.min.js .
 | 
			
		||||
	node hapi.js
 | 
			
		||||
 | 
			
		||||
.PHONY: nest
 | 
			
		||||
nest: init ## nest demo
 | 
			
		||||
	bash -c ./nest.sh
 | 
			
		||||
 | 
			
		||||
.PHONY: drash
 | 
			
		||||
drash: ## drash demo
 | 
			
		||||
	deno run --allow-net drash.ts
 | 
			
		||||
@ -1,208 +1,11 @@
 | 
			
		||||
# NodeJS Server Deployments
 | 
			
		||||
 | 
			
		||||
This library is 100% pure JS.  This is great for compatibility but tends to lock
 | 
			
		||||
up long-running processes.  In the web browser, Web Workers are used to offload
 | 
			
		||||
work from the main browser thread.  In NodeJS, there are other strategies.  This
 | 
			
		||||
demo shows a few different strategies applied to different server frameworks.
 | 
			
		||||
[The new demo](https://docs.sheetjs.com/docs/demos/server) has a more focused
 | 
			
		||||
discussion with examples for popular JS server-side frameworks.
 | 
			
		||||
 | 
			
		||||
NOTE: these examples merely demonstrate the core concepts and do not include
 | 
			
		||||
appropriate error checking or other production-level features.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Express Setup
 | 
			
		||||
 | 
			
		||||
The following commands are required in order to test the [Express](https://github.com/expressjs/express) demo:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install express printj express-formidable https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
 | 
			
		||||
node express.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Koa Setup
 | 
			
		||||
 | 
			
		||||
The following commands are required in order to test the [Koa](https://github.com/koajs/koa) demo:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install koa printj formidable https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
 | 
			
		||||
node koa.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Hapi Setup
 | 
			
		||||
 | 
			
		||||
**Note: Hapi demo as written only works with Hapi version 16 and below.**
 | 
			
		||||
 | 
			
		||||
The following commands are required in order to test the [Hapi](https://github.com/hapijs/hapi) demo:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install hapi@16.x printj tiny-worker https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
 | 
			
		||||
node hapi.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Node Buffer
 | 
			
		||||
 | 
			
		||||
The `read` and `write` functions can handle `Buffer` data with `type:"buffer"`.
 | 
			
		||||
For example, the `request` library returns data in a buffer:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var XLSX = require('xlsx'), request = require('request');
 | 
			
		||||
request(url, {encoding: null}, function(err, res, data) {
 | 
			
		||||
	if(err || res.statusCode !== 200) return;
 | 
			
		||||
 | 
			
		||||
	/* data is a node Buffer that can be passed to XLSX.read */
 | 
			
		||||
	var workbook = XLSX.read(data, {type:'buffer'});
 | 
			
		||||
 | 
			
		||||
	/* DO SOMETHING WITH workbook HERE */
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `readFile` / `writeFile` functions wrap `fs.{read,write}FileSync`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* equivalent to `var wb = XLSX.readFile("sheetjs.xlsx");` */
 | 
			
		||||
var buf = fs.readFileSync("sheetjs.xlsx");
 | 
			
		||||
var wb = XLSX.read(buf, {type:'buffer'});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Responding to Form Uploads
 | 
			
		||||
 | 
			
		||||
Using `formidable`, files uploaded to forms are stored to temporary files that
 | 
			
		||||
can be read with `readFile`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* within the server callback function(request, response) { */
 | 
			
		||||
var form = new formidable.IncomingForm();
 | 
			
		||||
form.parse(req, function(err, fields, files) {
 | 
			
		||||
	var f = files[Object.keys(files)[0]];
 | 
			
		||||
	var workbook = XLSX.readFile(f.path);
 | 
			
		||||
	/* DO SOMETHING WITH workbook HERE */
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `node.js` demo shows a plain HTTP server that accepts file uploads and
 | 
			
		||||
converts data to requested output format.
 | 
			
		||||
 | 
			
		||||
### Example servers
 | 
			
		||||
 | 
			
		||||
Each example server is expected to hold an array-of-arrays in memory.  They are
 | 
			
		||||
expected to handle:
 | 
			
		||||
 | 
			
		||||
- `POST /         ` accepts an encoded `file` and updates the internal storage
 | 
			
		||||
- `GET  /?t=<type>` returns the internal storage in the specified type
 | 
			
		||||
- `POST /?f=<name>` reads the local file and updates the internal storage
 | 
			
		||||
- `GET  /?f=<name>` writes the file to the specified name
 | 
			
		||||
 | 
			
		||||
Testing with cURL is straightforward:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# upload sheetjs.csv and update data
 | 
			
		||||
curl -X POST -F "data=@sheetjs.csv" http://localhost:7262/
 | 
			
		||||
# download data in SYLK format
 | 
			
		||||
curl -X GET http://localhost:7262/?t=slk
 | 
			
		||||
# read sheetjs.csv from the server directory
 | 
			
		||||
curl -X POST http://localhost:7262/?f=sheetjs.csv
 | 
			
		||||
# write sheetjs.xlsb in the XLSB format
 | 
			
		||||
curl -X GET http://localhost:7262/?f=sheetjs.xlsb
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Main-process logic with express
 | 
			
		||||
 | 
			
		||||
The most straightforward approach is to handle the data directly in HTTP event
 | 
			
		||||
handlers.  The `buffer` type for `XLSX.read` and `XLSX.write` work with `http`
 | 
			
		||||
module and with express directly.  The following snippet generates a workbook
 | 
			
		||||
based on an array of arrays and sends it to the client:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function send_aoa_to_client(req, res, data, bookType) {
 | 
			
		||||
	/* generate workbook */
 | 
			
		||||
	var ws = XLSX.utils.aoa_to_sheet(data);
 | 
			
		||||
	var wb = XLSX.utils.book_new();
 | 
			
		||||
	XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
 | 
			
		||||
 | 
			
		||||
	/* generate buffer */
 | 
			
		||||
	var buf = XLSX.write(wb, {type:'buffer', bookType:bookType || "xlsx"});
 | 
			
		||||
 | 
			
		||||
	/* send to client */
 | 
			
		||||
	res.status(200).send(buf);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## fork with koa
 | 
			
		||||
 | 
			
		||||
`child_process.fork` provides a light-weight and customizable way to offload
 | 
			
		||||
work from the main server process.  This demo passes commands to a custom child
 | 
			
		||||
process and the child passes back buffers of data.
 | 
			
		||||
 | 
			
		||||
The main server script is `koa.js` and the worker script is `koasub.js`.  State
 | 
			
		||||
is maintained in the worker script.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## tiny-worker with hapi
 | 
			
		||||
 | 
			
		||||
`tiny-worker` provides a Web Worker-like interface.  Binary strings and simple
 | 
			
		||||
objects are readily passed across the Worker divide.
 | 
			
		||||
 | 
			
		||||
The main server script is `hapi.js` and the worker script is `worker.js`.  State
 | 
			
		||||
is maintained in the server script.
 | 
			
		||||
 | 
			
		||||
Note: due to an issue with hapi payload parsing, the route `POST /file` is used
 | 
			
		||||
to handle the case of reading from file, so the cURL test is:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# upload sheetjs.csv and update data
 | 
			
		||||
curl -X POST -F "data=@sheetjs.csv" http://localhost:7262/
 | 
			
		||||
# download data in SYLK format
 | 
			
		||||
curl -X GET http://localhost:7262/?t=slk
 | 
			
		||||
# read sheetjs.csv from the server directory
 | 
			
		||||
curl -X POST http://localhost:7262/file?f=sheetjs.csv
 | 
			
		||||
# write sheetjs.xlsb in the XLSB format
 | 
			
		||||
curl -X GET http://localhost:7262/?f=sheetjs.xlsb
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## NestJS
 | 
			
		||||
 | 
			
		||||
[NestJS](https://nestjs.com/) is a Node.js framework for server-side web applications.
 | 
			
		||||
 | 
			
		||||
This demo uses SheetJS to parse a spreadsheet via a POST API endpoint. The file
 | 
			
		||||
arrives to the endpoint as body `form-data`, accessible using the `file` key.
 | 
			
		||||
After parsing the file, CSV contents of the first worksheet will be returned.
 | 
			
		||||
[Body parsing uses `multer`](https://docs.nestjs.com/techniques/file-upload).
 | 
			
		||||
 | 
			
		||||
Before running the demo, the NestJS CLI tool must be installed.  The instruction
 | 
			
		||||
is described in the NestJS ["First Steps"](https://docs.nestjs.com/first-steps):
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm i -g @nestjs/cli
 | 
			
		||||
make nest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The demo can be tested using the `/sheetjs/upload-xlsx-file` endpoint:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -X POST -F "file=@test.xlsx" http://localhost:3000/sheetjs/upload-xlsx-file
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The included [`nest.sh`](./nest.sh) script creates and configures the project.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
This demo creates a module and a controller.  The controller handles the actual
 | 
			
		||||
requests (creating the endpoint) while the module is used to configure `multer`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Deno
 | 
			
		||||
 | 
			
		||||
[`Drash`](https://drash.land/drash/) is a Deno framework for Deno's HTTP server.
 | 
			
		||||
 | 
			
		||||
The `drash.ts` demo responds to POST requests and responds with HTML previews.
 | 
			
		||||
 | 
			
		||||
<https://s2c.deno.dev> is a live deployment of the service.
 | 
			
		||||
Cloud services are covered in separate demos:
 | 
			
		||||
 | 
			
		||||
- [AWS](https://docs.sheetjs.com/docs/demos/aws)
 | 
			
		||||
- [Azure](https://docs.sheetjs.com/docs/demos/azure)
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
var cors = function(req, res) { res.header('Access-Control-Allow-Origin', '*'); };
 | 
			
		||||
cors.mw = function(req, res, next) { cors(req, res); next(); };
 | 
			
		||||
module.exports = cors;
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
var sprintf = require('printj').sprintf;
 | 
			
		||||
var logit = function(req, res) {
 | 
			
		||||
	console.log(sprintf("%s %s %d", req.method, req.url, res.statusCode));
 | 
			
		||||
};
 | 
			
		||||
logit.mw = function(req, res, next) { logit(req, res); next(); }
 | 
			
		||||
module.exports = logit;
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user