Repository: PatrickJS/PatrickJS-starter
Branch: master
Commit: 23ef49ac3f5d
Files: 114
Total size: 136.4 KB
Directory structure:
gitextract_obradcba/
├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── CONTRIBUTING.md
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .nvmrc
├── .travis.yml
├── .vscode/
│ ├── launch.json
│ └── settings.json
├── Dockerfile
├── Dockerfile-dev
├── LICENSE
├── README.md
├── config/
│ ├── build-utils.js
│ ├── config.common.json
│ ├── config.dev.json
│ ├── config.prod.json
│ ├── empty.js
│ ├── github-deploy/
│ │ └── index.js
│ ├── head-config.common.js
│ ├── helpers.js
│ ├── html-elements-plugin/
│ │ └── index.js
│ ├── karma.conf.js
│ ├── nginx-custom.conf
│ ├── protractor.conf.js
│ ├── resource-override.js
│ ├── spec-bundle.js
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ ├── webpack.github-deploy.js
│ ├── webpack.prod.js
│ └── webpack.test.js
├── docker-compose.yml
├── firebase.json
├── karma.conf.js
├── netlify.toml
├── package.json
├── protractor.conf.js
├── sonar-project.properties
├── src/
│ ├── app/
│ │ ├── +barrel/
│ │ │ ├── +child-barrel/
│ │ │ │ ├── child-barrel.component.ts
│ │ │ │ ├── child-barrel.module.ts
│ │ │ │ ├── child-barrel.routes.ts
│ │ │ │ └── index.ts
│ │ │ ├── barrel.component.ts
│ │ │ ├── barrel.module.ts
│ │ │ ├── barrel.routes.ts
│ │ │ └── index.ts
│ │ ├── +detail/
│ │ │ ├── +child-detail/
│ │ │ │ ├── child-detail.component.ts
│ │ │ │ ├── child-detail.module.ts
│ │ │ │ ├── child-detail.routes.ts
│ │ │ │ └── index.ts
│ │ │ ├── detail.component.ts
│ │ │ ├── detail.module.ts
│ │ │ ├── detail.routes.ts
│ │ │ └── index.ts
│ │ ├── +dev-module/
│ │ │ ├── dev-module.component.ts
│ │ │ ├── dev-module.module.ts
│ │ │ ├── dev-module.routes.ts
│ │ │ └── index.ts
│ │ ├── about/
│ │ │ ├── about.component.spec.ts
│ │ │ ├── about.component.ts
│ │ │ └── index.ts
│ │ ├── app.component.css
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ ├── app.e2e.ts
│ │ ├── app.module.ts
│ │ ├── app.resolver.ts
│ │ ├── app.routes.ts
│ │ ├── app.service.ts
│ │ ├── home/
│ │ │ ├── home.component.css
│ │ │ ├── home.component.html
│ │ │ ├── home.component.spec.ts
│ │ │ ├── home.component.ts
│ │ │ ├── home.e2e.ts
│ │ │ ├── index.ts
│ │ │ ├── title/
│ │ │ │ ├── index.ts
│ │ │ │ ├── title.service.spec.ts
│ │ │ │ └── title.service.ts
│ │ │ └── x-large/
│ │ │ ├── index.ts
│ │ │ ├── x-large.directive.spec.ts
│ │ │ └── x-large.directive.ts
│ │ ├── index.ts
│ │ └── no-content/
│ │ ├── index.ts
│ │ └── no-content.component.ts
│ ├── assets/
│ │ ├── css/
│ │ │ └── .gitkeep
│ │ ├── data.json
│ │ ├── humans.txt
│ │ ├── icon/
│ │ │ └── browserconfig.xml
│ │ ├── manifest.json
│ │ ├── mock-data/
│ │ │ └── mock-data.json
│ │ ├── robots.txt
│ │ └── service-worker.js
│ ├── custom-typings.d.ts
│ ├── environments/
│ │ ├── environment.e2e.prod.ts
│ │ ├── environment.prod.ts
│ │ ├── environment.ts
│ │ └── model.ts
│ ├── index.html
│ ├── main.browser.ts
│ ├── meta/
│ │ ├── humans.txt
│ │ └── robots.txt
│ ├── polyfills.browser.ts
│ └── styles/
│ ├── _variables.scss
│ ├── headings.css
│ └── styles.scss
├── tsconfig.json
├── tsconfig.webpack.json
├── tslint.json
├── typedoc.json
└── webpack.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
.git
.github
.vscode
coverage
# OS generated files #
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
# Node Files #
node_modules
npm-debug.log
npm-debug.log.*
# Typing #
src/typings/tsd
typings
tsd_typings
# Dist #
dist
.awcache
.webpack.json
compiled
dll
# IDE #
.idea
*.swp
# Angular #
*.ngfactory.ts
*.css.shim.ts
*.ngsummary.json
*.shim.ngstyle.ts
================================================
FILE: .editorconfig
================================================
# tipe.io
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
================================================
FILE: .gitattributes
================================================
yarn.lock -diff
================================================
FILE: .github/CONTRIBUTING.md
================================================
## Read and contribute to the Wiki
Make sure you read the [Wiki](https://github.com/gdi2290/angular-starter/wiki).
## Submitting Pull Requests
If you're changing the structure of the repository please create an issue first.
## Submitting bug reports
Make sure you are on latest changes and that you ran this command `npm run clean:install` after updating your local repository. If you can, please provide more information about your environment such as browser, operating system, node version, and npm version.
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [PatrickJS] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
* **I'm submitting a ...**
[ ] bug report
[ ] feature request
[ ] question about the decisions made in the repository
* **Do you want to request a *feature* or report a *bug*?**
* **What is the current behavior?**
* **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
* **What is the expected behavior?**
* **What is the motivation / use case for changing the behavior?**
* **Please tell us about your environment:**
- Angular version: 4.x.x
- Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
* **What is the current behavior?** (You can also link to an open issue here)
* **What is the new behavior (if this is a feature change)?**
* **Other information**:
================================================
FILE: .gitignore
================================================
# tipe.io
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# SonarQube sonar-scanner temp directory
.scannerwork
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Users Environment Variables
.lock-wscript
# OS generated files #
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
# Node Files #
/node_modules/
/bower_components/
npm-debug.log
/npm-debug.log.*
# Coverage #
/coverage/
# Generic Unit Sonar Reports #
/reports/
# Typing #
/src/typings/tsd/
/typings/
/tsd_typings/
# Dist #
/dist
/public/__build__/
/src/*/__build__/
/__build__/**
/public/dist/
/src/*/dist/
/dist/**
/.awcache
.webpack.json
/compiled/
dll/
temp
tmp
webpack-cache
# Doc #
/doc/
/documentation/
# IDE #
.idea/
*.swp
# Angular #
*.ngfactory.ts
*.css.shim.ts
*.ngsummary.json
*.shim.ngstyle.ts
================================================
FILE: .nvmrc
================================================
lts/*
================================================
FILE: .travis.yml
================================================
sudo: false
dist: trusty
language: node_js
cache:
directories:
- node_modules
addons:
chrome: stable
node_js:
- "6"
- "7"
- "8"
matrix:
fast_finish: true
before_install:
- npm install npm@5 -g
- npm cache verify
- npm prune
- npm update
install:
- npm install
script:
- npm run ci:travis
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Chrome against localhost, with sourcemaps",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000/*",
"runtimeArgs": [
"--disable-web-security",
"--user-data-dir",
"--remote-debugging-port=9222"
],
"sourceMaps": true,
"webRoot": "${workspaceRoot}"
},
{
"name": "Attach to Chrome, with sourcemaps",
"type": "chrome",
"request": "attach",
"url": "http://localhost:3000/*",
"port": 9222,
"sourceMaps": true,
"webRoot": "${workspaceRoot}"
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"typescript.tsdk": "node_modules/typescript/lib/"
}
================================================
FILE: Dockerfile
================================================
# Usage:
#
# Build image:
# docker build -t angular-starter .
#
# Run image (on localhost:8080):
# docker run --name angular-starter -p 8080:80 angular-starter
#
# Run image as virtual host (read more: https://github.com/jwilder/nginx-proxy):
# docker run -e VIRTUAL_HOST=angular-starter.your-domain.com --name angular-starter angular-starter
# Stage 1, based on Node.js, to build and compile Angular
FROM node:8.9.4-alpine as builder
COPY package.json ./
## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm i && mkdir /ng-app && mv ./node_modules ./ng-app
WORKDIR /ng-app
COPY . .
RUN npm run build:aot:prod
# Stage 2, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx:1.13.9-alpine
COPY ./config/nginx-custom.conf /etc/nginx/conf.d/default.conf
## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
## From ‘builder’ stage copy over the artifacts in dist folder to default nginx public folder
COPY --from=builder /ng-app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
================================================
FILE: Dockerfile-dev
================================================
# Usage:
#
# Build image:
# docker build -t angular-starter .
#
# Run image (on localhost:8080):
# docker run --name angular-starter -p 8080:80 angular-starter
#
# Run image as virtual host (read more: https://github.com/jwilder/nginx-proxy):
# docker run -e VIRTUAL_HOST=angular-starter.your-domain.com --name angular-starter angular-starter
FROM node:8.9.4-alpine as builder
COPY package.json ./
## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm i && mkdir /ng-app && mv ./node_modules ./ng-app
WORKDIR /ng-app
COPY . .
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015-2018 PatrickJS, Tipe Inc
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
================================================
FILE: README.md
================================================
# Please use the Angular CLI if you want an angular app
[](https://twitter.com/SwiftOnSecurity)
[](https://github.com/auchenberg/volkswagen)
[](https://travis-ci.org/gdi2290/angular-starter)
[](https://badge.fury.io/gh/gdi2290%2Fangular-starter)
[](https://david-dm.org/gdi2290/angular-starter)
[](http://stackshare.io/gdi2290/angular-starter)
<p align="center">
<a href="https://patrickjs.com" target="_blank">
<img src="https://cloud.githubusercontent.com/assets/1016365/26219144/aa986cfa-3bdb-11e7-9f04-7296dc9ae945.png" alt="Angular Starter" />
</a>
</p>
# Angular Webpack Starter [](https://gitter.im/angularclass/angular2-webpack-starter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
> An Angular starter kit featuring [Angular 6](https://angular.io), [Ahead of Time Compile](https://angular.io/docs/ts/latest/cookbook/aot-compiler.html), [Router](https://angular.io/docs/ts/latest/guide/router.html), [Forms](https://angular.io/docs/ts/latest/guide/forms.html),
[Http](https://angular.io/docs/ts/latest/guide/server-communication.html),
[Services](https://gist.github.com/gdi2290/634101fec1671ee12b3e#_follow_@AngularClass_on_twitter),
[Tests](https://angular.io/docs/ts/latest/guide/testing.html), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [@types](https://www.npmjs.com/~types), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack](http://webpack.github.io/).
> If you're looking for Angular 1.x please use [NG6-starter](https://github.com/gdi2290/NG6-starter)
> If you're looking to learn about Webpack and ES6 Build Tools check out [ES6-build-tools](https://github.com/AngularClass/ES6-build-tools)
> If you're looking to learn TypeScript see [TypeStrong/learn-typescript](https://github.com/TypeStrong/learn-typescript)
> If you're looking for something easier to get started with then see the angular-seed that I also maintain [gdi2290/angular-seed](https://github.com/gdi2290/angular-seed)
This seed repo serves as an Angular starter for anyone looking to get up and running with Angular and TypeScript fast. Using a [Webpack 4](https://webpack.js.org) for building our files and assisting with boilerplate. We're also using Protractor for our end-to-end story and Karma for our unit tests.
* Best practices in file and application organization for Angular.
* Ready to go build system using Webpack for working with TypeScript.
* Angular examples that are ready to go when experimenting with Angular.
* A great Angular seed repo for anyone who wants to start their project.
* Ahead of Time (AoT) compile for rapid page loads of your production builds.
* Tree shaking to automatically remove unused code from your production bundle.
* Testing Angular code with Jasmine and Karma.
* Coverage with Istanbul and Karma
* End-to-end Angular app testing using Protractor.
* Type manager with @types
* Hot Module Replacement with Webpack and [@gdi2290/hmr](https://github.com/gdi2290/angular-hmr) and [@gdi2290/hmr-loader](https://github.com/PatrickJS/angular-hmr-loader)
### Quick start
**Make sure you have Node version >= 8.0 and (NPM >= 5 or [Yarn](https://yarnpkg.com) )**
> Clone/Download the repo then edit `app.component.ts` inside [`/src/app/app.component.ts`](/src/app/app.component.ts)
```bash
# clone our repo
# --depth 1 removes all but one .git commit history
git clone --depth 1 https://github.com/gdi2290/angular-starter.git
# change directory to our repo
cd angular-starter
# install the repo with npm
npm install
# start the server
npm start
# use Hot Module Replacement
npm run server:dev:hmr
# if you're in China use cnpm
# https://github.com/cnpm/cnpm
```
go to [http://0.0.0.0:3000](http://0.0.0.0:3000) or [http://localhost:3000](http://localhost:3000) in your browser
# Table of Contents
* [File Structure](#file-structure)
* [Getting Started](#getting-started)
* [Dependencies](#dependencies)
* [Installing](#installing)
* [Running the app](#running-the-app)
* [Configuration](#configuration)
* [AoT Don'ts](#aot-donts)
* [External Stylesheets](#external-stylesheets)
* [Contributing](#contributing)
* [TypeScript](#typescript)
* [@Types](#types)
* [Frequently asked questions](#frequently-asked-questions)
* [Support, Questions, or Feedback](#support-questions-or-feedback)
* [Deployment](#deployment)
* [License](#license)
## File Structure
We use the component approach in our starter. This is the new standard for developing Angular apps and a great way to ensure maintainable code by encapsulation of our behavior logic. A component is basically a self contained app usually in a single file or a folder with each concern as a file: style, template, specs, e2e, and component class. Here's how it looks:
```
angular-starter/
├──config/ * our configuration
| ├──build-utils.js * common config and shared functions for prod and dev
| ├──config.common.json * config for both environments prod and dev such title and description of index.html
| ├──config.dev.json * config for development environment
| ├──config.prod.json * config for production environment
│ │ (note: you can load your own config file, just set the evn ANGULAR_CONF_FILE with the path of your own file)
| ├──helpers.js * helper functions for our configuration files
| ├──spec-bundle.js * ignore this magic that sets up our Angular testing environment
| ├──karma.conf.js * karma config for our unit tests
| ├──protractor.conf.js * protractor config for our end-to-end tests
│ ├──webpack.common.js * common tasks for webpack build process shared for dev and prod
│ ├──webpack.dev.js * our development webpack config
│ ├──webpack.prod.js * our production webpack config
│ └──webpack.test.js * our testing webpack config
│
├──src/ * our source files that will be compiled to javascript
| ├──main.browser.ts * our entry file for our browser environment
│ │
| ├──index.html * Index.html: where we generate our index page
│ │
| ├──polyfills.ts * our polyfills file
│ │
│ ├──app/ * WebApp: folder
│ │ ├──app.component.spec.ts * a simple test of components in app.component.ts
│ │ ├──app.e2e.ts * a simple end-to-end test for /
│ │ └──app.component.ts * a simple version of our App component components
│ │
│ └──assets/ * static assets are served here
│ ├──icon/ * our list of icons from www.favicon-generator.org
│ ├──service-worker.js * ignore this. Web App service worker that's not complete yet
│ ├──robots.txt * for search engines to crawl your website
│ └──humans.txt * for humans to know who the developers are
│
│
├──tslint.json * typescript lint config
├──typedoc.json * typescript documentation generator
├──tsconfig.json * typescript config used outside webpack
├──tsconfig.webpack.json * config that webpack uses for typescript
├──package.json * what npm uses to manage its dependencies
└──webpack.config.js * webpack main configuration file
```
# Getting Started
## Dependencies
What you need to run this app:
* `node` and `npm` (`brew install node`)
* Ensure you're running the latest versions Node `v8.x.x`+ (or `v9.x.x`) and NPM `5.x.x`+
> If you have `nvm` installed, which is highly recommended (`brew install nvm`) you can do a `nvm install --lts && nvm use` in `$` to run with the latest Node LTS. You can also have this `zsh` done for you [automatically](https://github.com/creationix/nvm#calling-nvm-use-automatically-in-a-directory-with-a-nvmrc-file)
Once you have those, you should install these globals with `npm install --global`:
* `webpack` (`npm install --global webpack`)
* `webpack-dev-server` (`npm install --global webpack-dev-server`)
* `karma` (`npm install --global karma-cli`)
* `protractor` (`npm install --global protractor`)
* `typescript` (`npm install --global typescript`)
* `tslint` (`npm install --global tslint@4.5.1`)
## Installing
* `fork` this repo
* `clone` your fork
* `npm install webpack-dev-server rimraf webpack -g` to install required global dependencies
* `npm install` to install all dependencies or `yarn`
* `npm run server` to start the dev server in another tab
## Running the app
After you have installed all dependencies you can now run the app. Run `npm run server` to start a local server using `webpack-dev-server` which will watch, build (in-memory), and reload for you. The port will be displayed to you as `http://0.0.0.0:3000` (or if you prefer IPv6, if you're using `express` server, then it's `http://[::1]:3000/`).
### server
```bash
# development
npm run server
# production
npm run build:prod
npm run server:prod
```
## Other commands
## the following commands with npm can be used with yarn as well
### build files
```bash
# development
npm run build:dev
# production (jit)
npm run build:prod
# AoT
npm run build:aot
```
### hot module replacement
```bash
npm run server:dev:hmr
```
### watch and build files
```bash
npm run watch
```
### run unit tests
```bash
npm run test
```
### watch and run our tests
```bash
npm run watch:test
```
### run end-to-end tests
```bash
# update Webdriver (optional, done automatically by postinstall script)
npm run webdriver:update
# this will start a test server and launch Protractor
npm run e2e
```
### continuous integration (run unit tests and e2e tests together)
```bash
# this will test both your JIT and AoT builds
npm run ci
```
### run Protractor's elementExplorer (for end-to-end)
```bash
npm run e2e:live
```
### build Docker
```bash
npm run build:docker
```
# Configuration
Configuration files live in `config/` we are currently using webpack, karma, and protractor for different stages of your application
# AoT Don'ts
The following are some things that will make AoT compile fail.
- Don’t use require statements for your templates or styles, use styleUrls and templateUrls, the angular2-template-loader plugin will change it to require at build time.
- Don’t use default exports.
- Don’t use `form.controls.controlName`, use `form.get(‘controlName’)`
- Don’t use `control.errors?.someError`, use `control.hasError(‘someError’)`
- Don’t use functions in your providers, routes or declarations, export a function and then reference that function name
- @Inputs, @Outputs, View or Content Child(ren), Hostbindings, and any field you use from the template or annotate for Angular should be public
For more detailed guide on AoT's Do's and Don'ts refer to https://github.com/rangle/angular-2-aot-sandbox
# External Stylesheets
Any stylesheets (Sass or CSS) placed in the `src/styles` directory and imported into your project will automatically be compiled into an external `.css` and embedded in your production builds.
For example to use Bootstrap as an external stylesheet:
1) Create a `styles.scss` file (name doesn't matter) in the `src/styles` directory.
2) `npm install` the version of Bootstrap you want.
3) In `styles.scss` add `@import '~bootstrap/scss/bootstrap.scss';`
4) In `src/app/app.module.ts` add underneath the other import statements: `import '../styles/styles.scss';`
# Contributing
You can include more examples as components but they must introduce a new concept such as `Home` component (separate folders), and Todo (services). I'll accept pretty much everything so feel free to open a Pull-Request
# TypeScript
> To take full advantage of TypeScript with autocomplete you would have to install it globally and use an editor with the correct TypeScript plugins.
## Use latest TypeScript compiler
TypeScript 2.7.x includes everything you need. Make sure to upgrade, even if you installed TypeScript previously.
```
npm install --global typescript
```
## Use a TypeScript-aware editor
We have good experience using these editors:
* [Visual Studio Code](https://code.visualstudio.com/)
* [Webstorm 2018.1](https://www.jetbrains.com/webstorm/download/)
* [Atom](https://atom.io/) with [TypeScript plugin](https://atom.io/packages/atom-typescript)
* [Sublime Text](http://www.sublimetext.com/3) with [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation)
### Visual Studio Code + Debugger for Chrome
> Install [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome) and see docs for instructions to launch Chrome
The included `.vscode` automatically connects to the webpack development server on port `3000`.
# Types
> When you include a module that doesn't include Type Definitions inside of the module you can include external Type Definitions with @types
i.e, to have youtube api support, run this command in terminal:
```shell
npm i @types/youtube @types/gapi @types/gapi.youtube
```
In some cases where your code editor doesn't support Typescript 2 yet or these types weren't listed in ```tsconfig.json```, add these to **"src/custom-typings.d.ts"** to make peace with the compile check:
```es6
import '@types/gapi.youtube';
import '@types/gapi';
import '@types/youtube';
```
## Custom Type Definitions
When including 3rd party modules you also need to include the type definition for the module
if they don't provide one within the module. You can try to install it with @types
```
npm install @types/node
npm install @types/lodash
```
If you can't find the type definition in the registry we can make an ambient definition in
this file for now. For example
```typescript
declare module "my-module" {
export function doesSomething(value: string): string;
}
```
If you're prototyping and you will fix the types later you can also declare it as type any
```typescript
declare var assert: any;
declare var _: any;
declare var $: any;
```
If you're importing a module that uses Node.js modules which are CommonJS you need to import as
```typescript
import * as _ from 'lodash';
```
# Frequently asked questions
* What's the current browser support for Angular?
* Please view the updated list of [browser support for Angular](https://github.com/gdi2290/awesome-angular#current-browser-support-for-angular)
* Why is my service, aka provider, is not injecting parameter correctly?
* Please use `@Injectable()` for your service for typescript to correctly attach the metadata (this is a TypeScript problem)
* Where do I write my tests?
* You can write your tests next to your component files. See [`/src/app/home/home.component.spec.ts`](/src/app/home/home.component.spec.ts)
* How do I start the app when I get `EACCES` and `EADDRINUSE` errors?
* The `EADDRINUSE` error means the port `3000` is currently being used and `EACCES` is lack of permission for webpack to build files to `./dist/`
* How to use `sass` for css?
* * `loaders: ['raw-loader','sass-loader']` and `@Component({ styleUrls: ['./filename.scss'] })` see Wiki page [How to include SCSS in components](https://github.com/gdi2290/angular-starter/wiki/How-to-include-SCSS-in-components), or issue [#136](https://github.com/gdi2290/angular-starter/issues/136) for more information.
* How do I test a Service?
* See issue [#130](https://github.com/gdi2290/angular-starter/issues/130#issuecomment-158872648)
* How do I add `vscode-chrome-debug` support?
* The VS Code chrome debug extension support can be done via `launch.json` see issue [#144](https://github.com/gdi2290/angular-starter/issues/144#issuecomment-164063790)
* How do I make the repo work in a virtual machine?
* You need to use `0.0.0.0` so revert these changes [#205](https://github.com/gdi2290/angular-starter/pull/205/files)
* What are the naming conventions for Angular?
* please see issue [#185](https://github.com/gdi2290/angular-starter/issues/185) and PR [196](https://github.com/gdi2290/angular-starter/pull/196)
* How do I include bootstrap or jQuery?
* please see issue [#215](https://github.com/gdi2290/angular-starter/issues/215) and [#214](https://github.com/gdi2290/angular-starter/issues/214#event-511768416)
* How do I async load a component?
* see wiki [How-do-I-async-load-a-component-with-AsyncRoute](https://github.com/gdi2290/angular-starter/wiki/How-do-I-async-load-a-component-with-AsyncRoute)
* Error: Cannot find module 'tapable'
* Remove `node_modules/` and run `npm cache clean` then `npm install`
* How do I turn on Hot Module Replacement
* Run `npm run server:dev:hmr`
* `RangeError: Maximum call stack size exceeded`
* This is a problem with minifying Angular and it's recent JIT templates. If you set `mangle` to `false` then you should be good.
* Why is the size of my app larger in development?
* We are using inline source-maps and hot module replacement which will increase the bundle size.
* If you're in China
* check out https://github.com/cnpm/cnpm
* node-pre-gyp ERR in npm install (Windows)
* often happens when you're behind proxy and proxy wasn't configured in the npm as it tries to download binary package from the github and if it fails to do so, it will try to compile node-sass from the source codes
* install Python3 x86
* `Error:Error: Parse tsconfig error [{"messageText":"Unknown compiler option 'lib'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'strictNullChecks'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'baseUrl'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'paths'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'types'.","category":1,"code":5023}]`
* remove `node_modules/typescript` and run `npm install typescript@beta`. This repo now uses ts 2.0
* "There are multiple modules with names that only differ in casing"
* change `c:\[path to angular-starter]` to `C:\[path to angular-starter]` see [926#issuecomment-245223547](https://github.com/gdi2290/angular-starter/issues/926#issuecomment-245223547)
# Support, Questions, or Feedback
> Contact us anytime for anything about this repo or Angular
`@PatrickJS__` on twitter
# Deployment
## Docker
To run project you only need host machine with **operating system** with installed **git** (to clone this repo)
and [docker](https://www.docker.com/) and thats all - any other software is not needed
(other software like node.js etc. will be automatically downloaded and installed inside docker container during build step based on dockerfile).
### Install docker
#### MacOS:
`brew cask install docker`
And run docker by Mac bottom menu> launchpad > docker (on first run docker will ask you about password)
#### Ubuntu:
```
sudo apt-get update
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
sudo apt-add-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main'
sudo apt-get update
apt-cache policy docker-engine
sudo apt-get install -y docker-engine
sudo systemctl status docker # test: should be ‘active’
```
And add your user to docker group (to avoid `sudo` before using `docker` command in future):
```
sudo usermod -aG docker $(whoami)
```
and logout and login again.
### Build image
Because *node.js* is big memory consumer you need 1-2GB RAM or virtual memory to build docker image
(it was successfully tested on machine with 512MB RAM + 2GB virtual memory - building process take 7min)
Go to main project folder. To build image type:
`docker build -t angular-starter .`
The **angular-starter** name used in above commands is only example image name.
To remove intermediate images created by docker on build process, type:
`docker rmi -f $(docker images -f "dangling=true" -q)`
### Run image
To run created docker image on [localhost:8080](localhost:8080) type (parameter `-p 8080:80` is host:container port mapping)
`docker run --name angular-starter -p 8080:80 angular-starter &`
And that's all, you can open browser and go to [localhost:8080](localhost:8080).
### Build and Run image using docker-compose
To create and run docker image on [localhost:8080](localhost:8080) as part of large project you may use **docker-compose**. Type
`docker-compose up`
And that's all, you can open browser and go to [localhost:8080](localhost:8080).
### Run image on sub-domain
If you want to run image as virtual-host on sub-domain you must setup [proxy](https://github.com/jwilder/nginx-proxy). You should install proxy and set sub-domain in this way:
```
docker run -d -p 80:80 --name nginx-proxy -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy:alpine
```
And in your `/etc/hosts` file (linux) add line: `127.0.0.1 angular-starter.your-domain.com` or in yor hosting add
following DNS record (wildchar `*` is handy because when you add new sub-domain in future, you don't need to touch/add any DNS record)
```
Type: CNAME
Hostname: *.your-domain.com
Direct to: your-domain.com
TTL(sec): 43200
```
And now you are ready to run image on subdomain by:
```
docker run -e VIRTUAL_HOST=angular-starter.your-domain.com --name angular-starter angular-starter &
```
### Login into docker container
`docker exec -t -i angular-starter /bin/bash`
## Netlify
You can quickly create a free site to get started using this
starter kit in production on [Netlify](https://www.netlify.com/):
[](https://app.netlify.com/start/deploy?repository=https://github.com/AngularClass/angular-starter)
### Optional Integration with SonarQube (for continous code quality)
Assuming you have SonarQube 5.5.6 (LTS) installed
* Setup SonarQube with the [Sonar Typescript plugin](https://github.com/Pablissimo/SonarTsPlugin#installation) and the Generic Test Coverage plugin https://docs.sonarqube.org/display/PLUG/Generic+Test+Coverage
* Install sonar-scanner globally
```bash
npm install --global sonar-scanner
```
* Install the [Karma plugin for sonarqube](https://www.npmjs.com/package/karma-sonarqube-unit-reporter) as a dev dependency
```bash
npm install karma-sonarqube-unit-reporter --save-dev
```
* Sonar Host URL configuration:
Update [`sonar-project.properties`](sonar-project.properties) file for the property `sonar.host.url` to point to your SonarQube server. By default this assumes that the SonarQube server is running locally using the default port
```
sonar.host.url=<Sonar Host URL and Port>
```
* Run the unit tests with sonar reporter enabled
```bash
npm run test:sonar
```
* The test results collected in the results folder in the sonar compatible format
* Push results to SonarCube
```bash
sonar-scanner
```
* If working with SonarQube 6.x it supports [Generic Test Data](https://docs.sonarqube.org/display/SONAR/Generic+Test+Data)
* Modify the [karma.conf.js](config/karma.config.js) to set the appropriate version of the sonarQube
```es6
sonarQubeUnitReporter: {
sonarQubeVersion: '6.x',
}
```
___
enjoy — [**PatrickJS**](https://patrickjs.com)
___
# License
[MIT](/LICENSE)
================================================
FILE: config/build-utils.js
================================================
const ts = require('typescript');
const path = require('path');
const fs = require('fs');
const helpers = require('./helpers');
const APP_COMMON_CONFIG = require('./config.common.json');
const DEFAULT_METADATA = {
title: APP_COMMON_CONFIG.title,
description: APP_COMMON_CONFIG.description,
baseUrl: '/',
isDevServer: helpers.isWebpackDevServer(),
HMR: helpers.hasProcessFlag('hot'),
AOT: process.env.BUILD_AOT || helpers.hasNpmFlag('aot'),
E2E: !!process.env.BUILD_E2E,
WATCH: helpers.hasProcessFlag('watch'),
tsConfigPath: 'tsconfig.webpack.json',
/**
* This suffix is added to the environment.ts file, if not set the default environment file is loaded (development)
* To disable environment files set this to null
*/
envFileSuffix: ''
};
function supportES2015(tsConfigPath) {
if (!supportES2015.hasOwnProperty('supportES2015')) {
const tsTarget = readTsConfig(tsConfigPath).options.target;
supportES2015['supportES2015'] = tsTarget !== ts.ScriptTarget.ES3 && tsTarget !== ts.ScriptTarget.ES5;
}
return supportES2015['supportES2015'];
}
function readTsConfig(tsConfigPath) {
const configResult = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
return ts.parseJsonConfigFileContent(configResult.config, ts.sys,
path.dirname(tsConfigPath), undefined, tsConfigPath);
}
function getEnvFile(suffix) {
if (suffix && suffix[0] !== '.') {
suffix = '.' + suffix;
}
if (suffix === null) {
return;
}
let fileName = helpers.root(`src/environments/environment${suffix}.ts`);
if (fs.existsSync(fileName)) {
return fileName;
} else if (fs.existsSync(fileName = helpers.root('src/environments/environment.ts'))) {
console.warn(`Could not find environment file with suffix ${suffix}, loading default environment file`);
return fileName;
} else {
throw new Error('Environment file not found.')
}
}
/**
* Read the tsconfig to determine if we should prefer ES2015 modules.
* Load rxjs path aliases.
* https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#build-and-treeshaking
* @param supportES2015 Set to true when the output of typescript is >= ES6
*/
function rxjsAlias(supportES2015) {
try {
const rxjsPathMappingImport = supportES2015 ? 'rxjs/_esm2015/path-mapping' : 'rxjs/_esm5/path-mapping';
const rxPaths = require(rxjsPathMappingImport);
return rxPaths(helpers.root('node_modules'));
} catch (e) {
return {};
}
}
function ngcWebpackSetup(prod, metadata) {
if (!metadata) {
metadata = DEFAULT_METADATA;
}
const buildOptimizer = prod && metadata.AOT;
const sourceMap = true; // TODO: apply based on tsconfig value?
const ngcWebpackPluginOptions = {
skipCodeGeneration: !metadata.AOT,
sourceMap
};
const environment = getEnvFile(metadata.envFileSuffix);
if (environment) {
ngcWebpackPluginOptions.hostReplacementPaths = {
[helpers.root('src/environments/environment.ts')]: environment
}
}
if (!prod && metadata.WATCH) {
// Force commonjs module format for TS on dev watch builds.
ngcWebpackPluginOptions.compilerOptions = {
module: 'commonjs'
};
}
const buildOptimizerLoader = {
loader: '@angular-devkit/build-optimizer/webpack-loader',
options: {
sourceMap
}
};
const loaders = [
{
test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
use: buildOptimizer ? [ buildOptimizerLoader, '@ngtools/webpack' ] : [ '@ngtools/webpack' ]
},
...buildOptimizer
? [ { test: /\.js$/, use: [ buildOptimizerLoader ] } ]
: []
];
return {
loaders,
plugin: ngcWebpackPluginOptions
};
}
exports.DEFAULT_METADATA = DEFAULT_METADATA;
exports.supportES2015 = supportES2015;
exports.readTsConfig = readTsConfig;
exports.getEnvFile = getEnvFile;
exports.rxjsAlias = rxjsAlias;
exports.ngcWebpackSetup = ngcWebpackSetup;
================================================
FILE: config/config.common.json
================================================
{
"title": "Angular Starter by @gdi2290 from @TipeIO",
"description": "An Angular starter kit featuring Angular 5, Ahead of Time Compile, Router, Forms, Http, Services, Tests, E2E), Karma, Protractor, Jasmine, Istanbul, TypeScript, @types, TsLint, Codelyzer, Hot Module Replacement, and Webpack by Tipe.io"
}
================================================
FILE: config/config.dev.json
================================================
{
"firebase": {
"apiKey": "",
"authDomain": "XXXXXX.firebaseapp.com",
"databaseURL": "https://XXXXXX.firebaseio.com",
"projectId": "XXXXXX",
"storageBucket": "XXXXXX.appspot.com",
"messagingSenderId": "000000000000"
}
}
================================================
FILE: config/config.prod.json
================================================
{
"firebase": {
"apiKey": "",
"authDomain": "XXXXXX.firebaseapp.com",
"databaseURL": "https://XXXXXX.firebaseio.com",
"projectId": "XXXXXX",
"storageBucket": "XXXXXX.appspot.com",
"messagingSenderId": "000000000000"
},
"gtmKey" : "GTM-XXXXXXX"
}
================================================
FILE: config/empty.js
================================================
module.exports = {
hmrModule: function(ngmodule) {
return ngmodule;
},
NgProbeToken: {},
HmrState: function() {},
_createConditionalRootRenderer: function(rootRenderer, extraTokens, coreTokens) {
return rootRenderer;
},
__platform_browser_private__: {}
};
================================================
FILE: config/github-deploy/index.js
================================================
const execSync = require('child_process').execSync;
/**
* Used to merge webpack configs.
*/
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const HtmlWebpackPlugin = require('html-webpack-plugin');
const helpers = require('../helpers');
const REPO_NAME_RE = /Push {2}URL: ((git@github\.com:)|(https:\/\/github\.com\/)).+\/(.+)\.git/;
function getWebpackConfigModule(options) {
if (options.githubDev) {
return require('../webpack.dev.js');
} else if (options.githubProd) {
return require('../webpack.prod.js');
} else {
throw new Error('Invalid compile option.');
}
}
function getRepoName(remoteName) {
remoteName = remoteName || 'origin';
var stdout = execSync('git remote show ' + remoteName),
match = REPO_NAME_RE.exec(stdout);
if (!match) {
throw new Error('Could not find a repository on remote ' + remoteName);
} else {
return match[4];
}
}
function stripTrailing(str, char) {
if (str[0] === char) {
str = str.substr(1);
}
if (str.substr(-1) === char) {
str = str.substr(0, str.length - 1);
}
return str;
}
/**
* Given a string remove trailing slashes and adds 1 slash at the end of the string.
*
* Example:
* safeUrl('/value/')
* // 'value/'
*
* @param url
* @returns {string}
*/
function safeUrl(url) {
const stripped = stripTrailing(url || '', '/');
return stripped ? stripped + '/' : '';
}
function replaceHtmlWebpackPlugin(plugins, ghRepoName) {
for (var i=0; i<plugins.length; i++) {
if (plugins[i] instanceof HtmlWebpackPlugin) {
/**
* Remove the old instance of the html plugin.
*/
const htmlPlug = plugins.splice(i, 1)[0];
const METADATA = webpackMerge(htmlPlug.options.metadata, {
/**
* Prefixing the REPO name to the baseUrl for router support.
* This also means all resource URIs (CSS/Images/JS) will have this prefix added by the browser
* unless they are absolute (start with '/'). We will handle it via `output.publicPath`
*/
baseUrl: '/' + ghRepoName + '/' + safeUrl(htmlPlug.options.metadata.baseUrl)
});
/**
* Add the new instance of the html plugin.
*/
plugins.splice(i, 0, new HtmlWebpackPlugin({
template: htmlPlug.options.template,
title: htmlPlug.options.title,
chunksSortMode: htmlPlug.options.chunksSortMode,
metadata: METADATA,
inject: htmlPlug.options.inject
}));
return;
}
}
}
exports.getWebpackConfigModule = getWebpackConfigModule;
exports.getRepoName = getRepoName;
exports.safeUrl = safeUrl;
exports.replaceHtmlWebpackPlugin = replaceHtmlWebpackPlugin;
================================================
FILE: config/head-config.common.js
================================================
/**
* Configuration for head elements added during the creation of index.html.
*
* All href attributes are added the publicPath (if exists) by default.
* You can explicitly hint to prefix a publicPath by setting a boolean value to a key that has
* the same name as the attribute you want to operate on, but prefix with =
*
* Example:
* { name: 'msapplication-TileImage', content: '/assets/icon/ms-icon-144x144.png', '=content': true },
* Will prefix the publicPath to content.
*
* { rel: 'apple-touch-icon', sizes: '57x57', href: '/assets/icon/apple-icon-57x57.png', '=href': false },
* Will not prefix the publicPath on href (href attributes are added by default
*
*/
module.exports = {
link: [
/**
* <link> tags for 'apple-touch-icon' (AKA Web Clips).
*/
{ rel: 'apple-touch-icon', sizes: '57x57', href: '/assets/icon/apple-icon-57x57.png' },
{ rel: 'apple-touch-icon', sizes: '60x60', href: '/assets/icon/apple-icon-60x60.png' },
{ rel: 'apple-touch-icon', sizes: '72x72', href: '/assets/icon/apple-icon-72x72.png' },
{ rel: 'apple-touch-icon', sizes: '76x76', href: '/assets/icon/apple-icon-76x76.png' },
{ rel: 'apple-touch-icon', sizes: '114x114', href: '/assets/icon/apple-icon-114x114.png' },
{ rel: 'apple-touch-icon', sizes: '120x120', href: '/assets/icon/apple-icon-120x120.png' },
{ rel: 'apple-touch-icon', sizes: '144x144', href: '/assets/icon/apple-icon-144x144.png' },
{ rel: 'apple-touch-icon', sizes: '152x152', href: '/assets/icon/apple-icon-152x152.png' },
{ rel: 'apple-touch-icon', sizes: '180x180', href: '/assets/icon/apple-icon-180x180.png' },
/**
* <link> tags for android web app icons
*/
{ rel: 'icon', type: 'image/png', sizes: '192x192', href: '/assets/icon/android-icon-192x192.png' },
/**
* <link> tags for favicons
*/
{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/assets/icon/favicon-32x32.png' },
{ rel: 'icon', type: 'image/png', sizes: '96x96', href: '/assets/icon/favicon-96x96.png' },
{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/assets/icon/favicon-16x16.png' },
/**
* <link> tags for a Web App Manifest
*/
{ rel: 'manifest', href: '/assets/manifest.json' }
],
meta: [
{ name: 'msapplication-TileColor', content: '#00bcd4' },
{ name: 'msapplication-TileImage', content: '/assets/icon/ms-icon-144x144.png', '=content': true },
{ name: 'theme-color', content: '#00bcd4' }
]
};
================================================
FILE: config/helpers.js
================================================
/**
* @author: tipe.io
*/
const path = require('path');
const EVENT = process.env.npm_lifecycle_event || '';
/**
* Helper functions.
*/
var ROOT = path.resolve(__dirname, '..');
function hasProcessFlag(flag) {
return process.argv.join('').indexOf(flag) > -1;
}
function hasNpmFlag(flag) {
return EVENT.includes(flag);
}
function isWebpackDevServer() {
return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1]));
}
var root = path.join.bind(path, ROOT);
exports.hasProcessFlag = hasProcessFlag;
exports.hasNpmFlag = hasNpmFlag;
exports.isWebpackDevServer = isWebpackDevServer;
exports.root = root;
================================================
FILE: config/html-elements-plugin/index.js
================================================
const RE_ENDS_WITH_BS = /\/$/;
/**
* Create an HTML tag with attributes from a map.
*
* Example:
* createTag('link', { rel: "manifest", href: "/assets/manifest.json" })
* // <link rel="manifest" href="/assets/manifest.json">
* @param tagName The name of the tag
* @param attrMap A Map of attribute names (keys) and their values.
* @param publicPath a path to add to eh start of static asset url
* @returns {string}
*/
function createTag(tagName, attrMap, publicPath) {
publicPath = publicPath || '';
/**
* Add trailing slash if we have a publicPath and it doesn't have one.
*/
if (publicPath && !RE_ENDS_WITH_BS.test(publicPath)) {
publicPath += '/';
}
const attributes = Object.getOwnPropertyNames(attrMap)
.filter(function (name) {
return name[0] !== '=';
})
.map(function (name) {
var value = attrMap[name];
if (publicPath) {
/**
* Check if we have explicit instruction, use it if so (e.g: =herf: false)
* if no instruction, use public path if it's href attribute.
*/
const usePublicPath = attrMap.hasOwnProperty('=' + name) ? !!attrMap['=' + name] : name === 'href';
if (usePublicPath) {
/**
* Remove a starting trailing slash if the value has one so we wont have //
*/
value = publicPath + (value[0] === '/' ? value.substr(1) : value);
}
}
return `${name}="${value}"`;
});
const closingTag = tagName === 'script' ? '</script>' : '';
return `<${tagName} ${attributes.join(' ')}>${closingTag}`;
}
/**
* Returns a string representing all html elements defined in a data source.
*
* Example:
*
* const ds = {
* link: [
* { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" }
* ],
* meta: [
* { name: "msapplication-TileColor", content: "#00bcd4" }
* ]
* }
*
* getHeadTags(ds);
* // "<link rel="apple-touch-icon" sizes="57x57" href="/assets/icon/apple-icon-57x57.png">"
* "<meta name="msapplication-TileColor" content="#00bcd4">"
*
* @returns {string}
*/
function getHtmlElementString(dataSource, publicPath) {
return Object.getOwnPropertyNames(dataSource)
.map(function (name) {
if (Array.isArray(dataSource[name])) {
return dataSource[name].map(function (attrs) {
return createTag(name, attrs, publicPath);
});
} else {
return [createTag(name, dataSource[name], publicPath)];
}
})
.reduce(function (arr, curr) {
return arr.concat(curr);
}, [])
.join('\n\t');
}
class HtmlElementsPlugin {
constructor(locations) {
this.locations = locations;
}
/* istanbul ignore next: this would be integration tests */
apply(compiler) {
compiler.hooks.compilation.tap('HtmlElementsPlugin', compilation => {
compilation.options.htmlElements = compilation.options.htmlElements || {};
compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync('HtmlElementsPlugin',
(htmlPluginData, callback) => {
const locations = this.locations;
if (locations) {
const publicPath = htmlPluginData.assets.publicPath;
Object.getOwnPropertyNames(locations).forEach(function (loc) {
compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath);
});
}
// return htmlPluginData;
callback(null, htmlPluginData);
}
);
});
}
}
module.exports = HtmlElementsPlugin;
================================================
FILE: config/karma.conf.js
================================================
/**
* @author: tipe.io
*/
module.exports = function (config) {
const testWebpackConfig = require('./webpack.test.js')({ env: 'test' });
const configuration = {
/**
* Base path that will be used to resolve all patterns (e.g. files, exclude).
*/
basePath: '',
/**
* Frameworks to use
*
* available frameworks: https://npmjs.org/browse/keyword/karma-adapter
*/
frameworks: ['jasmine'],
/**
* List of files to exclude.
*/
exclude: [],
client: {
captureConsole: false
},
/**
* List of files / patterns to load in the browser
*
* we are building the test environment in ./spec-bundle.js
*/
files: [
{ pattern: './config/spec-bundle.js', watched: false },
{ pattern: './src/assets/**/*', watched: false, included: false, served: true, nocache: false }
],
/**
* By default all assets are served at http://localhost:[PORT]/base/
*/
proxies: {
"/assets/": "/base/src/assets/"
},
/**
* Preprocess matching files before serving them to the browser
* available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
*/
preprocessors: { './config/spec-bundle.js': ['coverage', 'webpack', 'sourcemap'] },
/**
* Webpack Config at ./webpack.test.js
*/
webpack: testWebpackConfig,
coverageReporter: {
type: 'in-memory'
},
remapCoverageReporter: {
'text-summary': null,
json: './coverage/coverage.json',
html: './coverage/html'
},
/**
* Webpack please don't spam the console when running in karma!
*/
webpackMiddleware: {
/**
* webpack-dev-middleware configuration
* i.e.
*/
logLevel: 'warn',
/**
* and use stats to turn off verbose output
*/
stats: {
/**
* options i.e.
*/
chunks: false
}
},
/**
* Test results reporter to use
*
* possible values: 'dots', 'progress'
* available reporters: https://npmjs.org/browse/keyword/karma-reporter
*/
reporters: ['mocha', 'coverage', 'remap-coverage'],
/**
* Web server port.
*/
port: 9876,
/**
* enable / disable colors in the output (reporters and logs)
*/
colors: true,
/**
* Level of logging
* possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
*/
logLevel: config.LOG_WARN,
/**
* enable / disable watching file and executing tests whenever any file changes
*/
autoWatch: true,
/**
* start these browsers
* available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
*/
browsers: [
'ChromeTravisCi'
],
customLaunchers: {
ChromeTravisCi: {
base: 'ChromeHeadless',
flags: ['--no-sandbox', '--disable-gpu']
}
},
/**
* Continuous Integration mode
* if true, Karma captures browsers, runs the tests and exits
*/
singleRun: false,
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
/**
* For slower machines you may need to have a longer browser
* wait time . Uncomment the line below if required.
*/
// browserNoActivityTimeout: 30000
};
// Optional Sonar Qube Reporter
if (process.env.SONAR_QUBE) {
// SonarQube reporter plugin configuration
configuration.sonarQubeUnitReporter = {
sonarQubeVersion: '5.x',
outputFile: 'reports/ut_report.xml',
overrideTestDescription: true,
testPath: 'src/app',
testFilePattern: '.spec.ts',
useBrowserName: false
};
// Additional lcov format required for
// sonarqube
configuration.remapCoverageReporter.lcovonly = './coverage/coverage.lcov';
configuration.reporters.push('sonarqubeUnit');
}
if (process.env.TRAVIS) {
configuration.browsers = [
'ChromeTravisCi'
];
}
config.set(configuration);
};
================================================
FILE: config/nginx-custom.conf
================================================
server {
listen 80;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 1100;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 5;
root /usr/share/nginx/html;
location / {
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
================================================
FILE: config/protractor.conf.js
================================================
/**
* @author: tipe.io
*/
require('ts-node/register');
var helpers = require('./helpers');
exports.config = {
baseUrl: 'http://localhost:3000/',
/**
* Use `npm run e2e`
*/
specs: [
helpers.root('src/**/**.e2e.ts'),
helpers.root('src/**/*.e2e.ts')
],
exclude: [],
framework: 'jasmine',
allScriptsTimeout: 11000,
jasmineNodeOpts: {
showTiming: true,
showColors: true,
isVerbose: false,
includeStackTrace: false,
defaultTimeoutInterval: 40000
},
directConnect: true,
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=800x600", "--no-sandbox" ]
}
},
onPrepare: function() {
browser.ignoreSynchronization = true;
},
/**
* Angular 2 configuration
*
* useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching
* `rootEl`
*/
useAllAngular2AppRoots: true,
SELENIUM_PROMISE_MANAGER: false,
};
================================================
FILE: config/resource-override.js
================================================
================================================
FILE: config/spec-bundle.js
================================================
/**
* @author: tipe.io
*/
/**
* When testing with webpack and ES6, we have to do some extra
* things to get testing to work right. Because we are gonna write tests
* in ES6 too, we have to compile those as well. That's handled in
* karma.conf.js with the karma-webpack plugin. This is the entry
* file for webpack test. Just like webpack will create a bundle.js
* file for our client, when we run test, it will compile and bundle them
* all here! Crazy huh. So we need to do some setup
*/
Error.stackTraceLimit = Infinity;
require('core-js/es6');
require('core-js/es7/reflect');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy'); // since zone.js 0.6.15
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');
testing.TestBed.initTestEnvironment(
browser.BrowserDynamicTestingModule,
browser.platformBrowserDynamicTesting()
);
/**
* Ok, this is kinda crazy. We can use the context method on
* require that webpack created in order to tell webpack
* what files we actually want to require or import.
* Below, context will be a function/object with file names as keys.
* Using that regex we are saying look in ../src then find
* any file that ends with spec.ts and get its path. By passing in true
* we say do this recursively
*/
var testContext = require.context('../src', true, /\.spec\.ts/);
/**
* Get all the files, for each file, call the context function
* that will require the file and load it up here. Context will
* loop and require those spec files here
*/
function requireAll(requireContext) {
return requireContext.keys().map(requireContext);
}
/**
* Requires and returns all modules that match
*/
var modules = requireAll(testContext);
================================================
FILE: config/webpack.common.js
================================================
/**
* @author: tipe.io
*/
const helpers = require('./helpers');
/**
* Webpack Plugins
*
* problem with copy-webpack-plugin
*/
const DefinePlugin = require('webpack/lib/DefinePlugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlElementsPlugin = require('./html-elements-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackInlineManifestPlugin = require('webpack-inline-manifest-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;
const buildUtils = require('./build-utils');
/**
* Webpack configuration
*
* See: https://webpack.js.org/configuration/
*/
module.exports = function(options) {
const isProd = options.env === 'production';
const APP_CONFIG = require(process.env.ANGULAR_CONF_FILE || (isProd ? './config.prod.json' : './config.dev.json'));
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, options.metadata || {});
const GTM_API_KEY = process.env.GTM_API_KEY || APP_CONFIG.gtmKey;
const ngcWebpackConfig = buildUtils.ngcWebpackSetup(isProd, METADATA);
const supportES2015 = buildUtils.supportES2015(METADATA.tsConfigPath);
const entry = {
polyfills: './src/polyfills.browser.ts',
main: './src/main.browser.ts'
};
Object.assign(ngcWebpackConfig.plugin, {
tsConfigPath: METADATA.tsConfigPath,
mainPath: entry.main
});
return {
/**
* The entry point for the bundle
* Our Angular.js app
*
* See: https://webpack.js.org/configuration/entry-context/#entry
*/
entry: entry,
/**
* Options affecting the resolving of modules.
*
* See: https://webpack.js.org/configuration/resolve/
*/
resolve: {
mainFields: [...(supportES2015 ? ['es2015'] : []), 'browser', 'module', 'main'],
/**
* An array of extensions that should be used to resolve modules.
*
* See: https://webpack.js.org/configuration/resolve/#resolve-extensions
*/
extensions: ['.ts', '.js', '.json'],
/**
* An array of directory names to be resolved to the current directory
*/
modules: [helpers.root('src'), helpers.root('node_modules')],
/**
* Add support for lettable operators.
*
* For existing codebase a refactor is required.
* All rxjs operator imports (e.g. `import 'rxjs/add/operator/map'` or `import { map } from `rxjs/operator/map'`
* must change to `import { map } from 'rxjs/operators'` (note that all operators are now under that import.
* Additionally some operators have changed to to JS keyword constraints (do => tap, catch => catchError)
*
* Remember to use the `pipe()` method to chain operators, this functinoally makes lettable operators similar to
* the old operators usage paradigm.
*
* For more details see:
* https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#build-and-treeshaking
*
* If you are not planning on refactoring your codebase (or not planning on using imports from `rxjs/operators`
* comment out this line.
*
* BE AWARE that not using lettable operators will probably result in significant payload added to your bundle.
*/
alias: buildUtils.rxjsAlias(supportES2015)
},
/**
* Options affecting the normal modules.
*
* See: https://webpack.js.org/configuration/module/
*/
module: {
rules: [
...ngcWebpackConfig.loaders,
/**
* To string and css loader support for *.css files (from Angular components)
* Returns file content as string
*
*/
{
test: /\.css$/,
use: ['to-string-loader', 'css-loader'],
exclude: [helpers.root('src', 'styles')]
},
/**
* To string and sass loader support for *.scss files (from Angular components)
* Returns compiled css content as string
*
*/
{
test: /\.scss$/,
use: ['to-string-loader', 'css-loader', 'sass-loader'],
exclude: [helpers.root('src', 'styles')]
},
/**
* Raw loader support for *.html
* Returns file content as string
*
* See: https://github.com/webpack/raw-loader
*/
{
test: /\.html$/,
use: 'raw-loader',
exclude: [helpers.root('src/index.html')]
},
/**
* File loader for supporting images, for example, in CSS files.
*/
{
test: /\.(jpg|png|gif)$/,
use: 'file-loader'
},
/* File loader for supporting fonts, for example, in CSS files.
*/
{
test: /\.(eot|woff2?|svg|ttf)([\?]?.*)$/,
use: 'file-loader'
}
]
},
/**
* Add additional plugins to the compiler.
*
* See: https://webpack.js.org/configuration/plugins/
*/
plugins: [
/**
* Plugin: DefinePlugin
* Description: Define free variables.
* Useful for having development builds with debug logging or adding global constants.
*
* Environment helpers
*
* See: https://webpack.js.org/plugins/define-plugin/
*/
// NOTE: when adding more properties make sure you include them in custom-typings.d.ts
new DefinePlugin({
ENV: JSON.stringify(METADATA.ENV),
HMR: METADATA.HMR,
AOT: METADATA.AOT,
'process.env.ENV': JSON.stringify(METADATA.ENV),
'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
'process.env.HMR': METADATA.HMR
// 'FIREBASE_CONFIG': JSON.stringify(APP_CONFIG.firebase),
}),
/**
* Plugin: CopyWebpackPlugin
* Description: Copy files and directories in webpack.
*
* Copies project static assets.
*
* See: https://www.npmjs.com/package/copy-webpack-plugin
*/
new CopyWebpackPlugin(
[{ from: 'src/assets', to: 'assets' }, { from: 'src/meta' }],
isProd ? { ignore: ['mock-data/**/*'] } : undefined
),
/*
* Plugin: HtmlWebpackPlugin
* Description: Simplifies creation of HTML files to serve your webpack bundles.
* This is especially useful for webpack bundles that include a hash in the filename
* which changes every compilation.
*
* See: https://github.com/ampedandwired/html-webpack-plugin
*/
new HtmlWebpackPlugin({
template: 'src/index.html',
title: METADATA.title,
chunksSortMode: function(a, b) {
const entryPoints = ['inline', 'polyfills', 'sw-register', 'styles', 'vendor', 'main'];
return entryPoints.indexOf(a.names[0]) - entryPoints.indexOf(b.names[0]);
},
metadata: METADATA,
gtmKey: GTM_API_KEY,
inject: 'body',
xhtml: true,
minify: isProd
? {
caseSensitive: true,
collapseWhitespace: true,
keepClosingSlash: true
}
: false
}),
/**
* Plugin: ScriptExtHtmlWebpackPlugin
* Description: Enhances html-webpack-plugin functionality
* with different deployment options for your scripts including:
*
* See: https://github.com/numical/script-ext-html-webpack-plugin
*/
new ScriptExtHtmlWebpackPlugin({
sync: /inline|polyfills|vendor/,
defaultAttribute: 'async',
preload: [/polyfills|vendor|main/],
prefetch: [/chunk/]
}),
/**
* Plugin: HtmlElementsPlugin
* Description: Generate html tags based on javascript maps.
*
* If a publicPath is set in the webpack output configuration, it will be automatically added to
* href attributes, you can disable that by adding a "=href": false property.
* You can also enable it to other attribute by settings "=attName": true.
*
* The configuration supplied is map between a location (key) and an element definition object (value)
* The location (key) is then exported to the template under then htmlElements property in webpack configuration.
*
* Example:
* Adding this plugin configuration
* new HtmlElementsPlugin({
* headTags: { ... }
* })
*
* Means we can use it in the template like this:
* <%= webpackConfig.htmlElements.headTags %>
*
* Dependencies: HtmlWebpackPlugin
*/
new HtmlElementsPlugin({
headTags: require('./head-config.common')
}),
new AngularCompilerPlugin(ngcWebpackConfig.plugin),
/**
* Plugin: WebpackInlineManifestPlugin
* Inline Webpack's manifest.js in index.html
*
* https://github.com/almothafar/webpack-inline-manifest-plugin
*/
new WebpackInlineManifestPlugin()
],
/**
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.js.org/configuration/node/
*/
node: {
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
};
};
================================================
FILE: config/webpack.dev.js
================================================
/**
* @author: tipe.io
*/
const helpers = require('./helpers');
const buildUtils = require('./build-utils');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
/**
* Webpack Plugins
*/
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
/**
* Webpack configuration
*
* See: https://webpack.js.org/configuration/
*/
module.exports = function(options) {
const ENV = (process.env.ENV = process.env.NODE_ENV = 'development');
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 3000;
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
host: HOST,
port: PORT,
ENV: ENV,
HMR: helpers.hasProcessFlag('hot'),
PUBLIC: process.env.PUBLIC_DEV || HOST + ':' + PORT
});
return webpackMerge(commonConfig({ env: ENV, metadata: METADATA }), {
mode: 'development',
devtool: 'inline-source-map',
/**
* Options affecting the output of the compilation.
*
* See: https://webpack.js.org/configuration/output/
*/
output: {
/**
* The output directory as absolute path (required).
*
* See: https://webpack.js.org/configuration/output/#output-path
*/
path: helpers.root('dist'),
/**
* Specifies the name of each output file on disk.
* IMPORTANT: You must not specify an absolute path here!
*
* See: https://webpack.js.org/configuration/output/#output-filename
*/
filename: '[name].bundle.js',
/**
* The filename of the SourceMaps for the JavaScript files.
* They are inside the output.path directory.
*
* See: https://webpack.js.org/configuration/output/#output-sourcemapfilename
*/
sourceMapFilename: '[file].map',
/** The filename of non-entry chunks as relative path
* inside the output.path directory.
*
* See: https://webpack.js.org/configuration/output/#output-chunkfilename
*/
chunkFilename: '[id].chunk.js',
library: 'ac_[name]',
libraryTarget: 'var'
},
module: {
rules: [
/**
* Css loader support for *.css files (styles directory only)
* Loads external css styles into the DOM, supports HMR
*
*/
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
include: [helpers.root('src', 'styles')]
},
/**
* Sass loader support for *.scss files (styles directory only)
* Loads external sass styles into the DOM, supports HMR
*
*/
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: [helpers.root('src', 'styles')]
}
]
},
plugins: [
/**
* Plugin LoaderOptionsPlugin (experimental)
*
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({
debug: true,
options: {}
})
],
/**
* Webpack Development Server configuration
* Description: The webpack-dev-server is a little node.js Express server.
* The server emits information about the compilation state to the client,
* which reacts to those events.
*
* See: https://webpack.js.org/configuration/dev-server/
*/
devServer: {
port: METADATA.port,
host: METADATA.host,
hot: METADATA.HMR,
public: METADATA.PUBLIC,
historyApiFallback: true,
watchOptions: {
// if you're using Docker you may need this
// aggregateTimeout: 300,
// poll: 1000,
ignored: /node_modules/
},
/**
* Here you can access the Express app object and add your own custom middleware to it.
*
* See: https://webpack.js.org/configuration/dev-server/
*/
setup: function(app) {
// For example, to define custom handlers for some paths:
// app.get('/some/path', function(req, res) {
// res.json({ custom: 'response' });
// });
}
},
/**
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.js.org/configuration/node/
*/
node: {
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false,
fs: 'empty'
}
});
};
================================================
FILE: config/webpack.github-deploy.js
================================================
/**
* @author: tipe.io
*/
const fs = require('fs');
const path = require('path');
const helpers = require('./helpers');
const ghDeploy = require('./github-deploy');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
/**
* Webpack Constants
*/
const GIT_REMOTE_NAME = 'origin';
const COMMIT_MESSAGE = 'Updates';
const GH_REPO_NAME = ghDeploy.getRepoName(GIT_REMOTE_NAME);
module.exports = function(options) {
const webpackConfigFactory = ghDeploy.getWebpackConfigModule(options); // the settings that are common to prod and dev
const webpackConfig = webpackConfigFactory(options);
/**
* Replace the instance of HtmlWebpackPlugin with an updated one.
*/
ghDeploy.replaceHtmlWebpackPlugin(webpackConfig.plugins, GH_REPO_NAME);
return webpackMerge(webpackConfig, {
output: {
/**
* The public path is set to the REPO name.
*
* `HtmlElementsPlugin` will add it to all resources url's created by it.
* `HtmlWebpackPlugin` will add it to all webpack bundels/chunks.
*
* In theory publicPath shouldn't be used since the browser should automatically prefix the
* `baseUrl` into all URLs, however this is not the case when the URL is absolute (start with /)
*
* It's important to prefix & suffix the repo name with a slash (/).
* Prefixing so every resource will be absolute (otherwise it will be url.com/repoName/repoName...
* Suffixing since chunks will not do it automatically (testes against about page)
*/
publicPath: '/' + GH_REPO_NAME + '/' + ghDeploy.safeUrl(webpackConfig.output.publicPath)
},
plugins: [
function() {
this.plugin('done', function(stats) {
console.log('Starting deployment to GitHub.');
const logger = function(msg) {
console.log(msg);
};
const options = {
logger: logger,
remote: GIT_REMOTE_NAME,
message: COMMIT_MESSAGE,
dotfiles: true // for .nojekyll
};
/**
* Since GitHub moved to Jekyll 3.3, their server ignores the "node_modules" and "vendors" folder by default.
* but, as of now, it also ignores "vendors*" files.
* This means vendor.bundle.js or vendor.[chunk].bundle.js will return 404.
* this is the fix for now.
*/
fs.writeFileSync(path.join(webpackConfig.output.path, '.nojekyll'), '');
const ghpages = require('gh-pages');
ghpages.publish(webpackConfig.output.path, options, function(err) {
if (err) {
console.log('GitHub deployment done. STATUS: ERROR.');
throw err;
} else {
console.log('GitHub deployment done. STATUS: SUCCESS.');
}
});
});
}
]
});
};
================================================
FILE: config/webpack.prod.js
================================================
/**
* @author: tipe.io
*/
const helpers = require('./helpers');
const buildUtils = require('./build-utils');
/**
* Used to merge webpack configs
*/
const webpackMerge = require('webpack-merge');
/**
* The settings that are common to prod and dev
*/
const commonConfig = require('./webpack.common.js');
/**
* Webpack Plugins
*/
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HashedModuleIdsPlugin = require('webpack/lib/HashedModuleIdsPlugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
/***
* Ref: https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options
* @param supportES2015
* @param enableCompress disabling compress could improve the performance, see https://github.com/webpack/webpack/issues/4558#issuecomment-352255789
* @returns {{ecma: number, warnings: boolean, ie8: boolean, mangle: boolean, compress: {pure_getters: boolean, passes: number}, output: {ascii_only: boolean, comments: boolean}}}
*/
function getUglifyOptions(supportES2015, enableCompress) {
const uglifyCompressOptions = {
pure_getters: true /* buildOptimizer */,
// PURE comments work best with 3 passes.
// See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
passes: 2 /* buildOptimizer */
};
return {
ecma: supportES2015 ? 6 : 5,
warnings: false, // TODO verbose based on option?
ie8: false,
mangle: true,
compress: enableCompress ? uglifyCompressOptions : false,
output: {
ascii_only: true,
comments: false
}
};
}
module.exports = function(env) {
const ENV = (process.env.NODE_ENV = process.env.ENV = 'production');
const supportES2015 = buildUtils.supportES2015(buildUtils.DEFAULT_METADATA.tsConfigPath);
const sourceMapEnabled = process.env.SOURCE_MAP === '1';
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8080,
ENV: ENV,
HMR: false
});
// set environment suffix so these environments are loaded.
METADATA.envFileSuffix = METADATA.E2E ? 'e2e.prod' : 'prod';
return webpackMerge(commonConfig({ env: ENV, metadata: METADATA }), {
mode: 'production',
devtool: 'source-map',
/**
* Options affecting the output of the compilation.
*
* See: https://webpack.js.org/configuration/output/
*/
output: {
/**
* The output directory as absolute path (required).
*
* See: https://webpack.js.org/configuration/output/#output-path
*/
path: helpers.root('dist'),
/**
* Specifies the name of each output file on disk.
* IMPORTANT: You must not specify an absolute path here!
*
* See: https://webpack.js.org/configuration/output/#output-filename
*/
filename: '[name].[chunkhash].bundle.js',
/**
* The filename of the SourceMaps for the JavaScript files.
* They are inside the output.path directory.
*
* See: https://webpack.js.org/configuration/output/#output-sourcemapfilename
*/
sourceMapFilename: '[file].map',
/**
* The filename of non-entry chunks as relative path
* inside the output.path directory.
*
* See: https://webpack.js.org/configuration/output/#output-chunkfilename
*/
chunkFilename: '[name].[chunkhash].chunk.js'
},
module: {
rules: [
/**
* Extract CSS files from .src/styles directory to external CSS file
*/
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
include: [helpers.root('src', 'styles')]
},
/**
* Extract and compile SCSS files from .src/styles directory to external CSS file
*/
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
include: [helpers.root('src', 'styles')]
}
]
},
optimization: {
minimizer: [
/**
* Plugin: UglifyJsPlugin
* Description: Minimize all JavaScript output of chunks.
* Loaders are switched into minimizing mode.
*
* See: https://webpack.js.org/plugins/uglifyjs-webpack-plugin/
*
* NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
*/
new UglifyJsPlugin({
sourceMap: sourceMapEnabled,
parallel: true,
cache: helpers.root('webpack-cache/uglify-cache'),
uglifyOptions: getUglifyOptions(supportES2015, true)
})
],
splitChunks: {
chunks: 'all'
}
},
/**
* Add additional plugins to the compiler.
*
* See: https://webpack.js.org/configuration/plugins/
*/
plugins: [
new MiniCssExtractPlugin({ filename: '[name]-[hash].css', chunkFilename: '[name]-[chunkhash].css' }),
new HashedModuleIdsPlugin()
],
/**
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.js.org/configuration/node/
*/
node: {
global: true,
crypto: 'empty',
process: false,
module: false,
clearImmediate: false,
setImmediate: false,
fs: 'empty'
}
});
};
================================================
FILE: config/webpack.test.js
================================================
/**
* @author: tipe.io
*/
const helpers = require('./helpers');
/**
* Webpack Plugins
*/
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
/**
* Webpack Constants
*/
const ENV = (process.env.ENV = process.env.NODE_ENV = 'test');
/**
* Webpack configuration
*
* See: https://webpack.js.org/configuration/
*/
module.exports = function(options) {
return {
mode: 'development',
/**
* Source map for Karma from the help of karma-sourcemap-loader & karma-webpack
*
* Do not change, leave as is or it wont work.
* See: https://github.com/webpack/karma-webpack#source-maps
*/
devtool: 'inline-source-map',
/**
* Options affecting the resolving of modules.
*
* See: https://webpack.js.org/configuration/resolve/
*/
resolve: {
/**
* An array of extensions that should be used to resolve modules.
*
* See: https://webpack.js.org/configuration/resolve/#resolve-extensions
*/
extensions: ['.ts', '.js'],
/**
* Make sure root is src
*/
modules: [helpers.root('src'), 'node_modules']
},
/**
* Options affecting the normal modules.
*
* See: https://webpack.js.org/configuration/module/
*
* 'use:' revered back to 'loader:' as a temp. workaround for #1188
* See: https://github.com/gdi2290/angular-starter/issues/1188#issuecomment-262872034
*/
module: {
rules: [
/**
* Source map loader support for *.js files
* Extracts SourceMaps for source files that as added as sourceMappingURL comment.
*
* See: https://github.com/webpack/source-map-loader
*/
{
enforce: 'pre',
test: /\.js$/,
loader: 'source-map-loader',
exclude: [
/**
* These packages have problems with their sourcemaps
*/
helpers.root('node_modules/@angular')
]
},
/**
* Typescript loader support for .ts and Angular 2 async routes via .async.ts
*
* See: https://github.com/s-panferov/awesome-typescript-loader
*/
{
test: /\.ts$/,
use: [
{
loader: 'awesome-typescript-loader',
query: {
/**
* Use inline sourcemaps for "karma-remap-coverage" reporter
*/
sourceMap: false,
inlineSourceMap: true,
compilerOptions: {
/**
* Remove TypeScript helpers to be injected
* below by DefinePlugin
*/
removeComments: true
}
}
},
'angular2-template-loader'
],
exclude: [/\.e2e\.ts$/]
},
/**
* Raw loader support for *.css files
* Returns file content as string
*
* See: https://github.com/webpack/raw-loader
*/
{
test: /\.css$/,
loader: ['to-string-loader', { loader: 'css-loader', options: { url: false } }],
exclude: [helpers.root('src/index.html')]
},
/**
* Raw loader support for *.scss files
*
* See: https://github.com/webpack/raw-loader
*/
{
test: /\.scss$/,
loader: ['raw-loader', 'sass-loader'],
exclude: [helpers.root('src/index.html')]
},
/**
* Raw loader support for *.html
* Returns file content as string
*
* See: https://github.com/webpack/raw-loader
*/
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [helpers.root('src/index.html')]
},
/**
* Instruments JS files with Istanbul for subsequent code coverage reporting.
* Instrument only testing sources.
*
* See: https://github.com/deepsweet/istanbul-instrumenter-loader
*/
{
enforce: 'post',
test: /\.(js|ts)$/,
loader: 'istanbul-instrumenter-loader',
include: helpers.root('src'),
exclude: [/\.(e2e|spec)\.ts$/, /node_modules/]
}
]
},
/**
* Add additional plugins to the compiler.
*
* See: https://webpack.js.org/configuration/plugins/
*/
plugins: [
/**
* Plugin: DefinePlugin
* Description: Define free variables.
* Useful for having development builds with debug logging or adding global constants.
*
* Environment helpers
*
* See: https://webpack.js.org/plugins/define-plugin/
*
* NOTE: when adding more properties make sure you include them in custom-typings.d.ts
*/
new DefinePlugin({
ENV: JSON.stringify(ENV),
HMR: false,
'process.env': {
ENV: JSON.stringify(ENV),
NODE_ENV: JSON.stringify(ENV),
HMR: false
}
}),
/**
* Plugin: ContextReplacementPlugin
* Description: Provides context to Angular's use of System.import
*
* See: https://webpack.js.org/plugins/context-replacement-plugin/
* See: https://github.com/angular/angular/issues/11580
*/
new ContextReplacementPlugin(
/**
* The (\\|\/) piece accounts for path separators in *nix and Windows
*/
/\@angular(\\|\/)core(\\|\/)esm5/,
helpers.root('src'), // location of your src
{
/**
* your Angular Async Route paths relative to this root directory
*/
}
),
/**
* Plugin LoaderOptionsPlugin (experimental)
*
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({
debug: false,
options: {
/**
* legacy options go here
*/
}
})
],
/**
* Disable performance hints
*
* See: https://github.com/a-tarasyuk/rr-boilerplate/blob/master/webpack/dev.config.babel.js#L41
*/
performance: {
hints: false
},
/**
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.js.org/configuration/node/
*/
node: {
global: true,
crypto: 'empty',
process: false,
module: false,
clearImmediate: false,
setImmediate: false,
fs: 'empty'
}
};
};
================================================
FILE: docker-compose.yml
================================================
version: '3'
services:
angular-starter:
build:
context: .
dockerfile: Dockerfile-dev
container_name: angular-starter
networks:
- angular-starter
ports:
- '3000:3000'
environment:
- HOST=0.0.0.0
command: npm run start
networks:
angular-starter:
driver: bridge
================================================
FILE: firebase.json
================================================
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
================================================
FILE: karma.conf.js
================================================
/**
* @author: tipe.io
*/
/**
* Look in ./config for karma.conf.js
*/
module.exports = require('./config/karma.conf.js');
================================================
FILE: netlify.toml
================================================
[build]
command = "npm run build:prod"
publish = "dist"
================================================
FILE: package.json
================================================
{
"name": "angular-starter",
"version": "7.5.0",
"description": "An Angular Webpack Starter kit featuring Angular (Router, Http, Forms, Services, Tests, E2E, Coverage), Karma, Protractor, Jasmine, Istanbul, TypeScript, and Webpack by Tipe.io",
"keywords": [
"angular",
"angular2",
"angular4",
"angular5",
"webpack",
"typescript",
"tipe",
"tipe.io"
],
"author": "Patrick Stapleton <patrick@tipe.io>",
"homepage": "https://github.com/gdi2290/angular-starter",
"license": "MIT",
"scripts": {
"build:aot:prod": "rimraf dist compiled && cross-env BUILD_AOT=1 SOURCE_MAP=0 npm run webpack -- --config config/webpack.prod.js --progress --profile --bail",
"build:aot": "npm run build:aot:prod",
"build:aot:dev": "cross-env BUILD_AOT=1 npm run build:dev",
"build:dev": "rimraf dist && npm run webpack -- --config config/webpack.dev.js --mode development --progress --profile --trace-deprecation",
"build:docker": "npm run build:prod && docker build -t angular-webpack-starter:latest .",
"build:prod": "rimraf dist && npm run webpack -- --config config/webpack.prod.js --progress --profile --bail",
"build": "npm run build:dev",
"ci:aot": "cross-env BUILD_E2E=1 npm run lint && npm run test:ci && npm run build:aot && npm run e2e",
"ci:jit": "cross-env BUILD_E2E=1 npm run lint && npm run test:ci && npm run build:prod && npm run e2e",
"ci:nobuild": "npm run lint && npm test:ci && npm run e2e",
"ci:testall": "cross-env BUILD_E2E=1 npm run lint && npm run test:ci && npm run build:prod && npm run e2e && npm run build:aot && npm run e2e",
"ci:travis": "cross-env BUILD_E2E=1 npm run lint && npm run test:ci && npm run build:aot && npm run e2e:travis",
"ci": "npm run ci:testall",
"clean:all": "npm run rimraf -- doc coverage dist compiled webpack-cache",
"clean:cache": "npm run rimraf -- webpack-cache",
"clean:aot": "npm run rimraf -- compiled",
"clean:dist": "npm run rimraf -- dist",
"clean:install": "npm set progress=false && npm install",
"clean": "npm cache verify && npm run rimraf -- node_modules doc coverage dist compiled webpack-cache",
"docker": "docker",
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
"docs:compodoc": "compodoc -p tsconfig.json",
"docs:compodoc:serve": "compodoc -p tsconfig.json -s",
"docs:compodoc:serve:watch": "compodoc -p tsconfig.json -s -w",
"e2e:live": "npm-run-all -p -r server:prod:ci protractor:live",
"e2e:travis": "npm-run-all -p -r server:prod:ci protractor:delay",
"e2e": "npm-run-all -p -r server:prod:ci protractor",
"github-deploy:dev": "npm run webpack -- --config config/webpack.github-deploy.js --mode development --progress --profile --env.githubDev",
"github-deploy:prod": "npm run webpack -- --config config/webpack.github-deploy.js --mode production --progress --profile --env.githubProd",
"github-deploy": "npm run github-deploy:dev",
"lint": "npm run tslint \"src/**/*.ts\"",
"node": "node",
"postinstall": "npm run webdriver:update",
"postversion": "git push && git push --tags",
"preclean:install": "npm run clean",
"preversion": "npm test",
"protractor": "protractor",
"protractor:delay": "sleep 3 && npm run protractor",
"protractor:live": "protractor --elementExplorer",
"rimraf": "rimraf",
"server:dev:hmr": "npm run server:dev -- --hot --hotOnly",
"server:aot:dev": "cross-env BUILD_AOT=1 npm run server:dev",
"server:dev": "npm run webpack-dev-server -- --config config/webpack.dev.js --open --progress --profile --watch --content-base src/",
"server:prod": "http-server dist -c-1 --cors",
"server:prod:ci": "http-server dist -p 3000 -c-1 --cors",
"server": "npm run server:dev",
"start:prod:hmr": "cross-env ANGULAR_CONF_FILE=./config.prod.json npm run server:dev:hmr",
"start:hmr": "npm run server:dev:hmr",
"start": "npm run server:dev",
"start:aot": "npm run server:aot:dev",
"test": "karma start",
"test:sonar": "npm run lint && cross-env SONAR_QUBE=1 karma start",
"test:ci": "karma start --single-run --browsers ChromeTravisCi",
"tslint": "tslint \"src/**/*.ts\" --project tsconfig.json",
"typedoc": "typedoc",
"version": "npm run build",
"watch:dev:hmr": "npm run watch:dev -- --hot",
"watch:dev": "npm run build:dev -- --watch",
"watch:aot:dev": "npm run build:aot:dev -- --watch",
"watch:prod": "npm run build:prod -- --watch",
"watch:aot:prod": "npm run build:aot:prod -- --watch",
"watch:test": "npm run test -- --auto-watch --no-single-run",
"watch": "npm run watch:dev",
"webdriver-manager": "node ./node_modules/protractor/bin/webdriver-manager",
"webdriver:start": "node ./node_modules/protractor/bin/webdriver-manager start",
"webdriver:update": "node ./node_modules/protractor/bin/webdriver-manager update",
"webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
"webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js"
},
"dependencies": {
"@angular/animations": "^6.0.6",
"@angular/common": "^6.0.6",
"@angular/compiler": "^6.0.6",
"@angular/core": "^6.0.6",
"@angular/forms": "^6.0.6",
"@angular/platform-browser": "^6.0.6",
"@angular/platform-browser-dynamic": "^6.0.6",
"@angular/platform-server": "^6.0.6",
"@angular/router": "^6.0.6",
"core-js": "^2.5.7",
"http-server": "^0.11.1",
"ie-shim": "^0.1.0",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.2.1",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-optimizer": "^0.6.8",
"@angular/cli": "^6.0.8",
"@angular/compiler-cli": "^6.0.6",
"@angular/language-service": "^6.0.6",
"@compodoc/compodoc": "^1.1.3",
"@ngtools/webpack": "^6.0.8",
"@types/hammerjs": "^2.0.35",
"@types/jasmine": "^2.8.8",
"@types/node": "^10.3.5",
"@types/uglify-js": "^3.0.2",
"@types/webpack": "^4.4.2",
"add-asset-html-webpack-plugin": "^2.1.3",
"angular2-template-loader": "^0.6.2",
"assets-webpack-plugin": "^3.8.4",
"awesome-typescript-loader": "^5.2.0",
"codelyzer": "^4.3.0",
"copy-webpack-plugin": "^4.5.1",
"cross-env": "^5.2.0",
"css-loader": "^0.28.11",
"exports-loader": "^0.7.0",
"expose-loader": "^0.7.5",
"file-loader": "^1.1.11",
"find-root": "^1.1.0",
"gh-pages": "^1.2.0",
"html-webpack-plugin": "^3.2.0",
"imports-loader": "^0.8.0",
"istanbul-instrumenter-loader": "^3.0.1",
"jasmine-core": "^3.1.0",
"karma": "^2.0.4",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage": "^1.1.2",
"karma-jasmine": "^1.1.2",
"karma-mocha-reporter": "^2.2.5",
"karma-remap-coverage": "^0.1.5",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^3.0.0",
"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
"npm-run-all": "^4.1.3",
"optimize-js-plugin": "^0.0.4",
"parse5": "^5.0.0",
"protractor": "^5.3.2",
"raw-loader": "^0.5.1",
"rimraf": "^2.6.2",
"rxjs-tslint": "^0.1.5",
"sass-loader": "^7.0.3",
"script-ext-html-webpack-plugin": "^2.0.1",
"source-map-loader": "^0.2.3",
"string-replace-loader": "^2.1.1",
"style-loader": "^0.21.0",
"to-string-loader": "^1.1.5",
"ts-node": "^7.0.0",
"tslib": "^1.9.3",
"tslint": "^5.10.0",
"tslint-loader": "^3.6.0",
"typedoc": "^0.11.1",
"typescript": "~2.7.2",
"uglifyjs-webpack-plugin": "^1.2.6",
"url-loader": "^1.0.1",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.1.4",
"webpack-inline-manifest-plugin": "^4.0.1",
"webpack-merge": "^4.1.3"
},
"repository": {
"type": "git",
"url": "https://github.com/gdi2290/angular-starter.git"
},
"bugs": {
"url": "https://github.com/gdi2290/angular-starter/issues"
},
"engines": {
"node": ">= 8.0.0",
"npm": ">= 5"
}
}
================================================
FILE: protractor.conf.js
================================================
/**
* @author: tipe.io
*/
/**
* look in ./config for protractor.conf.js
*/
exports.config = require('./config/protractor.conf.js').config;
================================================
FILE: sonar-project.properties
================================================
sonar.projectKey=angular:angular-starter
sonar.projectName=angular-starter
sonar.projectVersion=6.0.0
sonar.sourceEncoding=UTF-8
sonar.sources=src
sonar.exclusions=**/node_modules/**,**/*.spec.ts
sonar.tests=src/app
sonar.test.inclusions=**/*.spec.ts
sonar.ts.tslint.configPath=tslint.json
sonar.ts.coverage.lcovReportPath=coverage/coverage.lcov
# if using local tslint then enable the line below
# sonar.ts.tslint.outputPath=reports/lint_issues.json
sonar.genericcoverage.unitTestReportPaths=reports/ut_report.xml
# Change the host.url to point to the
# sonarcube server (default localhost)
sonar.host.url=http://localhost:9000
================================================
FILE: src/app/+barrel/+child-barrel/child-barrel.component.ts
================================================
import {
Component,
OnInit,
} from '@angular/core';
/**
* We're loading this component asynchronously
* We are using some magic with es6-promise-loader that will wrap the module with a Promise
* see https://github.com/gdi2290/es6-promise-loader for more info
*/
console.log('`ChildBarrel` component loaded asynchronously');
@Component({
selector: 'child-barrel',
template: `
<h1>Hello from Child Barrel</h1>
`,
})
export class ChildBarrelComponent implements OnInit {
public ngOnInit() {
console.log('hello `ChildBarrel` component');
}
}
================================================
FILE: src/app/+barrel/+child-barrel/child-barrel.module.ts
================================================
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './child-barrel.routes';
import { ChildBarrelComponent } from './child-barrel.component';
console.log('`ChildBarrel` bundle loaded asynchronously');
@NgModule({
declarations: [
/**
* Components / Directives/ Pipes
*/
ChildBarrelComponent,
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
],
})
export class ChildBarrelModule {
public static routes = routes;
}
================================================
FILE: src/app/+barrel/+child-barrel/child-barrel.routes.ts
================================================
import { ChildBarrelComponent } from './child-barrel.component';
export const routes = [
{ path: '', component: ChildBarrelComponent, pathMatch: 'full' },
];
================================================
FILE: src/app/+barrel/+child-barrel/index.ts
================================================
export { ChildBarrelModule } from './child-barrel.module';
================================================
FILE: src/app/+barrel/barrel.component.ts
================================================
import {
Component,
OnInit,
} from '@angular/core';
/**
* We're loading this component asynchronously
* We are using some magic with es6-promise-loader that will wrap the module with a Promise
* see https://github.com/gdi2290/es6-promise-loader for more info
*/
console.log('`Barrel` component loaded asynchronously');
@Component({
selector: 'barrel',
template: `
<h1>Hello from Barrel</h1>
<span>
<a [routerLink]=" ['./child-barrel'] ">
Child Barrel
</a>
</span>
<router-outlet></router-outlet>
`,
})
export class BarrelComponent implements OnInit {
public ngOnInit() {
console.log('hello `Barrel` component');
}
}
================================================
FILE: src/app/+barrel/barrel.module.ts
================================================
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './barrel.routes';
import { BarrelComponent } from './barrel.component';
console.log('`Barrel` bundle loaded asynchronously');
@NgModule({
declarations: [
/**
* Components / Directives/ Pipes
*/
BarrelComponent,
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
],
})
export class BarrelModule {
public static routes = routes;
}
================================================
FILE: src/app/+barrel/barrel.routes.ts
================================================
import { BarrelComponent } from './barrel.component';
export const routes = [
{ path: '', children: [
{ path: '', component: BarrelComponent },
{ path: 'child-barrel', loadChildren: './+child-barrel#ChildBarrelModule' }
]},
];
================================================
FILE: src/app/+barrel/index.ts
================================================
export { BarrelModule } from './barrel.module';
================================================
FILE: src/app/+detail/+child-detail/child-detail.component.ts
================================================
import {
Component,
OnInit,
} from '@angular/core';
/**
* We're loading this component asynchronously
* We are using some magic with es6-promise-loader that will wrap the module with a Promise
* see https://github.com/gdi2290/es6-promise-loader for more info
*/
console.log('`ChildDetail` component loaded asynchronously');
@Component({
selector: 'child-detail',
template: `
<h1>Hello from Child Detail</h1>
`,
})
export class ChildDetailComponent implements OnInit {
public ngOnInit() {
console.log('hello `ChildDetail` component');
}
}
================================================
FILE: src/app/+detail/+child-detail/child-detail.module.ts
================================================
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './child-detail.routes';
import { ChildDetailComponent } from './child-detail.component';
console.log('`ChildDetail` bundle loaded asynchronously');
@NgModule({
declarations: [
/**
* Components / Directives/ Pipes
*/
ChildDetailComponent,
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
],
})
export class ChildDetailModule {
public static routes = routes;
}
================================================
FILE: src/app/+detail/+child-detail/child-detail.routes.ts
================================================
import { ChildDetailComponent } from './child-detail.component';
export const routes = [
{ path: '', component: ChildDetailComponent, pathMatch: 'full' },
];
================================================
FILE: src/app/+detail/+child-detail/index.ts
================================================
export { ChildDetailModule } from './child-detail.module';
================================================
FILE: src/app/+detail/detail.component.ts
================================================
import {
Component,
OnInit,
} from '@angular/core';
/**
* We're loading this component asynchronously
* We are using some magic with es6-promise-loader that will wrap the module with a Promise
* see https://github.com/gdi2290/es6-promise-loader for more info
*/
console.log('`Detail` component loaded asynchronously');
@Component({
selector: 'detail',
template: `
<h1>Hello from Detail</h1>
<span>
<a [routerLink]=" ['./child-detail'] ">
Child Detail
</a>
</span>
<router-outlet></router-outlet>
`,
})
export class DetailComponent implements OnInit {
public ngOnInit() {
console.log('hello `Detail` component');
}
}
================================================
FILE: src/app/+detail/detail.module.ts
================================================
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './detail.routes';
import { DetailComponent } from './detail.component';
console.log('`Detail` bundle loaded asynchronously');
@NgModule({
declarations: [
/**
* Components / Directives/ Pipes
*/
DetailComponent,
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
],
})
export class DetailModule {
public static routes = routes;
}
================================================
FILE: src/app/+detail/detail.routes.ts
================================================
import { DetailComponent } from './detail.component';
export const routes = [
{ path: '', children: [
{ path: '', component: DetailComponent },
{ path: 'child-detail', loadChildren: './+child-detail#ChildDetailModule' }
]},
];
================================================
FILE: src/app/+detail/index.ts
================================================
export { DetailModule } from './detail.module';
================================================
FILE: src/app/+dev-module/dev-module.component.ts
================================================
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'dev-module',
template: `
<h1>Hello from DevModule Component</h1>
`,
})
export class DevModuleComponent implements OnInit {
public ngOnInit() {
console.log('hello `DevModule` component');
}
}
================================================
FILE: src/app/+dev-module/dev-module.module.ts
================================================
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { routes } from './dev-module.routes';
import { DevModuleComponent } from './dev-module.component';
/*
Don't leave side-effects outside of classes so this will tree-shake nicely on prod
e.g. `console.log('something')` is a side effect.
*/
@NgModule({
declarations: [ DevModuleComponent ],
imports: [
CommonModule,
RouterModule.forChild(routes),
],
})
export class DevModuleModule {
public static routes = routes;
constructor() {
console.log('`DevModuleModule` module initialized');
}
}
================================================
FILE: src/app/+dev-module/dev-module.routes.ts
================================================
import { DevModuleComponent } from './dev-module.component';
export const routes = [
{ path: 'dev-module', component: DevModuleComponent }
];
================================================
FILE: src/app/+dev-module/index.ts
================================================
export { DevModuleModule } from './dev-module.module';
================================================
FILE: src/app/about/about.component.spec.ts
================================================
import { ActivatedRoute, Data } from '@angular/router';
import { Component } from '@angular/core';
import { inject, TestBed } from '@angular/core/testing';
/**
* Load the implementations that should be tested.
*/
import { AboutComponent } from './about.component';
describe('About', () => {
/**
* Provide our implementations or mocks to the dependency injector
*/
beforeEach(() => TestBed.configureTestingModule({
providers: [
/**
* Provide a better mock.
*/
{
provide: ActivatedRoute,
useValue: {
data: {
subscribe: (fn: (value: Data) => void) => fn({
yourData: 'yolo'
})
}
}
},
AboutComponent
]
}));
it('should log ngOnInit', inject([AboutComponent], (about: AboutComponent) => {
spyOn(console, 'log');
expect(console.log).not.toHaveBeenCalled();
about.ngOnInit();
expect(console.log).toHaveBeenCalled();
}));
});
================================================
FILE: src/app/about/about.component.ts
================================================
import {
Component,
OnInit
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'about',
styles: [`
`],
template: `
<h1>About</h1>
<div>
For hot module reloading run
<pre>npm run start:hmr</pre>
</div>
<div>
<h3>
patrick@tipe.io
</h3>
</div>
<pre>this.localState = {{ localState | json }}</pre>
`
})
export class AboutComponent implements OnInit {
public localState: any;
constructor(
public route: ActivatedRoute
) {}
public ngOnInit() {
this.route
.data
.subscribe((data: any) => {
/**
* Your resolved data from route.
*/
this.localState = data.yourData;
});
console.log('hello `About` component');
/**
* static data that is bundled
* var mockData = require('assets/mock-data/mock-data.json');
* console.log('mockData', mockData);
* if you're working with mock data you can also use http.get('assets/mock-data/mock-data.json')
*/
this.asyncDataWithWebpack();
}
private asyncDataWithWebpack() {
/**
* you can also async load mock data with 'es6-promise-loader'
* you would do this if you don't want the mock-data bundled
* remember that 'es6-promise-loader' is a promise
*/
setTimeout(() => {
import('../../assets/mock-data/mock-data.json')
.then((json) => {
console.log('async mockData', json);
this.localState = json;
});
});
}
}
================================================
FILE: src/app/about/index.ts
================================================
export * from './about.component';
================================================
FILE: src/app/app.component.css
================================================
html, body{
height: 100%;
font-family: Arial, Helvetica, sans-serif
}
a.active {
background-color: gray;
}
================================================
FILE: src/app/app.component.spec.ts
================================================
import { NO_ERRORS_SCHEMA } from '@angular/core';
import {
inject,
async,
TestBed,
ComponentFixture
} from '@angular/core/testing';
/**
* Load the implementations that should be tested
*/
import { AppComponent } from './app.component';
import { AppState } from './app.service';
describe(`App`, () => {
let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>;
/**
* async beforeEach
*/
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AppComponent ],
schemas: [NO_ERRORS_SCHEMA],
providers: [AppState]
})
/**
* Compile template and css
*/
.compileComponents();
}));
/**
* Synchronous beforeEach
*/
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
comp = fixture.componentInstance;
/**
* Trigger initial data binding
*/
fixture.detectChanges();
});
it(`should be readly initialized`, () => {
expect(fixture).toBeDefined();
expect(comp).toBeDefined();
});
it(`should be @TipeIO`, () => {
expect(comp.twitter).toEqual('https://twitter.com/gdi2290');
expect(comp.tipe).toEqual('assets/img/tipe.png');
expect(comp.name).toEqual('Angular Starter');
});
it('should log ngOnInit', () => {
spyOn(console, 'log');
expect(console.log).not.toHaveBeenCalled();
comp.ngOnInit();
expect(console.log).toHaveBeenCalled();
});
});
================================================
FILE: src/app/app.component.ts
================================================
/**
* Angular 2 decorators and services
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { environment } from 'environments/environment';
import { AppState } from './app.service';
export const ROOT_SELECTOR = 'app';
/**
* App Component
* Top Level Component
*/
@Component({
selector: ROOT_SELECTOR,
encapsulation: ViewEncapsulation.None,
styleUrls: [
'./app.component.css'
],
template: `
<nav>
<a [routerLink]=" ['./'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
Index
</a>
<a [routerLink]=" ['./home'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
Home
</a>
<a [routerLink]=" ['./detail'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
Detail
</a>
<a [routerLink]=" ['./barrel'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
Barrel
</a>
<a [routerLink]=" ['./about'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
About
</a>
<a *ngIf="showDevModule" [routerLink]=" ['./dev-module'] "
routerLinkActive="active" [routerLinkActiveOptions]= "{exact: true}">
DevModule
</a>
</nav>
<main>
<router-outlet></router-outlet>
</main>
<pre class="app-state">this.appState.state = {{ appState.state | json }}</pre>
<footer>
<span>Angular Starter by <a [href]="twitter">@gdi2290</a></span>
<div>
<a [href]="url">
<img [src]="tipe" width="25%">
</a>
</div>
</footer>
`
})
export class AppComponent implements OnInit {
public name = 'Angular Starter';
public tipe = 'assets/img/tipe.png';
public twitter = 'https://twitter.com/gdi2290';
public url = 'https://tipe.io';
public showDevModule: boolean = environment.showDevModule;
constructor(
public appState: AppState
) {}
public ngOnInit() {
console.log('Initial App State', this.appState.state);
}
}
/**
* Please review the https://github.com/AngularClass/angular-examples/ repo for
* more angular app examples that you may copy/paste
* (The examples may not be updated as quickly. Please open an issue on github for us to update it)
* For help or questions please contact us at @AngularClass on twitter
* or our chat on Slack at https://AngularClass.com/slack-join
*/
================================================
FILE: src/app/app.e2e.ts
================================================
import { browser, by, element } from 'protractor';
import 'tslib';
describe('App', () => {
beforeEach(async () => {
await browser.get('/');
});
it('should have a title', async () => {
const subject = await browser.getTitle();
const result = 'Angular Starter by @gdi2290 from @TipeIO';
expect(subject).toEqual(result);
});
it('should have header', async () => {
const subject = await element(by.css('h1')).isPresent();
const result = true;
expect(subject).toEqual(result);
});
it('should have <home>', async () => {
const subject = await element(by.css('app home')).isPresent();
const result = true;
expect(subject).toEqual(result);
});
it('should have buttons', async () => {
const subject = await element(by.css('button')).getText();
const result = 'Submit Value';
expect(subject).toEqual(result);
});
});
================================================
FILE: src/app/app.module.ts
================================================
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule, PreloadAllModules } from '@angular/router';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
/*
* Platform and Environment providers/directives/pipes
*/
import { environment } from 'environments/environment';
import { ROUTES } from './app.routes';
// App is our top level component
import { AppComponent } from './app.component';
import { APP_RESOLVER_PROVIDERS } from './app.resolver';
import { AppState, InternalStateType } from './app.service';
import { HomeComponent } from './home';
import { AboutComponent } from './about';
import { NoContentComponent } from './no-content';
import { XLargeDirective } from './home/x-large';
import { DevModuleModule } from './+dev-module';
import '../styles/styles.scss';
import '../styles/headings.css';
// Application wide providers
const APP_PROVIDERS = [
...APP_RESOLVER_PROVIDERS,
AppState
];
interface StoreType {
state: InternalStateType;
restoreInputValues: () => void;
disposeOldHosts: () => void;
}
/**
* `AppModule` is the main entry point into Angular2's bootstraping process
*/
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
AboutComponent,
HomeComponent,
NoContentComponent,
XLargeDirective
],
/**
* Import Angular's modules.
*/
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot(ROUTES, {
useHash: Boolean(history.pushState) === false,
preloadingStrategy: PreloadAllModules
}),
/**
* This section will import the `DevModuleModule` only in certain build types.
* When the module is not imported it will get tree shaked.
* This is a simple example, a big app should probably implement some logic
*/
...environment.showDevModule ? [ DevModuleModule ] : [],
],
/**
* Expose our Services and Providers into Angular's dependency injection.
*/
providers: [
environment.ENV_PROVIDERS,
APP_PROVIDERS
]
})
export class AppModule {}
================================================
FILE: src/app/app.resolver.ts
================================================
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
@Injectable()
export class DataResolver implements Resolve<any> {
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return of({ res: 'I am data'});
}
}
/**
* An array of services to resolve routes with data.
*/
export const APP_RESOLVER_PROVIDERS = [
DataResolver
];
================================================
FILE: src/app/app.routes.ts
================================================
import { Routes } from '@angular/router';
import { HomeComponent } from './home';
import { AboutComponent } from './about';
import { NoContentComponent } from './no-content';
export const ROUTES: Routes = [
{ path: '', component: HomeComponent },
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'detail', loadChildren: './+detail#DetailModule'},
{ path: 'barrel', loadChildren: './+barrel#BarrelModule'},
{ path: '**', component: NoContentComponent },
];
================================================
FILE: src/app/app.service.ts
================================================
import { Injectable } from '@angular/core';
export interface InternalStateType {
[key: string]: any;
}
@Injectable()
export class AppState {
public _state: InternalStateType = { };
/**
* Already return a clone of the current state.
*/
public get state() {
return this._state = this._clone(this._state);
}
/**
* Never allow mutation
*/
public set state(value) {
throw new Error('do not mutate the `.state` directly');
}
public get(prop?: any) {
/**
* Use our state getter for the clone.
*/
const state = this.state;
return state.hasOwnProperty(prop) ? state[prop] : state;
}
public set(prop: string, value: any) {
/**
* Internally mutate our state.
*/
return this._state[prop] = value;
}
private _clone(object: InternalStateType) {
/**
* Simple object clone.
*/
return JSON.parse(JSON.stringify( object ));
}
}
================================================
FILE: src/app/home/home.component.css
================================================
/*styles for home content only*/
================================================
FILE: src/app/home/home.component.html
================================================
<div>
<h1 x-large class="sample-content">Your Content Here</h1>
<hr>
<div>
For hot module reloading run
<pre>npm run start:hmr</pre>
</div>
<hr>
<div>
<h4>Local State</h4>
<form (ngSubmit)="submitState(localState.value)" autocomplete="off">
<input
[value]="localState.value"
(input)="localState.value = $event.target.value"
placeholder="Submit Local State to App State"
autofocus>
<button>Submit Value</button>
</form>
<!--
<input type="text" [value]="localState.value" (input)="localState.value = $event.target.value" autofocus>
Rather than wiring up two-way data-binding ourselves with [value] and (input)
we can use Angular's [(ngModel)] syntax
<input type="text" name="textInput" [(ngModel)]="localState.value" autofocus>
-->
<pre>this.localState = {{ localState | json }}</pre>
</div>
</div>
================================================
FILE: src/app/home/home.component.spec.ts
================================================
import { NO_ERRORS_SCHEMA } from '@angular/core';
import {
inject,
async,
TestBed,
ComponentFixture,
getTestBed
} from '@angular/core/testing';
import { Component } from '@angular/core';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
/**
* Load the implementations that should be tested.
*/
import { AppState } from '../app.service';
import { HomeComponent } from './home.component';
import { Title } from './title';
describe(`Home`, () => {
let comp: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
let injector: TestBed;
let service: AppState;
let httpMock: HttpTestingController;
/**
* async beforeEach.
*/
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [HomeComponent],
schemas: [NO_ERRORS_SCHEMA],
imports: [HttpClientTestingModule],
providers: [AppState, Title]
})
/**
* Compile template and css.
*/
.compileComponents();
injector = getTestBed();
service = injector.get(AppState);
httpMock = injector.get(HttpTestingController);
}));
/**
* Synchronous beforeEach.
*/
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
comp = fixture.componentInstance;
/**
* Trigger initial data binding.
*/
fixture.detectChanges();
});
it('should have default data', () => {
expect(comp.localState).toEqual({ value: '' });
});
it('should have a title', () => {
expect(!!comp.title).toEqual(true);
});
it('should log ngOnInit', () => {
spyOn(console, 'log');
expect(console.log).not.toHaveBeenCalled();
comp.ngOnInit();
expect(console.log).toHaveBeenCalled();
});
});
================================================
FILE: src/app/home/home.component.ts
================================================
import {
Component,
OnInit
} from '@angular/core';
import { AppState } from '../app.service';
import { Title } from './title';
import { XLargeDirective } from './x-large';
@Component({
/**
* The selector is what angular internally uses
* for `document.querySelectorAll(selector)` in our index.html
* where, in this case, selector is the string 'home'.
*/
selector: 'home', // <home></home>
/**
* We need to tell Angular's Dependency Injection which providers are in our app.
*/
providers: [
Title
],
/**
* Our list of styles in our component. We may add more to compose many styles together.
*/
styleUrls: [ './home.component.css' ],
/**
* Every Angular template is first compiled by the browser before Angular runs it's compiler.
*/
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
/**
* Set our default values
*/
public localState = { value: '' };
/**
* TypeScript public modifiers
*/
constructor(
public appState: AppState,
public title: Title
) {}
public ngOnInit() {
console.log('hello `Home` component');
/**
* this.title.getData().subscribe(data => this.data = data);
*/
}
public submitState(value: string) {
console.log('submitState', value);
this.appState.set('value', value);
this.localState.value = '';
}
}
================================================
FILE: src/app/home/home.e2e.ts
================================================
import { browser, by, element } from 'protractor';
import 'tslib';
describe('Home', () => {
beforeEach(async () => {
/**
* Change hash depending on router LocationStrategy.
*/
await browser.get('/');
await element(by.linkText('Home')).click();
});
it('should have a title', async () => {
const subject = await browser.getTitle();
const result = 'Angular Starter by @gdi2290 from @TipeIO';
expect(subject).toEqual(result);
});
it('should have `your content here` x-large', async () => {
const subject = await element(by.css('[x-large]')).getText();
const result = 'Your Content Here';
expect(subject).toEqual(result);
});
});
================================================
FILE: src/app/home/index.ts
================================================
export * from './home.component';
================================================
FILE: src/app/home/title/index.ts
================================================
export * from './title.service';
================================================
FILE: src/app/home/title/title.service.spec.ts
================================================
import {
inject,
async,
TestBed,
ComponentFixture,
getTestBed
} from '@angular/core/testing';
import { Component } from '@angular/core';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Title } from './title.service';
describe('Title', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [Title]
});
});
it('should have http', inject([Title], (title: Title) => {
expect(!!title.http).toEqual(true);
}));
it('should get data from the server', inject([Title], (title: Title) => {
spyOn(console, 'log');
expect(console.log).not.toHaveBeenCalled();
title.getData();
expect(console.log).toHaveBeenCalled();
title.getData().subscribe( (result) => {
expect(result).toEqual({ value: 'AngularClass' });
});
}));
});
================================================
FILE: src/app/home/title/title.service.ts
================================================
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class Title {
public value = 'Angular 2';
constructor(
public http: HttpClient
) { }
public getData() {
console.log('Title#getData(): Get Data');
return this.http.get('/assets/data.json');
}
}
================================================
FILE: src/app/home/x-large/index.ts
================================================
export * from './x-large.directive';
================================================
FILE: src/app/home/x-large/x-large.directive.spec.ts
================================================
import { By } from '@angular/platform-browser';
import {
inject,
fakeAsync,
tick,
async,
TestBed,
ComponentFixture,
getTestBed
} from '@angular/core/testing';
import { Component } from '@angular/core';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
/**
* Load the implementations that should be tested.
*/
import { XLargeDirective } from './x-large.directive';
describe('x-large directive', () => {
/**
* Create a test component to test directives.
*/
@Component({
template: '<div x-large>Content</div>'
})
class TestComponent { }
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
XLargeDirective,
TestComponent
]
});
});
it('should sent font-size to x-large', fakeAsync(() => {
TestBed.compileComponents().then(() => {
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
tick();
const element = fixture.debugElement.query(By.css('div'));
expect(element.nativeElement.style.fontSize).toBe('x-large');
});
}));
});
================================================
FILE: src/app/home/x-large/x-large.directive.ts
================================================
import {
Component,
Directive,
ElementRef,
Renderer
} from '@angular/core';
/**
* Directive
* XLarge is a simple directive to show how one is made
*/
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[x-large]' // using [ ] means selecting attributes
})
export class XLargeDirective {
constructor(
public element: ElementRef,
public renderer: Renderer
) {
/**
* Simple DOM manipulation to set font size to x-large
* `nativeElement` is the direct reference to the DOM element
* element.nativeElement.style.fontSize = 'x-large';
*
* for server/webworker support use the renderer
*/
renderer.setElementStyle(element.nativeElement, 'fontSize', 'x-large');
}
}
================================================
FILE: src/app/index.ts
================================================
/**
* App
*/
export * from './app.module';
================================================
FILE: src/app/no-content/index.ts
================================================
export * from './no-content.component';
================================================
FILE: src/app/no-content/no-content.component.ts
================================================
import { Component } from '@angular/core';
@Component({
selector: 'no-content',
template: `
<div>
<h1>404: page missing</h1>
</div>
`
})
export class NoContentComponent {
}
================================================
FILE: src/assets/css/.gitkeep
================================================
@AngularClass
================================================
FILE: src/assets/data.json
================================================
{
"value": "AngularClass"
}
================================================
FILE: src/assets/humans.txt
================================================
# humanstxt.org/
# The humans responsible & technology colophon
# TEAM
<name> -- <role> -- <twitter>
# THANKS
<name>
PatrickJS -- @gdi2290
AngularClass -- @AngularClass
# TECHNOLOGY COLOPHON
HTML5, CSS3
Angular2, TypeScript, Webpack
================================================
FILE: src/assets/icon/browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
================================================
FILE: src/assets/manifest.json
================================================
{
"name": "App",
"icons": [
{
"src": "/assets/icon/android-icon-36x36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "/assets/icon/android-icon-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/assets/icon/android-icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/assets/icon/android-icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/assets/icon/android-icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/assets/icon/android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}
]
}
================================================
FILE: src/assets/mock-data/mock-data.json
================================================
[
{"res": "data"}
]
================================================
FILE: src/assets/robots.txt
================================================
# robotstxt.org
User-agent: *
================================================
FILE: src/assets/service-worker.js
================================================
// This file is intentionally without code.
================================================
FILE: src/custom-typings.d.ts
================================================
/*
* Custom Type Definitions
* When including 3rd party modules you also need to include the type definition for the module
* if they don't provide one within the module. You can try to install it with @types
npm install @types/node
npm install @types/lodash
* If you can't find the type definition in the registry we can make an ambient/global definition in
* this file for now. For example
declare module 'my-module' {
export function doesSomething(value: string): string;
}
* If you are using a CommonJS module that is using module.exports then you will have to write your
* types using export = yourObjectOrFunction with a namespace above it
* notice how we have to create a namespace that is equal to the function we're
* assigning the export to
declare module 'jwt-decode' {
function jwtDecode(token: string): any;
namespace jwtDecode {}
export = jwtDecode;
}
*
* If you're prototying and you will fix the types later you can also declare it as type any
*
declare var assert: any;
declare var _: any;
declare var $: any;
*
* If you're importing a module that uses Node.js modules which are CommonJS you need to import as
* in the files such as main.browser.ts or any file within app/
*
import * as _ from 'lodash'
* You can include your type definitions in this file until you create one for the @types
*
*/
// support NodeJS modules without type definitions
declare module '*';
/*
// for legacy tslint etc to understand rename 'modern-lru' with your package
// then comment out `declare module '*';`. For each new module copy/paste
// this method of creating an `any` module type definition
declare module 'modern-lru' {
let x: any;
export = x;
}
*/
// Extra variables that live on Global that will be replaced by webpack DefinePlugin
declare var ENV: string;
declare var HMR: boolean;
declare var System: SystemJS;
// declare const FIREBASE_CONFIG: FirebaseConfig;
interface FirebaseConfig {
apiKey: string;
authDomain: string;
databaseURL: string;
projectId: string;
storageBucket: string;
messagingSenderId: string;
}
interface SystemJS {
import: (path?: string) => Promise<any>;
}
interface GlobalEnvironment {
ENV: string;
HMR: boolean;
SystemJS: SystemJS;
System: SystemJS;
// FIREBASE_CONFIG: FirebaseConfig;
}
interface Es6PromiseLoader {
(id: string): (exportName?: string) => Promise<any>;
}
type FactoryEs6PromiseLoader = () => Es6PromiseLoader;
type FactoryPromise = () => Promise<any>;
type AsyncRoutes = {
[component: string]: Es6PromiseLoader |
Function |
FactoryEs6PromiseLoader |
FactoryPromise ;
};
type IdleCallbacks = Es6PromiseLoader |
Function |
FactoryEs6PromiseLoader |
FactoryPromise ;
interface WebpackModule {
hot: {
data?: any,
idle: any,
accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void;
decline(deps?: any | string | string[]): void;
dispose(callback?: (data?: any) => void): void;
addDisposeHandler(callback?: (data?: any) => void): void;
removeDisposeHandler(callback?: (data?: any) => void): void;
check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void;
apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void;
status(callback?: (status?: string) => void): void | string;
removeStatusHandler(callback?: (status?: string) => void): void;
};
}
interface WebpackRequire {
(id: string): any;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure(ids: string[], callback: (req: WebpackRequire) => void, chunkName?: string): void;
context(directory: string, useSubDirectories?: boolean, regExp?: RegExp): WebpackContext;
}
interface WebpackContext extends WebpackRequire {
keys(): string[];
}
interface ErrorStackTraceLimit {
stackTraceLimit: number;
}
// Extend typings
interface NodeRequire extends WebpackRequire {}
interface ErrorConstructor extends ErrorStackTraceLimit {}
interface NodeRequireFunction extends Es6PromiseLoader {}
interface NodeModule extends WebpackModule {}
interface Global extends GlobalEnvironment {}
================================================
FILE: src/environments/environment.e2e.prod.ts
================================================
/* tslint:disable */
import { enableProdMode, NgModuleRef } from '@angular/core';
import { disableDebugTools } from '@angular/platform-browser';
import { Environment } from './model';
enableProdMode();
// export const ENV_FIREBASE_CONFIG: any = FIREBASE_CONFIG;
export const environment: Environment = {
production: true,
showDevModule: true,
/** Angular debug tools in the dev console
* https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
* @param modRef
* @return {any}
*/
decorateModuleRef(modRef: NgModuleRef<any>) {
disableDebugTools();
return modRef;
},
ENV_PROVIDERS: [
]
};
================================================
FILE: src/environments/environment.prod.ts
================================================
/* tslint:disable */
import { enableProdMode, NgModuleRef } from '@angular/core';
import { disableDebugTools } from '@angular/platform-browser';
import { Environment } from './model';
enableProdMode();
// export const ENV_FIREBASE_CONFIG: any = FIREBASE_CONFIG;
export const environment: Environment = {
production: true,
showDevModule: false,
/** Angular debug tools in the dev console
* https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
* @param modRef
* @return {any}
*/
decorateModuleRef(modRef: NgModuleRef<any>) {
disableDebugTools();
return modRef;
},
ENV_PROVIDERS: [
]
};
================================================
FILE: src/environments/environment.ts
================================================
/* tslint:disable */
import { ApplicationRef, NgModuleRef } from '@angular/core';
import { enableDebugTools } from '@angular/platform-browser';
import { Environment } from './model';
Error.stackTraceLimit = Infinity;
require('zone.js/dist/long-stack-trace-zone');
// export const ENV_FIREBASE_CONFIG: any = FIREBASE_CONFIG;
export const environment: Environment = {
production: false,
showDevModule: true,
/** Angular debug tools in the dev console
* https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
* @param modRef
* @return {any}
*/
decorateModuleRef(modRef: NgModuleRef<any>) {
const appRef = modRef.injector.get(ApplicationRef);
const cmpRef = appRef.components[0];
let _ng = (<any>window).ng;
enableDebugTools(cmpRef);
(<any>window).ng.probe = _ng.probe;
(<any>window).ng.coreTokens = _ng.coreTokens;
return modRef;
},
ENV_PROVIDERS: [
]
};
================================================
FILE: src/environments/model.ts
================================================
import { NgModuleRef } from '@angular/core';
export interface Environment {
production: boolean;
ENV_PROVIDERS: any;
showDevModule: boolean;
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any>;
}
================================================
FILE: src/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><%= htmlWebpackPlugin.options.title %></title>
<meta name="description" content="<%= htmlWebpackPlugin.options.metadata.description %>">
<!-- base url -->
<base href="<%= htmlWebpackPlugin.options.metadata.baseUrl %>">
<% if (webpackConfig.htmlElements.headTags) { %>
<!-- Configured Head Tags -->
<%= webpackConfig.htmlElements.headTags %>
<% } %>
<%= htmlWebpackPlugin.files.webpackManifest %>
<% if (htmlWebpackPlugin.options.metadata.isDevServer && htmlWebpackPlugin.options.metadata.HMR !== true) { %>
<!-- Webpack Dev Server reload -->
<script src="/webpack-dev-server.js"></script>
<% } %>
<!-- Async Google Tag Manager: change gtmKey value inside config.prod.conf to your to be your site's ID-->
<% if (htmlWebpackPlugin.options.gtmKey) { %>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<%= htmlWebpackPlugin.options.gtmKey %>');</script>
<!-- End Google Tag Manager -->
<% } %>
<!-- End Google Analytics -->
<!-- CSS will be injected by webpack here -->
<!-- Preload link tags will be injected by webpack here -->
</head>
<body>
<% if (htmlWebpackPlugin.options.gtmKey) { %>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<%= htmlWebpackPlugin.options.gtmKey %>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<% } %>
<app>
Loading...
</app>
<!-- Scripts will be injected by webpack here -->
</body>
</html>
================================================
FILE: src/main.browser.ts
================================================
/**
* Angular bootstrapping
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { environment } from 'environments/environment';
import { NgModuleRef } from '@angular/core';
/**
* App Module
* our top level module that holds all of our components
*/
import { AppModule } from './app';
import { ROOT_SELECTOR } from './app/app.component';
/**
* Bootstrap our Angular app with a top level NgModule
*/
export function main(): Promise<any> {
let modulePromise: Promise<NgModuleRef<AppModule>> = null;
if (module['hot']) {
module['hot'].accept();
module['hot'].dispose(() => {
// Before restarting the app, we create a new root element and dispose the old one
const oldRootElem = document.querySelector(ROOT_SELECTOR);
const newRootElem = document.createElement(ROOT_SELECTOR);
oldRootElem!.parentNode!.insertBefore(newRootElem, oldRootElem);
if (modulePromise) {
modulePromise.then((appModule) => {
appModule.destroy();
if (oldRootElem !== null) {
oldRootElem!.parentNode!.removeChild(oldRootElem);
}
return appModule;
});
}
});
}
modulePromise = platformBrowserDynamic().bootstrapModule(AppModule);
return modulePromise.then(environment.decorateModuleRef).catch((err) => console.error(err));
}
/**
* Needed for hmr
* in prod this is replace for document ready
*/
switch (document.readyState) {
case 'loading':
document.addEventListener('DOMContentLoaded', _domReadyHandler, false);
break;
case 'interactive':
case 'complete':
default:
main();
}
function _domReadyHandler() {
document.removeEventListener('DOMContentLoaded', _domReadyHandler, false);
main();
}
================================================
FILE: src/meta/humans.txt
================================================
# humanstxt.org/
# The humans responsible & technology colophon
# TEAM
<name> -- <role> -- <twitter>
# THANKS
<name>
PatrickJS -- @gdi2290
AngularClass -- @AngularClass
# TECHNOLOGY COLOPHON
HTML5, CSS3
Angular2, TypeScript, Webpack
================================================
FILE: src/meta/robots.txt
================================================
# robotstxt.org
User-agent: *
================================================
FILE: src/polyfills.browser.ts
================================================
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
// Internet Explorer 9 support
// import 'ie-shim';
// IE9, IE10 and IE11 requires all of the following polyfills.
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
// Evergreen browsers require these.
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
/**
* Required to support Web Animations `@angular/animation`.
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/***************************************************************************************************
* Zone JS is required by Angular itself.
*/
import 'zone.js/dist/zone';
// import 'zone.js/dist/long-stack-trace-zone' // async stack traces with zone.js included for dev
/***************************************************************************************************
* APPLICATION IMPORTS
*/
/**
* Date, currency, decimal and percent pipes.
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
*/
// import 'intl'; // Run `npm install --save intl`.
/**
* Need to import at least one locale-data with intl.
*/
// import 'intl/locale-data/jsonp/en';
if ('production' === ENV) {
// Production
} else {
// Development
}
================================================
FILE: src/styles/_variables.scss
================================================
$nav-button-color: #00838F;
================================================
FILE: src/styles/headings.css
================================================
h1 {
color: #00BCD4;
}
================================================
FILE: src/styles/styles.scss
================================================
/* this file will be extracted to main dist folder and is imported in index.html */
/* This file is for setting global styles */
@import 'variables';
nav {
margin-top: 16px;
}
nav a {
background-color: $nav-button-color;
color: white;
padding: 8px 16px;
margin: 8px;
vertical-align: middle;
line-height: 1.25;
text-align: center;
text-decoration: none;
border-radius: 4px;
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmit": true,
"noEmitHelpers": true,
"importHelpers": true,
"strictNullChecks": false,
"lib": [
"dom",
"es6"
],
"baseUrl": "./src",
"paths": {
"@angular/*": ["node_modules/@angular/*"]
},
"typeRoots": [
"node_modules/@types"
],
"types": [
"hammerjs",
"jasmine",
"node",
"uglify-js",
"webpack"
]
},
"exclude": [
"node_modules",
"dist"
],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true,
"useWebpackText": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
}
}
================================================
FILE: tsconfig.webpack.json
================================================
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmitHelpers": true,
"importHelpers": true,
"strictNullChecks": false,
"lib": [
"es2015",
"dom"
],
"baseUrl": "./src",
"paths": {
"@angular/*": ["../node_modules/@angular/*"]
},
"typeRoots": [
"node_modules/@types"
],
"types": [
"hammerjs",
"node"
]
},
"exclude": [
"node_modules",
"dist",
"src/**/*.spec.ts",
"src/**/*.e2e.ts"
],
"angularCompilerOptions": {
"skipMetadataEmit": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
}
}
================================================
FILE: tslint.json
================================================
{
"extends": [
"tslint:recommended"
],
"linterOptions": {
"exclude": [
"src/*.d.ts"
]
},
"rulesDirectory": [
"node_modules/codelyzer",
"node_modules/rxjs-tslint"
],
"rules": {
"trailing-comma": [false, {"multiline": "always", "singleline": "never"}],
"interface-name": [false, "always-prefix"],
"component-class-suffix": true,
// "component-selector": [true, "element", "my", "kebab-case"],
"directive-class-suffix": true,
// "directive-selector": [true, "attribute", "my", "camelCase"],
"import-destructuring-spacing": true,
"no-attribute-parameter-decorator": true,
"no-forward-ref": true,
"no-input-rename": true,
"no-output-rename": true,
"only-arrow-functions": false,
"pipe-naming": [true, "camelCase", "my"],
"use-host-property-decorator": true,
"use-input-property-decorator": true,
"use-life-cycle-interface": true,
"use-output-property-decorator": true,
"use-pipe-transform-interface": true,
"no-console": [true,
"time",
"timeEnd",
"trace"
],
"max-line-length": [
true,
100
],
"no-string-literal": false,
"no-use-before-declare": true,
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single",
"avoid-escape"
],
"variable-name": [
true,
"allow-leading-underscore",
"allow-pascal-case",
"ban-keywords",
"check-format"
],
"rxjs-collapse-imports": true,
"rxjs-pipeable-operators-only": true,
"rxjs-no-static-observable-methods": true,
"rxjs-proper-imports": true
}
}
================================================
FILE: typedoc.json
================================================
{
"mode": "modules",
"out": "doc",
"theme": "default",
"ignoreCompilerErrors": "true",
"experimentalDecorators": "true",
"emitDecoratorMetadata": "true",
"target": "ES5",
"moduleResolution": "node",
"preserveConstEnums": "true",
"stripInternal": "true",
"suppressExcessPropertyErrors": "true",
"suppressImplicitAnyIndexErrors": "true",
"module": "commonjs"
}
================================================
FILE: webpack.config.js
================================================
/**
* @author: tipe.io
*/
/**
* Look in ./config folder for webpack.dev.js
*/
switch (process.env.NODE_ENV) {
case 'prod':
case 'production':
module.exports = require('./config/webpack.prod')({env: 'production'});
break;
case 'test':
case 'testing':
module.exports = require('./config/webpack.test')({env: 'test'});
break;
case 'dev':
case 'development':
default:
module.exports = require('./config/webpack.dev')({env: 'development'});
}
gitextract_obradcba/ ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── CONTRIBUTING.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .nvmrc ├── .travis.yml ├── .vscode/ │ ├── launch.json │ └── settings.json ├── Dockerfile ├── Dockerfile-dev ├── LICENSE ├── README.md ├── config/ │ ├── build-utils.js │ ├── config.common.json │ ├── config.dev.json │ ├── config.prod.json │ ├── empty.js │ ├── github-deploy/ │ │ └── index.js │ ├── head-config.common.js │ ├── helpers.js │ ├── html-elements-plugin/ │ │ └── index.js │ ├── karma.conf.js │ ├── nginx-custom.conf │ ├── protractor.conf.js │ ├── resource-override.js │ ├── spec-bundle.js │ ├── webpack.common.js │ ├── webpack.dev.js │ ├── webpack.github-deploy.js │ ├── webpack.prod.js │ └── webpack.test.js ├── docker-compose.yml ├── firebase.json ├── karma.conf.js ├── netlify.toml ├── package.json ├── protractor.conf.js ├── sonar-project.properties ├── src/ │ ├── app/ │ │ ├── +barrel/ │ │ │ ├── +child-barrel/ │ │ │ │ ├── child-barrel.component.ts │ │ │ │ ├── child-barrel.module.ts │ │ │ │ ├── child-barrel.routes.ts │ │ │ │ └── index.ts │ │ │ ├── barrel.component.ts │ │ │ ├── barrel.module.ts │ │ │ ├── barrel.routes.ts │ │ │ └── index.ts │ │ ├── +detail/ │ │ │ ├── +child-detail/ │ │ │ │ ├── child-detail.component.ts │ │ │ │ ├── child-detail.module.ts │ │ │ │ ├── child-detail.routes.ts │ │ │ │ └── index.ts │ │ │ ├── detail.component.ts │ │ │ ├── detail.module.ts │ │ │ ├── detail.routes.ts │ │ │ └── index.ts │ │ ├── +dev-module/ │ │ │ ├── dev-module.component.ts │ │ │ ├── dev-module.module.ts │ │ │ ├── dev-module.routes.ts │ │ │ └── index.ts │ │ ├── about/ │ │ │ ├── about.component.spec.ts │ │ │ ├── about.component.ts │ │ │ └── index.ts │ │ ├── app.component.css │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.e2e.ts │ │ ├── app.module.ts │ │ ├── app.resolver.ts │ │ ├── app.routes.ts │ │ ├── app.service.ts │ │ ├── home/ │ │ │ ├── home.component.css │ │ │ ├── home.component.html │ │ │ ├── home.component.spec.ts │ │ │ ├── home.component.ts │ │ │ ├── home.e2e.ts │ │ │ ├── index.ts │ │ │ ├── title/ │ │ │ │ ├── index.ts │ │ │ │ ├── title.service.spec.ts │ │ │ │ └── title.service.ts │ │ │ └── x-large/ │ │ │ ├── index.ts │ │ │ ├── x-large.directive.spec.ts │ │ │ └── x-large.directive.ts │ │ ├── index.ts │ │ └── no-content/ │ │ ├── index.ts │ │ └── no-content.component.ts │ ├── assets/ │ │ ├── css/ │ │ │ └── .gitkeep │ │ ├── data.json │ │ ├── humans.txt │ │ ├── icon/ │ │ │ └── browserconfig.xml │ │ ├── manifest.json │ │ ├── mock-data/ │ │ │ └── mock-data.json │ │ ├── robots.txt │ │ └── service-worker.js │ ├── custom-typings.d.ts │ ├── environments/ │ │ ├── environment.e2e.prod.ts │ │ ├── environment.prod.ts │ │ ├── environment.ts │ │ └── model.ts │ ├── index.html │ ├── main.browser.ts │ ├── meta/ │ │ ├── humans.txt │ │ └── robots.txt │ ├── polyfills.browser.ts │ └── styles/ │ ├── _variables.scss │ ├── headings.css │ └── styles.scss ├── tsconfig.json ├── tsconfig.webpack.json ├── tslint.json ├── typedoc.json └── webpack.config.js
SYMBOL INDEX (101 symbols across 35 files)
FILE: config/build-utils.js
constant APP_COMMON_CONFIG (line 6) | const APP_COMMON_CONFIG = require('./config.common.json');
constant DEFAULT_METADATA (line 8) | const DEFAULT_METADATA = {
function supportES2015 (line 26) | function supportES2015(tsConfigPath) {
function readTsConfig (line 34) | function readTsConfig(tsConfigPath) {
function getEnvFile (line 40) | function getEnvFile(suffix) {
function rxjsAlias (line 66) | function rxjsAlias(supportES2015) {
function ngcWebpackSetup (line 76) | function ngcWebpackSetup(prod, metadata) {
FILE: config/github-deploy/index.js
constant REPO_NAME_RE (line 9) | const REPO_NAME_RE = /Push {2}URL: ((git@github\.com:)|(https:\/\/github...
function getWebpackConfigModule (line 11) | function getWebpackConfigModule(options) {
function getRepoName (line 21) | function getRepoName(remoteName) {
function stripTrailing (line 34) | function stripTrailing(str, char) {
function safeUrl (line 57) | function safeUrl(url) {
function replaceHtmlWebpackPlugin (line 62) | function replaceHtmlWebpackPlugin(plugins, ghRepoName) {
FILE: config/helpers.js
constant EVENT (line 6) | const EVENT = process.env.npm_lifecycle_event || '';
function hasProcessFlag (line 13) | function hasProcessFlag(flag) {
function hasNpmFlag (line 17) | function hasNpmFlag(flag) {
function isWebpackDevServer (line 21) | function isWebpackDevServer() {
FILE: config/html-elements-plugin/index.js
constant RE_ENDS_WITH_BS (line 1) | const RE_ENDS_WITH_BS = /\/$/;
function createTag (line 14) | function createTag(tagName, attrMap, publicPath) {
function getHtmlElementString (line 74) | function getHtmlElementString(dataSource, publicPath) {
class HtmlElementsPlugin (line 91) | class HtmlElementsPlugin {
method constructor (line 92) | constructor(locations) {
method apply (line 97) | apply(compiler) {
FILE: config/spec-bundle.js
function requireAll (line 51) | function requireAll(requireContext) {
FILE: config/webpack.github-deploy.js
constant GIT_REMOTE_NAME (line 13) | const GIT_REMOTE_NAME = 'origin';
constant COMMIT_MESSAGE (line 14) | const COMMIT_MESSAGE = 'Updates';
constant GH_REPO_NAME (line 15) | const GH_REPO_NAME = ghDeploy.getRepoName(GIT_REMOTE_NAME);
FILE: config/webpack.prod.js
function getUglifyOptions (line 31) | function getUglifyOptions(supportES2015, enableCompress) {
FILE: config/webpack.test.js
constant ENV (line 18) | const ENV = (process.env.ENV = process.env.NODE_ENV = 'test');
FILE: src/app/+barrel/+child-barrel/child-barrel.component.ts
class ChildBarrelComponent (line 19) | class ChildBarrelComponent implements OnInit {
method ngOnInit (line 21) | public ngOnInit() {
FILE: src/app/+barrel/+child-barrel/child-barrel.module.ts
class ChildBarrelModule (line 24) | class ChildBarrelModule {
FILE: src/app/+barrel/barrel.component.ts
class BarrelComponent (line 25) | class BarrelComponent implements OnInit {
method ngOnInit (line 27) | public ngOnInit() {
FILE: src/app/+barrel/barrel.module.ts
class BarrelModule (line 24) | class BarrelModule {
FILE: src/app/+detail/+child-detail/child-detail.component.ts
class ChildDetailComponent (line 19) | class ChildDetailComponent implements OnInit {
method ngOnInit (line 21) | public ngOnInit() {
FILE: src/app/+detail/+child-detail/child-detail.module.ts
class ChildDetailModule (line 24) | class ChildDetailModule {
FILE: src/app/+detail/detail.component.ts
class DetailComponent (line 25) | class DetailComponent implements OnInit {
method ngOnInit (line 27) | public ngOnInit() {
FILE: src/app/+detail/detail.module.ts
class DetailModule (line 24) | class DetailModule {
FILE: src/app/+dev-module/dev-module.component.ts
class DevModuleComponent (line 9) | class DevModuleComponent implements OnInit {
method ngOnInit (line 11) | public ngOnInit() {
FILE: src/app/+dev-module/dev-module.module.ts
class DevModuleModule (line 19) | class DevModuleModule {
method constructor (line 21) | constructor() {
FILE: src/app/about/about.component.ts
class AboutComponent (line 25) | class AboutComponent implements OnInit {
method constructor (line 28) | constructor(
method ngOnInit (line 32) | public ngOnInit() {
method asyncDataWithWebpack (line 51) | private asyncDataWithWebpack() {
FILE: src/app/app.component.ts
constant ROOT_SELECTOR (line 8) | const ROOT_SELECTOR = 'app';
class AppComponent (line 64) | class AppComponent implements OnInit {
method constructor (line 71) | constructor(
method ngOnInit (line 75) | public ngOnInit() {
FILE: src/app/app.module.ts
constant APP_PROVIDERS (line 27) | const APP_PROVIDERS = [
type StoreType (line 32) | interface StoreType {
class AppModule (line 78) | class AppModule {}
FILE: src/app/app.resolver.ts
class DataResolver (line 6) | class DataResolver implements Resolve<any> {
method resolve (line 7) | public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapsh...
constant APP_RESOLVER_PROVIDERS (line 15) | const APP_RESOLVER_PROVIDERS = [
FILE: src/app/app.routes.ts
constant ROUTES (line 6) | const ROUTES: Routes = [
FILE: src/app/app.service.ts
type InternalStateType (line 3) | interface InternalStateType {
class AppState (line 8) | class AppState {
method state (line 15) | public get state() {
method state (line 21) | public set state(value) {
method get (line 25) | public get(prop?: any) {
method set (line 33) | public set(prop: string, value: any) {
method _clone (line 40) | private _clone(object: InternalStateType) {
FILE: src/app/home/home.component.ts
class HomeComponent (line 32) | class HomeComponent implements OnInit {
method constructor (line 40) | constructor(
method ngOnInit (line 45) | public ngOnInit() {
method submitState (line 52) | public submitState(value: string) {
FILE: src/app/home/title/title.service.ts
class Title (line 5) | class Title {
method constructor (line 9) | constructor(
method getData (line 13) | public getData() {
FILE: src/app/home/x-large/x-large.directive.spec.ts
class TestComponent (line 23) | @Component({
FILE: src/app/home/x-large/x-large.directive.ts
class XLargeDirective (line 15) | class XLargeDirective {
method constructor (line 16) | constructor(
FILE: src/app/no-content/no-content.component.ts
class NoContentComponent (line 11) | class NoContentComponent {
FILE: src/custom-typings.d.ts
type FirebaseConfig (line 65) | interface FirebaseConfig {
type SystemJS (line 74) | interface SystemJS {
type GlobalEnvironment (line 78) | interface GlobalEnvironment {
type Es6PromiseLoader (line 86) | interface Es6PromiseLoader {
type FactoryEs6PromiseLoader (line 90) | type FactoryEs6PromiseLoader = () => Es6PromiseLoader;
type FactoryPromise (line 91) | type FactoryPromise = () => Promise<any>;
type AsyncRoutes (line 93) | type AsyncRoutes = {
type IdleCallbacks (line 100) | type IdleCallbacks = Es6PromiseLoader |
type WebpackModule (line 105) | interface WebpackModule {
type WebpackRequire (line 121) | interface WebpackRequire {
type WebpackContext (line 128) | interface WebpackContext extends WebpackRequire {
type ErrorStackTraceLimit (line 132) | interface ErrorStackTraceLimit {
type NodeRequire (line 137) | interface NodeRequire extends WebpackRequire {}
type ErrorConstructor (line 138) | interface ErrorConstructor extends ErrorStackTraceLimit {}
type NodeRequireFunction (line 139) | interface NodeRequireFunction extends Es6PromiseLoader {}
type NodeModule (line 140) | interface NodeModule extends WebpackModule {}
type Global (line 141) | interface Global extends GlobalEnvironment {}
FILE: src/environments/environment.e2e.prod.ts
method decorateModuleRef (line 19) | decorateModuleRef(modRef: NgModuleRef<any>) {
FILE: src/environments/environment.prod.ts
method decorateModuleRef (line 19) | decorateModuleRef(modRef: NgModuleRef<any>) {
FILE: src/environments/environment.ts
method decorateModuleRef (line 22) | decorateModuleRef(modRef: NgModuleRef<any>) {
FILE: src/environments/model.ts
type Environment (line 3) | interface Environment {
FILE: src/main.browser.ts
function main (line 18) | function main(): Promise<any> {
function _domReadyHandler (line 59) | function _domReadyHandler() {
Condensed preview — 114 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (152K chars).
[
{
"path": ".dockerignore",
"chars": 350,
"preview": ".git\n.github\n.vscode\ncoverage\n\n# OS generated files #\n.DS_Store\nehthumbs.db\nIcon?\nThumbs.db\n\n# Node Files #\nnode_modules"
},
{
"path": ".editorconfig",
"chars": 254,
"preview": "# tipe.io\n# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line ="
},
{
"path": ".gitattributes",
"chars": 16,
"preview": "yarn.lock -diff\n"
},
{
"path": ".github/CONTRIBUTING.md",
"chars": 516,
"preview": "## Read and contribute to the Wiki\n\nMake sure you read the [Wiki](https://github.com/gdi2290/angular-starter/wiki).\n\n## "
},
{
"path": ".github/FUNDING.yml",
"chars": 723,
"preview": "# These are supported funding model platforms\n\ngithub: [PatrickJS] # Replace with up to 4 GitHub Sponsors-enabled userna"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 989,
"preview": "* **I'm submitting a ...**\n[ ] bug report\n[ ] feature request\n[ ] question about the decisions made in the repository\n\n*"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 261,
"preview": "* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)\n\n\n\n* **What is the current behavi"
},
{
"path": ".gitignore",
"chars": 1028,
"preview": "# tipe.io\n\n# Logs\nlogs\n*.log\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverag"
},
{
"path": ".nvmrc",
"chars": 6,
"preview": "lts/*\n"
},
{
"path": ".travis.yml",
"chars": 323,
"preview": "sudo: false\ndist: trusty\nlanguage: node_js\n\ncache:\n directories:\n - node_modules\n\naddons:\n chrome: stable\n\nnode_js:"
},
{
"path": ".vscode/launch.json",
"chars": 782,
"preview": "{\n \"version\": \"0.2.0\",\n \"configurations\": [\n {\n \"name\": \"Launch Chrome against localhost, with s"
},
{
"path": ".vscode/settings.json",
"chars": 56,
"preview": "{\n \"typescript.tsdk\": \"node_modules/typescript/lib/\"\n}\n"
},
{
"path": "Dockerfile",
"chars": 1155,
"preview": "# Usage:\n#\n# Build image:\n# docker build -t angular-starter .\n#\n# Run image (on localhost:8080):\n# docker ru"
},
{
"path": "Dockerfile-dev",
"chars": 599,
"preview": "# Usage:\n#\n# Build image:\n# docker build -t angular-starter .\n#\n# Run image (on localhost:8080):\n# docker ru"
},
{
"path": "LICENSE",
"chars": 1091,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015-2018 PatrickJS, Tipe Inc\n\nPermission is hereby granted, free of charge, to any"
},
{
"path": "README.md",
"chars": 24232,
"preview": "# Please use the Angular CLI if you want an angular app\n\n[;\nconst path = require('path');\nconst fs = require('fs');\nconst helpers = require('./hel"
},
{
"path": "config/config.common.json",
"chars": 313,
"preview": "{\n \"title\": \"Angular Starter by @gdi2290 from @TipeIO\",\n \"description\": \"An Angular starter kit featuring Angular 5, A"
},
{
"path": "config/config.dev.json",
"chars": 248,
"preview": "{\n \"firebase\": {\n \"apiKey\": \"\",\n \"authDomain\": \"XXXXXX.firebaseapp.com\",\n \"databaseURL\": \"https://XXXXXX.fireb"
},
{
"path": "config/config.prod.json",
"chars": 276,
"preview": "{\n \"firebase\": {\n \"apiKey\": \"\",\n \"authDomain\": \"XXXXXX.firebaseapp.com\",\n \"databaseURL\": \"https://XXXXXX.fireb"
},
{
"path": "config/empty.js",
"chars": 278,
"preview": "module.exports = {\n hmrModule: function(ngmodule) {\n return ngmodule;\n },\n NgProbeToken: {},\n HmrState: function("
},
{
"path": "config/github-deploy/index.js",
"chars": 2691,
"preview": "const execSync = require('child_process').execSync;\n/**\n * Used to merge webpack configs.\n */\nconst webpackMerge = requi"
},
{
"path": "config/head-config.common.js",
"chars": 2488,
"preview": "/**\n * Configuration for head elements added during the creation of index.html.\n *\n * All href attributes are added the "
},
{
"path": "config/helpers.js",
"chars": 630,
"preview": "/**\n * @author: tipe.io\n */\nconst path = require('path');\n\nconst EVENT = process.env.npm_lifecycle_event || '';\n\n/**\n * "
},
{
"path": "config/html-elements-plugin/index.js",
"chars": 3587,
"preview": "const RE_ENDS_WITH_BS = /\\/$/;\n\n/**\n * Create an HTML tag with attributes from a map.\n *\n * Example:\n * createTag('link'"
},
{
"path": "config/karma.conf.js",
"chars": 4099,
"preview": "/**\n * @author: tipe.io\n */\n\nmodule.exports = function (config) {\n const testWebpackConfig = require('./webpack.test.js"
},
{
"path": "config/nginx-custom.conf",
"chars": 523,
"preview": "server {\n listen 80;\n\n gzip on;\n gzip_http_version 1.1;\n gzip_disable \"MSIE [1-6]\\.\";\n gzip_min_length 1100;"
},
{
"path": "config/protractor.conf.js",
"chars": 1020,
"preview": "/**\n * @author: tipe.io\n */\n\nrequire('ts-node/register');\nvar helpers = require('./helpers');\n\nexports.config = {\n base"
},
{
"path": "config/resource-override.js",
"chars": 0,
"preview": ""
},
{
"path": "config/spec-bundle.js",
"chars": 1987,
"preview": "/**\n * @author: tipe.io\n */\n\n/**\n * When testing with webpack and ES6, we have to do some extra\n * things to get testing"
},
{
"path": "config/webpack.common.js",
"chars": 9373,
"preview": "/**\n * @author: tipe.io\n */\n\nconst helpers = require('./helpers');\n\n/**\n * Webpack Plugins\n *\n * problem with copy-webpa"
},
{
"path": "config/webpack.dev.js",
"chars": 4578,
"preview": "/**\n * @author: tipe.io\n */\n\nconst helpers = require('./helpers');\nconst buildUtils = require('./build-utils');\nconst we"
},
{
"path": "config/webpack.github-deploy.js",
"chars": 2877,
"preview": "/**\n * @author: tipe.io\n */\nconst fs = require('fs');\nconst path = require('path');\nconst helpers = require('./helpers')"
},
{
"path": "config/webpack.prod.js",
"chars": 5338,
"preview": "/**\n * @author: tipe.io\n */\nconst helpers = require('./helpers');\nconst buildUtils = require('./build-utils');\n\n/**\n * U"
},
{
"path": "config/webpack.test.js",
"chars": 6817,
"preview": "/**\n * @author: tipe.io\n */\n\nconst helpers = require('./helpers');\n\n/**\n * Webpack Plugins\n */\nconst ProvidePlugin = req"
},
{
"path": "docker-compose.yml",
"chars": 320,
"preview": "version: '3'\nservices:\n angular-starter:\n build:\n context: .\n dockerfile: Dockerfile-dev\n container_nam"
},
{
"path": "firebase.json",
"chars": 233,
"preview": "{\n \"hosting\": {\n \"public\": \"dist\",\n \"rewrites\": [\n {\n \"source\": \"**\",\n \"destination\": \"/index."
},
{
"path": "karma.conf.js",
"chars": 127,
"preview": "/**\n * @author: tipe.io\n */\n\n/**\n * Look in ./config for karma.conf.js\n */\nmodule.exports = require('./config/karma.conf"
},
{
"path": "netlify.toml",
"chars": 60,
"preview": "[build]\n command = \"npm run build:prod\"\n publish = \"dist\"\n"
},
{
"path": "package.json",
"chars": 8108,
"preview": "{\n \"name\": \"angular-starter\",\n \"version\": \"7.5.0\",\n \"description\": \"An Angular Webpack Starter kit featuring Angular "
},
{
"path": "protractor.conf.js",
"chars": 144,
"preview": "/**\n * @author: tipe.io\n */\n\n/**\n * look in ./config for protractor.conf.js\n */\nexports.config = require('./config/protr"
},
{
"path": "sonar-project.properties",
"chars": 631,
"preview": "sonar.projectKey=angular:angular-starter\nsonar.projectName=angular-starter\nsonar.projectVersion=6.0.0\nsonar.sourceEncodi"
},
{
"path": "src/app/+barrel/+child-barrel/child-barrel.component.ts",
"chars": 568,
"preview": "import {\n Component,\n OnInit,\n} from '@angular/core';\n/**\n * We're loading this component asynchronously\n * We are usi"
},
{
"path": "src/app/+barrel/+child-barrel/child-barrel.module.ts",
"chars": 633,
"preview": "import { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '"
},
{
"path": "src/app/+barrel/+child-barrel/child-barrel.routes.ts",
"chars": 162,
"preview": "import { ChildBarrelComponent } from './child-barrel.component';\n\nexport const routes = [\n { path: '', component: Child"
},
{
"path": "src/app/+barrel/+child-barrel/index.ts",
"chars": 59,
"preview": "export { ChildBarrelModule } from './child-barrel.module';\n"
},
{
"path": "src/app/+barrel/barrel.component.ts",
"chars": 678,
"preview": "import {\n Component,\n OnInit,\n} from '@angular/core';\n/**\n * We're loading this component asynchronously\n * We are usi"
},
{
"path": "src/app/+barrel/barrel.module.ts",
"chars": 601,
"preview": "import { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '"
},
{
"path": "src/app/+barrel/barrel.routes.ts",
"chars": 240,
"preview": "import { BarrelComponent } from './barrel.component';\n\nexport const routes = [\n { path: '', children: [\n { path: '',"
},
{
"path": "src/app/+barrel/index.ts",
"chars": 48,
"preview": "export { BarrelModule } from './barrel.module';\n"
},
{
"path": "src/app/+detail/+child-detail/child-detail.component.ts",
"chars": 568,
"preview": "import {\n Component,\n OnInit,\n} from '@angular/core';\n/**\n * We're loading this component asynchronously\n * We are usi"
},
{
"path": "src/app/+detail/+child-detail/child-detail.module.ts",
"chars": 633,
"preview": "import { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '"
},
{
"path": "src/app/+detail/+child-detail/child-detail.routes.ts",
"chars": 162,
"preview": "import { ChildDetailComponent } from './child-detail.component';\n\nexport const routes = [\n { path: '', component: Child"
},
{
"path": "src/app/+detail/+child-detail/index.ts",
"chars": 59,
"preview": "export { ChildDetailModule } from './child-detail.module';\n"
},
{
"path": "src/app/+detail/detail.component.ts",
"chars": 678,
"preview": "import {\n Component,\n OnInit,\n} from '@angular/core';\n/**\n * We're loading this component asynchronously\n * We are usi"
},
{
"path": "src/app/+detail/detail.module.ts",
"chars": 601,
"preview": "import { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '"
},
{
"path": "src/app/+detail/detail.routes.ts",
"chars": 240,
"preview": "import { DetailComponent } from './detail.component';\n\nexport const routes = [\n { path: '', children: [\n { path: '',"
},
{
"path": "src/app/+detail/index.ts",
"chars": 48,
"preview": "export { DetailModule } from './detail.module';\n"
},
{
"path": "src/app/+dev-module/dev-module.component.ts",
"chars": 287,
"preview": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n selector: 'dev-module',\n template: `\n <h1>Hello f"
},
{
"path": "src/app/+dev-module/dev-module.module.ts",
"chars": 669,
"preview": "import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterModule } from '"
},
{
"path": "src/app/+dev-module/dev-module.routes.ts",
"chars": 145,
"preview": "import { DevModuleComponent } from './dev-module.component';\n\nexport const routes = [\n { path: 'dev-module', component:"
},
{
"path": "src/app/+dev-module/index.ts",
"chars": 55,
"preview": "export { DevModuleModule } from './dev-module.module';\n"
},
{
"path": "src/app/about/about.component.spec.ts",
"chars": 983,
"preview": "import { ActivatedRoute, Data } from '@angular/router';\nimport { Component } from '@angular/core';\nimport { inject, Test"
},
{
"path": "src/app/about/about.component.ts",
"chars": 1539,
"preview": "import {\n Component,\n OnInit\n} from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\n\n@Component({\n "
},
{
"path": "src/app/about/index.ts",
"chars": 35,
"preview": "export * from './about.component';\n"
},
{
"path": "src/app/app.component.css",
"chars": 114,
"preview": "html, body{\n height: 100%;\n font-family: Arial, Helvetica, sans-serif\n}\n\na.active {\n background-color: gray;\n}\n"
},
{
"path": "src/app/app.component.spec.ts",
"chars": 1437,
"preview": "import { NO_ERRORS_SCHEMA } from '@angular/core';\nimport {\n inject,\n async,\n TestBed,\n ComponentFixture\n} from '@ang"
},
{
"path": "src/app/app.component.ts",
"chars": 2475,
"preview": "/**\n * Angular 2 decorators and services\n */\nimport { Component, OnInit, ViewEncapsulation } from '@angular/core';\nimpor"
},
{
"path": "src/app/app.e2e.ts",
"chars": 890,
"preview": "import { browser, by, element } from 'protractor';\nimport 'tslib';\n\ndescribe('App', () => {\n\n beforeEach(async () => {\n"
},
{
"path": "src/app/app.module.ts",
"chars": 2253,
"preview": "import { NgModule } from '@angular/core';\nimport { BrowserModule } from '@angular/platform-browser';\nimport { FormsModul"
},
{
"path": "src/app/app.resolver.ts",
"chars": 466,
"preview": "import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';\nimport { Injectable } from '@ang"
},
{
"path": "src/app/app.routes.ts",
"chars": 527,
"preview": "import { Routes } from '@angular/router';\nimport { HomeComponent } from './home';\nimport { AboutComponent } from './abou"
},
{
"path": "src/app/app.service.ts",
"chars": 923,
"preview": "import { Injectable } from '@angular/core';\n\nexport interface InternalStateType {\n [key: string]: any;\n}\n\n@Injectable()"
},
{
"path": "src/app/home/home.component.css",
"chars": 32,
"preview": "/*styles for home content only*/"
},
{
"path": "src/app/home/home.component.html",
"chars": 931,
"preview": "<div>\n <h1 x-large class=\"sample-content\">Your Content Here</h1>\n\n <hr>\n\n <div>\n For hot module reloading run\n "
},
{
"path": "src/app/home/home.component.spec.ts",
"chars": 1750,
"preview": "import { NO_ERRORS_SCHEMA } from '@angular/core';\nimport {\n inject,\n async,\n TestBed,\n ComponentFixture,\n getTestBe"
},
{
"path": "src/app/home/home.component.ts",
"chars": 1385,
"preview": "import {\n Component,\n OnInit\n} from '@angular/core';\n\nimport { AppState } from '../app.service';\nimport { Title } from"
},
{
"path": "src/app/home/home.e2e.ts",
"chars": 690,
"preview": "import { browser, by, element } from 'protractor';\nimport 'tslib';\n\ndescribe('Home', () => {\n\n beforeEach(async () => {"
},
{
"path": "src/app/home/index.ts",
"chars": 34,
"preview": "export * from './home.component';\n"
},
{
"path": "src/app/home/title/index.ts",
"chars": 33,
"preview": "export * from './title.service';\n"
},
{
"path": "src/app/home/title/title.service.spec.ts",
"chars": 898,
"preview": "import {\n inject,\n async,\n TestBed,\n ComponentFixture,\n getTestBed\n} from '@angular/core/testing';\nimport { Compone"
},
{
"path": "src/app/home/title/title.service.ts",
"chars": 336,
"preview": "import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\n@Injectable()\nexport cla"
},
{
"path": "src/app/home/x-large/index.ts",
"chars": 37,
"preview": "export * from './x-large.directive';\n"
},
{
"path": "src/app/home/x-large/x-large.directive.spec.ts",
"chars": 1133,
"preview": "import { By } from '@angular/platform-browser';\nimport {\n inject,\n fakeAsync,\n tick,\n async,\n TestBed,\n ComponentF"
},
{
"path": "src/app/home/x-large/x-large.directive.ts",
"chars": 745,
"preview": "import {\n Component,\n Directive,\n ElementRef,\n Renderer\n} from '@angular/core';\n/**\n * Directive\n * XLarge is a simp"
},
{
"path": "src/app/index.ts",
"chars": 45,
"preview": "/**\n * App\n */\nexport * from './app.module';\n"
},
{
"path": "src/app/no-content/index.ts",
"chars": 40,
"preview": "export * from './no-content.component';\n"
},
{
"path": "src/app/no-content/no-content.component.ts",
"chars": 195,
"preview": "import { Component } from '@angular/core';\n\n@Component({\n selector: 'no-content',\n template: `\n <div>\n <h1>404"
},
{
"path": "src/assets/css/.gitkeep",
"chars": 14,
"preview": "@AngularClass\n"
},
{
"path": "src/assets/data.json",
"chars": 30,
"preview": "{\n \"value\": \"AngularClass\"\n}\n"
},
{
"path": "src/assets/humans.txt",
"chars": 251,
"preview": "# humanstxt.org/\n# The humans responsible & technology colophon\n\n# TEAM\n\n <name> -- <role> -- <twitter>\n\n# THANKS\n\n <n"
},
{
"path": "src/assets/icon/browserconfig.xml",
"chars": 281,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"/ms-icon-70x70.png\"/><s"
},
{
"path": "src/assets/manifest.json",
"chars": 654,
"preview": "{\n \"name\": \"App\",\n \"icons\": [\n {\n \"src\": \"/assets/icon/android-icon-36x36.png\",\n \"sizes\": \"36x36\",\n \"type\": \"imag"
},
{
"path": "src/assets/mock-data/mock-data.json",
"chars": 22,
"preview": "[\n {\"res\": \"data\"}\n]\n"
},
{
"path": "src/assets/robots.txt",
"chars": 31,
"preview": "# robotstxt.org\n\nUser-agent: *\n"
},
{
"path": "src/assets/service-worker.js",
"chars": 44,
"preview": "// This file is intentionally without code.\n"
},
{
"path": "src/custom-typings.d.ts",
"chars": 4281,
"preview": "/*\n * Custom Type Definitions\n * When including 3rd party modules you also need to include the type definition for the m"
},
{
"path": "src/environments/environment.e2e.prod.ts",
"chars": 662,
"preview": "/* tslint:disable */\nimport { enableProdMode, NgModuleRef } from '@angular/core';\nimport { disableDebugTools } from '@an"
},
{
"path": "src/environments/environment.prod.ts",
"chars": 663,
"preview": "/* tslint:disable */\nimport { enableProdMode, NgModuleRef } from '@angular/core';\nimport { disableDebugTools } from '@an"
},
{
"path": "src/environments/environment.ts",
"chars": 953,
"preview": "/* tslint:disable */\n\nimport { ApplicationRef, NgModuleRef } from '@angular/core';\nimport { enableDebugTools } from '@an"
},
{
"path": "src/environments/model.ts",
"chars": 215,
"preview": "import { NgModuleRef } from '@angular/core';\n\nexport interface Environment {\n production: boolean;\n ENV_PROVIDERS: any"
},
{
"path": "src/index.html",
"chars": 2057,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\">\n <meta n"
},
{
"path": "src/main.browser.ts",
"chars": 1756,
"preview": "/**\n * Angular bootstrapping\n */\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\nimport { en"
},
{
"path": "src/meta/humans.txt",
"chars": 251,
"preview": "# humanstxt.org/\n# The humans responsible & technology colophon\n\n# TEAM\n\n <name> -- <role> -- <twitter>\n\n# THANKS\n\n <n"
},
{
"path": "src/meta/robots.txt",
"chars": 31,
"preview": "# robotstxt.org\n\nUser-agent: *\n"
},
{
"path": "src/polyfills.browser.ts",
"chars": 2660,
"preview": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfi"
},
{
"path": "src/styles/_variables.scss",
"chars": 27,
"preview": "$nav-button-color: #00838F;"
},
{
"path": "src/styles/headings.css",
"chars": 24,
"preview": "h1 {\n color: #00BCD4;\n}"
},
{
"path": "src/styles/styles.scss",
"chars": 398,
"preview": "/* this file will be extracted to main dist folder and is imported in index.html */\n/* This file is for setting global s"
},
{
"path": "tsconfig.json",
"chars": 891,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"module\": \"commonjs\",\n \"moduleResolution\": \"node\",\n \"emitDecorat"
},
{
"path": "tsconfig.webpack.json",
"chars": 838,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"module\": \"esnext\",\n \"moduleResolution\": \"node\",\n \"emitDecorator"
},
{
"path": "tslint.json",
"chars": 1664,
"preview": "{\n \"extends\": [\n \"tslint:recommended\"\n ],\n \"linterOptions\": {\n \"exclude\": [\n \"src/*.d.ts\"\n ]\n },\n \"ru"
},
{
"path": "typedoc.json",
"chars": 385,
"preview": "{\n \"mode\": \"modules\",\n \"out\": \"doc\",\n \"theme\": \"default\",\n \"ignoreCompilerErrors\": \"true\",\n \"experimentalDecorators"
},
{
"path": "webpack.config.js",
"chars": 477,
"preview": "/**\n * @author: tipe.io\n */\n\n/**\n * Look in ./config folder for webpack.dev.js\n */\nswitch (process.env.NODE_ENV) {\n cas"
}
]
About this extraction
This page contains the full source code of the PatrickJS/PatrickJS-starter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 114 files (136.4 KB), approximately 38.0k tokens, and a symbol index with 101 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.