├── demo ├── src │ ├── assets │ │ ├── .gitkeep │ │ ├── .npmignore │ │ └── logo.svg │ ├── app │ │ ├── app.component.scss │ │ ├── shared │ │ │ ├── index.ts │ │ │ ├── content-wrapper │ │ │ │ ├── content-wrapper.component.scss │ │ │ │ ├── content-wrapper.component.html │ │ │ │ ├── content-wrapper.component.ts │ │ │ │ └── content-wrapper.component.spec.ts │ │ │ ├── header │ │ │ │ ├── header.component.scss │ │ │ │ ├── header.component.ts │ │ │ │ ├── header.component.html │ │ │ │ └── header.component.spec.ts │ │ │ ├── footer │ │ │ │ ├── footer.component.scss │ │ │ │ ├── footer.component.ts │ │ │ │ ├── footer.component.html │ │ │ │ └── footer.component.spec.ts │ │ │ └── shared.module.ts │ │ ├── app.component.html │ │ ├── home │ │ │ ├── home.component.scss │ │ │ ├── home-routing.module.ts │ │ │ ├── home.module.ts │ │ │ ├── home.component.ts │ │ │ ├── home.component.spec.ts │ │ │ └── home.component.html │ │ ├── getting-started │ │ │ ├── getting-started-routing.module.ts │ │ │ ├── getting-started.module.ts │ │ │ ├── getting-started.component.ts │ │ │ ├── getting-started.component.spec.ts │ │ │ ├── getting-started.component.scss │ │ │ └── getting-started.component.html │ │ ├── app-routing.module.ts │ │ ├── app.component.ts │ │ ├── app.server.module.ts │ │ ├── app.module.ts │ │ └── app.component.spec.ts │ ├── testing │ │ ├── index.ts │ │ └── router-stubs.ts │ ├── main.server.ts │ ├── favicon.ico │ ├── environments │ │ ├── environment.hmr.ts │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── typings.d.ts │ ├── _variables.scss │ ├── tsconfig.spec.json │ ├── tsconfig.server.json │ ├── tsconfig.app.json │ ├── hmr.ts │ ├── main.ts │ ├── styles.scss │ ├── test.ts │ ├── index.html │ └── polyfills.ts ├── static.paths.ts ├── proxy.conf.json ├── e2e │ ├── app.po.ts │ ├── tsconfig.e2e.json │ └── app.e2e-spec.ts ├── .editorconfig ├── tsconfig.json ├── .gitignore ├── protractor.conf.js ├── karma.conf.js ├── README.md ├── webpack.server.config.js ├── prerender.ts ├── server.ts ├── package.json ├── .angular-cli.json └── tslint.json ├── src ├── index.ts ├── module │ ├── component │ │ ├── avatar.component.scss │ │ ├── avatar.component.html │ │ ├── avatar.component.ts │ │ └── avatar.component.spec.ts │ ├── avatar.module.ts │ └── Md5.ts ├── tsconfig.spec.json └── tsconfig.lib.json ├── .babelrc ├── karma.conf.js ├── webpack.config.js ├── .editorconfig ├── tsconfig.json ├── .travis.yml ├── .gitignore ├── config ├── karma-test-shim.js ├── helpers.js ├── karma.conf.js └── webpack.test.js ├── .yo-rc.json ├── LICENSE ├── .github └── ISSUE_TEMPLATE.md ├── tslint.json ├── CHANGELOG.md ├── package.json ├── README.MD └── gulpfile.js /demo/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/src/assets/.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/src/testing/index.ts: -------------------------------------------------------------------------------- 1 | export * from './router-stubs'; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/avatar.module'; 2 | -------------------------------------------------------------------------------- /demo/src/app/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shared.module'; -------------------------------------------------------------------------------- /demo/src/app/shared/content-wrapper/content-wrapper.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015" 4 | ] 5 | } 6 | 7 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./config/karma.conf.js'); 2 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./config/webpack.test.js'); 2 | -------------------------------------------------------------------------------- /demo/src/main.server.ts: -------------------------------------------------------------------------------- 1 | export { AppServerModule } from './app/app.server.module'; 2 | -------------------------------------------------------------------------------- /demo/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snics/ng2-avatar/HEAD/demo/src/favicon.ico -------------------------------------------------------------------------------- /demo/static.paths.ts: -------------------------------------------------------------------------------- 1 | export const ROUTES = [ 2 | '/', 3 | '/getting-started/', 4 | ]; 5 | -------------------------------------------------------------------------------- /demo/src/app/shared/header/header.component.scss: -------------------------------------------------------------------------------- 1 | .navbar { 2 | background: hsla(0,0%,100%,.95) 3 | } 4 | -------------------------------------------------------------------------------- /demo/src/environments/environment.hmr.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | hmr: true 4 | }; 5 | -------------------------------------------------------------------------------- /demo/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | hmr: false 4 | }; 5 | -------------------------------------------------------------------------------- /demo/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | -------------------------------------------------------------------------------- /demo/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /demo/src/_variables.scss: -------------------------------------------------------------------------------- 1 | $icon-font-path: '../node_modules/bootstrap-sass/assets/fonts/bootstrap/'; 2 | $fa-font-path: '../node_modules/font-awesome/fonts/'; 3 | -------------------------------------------------------------------------------- /src/module/component/avatar.component.scss: -------------------------------------------------------------------------------- 1 | .avatar { 2 | text-align : center; 3 | overflow : hidden; 4 | 5 | img { 6 | vertical-align: top; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /demo/src/app/home/home.component.scss: -------------------------------------------------------------------------------- 1 | .logo { 2 | width: 256px; 3 | height: 256px; 4 | margin-top: 1.4rem; 5 | } 6 | 7 | .home { 8 | margin-top: 1.0rem; 9 | } -------------------------------------------------------------------------------- /demo/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/doc/*": { 3 | "target": "http://localhost:8080", 4 | "secure": false, 5 | "pathRewrite": {"^/doc" : ""}, 6 | "logLevel": "info" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /demo/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | export class Ng2AvatarDemoPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = 0 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /demo/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /demo/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /demo/src/app/shared/footer/footer.component.scss: -------------------------------------------------------------------------------- 1 | footer { 2 | padding: 3rem 0; 3 | font-size: 85%; 4 | background-color: #f7f7f7; 5 | text-align: left; 6 | 7 | .heart{ 8 | color: #ff005d; 9 | } 10 | 11 | p { 12 | margin-bottom: 0; 13 | } 14 | 15 | a { 16 | font-weight: 500; 17 | color: #55595c; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /demo/src/app/shared/footer/footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-footer', 5 | templateUrl: './footer.component.html', 6 | styleUrls: ['./footer.component.scss'] 7 | }) 8 | export class FooterComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /demo/src/app/home/home-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { HomeComponent } from './home.component'; 4 | 5 | @NgModule({ 6 | imports: [RouterModule.forChild([ 7 | { path: 'home', component: HomeComponent } 8 | ])], 9 | exports: [RouterModule] 10 | }) 11 | export class HomeRoutingModule {} -------------------------------------------------------------------------------- /demo/src/app/shared/content-wrapper/content-wrapper.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

{{ component }}

4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 | 12 |
13 |
-------------------------------------------------------------------------------- /demo/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Ng2AvatarDemoPage } from './app.po'; 2 | 3 | describe('ng2-avatar-demo App', () => { 4 | let page: Ng2AvatarDemoPage; 5 | 6 | beforeEach(() => { 7 | page = new Ng2AvatarDemoPage (); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /demo/src/app/shared/footer/footer.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/src/app/shared/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-header', 5 | templateUrl: './header.component.html', 6 | styleUrls: ['./header.component.scss'] 7 | }) 8 | export class HeaderComponent implements OnInit { 9 | 10 | navbarCollapsed = true; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /demo/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /demo/src/tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "testing/*", 11 | "test.ts", 12 | "**/*.spec.ts" 13 | ], 14 | "angularCompilerOptions": { 15 | "entryModule": "app/app.server.module#AppServerModule" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demo/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015", 7 | "types": [], 8 | "paths": { 9 | "@angular/*": ["../node_modules/@angular/*"], 10 | "ts-md5": ["../node_modules/ts-md5"] 11 | } 12 | }, 13 | "exclude": [ 14 | "testing/*", 15 | "test.ts", 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { GettingStartedComponent } from './getting-started.component'; 4 | 5 | @NgModule({ 6 | imports: [RouterModule.forChild([ 7 | { path: '', component: GettingStartedComponent } 8 | ])], 9 | exports: [RouterModule] 10 | }) 11 | export class GettingStartedRoutingModule {} -------------------------------------------------------------------------------- /demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es5", 11 | "typeRoots": [ 12 | "node_modules/@types" 13 | ], 14 | "lib": [ 15 | "es2017", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false, 8 | hmr: false 9 | }; 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "declaration": true, 9 | "experimentalDecorators": true, 10 | "noImplicitAny": true, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "skipLibCheck": true, 13 | "stripInternal": true, 14 | "lib": [ 15 | "es2015", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/src/app/shared/content-wrapper/content-wrapper.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-content-wrapper', 5 | templateUrl: './content-wrapper.component.html', 6 | styleUrls: ['./content-wrapper.component.scss'] 7 | }) 8 | export class ContentWrapperComponent implements OnInit { 9 | 10 | @Input() 11 | public component: string; 12 | 13 | constructor() { } 14 | 15 | ngOnInit() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /demo/src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import {AvatarModule} from 'ng2-avatar'; 4 | 5 | import {HomeRoutingModule} from './home-routing.module'; 6 | import {HomeComponent} from './home.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | AvatarModule.forRoot(), 12 | HomeRoutingModule, 13 | ], 14 | declarations: [HomeComponent], 15 | }) 16 | export class HomeModule { 17 | } 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | #install google chrome, using addons 5 | addons: 6 | apt: 7 | sources: 8 | - google-chrome 9 | packages: 10 | - google-chrome-stable 11 | 12 | language: node_js 13 | node_js: 14 | - "6" 15 | 16 | before_script: 17 | - export DISPLAY=:99.0 18 | - sh -e /etc/init.d/xvfb start 19 | - npm install --quiet -g gulp-cli 20 | 21 | script: gulp test:ci 22 | 23 | after_success: gulp coveralls 24 | 25 | cache: 26 | yarn: true 27 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { GettingStartedComponent } from './getting-started.component'; 4 | import { GettingStartedRoutingModule } from './getting-started-routing.module'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | CommonModule, 9 | GettingStartedRoutingModule 10 | ], 11 | declarations: [GettingStartedComponent], 12 | }) 13 | export class GettingStartedModule { } 14 | -------------------------------------------------------------------------------- /demo/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | const routes: Routes = [ 5 | { 6 | path: '', 7 | redirectTo: 'home', 8 | pathMatch: 'full' 9 | }, 10 | { 11 | path: 'getting-started', 12 | loadChildren: 'app/getting-started/getting-started.module#GettingStartedModule' 13 | } 14 | ]; 15 | 16 | @NgModule({ 17 | imports: [RouterModule.forRoot(routes)], 18 | exports: [RouterModule] 19 | }) 20 | export class AppRoutingModule { } 21 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Title } from '@angular/platform-browser'; 3 | 4 | 5 | @Component({ 6 | selector: 'app-getting-started', 7 | templateUrl: './getting-started.component.html', 8 | styleUrls: ['./getting-started.component.scss'] 9 | }) 10 | export class GettingStartedComponent implements OnInit { 11 | 12 | constructor(private titleService:Title) { } 13 | 14 | ngOnInit() { 15 | this.titleService.setTitle('Getting Started | ng2-avatar'); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/module/component/avatar.component.html: -------------------------------------------------------------------------------- 1 |
9 | {{name}} | {{letter}} 13 | {{letter}} 14 |
15 | -------------------------------------------------------------------------------- /demo/src/hmr.ts: -------------------------------------------------------------------------------- 1 | import { NgModuleRef, ApplicationRef } from '@angular/core'; 2 | import { createNewHosts } from '@angularclass/hmr'; 3 | 4 | export const hmrBootstrap = (module: any, bootstrap: () => Promise>) => { 5 | let ngModule: NgModuleRef; 6 | module.hot.accept(); 7 | bootstrap().then(mod => ngModule = mod); 8 | module.hot.dispose(() => { 9 | const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef); 10 | const elements = appRef.components.map(c => c.location.nativeElement); 11 | const makeVisible = createNewHosts(elements); 12 | ngModule.destroy(); 13 | makeVisible(); 14 | }); 15 | }; -------------------------------------------------------------------------------- /src/module/avatar.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule, ModuleWithProviders } from '@angular/core'; 3 | 4 | import { AvatarComponent } from './component/avatar.component'; 5 | 6 | // Export module's public API 7 | export { AvatarComponent } from './component/avatar.component'; 8 | 9 | 10 | @NgModule({ 11 | imports: [ 12 | CommonModule 13 | ], 14 | exports: [ 15 | AvatarComponent 16 | ], 17 | declarations: [ 18 | AvatarComponent 19 | ] 20 | }) 21 | export class AvatarModule { 22 | static forRoot(): ModuleWithProviders { 23 | return { 24 | ngModule: AvatarModule, 25 | providers: [] 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demo/src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; 4 | 5 | import { HeaderComponent } from './header/header.component'; 6 | import { FooterComponent } from './footer/footer.component'; 7 | import { ContentWrapperComponent } from './content-wrapper/content-wrapper.component'; 8 | 9 | @NgModule({ 10 | imports: [RouterModule, NgbCollapseModule.forRoot() ], 11 | exports: [HeaderComponent, FooterComponent, ContentWrapperComponent], 12 | declarations: [HeaderComponent, FooterComponent, ContentWrapperComponent], 13 | providers: [], 14 | }) 15 | export class AppSharedModule { } 16 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "declaration": true, 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "noImplicitAny": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "rootDir": "./", 14 | "baseUrl": "", 15 | "skipLibCheck": true, 16 | "stripInternal": true, 17 | "lib": [ 18 | "es2015", 19 | "dom" 20 | ], 21 | "typeRoots": [ 22 | "../node_modules/@types" 23 | ] 24 | }, 25 | "awesomeTypescriptLoaderOptions": { 26 | "useWebpackText": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /demo/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject, PLATFORM_ID } from '@angular/core'; 2 | import { Router, NavigationEnd } from '@angular/router'; 3 | import { isPlatformBrowser } from '@angular/common'; 4 | import 'rxjs/add/operator/filter'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.scss'] 10 | }) 11 | export class AppComponent { 12 | 13 | constructor(private router: Router, @Inject(PLATFORM_ID) private platformId: Object) { 14 | 15 | this.router.events.filter(event => event instanceof NavigationEnd).subscribe(event => { 16 | if (isPlatformBrowser(this.platformId)) { 17 | window.scroll(0, 0); 18 | } 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | 10 | # IDEs and editors 11 | /.idea 12 | .project 13 | .classpath 14 | .c9/ 15 | *.launch 16 | .settings/ 17 | *.sublime-workspace 18 | 19 | # IDE - VSCode 20 | .vscode/* 21 | !.vscode/settings.json 22 | !.vscode/tasks.json 23 | !.vscode/launch.json 24 | !.vscode/extensions.json 25 | 26 | # misc 27 | /.sass-cache 28 | /connect.lock 29 | /coverage 30 | /libpeerconnection.log 31 | npm-debug.log 32 | yarn-error.log 33 | testem.log 34 | /typings 35 | /config/gulp-tasks/README.md 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /demo/src/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ServerModule} from '@angular/platform-server'; 3 | 4 | import {AppModule} from './app.module'; 5 | import {AppComponent} from './app.component'; 6 | import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | // The AppServerModule should import your AppModule followed 11 | // by the ServerModule from @angular/platform-server. 12 | AppModule, 13 | ServerModule, 14 | ModuleMapLoaderModule 15 | ], 16 | // Since the bootstrapped component is not inherited from your 17 | // imported AppModule, it needs to be repeated here. 18 | bootstrap: [AppComponent], 19 | }) 20 | export class AppServerModule { } 21 | -------------------------------------------------------------------------------- /config/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | Error.stackTraceLimit = Infinity; 2 | 3 | require('core-js/es6'); 4 | require('core-js/es7/reflect'); 5 | 6 | require('zone.js/dist/zone'); 7 | require('zone.js/dist/long-stack-trace-zone'); 8 | require('zone.js/dist/proxy'); 9 | require('zone.js/dist/sync-test'); 10 | require('zone.js/dist/jasmine-patch'); 11 | require('zone.js/dist/async-test'); 12 | require('zone.js/dist/fake-async-test'); 13 | 14 | var appContext = require.context('../src', true, /\.spec\.ts/); 15 | 16 | appContext.keys().forEach(appContext); 17 | 18 | var testing = require('@angular/core/testing'); 19 | var browser = require('@angular/platform-browser-dynamic/testing'); 20 | 21 | testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting()); 22 | -------------------------------------------------------------------------------- /src/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "declaration": true, 9 | "experimentalDecorators": true, 10 | "noImplicitAny": false, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "rootDir": "./", 13 | "baseUrl": "", 14 | "skipLibCheck": true, 15 | "stripInternal": true, 16 | "outDir": "../tmp/lib-es5/", 17 | "lib": [ 18 | "es2015", 19 | "dom" 20 | ] 21 | }, 22 | "files": [ 23 | "./index.ts" 24 | ], 25 | 26 | "angularCompilerOptions": { 27 | "strictMetadataEmit": true, 28 | "skipTemplateCodegen": true, 29 | "genDir": "../tmp/lib-gen-dir/" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo/src/app/shared/footer/footer.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DebugElement } from '@angular/core'; 3 | 4 | import { FooterComponent } from './footer.component'; 5 | 6 | describe('FooterComponent', () => { 7 | let component: FooterComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [FooterComponent] 13 | }) 14 | .compileComponents() 15 | .then(() => { 16 | fixture = TestBed.createComponent(FooterComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | })); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /demo/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | import { hmrBootstrap } from './hmr'; 8 | 9 | if (environment.production) { 10 | enableProdMode(); 11 | } 12 | 13 | const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule); 14 | 15 | if (environment.hmr) { 16 | if (module[ 'hot' ]) { 17 | hmrBootstrap(module, bootstrap); 18 | } else { 19 | console.error('HMR is not enabled for webpack-dev-server!'); 20 | console.log('Are you using the --hmr flag for ng serve?'); 21 | } 22 | } else { 23 | bootstrap().catch(err => console.log(err)); 24 | } 25 | -------------------------------------------------------------------------------- /demo/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /demo/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, ViewChild} from '@angular/core'; 2 | import { Title } from '@angular/platform-browser'; 3 | 4 | @Component({ 5 | selector: 'app-home', 6 | templateUrl: './home.component.html', 7 | styleUrls: ['./home.component.scss'] 8 | }) 9 | export class HomeComponent implements OnInit { 10 | public email: string = null; 11 | public name: string = null; 12 | public size: number = 100; 13 | public background: string = '#cf2c4b'; 14 | public displayType: string = null; 15 | public letter: string = '?'; 16 | 17 | @ViewChild('avatar') private elAvatar : any; 18 | 19 | constructor(private titleService:Title) { } 20 | 21 | ngOnInit() { 22 | this.titleService.setTitle('Home | ng2-avatar'); 23 | } 24 | 25 | changeData() { 26 | this.elAvatar.ngOnInit(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /demo/src/app/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DebugElement } from '@angular/core'; 3 | 4 | import { HomeComponent } from './home.component'; 5 | import { LibModule } from 'ng2-avatar'; 6 | 7 | describe('HomeComponent', () => { 8 | let component: HomeComponent; 9 | let fixture: ComponentFixture; 10 | 11 | beforeEach(async(() => { 12 | TestBed.configureTestingModule({ 13 | imports: [ 14 | LibModule.forRoot(),], 15 | declarations: [HomeComponent] 16 | }) 17 | .compileComponents() 18 | .then(() => { 19 | fixture = TestBed.createComponent(HomeComponent); 20 | component = fixture.componentInstance; 21 | }); 22 | })); 23 | 24 | it('should create', () => { 25 | expect(component).toBeTruthy(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DebugElement } from '@angular/core'; 3 | 4 | import { GettingStartedComponent } from './getting-started.component'; 5 | 6 | describe('GettingStartedComponent', () => { 7 | let component: GettingStartedComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [GettingStartedComponent] 13 | }) 14 | .compileComponents() 15 | .then(() => { 16 | fixture = TestBed.createComponent(GettingStartedComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | })); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /demo/src/app/shared/content-wrapper/content-wrapper.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DebugElement } from '@angular/core'; 3 | 4 | import { ContentWrapperComponent } from './content-wrapper.component'; 5 | 6 | describe('ContentWrapperComponent', () => { 7 | let component: ContentWrapperComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ContentWrapperComponent] 13 | }) 14 | .compileComponents() 15 | .then(() => { 16 | fixture = TestBed.createComponent(ContentWrapperComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | })); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-ngx-library": { 3 | "version": "5.4.0", 4 | "authorName": "Nico Swiatecki", 5 | "authorEmail": "nico@devninjas.io", 6 | "githubUsername": "snics", 7 | "githubRepoName": "ng2-avatar", 8 | "projectName": "ng2-avatar", 9 | "projectVersion": "2.1.1", 10 | "projectDescription": "Angular Avatar (ng2-avatar) is a simple and lightweight avatar component", 11 | "projectKeywords": [ 12 | "ng", 13 | "angular", 14 | "library" 15 | ], 16 | "ngVersion": "2.0.0", 17 | "ngModules": [ 18 | "core", 19 | "common" 20 | ], 21 | "otherDependencies": [ 22 | "ts-md5" 23 | ], 24 | "dependenciesRange": "^", 25 | "ngPrefix": "ng2-avatar", 26 | "useGreenkeeper": false, 27 | "useCompodoc": true, 28 | "enforceNgGitCommitMsg": true, 29 | "exclusions": [ 30 | "src/tsconfig.lib.es5.json" 31 | ] 32 | } 33 | } -------------------------------------------------------------------------------- /demo/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demo/src/app/shared/header/header.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 20 |
-------------------------------------------------------------------------------- /demo/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | 2 | import { NgModule } from '@angular/core'; 3 | import { HttpModule } from '@angular/http'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { BrowserModule } from '@angular/platform-browser'; 6 | 7 | import { AppRoutingModule } from './app-routing.module'; 8 | import { AppSharedModule } from './shared/shared.module'; 9 | import { HomeModule } from './home/home.module'; 10 | import { AppComponent } from './app.component'; 11 | 12 | @NgModule({ 13 | declarations: [ 14 | AppComponent 15 | ], 16 | imports: [ 17 | // Add .withServerTransition() to support Universal rendering. 18 | // The application ID can be any identifier which is unique on 19 | // the page. 20 | BrowserModule.withServerTransition({appId: 'ng2-avatar-demo-id'}), 21 | FormsModule, 22 | HttpModule, 23 | AppRoutingModule, 24 | AppSharedModule, 25 | HomeModule 26 | ], 27 | providers: [], 28 | bootstrap: [AppComponent] 29 | }) 30 | export class AppModule { } 31 | -------------------------------------------------------------------------------- /demo/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /demo/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | @import 'variables'; 4 | @import '~bootstrap/scss/bootstrap'; 5 | @import '~font-awesome/scss/font-awesome'; 6 | @import "~include-media/dist/include-media"; 7 | // 'include-media' plugging into Bootstrap 4's Grid Breakpoints map 8 | 9 | $breakpoints: $grid-breakpoints; 10 | @include media("=md") { 30 | .jumbotron { 31 | // margin-top: 3.4rem; 32 | margin-bottom: 0rem; 33 | h1 { 34 | font-size: 3.6rem; 35 | margin-bottom: 1.8rem; 36 | } 37 | p { 38 | font-size: 1.4rem; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # ng2-avatar-demo 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Nico Swiatecki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /demo/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | ### Bug Report or Feature Request (mark with an `x`) 5 | ``` 6 | - [ ] bug report -> please search issues before submitting 7 | - [ ] feature request 8 | ``` 9 | 10 | ### OS and Version? 11 | 14 | 15 | ### Versions 16 | 20 | 21 | 22 | ### Repro steps 23 | 28 | 29 | 30 | ### The log given by the failure 31 | 32 | 33 | 34 | ### Desired functionality 35 | 39 | 40 | 41 | ### Mention any other details that might be useful 42 | 43 | -------------------------------------------------------------------------------- /demo/webpack.server.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: { 6 | // This is our Express server for Dynamic universal 7 | server: './server.ts', 8 | // This is an example of Static prerendering (generative) 9 | prerender: './prerender.ts' 10 | }, 11 | resolve: { extensions: ['.js', '.ts'] }, 12 | target: 'node', 13 | // this makes sure we include node_modules and other 3rd party libraries 14 | externals: [/(node_modules|main\..*\.js)/], 15 | output: { 16 | path: path.join(__dirname, 'dist'), 17 | filename: '[name].js' 18 | }, 19 | module: { 20 | rules: [ 21 | { test: /\.ts$/, loader: 'ts-loader' } 22 | ] 23 | }, 24 | plugins: [ 25 | // Temporary Fix for issue: https://github.com/angular/angular/issues/11580 26 | // for "WARNING Critical dependency: the request of a dependency is an expression" 27 | new webpack.ContextReplacementPlugin( 28 | /(.+)?angular(\\|\/)core(.+)?/, 29 | path.join(__dirname, 'src'), // location of your src 30 | {} // a map of your routes 31 | ), 32 | new webpack.ContextReplacementPlugin( 33 | /(.+)?express(\\|\/)(.+)?/, 34 | path.join(__dirname, 'src'), 35 | {} 36 | ) 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /demo/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | import { Router } from '@angular/router'; 3 | import { Component } from '@angular/core'; 4 | import { TestBed, async } from '@angular/core/testing'; 5 | import { AppComponent } from './app.component'; 6 | import { FooterComponent } from './shared/footer/footer.component'; 7 | 8 | import { RouterOutletStubComponent, RouterLinkStubDirective } from '../testing/router-stubs'; 9 | import { Observable } from 'rxjs/Observable'; 10 | import 'rxjs/add/observable/of'; 11 | 12 | @Component({ selector: 'app-header', template: '' }) 13 | class HeaderStubComponent { } 14 | 15 | class RouterStub { 16 | events: Observable = Observable.of(); 17 | } 18 | 19 | describe('AppComponent', () => { 20 | beforeEach(async(() => { 21 | TestBed.configureTestingModule({ 22 | declarations: [ 23 | AppComponent, 24 | HeaderStubComponent, 25 | FooterComponent, 26 | RouterOutletStubComponent 27 | ], 28 | providers: [ 29 | { provide: Router, useClass: RouterStub } 30 | ] 31 | }); 32 | })); 33 | 34 | it('should create', async(() => { 35 | let fixture = TestBed.createComponent(AppComponent); 36 | let app = fixture.debugElement.componentInstance; 37 | expect(app).toBeTruthy(); 38 | })); 39 | 40 | }); 41 | -------------------------------------------------------------------------------- /demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ng2-avatar 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Loading... 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demo/src/testing/router-stubs.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Component, Directive, Injectable, Input } from '@angular/core'; 3 | import { NavigationExtras } from '@angular/router'; 4 | // Only implements params and part of snapshot.params 5 | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 6 | 7 | // export for convenience. 8 | export { ActivatedRoute, Router, RouterLink, RouterOutlet } from '@angular/router'; 9 | 10 | 11 | @Directive({ 12 | selector: '[routerLink]', 13 | host: { 14 | '(click)': 'onClick()' 15 | } 16 | }) 17 | export class RouterLinkStubDirective { 18 | @Input('routerLink') linkParams: any; 19 | navigatedTo: any = null; 20 | 21 | onClick() { 22 | this.navigatedTo = this.linkParams; 23 | } 24 | } 25 | 26 | @Directive({ 27 | selector: '[routerLinkActive]' 28 | }) 29 | export class RouterLinkActiveStubDirective { 30 | @Input('routerLinkActive') linkParams: any; 31 | } 32 | 33 | @Component({ selector: 'router-outlet', template: '' }) 34 | export class RouterOutletStubComponent { } 35 | 36 | @Injectable() 37 | export class RouterStub { 38 | navigate(commands: any[], extras?: NavigationExtras) { } 39 | } 40 | 41 | 42 | @Injectable() 43 | export class ActivatedRouteStub { 44 | 45 | // ActivatedRoute.params is Observable 46 | private subject = new BehaviorSubject(this.testParams); 47 | params = this.subject.asObservable(); 48 | 49 | // Test parameters 50 | private _testParams: {}; 51 | get testParams() { return this._testParams; } 52 | set testParams(params: {}) { 53 | this._testParams = params; 54 | this.subject.next(params); 55 | } 56 | 57 | // ActivatedRoute.snapshot.params 58 | get snapshot() { 59 | return { params: this.testParams }; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demo/prerender.ts: -------------------------------------------------------------------------------- 1 | // Load zone.js for the server. 2 | import 'zone.js/dist/zone-node'; 3 | import 'reflect-metadata'; 4 | import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; 5 | import { join } from 'path'; 6 | 7 | import { enableProdMode } from '@angular/core'; 8 | // Faster server renders w/ Prod mode (dev mode never needed) 9 | enableProdMode(); 10 | 11 | // Express Engine 12 | import { ngExpressEngine } from '@nguniversal/express-engine'; 13 | // Import module map for lazy loading 14 | import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; 15 | import { renderModuleFactory } from '@angular/platform-server'; 16 | import { ROUTES } from './static.paths'; 17 | 18 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 19 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle'); 20 | 21 | const BROWSER_FOLDER = join(process.cwd(), 'dist', 'browser'); 22 | 23 | // Load the index.html file containing referances to your application bundle. 24 | const index = readFileSync(join(BROWSER_FOLDER, 'index.html'), 'utf8'); 25 | 26 | let previousRender = Promise.resolve(); 27 | 28 | // Iterate each route path 29 | ROUTES.forEach(route => { 30 | var fullPath = join(BROWSER_FOLDER, route); 31 | 32 | // Make sure the directory structure is there 33 | if(!existsSync(fullPath)){ 34 | mkdirSync(fullPath); 35 | } 36 | 37 | // Writes rendered HTML to index.html, replacing the file if it already exists. 38 | previousRender = previousRender.then(_ => renderModuleFactory(AppServerModuleNgFactory, { 39 | document: index, 40 | url: route, 41 | extraProviders: [ 42 | provideModuleMap(LAZY_MODULE_MAP) 43 | ] 44 | })).then(html => writeFileSync(join(fullPath, 'index.html'), html)); 45 | }); 46 | -------------------------------------------------------------------------------- /config/helpers.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const path = require('path'); 3 | const exec = require('child_process').exec; 4 | 5 | const _root = path.resolve(__dirname, '..'); 6 | 7 | 8 | /** 9 | * Plaform independant path to an executable cmd 10 | * @param {string} path 11 | */ 12 | platformPath = (path) => { 13 | return /^win/.test(os.platform()) ? `${path}.cmd` : path; 14 | }; 15 | 16 | /** 17 | * 18 | * @param {string[]} args 19 | */ 20 | rootDir = (...args) => { 21 | return path.join.apply(path, [_root].concat(...args)); 22 | }; 23 | 24 | /** 25 | * 26 | * @param {string} cmd 27 | */ 28 | binPath = (cmd) => { 29 | return platformPath(`/node_modules/.bin/${cmd}`); 30 | }; 31 | 32 | /** 33 | * Promisified child_process.exec 34 | * 35 | * @param cmd 36 | * @param opts See child_process.exec node docs 37 | * @returns {Promise} 38 | */ 39 | execp = (cmd, opts) => { 40 | opts = Object.assign(opts || {}, { 41 | stdout: process.stdout, 42 | stderr: process.stderr 43 | }); 44 | return new Promise((resolve, reject) => { 45 | const child = exec(cmd, opts, 46 | (err, stdout, stderr) => err ? reject(err.code) : resolve(0)); 47 | 48 | if (opts.stdout) { 49 | child.stdout.pipe(opts.stdout); 50 | } 51 | if (opts.stderr) { 52 | child.stderr.pipe(opts.stderr); 53 | } 54 | }); 55 | }; 56 | 57 | /** 58 | * Install dependencies using yarn, if present, or npm otherwise. 59 | * @param opts See child_process.exec node docs 60 | * @returns {Promise} 61 | */ 62 | installDependencies = (opts) => { 63 | return execp('yarn -v') // first try to install deps using yarn 64 | .then(exitCode => exitCode === 0 ? execp('yarn install', opts) : execp('npm install', opts)); 65 | }; 66 | 67 | var exports = module.exports = { 68 | root: rootDir, 69 | execp: execp, 70 | binPath: binPath, 71 | platformPath: platformPath, 72 | installDependencies: installDependencies 73 | }; 74 | -------------------------------------------------------------------------------- /demo/server.ts: -------------------------------------------------------------------------------- 1 | // These are important and needed before anything else 2 | import 'zone.js/dist/zone-node'; 3 | import 'reflect-metadata'; 4 | 5 | import { renderModuleFactory } from '@angular/platform-server'; 6 | import { enableProdMode } from '@angular/core'; 7 | 8 | import * as express from 'express'; 9 | import { join } from 'path'; 10 | import { readFileSync } from 'fs'; 11 | 12 | // Faster server renders w/ Prod mode (dev mode never needed) 13 | enableProdMode(); 14 | 15 | // Express server 16 | const app = express(); 17 | 18 | const PORT = process.env.PORT || 4000; 19 | const DIST_FOLDER = join(process.cwd(), 'dist'); 20 | 21 | // Our index.html we'll use as our template 22 | const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString(); 23 | 24 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 25 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle'); 26 | 27 | const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader'); 28 | 29 | app.engine('html', (_, options, callback) => { 30 | renderModuleFactory(AppServerModuleNgFactory, { 31 | // Our index.html 32 | document: template, 33 | url: options.req.url, 34 | // DI so that we can get lazy-loading to work differently (since we need it to just instantly render it) 35 | extraProviders: [ 36 | provideModuleMap(LAZY_MODULE_MAP) 37 | ] 38 | }).then(html => { 39 | callback(null, html); 40 | }); 41 | }); 42 | 43 | app.set('view engine', 'html'); 44 | app.set('views', join(DIST_FOLDER, 'browser')); 45 | 46 | // Server static files from /browser 47 | app.get('*.*', express.static(join(DIST_FOLDER, 'browser'))); 48 | 49 | // All regular routes use the Universal engine 50 | app.get('*', (req, res) => { 51 | res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req }); 52 | }); 53 | 54 | // Start up the Node server 55 | app.listen(PORT, () => { 56 | console.log(`Node server listening on http://localhost:${PORT}`); 57 | }); 58 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-avatar-demo", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "description": "Demo app for ng2-avatar", 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve", 9 | "build": "ng build", 10 | "test": "ng test", 11 | "lint": "ng lint", 12 | "e2e": "ng e2e", 13 | "postinstall": "npm link ng2-avatar" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@angular/animations": "^5.0.0", 18 | "@angular/common": "^5.0.0", 19 | "@angular/compiler": "^5.0.0", 20 | "@angular/core": "^5.0.0", 21 | "@angular/forms": "^5.0.0", 22 | "@angular/http": "^5.0.0", 23 | "@angular/platform-browser": "^5.0.0", 24 | "@angular/platform-browser-dynamic": "^5.0.0", 25 | "@angular/router": "^5.0.0", 26 | "@ng-bootstrap/ng-bootstrap": "1.0.0-beta.3", 27 | "bootstrap": "4.1.3", 28 | "core-js": "^2.4.1", 29 | "font-awesome": "^4.7.0", 30 | "include-media": "^1.4.9", 31 | "rxjs": "^5.5.2", 32 | "zone.js": "^0.8.14", 33 | "@angular/platform-server": "^5.0.0" 34 | }, 35 | "devDependencies": { 36 | "@angular/cli": "^1.6.0", 37 | "@angular/compiler-cli": "^5.0.0", 38 | "@angular/language-service": "^5.0.0", 39 | "@angularclass/hmr": "~2.1.3", 40 | "@types/jasmine": "~2.5.53", 41 | "@types/jasminewd2": "~2.0.2", 42 | "@types/node": "~6.0.60", 43 | "codelyzer": "^4.0.1", 44 | "jasmine-core": "~2.6.2", 45 | "jasmine-spec-reporter": "~4.1.0", 46 | "karma": "~1.7.0", 47 | "karma-chrome-launcher": "~2.1.1", 48 | "karma-cli": "~1.0.1", 49 | "karma-coverage-istanbul-reporter": "^1.2.1", 50 | "karma-jasmine": "~1.1.0", 51 | "karma-jasmine-html-reporter": "^0.2.2", 52 | "protractor": "~5.1.2", 53 | "ts-node": "~3.2.0", 54 | "tslint": "~5.7.0", 55 | "typescript": "~2.4.2", 56 | "ts-loader": "~2.3.7", 57 | "reflect-metadata": "~0.1.10", 58 | "webpack-node-externals": "~1.6.0", 59 | "express": "^4.16.2", 60 | "@nguniversal/express-engine": "^5.0.0-beta.5", 61 | "@nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.5" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /config/karma.conf.js: -------------------------------------------------------------------------------- 1 | var webpack = require('./webpack.test'); 2 | 3 | module.exports = function (config) { 4 | var _config = { 5 | basePath: '', 6 | 7 | frameworks: ['jasmine'], 8 | 9 | plugins: [ 10 | require('karma-jasmine'), 11 | require('karma-webpack'), 12 | require('karma-coverage'), 13 | require('karma-chrome-launcher'), 14 | require('karma-remap-coverage'), 15 | require('karma-sourcemap-loader'), 16 | require('karma-mocha-reporter'), 17 | require('karma-jasmine-html-reporter'), 18 | ], 19 | 20 | customLaunchers: { 21 | // chrome setup for travis CI 22 | Chrome_travis_ci: { 23 | base: 'Chrome', 24 | flags: ['--no-sandbox'] 25 | } 26 | }, 27 | files: [ 28 | { pattern: './config/karma-test-shim.js', watched: false } 29 | ], 30 | 31 | preprocessors: { 32 | './config/karma-test-shim.js': config.hasCoverage ? ['coverage', 'webpack', 'sourcemap'] : ['webpack', 'sourcemap'] 33 | }, 34 | 35 | webpack: webpack.getConfig(config.hasCoverage, config.autoWatch), 36 | 37 | // Webpack please don't spam the console when running in karma! 38 | webpackMiddleware: { 39 | // webpack-dev-middleware configuration 40 | // i.e. 41 | noInfo: true, 42 | // and use stats to turn off verbose output 43 | stats: { 44 | // options i.e. 45 | chunks: false 46 | } 47 | }, 48 | 49 | // save interim raw coverage report in memory 50 | coverageReporter: { 51 | type: 'in-memory' 52 | }, 53 | 54 | remapCoverageReporter: { 55 | 'text-summary': null, 56 | lcovonly: './coverage/coverage.lcov', 57 | html: './coverage/html' 58 | }, 59 | 60 | mochaReporter: { 61 | output: 'autowatch', 62 | }, 63 | 64 | reporters: config.hasCoverage ? ['mocha', 'kjhtml', 'coverage', 'remap-coverage'] : ['mocha', 'kjhtml'], 65 | port: 9876, 66 | colors: true, 67 | logLevel: config.LOG_INFO, 68 | failOnEmptyTestSuite: false, 69 | autoWatch: false, 70 | browsers: ['Chrome'], 71 | singleRun: true 72 | }; 73 | 74 | config.set(_config); 75 | }; 76 | -------------------------------------------------------------------------------- /demo/.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "ng2-avatar-demo" 5 | }, 6 | "apps": [ 7 | { 8 | "name": "bsr", 9 | "root": "src", 10 | "outDir": "dist/browser", 11 | "assets": [ 12 | "assets", 13 | "favicon.ico" 14 | ], 15 | "index": "index.html", 16 | "main": "main.ts", 17 | "polyfills": "polyfills.ts", 18 | "test": "test.ts", 19 | "tsconfig": "tsconfig.app.json", 20 | "testTsconfig": "tsconfig.spec.json", 21 | "prefix": "app", 22 | "styles": [ 23 | "styles.scss" 24 | ], 25 | "scripts": [], 26 | "environmentSource": "environments/environment.ts", 27 | "environments": { 28 | "dev": "environments/environment.ts", 29 | "hmr": "environments/environment.hmr.ts", 30 | "prod": "environments/environment.prod.ts" 31 | } 32 | }, 33 | { 34 | "name": "ssr", 35 | "root": "src", 36 | "outDir": "dist/server", 37 | "assets": [ 38 | "assets", 39 | "favicon.ico" 40 | ], 41 | "platform": "server", 42 | "index": "index.html", 43 | "main": "main.server.ts", 44 | "test": "test.ts", 45 | "tsconfig": "tsconfig.server.json", 46 | "testTsconfig": "tsconfig.spec.json", 47 | "prefix": "app", 48 | "styles": [ 49 | "styles.scss" 50 | ], 51 | "scripts": [], 52 | "environmentSource": "environments/environment.ts", 53 | "environments": { 54 | "dev": "environments/environment.ts", 55 | "prod": "environments/environment.prod.ts" 56 | } 57 | } 58 | ], 59 | "e2e": { 60 | "protractor": { 61 | "config": "./protractor.conf.js" 62 | } 63 | }, 64 | "lint": [ 65 | { 66 | "project": "src/tsconfig.app.json", 67 | "exclude": "**/node_modules/**" 68 | }, 69 | { 70 | "project": "src/tsconfig.spec.json", 71 | "exclude": "**/node_modules/**" 72 | }, 73 | { 74 | "project": "e2e/tsconfig.e2e.json", 75 | "exclude": "**/node_modules/**" 76 | } 77 | ], 78 | "test": { 79 | "karma": { 80 | "config": "./karma.conf.js" 81 | } 82 | }, 83 | "defaults": { 84 | "styleExt": "scss", 85 | "component": {} 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /demo/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | // import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Required to support Web Animations `@angular/platform-browser/animations`. 51 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 52 | **/ 53 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 54 | 55 | 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /demo/src/app/shared/header/header.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { By } from '@angular/platform-browser'; 3 | import { DebugElement } from '@angular/core'; 4 | 5 | import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; 6 | 7 | import { HeaderComponent } from './header.component'; 8 | import { RouterLinkStubDirective, RouterLinkActiveStubDirective } from './../../../testing/router-stubs'; 9 | 10 | describe('HeaderComponent', () => { 11 | let component: HeaderComponent; 12 | let fixture: ComponentFixture; 13 | 14 | let linkDes: DebugElement[]; 15 | let links: RouterLinkStubDirective[]; 16 | 17 | beforeEach(async(() => { 18 | TestBed.configureTestingModule({ 19 | imports: [ 20 | NgbCollapseModule.forRoot() 21 | ], 22 | declarations: [ 23 | HeaderComponent, 24 | RouterLinkStubDirective, 25 | RouterLinkActiveStubDirective 26 | ] 27 | }) 28 | .compileComponents() 29 | .then(() => { 30 | fixture = TestBed.createComponent(HeaderComponent); 31 | component = fixture.componentInstance; 32 | }); 33 | })); 34 | 35 | beforeEach(() => { 36 | // trigger initial data binding 37 | fixture.detectChanges(); 38 | 39 | // find DebugElements with an attached RouterLinkStubDirective 40 | linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkStubDirective)); 41 | 42 | // get the attached link directive instances using the DebugElement injectors 43 | links = linkDes.map(de => de.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective); 44 | }); 45 | 46 | it('should create', () => { 47 | expect(component).toBeTruthy(); 48 | }); 49 | 50 | it('can get RouterLinks from template', () => { 51 | expect(links.length).toBe(2, 'should have 2 links'); 52 | expect(links[0].linkParams).toBe('/home', '1st link should go to Home'); 53 | expect(links[1].linkParams).toBe('/getting-started', '2nd link should go to GettingStarted'); 54 | }); 55 | 56 | it('can click Home link in template', () => { 57 | const homeLinkDe = linkDes[0]; 58 | const homeLink = links[0]; 59 | 60 | expect(homeLink.navigatedTo).toBeNull('link should not have navigated yet'); 61 | 62 | homeLinkDe.triggerEventHandler('click', null); 63 | fixture.detectChanges(); 64 | 65 | expect(homeLink.navigatedTo).toBe('/home'); 66 | }); 67 | 68 | it('can click GettingStarted link in template', () => { 69 | const gettingStartedLinkDe = linkDes[1]; 70 | const gettingStartedLink = links[1]; 71 | 72 | expect(gettingStartedLink.navigatedTo).toBeNull('link should not have navigated yet'); 73 | 74 | gettingStartedLinkDe.triggerEventHandler('click', null); 75 | fixture.detectChanges(); 76 | 77 | expect(gettingStartedLink.navigatedTo).toBe('/getting-started'); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /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 | "label-undefined": true, 20 | "max-line-length": [ 21 | true, 22 | 140 23 | ], 24 | "member-access": false, 25 | "member-ordering": [ 26 | true, 27 | "static-before-instance", 28 | "variables-before-functions" 29 | ], 30 | "no-arg": true, 31 | "no-bitwise": true, 32 | "no-console": [ 33 | true, 34 | "log", 35 | "debug", 36 | "info", 37 | "time", 38 | "timeEnd", 39 | "trace" 40 | ], 41 | "no-construct": true, 42 | "no-debugger": true, 43 | "no-duplicate-key": true, 44 | "no-duplicate-variable": true, 45 | "no-empty": false, 46 | "no-eval": true, 47 | "no-inferrable-types": true, 48 | "no-shadowed-variable": true, 49 | "no-string-literal": false, 50 | "no-switch-case-fall-through": true, 51 | "no-trailing-whitespace": true, 52 | "no-unused-expression": true, 53 | "no-unused-variable": true, 54 | "no-unreachable": true, 55 | "no-use-before-declare": true, 56 | "no-var-keyword": true, 57 | "object-literal-sort-keys": false, 58 | "one-line": [ 59 | true, 60 | "check-open-brace", 61 | "check-catch", 62 | "check-else", 63 | "check-whitespace" 64 | ], 65 | "quotemark": [ 66 | true, 67 | "single" 68 | ], 69 | "radix": true, 70 | "semicolon": [ 71 | "always" 72 | ], 73 | "triple-equals": [ 74 | true, 75 | "allow-null-check" 76 | ], 77 | "typedef-whitespace": [ 78 | true, 79 | { 80 | "call-signature": "nospace", 81 | "index-signature": "nospace", 82 | "parameter": "nospace", 83 | "property-declaration": "nospace", 84 | "variable-declaration": "nospace" 85 | } 86 | ], 87 | "variable-name": false, 88 | "whitespace": [ 89 | true, 90 | "check-branch", 91 | "check-decl", 92 | "check-operator", 93 | "check-separator", 94 | "check-type" 95 | ], 96 | "directive-selector-prefix": [ 97 | false 98 | ], 99 | "component-selector-prefix": [ 100 | false 101 | ], 102 | "directive-selector-name": [ 103 | true, 104 | "camelCase" 105 | ], 106 | "component-selector-name": [ 107 | true, 108 | "kebab-case" 109 | ], 110 | "directive-selector-type": [ 111 | true, 112 | "attribute" 113 | ], 114 | "component-selector-type": [ 115 | true, 116 | "element" 117 | ], 118 | "use-input-property-decorator": true, 119 | "use-output-property-decorator": true, 120 | "use-host-property-decorator": true, 121 | "no-input-rename": true, 122 | "no-output-rename": true, 123 | "use-life-cycle-interface": true, 124 | "use-pipe-transform-interface": true, 125 | "component-class-suffix": true, 126 | "directive-class-suffix": true, 127 | "templates-use-public": true, 128 | "invoke-injectable": true 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [2.3.1](https://github.com/snics/ng2-avatar/compare/v2.3.0...v2.3.1) (2018-04-02) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * **lint:** add missing semicolon ([bacdaf6](https://github.com/snics/ng2-avatar/commit/bacdaf6)) 8 | * **name:** use first character as fallback for non-ASCII case ([5b32259](https://github.com/snics/ng2-avatar/commit/5b32259)) 9 | 10 | 11 | 12 | 13 | # [2.3.0](https://github.com/snics/ng2-avatar/compare/v2.2.1...v2.3.0) (2018-03-29) 14 | 15 | 16 | ### Bug Fixes 17 | 18 | * **@dist:** added dist again to gitignore ([5a81fe8](https://github.com/snics/ng2-avatar/commit/5a81fe8)) 19 | * **ssr:** transpiled all js file to es5 using babel preset es2015 (new gulp task) ([a2b5d5b](https://github.com/snics/ng2-avatar/commit/a2b5d5b)) 20 | 21 | 22 | 23 | 24 | ## [2.2.1](https://github.com/snics/ng2-avatar/compare/v2.2.0...v2.2.1) (2017-12-21) 25 | 26 | 27 | ### Bug Fixes 28 | 29 | * **build:** not exported Md5 class ([be6f241](https://github.com/snics/ng2-avatar/commit/be6f241)) 30 | 31 | 32 | 33 | 34 | # [2.2.0](https://github.com/snics/ng2-avatar/compare/v2.1.1...v2.2.0) (2017-12-20) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * **console:** remove console logging, ([f5d605f](https://github.com/snics/ng2-avatar/commit/f5d605f)), closes [#6](https://github.com/snics/ng2-avatar/issues/6) 40 | * **ui:** scrollbar is no longer displayed on windows ([22eac5e](https://github.com/snics/ng2-avatar/commit/22eac5e)) 41 | 42 | 43 | ### Features 44 | 45 | * **demo:** add demo page with playground and getting started instructions ([5881694](https://github.com/snics/ng2-avatar/commit/5881694)) 46 | * **doc:** Add documentations description for avatar ([65b0d55](https://github.com/snics/ng2-avatar/commit/65b0d55)) 47 | 48 | 49 | 50 | 51 | ## [2.1.1](https://github.com/snics/ng2-avatar/compare/v2.1.0...v2.1.1) (2017-10-06) 52 | 53 | 54 | 55 | 56 | # [2.1.0](https://github.com/snics/ng2-avatar/compare/v2.0.5...v2.1.0) (2017-10-06) 57 | 58 | 59 | 60 | 61 | ## [2.0.5](https://github.com/snics/ng2-avatar/compare/v2.0.4...v2.0.5) (2017-08-28) 62 | 63 | 64 | 65 | 66 | ## [2.0.4](https://github.com/snics/ng2-avatar/compare/v2.0.3...v2.0.4) (2017-08-28) 67 | 68 | 69 | 70 | 71 | ## [2.0.3](https://github.com/snics/ng2-avatar/compare/v2.0.2...v2.0.3) (2017-08-28) 72 | 73 | 74 | 75 | 76 | ## [2.0.2](https://github.com/snics/ng2-avatar/compare/v2.0.1...v2.0.2) (2017-08-28) 77 | 78 | 79 | 80 | 81 | ## [2.0.1](https://github.com/snics/ng2-avatar/compare/v2.0.0...v2.0.1) (2017-08-28) 82 | 83 | 84 | 85 | 86 | # [2.0.0](https://github.com/snics/ng2-avatar/compare/v1.1.0...v2.0.0) (2017-08-28) 87 | 88 | 89 | 90 | 91 | # [1.1.0](https://github.com/snics/ng2-avatar/compare/v1.0.4...v1.1.0) (2017-08-28) 92 | 93 | 94 | 95 | 96 | ## [1.0.4](https://github.com/snics/ng2-avatar/compare/v1.0.3...v1.0.4) (2017-08-28) 97 | 98 | 99 | 100 | 101 | ## [1.0.3](https://github.com/snics/ng2-avatar/compare/v1.0.2...v1.0.3) (2017-05-12) 102 | 103 | 104 | 105 | 106 | ## [1.0.2](https://github.com/snics/ng2-avatar/compare/v1.0.1...v1.0.2) (2017-05-12) 107 | 108 | 109 | 110 | 111 | ## 1.0.1 (2017-05-12) 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /demo/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs", 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": [ 26 | true, 27 | "spaces" 28 | ], 29 | "interface-over-type-literal": true, 30 | "label-position": true, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-access": false, 36 | "member-ordering": [ 37 | true, 38 | { 39 | "order": [ 40 | "static-field", 41 | "instance-field", 42 | "static-method", 43 | "instance-method" 44 | ] 45 | } 46 | ], 47 | "no-arg": true, 48 | "no-bitwise": true, 49 | "no-console": [ 50 | true, 51 | "debug", 52 | "info", 53 | "time", 54 | "timeEnd", 55 | "trace" 56 | ], 57 | "no-construct": true, 58 | "no-debugger": true, 59 | "no-duplicate-super": true, 60 | "no-empty": false, 61 | "no-empty-interface": true, 62 | "no-eval": true, 63 | "no-inferrable-types": [ 64 | true, 65 | "ignore-params" 66 | ], 67 | "no-misused-new": true, 68 | "no-non-null-assertion": true, 69 | "no-shadowed-variable": true, 70 | "no-string-literal": false, 71 | "no-string-throw": true, 72 | "no-switch-case-fall-through": true, 73 | "no-trailing-whitespace": true, 74 | "no-unnecessary-initializer": true, 75 | "no-unused-expression": true, 76 | "no-use-before-declare": true, 77 | "no-var-keyword": true, 78 | "object-literal-sort-keys": false, 79 | "one-line": [ 80 | true, 81 | "check-open-brace", 82 | "check-catch", 83 | "check-else", 84 | "check-whitespace" 85 | ], 86 | "prefer-const": true, 87 | "quotemark": [ 88 | true, 89 | "single" 90 | ], 91 | "radix": true, 92 | "semicolon": [ 93 | true, 94 | "always" 95 | ], 96 | "triple-equals": [ 97 | true, 98 | "allow-null-check" 99 | ], 100 | "typedef-whitespace": [ 101 | true, 102 | { 103 | "call-signature": "nospace", 104 | "index-signature": "nospace", 105 | "parameter": "nospace", 106 | "property-declaration": "nospace", 107 | "variable-declaration": "nospace" 108 | } 109 | ], 110 | "typeof-compare": true, 111 | "unified-signatures": true, 112 | "variable-name": false, 113 | "whitespace": [ 114 | true, 115 | "check-branch", 116 | "check-decl", 117 | "check-operator", 118 | "check-separator", 119 | "check-type" 120 | ], 121 | "directive-selector": [ 122 | true, 123 | "attribute", 124 | "app", 125 | "camelCase" 126 | ], 127 | "component-selector": [ 128 | true, 129 | "element", 130 | "app", 131 | "kebab-case" 132 | ], 133 | "no-output-on-prefix": true, 134 | "use-input-property-decorator": true, 135 | "use-output-property-decorator": true, 136 | "use-host-property-decorator": true, 137 | "no-input-rename": true, 138 | "no-output-rename": true, 139 | "use-life-cycle-interface": true, 140 | "use-pipe-transform-interface": true, 141 | "component-class-suffix": true, 142 | "directive-class-suffix": true 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /demo/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |

ng2-avatar

9 |

Angular2+ Avatar (ng2-avatar) is a simple and lightweight avatar component

10 |

Scroll down to see it in action!

11 |

12 | Code on Github 13 | Documentation 14 |

15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |

Playground

25 | 26 |
27 |
28 |
29 | 30 | 35 |
36 | 37 |
38 | 39 | 44 |
45 | 46 |
47 | 48 | 54 |
55 | 56 |
57 | 58 | 64 |
65 | 66 | 67 |
68 | 69 | 76 |
77 | 78 |
79 | 80 | 84 |
85 |
86 | 87 |
88 | 95 |
96 |
97 |
98 |
99 |
100 | -------------------------------------------------------------------------------- /src/module/component/avatar.component.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable component-selector-name */ 2 | 3 | import {Component, Input, OnChanges, OnInit} from '@angular/core'; 4 | import {Md5} from '../Md5'; 5 | 6 | /** 7 | * The main component for the avatar 8 | * 9 | * @example 10 | * 11 | * 12 | */ 13 | @Component({ 14 | selector: 'avatar', 15 | templateUrl: './avatar.component.html', 16 | styleUrls: ['./avatar.component.scss'] 17 | }) 18 | export class AvatarComponent implements OnInit, OnChanges { 19 | 20 | /** 21 | * The user email adresse for Gravatar.com 22 | */ 23 | @Input('email') email: string; 24 | 25 | /** 26 | * The full name of the user for the avatar letter 27 | * @type {string} 28 | */ 29 | @Input('name') name: string; 30 | 31 | /** 32 | * The display size 33 | * @type {number} 34 | */ 35 | @Input('size') size = 100; 36 | 37 | /** 38 | * Value to set a fixed color via HEX code 39 | * @type {string} 40 | */ 41 | @Input('background') background = this.getRandomColor(); 42 | 43 | /** 44 | * Value to set the display type 45 | * @type {string} - none|circle|rounded 46 | */ 47 | @Input('displayType') displayType = 'none'; 48 | 49 | /** 50 | * Value to set a default letter 51 | * @type {string} 52 | */ 53 | @Input('letter') letter = '?'; 54 | 55 | /** 56 | * Value to set a default protocol 57 | * @type {string|null} - http|https 58 | */ 59 | @Input('defaultProtocol') defaultProtocol: string = null; 60 | 61 | gravatarUrl: string; 62 | displayImage = true; 63 | fontSize = 49; 64 | fontColor = '#FFFFFF'; 65 | props: any = null; 66 | 67 | constructor() { 68 | } 69 | 70 | /** 71 | * Randomly generates a HEX color 72 | * @return {string} 73 | */ 74 | getRandomColor(): string { 75 | const letters = '0123456789ABCDEF'.split(''); 76 | let color = '#'; 77 | for (let i = 0; i < 6; i++) { 78 | color += letters[Math.floor(Math.random() * 16)]; 79 | } 80 | return color; 81 | } 82 | 83 | /** 84 | * Set the avatar letter based on full name or email 85 | */ 86 | getLetter(): void { 87 | if (this.name && this.name.length) { 88 | const nameInitials = this.name.match(/\b(\w)/g); 89 | if (nameInitials) { 90 | const nameLetters = nameInitials.slice(0, 3).join(''); 91 | this.letter = nameLetters.toUpperCase(); 92 | } else { 93 | this.letter = this.name[0]; 94 | } 95 | } else if (this.email && this.email.length) { 96 | const emailInitials = this.email.split('@')[0].match(/\b(\w)/g); 97 | const emailLetters = emailInitials.slice(0, 3).join(''); 98 | this.letter = emailLetters.toUpperCase(); 99 | } 100 | } 101 | 102 | /** 103 | * Create a Gravatar API url 104 | */ 105 | getAvatar(): void { 106 | // tslint:disable-next-line 107 | if (this.email && /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(this.email)) { 108 | const hash = Md5.init(this.email); 109 | 110 | const protocol = this.defaultProtocol ? this.defaultProtocol + ':' : ''; 111 | this.gravatarUrl = `${protocol}//www.gravatar.com/avatar/${hash}?s=${this.size}&d=404`; 112 | this.displayImage = true; 113 | } else { 114 | this.displayImage = false; 115 | } 116 | } 117 | 118 | setCssProps() { 119 | this.fontSize = (39 * this.size) / 100; 120 | this.props = { 121 | size: `${this.size}px`, 122 | lineheight: `${this.size}px`, 123 | background: this.background, 124 | fontSize: `${this.fontSize}px` 125 | }; 126 | 127 | switch (this.displayType) { 128 | case 'rounded': 129 | this.props['borderradius'] = '5%'; 130 | break; 131 | case 'circle': 132 | this.props['borderradius'] = '50%'; 133 | break; 134 | default: 135 | this.props['borderradius'] = '0'; 136 | } 137 | } 138 | 139 | /** 140 | * Set avatar size, background and display type 141 | */ 142 | ngOnInit() { 143 | this.setCssProps(); 144 | 145 | this.getLetter(); 146 | this.getAvatar(); 147 | } 148 | 149 | /** 150 | * Updates avatar image and letter on email updates 151 | */ 152 | ngOnChanges() { 153 | this.getAvatar(); 154 | this.getLetter(); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /config/webpack.test.js: -------------------------------------------------------------------------------- 1 | const helpers = require('./helpers'); 2 | const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); 3 | const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'); 4 | const { CheckerPlugin } = require('awesome-typescript-loader'); 5 | 6 | const getConfig = (hasCoverage, isTddMode) => { 7 | 8 | let extraRules = []; 9 | if (hasCoverage) { 10 | extraRules.push( 11 | { 12 | enforce: 'post', 13 | test: /\.(js|ts)$/, 14 | loader: 'istanbul-instrumenter-loader', 15 | include: helpers.root('src'), 16 | exclude: [ 17 | /\.(e2e|spec)\.ts$/, 18 | /node_modules/ 19 | ] 20 | } 21 | ); 22 | } 23 | 24 | let extraPlugins = []; 25 | if (isTddMode) { 26 | extraPlugins.push(new CheckerPlugin());// to speed up compilation during TDD 27 | } 28 | 29 | return { 30 | devtool: 'inline-source-map', 31 | resolve: { 32 | extensions: ['.ts', '.js'], 33 | modules: [helpers.root('src'), 'node_modules'] 34 | }, 35 | module: { 36 | rules: [ 37 | { 38 | enforce: 'pre', 39 | test: /\.js$/, 40 | loader: 'source-map-loader', 41 | exclude: [ 42 | // these packages have problems with their sourcemaps 43 | helpers.root('node_modules/rxjs'), 44 | helpers.root('node_modules/@angular') 45 | ] 46 | }, 47 | { 48 | test: /\.ts$/, 49 | use: [ 50 | { 51 | loader: 'awesome-typescript-loader', 52 | options: { 53 | configFileName: helpers.root('src', 'tsconfig.spec.json'), 54 | // use inline sourcemaps for "karma-remap-coverage" reporter (if coverage is activated) 55 | sourceMap: !hasCoverage, 56 | inlineSourceMap: hasCoverage, 57 | compilerOptions: { 58 | 59 | // Remove TypeScript helpers to be injected 60 | // below by DefinePlugin 61 | removeComments: true 62 | } 63 | }, 64 | }, 65 | 'angular2-template-loader' 66 | ], 67 | exclude: [/\.e2e\.ts$/] 68 | }, 69 | { 70 | test: /\.css$/, 71 | loader: ['to-string-loader', 'css-loader'] 72 | }, 73 | { 74 | test: /\.(scss|sass)$/, 75 | use: ['to-string-loader', 'css-loader', 'sass-loader'], 76 | exclude: [helpers.root('src', 'scss')] 77 | }, 78 | { 79 | test: /\.html$/, 80 | loader: 'raw-loader' 81 | } 82 | ].concat(extraRules) 83 | }, 84 | 85 | plugins: [ 86 | 87 | new LoaderOptionsPlugin({ 88 | debug: false, 89 | options: { 90 | // legacy options go here 91 | } 92 | }), 93 | // Fixes linker warnings (see https://github.com/angular/angular/issues/11580) 94 | new ContextReplacementPlugin( 95 | // fixes WARNING Critical dependency: the request of a dependency is an expression 96 | /(.+)?angular(\\|\/)core(.+)?/, 97 | helpers.root('src'), // location of your src 98 | {} // a map of your routes 99 | ), 100 | ].concat(extraPlugins), 101 | 102 | performance: { 103 | hints: false 104 | }, 105 | node: { 106 | global: true, 107 | process: false, 108 | crypto: 'empty', 109 | module: false, 110 | clearImmediate: false, 111 | setImmediate: false 112 | } 113 | }; 114 | } 115 | 116 | module.exports.getConfig = getConfig; 117 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-avatar", 3 | "description": "Angular Avatar (ng2-avatar) is a simple and lightweight avatar component", 4 | "version": "2.3.1", 5 | "homepage": "https://github.com/snics/ng2-avatar", 6 | "author": { 7 | "name": "Nico Swiatecki", 8 | "url": "https://github.com/snics" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/snics/ng2-avatar.git" 13 | }, 14 | "license": "MIT", 15 | "keywords": [ 16 | "ng", 17 | "ng2", 18 | "ng4", 19 | "ngx", 20 | "angular", 21 | "angular 2", 22 | "angular 4", 23 | "library", 24 | "avatar", 25 | "angular-avatar", 26 | "letter avatar", 27 | "initials avatar", 28 | "angular avatar", 29 | "profile picture", 30 | "string avatar", 31 | "ng-avatar", 32 | "ng2-avatar", 33 | "ng4-avatar", 34 | "ngx-avatar", 35 | "gravatar", 36 | "gravatar api", 37 | "angular-gravatar", 38 | "ng-gravatar", 39 | "ng2-gravatar" 40 | ], 41 | "bugs": { 42 | "url": "https://github.com/snics/ng2-avatar/issues" 43 | }, 44 | "private": true, 45 | "scripts": { 46 | "start": "gulp build", 47 | "test": " gulp test", 48 | "demo": " gulp build:demo", 49 | "check-travis": " travis-status --repo=snics/ng2-avatar --branch=master --fail-pending || echo 'Not yet passing'" 50 | }, 51 | "dependencies": { 52 | "@angular/common": "^2.0.0", 53 | "@angular/core": "^2.0.0" 54 | }, 55 | "devDependencies": { 56 | "@angular/cli": "^6.2.4", 57 | "@angular/compiler": "2.0.0", 58 | "@angular/compiler-cli": "0.6.2", 59 | "@angular/platform-browser": "2.0.0", 60 | "@angular/platform-browser-dynamic": "2.0.0", 61 | "@angular/platform-server": "2.0.0", 62 | "@compodoc/gulp-compodoc": "0.0.8", 63 | "@types/jasmine": "2.5.41", 64 | "@types/node": "8.0.44", 65 | "angular-cli-ghpages": "0.5.1", 66 | "angular2-template-loader": "0.6.2", 67 | "autoprefixer": "7.1.5", 68 | "awesome-typescript-loader": "3.0.5", 69 | "babel-cli": "^6.26.0", 70 | "babel-preset-es2015": "^6.24.1", 71 | "codelyzer": "1.0.0-beta.0", 72 | "commitplease": "^3.1.0", 73 | "conventional-github-releaser": "1.1.13", 74 | "core-js": "2.5.1", 75 | "css-loader": "0.28.7", 76 | "cssnano": "4.1.4", 77 | "del": "3.0.0", 78 | "greenkeeper-lockfile": "1.12.0", 79 | "gulp": "3.9.1", 80 | "gulp-babel": "^7.0.1", 81 | "gulp-bump": "2.8.0", 82 | "gulp-conventional-changelog": "1.1.6", 83 | "gulp-coveralls": "0.1.4", 84 | "gulp-file": "0.3.0", 85 | "gulp-git": "2.4.2", 86 | "gulp-hub": "0.8.0", 87 | "gulp-inline-ng2-template": "4.0.0", 88 | "gulp-tslint": "6.1.1", 89 | "gulp-util": "3.0.8", 90 | "html-loader": "0.5.1", 91 | "istanbul-instrumenter-loader": "3.0.0", 92 | "jasmine-core": "2.8.0", 93 | "karma": "1.7.0", 94 | "karma-chrome-launcher": "2.2.0", 95 | "karma-coverage": "1.1.1", 96 | "karma-jasmine": "1.1.0", 97 | "karma-jasmine-html-reporter": "0.2.2", 98 | "karma-mocha-reporter": "2.2.5", 99 | "karma-remap-coverage": "0.1.4", 100 | "karma-sourcemap-loader": "0.3.7", 101 | "karma-webpack": "2.0.5", 102 | "node-sass": "4.5.3", 103 | "postcss": "6.0.13", 104 | "postcss-strip-inline-comments": "0.1.5", 105 | "pump": "1.0.2", 106 | "raw-loader": "0.5.1", 107 | "rollup": "0.50.0", 108 | "rollup-plugin-commonjs": "8.2.6", 109 | "rollup-plugin-node-resolve": "3.0.0", 110 | "rollup-plugin-sourcemaps": "0.4.2", 111 | "rollup-plugin-uglify": "2.0.1", 112 | "run-sequence": "2.2.0", 113 | "rxjs": "5.0.0-beta.12", 114 | "sass-loader": "6.0.6", 115 | "source-map-loader": "0.2.2", 116 | "to-string-loader": "1.1.5", 117 | "travis-status": "2.0.0", 118 | "tslint": "3.15.1", 119 | "typescript": "2.0.3", 120 | "webpack": "3.8.1", 121 | "webpack-dev-middleware": "1.12.0", 122 | "webpack-dev-server": "2.9.2", 123 | "yargs": "10.0.3", 124 | "zone.js": "0.6.21" 125 | }, 126 | "engines": { 127 | "node": ">=6.0.0" 128 | }, 129 | "commitplease": { 130 | "style": "angular", 131 | "types": [ 132 | "feat", 133 | "fix", 134 | "docs", 135 | "style", 136 | "refactor", 137 | "perf", 138 | "test", 139 | "chore", 140 | "revert", 141 | "demo" 142 | ], 143 | "scope": "\\S+.*" 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started.component.scss: -------------------------------------------------------------------------------- 1 | .getting-started{ 2 | margin-top: 1.0rem; 3 | } 4 | 5 | .editor { 6 | background-color: #f5f5f5; 7 | color: #555555; 8 | .gutter { 9 | background-color: #f5f5f5; 10 | color: #555555; 11 | } 12 | .invisible-character, .indent-guide { 13 | color: rgba(85, 85, 85, 0.2); 14 | } 15 | .wrap-guide { 16 | background-color: rgba(85, 85, 85, 0.2); 17 | } 18 | .gutter { 19 | color: #555555; 20 | background: #ffffff; 21 | .line-number { 22 | &.folded, &:after { 23 | color: #e87b00; 24 | } 25 | } 26 | } 27 | .fold-marker:after { 28 | color: #e87b00; 29 | } 30 | .invisible { 31 | color: #555; 32 | } 33 | .selection .region { 34 | background-color: #e1e1e1; 35 | } 36 | &.is-focused { 37 | .cursor { 38 | border-color: #000000; 39 | } 40 | .selection .region { 41 | background-color: #afc4da; 42 | } 43 | .line-number.cursor-line-no-selection, .line.cursor-line { 44 | background-color: rgba(255, 255, 134, 0.34); 45 | } 46 | } 47 | .comment { 48 | color: #999988; 49 | font-style: italic; 50 | } 51 | .string { 52 | color: #D14; 53 | } 54 | .source .string { 55 | .source, .meta.embedded.line { 56 | color: #5A5A5A; 57 | } 58 | .punctuation.section.embedded { 59 | color: #920B2D; 60 | .source { 61 | color: #920B2D; 62 | } 63 | } 64 | } 65 | .constant { 66 | &.numeric { 67 | color: #D14; 68 | } 69 | &.language, &.character, &.other { 70 | color: #606aa1; 71 | } 72 | &.symbol { 73 | color: #990073; 74 | } 75 | &.numeric.line-number.find-in-files .match { 76 | color: rgba(143, 190, 0, 0.63); 77 | } 78 | } 79 | .variable { 80 | color: #008080; 81 | &.parameter { 82 | color: #606aa1; 83 | } 84 | } 85 | .keyword { 86 | color: #222; 87 | font-weight: bold; 88 | &.unit { 89 | color: #445588; 90 | } 91 | &.special-method { 92 | color: #0086B3; 93 | } 94 | } 95 | .storage { 96 | color: #222; 97 | &.type { 98 | color: #222; 99 | } 100 | } 101 | .entity { 102 | &.name.class, &.other.inherited-class { 103 | text-decoration: underline; 104 | color: #606aa1; 105 | } 106 | &.name { 107 | &.function { 108 | color: #900; 109 | } 110 | &.tag { 111 | color: #008080; 112 | } 113 | } 114 | &.other.attribute-name { 115 | color: #458; 116 | font-weight: bold; 117 | } 118 | &.name.filename.find-in-files { 119 | color: #E6DB74; 120 | } 121 | } 122 | .support { 123 | &.constant, &.function, &.type { 124 | color: #458; 125 | } 126 | &.class { 127 | color: #008080; 128 | } 129 | } 130 | .invalid { 131 | color: #F8F8F0; 132 | background-color: #00A8C6; 133 | &.deprecated { 134 | color: #F8F8F0; 135 | background-color: #8FBE00; 136 | } 137 | } 138 | .meta { 139 | &.structure.dictionary { 140 | &.json > .string.quoted.double.json { 141 | color: #000080; 142 | .punctuation.string { 143 | color: #000080; 144 | } 145 | } 146 | &.value.json > .string.quoted.double.json { 147 | color: #d14; 148 | } 149 | } 150 | &.diff { 151 | color: #75715E; 152 | &.header { 153 | color: #75715E; 154 | } 155 | } 156 | } 157 | .css { 158 | &.support.property-name { 159 | font-weight: bold; 160 | color: #333; 161 | } 162 | &.constant { 163 | color: #099; 164 | } 165 | } 166 | .source.gfm { 167 | color: #444; 168 | } 169 | .gfm { 170 | .markup.heading { 171 | color: #111; 172 | } 173 | .link, .variable.list { 174 | color: #888; 175 | } 176 | } 177 | .markdown { 178 | .paragraph { 179 | color: #444; 180 | } 181 | .heading { 182 | color: #111; 183 | } 184 | .link { 185 | color: #888; 186 | .string { 187 | color: #888; 188 | } 189 | } 190 | } 191 | .search-results .marker { 192 | .region { 193 | background-color: transparent; 194 | border: 1px solid #999999; 195 | } 196 | &.current-result .region { 197 | border: 1px solid #000000; 198 | } 199 | } 200 | } 201 | 202 | .bracket-matcher { 203 | background-color: #C9C9C9; 204 | opacity: .7; 205 | border-bottom: 0 none; 206 | } 207 | 208 | strong.code { 209 | font-family: Consolas, "Liberation Mono", Menlo, Monaco, Courier, monospace; 210 | } 211 | 212 | blockquote { 213 | padding: 0 15px; 214 | color: #555; 215 | border-left: 4px solid #ccc; 216 | } 217 | 218 | code { 219 | font-family: Consolas, "Liberation Mono", Menlo, Monaco, Courier, monospace; 220 | background-color: #f5f5f5; 221 | } 222 | 223 | pre { 224 | overflow-x: auto; 225 | width: 100%; 226 | &.editor { 227 | display: inline-block; 228 | padding: 8px; 229 | border-radius: 2px; 230 | } 231 | code { 232 | display: inline-block; 233 | padding: 8px; 234 | border-radius: 2px; 235 | margin: 0 0 15px 0; 236 | } 237 | } 238 | 239 | .highlight { 240 | margin: 0 0 15px 0; 241 | } 242 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # ng2-avatar 2 | 3 | [![npm version](https://badge.fury.io/js/ng2-avatar.svg)](https://badge.fury.io/js/ng2-avatar), 4 | [![Build Status](https://travis-ci.org/snics/ng2-avatar.svg?branch=master)](https://travis-ci.org/snics/ng2-avatar) 5 | [![Coverage Status](https://coveralls.io/repos/github/snics/ng2-avatar/badge.svg?branch=master)](https://coveralls.io/github/snics/ng2-avatar?branch=master) 6 | [![dependency Status](https://david-dm.org/snics/ng2-avatar/status.svg)](https://david-dm.org/snics/ng2-avatar) 7 | [![devDependency Status](https://david-dm.org/snics/ng2-avatar/dev-status.svg?branch=master)](https://david-dm.org/snics/ng2-avatar#info=devDependencies) 8 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/snics/ng2-avatar#the-mit-license) 9 | 10 | Angular Avatar (ng2-avatar) is a simple and lightweight avatar component 11 | 12 | ## Demo 13 | 14 | View all the directives in action at https://snics.github.io/ng2-avatar 15 | 16 | ## Dependencies 17 | * [Angular](https://angular.io) (*requires* Angular 2 or higher, tested with 2.0.0) 18 | 19 | ## Installation 20 | Install above dependencies via *npm*. 21 | 22 | Now install `ng2-avatar` via: 23 | ```shell 24 | npm install --save ng2-avatar 25 | ``` 26 | 27 | --- 28 | ##### SystemJS 29 | >**Note**:If you are using `SystemJS`, you should adjust your configuration to point to the UMD bundle. 30 | In your systemjs config file, `map` needs to tell the System loader where to look for `ng2-avatar`: 31 | ```js 32 | map: { 33 | 'ng2-avatar': 'node_modules/ng2-avatar/bundles/ng2-avatar.umd.js', 34 | } 35 | ``` 36 | --- 37 | 38 | Once installed you need to import the main module: 39 | ```js 40 | import { AvatarModule } from 'ng2-avatar'; 41 | ``` 42 | The only remaining part is to list the imported module in your application module. The exact method will be slightly 43 | different for the root (top-level) module for which you should end up with the code similar to (notice ` AvatarModule.forRoot()`): 44 | ```js 45 | import { AvatarModule } from 'ng2-avatar'; 46 | 47 | @NgModule({ 48 | declarations: [ 49 | AppComponent, 50 | ... 51 | ], 52 | imports: [ 53 | AvatarModule.forRoot(), 54 | ... 55 | ], 56 | bootstrap: [AppComponent] 57 | }) 58 | export class AppModule { 59 | } 60 | ``` 61 | 62 | Other modules in your application can simply import ` AvatarModule `: 63 | 64 | ```js 65 | import { AvatarModule } from 'ng2-avatar'; 66 | 67 | @NgModule({ 68 | declarations: [OtherComponent, ...], 69 | imports: [AvatarModule, ...], 70 | }) 71 | export class OtherModule { 72 | } 73 | ``` 74 | 75 | # Usage 76 | ```html 77 | 78 | 79 | ``` 80 | 81 | # Configuration 82 | | configuration option | type | default | description | 83 | |:---------------------|:------:|:------------:|:-------------------------------------------------------------------------------------------------| 84 | | email | String | none | This email is for generated the initials letters or get the picture from Gravatar API (required) | 85 | | name | string | none | This name is for generated the initials letters (required) | 86 | | size | number | 100 | Is the size of the image and avatar | 87 | | background | string | Random color | The background colors for the letter's avatar | 88 | | displayType | string | circle | none, circle, rounded | 89 | | letter | string | ? | These are the default letter | 90 | | defaultProtocol | string | null | specifies a protocol or uses protocol-agnostic gravatar url when empty | 91 | 92 | ## License 93 | 94 | Copyright (c) 2017 Nico Swiatecki. Licensed under the MIT License (MIT) - *Initial work* - [Snics](https://github.com/snics) 95 | 96 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 97 | 98 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 99 | 100 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 101 | -------------------------------------------------------------------------------- /src/module/component/avatar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import {async, ComponentFixture, TestBed} from '@angular/core/testing'; 2 | import {DebugElement} from '@angular/core'; 3 | 4 | import {AvatarComponent} from './avatar.component'; 5 | 6 | describe('AvatarComponent', function () { 7 | let comp: AvatarComponent; 8 | let fixture: ComponentFixture; 9 | let de: DebugElement; 10 | 11 | beforeEach(async(() => { 12 | TestBed.configureTestingModule({ 13 | declarations: [AvatarComponent] 14 | }) 15 | .compileComponents(); 16 | })); 17 | 18 | beforeEach(() => { 19 | fixture = TestBed.createComponent(AvatarComponent); 20 | comp = fixture.componentInstance; 21 | de = fixture.debugElement; 22 | }); 23 | 24 | it('should create component', () => expect(comp).toBeDefined()); 25 | 26 | it('should can sat avatar size', () => { 27 | comp.size = 250; 28 | 29 | fixture.detectChanges(); 30 | expect(comp.fontSize).toEqual(97.5); 31 | expect(comp.props.size).toEqual('250px'); 32 | expect(comp.props.size).not.toBeUndefined(); 33 | expect(comp.props.lineheight).toEqual('250px'); 34 | expect(comp.props.lineheight).not.toBeUndefined(); 35 | expect(comp.props.fontSize).toEqual('97.5px'); 36 | expect(comp.props.fontSize).not.toBeUndefined(); 37 | }); 38 | 39 | describe('should can sat display type', function () { 40 | it('should can sat display type to rounded', () => { 41 | comp.displayType = 'rounded'; 42 | fixture.detectChanges(); 43 | expect(comp.props.borderradius).toEqual('5%'); 44 | }); 45 | 46 | it('should can sat display type to circle', () => { 47 | comp.displayType = 'circle'; 48 | fixture.detectChanges(); 49 | expect(comp.props.borderradius).toEqual('50%'); 50 | }); 51 | 52 | it('should can sat display type to none', () => { 53 | fixture.detectChanges(); 54 | expect(comp.props.borderradius).toEqual('0'); 55 | }); 56 | }); 57 | 58 | describe('getRandomColor()', function () { 59 | 60 | it('should get a random color', () => { 61 | expect(comp.getRandomColor()).not.toEqual(comp.getRandomColor()); 62 | expect(comp.getRandomColor().length).toEqual(7); 63 | expect(comp.getRandomColor()[0]).toEqual('#'); 64 | }); 65 | 66 | }); 67 | 68 | describe('getLetter()', function () { 69 | it('should create letters by name', () => { 70 | expect(comp.letter).toEqual('?'); 71 | 72 | expect(comp.name).toBeUndefined(); 73 | comp.name = 'Alfonso Keenan'; 74 | expect(comp.name).toEqual('Alfonso Keenan'); 75 | comp.getLetter(); 76 | expect(comp.letter).toEqual('AK'); 77 | }); 78 | 79 | 80 | it('should create letters by complex name', () => { 81 | expect(comp.letter).toEqual('?'); 82 | 83 | expect(comp.name).toBeUndefined(); 84 | comp.name = 'Alfonso H. Keenan'; 85 | expect(comp.name).toEqual('Alfonso H. Keenan'); 86 | comp.getLetter(); 87 | expect(comp.letter).toEqual('AHK'); 88 | 89 | 90 | comp.name = 'Alfonso Gertrude H. Keenan'; 91 | expect(comp.name).toEqual('Alfonso Gertrude H. Keenan'); 92 | comp.getLetter(); 93 | expect(comp.letter).toEqual('AGH'); 94 | }); 95 | 96 | it('should create letters by non-ASCII name', () => { 97 | expect(comp.letter).toEqual('?'); 98 | 99 | expect(comp.name).toBeUndefined(); 100 | comp.name = '张三'; 101 | expect(comp.name).toEqual('张三'); 102 | comp.getLetter(); 103 | expect(comp.letter).toEqual('张'); 104 | }); 105 | 106 | it('should create letters by email', () => { 107 | expect(comp.letter).toEqual('?'); 108 | 109 | expect(comp.email).toBeUndefined(); 110 | comp.email = 'alfonso.keenan@domain.com'; 111 | expect(comp.email).toEqual('alfonso.keenan@domain.com'); 112 | comp.getLetter(); 113 | expect(comp.letter).toEqual('AK'); 114 | }); 115 | 116 | 117 | it('should create letters by complex email', () => { 118 | expect(comp.letter).toEqual('?'); 119 | 120 | expect(comp.email).toBeUndefined(); 121 | comp.email = 'alfonso.h.keenan@domain.com'; 122 | expect(comp.email).toEqual('alfonso.h.keenan@domain.com'); 123 | comp.getLetter(); 124 | expect(comp.letter).toEqual('AHK'); 125 | 126 | comp.email = 'alfonso.h.gertrude.keenan@domain.com'; 127 | expect(comp.email).toEqual('alfonso.h.gertrude.keenan@domain.com'); 128 | comp.getLetter(); 129 | expect(comp.letter).toEqual('AHG'); 130 | }); 131 | }); 132 | 133 | describe('getAvatar()', function () { 134 | it('should create Gravatar url', () => { 135 | expect(comp.displayImage).toBeTruthy(); 136 | expect(comp.gravatarUrl).toBeUndefined(); 137 | expect(comp.email).toBeUndefined(); 138 | 139 | comp.email = 'alfonso.keenan@domain.com'; 140 | comp.getAvatar(); 141 | expect(comp.displayImage).toBeTruthy(); 142 | expect(comp.gravatarUrl.indexOf('//www.gravatar.com/avatar/')).toBeGreaterThan(-1); 143 | }); 144 | 145 | it('should can not create Gravatar url', () => { 146 | expect(comp.displayImage).toBeTruthy(); 147 | expect(comp.gravatarUrl).toBeUndefined(); 148 | expect(comp.email).toBeUndefined(); 149 | 150 | comp.email = 'This is not an email'; 151 | comp.getAvatar(); 152 | expect(comp.displayImage).toBeFalsy(); 153 | }); 154 | 155 | it('should can not create Gravatar url', () => { 156 | expect(comp.displayImage).toBeTruthy(); 157 | expect(comp.gravatarUrl).toBeUndefined(); 158 | expect(comp.email).toBeUndefined(); 159 | 160 | comp.email = 'This is not an email'; 161 | comp.getAvatar(); 162 | expect(comp.displayImage).toBeFalsy(); 163 | }); 164 | 165 | it('should have no protocol', () => { 166 | comp.email = 'alfonso.keenan@domain.com'; 167 | 168 | comp.getAvatar(); 169 | expect(comp.gravatarUrl.indexOf('http:')).toEqual(-1); 170 | expect(comp.gravatarUrl.indexOf('https:')).toEqual(-1); 171 | }); 172 | 173 | it('should have http as a protocol', () => { 174 | comp.email = 'alfonso.keenan@domain.com'; 175 | comp.defaultProtocol = 'http'; 176 | 177 | comp.getAvatar(); 178 | expect(comp.gravatarUrl.indexOf('http:')).toBeGreaterThan(-1); 179 | expect(comp.gravatarUrl.indexOf('https:')).toEqual(-1); 180 | }); 181 | 182 | it('should have https as a protocol', () => { 183 | comp.email = 'alfonso.keenan@domain.com'; 184 | comp.defaultProtocol = 'https'; 185 | 186 | comp.getAvatar(); 187 | expect(comp.gravatarUrl.indexOf('http:')).toEqual(-1); 188 | expect(comp.gravatarUrl.indexOf('https:')).toBeGreaterThan(-1); 189 | }); 190 | }); 191 | 192 | }); 193 | -------------------------------------------------------------------------------- /demo/src/app/getting-started/getting-started.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Getting Started

4 |
5 |
6 | 7 |
8 |
9 | 10 |

Dependencies

11 |
    12 |
  • Angular (requires Angular 2 or higher, tested with 2.0.0)
  • 13 |
14 | 15 |

Installation

16 |

Install above dependencies via npm.

17 |

Now install ng2-avatar via:

18 | 19 |
>npm install --save ng2-avatar
20 | 21 | 22 |
SystemJS
23 |
24 |

Note:If you are using SystemJS, you should adjust your configuration to point to 25 | the UMD bundle. 26 | In your systemjs config file, map needs to tell the System loader where to look for ng2-avatar: 27 |

28 |
29 | 30 |
map: {{ '{' }}
  'ng2-avatar': 'node_modules/ng2-avatar/bundles/ng2-avatar.umd.js',
}
31 | 32 |

Once installed you need to import the main module:

33 | 34 |
import {{ '{' }}AvatarModule} from 'ng2-avatar';
35 | 36 |

The only remaining part is to list the imported module in your application module. The exact method will be 37 | slightly 38 | different for the root (top-level) module for which you should end up with the code similar to (notice AvatarModule.forRoot()): 39 |

40 | 41 |
import {{ '{' }}AvatarModule} from 'ng2-avatar';
 
@NgModule({{ '{' }}
  declarations: [AppComponent, ...],
  imports: [AvatarModule.forRoot(), ...],  
  bootstrap: [AppComponent]
})
export class AppModule {{ '{' }}
}
42 | 43 |

Other modules in your application can simply import AvatarModule :

44 | 45 |
import {{ '{' }}AvatarModule} from 'ng-scrollreveal';
 
@NgModule({{ '{' }}
  declarations: [OtherComponent, ...],
  imports: [AvatarModule, ...], 
})
export class OtherModule {{ '{' }}
}
46 | 47 |

Usage

48 |
<avatar [email]="email" [displayType]="'circle'"></avatar>
<input type="email" [(ngModel)]="email">
49 | 50 |

Configuration

51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
configuration option type default description
email String none This email is for generated the initials letters or get the picture from Gravatar API 66 | (required) 67 |
name string none This name is for generated the initials letters (required)
size number 100 Is the size of the image and avatar
background string Random color The background colors for the letter's avatar
displayType string circle none, circle, rounded
letter string ? These are the default letter
defaultProtocol string null specifies a protocol or uses protocol-agnostic gravatar url when empty
107 |
108 |
109 | -------------------------------------------------------------------------------- /src/module/Md5.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | 3 | export abstract class Md5 { 4 | 5 | private static string: string; 6 | private static x: Array = >Array(); 7 | private static k: number; 8 | private static AA: number; 9 | private static BB: number; 10 | private static CC: number; 11 | private static DD: number; 12 | private static a: number; 13 | private static b: number; 14 | private static c: number; 15 | private static d: number; 16 | private static S11: number = 7; 17 | private static S12: number = 12; 18 | private static S13: number = 17; 19 | private static S14: number = 22; 20 | private static S21: number = 5; 21 | private static S22: number = 9; 22 | private static S23: number = 14; 23 | private static S24: number = 20; 24 | private static S31: number = 4; 25 | private static S32: number = 11; 26 | private static S33: number = 16; 27 | private static S34: number = 23; 28 | private static S41: number = 6; 29 | private static S42: number = 10; 30 | private static S43: number = 15; 31 | private static S44: number = 21; 32 | 33 | private static RotateLeft: Function = ( lValue: number, iShiftBits: number ) : number => (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); 34 | 35 | private static AddUnsigned( lX: number, lY: number ) : number 36 | { 37 | let lX4: number, 38 | lY4: number, 39 | lX8: number, 40 | lY8: number, 41 | lResult: number; 42 | 43 | lX8 = (lX & 0x80000000); 44 | lY8 = (lY & 0x80000000); 45 | lX4 = (lX & 0x40000000); 46 | lY4 = (lY & 0x40000000); 47 | lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); 48 | 49 | if ( !!(lX4 & lY4) ) 50 | { 51 | return (lResult ^ 0x80000000 ^ lX8 ^ lY8); 52 | } 53 | 54 | if ( !!(lX4 | lY4) ) 55 | { 56 | if ( !!(lResult & 0x40000000) ) 57 | { 58 | return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); 59 | } 60 | else 61 | { 62 | return (lResult ^ 0x40000000 ^ lX8 ^ lY8); 63 | } 64 | } 65 | else 66 | { 67 | return (lResult ^ lX8 ^ lY8); 68 | } 69 | } 70 | 71 | private static F: Function = ( x: number, y: number, z: number ) : number => (x & y) | ((~x) & z); 72 | 73 | private static G: Function = ( x: number, y: number, z: number ) : number => (x & z) | (y & (~z)); 74 | 75 | private static H: Function = ( x: number, y: number, z: number ) : number => (x ^ y ^ z); 76 | 77 | private static I: Function = ( x: number, y: number, z: number ) : number => (y ^ (x | (~z))); 78 | 79 | private static FF( a: number, b: number, c: number, d: number, x: number, s: number, ac: number ) : number 80 | { 81 | a = Md5.AddUnsigned(a, Md5.AddUnsigned(Md5.AddUnsigned(Md5.F(b, c, d), x), ac)); 82 | return Md5.AddUnsigned(Md5.RotateLeft(a, s), b); 83 | } 84 | 85 | private static GG( a: number, b: number, c: number, d: number, x: number, s: number, ac: number) : number 86 | { 87 | a = Md5.AddUnsigned(a, Md5.AddUnsigned(Md5.AddUnsigned(Md5.G(b, c, d), x), ac)); 88 | return Md5.AddUnsigned(Md5.RotateLeft(a, s), b); 89 | } 90 | 91 | private static HH( a: number, b: number, c: number, d: number, x: number, s: number, ac: number ) : number 92 | { 93 | a = Md5.AddUnsigned(a, Md5.AddUnsigned(Md5.AddUnsigned(Md5.H(b, c, d), x), ac)); 94 | return Md5.AddUnsigned(Md5.RotateLeft(a, s), b); 95 | } 96 | 97 | private static II(a: number, b: number, c: number, d: number, x: number, s: number, ac: number) : number 98 | { 99 | a = Md5.AddUnsigned(a, Md5.AddUnsigned(Md5.AddUnsigned(Md5.I(b, c, d), x), ac)); 100 | return Md5.AddUnsigned(Md5.RotateLeft(a, s), b); 101 | } 102 | 103 | private static ConvertToWordArray( string: string ) : Array 104 | { 105 | let lWordCount: number, 106 | lMessageLength: number = string.length, 107 | lNumberOfWords_temp1: number = lMessageLength + 8, 108 | lNumberOfWords_temp2: number = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64, 109 | lNumberOfWords: number = (lNumberOfWords_temp2 + 1) * 16, 110 | lWordArray: Array = Array(lNumberOfWords - 1), 111 | lBytePosition: number = 0, 112 | lByteCount: number = 0; 113 | 114 | while ( lByteCount < lMessageLength ) 115 | { 116 | lWordCount = (lByteCount - (lByteCount % 4)) / 4; 117 | lBytePosition = (lByteCount % 4) * 8; 118 | lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); 119 | lByteCount++; 120 | } 121 | 122 | lWordCount = (lByteCount - (lByteCount % 4)) / 4; 123 | lBytePosition = (lByteCount % 4) * 8; 124 | lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); 125 | lWordArray[lNumberOfWords - 2] = lMessageLength << 3; 126 | lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; 127 | 128 | return lWordArray; 129 | } 130 | 131 | private static WordToHex( lValue: number ) : string 132 | { 133 | let WordToHexValue: string = "", 134 | WordToHexValue_temp: string = "", 135 | lByte: number, 136 | lCount: number; 137 | 138 | for ( lCount = 0; lCount <= 3; lCount++ ) 139 | { 140 | lByte = (lValue >>> (lCount * 8)) & 255; 141 | WordToHexValue_temp = "0" + lByte.toString(16); 142 | WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2); 143 | } 144 | 145 | return WordToHexValue; 146 | } 147 | 148 | private static Utf8Encode( string: string ) : string 149 | { 150 | let utftext: string = "", 151 | c: number; 152 | 153 | string = string.replace(/\r\n/g, "\n"); 154 | 155 | for ( let n = 0; n < string.length; n++ ) 156 | { 157 | c = string.charCodeAt(n); 158 | 159 | if ( c < 128 ) 160 | { 161 | utftext += String.fromCharCode(c); 162 | } 163 | else if ( (c > 127) && (c < 2048) ) 164 | { 165 | utftext += String.fromCharCode((c >> 6) | 192); 166 | utftext += String.fromCharCode((c & 63) | 128); 167 | } 168 | else 169 | { 170 | utftext += String.fromCharCode((c >> 12) | 224); 171 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 172 | utftext += String.fromCharCode((c & 63) | 128); 173 | } 174 | 175 | } 176 | 177 | return utftext; 178 | } 179 | 180 | public static init( string: any ) : string 181 | { 182 | let temp: string; 183 | 184 | if ( typeof string !== 'string' ) 185 | string = JSON.stringify(string); 186 | 187 | Md5.string = Md5.Utf8Encode(string); 188 | Md5.x = Md5.ConvertToWordArray(Md5.string); 189 | 190 | Md5.a = 0x67452301; 191 | Md5.b = 0xEFCDAB89; 192 | Md5.c = 0x98BADCFE; 193 | Md5.d = 0x10325476; 194 | 195 | for ( Md5.k = 0; Md5.k < Md5.x.length; Md5.k += 16 ) 196 | { 197 | Md5.AA = Md5.a; 198 | Md5.BB = Md5.b; 199 | Md5.CC = Md5.c; 200 | Md5.DD = Md5.d; 201 | Md5.a = Md5.FF(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k], Md5.S11, 0xD76AA478); 202 | Md5.d = Md5.FF(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 1], Md5.S12, 0xE8C7B756); 203 | Md5.c = Md5.FF(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 2], Md5.S13, 0x242070DB); 204 | Md5.b = Md5.FF(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 3], Md5.S14, 0xC1BDCEEE); 205 | Md5.a = Md5.FF(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 4], Md5.S11, 0xF57C0FAF); 206 | Md5.d = Md5.FF(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 5], Md5.S12, 0x4787C62A); 207 | Md5.c = Md5.FF(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 6], Md5.S13, 0xA8304613); 208 | Md5.b = Md5.FF(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 7], Md5.S14, 0xFD469501); 209 | Md5.a = Md5.FF(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 8], Md5.S11, 0x698098D8); 210 | Md5.d = Md5.FF(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 9], Md5.S12, 0x8B44F7AF); 211 | Md5.c = Md5.FF(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 10], Md5.S13, 0xFFFF5BB1); 212 | Md5.b = Md5.FF(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 11], Md5.S14, 0x895CD7BE); 213 | Md5.a = Md5.FF(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 12], Md5.S11, 0x6B901122); 214 | Md5.d = Md5.FF(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 13], Md5.S12, 0xFD987193); 215 | Md5.c = Md5.FF(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 14], Md5.S13, 0xA679438E); 216 | Md5.b = Md5.FF(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 15], Md5.S14, 0x49B40821); 217 | Md5.a = Md5.GG(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 1], Md5.S21, 0xF61E2562); 218 | Md5.d = Md5.GG(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 6], Md5.S22, 0xC040B340); 219 | Md5.c = Md5.GG(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 11], Md5.S23, 0x265E5A51); 220 | Md5.b = Md5.GG(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k], Md5.S24, 0xE9B6C7AA); 221 | Md5.a = Md5.GG(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 5], Md5.S21, 0xD62F105D); 222 | Md5.d = Md5.GG(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 10], Md5.S22, 0x2441453); 223 | Md5.c = Md5.GG(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 15], Md5.S23, 0xD8A1E681); 224 | Md5.b = Md5.GG(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 4], Md5.S24, 0xE7D3FBC8); 225 | Md5.a = Md5.GG(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 9], Md5.S21, 0x21E1CDE6); 226 | Md5.d = Md5.GG(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 14], Md5.S22, 0xC33707D6); 227 | Md5.c = Md5.GG(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 3], Md5.S23, 0xF4D50D87); 228 | Md5.b = Md5.GG(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 8], Md5.S24, 0x455A14ED); 229 | Md5.a = Md5.GG(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 13], Md5.S21, 0xA9E3E905); 230 | Md5.d = Md5.GG(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 2], Md5.S22, 0xFCEFA3F8); 231 | Md5.c = Md5.GG(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 7], Md5.S23, 0x676F02D9); 232 | Md5.b = Md5.GG(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 12], Md5.S24, 0x8D2A4C8A); 233 | Md5.a = Md5.HH(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 5], Md5.S31, 0xFFFA3942); 234 | Md5.d = Md5.HH(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 8], Md5.S32, 0x8771F681); 235 | Md5.c = Md5.HH(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 11], Md5.S33, 0x6D9D6122); 236 | Md5.b = Md5.HH(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 14], Md5.S34, 0xFDE5380C); 237 | Md5.a = Md5.HH(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 1], Md5.S31, 0xA4BEEA44); 238 | Md5.d = Md5.HH(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 4], Md5.S32, 0x4BDECFA9); 239 | Md5.c = Md5.HH(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 7], Md5.S33, 0xF6BB4B60); 240 | Md5.b = Md5.HH(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 10], Md5.S34, 0xBEBFBC70); 241 | Md5.a = Md5.HH(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 13], Md5.S31, 0x289B7EC6); 242 | Md5.d = Md5.HH(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k], Md5.S32, 0xEAA127FA); 243 | Md5.c = Md5.HH(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 3], Md5.S33, 0xD4EF3085); 244 | Md5.b = Md5.HH(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 6], Md5.S34, 0x4881D05); 245 | Md5.a = Md5.HH(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 9], Md5.S31, 0xD9D4D039); 246 | Md5.d = Md5.HH(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 12], Md5.S32, 0xE6DB99E5); 247 | Md5.c = Md5.HH(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 15], Md5.S33, 0x1FA27CF8); 248 | Md5.b = Md5.HH(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 2], Md5.S34, 0xC4AC5665); 249 | Md5.a = Md5.II(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k], Md5.S41, 0xF4292244); 250 | Md5.d = Md5.II(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 7], Md5.S42, 0x432AFF97); 251 | Md5.c = Md5.II(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 14], Md5.S43, 0xAB9423A7); 252 | Md5.b = Md5.II(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 5], Md5.S44, 0xFC93A039); 253 | Md5.a = Md5.II(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 12], Md5.S41, 0x655B59C3); 254 | Md5.d = Md5.II(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 3], Md5.S42, 0x8F0CCC92); 255 | Md5.c = Md5.II(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 10], Md5.S43, 0xFFEFF47D); 256 | Md5.b = Md5.II(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 1], Md5.S44, 0x85845DD1); 257 | Md5.a = Md5.II(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 8], Md5.S41, 0x6FA87E4F); 258 | Md5.d = Md5.II(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 15], Md5.S42, 0xFE2CE6E0); 259 | Md5.c = Md5.II(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 6], Md5.S43, 0xA3014314); 260 | Md5.b = Md5.II(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 13], Md5.S44, 0x4E0811A1); 261 | Md5.a = Md5.II(Md5.a, Md5.b, Md5.c, Md5.d, Md5.x[Md5.k + 4], Md5.S41, 0xF7537E82); 262 | Md5.d = Md5.II(Md5.d, Md5.a, Md5.b, Md5.c, Md5.x[Md5.k + 11], Md5.S42, 0xBD3AF235); 263 | Md5.c = Md5.II(Md5.c, Md5.d, Md5.a, Md5.b, Md5.x[Md5.k + 2], Md5.S43, 0x2AD7D2BB); 264 | Md5.b = Md5.II(Md5.b, Md5.c, Md5.d, Md5.a, Md5.x[Md5.k + 9], Md5.S44, 0xEB86D391); 265 | 266 | Md5.a = Md5.AddUnsigned(Md5.a, Md5.AA); 267 | Md5.b = Md5.AddUnsigned(Md5.b, Md5.BB); 268 | Md5.c = Md5.AddUnsigned(Md5.c, Md5.CC); 269 | Md5.d = Md5.AddUnsigned(Md5.d, Md5.DD); 270 | } 271 | 272 | temp = Md5.WordToHex(Md5.a) + Md5.WordToHex(Md5.b) + Md5.WordToHex(Md5.c) + Md5.WordToHex(Md5.d); 273 | return temp.toLowerCase(); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const del = require('del'); 3 | const gulp = require('gulp'); 4 | const gulpUtil = require('gulp-util'); 5 | const babel = require('gulp-babel'); 6 | const helpers = require('./config/helpers'); 7 | 8 | /** TSLint checker */ 9 | const gulpTslint = require('gulp-tslint'); 10 | 11 | /** External command runner */ 12 | const process = require('process'); 13 | const execSync = require('child_process').execSync; 14 | 15 | /** File Access */ 16 | const fs = require('fs'); 17 | const path = require('path'); 18 | const gulpFile = require('gulp-file'); 19 | 20 | /** To properly handle pipes on error */ 21 | const pump = require('pump'); 22 | 23 | /** To upload code coverage to coveralls */ 24 | const gulpCoveralls = require('gulp-coveralls'); 25 | 26 | /** To order tasks */ 27 | const runSequence = require('run-sequence'); 28 | 29 | /** To compile & bundle the library with Angular & Rollup */ 30 | const ngc = (args) => {// Promisify version of the ngc compiler 31 | const project = args.p || args.project || '.'; 32 | const cmd = helpers.root(helpers.binPath('ngc')); 33 | return helpers.execp(`${cmd} -p ${project}`); 34 | }; 35 | const rollup = require('rollup'); 36 | const rollupUglify = require('rollup-plugin-uglify'); 37 | const rollupSourcemaps = require('rollup-plugin-sourcemaps'); 38 | const rollupNodeResolve = require('rollup-plugin-node-resolve'); 39 | const rollupCommonjs = require('rollup-plugin-commonjs'); 40 | 41 | /** To load templates and styles in Angular components */ 42 | const gulpInlineNgTemplate = require('gulp-inline-ng2-template'); 43 | 44 | /** Sass style */ 45 | const sass = require('node-sass'); 46 | const cssnano = require('cssnano'); 47 | const postcss = require('postcss'); 48 | const autoprefixer = require('autoprefixer'); 49 | const stripInlineComments = require('postcss-strip-inline-comments'); 50 | 51 | //Bumping, Releasing tools 52 | const gulpGit = require('gulp-git'); 53 | const gulpBump = require('gulp-bump'); 54 | const gulpConventionalChangelog = require('gulp-conventional-changelog'); 55 | const conventionalGithubReleaser = require('conventional-github-releaser'); 56 | 57 | /** To load gulp tasks from multiple files */ 58 | const gulpHub = require('gulp-hub'); 59 | 60 | /** Documentation generation tools **/ 61 | const gulpCompodoc = require('@compodoc/gulp-compodoc'); 62 | 63 | const yargs = require('yargs'); 64 | const argv = yargs 65 | .option('version', { 66 | alias: 'v', 67 | describe: 'Enter Version to bump to', 68 | choices: ['patch', 'minor', 'major'], 69 | type: "string" 70 | }) 71 | .option('ghToken', { 72 | alias: 'gh', 73 | describe: 'Enter Github Token for releasing', 74 | type: "string" 75 | }) 76 | .version(false) // disable default --version from yargs( since v9.0.0) 77 | .argv; 78 | 79 | const config = { 80 | libraryName: 'ng2-avatar', 81 | unscopedLibraryName: 'ng2-avatar', 82 | allSrc: 'src/**/*', 83 | allTs: 'src/**/!(*.spec).ts', 84 | allSass: 'src/**/*.+(scss|sass)', 85 | allHtml: 'src/**/*.html', 86 | demoDir: 'demo/', 87 | buildDir: 'tmp/', 88 | outputDir: 'dist/', 89 | outputDemoDir: 'demo/dist/browser/', 90 | coverageDir: 'coverage/' 91 | }; 92 | 93 | const rootFolder = path.join(__dirname); 94 | const buildFolder = path.join(rootFolder, `${config.buildDir}`); 95 | const distFolder = path.join(rootFolder, `${config.outputDir}`); 96 | const es5OutputFolder = path.join(buildFolder, 'lib-es5'); 97 | 98 | //Helper functions 99 | const startKarmaServer = (isTddMode, hasCoverage, cb) => { 100 | const karmaServer = require('karma').Server; 101 | const travis = process.env.TRAVIS; 102 | 103 | let config = {configFile: `${__dirname}/karma.conf.js`, singleRun: !isTddMode, autoWatch: isTddMode}; 104 | 105 | if (travis) { 106 | config['browsers'] = ['Chrome_travis_ci']; // 'Chrome_travis_ci' is defined in "customLaunchers" section of config/karma.conf.js 107 | } 108 | 109 | config['hasCoverage'] = hasCoverage; 110 | 111 | new karmaServer(config, cb).start(); 112 | }; 113 | 114 | const getPackageJsonVersion = () => { 115 | // We parse the json file instead of using require because require caches 116 | // multiple calls so the version number won't be updated 117 | return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; 118 | }; 119 | 120 | const isOK = condition => { 121 | if (condition === undefined) { 122 | return gulpUtil.colors.yellow('[SKIPPED]'); 123 | } 124 | return condition ? gulpUtil.colors.green('[OK]') : gulpUtil.colors.red('[KO]'); 125 | }; 126 | 127 | const readyToRelease = () => { 128 | let isTravisPassing = /build #\d+ passed/.test(execSync('npm run check-travis').toString().trim()); 129 | let onMasterBranch = execSync('git symbolic-ref --short -q HEAD').toString().trim() === 'master'; 130 | let canBump = !!argv.version; 131 | let canGhRelease = argv.ghToken || process.env.CONVENTIONAL_GITHUB_RELEASER_TOKEN; 132 | let canNpmPublish = !!execSync('npm whoami').toString().trim() && execSync('npm config get registry').toString().trim() === 'https://registry.npmjs.org/'; 133 | 134 | gulpUtil.log(`[travis-ci] Travis build on 'master' branch is passing............................................${isOK(isTravisPassing)}`); 135 | gulpUtil.log(`[git-branch] User is currently on 'master' branch..................................................${isOK(onMasterBranch)}`); 136 | gulpUtil.log(`[npm-publish] User is currently logged in to NPM Registry...........................................${isOK(canNpmPublish)}`); 137 | gulpUtil.log(`[bump-version] Option '--version' provided, with value : 'major', 'minor' or 'patch'.................${isOK(canBump)}`); 138 | gulpUtil.log(`[github-release] Option '--ghToken' provided or 'CONVENTIONAL_GITHUB_RELEASER_TOKEN' variable set......${isOK(canGhRelease)}`); 139 | 140 | return isTravisPassing && onMasterBranch && canBump && canGhRelease && canNpmPublish; 141 | }; 142 | 143 | const execCmd = (name, args, opts, ...subFolders) => { 144 | const cmd = helpers.root(subFolders, helpers.binPath(`${name}`)); 145 | return helpers.execp(`${cmd} ${args}`, opts) 146 | .catch(e => { 147 | gulpUtil.log(gulpUtil.colors.red(`${name} command failed. See below for errors.\n`)); 148 | gulpUtil.log(gulpUtil.colors.red(e)); 149 | process.exit(1); 150 | }); 151 | }; 152 | 153 | const execExternalCmd = (name, args, opts) => { 154 | return helpers.execp(`${name} ${args}`, opts) 155 | .catch(e => { 156 | gulpUtil.log(gulpUtil.colors.red(`${name} command failed. See below for errors.\n`)); 157 | gulpUtil.log(gulpUtil.colors.red(e)); 158 | process.exit(1); 159 | }); 160 | }; 161 | 162 | 163 | // Compile Sass to css 164 | const styleProcessor = (stylePath, ext, styleFile, callback) => { 165 | /** 166 | * Remove comments, autoprefixer, Minifier 167 | */ 168 | const processors = [ 169 | stripInlineComments, 170 | autoprefixer, 171 | cssnano 172 | ]; 173 | 174 | const postProcessCss = css => { 175 | postcss(processors).process(css).then(function (result) { 176 | result.warnings().forEach(function (warn) { 177 | gutil.warn(warn.toString()); 178 | }); 179 | styleFile = result.css; 180 | callback(null, styleFile); 181 | }); 182 | }; 183 | 184 | if (/\.(scss|sass)$/.test(ext[0])) { 185 | let sassObj = sass.renderSync({file: stylePath}); 186 | if (sassObj && sassObj['css']) { 187 | let css = sassObj.css.toString('utf8'); 188 | postProcessCss(css); 189 | } 190 | } else if (/\.css$/.test(ext[0])) { 191 | postProcessCss(styleFile); 192 | } 193 | }; 194 | 195 | ///////////////////////////////////////////////////////////////////////////// 196 | // Cleaning Tasks 197 | ///////////////////////////////////////////////////////////////////////////// 198 | gulp.task('clean:dist', () => { 199 | return del(config.outputDir); 200 | }); 201 | 202 | gulp.task('clean:build', () => { 203 | return del(config.buildDir); 204 | }); 205 | 206 | gulp.task('clean:coverage', () => { 207 | return del(config.coverageDir); 208 | }); 209 | 210 | gulp.task('clean:doc', () => { 211 | return del(`${config.outputDir}/doc`); 212 | }); 213 | 214 | gulp.task('clean', ['clean:dist', 'clean:coverage', 'clean:build']); 215 | 216 | ///////////////////////////////////////////////////////////////////////////// 217 | // Compilation Tasks 218 | ///////////////////////////////////////////////////////////////////////////// 219 | 220 | gulp.task('lint', (cb) => { 221 | pump([ 222 | gulp.src(config.allTs), 223 | gulpTslint( 224 | { 225 | 226 | formatter: 'verbose', 227 | configuration: 'tslint.json' 228 | }), 229 | gulpTslint.report() 230 | ], cb); 231 | }); 232 | 233 | // Inline Styles and Templates into components 234 | gulp.task('inline-templates', (cb) => { 235 | const options = { 236 | base: `${config.buildDir}`, 237 | styleProcessor: styleProcessor, 238 | useRelativePaths: true 239 | }; 240 | pump( 241 | [ 242 | gulp.src(config.allTs), 243 | gulpInlineNgTemplate(options), 244 | gulp.dest(`${config.buildDir}`) 245 | ], 246 | cb); 247 | }); 248 | 249 | // Prepare files for compilation 250 | gulp.task('pre-compile', (cb) => { 251 | pump([ 252 | gulp.src([config.allSrc]), 253 | gulp.dest(config.buildDir) 254 | ], cb); 255 | }); 256 | 257 | gulp.task('ng-compile', () => { 258 | return Promise.resolve() 259 | // Compile to ES5. 260 | .then(() => ngc({project: `${buildFolder}/tsconfig.lib.json`}) 261 | .then(exitCode => exitCode === 0 ? Promise.resolve() : Promise.reject()) 262 | .then(() => gulpUtil.log('ES5 compilation succeeded.')) 263 | ) 264 | .catch(e => { 265 | gulpUtil.log(gulpUtil.colors.red('ng-compilation failed. See below for errors.\n')); 266 | gulpUtil.log(gulpUtil.colors.red(e)); 267 | process.exit(1); 268 | }); 269 | }); 270 | 271 | // Lint, Prepare Build, , Sass to css, Inline templates & Styles and Ng-Compile 272 | gulp.task('compile', (cb) => { 273 | runSequence('lint', 'pre-compile', 'inline-templates', 'ng-compile', cb); 274 | }); 275 | 276 | gulp.task('transpileES2015', () => 277 | gulp.src(`${config.outputDir}/**/*.js`) 278 | .pipe(babel({ 279 | presets: ['es2015'] 280 | })) 281 | .pipe(gulp.dest(config.outputDir)) 282 | ); 283 | 284 | 285 | // Build the 'dist' folder (without publishing it to NPM) 286 | gulp.task('build', ['clean'], (cb) => { 287 | runSequence('compile', 'test', 'npm-package', 'rollup-bundle', 'transpileES2015', cb); 288 | }); 289 | 290 | // Same as 'build' but without cleaning temp folders (to avoid breaking demo app, if currently being served) 291 | gulp.task('build-watch', (cb) => { 292 | runSequence('compile', 'test', 'npm-package', 'rollup-bundle', cb); 293 | }); 294 | 295 | // Same as 'build-watch' but without running tests 296 | gulp.task('build-watch-no-tests', (cb) => { 297 | runSequence('compile', 'npm-package', 'rollup-bundle', cb); 298 | }); 299 | 300 | // Watch changes on (*.ts, *.html, *.sass) and Re-build library 301 | gulp.task('build:watch', ['build-watch'], () => { 302 | gulp.watch([config.allTs, config.allHtml, config.allSass], ['build-watch']); 303 | }); 304 | 305 | // Watch changes on (*.ts, *.html, *.sass) and Re-build library (without running tests) 306 | gulp.task('build:watch-fast', ['build-watch-no-tests'], () => { 307 | gulp.watch([config.allTs, config.allHtml, config.allSass], ['build-watch-no-tests']); 308 | }); 309 | 310 | 311 | ///////////////////////////////////////////////////////////////////////////// 312 | // Packaging Tasks 313 | ///////////////////////////////////////////////////////////////////////////// 314 | 315 | // Prepare 'dist' folder for publication to NPM 316 | gulp.task('npm-package', (cb) => { 317 | let pkgJson = JSON.parse(fs.readFileSync('./package.json', 'utf8')); 318 | let targetPkgJson = {}; 319 | let fieldsToCopy = ['version', 'description', 'keywords', 'author', 'repository', 'license', 'bugs', 'homepage']; 320 | 321 | targetPkgJson['name'] = config.libraryName; 322 | 323 | //only copy needed properties from project's package json 324 | fieldsToCopy.forEach((field) => { 325 | targetPkgJson[field] = pkgJson[field]; 326 | }); 327 | 328 | targetPkgJson['main'] = `./bundles/${config.unscopedLibraryName}.umd.js`; 329 | targetPkgJson['module'] = `./index.js`; 330 | targetPkgJson['typings'] = `./index.d.ts`; 331 | 332 | // defines project's dependencies as 'peerDependencies' for final users 333 | targetPkgJson.peerDependencies = {}; 334 | Object.keys(pkgJson.dependencies).forEach((dependency) => { 335 | // versions are defined as '^' by default, but you can customize it by editing "dependenciesRange" in '.yo-rc.json' file 336 | targetPkgJson.peerDependencies[dependency] = `^${pkgJson.dependencies[dependency].replace(/[\^~><=]/, '')}`; 337 | }); 338 | 339 | // copy the needed additional files in the 'dist' folder 340 | pump( 341 | [ 342 | gulp.src(['README.md', 'LICENSE', 'CHANGELOG.md', 343 | `${config.buildDir}/lib-es5/**/*.js`, 344 | `${config.buildDir}/lib-es5/**/*.js.map`, 345 | `${config.buildDir}/lib-es5/**/*.d.ts`, 346 | `${config.buildDir}/lib-es5/**/*.metadata.json`]), 347 | gulpFile('package.json', JSON.stringify(targetPkgJson, null, 2)), 348 | gulp.dest(config.outputDir) 349 | ], cb); 350 | }); 351 | 352 | // Bundles the library as UMD bundles using RollupJS 353 | gulp.task('rollup-bundle', (cb) => { 354 | return Promise.resolve() 355 | // Bundle lib. 356 | .then(() => { 357 | // Base configuration. 358 | const es5Input = path.join(es5OutputFolder, `index.js`); 359 | const globals = { 360 | // Angular dependencies 361 | '@angular/core': 'ng.core', 362 | '@angular/common': 'ng.common', 363 | 364 | // Rxjs dependencies 365 | 'rxjs/Subject': 'Rx', 366 | 'rxjs/Observable': 'Rx', 367 | 'rxjs/add/observable/fromEvent': 'Rx.Observable', 368 | 'rxjs/add/observable/forkJoin': 'Rx.Observable', 369 | 'rxjs/add/observable/of': 'Rx.Observable', 370 | 'rxjs/add/observable/merge': 'Rx.Observable', 371 | 'rxjs/add/observable/throw': 'Rx.Observable', 372 | 'rxjs/add/operator/auditTime': 'Rx.Observable.prototype', 373 | 'rxjs/add/operator/toPromise': 'Rx.Observable.prototype', 374 | 'rxjs/add/operator/map': 'Rx.Observable.prototype', 375 | 'rxjs/add/operator/filter': 'Rx.Observable.prototype', 376 | 'rxjs/add/operator/do': 'Rx.Observable.prototype', 377 | 'rxjs/add/operator/share': 'Rx.Observable.prototype', 378 | 'rxjs/add/operator/finally': 'Rx.Observable.prototype', 379 | 'rxjs/add/operator/catch': 'Rx.Observable.prototype', 380 | 'rxjs/add/observable/empty': 'Rx.Observable.prototype', 381 | 'rxjs/add/operator/first': 'Rx.Observable.prototype', 382 | 'rxjs/add/operator/startWith': 'Rx.Observable.prototype', 383 | 'rxjs/add/operator/switchMap': 'Rx.Observable.prototype', 384 | 385 | // ATTENTION: 386 | // Add any other dependency or peer dependency of your library here 387 | // This is required for UMD bundle users. 388 | 'ts-md5': 'ts-md5' 389 | }; 390 | const rollupBaseConfig = { 391 | name: _.camelCase(config.libraryName), 392 | sourcemap: true, 393 | globals: globals, 394 | external: Object.keys(globals), 395 | plugins: [ 396 | rollupCommonjs({ 397 | include: ['node_modules/rxjs/**'] 398 | }), 399 | rollupSourcemaps(), 400 | rollupNodeResolve({jsnext: true, module: true}) 401 | ] 402 | }; 403 | 404 | // UMD bundle. 405 | const umdConfig = Object.assign({}, rollupBaseConfig, { 406 | input: es5Input, 407 | file: path.join(distFolder, `bundles`, `${config.unscopedLibraryName}.umd.js`), 408 | format: 'umd', 409 | }); 410 | 411 | // Minified UMD bundle. 412 | const minifiedUmdConfig = Object.assign({}, rollupBaseConfig, { 413 | input: es5Input, 414 | file: path.join(distFolder, `bundles`, `${config.unscopedLibraryName}.umd.min.js`), 415 | format: 'umd', 416 | plugins: rollupBaseConfig.plugins.concat([rollupUglify({})]) 417 | }); 418 | 419 | const allBundles = [ 420 | umdConfig, 421 | minifiedUmdConfig 422 | ].map(cfg => rollup.rollup(cfg).then(bundle => bundle.write(cfg))); 423 | 424 | return Promise.all(allBundles) 425 | .then(() => gulpUtil.log('All bundles generated successfully.')) 426 | }) 427 | .catch(e => { 428 | gulpUtil.log(gulpUtil.colors.red('rollup-bundling failed. See below for errors.\n')); 429 | gulpUtil.log(gulpUtil.colors.red(e)); 430 | process.exit(1); 431 | }); 432 | }); 433 | 434 | 435 | ///////////////////////////////////////////////////////////////////////////// 436 | // Documentation Tasks 437 | ///////////////////////////////////////////////////////////////////////////// 438 | gulp.task('build:doc', (cb) => { 439 | pump([ 440 | gulp.src('src/**/*.ts'), 441 | gulpCompodoc({ 442 | tsconfig: 'src/tsconfig.lib.json', 443 | hideGenerator: true, 444 | disableCoverage: true, 445 | output: `${config.outputDemoDir}/doc/` 446 | }) 447 | ], cb); 448 | }); 449 | 450 | gulp.task('serve:doc', ['clean:doc'], (cb) => { 451 | pump([ 452 | gulp.src('src/**/*.ts'), 453 | gulpCompodoc({ 454 | tsconfig: 'src/tsconfig.lib.json', 455 | serve: true, 456 | output: `${config.outputDir}/doc/` 457 | }) 458 | ], cb); 459 | }); 460 | 461 | 462 | ///////////////////////////////////////////////////////////////////////////// 463 | // Demo Tasks 464 | ///////////////////////////////////////////////////////////////////////////// 465 | const execDemoCmd = (args, opts) => { 466 | if (fs.existsSync(`${config.demoDir}/node_modules`)) { 467 | return execCmd('ng', args, opts, `/${config.demoDir}`); 468 | } 469 | else { 470 | gulpUtil.log(gulpUtil.colors.yellow(`No 'node_modules' found in '${config.demoDir}'. Installing dependencies for you...`)); 471 | return helpers.installDependencies({cwd: `${config.demoDir}`}) 472 | .then(exitCode => exitCode === 0 ? execCmd('ng', args, opts, `/${config.demoDir}`) : Promise.reject()) 473 | .catch(e => { 474 | gulpUtil.log(gulpUtil.colors.red(`ng command failed. See below for errors.\n`)); 475 | gulpUtil.log(gulpUtil.colors.red(e)); 476 | process.exit(1); 477 | }); 478 | } 479 | }; 480 | 481 | gulp.task('test:demo', () => { 482 | return execDemoCmd('test --preserve-symlinks', {cwd: `${config.demoDir}`}); 483 | }); 484 | 485 | gulp.task('serve:demo', () => { 486 | return execDemoCmd('serve --preserve-symlinks --aot --proxy-config proxy.conf.json', {cwd: `${config.demoDir}`}); 487 | }); 488 | 489 | gulp.task('serve:demo-hmr', () => { 490 | return execDemoCmd('serve --hmr -e=hmr --preserve-symlinks --aot --proxy-config proxy.conf.json', {cwd: `${config.demoDir}`}); 491 | }); 492 | 493 | gulp.task('build:demo', () => { 494 | return execDemoCmd(`build --preserve-symlinks --prod --aot --build-optimizer`, {cwd: `${config.demoDir}`}); 495 | }); 496 | 497 | gulp.task('serve:demo-ssr', ['build:demo'], () => { 498 | return execDemoCmd(`build --preserve-symlinks --prod --aot --build-optimizer --app ssr --output-hashing=none`, {cwd: `${config.demoDir}`}) 499 | .then(exitCode => { 500 | if (exitCode === 0) { 501 | execCmd('webpack', '--config webpack.server.config.js --progress --colors', {cwd: `${config.demoDir}`}, `/${config.demoDir}`) 502 | .then(exitCode => exitCode === 0 ? execExternalCmd('node', 'dist/server.js', {cwd: `${config.demoDir}`}, `/${config.demoDir}`) : Promise.reject(1)); 503 | } else { 504 | Promise.reject(1); 505 | } 506 | } 507 | ); 508 | }); 509 | 510 | gulp.task('build:demo-ssr', ['build:demo'], () => { 511 | return execDemoCmd(`build --preserve-symlinks --prod --aot --build-optimizer --app ssr --output-hashing=none`, {cwd: `${config.demoDir}`}) 512 | .then(exitCode => { 513 | if (exitCode === 0) { 514 | execCmd('webpack', '--config webpack.server.config.js --progress --colors', {cwd: `${config.demoDir}`}, `/${config.demoDir}`) 515 | .then(exitCode => exitCode === 0 ? execExternalCmd('node', 'dist/prerender.js', {cwd: `${config.demoDir}`}, `/${config.demoDir}`) : Promise.reject(1)); 516 | } else { 517 | Promise.reject(1); 518 | } 519 | } 520 | ); 521 | }); 522 | 523 | gulp.task('push:demo', () => { 524 | return execCmd('ngh', `--dir ${config.outputDemoDir} --message="chore(demo): :rocket: deploy new version"`); 525 | }); 526 | 527 | gulp.task('deploy:demo', (cb) => { 528 | runSequence('build:demo', 'build:doc', 'push:demo', cb); 529 | }); 530 | 531 | 532 | ///////////////////////////////////////////////////////////////////////////// 533 | // Test Tasks 534 | ///////////////////////////////////////////////////////////////////////////// 535 | gulp.task('test', (cb) => { 536 | const ENV = process.env.NODE_ENV = process.env.ENV = 'test'; 537 | startKarmaServer(false, true, cb); 538 | }); 539 | 540 | gulp.task('test:ci', ['clean'], (cb) => { 541 | runSequence('compile', 'test'); 542 | }); 543 | 544 | gulp.task('test:watch', (cb) => { 545 | const ENV = process.env.NODE_ENV = process.env.ENV = 'test'; 546 | startKarmaServer(true, true, cb); 547 | }); 548 | 549 | gulp.task('test:watch-no-cc', (cb) => {//no coverage (useful for debugging failing tests in browser) 550 | const ENV = process.env.NODE_ENV = process.env.ENV = 'test'; 551 | startKarmaServer(true, false, cb); 552 | }); 553 | 554 | ///////////////////////////////////////////////////////////////////////////// 555 | // Release Tasks 556 | ///////////////////////////////////////////////////////////////////////////// 557 | gulp.task('changelog', (cb) => { 558 | pump( 559 | [ 560 | gulp.src('CHANGELOG.md', {buffer: false}), 561 | gulpConventionalChangelog({preset: 'angular', releaseCount: 0}), 562 | gulp.dest('./') 563 | ], cb); 564 | }); 565 | 566 | gulp.task('github-release', (cb) => { 567 | if (!argv.ghToken && !process.env.CONVENTIONAL_GITHUB_RELEASER_TOKEN) { 568 | gulpUtil.log(gulpUtil.colors.red(`You must specify a Github Token via '--ghToken' or set environment variable 'CONVENTIONAL_GITHUB_RELEASER_TOKEN' to allow releasing on Github`)); 569 | throw new Error(`Missing '--ghToken' argument and environment variable 'CONVENTIONAL_GITHUB_RELEASER_TOKEN' not set`); 570 | } 571 | 572 | conventionalGithubReleaser( 573 | { 574 | type: 'oauth', 575 | token: argv.ghToken || process.env.CONVENTIONAL_GITHUB_RELEASER_TOKEN 576 | }, 577 | {preset: 'angular'}, 578 | cb); 579 | }); 580 | 581 | gulp.task('bump-version', (cb) => { 582 | if (!argv.version) { 583 | gulpUtil.log(gulpUtil.colors.red(`You must specify which version to bump to (Possible values: 'major', 'minor', and 'patch')`)); 584 | throw new Error(`Missing '--version' argument`); 585 | } 586 | 587 | pump( 588 | [ 589 | gulp.src('./package.json'), 590 | gulpBump({type: argv.version}), 591 | gulp.dest('./'), 592 | ], cb); 593 | }); 594 | 595 | gulp.task('commit-changes', (cb) => { 596 | let version = getPackageJsonVersion(); 597 | pump( 598 | [ 599 | gulp.src('.'), 600 | gulpGit.add(), 601 | gulpGit.commit(`chore(release): bump version number to ${version}`) 602 | ], cb); 603 | }); 604 | 605 | gulp.task('push-changes', (cb) => { 606 | gulpGit.push('origin', 'master', cb); 607 | }); 608 | 609 | gulp.task('create-new-tag', (cb) => { 610 | let version = `v${getPackageJsonVersion()}`; 611 | gulpGit.tag(version, `chore(release): :sparkles: :tada: create tag for version v${version}`, (error) => { 612 | if (error) { 613 | return cb(error); 614 | } 615 | gulpGit.push('origin', 'master', {args: '--tags'}, cb); 616 | }); 617 | 618 | }); 619 | 620 | // Build and then Publish 'dist' folder to NPM 621 | gulp.task('npm-publish', ['build'], () => { 622 | return execExternalCmd('npm', `publish ${config.outputDir}`) 623 | }); 624 | 625 | // Perfom pre-release checks (no actual release) 626 | gulp.task('pre-release', cb => { 627 | readyToRelease(); 628 | cb(); 629 | }); 630 | 631 | gulp.task('release', (cb) => { 632 | gulpUtil.log('# Performing Pre-Release Checks...'); 633 | if (!readyToRelease()) { 634 | gulpUtil.log(gulpUtil.colors.red('# Pre-Release Checks have failed. Please fix them and try again. Aborting...')); 635 | cb(); 636 | } 637 | else { 638 | gulpUtil.log(gulpUtil.colors.green('# Pre-Release Checks have succeeded. Continuing...')); 639 | runSequence( 640 | 'bump-version', 641 | 'changelog', 642 | 'commit-changes', 643 | 'push-changes', 644 | 'create-new-tag', 645 | 'github-release', 646 | 'npm-publish', 647 | 'deploy:demo', 648 | (error) => { 649 | if (error) { 650 | gulpUtil.log(gulpUtil.colors.red(error.message)); 651 | } else { 652 | gulpUtil.log(gulpUtil.colors.green('RELEASE FINISHED SUCCESSFULLY')); 653 | } 654 | cb(error); 655 | }); 656 | } 657 | }); 658 | 659 | 660 | ///////////////////////////////////////////////////////////////////////////// 661 | // Utility Tasks 662 | ///////////////////////////////////////////////////////////////////////////// 663 | 664 | // Link 'dist' folder (create a local 'ng-scrollreveal' package that symlinks to it) 665 | // This way, we can have the demo project declare a dependency on 'ng-scrollreveal' (as it should) 666 | // and, thanks to 'npm link ng-scrollreveal' on demo project, be sure to always use the latest built 667 | // version of the library ( which is in 'dist/' folder) 668 | gulp.task('link', () => { 669 | return execExternalCmd('npm', 'link', {cwd: `${config.outputDir}`}); 670 | }); 671 | 672 | gulp.task('unlink', () => { 673 | return execExternalCmd('npm', 'unlink', {cwd: `${config.outputDir}`}); 674 | }); 675 | 676 | // Upload code coverage report to coveralls.io (will be triggered by Travis CI on successful build) 677 | gulp.task('coveralls', (cb) => { 678 | pump( 679 | [ 680 | gulp.src(`${config.coverageDir}/coverage.lcov`), 681 | gulpCoveralls() 682 | ], cb); 683 | }); 684 | 685 | gulp.task('default', ['build']); 686 | 687 | // Load additional tasks 688 | gulpHub(['./config/gulp-tasks/*.js']); 689 | --------------------------------------------------------------------------------