├── .gitattributes
├── .gitignore
├── .travis.yml
├── generators
└── app
│ ├── templates
│ ├── _jest.ts
│ ├── travis.yml
│ ├── src
│ │ ├── sample.service.ts
│ │ ├── sample.directive.ts
│ │ ├── sample.component.ts
│ │ ├── sample.pipe.ts
│ │ ├── _tsconfig.spec.json
│ │ ├── _tsconfig.es5.json
│ │ ├── _package.json
│ │ ├── index.ts
│ │ └── sample.component.spec.ts
│ ├── bs-config.json
│ ├── _tsconfig.json
│ ├── playground
│ │ ├── tsconfig.json
│ │ ├── _index.ts
│ │ ├── _index.html
│ │ ├── systemjs-angular-loader.js
│ │ └── _systemjs.config.js
│ ├── gitignore
│ ├── npmignore
│ ├── _jest-global-mocks.ts
│ ├── README.MD
│ ├── _package_jest.json
│ ├── _package.json
│ ├── _tslint.json
│ ├── tools
│ │ └── gulp
│ │ │ └── inline-resources.js
│ └── gulpfile.js
│ ├── playground.js
│ └── index.js
├── .editorconfig
├── package.json
├── LICENSE
├── gulpfile.js
├── test
└── app.js
├── .eslintrc
├── guides
└── import_non_angular_libraries.md
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | .idea
4 | .vscode/*
5 | *.log
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - v10
4 | - v8
5 | - v6
6 |
--------------------------------------------------------------------------------
/generators/app/templates/_jest.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular';
2 | import './jest-global-mocks';
3 |
--------------------------------------------------------------------------------
/generators/app/templates/travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | sudo: false
3 | node_js:
4 | - '4.2.1'
5 |
--------------------------------------------------------------------------------
/generators/app/templates/src/sample.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable()
4 | export class SampleService {
5 |
6 | constructor() {
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [*.md]
11 | trim_trailing_whitespace = false
12 |
--------------------------------------------------------------------------------
/generators/app/templates/bs-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "server": {
3 | "baseDir": "src",
4 | "routes": {
5 | "/": "playground",
6 | "/node_modules/": "node_modules",
7 | "/dist/": "dist",
8 | "/.playground": ".playground"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/generators/app/templates/src/sample.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[sampleDirective]'
5 | })
6 | export class SampleDirective {
7 |
8 | constructor(private el: ElementRef) {
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/generators/app/templates/src/sample.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'sample-component',
5 | template: `
Sample component
`
6 | })
7 | export class SampleComponent {
8 |
9 | constructor() {
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/generators/app/templates/_tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./src",
4 | "experimentalDecorators": true,
5 | "moduleResolution": "node",
6 | "rootDir": "./src",
7 | "lib": [
8 | "es2015",
9 | "dom"
10 | ],
11 | "skipLibCheck": true,
12 | "types": []
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/generators/app/templates/src/sample.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, PipeTransform, Pipe } from '@angular/core';
2 |
3 | /**
4 | * Transforms any input value
5 | */
6 | @Pipe({
7 | name: 'samplePipe'
8 | })
9 | @Injectable()
10 | export class SamplePipe implements PipeTransform {
11 | transform(value: any, args: any[] = null): string {
12 | return value;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/generators/app/templates/playground/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "../.playground",
4 | "target": "es5",
5 | "module": "commonjs",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "lib": [ "es2015", "dom" ],
11 | "noImplicitAny": true,
12 | "suppressImplicitAnyIndexErrors": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/generators/app/templates/src/_tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.es5.json",
3 | "compilerOptions": {
4 | "emitDecoratorMetadata": true,
5 | "experimentalDecorators": true,
6 | "outDir": "../out-tsc/spec",
7 | "module": "commonjs",
8 | "target": "es6",
9 | "baseUrl": "",
10 | "types": [
11 | "jest",
12 | "node"
13 | ]
14 | },
15 | "files": [
16 | "**/*.spec.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/generators/app/templates/gitignore:
--------------------------------------------------------------------------------
1 | # Node
2 | node_modules/*
3 | npm-debug.log
4 |
5 | # TypeScript
6 | src/*.js
7 | src/*.map
8 | src/*.d.ts
9 |
10 | # JetBrains
11 | .idea
12 | .project
13 | .settings
14 | .idea/*
15 | *.iml
16 |
17 | # VS Code
18 | .vscode/*
19 |
20 | # Windows
21 | Thumbs.db
22 | Desktop.ini
23 |
24 | # Mac
25 | .DS_Store
26 | **/.DS_Store
27 |
28 | # Ngc generated files
29 | **/*.ngfactory.ts
30 |
31 | # Build files
32 | dist/*
33 |
34 | # Playground tmp files
35 | .playground
36 |
--------------------------------------------------------------------------------
/generators/app/templates/npmignore:
--------------------------------------------------------------------------------
1 | # Node
2 | node_modules/*
3 | npm-debug.log
4 | docs/*
5 | # DO NOT IGNORE TYPESCRIPT FILES FOR NPM
6 | # TypeScript
7 | # *.js
8 | # *.map
9 | # *.d.ts
10 |
11 | # JetBrains
12 | .idea
13 | .project
14 | .settings
15 | .idea/*
16 | *.iml
17 |
18 | # VS Code
19 | .vscode/*
20 |
21 | # Windows
22 | Thumbs.db
23 | Desktop.ini
24 |
25 | # Mac
26 | .DS_Store
27 | **/.DS_Store
28 |
29 | # Ngc generated files
30 | **/*.ngfactory.ts
31 |
32 | # Library files
33 | src/*
34 | build/*
35 |
--------------------------------------------------------------------------------
/generators/app/templates/_jest-global-mocks.ts:
--------------------------------------------------------------------------------
1 | const mock = () => {
2 | let storage = {};
3 | return {
4 | getItem: key => key in storage ? storage[key] : null,
5 | setItem: (key, value) => storage[key] = value || '',
6 | removeItem: key => delete storage[key],
7 | clear: () => storage = {},
8 | };
9 | };
10 |
11 | Object.defineProperty(window, 'localStorage', {value: mock()});
12 | Object.defineProperty(window, 'sessionStorage', {value: mock()});
13 | Object.defineProperty(window, 'getComputedStyle', {
14 | value: () => ['-webkit-appearance']
15 | });
16 |
--------------------------------------------------------------------------------
/generators/app/templates/playground/_index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This is only for local test
3 | */
4 | import { BrowserModule } from '@angular/platform-browser';
5 | import { NgModule } from '@angular/core';
6 | import { Component } from '@angular/core';
7 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
8 |
9 | import { SampleModule } from '<%= props.scope %><%= props.libraryName.kebabCase %>';
10 |
11 | @Component({
12 | selector: 'app',
13 | template: ``
14 | })
15 | class AppComponent {}
16 |
17 | @NgModule({
18 | bootstrap: [ AppComponent ],
19 | declarations: [ AppComponent ],
20 | imports: [ BrowserModule, SampleModule ]
21 | })
22 | class AppModule {}
23 |
24 | platformBrowserDynamic().bootstrapModule(AppModule);
25 |
--------------------------------------------------------------------------------
/generators/app/templates/playground/_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= props.scope %><%= props.libraryName.original %> Playground
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 | Loading AppComponent content here ...
22 |
23 |
24 |
--------------------------------------------------------------------------------
/generators/app/templates/src/_tsconfig.es5.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "module": "es2015",
5 | "target": "es5",
6 | "baseUrl": ".",
7 | "stripInternal": true,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "moduleResolution": "node",
11 | "outDir": "../build",
12 | "rootDir": ".",
13 | "lib": [
14 | "es2015",
15 | "dom"
16 | ],
17 | "skipLibCheck": true,
18 | "types": []
19 | },
20 | "angularCompilerOptions": {
21 | "annotateForClosureCompiler": true,
22 | "strictMetadataEmit": true,
23 | "skipTemplateCodegen": true,
24 | "flatModuleOutFile": "<%= props.libraryName.kebabCase %>.js",
25 | "flatModuleId": "<%= props.scope %><%= props.libraryName.kebabCase %>"
26 | },
27 | "files": [
28 | "./index.ts"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/generators/app/templates/src/_package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= props.scope%><%= props.libraryName.kebabCase %>",
3 | "version": "0.1.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "<%= props.gitRepositoryUrl %>"
7 | },
8 | "author": {
9 | "name": "<%= props.author.name %>",
10 | "email": "<%= props.author.email %>"
11 | },
12 | "keywords": [
13 | "angular"
14 | ],
15 | "license": "MIT",
16 | "bugs": {
17 | "url": "<%= props.gitRepositoryUrl %>/issues"
18 | },
19 | "main": "<%= props.libraryName.kebabCase %>.umd.js",
20 | "module": "<%= props.libraryName.kebabCase %>.js",
21 | "jsnext:main": "<%= props.libraryName.kebabCase %>.js",
22 | "typings": "<%= props.libraryName.kebabCase %>.d.ts",
23 | "peerDependencies": {
24 | "@angular/core": "^4.0.0",
25 | "rxjs": "^5.1.0",
26 | "zone.js": "^0.8.4"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/generators/app/templates/src/index.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { SampleComponent } from './sample.component';
4 | import { SampleDirective } from './sample.directive';
5 | import { SamplePipe } from './sample.pipe';
6 | import { SampleService } from './sample.service';
7 |
8 | export * from './sample.component';
9 | export * from './sample.directive';
10 | export * from './sample.pipe';
11 | export * from './sample.service';
12 |
13 | @NgModule({
14 | imports: [
15 | CommonModule
16 | ],
17 | declarations: [
18 | SampleComponent,
19 | SampleDirective,
20 | SamplePipe
21 | ],
22 | exports: [
23 | SampleComponent,
24 | SampleDirective,
25 | SamplePipe
26 | ]
27 | })
28 | export class SampleModule {
29 | static forRoot(): ModuleWithProviders {
30 | return {
31 | ngModule: SampleModule,
32 | providers: [SampleService]
33 | };
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/generators/app/templates/src/sample.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { By } from '@angular/platform-browser';
3 | import { DebugElement } from '@angular/core';
4 |
5 | import { SampleComponent } from './sample.component';
6 |
7 | describe('SampleComponent', () => {
8 |
9 | let comp: SampleComponent;
10 | let fixture: ComponentFixture;
11 | let de: DebugElement;
12 | let el: HTMLElement;
13 |
14 | beforeEach(() => {
15 | TestBed.configureTestingModule({
16 | declarations: [ SampleComponent ], // declare the test component
17 | });
18 |
19 | fixture = TestBed.createComponent(SampleComponent);
20 |
21 | comp = fixture.componentInstance; // BannerComponent test instance
22 |
23 | // query for the title by CSS element selector
24 | de = fixture.debugElement.query(By.css('h1'));
25 | el = de.nativeElement;
26 | });
27 |
28 | it('Should be false', () => {
29 | expect(false).toBe(true);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generator-angular2-library",
3 | "version": "12.5.0",
4 | "description": "Generator to create an Angular 2 library",
5 | "homepage": "https://github.com/jvandemo/generator-angular2-library",
6 | "author": {
7 | "name": "Jurgen Van de Moere",
8 | "email": "jurgen.van.de.moere@gmail.com",
9 | "url": "http://www.jvandemo.com"
10 | },
11 | "files": [
12 | "generators"
13 | ],
14 | "main": "generators/index.js",
15 | "keywords": [
16 | "yeoman-generator"
17 | ],
18 | "license": "MIT",
19 | "dependencies": {
20 | "chalk": "^1.1.3",
21 | "underscore.string": "^3.3.4",
22 | "yeoman-generator": "^2.0.5",
23 | "yosay": "^2.0.0"
24 | },
25 | "devDependencies": {
26 | "yeoman-assert": "^3.1.1",
27 | "gulp": "^3.9.1",
28 | "gulp-eslint": "^2.0.0",
29 | "gulp-exclude-gitignore": "^1.0.0",
30 | "gulp-istanbul": "^0.10.4",
31 | "gulp-mocha": "^2.2.0",
32 | "gulp-plumber": "^1.1.0",
33 | "gulp-nsp": "^3.0.1",
34 | "gulp-coveralls": "^0.1.4"
35 | },
36 | "repository": "jvandemo/generator-angular2-library",
37 | "scripts": {
38 | "prepublish": "gulp prepublish",
39 | "test": "gulp"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Jurgen Van de Moere (http://www.jvandemo.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/generators/app/playground.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const setupPlayground =
4 | (generator) => {
5 | // Copy playground
6 | generator.fs.copyTpl(
7 | generator.templatePath('playground/_systemjs.config.js'),
8 | generator.destinationPath('playground/systemjs.config.js'),
9 | {
10 | props: generator.props
11 | }
12 | );
13 |
14 | generator.fs.copy(
15 | generator.templatePath('playground/systemjs-angular-loader.js'),
16 | generator.destinationPath('playground/systemjs-angular-loader.js')
17 | );
18 |
19 | generator.fs.copyTpl(
20 | generator.templatePath('playground/_index.ts'),
21 | generator.destinationPath('playground/index.ts'),
22 | {
23 | props: generator.props
24 | }
25 | );
26 |
27 | generator.fs.copyTpl(
28 | generator.templatePath('playground/_index.html'),
29 | generator.destinationPath('playground/index.html'),
30 | {
31 | props: generator.props
32 | }
33 | );
34 |
35 | generator.fs.copy(
36 | generator.templatePath('playground/tsconfig.json'),
37 | generator.destinationPath('playground/tsconfig.json')
38 | );
39 |
40 | generator.fs.copy(
41 | generator.templatePath('bs-config.json'),
42 | generator.destinationPath('bs-config.json')
43 | );
44 | };
45 |
46 | module.exports = setupPlayground;
47 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require('path');
3 | var gulp = require('gulp');
4 | var eslint = require('gulp-eslint');
5 | var excludeGitignore = require('gulp-exclude-gitignore');
6 | var mocha = require('gulp-mocha');
7 | var istanbul = require('gulp-istanbul');
8 | var nsp = require('gulp-nsp');
9 | var plumber = require('gulp-plumber');
10 | var coveralls = require('gulp-coveralls');
11 |
12 | gulp.task('static', function () {
13 | return gulp.src('**/*.js')
14 | .pipe(excludeGitignore())
15 | .pipe(eslint())
16 | .pipe(eslint.format())
17 | .pipe(eslint.failAfterError());
18 | });
19 |
20 | gulp.task('nsp', function (cb) {
21 | nsp({package: path.resolve('package.json')}, cb);
22 | });
23 |
24 | gulp.task('pre-test', function () {
25 | return gulp.src('generators/**/*.js')
26 | .pipe(istanbul({
27 | includeUntested: true
28 | }))
29 | .pipe(istanbul.hookRequire());
30 | });
31 |
32 | gulp.task('test', ['pre-test'], function (cb) {
33 | var mochaErr;
34 |
35 | gulp.src('test/**/*.js')
36 | .pipe(plumber())
37 | .pipe(mocha({reporter: 'spec', timeout: 60000}))
38 | .on('error', function (err) {
39 | mochaErr = err;
40 | })
41 | .pipe(istanbul.writeReports())
42 | .on('end', function () {
43 | cb(mochaErr);
44 | });
45 | });
46 |
47 | gulp.task('coveralls', ['test'], function () {
48 | if (!process.env.CI) {
49 | return;
50 | }
51 |
52 | return gulp.src(path.join(__dirname, 'coverage/lcov.info'))
53 | .pipe(coveralls());
54 | });
55 |
56 | gulp.task('prepublish', ['nsp']);
57 | gulp.task('default', ['static', 'test']);
58 |
--------------------------------------------------------------------------------
/generators/app/templates/playground/systemjs-angular-loader.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm;
4 | var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g;
5 | var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g;
6 |
7 | module.exports.translate = function (load){
8 | if (load.source.indexOf('moduleId') !== -1) {
9 | return load;
10 | }
11 |
12 | // eslint-disable-next-line
13 | var url = document.createElement('a');
14 | url.href = load.address;
15 |
16 | var basePathParts = url.pathname.split('/');
17 |
18 | basePathParts.pop();
19 | var basePath = basePathParts.join('/');
20 |
21 | // eslint-disable-next-line
22 | var baseHref = document.createElement('a');
23 | baseHref.href = this.baseURL;
24 | baseHref = baseHref.pathname;
25 |
26 | if (!baseHref.startsWith('/base/')) { // it is not karma
27 | basePath = basePath.replace(baseHref, '');
28 | }
29 |
30 | load.source = load.source
31 | .replace(templateUrlRegex, function (match, quote, sourceUrl){
32 | var resolvedUrl = sourceUrl;
33 |
34 | if (sourceUrl.startsWith('.')) {
35 | resolvedUrl = basePath + sourceUrl.substr(1);
36 | }
37 |
38 | return 'templateUrl: "' + resolvedUrl + '"';
39 | })
40 | .replace(stylesRegex, function (match, relativeUrls) {
41 | var urls = [];
42 |
43 | while ((match = stringRegex.exec(relativeUrls)) !== null) {
44 | if (match[2].startsWith('.')) {
45 | urls.push('"' + basePath + match[2].substr(1) + '"');
46 | } else {
47 | urls.push('"' + match[2] + '"');
48 | }
49 | }
50 |
51 | return 'styleUrls: [' + urls.join(', ') + ']';
52 | });
53 |
54 | return load;
55 | };
56 |
--------------------------------------------------------------------------------
/generators/app/templates/README.MD:
--------------------------------------------------------------------------------
1 | # <%= props.scope %><%= props.libraryName.kebabCase %>
2 |
3 | ## Installation
4 |
5 | To install this library, run:
6 |
7 | ```bash
8 | $ npm install <%= props.scope%><%= props.libraryName.kebabCase %> --save
9 | ```
10 |
11 | ## Consuming your library
12 |
13 | Once you have published your library to npm, you can import your library in any Angular application by running:
14 |
15 | ```bash
16 | $ npm install <%= props.scope %><%= props.libraryName.kebabCase %>
17 | ```
18 |
19 | and then from your Angular `AppModule`:
20 |
21 | ```typescript
22 | import { BrowserModule } from '@angular/platform-browser';
23 | import { NgModule } from '@angular/core';
24 |
25 | import { AppComponent } from './app.component';
26 |
27 | // Import your library
28 | import { SampleModule } from '<%= props.scope %><%= props.libraryName.kebabCase %>';
29 |
30 | @NgModule({
31 | declarations: [
32 | AppComponent
33 | ],
34 | imports: [
35 | BrowserModule,
36 |
37 | // Specify your library as an import
38 | LibraryModule
39 | ],
40 | providers: [],
41 | bootstrap: [AppComponent]
42 | })
43 | export class AppModule { }
44 | ```
45 |
46 | Once your library is imported, you can use its components, directives and pipes in your Angular application:
47 |
48 | ```xml
49 |
50 |
51 | {{title}}
52 |
53 |
54 | ```
55 |
56 | ## Development
57 |
58 | To generate all `*.js`, `*.d.ts` and `*.metadata.json` files:
59 |
60 | ```bash
61 | $ npm run build
62 | ```
63 |
64 | To lint all `*.ts` files:
65 |
66 | ```bash
67 | $ npm run lint
68 | ```
69 |
70 | ## License
71 |
72 | MIT © [<%= props.author.name %>](mailto:<%= props.author.email %>)
73 |
--------------------------------------------------------------------------------
/test/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require('path');
3 | var assert = require('yeoman-assert');
4 | var helpers = require('yeoman-test');
5 |
6 | describe('generator-angular-2-library:app', function () {
7 |
8 | before(function (done) {
9 |
10 | helpers.run(path.join(__dirname, '../generators/app'))
11 | .withOptions({})
12 | .withPrompts({libraryName: 'angular2-library-name'})
13 | .on('end', done);
14 |
15 | });
16 |
17 | it('should create package.json', function () {
18 | assert.file([
19 | 'package.json'
20 | ]);
21 | });
22 |
23 | it('should create tsconfig.json', function () {
24 | assert.file([
25 | 'tsconfig.json'
26 | ]);
27 | });
28 |
29 | it('should create .gitignore', function () {
30 | assert.file([
31 | '.gitignore'
32 | ]);
33 | });
34 |
35 | it('should create .npmignore', function () {
36 | assert.file([
37 | '.npmignore'
38 | ]);
39 | });
40 |
41 | it('should create README.MD', function () {
42 | assert.file([
43 | 'README.MD'
44 | ]);
45 | });
46 |
47 | it('should create main library file', function () {
48 | assert.file([
49 | 'index.ts'
50 | ]);
51 | });
52 |
53 | it('should create sample component', function () {
54 | assert.file([
55 | 'src/sample.component.ts'
56 | ]);
57 | });
58 |
59 | it('should create sample directive', function () {
60 | assert.file([
61 | 'src/sample.directive.ts'
62 | ]);
63 | });
64 |
65 | it('should create sample pipe', function () {
66 | assert.file([
67 | 'src/sample.pipe.ts'
68 | ]);
69 | });
70 |
71 | it('should create sample service', function () {
72 | assert.file([
73 | 'src/sample.service.ts'
74 | ]);
75 | });
76 |
77 | });
78 |
--------------------------------------------------------------------------------
/generators/app/templates/playground/_systemjs.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * System configuration for Angular samples
4 | * Adjust as necessary for your application needs.
5 | */
6 | (function () {
7 | System.config({
8 | paths: {
9 | // paths serve as alias
10 | 'npm:': '../node_modules/'
11 | },
12 | // map tells the System loader where to look for things
13 | map: {
14 | // our app is within the app folder
15 | app: 'app',
16 |
17 | // angular bundles
18 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
19 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
20 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
21 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
22 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
23 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
24 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
26 |
27 | // other libraries
28 | rxjs: 'npm:rxjs',
29 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
30 | '<%= props.scope %><%= props.libraryName.kebabCase %>': '../dist'
31 | },
32 | // packages tells the System loader how to load when no filename and/or no extension
33 | packages: {
34 | '.': {
35 | defaultExtension: 'js'
36 | },
37 | app: {
38 | defaultExtension: 'js',
39 | meta: {
40 | './*.js': {
41 | loader: 'systemjs-angular-loader.js'
42 | }
43 | }
44 | },
45 | rxjs: {
46 | defaultExtension: 'js'
47 | },
48 | '<%= props.scope %><%= props.libraryName.kebabCase %>': {
49 | main: '<%= props.libraryName.kebabCase %>.umd.js',
50 | defaultExtension: 'js'
51 | }
52 | }
53 | });
54 | })(this);
55 |
--------------------------------------------------------------------------------
/generators/app/templates/_package_jest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= props.scope %><%= props.libraryName.kebabCase %>",
3 | "version": "0.1.0",
4 | "scripts": {
5 | "build": "gulp build",
6 | "build:watch": "gulp",
7 | "docs": "npm run docs:build",
8 | "docs:build": "compodoc -p tsconfig.json -n <%= props.scope %><%= props.libraryName.original %> -d docs --hideGenerator",
9 | "docs:serve": "npm run docs:build -- -s",
10 | "docs:watch": "npm run docs:build -- -s -w",
11 | "lint": "tslint --type-check --project tsconfig.json src/**/*.ts",
12 | "lite": "lite-server",
13 | "playground:build": "tsc -p playground -w",
14 | "playground": "concurrently \"npm run build:watch\" \"npm run playground:build\" \"npm run lite\"",
15 | "test": "jest",
16 | "test:watch": "jest --watch",
17 | "test:ci": "jest --runInBand"
18 | },
19 | "jest": {
20 | "preset": "jest-preset-angular",
21 | "setupTestFrameworkScriptFile": "/src/jest.ts"
22 | },
23 | "repository": {
24 | "type": "git",
25 | "url": "<%= props.gitRepositoryUrl %>"
26 | },
27 | "author": {
28 | "name": "<%= props.author.name %>",
29 | "email": "<%= props.author.email %>"
30 | },
31 | "keywords": [
32 | "angular"
33 | ],
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "<%= props.gitRepositoryUrl %>/issues"
37 | },
38 | "devDependencies": {
39 | "@angular/common": "^5.0.0",
40 | "@angular/compiler": "^5.0.0",
41 | "@angular/compiler-cli": "^5.0.0",
42 | "@angular/core": "^5.0.0",
43 | "@angular/platform-browser": "^5.0.0",
44 | "@angular/platform-browser-dynamic": "^5.0.0",
45 | "@compodoc/compodoc": "^1.0.0-beta.10",
46 | "@types/node": "~6.0.60",
47 | "@types/jest": "^22.0.1",
48 | "angular-in-memory-web-api": "^0.3.2",
49 | "codelyzer": "~3.2.0",
50 | "concurrently": "^3.4.0",
51 | "core-js": "^2.4.1",
52 | "fs-extra": "^5.0.0",
53 | "del": "^2.2.2",
54 | "gulp": "^3.9.1",
55 | "gulp-rename": "^1.2.2",
56 | "gulp-rollup": "^2.11.0",
57 | "jest": "^22.1.4",
58 | "jest-preset-angular": "^5.0.0",
59 | "lite-server": "^2.3.0",
60 | "node-sass": "^4.5.2",
61 | "node-sass-tilde-importer": "^1.0.0",
62 | "node-watch": "^0.5.2",
63 | "protractor": "~5.1.2",
64 | "rollup": "^0.49.3",
65 | "run-sequence": "^1.2.2",
66 | "rxjs": "^5.5.2",
67 | "systemjs": "^0.20.12",
68 | "ts-node": "~3.2.0",
69 | "tslint": "~5.7.0",
70 | "typescript": "~2.4.2",
71 | "zone.js": "^0.8.14"
72 | },
73 | "engines": {
74 | "node": ">=6.0.0"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/generators/app/templates/_package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= props.scope %><%= props.libraryName.kebabCase %>",
3 | "version": "0.1.0",
4 | "scripts": {
5 | "build": "gulp build",
6 | "build:watch": "gulp",
7 | "docs": "npm run docs:build",
8 | "docs:build": "compodoc -p tsconfig.json -n <%= props.scope%><%= props.libraryName.original %> -d docs --hideGenerator",
9 | "docs:serve": "npm run docs:build -- -s",
10 | "docs:watch": "npm run docs:build -- -s -w",
11 | "lint": "tslint --type-check --project tsconfig.json src/**/*.ts",
12 | "lite": "lite-server",
13 | "playground:build": "tsc -p playground -w",
14 | "playground": "concurrently \"npm run build:watch\" \"npm run playground:build\" \"npm run lite\"",
15 | "test": "tsc && karma start"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "<%= props.gitRepositoryUrl %>"
20 | },
21 | "author": {
22 | "name": "<%= props.author.name %>",
23 | "email": "<%= props.author.email %>"
24 | },
25 | "keywords": [
26 | "angular"
27 | ],
28 | "license": "MIT",
29 | "bugs": {
30 | "url": "<%= props.gitRepositoryUrl %>/issues"
31 | },
32 | "devDependencies": {
33 | "@angular/common": "^5.0.0",
34 | "@angular/compiler": "^5.0.0",
35 | "@angular/compiler-cli": "^5.0.0",
36 | "@angular/core": "^5.0.0",
37 | "@angular/platform-browser": "^5.0.0",
38 | "@angular/platform-browser-dynamic": "^5.0.0",
39 | "@compodoc/compodoc": "^1.0.0-beta.10",
40 | "@types/jasmine": "2.5.53",
41 | "@types/node": "~6.0.60",
42 | "angular-in-memory-web-api": "^0.3.2",
43 | "codelyzer": "~3.2.0",
44 | "concurrently": "^3.4.0",
45 | "core-js": "^2.4.1",
46 | "fs-extra": "^5.0.0",
47 | "gulp": "^3.9.1",
48 | "gulp-rename": "^1.2.2",
49 | "gulp-rollup": "^2.15.0",
50 | "jasmine-core": "~2.6.2",
51 | "jasmine-spec-reporter": "~4.1.0",
52 | "karma": "~1.7.0",
53 | "karma-chrome-launcher": "~2.1.1",
54 | "karma-cli": "~1.0.1",
55 | "karma-coverage-istanbul-reporter": "^1.2.1",
56 | "karma-jasmine": "~1.1.0",
57 | "karma-jasmine-html-reporter": "^0.2.2",
58 | "lite-server": "^2.3.0",
59 | "node-sass": "^4.5.2",
60 | "node-sass-tilde-importer": "^1.0.0",
61 | "node-watch": "^0.5.2",
62 | "protractor": "~5.1.2",
63 | "rollup": "^0.49.3",
64 | "run-sequence": "^1.2.2",
65 | "rxjs": "^5.5.2",
66 | "systemjs": "^0.20.12",
67 | "ts-node": "~3.2.0",
68 | "tslint": "~5.7.0",
69 | "typescript": "~2.4.2",
70 | "zone.js": "^0.8.14"
71 | },
72 | "engines": {
73 | "node": ">=6.0.0"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint:recommended",
3 | "env": {
4 | "node": true,
5 | "mocha": true,
6 | "es6": true
7 | },
8 | "rules": {
9 | "array-bracket-spacing": [
10 | 2,
11 | "never"
12 | ],
13 | "brace-style": [
14 | 2,
15 | "1tbs"
16 | ],
17 | "consistent-return": 0,
18 | "indent": [
19 | 2,
20 | 2
21 | ],
22 | "no-multiple-empty-lines": [
23 | 2,
24 | {
25 | "max": 2
26 | }
27 | ],
28 | "no-use-before-define": [
29 | 2,
30 | "nofunc"
31 | ],
32 | "one-var": [
33 | 2,
34 | "never"
35 | ],
36 | "quote-props": [
37 | 2,
38 | "as-needed"
39 | ],
40 | "quotes": [
41 | 2,
42 | "single"
43 | ],
44 | "keyword-spacing": 2,
45 | "space-before-function-paren": [
46 | 2,
47 | {
48 | "anonymous": "always",
49 | "named": "never"
50 | }
51 | ],
52 | "space-in-parens": [
53 | 2,
54 | "never"
55 | ],
56 | "strict": [
57 | 2,
58 | "global"
59 | ],
60 | "curly": [
61 | 2,
62 | "all"
63 | ],
64 | "eol-last": 2,
65 | "key-spacing": [
66 | 2,
67 | {
68 | "beforeColon": false,
69 | "afterColon": true
70 | }
71 | ],
72 | "no-eval": 2,
73 | "no-with": 2,
74 | "space-infix-ops": 2,
75 | "dot-notation": [
76 | 2,
77 | {
78 | "allowKeywords": true
79 | }
80 | ],
81 | "eqeqeq": 2,
82 | "no-alert": 2,
83 | "no-caller": 2,
84 | "no-extend-native": 2,
85 | "no-extra-bind": 2,
86 | "no-implied-eval": 2,
87 | "no-iterator": 2,
88 | "no-label-var": 2,
89 | "no-labels": 2,
90 | "no-lone-blocks": 2,
91 | "no-loop-func": 2,
92 | "no-multi-spaces": 2,
93 | "no-multi-str": 2,
94 | "no-native-reassign": 2,
95 | "no-new": 2,
96 | "no-new-func": 2,
97 | "no-new-wrappers": 2,
98 | "no-octal-escape": 2,
99 | "no-proto": 2,
100 | "no-return-assign": 2,
101 | "no-script-url": 2,
102 | "no-sequences": 2,
103 | "no-unused-expressions": 2,
104 | "yoda": 2,
105 | "no-shadow": 2,
106 | "no-shadow-restricted-names": 2,
107 | "no-undef-init": 2,
108 | "camelcase": 2,
109 | "comma-spacing": 2,
110 | "new-cap": 0,
111 | "new-parens": 2,
112 | "no-array-constructor": 2,
113 | "no-extra-parens": 2,
114 | "no-new-object": 2,
115 | "no-spaced-func": 2,
116 | "no-trailing-spaces": 2,
117 | "no-underscore-dangle": 2,
118 | "semi": 2,
119 | "semi-spacing": [
120 | 2,
121 | {
122 | "before": false,
123 | "after": true
124 | }
125 | ]
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/generators/app/templates/_tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "class-name": true,
7 | "comment-format": [
8 | true,
9 | "check-space"
10 | ],
11 | "curly": true,
12 | "eofline": true,
13 | "forin": true,
14 | "indent": [
15 | true,
16 | "spaces"
17 | ],
18 | "label-position": true,
19 | "max-line-length": [
20 | true,
21 | 140
22 | ],
23 | "member-access": false,
24 | "member-ordering": [
25 | true,
26 | "static-before-instance",
27 | "variables-before-functions"
28 | ],
29 | "no-arg": true,
30 | "no-bitwise": true,
31 | "no-console": [
32 | true,
33 | "debug",
34 | "info",
35 | "time",
36 | "timeEnd",
37 | "trace"
38 | ],
39 | "no-construct": true,
40 | "no-debugger": true,
41 | "no-duplicate-variable": true,
42 | "no-empty": false,
43 | "no-eval": true,
44 | "no-inferrable-types": true,
45 | "no-shadowed-variable": true,
46 | "no-string-literal": false,
47 | "no-switch-case-fall-through": true,
48 | "no-trailing-whitespace": true,
49 | "no-unused-expression": true,
50 | "no-unused-variable": true,
51 | "no-use-before-declare": true,
52 | "no-var-keyword": true,
53 | "object-literal-sort-keys": false,
54 | "one-line": [
55 | true,
56 | "check-open-brace",
57 | "check-catch",
58 | "check-else",
59 | "check-whitespace"
60 | ],
61 | "quotemark": [
62 | true,
63 | "single"
64 | ],
65 | "radix": true,
66 | "semicolon": [
67 | true,
68 | "always"
69 | ],
70 | "triple-equals": [
71 | true,
72 | "allow-null-check"
73 | ],
74 | "typedef-whitespace": [
75 | true,
76 | {
77 | "call-signature": "nospace",
78 | "index-signature": "nospace",
79 | "parameter": "nospace",
80 | "property-declaration": "nospace",
81 | "variable-declaration": "nospace"
82 | }
83 | ],
84 | "variable-name": false,
85 | "whitespace": [
86 | true,
87 | "check-branch",
88 | "check-decl",
89 | "check-operator",
90 | "check-separator",
91 | "check-type"
92 | ],
93 | "directive-selector": [true, "attribute", "", "camelCase"],
94 | "component-selector": [true, "element", "", "kebab-case"],
95 | "use-input-property-decorator": true,
96 | "use-output-property-decorator": true,
97 | "use-host-property-decorator": true,
98 | "no-input-rename": true,
99 | "no-output-rename": true,
100 | "use-life-cycle-interface": true,
101 | "use-pipe-transform-interface": true,
102 | "component-class-suffix": true,
103 | "directive-class-suffix": true
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/generators/app/templates/tools/gulp/inline-resources.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // https://github.com/filipesilva/angular-quickstart-lib/blob/master/inline-resources.js
3 | 'use strict';
4 |
5 | const fs = require('fs');
6 | const path = require('path');
7 | const glob = require('glob');
8 | const sass = require('node-sass');
9 | const tildeImporter = require('node-sass-tilde-importer');
10 |
11 | /**
12 | * Simple Promiseify function that takes a Node API and return a version that supports promises.
13 | * We use promises instead of synchronized functions to make the process less I/O bound and
14 | * faster. It also simplifies the code.
15 | */
16 | function promiseify(fn) {
17 | return function () {
18 | const args = [].slice.call(arguments, 0);
19 | return new Promise((resolve, reject) => {
20 | fn.apply(this, args.concat([function (err, value) {
21 | if (err) {
22 | reject(err);
23 | } else {
24 | resolve(value);
25 | }
26 | }]));
27 | });
28 | };
29 | }
30 |
31 | const readFile = promiseify(fs.readFile);
32 | const writeFile = promiseify(fs.writeFile);
33 |
34 | /**
35 | * Inline resources in a tsc/ngc compilation.
36 | * @param projectPath {string} Path to the project.
37 | */
38 | function inlineResources(projectPath) {
39 |
40 | // Match only TypeScript files in projectPath.
41 | const files = glob.sync('**/*.ts', {cwd: projectPath});
42 |
43 | // For each file, inline the templates and styles under it and write the new file.
44 | return Promise.all(files.map(filePath => {
45 | const fullFilePath = path.join(projectPath, filePath);
46 | return readFile(fullFilePath, 'utf-8')
47 | .then(content => inlineResourcesFromString(content, url => {
48 | // Resolve the template url.
49 | return path.join(path.dirname(fullFilePath), url);
50 | }))
51 | .then(content => writeFile(fullFilePath, content))
52 | .catch(err => {
53 | console.error('An error occured: ', err);
54 | });
55 | }));
56 | }
57 |
58 | /**
59 | * Inline resources from a string content.
60 | * @param content {string} The source file's content.
61 | * @param urlResolver {Function} A resolver that takes a URL and return a path.
62 | * @returns {string} The content with resources inlined.
63 | */
64 | function inlineResourcesFromString(content, urlResolver) {
65 | // Curry through the inlining functions.
66 | return [
67 | inlineTemplate,
68 | inlineStyle,
69 | removeModuleId
70 | ].reduce((content, fn) => fn(content, urlResolver), content);
71 | }
72 |
73 | /**
74 | * Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and
75 | * replace with `template: ...` (with the content of the file included).
76 | * @param content {string} The source file's content.
77 | * @param urlResolver {Function} A resolver that takes a URL and return a path.
78 | * @return {string} The content with all templates inlined.
79 | */
80 | function inlineTemplate(content, urlResolver) {
81 | return content.replace(/templateUrl:\s*(['"])([^\1]+?\.html)\1/g, function (fullMatch, quote, templateUrl) {
82 | const templateFile = urlResolver(templateUrl);
83 | const templateContent = fs.readFileSync(templateFile, 'utf-8');
84 | const shortenedTemplate = templateContent
85 | .replace(/([\n\r]\s*)+/gm, ' ')
86 | .replace(/"/g, '\\"');
87 | return `template: "${shortenedTemplate}"`;
88 | });
89 | }
90 |
91 |
92 | /**
93 | * Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and
94 | * replace with `styles: [...]` (with the content of the file included).
95 | * @param urlResolver {Function} A resolver that takes a URL and return a path.
96 | * @param content {string} The source file's content.
97 | * @return {string} The content with all styles inlined.
98 | */
99 | function inlineStyle(content, urlResolver) {
100 | return content.replace(/styleUrls\s*:\s*(\[[\s\S]*?\])/gm, function (m, styleUrls) {
101 | const urls = eval(styleUrls);
102 | return 'styles: ['
103 | + urls.map(styleUrl => {
104 | const styleFile = urlResolver(styleUrl);
105 | const originContent = fs.readFileSync(styleFile, 'utf-8');
106 | const styleContent = styleFile.endsWith('.scss') ? buildSass(originContent, styleFile) : originContent;
107 | const shortenedStyle = styleContent
108 | .replace(/([\n\r]\s*)+/gm, ' ')
109 | .replace(/"/g, '\\"');
110 | return `"${shortenedStyle}"`;
111 | })
112 | .join(',\n')
113 | + ']';
114 | });
115 | }
116 |
117 | /**
118 | * build sass content to css
119 | * @param content {string} the css content
120 | * @param sourceFile {string} the scss file sourceFile
121 | * @return {string} the generated css, empty string if error occured
122 | */
123 | function buildSass(content, sourceFile) {
124 | try {
125 | const result = sass.renderSync({
126 | data: content,
127 | file: sourceFile,
128 | importer: tildeImporter
129 | });
130 | return result.css.toString()
131 | } catch (e) {
132 | console.error('\x1b[41m');
133 | console.error('at ' + sourceFile + ':' + e.line + ":" + e.column);
134 | console.error(e.formatted);
135 | console.error('\x1b[0m');
136 | return "";
137 | }
138 | }
139 |
140 | /**
141 | * Remove every mention of `moduleId: module.id`.
142 | * @param content {string} The source file's content.
143 | * @returns {string} The content with all moduleId: mentions removed.
144 | */
145 | function removeModuleId(content) {
146 | return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, '');
147 | }
148 |
149 | module.exports = inlineResources;
150 | module.exports.inlineResourcesFromString = inlineResourcesFromString;
151 |
152 | // Run inlineResources if module is being called directly from the CLI with arguments.
153 | if (require.main === module && process.argv.length > 2) {
154 | console.log('Inlining resources from project:', process.argv[2]);
155 | return inlineResources(process.argv[2]);
156 | }
157 |
--------------------------------------------------------------------------------
/generators/app/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const chalk = require('chalk');
3 | const yosay = require('yosay');
4 | const underscoreString = require('underscore.string');
5 | const Generator = require('yeoman-generator');
6 | const setupPlaygorund = require('./playground');
7 |
8 | module.exports = class extends Generator {
9 |
10 | constructor(args, opts) {
11 | super(args, opts);
12 | }
13 |
14 | initializing() {
15 | // Have Yeoman greet the user.
16 | this.log(yosay(
17 | 'Welcome to the ' + chalk.red('Angular Library') + ' generator!'
18 | ));
19 | }
20 |
21 | prompting() {
22 | const prompts = [
23 | {
24 | type: 'input',
25 | name: 'authorName',
26 | message: 'Your full name:',
27 | validate: function (input) {
28 | if (/.+/.test(input)) {
29 | return true;
30 | }
31 | return 'Please enter your full name';
32 | },
33 | default: this.user.git.name
34 | },
35 | {
36 | type: 'input',
37 | name: 'authorEmail',
38 | message: 'Your email address:',
39 | validate: function (input) {
40 | if (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(input)) {
41 | return true;
42 | }
43 | return 'Please enter a valid email address';
44 | },
45 | default: this.user.git.email
46 | },
47 | {
48 | type: 'input',
49 | name: 'libraryName',
50 | message: 'Your library name (kebab-case)',
51 | default: underscoreString.slugify(this.appname),
52 | filter: function (x) {
53 | return underscoreString.slugify(x);
54 | }
55 | },
56 | {
57 | type: 'input',
58 | name: 'scope',
59 | message: 'Your library scope (eg: @angular) leave blank for none',
60 | default: '',
61 | validate: function (x) {
62 | return !x || x.indexOf('@') === 0;
63 | },
64 | filter: function (x) {
65 | return x ? x + '/' : '';
66 | }
67 | },
68 | {
69 | type: 'input',
70 | name: 'gitRepositoryUrl',
71 | message: 'Git repository url',
72 | default: 'https://github.com/username/repo',
73 | store: true
74 | },
75 | {
76 | type: 'list',
77 | name: 'testFramework',
78 | message: 'Test framework',
79 | choices: [
80 | 'karma + jasmine',
81 | 'jest'
82 | ]
83 | }
84 | ];
85 |
86 | return this.prompt(prompts).then(props => {
87 |
88 | this.props = {
89 |
90 | author: {
91 | name: props.authorName,
92 | email: props.authorEmail
93 | },
94 |
95 | libraryName: {
96 | original: props.libraryName,
97 | kebabCase: props.libraryName
98 | },
99 |
100 | gitRepositoryUrl: props.gitRepositoryUrl,
101 |
102 | testFramework: props.testFramework,
103 |
104 | scope: props.scope
105 | };
106 |
107 | });
108 | }
109 |
110 | writing() {
111 |
112 | // Copy .gitignore
113 | this.fs.copy(
114 | this.templatePath('gitignore'),
115 | this.destinationPath('.gitignore')
116 | );
117 |
118 | // Copy .npmignore
119 | this.fs.copy(
120 | this.templatePath('npmignore'),
121 | this.destinationPath('.npmignore')
122 | );
123 |
124 | // Copy .travis.yml
125 | this.fs.copy(
126 | this.templatePath('travis.yml'),
127 | this.destinationPath('.travis.yml')
128 | );
129 |
130 | // Copy tsconfig.json
131 | this.fs.copyTpl(
132 | this.templatePath('_tsconfig.json'),
133 | this.destinationPath('tsconfig.json'),
134 | {
135 | props: this.props
136 | }
137 | );
138 |
139 | // Copy tslint.json
140 | this.fs.copyTpl(
141 | this.templatePath('_tslint.json'),
142 | this.destinationPath('tslint.json'),
143 | {
144 | props: this.props
145 | }
146 | );
147 |
148 | // Copy package.json
149 | if (this.props.testFramework === 'jest') {
150 | this.fs.copyTpl(
151 | this.templatePath('_package_jest.json'),
152 | this.destinationPath('package.json'),
153 | {
154 | props: this.props
155 | }
156 | );
157 |
158 | this.fs.copyTpl(
159 | this.templatePath('_jest.ts'),
160 | this.destinationPath('src/jest.ts')
161 | );
162 |
163 | this.fs.copyTpl(
164 | this.templatePath('_jest-global-mocks.ts'),
165 | this.destinationPath('src/jest-global-mocks.ts')
166 | );
167 | } else {
168 | this.fs.copyTpl(
169 | this.templatePath('_package.json'),
170 | this.destinationPath('package.json'),
171 | {
172 | props: this.props
173 | }
174 | );
175 | }
176 |
177 | // Copy README
178 | this.fs.copyTpl(
179 | this.templatePath('README.MD'),
180 | this.destinationPath('README.MD'),
181 | {
182 | props: this.props
183 | }
184 | );
185 |
186 | // Copy tools directory
187 | this.fs.copyTpl(
188 | this.templatePath('tools/**/*'),
189 | this.destinationPath('tools')
190 | );
191 |
192 | // Copy gulpfile.js
193 | this.fs.copyTpl(
194 | this.templatePath('gulpfile.js'),
195 | this.destinationPath('gulpfile.js'),
196 | {
197 | props: this.props
198 | }
199 | );
200 |
201 | // Copy src folder
202 | this.fs.copy(
203 | this.templatePath('src/**/*.ts'),
204 | this.destinationPath('src')
205 | );
206 |
207 | // Copy src/package.json
208 | this.fs.copyTpl(
209 | this.templatePath('src/_package.json'),
210 | this.destinationPath('src/package.json'),
211 | {
212 | props: this.props
213 | }
214 | );
215 |
216 | // Copy src/tsconfig.es5.json
217 | this.fs.copyTpl(
218 | this.templatePath('src/_tsconfig.es5.json'),
219 | this.destinationPath('src/tsconfig.es5.json'),
220 | {
221 | props: this.props
222 | }
223 | );
224 |
225 | // Copy src/tsconfig.spec.json
226 | this.fs.copyTpl(
227 | this.templatePath('src/_tsconfig.spec.json'),
228 | this.destinationPath('src/tsconfig.spec.json')
229 | );
230 |
231 | setupPlaygorund(this);
232 | }
233 |
234 | install() {
235 | this.installDependencies({bower: false});
236 | }
237 | };
238 |
--------------------------------------------------------------------------------
/generators/app/templates/gulpfile.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | var gulp = require('gulp'),
3 | path = require('path'),
4 | ngc = require('@angular/compiler-cli/src/main').main,
5 | rollup = require('gulp-rollup'),
6 | rename = require('gulp-rename'),
7 | fs = require('fs-extra'),
8 | runSequence = require('run-sequence'),
9 | inlineResources = require('./tools/gulp/inline-resources');
10 |
11 | const rootFolder = path.join(__dirname);
12 | const srcFolder = path.join(rootFolder, 'src');
13 | const tmpFolder = path.join(rootFolder, '.tmp');
14 | const buildFolder = path.join(rootFolder, 'build');
15 | const distFolder = path.join(rootFolder, 'dist');
16 |
17 | /**
18 | * 1. Delete /dist folder
19 | */
20 | gulp.task('clean:dist', function () {
21 |
22 | // Delete contents but not dist folder to avoid broken npm links
23 | // when dist directory is removed while npm link references it.
24 | return fs.emptyDirSync(distFolder);
25 | });
26 |
27 | /**
28 | * 2. Clone the /src folder into /.tmp. If an npm link inside /src has been made,
29 | * then it's likely that a node_modules folder exists. Ignore this folder
30 | * when copying to /.tmp.
31 | */
32 | gulp.task('copy:source', function () {
33 | return gulp.src([`${srcFolder}/**/*`, `!${srcFolder}/node_modules`])
34 | .pipe(gulp.dest(tmpFolder));
35 | });
36 |
37 | /**
38 | * 3. Inline template (.html) and style (.css) files into the the component .ts files.
39 | * We do this on the /.tmp folder to avoid editing the original /src files
40 | */
41 | gulp.task('inline-resources', function () {
42 | return Promise.resolve()
43 | .then(() => inlineResources(tmpFolder));
44 | });
45 |
46 |
47 | /**
48 | * 4. Run the Angular compiler, ngc, on the /.tmp folder. This will output all
49 | * compiled modules to the /build folder.
50 | *
51 | * As of Angular 5, ngc accepts an array and no longer returns a promise.
52 | */
53 | gulp.task('ngc', function () {
54 | ngc(['--project', `${tmpFolder}/tsconfig.es5.json`]);
55 | return Promise.resolve()
56 | });
57 |
58 | /**
59 | * 5. Run rollup inside the /build folder to generate our Flat ES module and place the
60 | * generated file into the /dist folder
61 | */
62 | gulp.task('rollup:fesm', function () {
63 | return gulp.src(`${buildFolder}/**/*.js`)
64 | // transform the files here.
65 | .pipe(rollup({
66 |
67 | // Bundle's entry point
68 | // See "input" in https://rollupjs.org/#core-functionality
69 | input: `${buildFolder}/index.js`,
70 |
71 | // Allow mixing of hypothetical and actual files. "Actual" files can be files
72 | // accessed by Rollup or produced by plugins further down the chain.
73 | // This prevents errors like: 'path/file' does not exist in the hypothetical file system
74 | // when subdirectories are used in the `src` directory.
75 | allowRealFiles: true,
76 |
77 | // A list of IDs of modules that should remain external to the bundle
78 | // See "external" in https://rollupjs.org/#core-functionality
79 | external: [
80 | '@angular/core',
81 | '@angular/common'
82 | ],
83 |
84 | output: {
85 | // Format of generated bundle
86 | // See "format" in https://rollupjs.org/#core-functionality
87 | format: 'es'
88 | }
89 | }))
90 | .pipe(gulp.dest(distFolder));
91 | });
92 |
93 | /**
94 | * 6. Run rollup inside the /build folder to generate our UMD module and place the
95 | * generated file into the /dist folder
96 | */
97 | gulp.task('rollup:umd', function () {
98 | return gulp.src(`${buildFolder}/**/*.js`)
99 | // transform the files here.
100 | .pipe(rollup({
101 |
102 | // Bundle's entry point
103 | // See "input" in https://rollupjs.org/#core-functionality
104 | input: `${buildFolder}/index.js`,
105 |
106 | // Allow mixing of hypothetical and actual files. "Actual" files can be files
107 | // accessed by Rollup or produced by plugins further down the chain.
108 | // This prevents errors like: 'path/file' does not exist in the hypothetical file system
109 | // when subdirectories are used in the `src` directory.
110 | allowRealFiles: true,
111 |
112 | // A list of IDs of modules that should remain external to the bundle
113 | // See "external" in https://rollupjs.org/#core-functionality
114 | external: [
115 | '@angular/core',
116 | '@angular/common'
117 | ],
118 |
119 | output: {
120 | // The name to use for the module for UMD/IIFE bundles
121 | // (required for bundles with exports)
122 | // See "name" in https://rollupjs.org/#core-functionality
123 | name: '<%= props.libraryName.original %>',
124 |
125 | // See "globals" in https://rollupjs.org/#core-functionality
126 | globals: {
127 | typescript: 'ts'
128 | },
129 |
130 | // Format of generated bundle
131 | // See "format" in https://rollupjs.org/#core-functionality
132 | format: 'umd',
133 |
134 | // Export mode to use
135 | // See "exports" in https://rollupjs.org/#danger-zone
136 | exports: 'named'
137 | }
138 |
139 | }))
140 | .pipe(rename('<%= props.libraryName.kebabCase %>.umd.js'))
141 | .pipe(gulp.dest(distFolder));
142 | });
143 |
144 | /**
145 | * 7. Copy all the files from /build to /dist, except .js files. We ignore all .js from /build
146 | * because with don't need individual modules anymore, just the Flat ES module generated
147 | * on step 5.
148 | */
149 | gulp.task('copy:build', function () {
150 | return gulp.src([`${buildFolder}/**/*`, `!${buildFolder}/**/*.js`])
151 | .pipe(gulp.dest(distFolder));
152 | });
153 |
154 | /**
155 | * 8. Copy package.json from /src to /dist
156 | */
157 | gulp.task('copy:manifest', function () {
158 | return gulp.src([`${srcFolder}/package.json`])
159 | .pipe(gulp.dest(distFolder));
160 | });
161 |
162 | /**
163 | * 9. Copy README.md from / to /dist
164 | */
165 | gulp.task('copy:readme', function () {
166 | return gulp.src([path.join(rootFolder, 'README.MD')])
167 | .pipe(gulp.dest(distFolder));
168 | });
169 |
170 | /**
171 | * 10. Delete /.tmp folder
172 | */
173 | gulp.task('clean:tmp', function () {
174 | return deleteFolder(tmpFolder);
175 | });
176 |
177 | /**
178 | * 11. Delete /build folder
179 | */
180 | gulp.task('clean:build', function () {
181 | return deleteFolder(buildFolder);
182 | });
183 |
184 | gulp.task('compile', function () {
185 | runSequence(
186 | 'clean:dist',
187 | 'copy:source',
188 | 'inline-resources',
189 | 'ngc',
190 | 'rollup:fesm',
191 | 'rollup:umd',
192 | 'copy:build',
193 | 'copy:manifest',
194 | 'copy:readme',
195 | 'clean:build',
196 | 'clean:tmp',
197 | function (err) {
198 | if (err) {
199 | console.log('ERROR:', err.message);
200 | deleteFolder(distFolder);
201 | deleteFolder(tmpFolder);
202 | deleteFolder(buildFolder);
203 | } else {
204 | console.log('Compilation finished succesfully');
205 | }
206 | });
207 | });
208 |
209 | /**
210 | * Watch for any change in the /src folder and compile files
211 | */
212 | gulp.task('watch', function () {
213 | gulp.watch(`${srcFolder}/**/*`, ['compile']);
214 | });
215 |
216 | gulp.task('clean', function (callback) {
217 | runSequence('clean:dist', 'clean:tmp', 'clean:build', callback);
218 | });
219 |
220 | gulp.task('build', function (callback) {
221 | runSequence('clean', 'compile', callback);
222 | });
223 |
224 | gulp.task('build:watch', function (callback) {
225 | runSequence('build', 'watch', callback);
226 | });
227 |
228 | gulp.task('default', ['build:watch']);
229 |
230 | /**
231 | * Deletes the specified folder
232 | */
233 | function deleteFolder(folder) {
234 | return fs.removeSync(folder);
235 | }
236 |
--------------------------------------------------------------------------------
/guides/import_non_angular_libraries.md:
--------------------------------------------------------------------------------
1 | - Last updated: 2017-08-16
2 | - Written by: [Ka Tam](https://github.com/kktam)
3 |
4 | ## generator-angular-2-library help guide
5 |
6 | ## How to import non Angular libraries into your own project
7 |
8 | To begin, first follow the general installation guide in the [README.md](https://github.com/kktam/generator-angular2-library) of generator-angular2-library.
9 |
10 | The demo projects for instructions described below are in the following Github projects.
11 |
12 | [Full Calendar reusable component project](https://github.com/kktam/fullcalendar-ag4), and
13 | [Full Calendar demo app, using the reusable component](https://github.com/kktam/fullcalendar-app-ag4)
14 |
15 | ### General installation of new generator-angular-2-library based project
16 |
17 | Simply run the generator and install the dependencies to start a new project.
18 |
19 | ```
20 | yo angular2-library
21 | npm i
22 | npm run build
23 | ```
24 |
25 | ### Structure of the project
26 |
27 | An important note to make about projects created by generator-angular-2-library is that the project contains 2 package.json files. The first one is located at ROOT\package.json and the second one at ROOT\src\package.json. The first package file is responsible to combine the project, like any other Angular project for build, run and distribution etc. So it has all the regular things a standard package.json would have, such as scripts, dependencies and devDependencies.
28 |
29 | The second package file, however, is only responsible for describing the packaging steps used for creation of UMD builds, as required by npm repository. For more information about npm's requirement in package.json, please goto [npm package.json explained](https://docs.npmjs.com/cli/build)
30 |
31 | ### Import non Angular based 3rd party library
32 |
33 | We will use FullCalendar.io as an example.
34 |
35 | To install FullCalendar.io use yarn or npm to install the npm package
36 |
37 | ```
38 | npm install fullcalendar
39 | ```
40 |
41 | This will install the fullcalendar name into the dependencies section of ROOT\package.json. This is important as the library package need to have all its dependencies at any given time in order to compile and run the projects.
42 |
43 | After the first install the ROOT\package.json will look like this
44 |
45 | ```
46 | "dependencies": {
47 | "fullcalendar": "^3.4.0"
48 | }
49 | ```
50 |
51 | Next open the ROOT\src\package.json
52 |
53 | The contents of ROOT\src\package.json are not managed either by npm, or by the generator itself. Therefore, the user must edit the contents of the ROOT\src\package.json manually, and **ensure** the peerDependencies section of the file matches all the contents of the dependencies section of ROOT\package.json.
54 |
55 | A common error is that, during the course of re-usable component library development, it is easy to forget to update the ROOT\src\package.json and it is missing a couple of libraries that was in the ROOT\package.json file. As a result, when the re-usable component project is imported into the host application, the running application will throw a module not found exception.
56 |
57 | In order to run libraries created from other technologies such as JQuery or just using pure Javascript, ES2015 support may be required, especially when those libraries were not ES6 compliant. In order to enable ES2015 support, simply open tsconfig.json, and edit following
58 |
59 | ```
60 | "lib": [
61 | "es2015",
62 | "es2015.iterable",
63 | "dom"
64 | ],
65 | ```
66 |
67 | There is also a default setting that needed to be changed, to support ES2015 by the AOT compiler.
68 | The change is the set annotateForClosureCompiler flag to false for ES2015 dependencies. If the reusable component project does not have any ES5 dependencies, this step is not required.
69 |
70 | To change, open the file at ROOT\src\tsconfig.es5.json and edit the following
71 |
72 | ```
73 | "angularCompilerOptions": {
74 | "annotateForClosureCompiler": false,
75 | ...
76 | },
77 | ```
78 |
79 | If the setting is not done correctly, then compiling the library will result in error. This is documented in Angular's [AOT issue](https://github.com/angular/angular/issues/16084)
80 |
81 | ### Setting up Types for TypeScript
82 |
83 | Since Angular 4 uses TypeScript for tooling and automation, and much of Angular 4's library is written in TypeScript. Therefore all of non-Angular based libraries used in an Angular project must be coupled with a "type" definition. Fortunately Angular and the open source community have created a lot of type definitions that are ready to use. Please go to [@types](https://www.npmjs.com/~types) npm repository for a complete list of type definition available.
84 |
85 | In the case of wrapping FullCalendar in our re-usable component, we will need @types/fullcalendar. Since we will also need jquery to locate elements in native DOM, and create javascript component directly on it (ES5 ways of creating most JavaScript components), the final dependencies for ROOT\package.json will now look like this:
86 |
87 | ```
88 | "dependencies": {
89 | "@types/fullcalendar": "^2.7.44",
90 | "@types/jquery": "3.2.5",
91 | "fullcalendar": "^3.4.0",
92 | "jasmine": "^2.6.0",
93 | "jquery": "^3.2.1"
94 | }
95 | ```
96 |
97 | You may need to install some extra typings that the types depends on. In my case, I have to install the following typings to compile all the dependencies.
98 |
99 | ```
100 | typings install core-js es6-shim jasmine node --save
101 | ```
102 |
103 | ### Instantiate the jQuery components
104 |
105 | First of all, the $ symbol we got to use and familiar with JQuery cannot be used in Angular 4 projects. Therefore, to use JQuery, first import and rename the imported component. Then use .default command call the static typed [constructor](http://definitelytyped.org/docs/angularjs--angular-route/interfaces/jquerystatic.html), like so:
106 |
107 | ```
108 | import * as jqueryProxy from 'jquery'
109 | const jquery: JQueryStatic = (jqueryProxy).default || jqueryProxy;
110 | ```
111 |
112 | finally to instantiate the JavaScript typed component, one can hook to the ngAfterViewInit event, and use jquery to search for element install underneath it.
113 |
114 | ```
115 | ngAfterViewInit() {
116 | setTimeout(() => {
117 | jquery('calendar-component').fullCalendar(this.options);
118 | }, 100);
119 | }
120 | ```
121 |
122 | ### Importing CSS provided by 3rd Party library
123 |
124 | Most 3rd party library provides a default suite of CSS files to provide a default theme for use with the library. It is useful to have the re-usable component project bundle the necessary CSS files, instead of having the target users of the re-usable component project, having to download or import the CSS files form a hosted CDN, manually import them again from npm, etc.
125 |
126 | To include native css from 3rd party libraries, create a ROOT\src\styles.css and include all of FullCalendar's css in this file. Once again the ~ import rule will direct to search from the nearest node_modules.
127 |
128 | ```
129 | @import "~fullcalendar/dist/fullcalendar.css";
130 | @import "~fullcalendar/dist/fullcalendar.print.css";
131 | ```
132 |
133 | generator-angular2-library does not have steps to copy css files manually added into the UMD distribution.
134 |
135 | in ROOT\package.json, install CPX, a copy tool with watches [npm](https://www.npmjs.com/package/cpx) and [github](https://github.com/mysticatea/cpx), and create a step to copy all he necessary css files into dist folder
136 |
137 | ```
138 | "scripts": {
139 | ...
140 | "build:copy": "cpx 'src/styles.css' dist/",
141 | ...
142 | "devDependencies": {
143 | ...
144 | "cpx": "^1.5.0"
145 | },
146 | ```
147 |
148 |
149 | ### Things to add in the Host applications, to support CSS from the Re-usable component library
150 |
151 | If you are using angular-cli to create hosted Angular projects, then you will need to create a new styles.css file under src, and import the merged css styles from the imported re-usable component library, like the following
152 |
153 | src/styles.css
154 |
155 | ```
156 | +@import "~fullcalendar-ag4/styles.css";
157 | ```
158 |
159 | Please note the ~ symbol allows you to specify to the Angular transpiler to search from the nearest node_modules folder. In this case, you do not need to specify relative path, or include "node_modules" in the path.
160 |
161 | If everything goes well, you will see your new project with the renewed CSS loaded on the component.
162 | If you every see the following error from the browser debugger while running the host application, and that would mean the component library CSS is not setup or loaded properly.
163 |
164 | ```
165 | Uncaught Error: Unexpected value '[object Object]' imported by the module 'AppModule'. Please add a @NgModule annotation.
166 | at syntaxError (compiler.es5.js:1689)
167 | at compiler.es5.js:15373
168 | at Array.forEach ()
169 | at CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver.getNgModuleMetadata (compiler.es5.js:15356)
170 | at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._loadModules (compiler.es5.js:26679)
171 | at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileModuleAndComponents (compiler.es5.js:26652)
172 | at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler.compileModuleAsync (compiler.es5.js:26581)
173 | at PlatformRef_.webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_._bootstrapModuleWithZone (core.es5.js:4595)
174 | at PlatformRef_.webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_.bootstrapModule (core.es5.js:4581)
175 | at Object.../../../../../src/main.ts (main.ts:11)
176 | ```
177 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url]
3 |
4 | [Yeoman](http://yeoman.io) generator to create a standalone [Angular](https://angular.io/) library in seconds.
5 |
6 | If you want to create an Angular library with directives, services and/or pipes, then this generator is just what you need.
7 |
8 | This generator aligns with the [official Angular Package Format](https://goo.gl/AMOU5G) and automatically generates a [Flat ES Module](http://angularjs.blogspot.be/2017/03/angular-400-now-available.html), a UMD bundle, a single metadata.json and type definitions to make your library ready for AOT compilation by the consuming Angular application.
9 |
10 | Watch [Jason Aden's talk](https://www.youtube.com/watch?v=unICbsPGFIA) to learn more about the Angular Package Format.
11 |
12 | More specifically, the latest version of this generator:
13 |
14 | - supports Angular 5
15 | - creates and configures `package.json` for the development of your library
16 | - creates and configures a second `package.json` for the distribution of your library
17 | - creates and configures `tsconfig.json` for your editor during development
18 | - creates and configures `tslint.json` for linting purposes
19 | - creates and configures `.gitignore`, `.npmignore` and `.travis.yml`
20 | - creates the main library file, a sample directive, a sample component, a sample service and a sample pipe
21 | - configures [tslint](https://palantir.github.io/tslint/) for you with [codelyzer](https://github.com/mgechev/codelyzer) support
22 | - creates and configures build scripts to generate a Flat ES Module (FESM), type definitions and metadata files for your library to make it ready for AOT compilation
23 | - creates and configures build scripts to generate a Universal Module Definition (UMD) bundle to use your library in Node.js, SystemJS and with script tags (Plunker, Fiddle, etc)
24 | - inlines templates automatically for you so you can use external HTML templates
25 | - inlines styles automatically for you so you can use external CSS templates
26 | - supports .scss files
27 | - supports unit tests and code coverage using [jest](https://facebook.github.io/jest/)
28 |
29 | This generator is built for Angular version 2 and above, hence the name generator-angular2-library. If you are looking for a similar generator for AngularJS 1.x, please visit [generator-angularjs-library](https://github.com/jvandemo/generator-angularjs-library).
30 |
31 | ## Quick start
32 |
33 | 
34 |
35 | First, install [Yeoman](http://yeoman.io) and generator-angular2-library using [npm](https://www.npmjs.com/) (assuming you already have [node.js](https://nodejs.org/) pre-installed).
36 |
37 | ```bash
38 | $ npm install -g yo
39 | $ npm install -g generator-angular2-library
40 | ```
41 |
42 | make a new directory and `cd` into it:
43 |
44 | ```bash
45 | $ mkdir angular-library-name
46 | $ cd angular-library-name
47 | ```
48 |
49 | and generate your new library:
50 |
51 | ```bash
52 | $ yo angular2-library
53 | ```
54 |
55 | The generator will prompt you for:
56 |
57 | ```bash
58 | ? Your full name: Jurgen Van de Moere
59 | ? Your email address: jurgen.van.de.moere@gmail.com
60 | ? Your library name (kebab case): angular-library-name
61 | ? Git repository url: https://github.com/jvandemo/angular2-library-name
62 | ```
63 |
64 | and create the following files for you:
65 |
66 | ```bash
67 | .
68 | ├── README.MD
69 | ├── gulpfile.js
70 | ├── package.json
71 | ├── src
72 | │ ├── index.ts
73 | │ ├── package.json
74 | │ ├── sample.component.ts
75 | │ ├── sample.directive.ts
76 | │ ├── sample.pipe.ts
77 | │ ├── sample.service.ts
78 | │ └── tsconfig.es5.json
79 | ├── tsconfig.json
80 | └── tslint.json
81 | ```
82 |
83 | You can then add or edit `*.ts` files in the `src/` directory and run:
84 |
85 | ```bash
86 | $ npm run build
87 | ```
88 |
89 | to automatically create all `*.js`, `*.d.ts` and `*.metadata.json` files in the `dist` directory:
90 |
91 | ```bash
92 | dist
93 | ├── index.d.ts # Typings for AOT compilation
94 | ├── index.js # Flat ES Module (FESM) for use with webpack
95 | ├── lib.d.ts # Typings for AOT compilation
96 | ├── lib.metadata.json # Metadata for AOT compilation
97 | ├── lib.umd.js # UMD bundle for use with Node.js, SystemJS or script tag
98 | ├── package.json # package.json for consumer of your library
99 | ├── sample.component.d.ts # Typings for AOT compilation
100 | ├── sample.directive.d.ts # Typings for AOT compilation
101 | ├── sample.pipe.d.ts # Typings for AOT compilation
102 | └── sample.service.d.ts # Typings for AOT compilation
103 | ```
104 |
105 | Finally you publish your library to NPM by publishing the contents of the `dist` directory:
106 |
107 | ```bash
108 | $ npm publish dist
109 | ```
110 |
111 | ## TypeScript config
112 |
113 | The generator creates 2 TypeScript config files:
114 |
115 | - `tsconfig.json` is used to configure your editor during development and is not used for building your library
116 | - `src/tsconfig.es5.json` is used by the Angular compiler to build the files in the `dist` directory when you run `npm run build`
117 |
118 | ## Linting your code
119 |
120 | Your library comes pre-configured with tslint and codelyzer support. To lint your code:
121 |
122 | ```bash
123 | $ npm run lint
124 | ```
125 |
126 | ## Building your library
127 |
128 | From the root of your library directory, run:
129 |
130 | ```bash
131 | $ npm run build
132 | ```
133 |
134 | This will generate a `dist` directory with:
135 |
136 | - a `package.json` file specifically for distribution with Angular listed in the `peerDependencies`
137 | - `sample-library.js`: a Flat ES Module (FESM) file that contains all your library code in a single file
138 | - `sample-library.umd.js`: a Universal Module Definition (UMD) bundle file that contains all your library code in UMD format for use in Node.js, SystemJS or via a script tag (e.g. in Plunker, Fiddle, etc)
139 | - `*.d.ts`: type definitions for you library
140 | - `sample-library.metadata.json`: metadata for your library to support AOT compilation
141 |
142 | ## Generating documentation for your library
143 |
144 | From the root of your library directory, run:
145 |
146 | ```bash
147 | $ npm run docs:build
148 | ```
149 | This will generate a `docs` directory with all documentation of your library.
150 |
151 | To serve your documentation, run:
152 |
153 | ```bash
154 | $ npm run docs:serve
155 | ```
156 |
157 | and navigate your browser to `http://localhost:8080`.
158 |
159 | To automatically rebuild your documentation every time a file in the `src` directory changes, run:
160 |
161 | ```bash
162 | $ npm run docs:watch
163 | ```
164 |
165 | For more features, check out the [compodoc website](https://compodoc.github.io/website/).
166 |
167 | ## Publishing your library to NPM
168 |
169 | To publish your library to NPM, first generate the `dist` directory:
170 |
171 | ```bash
172 | $ npm run build
173 | ```
174 |
175 | and then publish the contents of the `dist` directory to NPM:
176 |
177 | ```bash
178 | $ npm publish dist
179 | ```
180 |
181 | ## Consuming your library
182 |
183 | Once you have published your library to the NPM registry, you can import it in any Angular application by first installing it using NPM:
184 |
185 | ```bash
186 | $ npm install sample-library # use the name you used to publish to npm
187 | ```
188 |
189 | and then importing your library in your Angular `AppModule` (or whatever module you wish to import your library into):
190 |
191 | ```typescript
192 | import { BrowserModule } from '@angular/platform-browser';
193 | import { NgModule } from '@angular/core';
194 |
195 | import { AppComponent } from './app.component';
196 |
197 | // Import your library
198 | import { SampleModule } from 'sample-library';
199 |
200 | @NgModule({
201 | declarations: [
202 | AppComponent
203 | ],
204 | imports: [
205 | BrowserModule,
206 |
207 | // Specify your library as an import
208 | SampleModule.forRoot()
209 | ],
210 | providers: [],
211 | bootstrap: [AppComponent]
212 | })
213 | export class AppModule { }
214 | ```
215 |
216 | Once your shared library is imported, you can use its components, directives and pipes in your Angular application templates:
217 |
218 | ```xml
219 |
220 | {{ title }}
221 |
222 | This component is part of the shared library and will now work as expected.
223 |
224 | ```
225 |
226 | and if you need to access a service from your shared library, you can inject it using Dependency Injection:
227 |
228 | ```typescript
229 | import { Component } from '@angular/core';
230 |
231 | // Import the shared service
232 | import { SampleService } from 'sample-library';
233 |
234 | @Component({
235 | template: 'Injecting a service from the shared library'
236 | })
237 | export class HomeComponent {
238 |
239 | // Inject the service using Angular DI
240 | constructor(private sampleService: SampleService){
241 |
242 | }
243 |
244 | }
245 | ```
246 |
247 | To learn more about Angular Dependency Injection, check out the [Official Angular Documentation](https://angular.io/docs/ts/latest/cookbook/dependency-injection.html).
248 |
249 | ## Preview your library during development
250 |
251 | To preview your library code during development, start the playground:
252 |
253 | ```bash
254 | $ npm run playground
255 | ```
256 |
257 | Changes to your library code will be updated live in the browser window:
258 |
259 | 
260 |
261 | ## Consuming your library in a local application during development
262 |
263 | To consume your library in a local application before you publish it to npm, you can follow the following steps:
264 |
265 | 1. Create your library:
266 | ```
267 | $ yo angular2-library
268 | ```
269 | Let's assume you name your library `sample-library`.
270 |
271 | 2. Navigate to the `sample-library` directory:
272 | ```
273 | $ cd sample-library
274 | ```
275 |
276 | 3. Compile your library files:
277 | ```
278 | $ npm run build
279 | ```
280 |
281 | 4. From the `sample-library/dist` directory, create a symlink in the global node_modules directory to the `dist` directory of your library:
282 | ```
283 | $ cd dist
284 | $ npm link
285 | ```
286 |
287 | 5. Create a new Angular app. Let's assume you use angular-cli:
288 | ```
289 | $ cd /your-projects-path
290 | $ ng new my-app
291 | ```
292 |
293 | 6. Navigate to the `my-app` directory:
294 | ```
295 | $ cd my-app
296 | ```
297 |
298 | 7. From the `my-app` directory, link the global `sample-library` directory to node_modules of the `my-app` directory:
299 | ```
300 | $ npm link sample-library
301 | ```
302 |
303 | 8. Import `SampleModule` in your Angular application:
304 |
305 | ```typescript
306 | import { BrowserModule } from '@angular/platform-browser';
307 | import { NgModule } from '@angular/core';
308 |
309 | import { AppComponent } from './app.component';
310 |
311 | // Import your library
312 | import { SampleModule } from 'sample-library';
313 |
314 | @NgModule({
315 | declarations: [
316 | AppComponent
317 | ],
318 | imports: [
319 | BrowserModule,
320 |
321 | // Specify your library as an import
322 | SampleModule.forRoot()
323 | ],
324 | providers: [],
325 | bootstrap: [AppComponent]
326 | })
327 | export class AppModule { }
328 | ```
329 |
330 | 9. Once your shared library is imported, you can use its components, directives and pipes in your Angular application templates:
331 |
332 | ```xml
333 |
334 | {{ title }}
335 |
336 | This component is part of the shared library and will now work as expected.
337 |
338 | ```
339 |
340 | and if you need to access a service from your shared library, you can inject it using Dependency Injection:
341 |
342 | ```typescript
343 | import { Component } from '@angular/core';
344 |
345 | // Import the shared service
346 | import { SampleService } from 'sample-library';
347 |
348 | @Component({
349 | template: 'Injecting a service from the shared library'
350 | })
351 | export class HomeComponent {
352 |
353 | // Inject the service using Angular DI
354 | constructor(private sampleService: SampleService){
355 |
356 | }
357 |
358 | }
359 | ```
360 |
361 | 10. When you make a change to your library, recompile your library files again from your `sample-library` directory:
362 | ```
363 | $ npm run build
364 | ```
365 |
366 | 11. If you want to automatically recompile the library files when a file in `src` changes, run
367 | ```
368 | $ npm run build:watch
369 | ```
370 |
371 | 12. If you are using an Angular CLI application to consume your library, make sure to set up a [path mapping](https://github.com/angular/angular-cli/wiki/stories-linked-library#use-typesscript-path-mapping-for-peer-dependencies) in `/src/tsconfig.app.json` of your consuming application (not your library):
372 | ```typescript
373 | {
374 | "compilerOptions": {
375 | // ...
376 | // Note: these paths are relative to `baseUrl` path.
377 | "paths": {
378 | "@angular/*": [
379 | "../node_modules/@angular/*"
380 | ]
381 | }
382 | }
383 | }
384 | ```
385 |
386 | When you npm link a library with peer dependencies, the [consuming application searches for the peer dependencies in the library's parent directories instead of the application's parent directories](http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies).
387 |
388 | If you get `Error: Unexpected value '[object Object]' imported by the module 'AppModule'. Please add a @NgModule annotation.`, then try:
389 |
390 | ```
391 | $ ng serve --preserve-symlinks
392 | ```
393 |
394 | to make sure the consuming application searches for the peer dependencies in the application's node_modules directory.
395 |
396 | ## Frequently asked questions
397 |
398 | #### How can I configure Karma?
399 |
400 | Currently, the generator does not create a custom Karma configuration for running unit tests.
401 |
402 | If your library requires a custom Karma setup, please check out [this tutorial on how to configure Karma for your library](https://github.com/raphael-volt/ng2-testable-lib) (Credits to [Raphael](https://github.com/raphael-volt)).
403 |
404 | As soon as official recommendations are available on how to set up Karma for testing libraries, this generator will be updated accordingly.
405 |
406 | #### How can I use a scoped package name?
407 |
408 | First update the package name in `src/package.json`:
409 |
410 | ```javascript
411 | "name": "@scope/library-name"
412 | ```
413 |
414 | and then also update `flatModuleId` in `src/tsconfig.es5.json` accordingly:
415 |
416 | ```javascript
417 | "flatModuleId": "@scope/library-name"
418 | ```
419 |
420 | See [#75](https://github.com/jvandemo/generator-angular2-library/issues/75) for more information.
421 |
422 | #### How can I avoid recompilation during development
423 |
424 | If you experience issues ([#72](https://github.com/jvandemo/generator-angular2-library/issues/72)) or want to avoid constant recompilation of your library during development, you can also `npm link src` instead of `npm link dist` in step 4 of the process above.
425 |
426 | This will let you consume the TypeScript code directly from the `src` directory of your library instead of the generated bundle from the `dist` directory. This increases development speed if you are testing your library in a local Angular application, but remember to test the generated bundle using `npm link dist` after you finish writing your code, to ensure that your generated bundle is working as expected before you publish your library to NPM.
427 |
428 | #### How can I use .scss files?
429 |
430 | Simply store your styles in a file with a filename extension of `scss` and reference it in your component's `styleUrls` property.
431 |
432 | So if you have a `sample.component.scss`:
433 |
434 | ```scss
435 | h1 {
436 | color: red;
437 | }
438 | ```
439 |
440 | then reference it in your component's `styleUrls` in `sample.component.ts` accordingly:
441 |
442 | ```typescript
443 | @Component({
444 | selector: 'sample-component',
445 | template: `Sample component
`,
446 | styleUrls: [
447 | 'sample.component.scss'
448 | ]
449 | })
450 | ```
451 |
452 | The .scss files will automatically be compiled and inlined in your library bundle.
453 |
454 | #### How can I import .scss files
455 |
456 | To import a .scss file in an existing .scss file, you can specify a relative path:
457 |
458 | ```
459 | @import '../relative/path/to/other.scss';
460 | ```
461 |
462 | or use a tilde to import a file from the nearest parent `node_modules` directory:
463 |
464 | ```
465 | @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
466 | ```
467 |
468 | #### How can I see which version of the generator I have installed
469 |
470 | From the command line, run:
471 |
472 | ```
473 | $ npm ls -g --depth=1 2>/dev/null | grep generator-
474 | ```
475 |
476 | #### How can I update my generator to the latest version?
477 |
478 | From the command line, run
479 |
480 | ```bash
481 | $ yo
482 | ```
483 | and select the option *Update your generators*.
484 |
485 | #### What if my library depends on a third party library?
486 |
487 | If your library depends on a third party library such as Angular Material or PrimeNG, you don't have to include the third party library in your library.
488 |
489 | Instead, you should add the third party library as a peer dependency to the `peerDependencies` property in `src/package.json` of your library:
490 |
491 | ```javascript
492 | "peerDependencies": {
493 | "@angular/core": "^4.0.0",
494 | "rxjs": "^5.1.0",
495 | "zone.js": "^0.8.4"
496 | }
497 | ```
498 |
499 | This causes a warning to be displayed when the consuming application runs `npm install` and does not have the third party library installed that your library depends on.
500 |
501 | The generator already adds `@angular/core`, `rxjs` and `zone.js` as peer dependencies for you by default.
502 |
503 | Consider the following scenario where your library depends on a third party library called "PrimeNG".
504 |
505 | In your Angular library:
506 |
507 | 1. run `npm install primeng --save` to install PrimeNG and add it as a devDependency to `package.json` in the root directory
508 | 2. add PrimeNG as a peerDependency in `src/package.json`, *NOT* as dependency or devDependency (`src/package.json` is the package.json that is distributed with your library, so you must specify primeng as peer dependency here, *NOT* in the package.json file in the root of your library)
509 | 3. import the necessary PrimeNG Angular module(s) in your library Angular module
510 | 4. write code that uses PrimeNG components
511 | 5. build your library and publish it (or link it locally)
512 |
513 | In the consuming Angular application
514 |
515 | 1. run `npm install yourlibrary` to install your library (which should display a warning if PrimeNG is not installed) or link it locally
516 | 2. run `npm install primeng` to install PrimeNG if it is not installed yet
517 | 3. import the necessary PrimeNG Angular module(s) in your Angular application module (usually `AppModule`) (this step is not needed if your library exports the PrimeNG module(s) in its module metadata)
518 | 4. import your library module in your Angular application module (usually `AppModule`)
519 | 5. you can now use your library components
520 |
521 | To see a fully documented example, check out [this guide](./guides/import_non_angular_libraries.md).
522 |
523 | #### How can I upgrade my library to support Angular 5
524 |
525 | Version 12 or later of this generator supports Angular 5.
526 |
527 | If you have an existing library that was generated with an earlier version of this generator:
528 |
529 | 1. update the versions of the Angular packages in `package.json` to Angular 5 ([example](https://github.com/jvandemo/generator-angular2-library/blob/master/generators/app/templates/_package.json))
530 | 2. replace the `ngc` script in your `gulpfile.js` with:
531 |
532 | ```
533 | gulp.task('ngc', function () {
534 | ngc([ '--project', `${tmpFolder}/tsconfig.es5.json` ]);
535 | return Promise.resolve()
536 | });
537 | ```
538 |
539 | See [#230](https://github.com/jvandemo/generator-angular2-library/issues/230) for more information.
540 |
541 | ## Issues
542 |
543 | Please report bugs and issues [here](https://github.com/jvandemo/generator-angular2-library/issues).
544 |
545 | ## Development
546 |
547 | To run the generator unit tests:
548 |
549 | ```bash
550 | $ npm run test
551 | ```
552 |
553 | ## License
554 |
555 | MIT © [Jurgen Van de Moere](http://www.jvandemo.com)
556 |
557 | ## Change log
558 |
559 | ### v12.4.1
560 |
561 | - Fix tslint rule [#286](https://github.com/jvandemo/generator-angular2-library/pull/286) (Credits to [Mathias Wittlock](https://github.com/wittlock))
562 |
563 | ### v12.4.0
564 |
565 | - Add prompt to ask for scope [#283](https://github.com/jvandemo/generator-angular2-library/pull/283) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
566 |
567 | ### v12.3.0
568 |
569 | - Update rollup options [#270](https://github.com/jvandemo/generator-angular2-library/pull/270) (Credits to [Zura Gabievi](https://github.com/zgabievi))
570 | - Fix mkdir error [#269](https://github.com/jvandemo/generator-angular2-library/pull/269) (Credits to [Louis Amstutz](https://github.com/lamstutz))
571 |
572 | ### v12.2.1
573 |
574 | - Update system.js config to use single quotes
575 |
576 | ### v12.2.0
577 |
578 | - Added default extension to playground system.js config to fix [#146](https://github.com/jvandemo/generator-angular2-library/pull/146)
579 |
580 | ### v12.1.0
581 |
582 | - Fixed issue with deleting .tmp folder after failed build (See [#261](https://github.com/jvandemo/generator-angular2-library/pull/261)) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
583 | - Updated package_jest.json (See [#267](https://github.com/jvandemo/generator-angular2-library/pull/267)) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
584 |
585 | ### v12.0.0
586 |
587 | - Updated packages to Angular 5
588 | - Updated ngc gulp script (See [#230](https://github.com/jvandemo/generator-angular2-library/issues/230)) (Credits to [Filip Lauc](https://github.com/flauc))
589 |
590 | ### v11.4.0
591 |
592 | - Updated rollup and gulp-rollup configuration (See [#190](https://github.com/jvandemo/generator-angular2-library/pull/190)) (Credits to [Daniel Geri](https://github.com/danielgeri))
593 |
594 | ### v11.3.0
595 |
596 | - Added playground (See [#146](https://github.com/jvandemo/generator-angular2-library/pull/146)) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
597 |
598 | ### v11.2.0
599 |
600 | - Added guide on how depend on third party library (See [#172](https://github.com/jvandemo/generator-angular2-library/pull/172)) (Credits to [Ka Tam](https://github.com/kktam))
601 |
602 | ### v11.1.0
603 |
604 | - Added `main` and `jsnext:main` properties to package.json
605 |
606 | ### v11.0.3
607 |
608 | - Added FAQ on how to add third party library
609 | - Updated jest support (See [#91](https://github.com/jvandemo/generator-angular2-library/pull/158)) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
610 |
611 | ### v11.0.2
612 |
613 | - Fixed package.json for [Jest](https://facebook.github.io/jest/) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
614 |
615 | ### v11.0.1
616 |
617 | - Updated `styleUrls` to fix [#140](https://github.com/jvandemo/generator-angular2-library/issues/140)
618 |
619 | ### v11.0.0
620 |
621 | - Added support for [Jest](https://facebook.github.io/jest/) (Credits to [Fabrizio Fortunato](https://github.com/izifortune))
622 | - Updated Compodoc (Credits to [Artem Kuznetsov](https://github.com/artemsky))
623 |
624 | ### v10.2.2
625 |
626 | - Avoid deletion of dist directory to prevent npm link errors (See [#91](https://github.com/jvandemo/generator-angular2-library/issues/91)) (Credits to [Filipe Silva](https://github.com/filipesilva) and [Brenden Niedermeyer](https://github.com/bniedermeyer))
627 |
628 | ### v10.2.1
629 |
630 | - Allow real files in rollup to fix [#105](https://github.com/jvandemo/generator-angular2-library/issues/105)
631 |
632 | ### v10.2.0
633 |
634 | - Add support for scss imports ([#100](https://github.com/jvandemo/generator-angular2-library/pull/100))(Credits to [rtrompier](https://github.com/rtrompier))
635 |
636 | ### v10.1.1
637 |
638 | - Fix README
639 |
640 | ### v10.1.0
641 |
642 | - Copy README to dist directory ([#85](https://github.com/jvandemo/generator-angular2-library/pull/85)) (Credits to [David](https://github.com/dbfannin))
643 |
644 | ### v10.0.0
645 |
646 | - Added support for generating UMD bundle
647 |
648 | ### v9.3.0
649 |
650 | - Added support for .scss files (Credits to [Thomas Deblock](https://github.com/deblockt))
651 |
652 | ### v9.2.0
653 |
654 | - Added convenience scripts for generating documentation
655 |
656 | ### v9.1.0
657 |
658 | - Added compodoc for generating documentation ([#76](https://github.com/jvandemo/generator-angular2-library/pull/76))
659 | - Removed comments from TypeScript config files to allow JSON validity checks
660 |
661 | ### v9.0.0
662 |
663 | - Added Gulp for support on Mac, Linux and Windows (Credits to [Carlos Roso](https://github.com/caroso1222))
664 | - Added template inlining (Credits to [Filipe Silva](https://github.com/filipesilva))
665 | - Added style inlining (Credits to [Filipe Silva](https://github.com/filipesilva))
666 |
667 | ### v8.2.1
668 |
669 | - Updated TypeScript files in gitignore
670 |
671 | ### v8.2.0
672 |
673 | - Added build:watch script
674 | - Added dist folder to gitignore
675 |
676 | ### v8.1.0
677 |
678 | - Remove prepublish script
679 |
680 | ### v8.0.0
681 |
682 | - Update build process
683 | - Add support for AOT compilation
684 |
685 | ### v7.0.0
686 |
687 | - Update to Angular 4
688 |
689 | ### v6.0.0
690 |
691 | - Update to Yeoman 1.x
692 |
693 | ### v5.6.0
694 |
695 | - Ignore files generated by ngc in .gitignore
696 |
697 | ### v5.5.2
698 |
699 | - Remove obsolete files in package.json
700 |
701 | ### v5.5.1
702 |
703 | - Add README.md to package.json so NPM registry can display it
704 |
705 | ### v5.5.0
706 |
707 | - Update devDependencies
708 |
709 | ### v5.4.0
710 |
711 | - Update to latest tslint and codelyzer
712 |
713 | ### v5.3.0
714 |
715 | - Update TypeScript version to fix #41
716 |
717 | ### v5.2.1
718 |
719 | - Fix eslint errors
720 | - Remove duplicate dependency
721 |
722 | ### v5.2.0
723 |
724 | - Suggest better default library name
725 |
726 | ### v5.1.0
727 |
728 | - Add support for AOT compilation
729 | - Update Angular 2 references to just Angular
730 |
731 | ### v5.0.0
732 |
733 | - Replace typings with @types (#29)
734 |
735 | ### v4.0.0
736 |
737 | - Remove default keyword when exporting module to fix #23
738 |
739 | ### v3.0.4
740 |
741 | - Updated version of Codelyzer
742 | - Updated selector of sample component to kebab case to fix #21
743 |
744 | ### v3.0.3
745 |
746 | - Fixed unit tests
747 |
748 | ### v3.0.2
749 |
750 | - Fixed `README.md` example code
751 |
752 | ### v3.0.1
753 |
754 | - Fixed `tsconfig.json` files
755 |
756 | ### v3.0.0
757 |
758 | - Added support for `NgModule`
759 |
760 | ### v2.2.0
761 |
762 | - Updated dependencies in package.json to Angular 2 final
763 |
764 | ### v2.1.0
765 |
766 | - Updated templates to Angular 2.0.0 RC3 syntax
767 |
768 | ### v2.0.0
769 |
770 | - Updated with file structure using `src` and `dist` directory
771 |
772 | ### v1.1.1
773 |
774 | - Updated templates to Angular 2.0.0 RC1 syntax
775 |
776 | ### v1.1.0
777 |
778 | - Added codelyzer support
779 | - Added tslint support
780 | - Added typings support
781 |
782 | ### v1.0.0
783 |
784 | - BREAKING CHANGE: Updated to support [Angular 2.0.0-rc.1](https://github.com/angular/angular/blob/master/CHANGELOG.md#200-rc1-2016-05-03)
785 |
786 | ### v0.6.0
787 |
788 | - Updated dependency versions
789 |
790 | ### v0.5.0
791 |
792 | - Added `browser.d.ts` to files in `tsconfig.json` instead of using tripleslash (see #9)
793 |
794 | ### v0.4.0
795 |
796 | - Added reference to Angular typings
797 |
798 | ### v0.3.1
799 |
800 | - Removed explicit RxJS dependency
801 |
802 | ### v0.3.0
803 |
804 | - Updated to Angular 2 beta
805 |
806 | ### v0.2.0
807 |
808 | - Added documentation
809 | - Added support for `PROVIDERS`, `DIRECTIVES` and `PIPES`
810 |
811 | ### v0.1.0
812 |
813 | - Added documentation
814 | - Added boilerplate scaffolding
815 | - Initial version
816 |
817 | [npm-image]: https://badge.fury.io/js/generator-angular2-library.svg
818 | [npm-url]: https://npmjs.org/package/generator-angular2-library
819 | [travis-image]: https://travis-ci.org/jvandemo/generator-angular2-library.svg?branch=master
820 | [travis-url]: https://travis-ci.org/jvandemo/generator-angular2-library
821 | [daviddm-image]: https://david-dm.org/jvandemo/generator-angular2-library.svg?theme=shields.io
822 | [daviddm-url]: https://david-dm.org/jvandemo/generator-angular2-library
823 | [coveralls-image]: https://coveralls.io/repos/jvandemo/generator-angular2-library/badge.svg
824 | [coveralls-url]: https://coveralls.io/r/jvandemo/generator-angular2-library
825 |
--------------------------------------------------------------------------------