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