diff --git a/Makefile b/Makefile index f643214..eb8262f 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ ctestserv: ## Start a test server on port 8000 ## Demos -DEMOS=angular browserify requirejs rollup systemjs webpack +DEMOS=angular angular-new browserify requirejs rollup systemjs webpack DEMOTGTS=$(patsubst %,demo-%,$(DEMOS)) .PHONY: demos demos: $(DEMOTGTS) @@ -125,6 +125,11 @@ demo-angular: ## Run angular demo build #make -C demos/angular @echo "start a local server and go to demos/angular/angular.html" +.PHONY: demo-angular-new +demo-angular-new: ## Run angular 2 demo build + make -C demos/angular2 + @echo "go to demos/angular/angular.html and run 'ng serve'" + .PHONY: demo-browserify demo-browserify: ## Run browserify demo build make -C demos/browserify diff --git a/README.md b/README.md index db9722e..535e7c9 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,8 @@ CDNjs automatically pulls the latest version and makes all versions available at The `demos` directory includes sample projects for: -- [`angular`](demos/angular/) +- [`angular 1.x`](demos/angular/) +- [`angular 2.x / 4.x`](demos/angular2/) - [`browserify`](demos/browserify/) - [`Adobe ExtendScript`](demos/extendscript/) - [`meteor`](demos/meteor/) diff --git a/demos/angular2/.angular-cli.json b/demos/angular2/.angular-cli.json new file mode 100644 index 0000000..35d76d7 --- /dev/null +++ b/demos/angular2/.angular-cli.json @@ -0,0 +1,23 @@ +{ + "$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": {} + } +} diff --git a/demos/angular2/Makefile b/demos/angular2/Makefile new file mode 100644 index 0000000..3d6b056 --- /dev/null +++ b/demos/angular2/Makefile @@ -0,0 +1,12 @@ +.PHONY: angular +angular: + # Test Angular2 build + cp package.json-angular2 package.json + npm install + ng build + + # Test Angular4 build + cp package.json-angular2 package.json + npm install + ng build + diff --git a/demos/angular2/README.md b/demos/angular2/README.md new file mode 100644 index 0000000..d5db372 --- /dev/null +++ b/demos/angular2/README.md @@ -0,0 +1,68 @@ +# Angular 2+ + +The library can be imported directly from TS code with: + +```typescript +import * as XLSX from 'xlsx'; +``` + +This demo uses an array of arrays as the core data structure. The component +template includes a file input element, a table that updates based on the data, +and a button to export the data. + +## 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 a `package.json` for Angular 2 +and another `package.json` for Angular 4. + +Switching to Angular 2 is as simple as: + +```bash +$ cp package.json-angular2 package.json +$ npm install +$ ng serve +``` + +Switching to Angular 4 is as simple as: + +```bash +$ cp package.json-angular4 package.json +$ npm install +$ ng serve +``` + +## XLSX Symlink + +In this tree, `node_modules/xlsx` is a symlink 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 xlsx + +``` + +## SystemJS Configuration + +The default angular-cli configuration requires no additional configuration. + +Some deployments use the SystemJS loader, which does require configuration. The +SystemJS example shows the required meta and map settings: + +```js +SystemJS.config({ + meta: { + 'xlsx': { + exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable + } + }, + map: { + 'xlsx': 'xlsx.full.min.js', // <-- make sure xlsx.full.min.js is in same dir + 'fs': '', // <--| + 'crypto': '', // <--| suppress native node modules + 'stream': '' // <--| + } +}); +``` diff --git a/demos/angular2/node_modules/xlsx b/demos/angular2/node_modules/xlsx new file mode 120000 index 0000000..1b20c9f --- /dev/null +++ b/demos/angular2/node_modules/xlsx @@ -0,0 +1 @@ +../../../ \ No newline at end of file diff --git a/demos/angular2/package.json b/demos/angular2/package.json new file mode 100644 index 0000000..b2867a6 --- /dev/null +++ b/demos/angular2/package.json @@ -0,0 +1,39 @@ +{ + "name": "angular2", + "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", + "file-saver": "^1.3.3" + }, + "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" + } +} diff --git a/demos/angular2/package.json-angular2 b/demos/angular2/package.json-angular2 new file mode 100644 index 0000000..eabba54 --- /dev/null +++ b/demos/angular2/package.json-angular2 @@ -0,0 +1,39 @@ +{ + "name": "angular2", + "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": "~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", + "file-saver": "^1.3.3" + }, + "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" + } +} diff --git a/demos/angular2/package.json-angular4 b/demos/angular2/package.json-angular4 new file mode 100644 index 0000000..b2867a6 --- /dev/null +++ b/demos/angular2/package.json-angular4 @@ -0,0 +1,39 @@ +{ + "name": "angular2", + "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", + "file-saver": "^1.3.3" + }, + "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" + } +} diff --git a/demos/angular2/src/app/app.module.ts b/demos/angular2/src/app/app.module.ts new file mode 100644 index 0000000..d7bb39a --- /dev/null +++ b/demos/angular2/src/app/app.module.ts @@ -0,0 +1,28 @@ +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: `` +}) +export class AppComponent { + title = 'test'; +} + +@NgModule({ + declarations: [ + SheetJSComponent, + AppComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/demos/angular2/src/app/sheetjs.component.ts b/demos/angular2/src/app/sheetjs.component.ts new file mode 100644 index 0000000..4af9b64 --- /dev/null +++ b/demos/angular2/src/app/sheetjs.component.ts @@ -0,0 +1,74 @@ +/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +import { Component } from '@angular/core'; + +import * as XLSX from 'xlsx'; + +import { saveAs } from 'file-saver'; + +type AOA = Array >; + +function s2ab(s:string):ArrayBuffer { + const buf = new ArrayBuffer(s.length); + const view = new Uint8Array(buf); + for (let i = 0; i !== s.length; ++i) { + view[i] = s.charCodeAt(i) & 0xFF; + }; + return buf; +} + +@Component({ + selector: 'sheetjs', + template: ` + + + + + +
+ {{val}} +
+ + ` +}) + +export class SheetJSComponent { + data:AOA = [[1,2],[3,4]]; + wopts:XLSX.WritingOptions = { bookType:'xlsx', type:'binary' }; + fileName:string = "SheetJS.xlsx"; + + public onFileChange(evt:any) { + const scope = this; + /* wire up file reader */ + const target:DataTransfer = ((evt.target)); + if(target.files.length != 1) throw new Error("Cannot upload multiple files on the entry"); + const reader = new FileReader(); + reader.onload = function (e:any) { + /* read workbook */ + const bstr = e.target.result; + const wb = XLSX.read(bstr, {type:'binary'}); + + /* grab first sheet */ + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + + /* save data to scope */ + scope.data = ((XLSX.utils.sheet_to_json(ws, {header:1}))); + }; + reader.readAsBinaryString(target.files[0]); + } + + export():void { + /* generate worksheet */ + const ws = XLSX.utils.aoa_to_sheet(this.data); + + /* generate workbook and add the worksheet */ + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); + + /* save to file */ + const wbout = XLSX.write(wb, this.wopts); + console.log(this.fileName); + saveAs(new Blob([s2ab(wbout)]), this.fileName); + } +} diff --git a/demos/angular2/src/index.html b/demos/angular2/src/index.html new file mode 100644 index 0000000..bc806fb --- /dev/null +++ b/demos/angular2/src/index.html @@ -0,0 +1,30 @@ + + + + + + SheetJS + Angular 2+ + + + + + +
+SheetJS + Angular 2+ demo
+
+The core library can be used as-is in angular applications.
+The Community Edition README details some common use cases.
+We also have some more public demos
+
+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.
+
+Sample Spreadsheet
+
+ + + + diff --git a/demos/angular2/src/main.ts b/demos/angular2/src/main.ts new file mode 100644 index 0000000..d3da1bb --- /dev/null +++ b/demos/angular2/src/main.ts @@ -0,0 +1,3 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/demos/angular2/src/polyfills.ts b/demos/angular2/src/polyfills.ts new file mode 100644 index 0000000..67478c2 --- /dev/null +++ b/demos/angular2/src/polyfills.ts @@ -0,0 +1,3 @@ +import 'core-js/es6/reflect'; +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; \ No newline at end of file diff --git a/demos/angular2/src/tsconfig.app.json b/demos/angular2/src/tsconfig.app.json new file mode 100644 index 0000000..321e0d7 --- /dev/null +++ b/demos/angular2/src/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "module": "es2015", + "baseUrl": "", + "types": [] + } +} diff --git a/demos/angular2/tsconfig.json b/demos/angular2/tsconfig.json new file mode 100644 index 0000000..a35a8ee --- /dev/null +++ b/demos/angular2/tsconfig.json @@ -0,0 +1,20 @@ +{ + "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" + ] + } +}