diff --git a/README.md b/README.md index 7d71796fa..0875db922 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,21 @@ For example, the following would use `index.ts` as the secondary entry point: } ``` +##### How do I use es2016 or es2017 features in my TypeScript library? + +You can change the TypeScript language level support in tsconfig by also using the `ngPackage` configuration field in your secondary `package.json` and setting the `languageLevel` property in `lib`: +For example,: + +```json +{ + "ngPackage": { + "lib": { + "languageLevel": [ "dom", "es2017" ] + } + } +} +``` + #### How to embed assets in CSS? You can embed assets such as font and images inside the outputted css. More information [in the CSS tricks website](https://css-tricks.com/data-uris) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index b3ed5e407..93dc086a7 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -153,6 +153,8 @@ If auto-generating a tsconfig, `ng-packagr` would need to read its default value The most important setting here is the `"files": []` property, which must contain exactly one file since `"flatModuleId"` and `"flatModuleOutFile"` options will also be used for flattended library indexes. The value for `"flatModuleId"` could be inferred by the library's name as given in `package.json`, `"flatModuleOutFile"` could be statically set to `"index"`. +The `"lib"` property that denotes TypeScript language level support can be overriden through a `lib.languageLevel` property in `ng-package.json`. + Other configuration properties like `"target"` or `"module"` cannot be set by users since the order of transformations relies on certain settings. For example, `ngc` will need to compile to `"target": "es2015"` and `"module": "es2015"` in order to allow subsequent steps to happen. diff --git a/integration/samples/embed-assets/package.json b/integration/samples/embed-assets/package.json index f8d9accfa..9b7286e7b 100644 --- a/integration/samples/embed-assets/package.json +++ b/integration/samples/embed-assets/package.json @@ -1,6 +1,6 @@ { "name": "@sample/embed-assets", - "description": "A sample library with embeded css assets", + "description": "A sample library with embedded css assets", "version": "1.0.0-pre.0", "private": true, "repository": "https://github.com/dherges/ng-packagr.git", diff --git a/integration/samples/language-level/ng-package.json b/integration/samples/language-level/ng-package.json new file mode 100644 index 000000000..39af6d992 --- /dev/null +++ b/integration/samples/language-level/ng-package.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../src/ng-package.schema.json", + "lib": { + "entryFile": "public_api.ts", + "languageLevel": [ + "dom", + "es2017" + ] + } +} diff --git a/integration/samples/language-level/package.json b/integration/samples/language-level/package.json new file mode 100644 index 000000000..5407c130f --- /dev/null +++ b/integration/samples/language-level/package.json @@ -0,0 +1,16 @@ +{ + "name": "@sample/language-level", + "description": "A sample library to test es2016/es2017 syntax in TypeScript", + "version": "1.0.0-pre.0", + "private": true, + "repository": "https://github.com/dherges/ng-packagr.git", + "peerDependencies": { + "@angular/common": "^4.1.3", + "@angular/core": "^4.1.3", + "rxjs": "^5.0.1", + "zone.js": "^0.8.4" + }, + "scripts": { + "test": "../../../node_modules/.bin/cross-env TS_NODE_PROJECT=../../../integration/tsconfig.specs.json ../../../node_modules/.bin/mocha --compilers ts:ts-node/register specs/**/*.ts" + } +} diff --git a/integration/samples/language-level/public_api.ts b/integration/samples/language-level/public_api.ts new file mode 100644 index 000000000..05b8f5fa8 --- /dev/null +++ b/integration/samples/language-level/public_api.ts @@ -0,0 +1,2 @@ +export * from './src/angular.component'; +export * from './src/angular.module'; diff --git a/integration/samples/language-level/src/angular.component.ts b/integration/samples/language-level/src/angular.component.ts new file mode 100644 index 000000000..f227759e9 --- /dev/null +++ b/integration/samples/language-level/src/angular.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + + +@Component({ + selector: 'ng-component', + template: '

Angular!

' +}) +export class AngularComponent { + + es2016Includes() { + const arr = ['foo', 'bar']; + arr.includes('foo'); + } + + es2017String() { + const str = 'abc'; + str.padStart(10); // " abc" + str.padEnd(10); // "abc " + } +} diff --git a/integration/samples/language-level/src/angular.module.ts b/integration/samples/language-level/src/angular.module.ts new file mode 100644 index 000000000..5a0ba1fbf --- /dev/null +++ b/integration/samples/language-level/src/angular.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { AngularComponent } from './angular.component'; +@NgModule({ + imports: [ + CommonModule + ], + declarations: [ + AngularComponent + ], + providers: [ + + ] +}) +export class AngularModule {} diff --git a/src/lib/ng-package-format/entry-point.ts b/src/lib/ng-package-format/entry-point.ts index 5d80137f9..1c3ffc4a2 100644 --- a/src/lib/ng-package-format/entry-point.ts +++ b/src/lib/ng-package-format/entry-point.ts @@ -84,6 +84,10 @@ export class NgEntryPoint { return this.$get('lib.flatModuleFile') || this.flattenModuleId('-'); } + public get languageLevel(): string[] { + return this.$get('lib.languageLevel'); + } + /** * The module ID is an "identifier of a module used in the import statements, e.g. * '@angular/core'. The ID often maps directly to a path on the filesystem, but this diff --git a/src/lib/steps/ngc.ts b/src/lib/steps/ngc.ts index bd5f32216..c2c024a9a 100644 --- a/src/lib/steps/ngc.ts +++ b/src/lib/steps/ngc.ts @@ -26,7 +26,7 @@ export const prepareTsConfig: BuildStep = // Read the default configuration and overwrite package-specific options const tsConfig = ng.readConfiguration(path.resolve(__dirname, '..', 'conf', 'tsconfig.ngc.json')); tsConfig.rootNames = [ entryPoint.entryFilePath ]; - tsConfig.options.flatModuleId = entryPoint.moduleId + tsConfig.options.flatModuleId = entryPoint.moduleId; tsConfig.options.flatModuleOutFile = `${entryPoint.flatModuleFile}.js`; tsConfig.options.basePath = basePath; tsConfig.options.baseUrl = basePath; @@ -34,6 +34,11 @@ export const prepareTsConfig: BuildStep = tsConfig.options.outDir = artefacts.outDir; tsConfig.options.genDir = artefacts.outDir; + if (entryPoint.languageLevel) { + // ng.readConfiguration implicitly converts "es6" to "lib.es6.d.ts", etc. + tsConfig.options.lib = entryPoint.languageLevel.map(lib => `lib.${lib}.d.ts`); + } + switch (entryPoint.jsxConfig) { case 'preserve': tsConfig.options.jsx = ts.JsxEmit.Preserve; diff --git a/src/ng-package.schema.json b/src/ng-package.schema.json index 6b98626ce..15f49de2d 100644 --- a/src/ng-package.schema.json +++ b/src/ng-package.schema.json @@ -63,6 +63,17 @@ "inline" ], "default": "none" + }, + "languageLevel": { + "description": "Set typescript language level, i.e. tsconfig.lib. This will enable accessing typescript features available in es2016, es2017, etc.", + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "dom", + "es2015" + ] } } }