Full Code of driftyco/ionic-app-scripts for AI

master 972fdeccefbb cached
148 files
814.5 KB
228.7k tokens
814 symbols
1 requests
Download .txt
Showing preview only (860K chars total). Download the full file or copy to clipboard to get everything.
Repository: driftyco/ionic-app-scripts
Branch: master
Commit: 972fdeccefbb
Files: 148
Total size: 814.5 KB

Directory structure:
gitextract_525rclba/

├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .npmrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bin/
│   ├── ion-dev.js
│   └── ionic-app-scripts.js
├── circle.yml
├── config/
│   ├── cleancss.config.js
│   ├── copy.config.js
│   ├── sass.config.js
│   ├── uglifyjs.config.js
│   ├── watch.config.js
│   └── webpack.config.js
├── lab/
│   ├── index.html
│   └── static/
│       ├── css/
│       │   └── style.css
│       └── js/
│           └── lab.js
├── package.json
├── preprocessor.js
├── scripts/
│   ├── commit-changelog.js
│   ├── create-github-release.js
│   └── publish-nightly.js
├── src/
│   ├── aot/
│   │   ├── aot-compiler.ts
│   │   ├── compiler-host-factory.ts
│   │   ├── compiler-host.ts
│   │   └── utils.ts
│   ├── build/
│   │   └── util.ts
│   ├── build.spec.ts
│   ├── build.ts
│   ├── bundle.spec.ts
│   ├── bundle.ts
│   ├── clean.spec.ts
│   ├── clean.ts
│   ├── cleancss.spec.ts
│   ├── cleancss.ts
│   ├── copy.spec.ts
│   ├── copy.ts
│   ├── core/
│   │   ├── bundle-components.ts
│   │   ├── inject-script.spec.ts
│   │   ├── inject-scripts.ts
│   │   ├── ionic-global.spec.ts
│   │   └── ionic-global.ts
│   ├── declarations.d.ts
│   ├── deep-linking/
│   │   ├── util.spec.ts
│   │   └── util.ts
│   ├── deep-linking.spec.ts
│   ├── deep-linking.ts
│   ├── dev-client/
│   │   └── sass/
│   │       ├── _code-block.scss
│   │       ├── _diagnostics.scss
│   │       ├── _header.scss
│   │       ├── _options-menu.scss
│   │       ├── _stack-block.scss
│   │       ├── _system-info.scss
│   │       ├── _toast.scss
│   │       └── ion-dev.scss
│   ├── dev-server/
│   │   ├── http-server.ts
│   │   ├── injector.ts
│   │   ├── lab.ts
│   │   ├── live-reload.ts
│   │   ├── notification-server.ts
│   │   └── serve-config.ts
│   ├── generators/
│   │   ├── constants.ts
│   │   ├── util.spec.ts
│   │   └── util.ts
│   ├── generators.ts
│   ├── highlight/
│   │   ├── github-gist.scss
│   │   ├── highlight.spec.ts
│   │   └── highlight.ts
│   ├── index.ts
│   ├── lint/
│   │   ├── lint-factory.spec.ts
│   │   ├── lint-factory.ts
│   │   ├── lint-utils.spec.ts
│   │   └── lint-utils.ts
│   ├── lint.spec.ts
│   ├── lint.ts
│   ├── logger/
│   │   ├── logger-diagnostics.ts
│   │   ├── logger-runtime.ts
│   │   ├── logger-sass.ts
│   │   ├── logger-tslint.ts
│   │   ├── logger-typescript.ts
│   │   └── logger.ts
│   ├── minify.ts
│   ├── mocks/
│   │   └── mock-helpers.ts
│   ├── ngc.ts
│   ├── optimization/
│   │   ├── remove-unused-fonts.spec.ts
│   │   └── remove-unused-fonts.ts
│   ├── postprocess.ts
│   ├── preprocess.spec.ts
│   ├── preprocess.ts
│   ├── sass.ts
│   ├── serve.spec.ts
│   ├── serve.ts
│   ├── template.spec.ts
│   ├── template.ts
│   ├── transpile-worker.ts
│   ├── transpile.spec.ts
│   ├── transpile.ts
│   ├── uglifyjs.ts
│   ├── upgrade-scripts/
│   │   ├── add-default-ngmodules.spec.ts
│   │   └── add-default-ngmodules.ts
│   ├── util/
│   │   ├── clean-css-factory.ts
│   │   ├── config.spec.ts
│   │   ├── config.ts
│   │   ├── constants.ts
│   │   ├── cordova-config.spec.ts
│   │   ├── cordova-config.ts
│   │   ├── errors.spec.ts
│   │   ├── errors.ts
│   │   ├── events.ts
│   │   ├── file-cache.ts
│   │   ├── glob-util.ts
│   │   ├── helpers/
│   │   │   ├── camel-case-regexp.ts
│   │   │   ├── camel-case-upper-regexp.ts
│   │   │   └── non-word-regexp.ts
│   │   ├── helpers.spec.ts
│   │   ├── helpers.ts
│   │   ├── hybrid-file-system-factory.ts
│   │   ├── hybrid-file-system.ts
│   │   ├── interfaces.ts
│   │   ├── ionic-project.ts
│   │   ├── network.ts
│   │   ├── open.ts
│   │   ├── promisify.ts
│   │   ├── source-maps.spec.ts
│   │   ├── source-maps.ts
│   │   ├── typescript-utils.spec.ts
│   │   ├── typescript-utils.ts
│   │   └── virtual-file-utils.ts
│   ├── watch.spec.ts
│   ├── watch.ts
│   ├── webpack/
│   │   ├── cache-loader-impl.ts
│   │   ├── cache-loader.ts
│   │   ├── common-chunks-plugins.ts
│   │   ├── ionic-environment-plugin.ts
│   │   ├── ionic-webpack-factory.ts
│   │   ├── loader-impl.spec.ts
│   │   ├── loader-impl.ts
│   │   ├── loader.ts
│   │   ├── source-mapper.ts
│   │   └── watch-memory-system.ts
│   ├── webpack.ts
│   ├── worker-client.ts
│   └── worker-process.ts
├── tsconfig.json
└── tslint.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# 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: .github/ISSUE_TEMPLATE.md
================================================
**Note: for support questions, please use one of these channels:**

https://forum.ionicframework.com/
http://ionicworldwide.herokuapp.com/


#### Short description of the problem:


#### What behavior are you expecting?


**Steps to reproduce:**
1.
2.
3.

```
insert any relevant code between the above and below backticks
```

**Which @ionic/app-scripts version are you using?**


**Other information:** (e.g. stacktraces, related issues, suggestions how to fix, stackoverflow links, forum links, etc)



================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
#### Short description of what this resolves:


#### Changes proposed in this pull request:

-
-
-

**Fixes**: #


================================================
FILE: .gitignore
================================================
.DS_Store

# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage


# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

# various
dist

.vscode
*.sw[mnpcod]

bin/ion-dev.css

# WebStorm
.idea


================================================
FILE: .npmrc
================================================
package-lock=false


================================================
FILE: CHANGELOG.md
================================================
<a name="3.2.4"></a>
## [3.2.4](https://github.com/ionic-team/ionic-app-scripts/compare/v3.2.3...v3.2.4) (2019-05-24)


### Bug Fixes

*  **livereload:** always serve latest file changes ([#1521](https://github.com/ionic-team/ionic-app-scripts/issues/1521)) ([266a871](https://github.com/ionic-team/ionic-app-scripts/commit/266a871))



<a name="3.2.3"></a>
## [3.2.3](https://github.com/ionic-team/ionic-app-scripts/compare/v3.2.2...v3.2.3) (2019-03-01)


### Bug Fixes

* **livereload:** fix issue with files not reloading([8870a17](https://github.com/ionic-team/ionic-app-scripts/commit/8870a17))



<a name="3.2.2"></a>
## [3.2.2](https://github.com/ionic-team/ionic-app-scripts/compare/v3.2.1...v3.2.2) (2019-01-22)

* Added support for Node 10

<a name="3.2.1"></a>

## [3.2.1](https://github.com/ionic-team/ionic-app-scripts/compare/v3.2.0...v3.2.1) (2018-11-26)

* Security release for dependencies for `node-sass`

<a name="3.2.0"></a>
# [3.2.0](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.11...v3.2.0) (2018-08-24)


### Bug Fixes

* **sass:** remove PostCSS warning ([#1364](https://github.com/ionic-team/ionic-app-scripts/issues/1364)) ([1e2035e](https://github.com/ionic-team/ionic-app-scripts/commit/1e2035e)), closes [#1359](https://github.com/ionic-team/ionic-app-scripts/issues/1359) [#13763](https://github.com/ionic-team/ionic-app-scripts/issues/13763)
* **serve:** use wss protocol for secure websocket when page is using https ([#1358](https://github.com/ionic-team/ionic-app-scripts/issues/1358)) ([29c3e23](https://github.com/ionic-team/ionic-app-scripts/commit/29c3e23))


### Features

* **environments:** configuration via process.env.VAR replacement ([#1471](https://github.com/ionic-team/ionic-app-scripts/issues/1471)) ([53fc341](https://github.com/ionic-team/ionic-app-scripts/commit/53fc341))



<a name="3.1.11"></a>
## [3.1.11](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.10...v3.1.11) (2018-07-12)


### Bug Fixes

* **serve:** fix EADDRINUSE issue with dev logger server ([271a6e1](https://github.com/ionic-team/ionic-app-scripts/commit/271a6e1))



<a name="3.1.10"></a>
## [3.1.10](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.9...v3.1.10) (2018-06-11)



<a name="3.1.9"></a>
## [3.1.9](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.8...v3.1.9) (2018-04-18)


### Bug Fixes

* **2889:** fix build error with --prod ([94e5f7c](https://github.com/ionic-team/ionic-app-scripts/commit/94e5f7c))
* **live-server:** update android platform path ([#1407](https://github.com/ionic-team/ionic-app-scripts/issues/1407)) ([1591c81](https://github.com/ionic-team/ionic-app-scripts/commit/1591c81))
* **serve:** start listening when watch is ready ([06bbd06](https://github.com/ionic-team/ionic-app-scripts/commit/06bbd06))



<a name="3.1.8"></a>
## [3.1.8](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.7...v3.1.8) (2018-01-18)

This release includes a bump in the version of node-sass. This adds support for node 9.


<a name="3.1.7"></a>
## [3.1.7](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.6...v3.1.7) (2017-12-27)


### Bug Fixes

* pin uglify-es ([dacf080](https://github.com/ionic-team/ionic-app-scripts/commit/dacf080)), closes [#1353](https://github.com/ionic-team/ionic-app-scripts/issues/1353)



<a name="3.1.6"></a>
## [3.1.6](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.5...v3.1.6) (2017-12-18)


### Bug Fixes

* pin ws version ([db0cc4d](https://github.com/ionic-team/ionic-app-scripts/commit/db0cc4d))



<a name="3.1.5"></a>
## [3.1.5](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.4...v3.1.5) (2017-12-07)


### Bug Fixes

* **dependencies:** update angular build optimizer for a source map fix ([a5df139](https://github.com/ionic-team/ionic-app-scripts/commit/a5df139))



<a name="3.1.4"></a>
## [3.1.4](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.3...v3.1.4) (2017-11-30)


### Bug Fixes

* **aot:** remove template validation until we can properly handle the error message format ([d7c7136](https://github.com/ionic-team/ionic-app-scripts/commit/d7c7136))



<a name="3.1.3"></a>
## [3.1.3](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.2...v3.1.3) (2017-11-29)


### Bug Fixes

* **aot:** fix error reporting with ng 5.0.1 or greater ([dece391](https://github.com/ionic-team/ionic-app-scripts/commit/dece391))



<a name="3.1.2"></a>
## [3.1.2](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.1...v3.1.2) (2017-11-13)


### Bug Fixes

* **webpack:** revert to 3.6.0 for faster builds ([2553ca6](https://github.com/ionic-team/ionic-app-scripts/commit/2553ca6))



<a name="3.1.1"></a>
## [3.1.1](https://github.com/ionic-team/ionic-app-scripts/compare/v3.1.0...v3.1.1) (2017-11-13)


### Bug Fixes

* **AoT:** properly check for ngmodule declaration errors from the AoT build ([a47f120](https://github.com/ionic-team/ionic-app-scripts/commit/a47f120))
* **template:** fix bug with using dollar sign within templates ([de09048](https://github.com/ionic-team/ionic-app-scripts/commit/de09048))



<a name="3.1.0"></a>
# [3.1.0](https://github.com/ionic-team/ionic-app-scripts/compare/v3.0.1...v3.1.0) (2017-11-08)

## Features

Supports Angular 5

### Bug Fixes

* **aot:** pass genDir to ng4 ([7506764](https://github.com/ionic-team/ionic-app-scripts/commit/7506764))
* **config:** only read ionic-angular package json for version info in apps, not in the Ionic repo itself ([700ca04](https://github.com/ionic-team/ionic-app-scripts/commit/700ca04))
* **deep-linking:** use .ts file extension for lazy loading in dev mode, and .js in AoT mode since the AoT compiler no longer emits an ngfactory.ts file ([dd99f14](https://github.com/ionic-team/ionic-app-scripts/commit/dd99f14))
* **live-server:** content.toString() crash ([#1288](https://github.com/ionic-team/ionic-app-scripts/issues/1288)) ([07e7e05](https://github.com/ionic-team/ionic-app-scripts/commit/07e7e05))
* **templates:** escape strings in template ([484d90d](https://github.com/ionic-team/ionic-app-scripts/commit/484d90d))


### Performance Improvements

* **uglifyjs:** remove unused `readFileAsync` during uglify ([#1305](https://github.com/ionic-team/ionic-app-scripts/issues/1305)) ([e9217c2](https://github.com/ionic-team/ionic-app-scripts/commit/e9217c2))



<a name="3.0.1"></a>
## [3.0.1](https://github.com/ionic-team/ionic-app-scripts/compare/v3.0.0...v3.0.1) (2017-10-20)


### Bug Fixes

* **cleancss:** update to latest version of clean-css to mitigate issue with purging some css that should not be purged ([564bd61](https://github.com/ionic-team/ionic-app-scripts/commit/564bd61))
* **deep-linking:** ensure hasExistingDeepLinkConfig returns true where there is a config referenced by a variable ([2e40340](https://github.com/ionic-team/ionic-app-scripts/commit/2e40340))
* **deep-linking:** ensure the deepLinkDir ends in path.sep ([496af40](https://github.com/ionic-team/ionic-app-scripts/commit/496af40))
* set context right immediately ([802b329](https://github.com/ionic-team/ionic-app-scripts/commit/802b329))
* **dev-server:** fix for --nolivereload flag to stop reloading ([#1200](https://github.com/ionic-team/ionic-app-scripts/issues/1200)) ([d62f5da](https://github.com/ionic-team/ionic-app-scripts/commit/d62f5da))
* **html:** limit regex to only applicable script tags for replacing content ([93db0ef](https://github.com/ionic-team/ionic-app-scripts/commit/93db0ef))
* **proxy:** add a cookieRewrite option which is passed to proxy-middleware. ([#1226](https://github.com/ionic-team/ionic-app-scripts/issues/1226))  ([771ee63](https://github.com/ionic-team/ionic-app-scripts/commit/771ee63))
* **source-maps:** fix race condition between copying and purging source maps ([f5529b5](https://github.com/ionic-team/ionic-app-scripts/commit/f5529b5))
* **webpack:** always use modules output from webpack to form default basis of where to look for sass files ([c199ea4](https://github.com/ionic-team/ionic-app-scripts/commit/c199ea4))



<a name="3.0.0"></a>
# [3.0.0](https://github.com/ionic-team/ionic-app-scripts/compare/v2.1.4...v3.0.0) (2017-09-28)

### Breaking Changes
The `webpack` config format changed from being a config that is exported to being a dictionary of configs. Basically, the default config now exports a `dev` and `prod` property with a config assigned to each. See an example of the change [here](https://github.com/ionic-team/ionic-app-scripts/blob/master/config/webpack.config.js#L143-L146). This change is setting the stage for adding multiple "environment" support for the next app-scripts release.

### New Features
This release adds support for `ngo`, the Angular team's build optimizer tool. `ngo` is enabled by default on `--prod` builds. In the event that `ngo` is not working for your app or something goes wrong, it can be disabled by running the following build command.

```
ionic cordova build ios --aot --minifyjs --minifycss --optimizejs
```

Using the `--aot` flag enables the `AoT Compiler`. `--minifyjs` and `--minifycss` minify the outputted code.

### Notes
Version `3.0.0` deprecated support for Rollup, Closure Compiler, and Babili. The support for these was poor and they were not used by many developers. `uglifyjs` was replaced with the newer `uglifyes`, which supports ES2015.

### Bug Fixes

* **aot:** normalize paths to fix path issues on windows ([b766037](https://github.com/ionic-team/ionic-app-scripts/commit/b766037))
* **build:** scan deeplink dir too if different from srcDir ([8929265](https://github.com/ionic-team/ionic-app-scripts/commit/8929265))
* **deep-linking:** convert deep linking to use TS Transform. DeepLinking now works on TypeScript src instead of on transpiled JS code ([63c4c7f](https://github.com/ionic-team/ionic-app-scripts/commit/63c4c7f))
* **deep-linking:** remove IonicPage import statement in transform/non-transform approachs to work better with strict TS settings ([84d9ec7](https://github.com/ionic-team/ionic-app-scripts/commit/84d9ec7))
* **devapp:** do not enable shake ([#1215](https://github.com/ionic-team/ionic-app-scripts/issues/1215)) ([118189c](https://github.com/ionic-team/ionic-app-scripts/commit/118189c))
* **generators:** correct pipes default folder name ([f0ea0da](https://github.com/ionic-team/ionic-app-scripts/commit/f0ea0da))
* **ngc:** don't replace deeplink config if an existing one exists ([eeed98b](https://github.com/ionic-team/ionic-app-scripts/commit/eeed98b))
* **optimization:** removing optimizations in preparation for ngo, updating to latest deps ([90eb8b3](https://github.com/ionic-team/ionic-app-scripts/commit/90eb8b3))
* **postprocess:** fix and add tests for the logic surrounding purging fonts ([0dd1b22](https://github.com/ionic-team/ionic-app-scripts/commit/0dd1b22))
* **sass:** include the platforms dir by default ([0da47cb](https://github.com/ionic-team/ionic-app-scripts/commit/0da47cb))
* **transpile:** check for existing deep link config before using generated one ([c51ac93](https://github.com/ionic-team/ionic-app-scripts/commit/c51ac93))
* **webpack:** when analyzing stats, factor in new shape of ModuleConcatenation info ([00cf038](https://github.com/ionic-team/ionic-app-scripts/commit/00cf038))



<a name="2.1.4"></a>
## [2.1.4](https://github.com/ionic-team/ionic-app-scripts/compare/v2.1.3...v2.1.4) (2017-08-16)


### Bug Fixes

* make --lab respect --nobrowser ([8db3be5](https://github.com/ionic-team/ionic-app-scripts/commit/8db3be5))
* **serve:** allow multiple arguments in console.log ([5c00970](https://github.com/ionic-team/ionic-app-scripts/commit/5c00970))
* **serve:** fix --consolelogs/--serverlogs usage with Cordova console plugin ([8e64407](https://github.com/ionic-team/ionic-app-scripts/commit/8e64407))
* **serve:** fix 'launchBrowser' of undefined ([8f71e35](https://github.com/ionic-team/ionic-app-scripts/commit/8f71e35))


### Features

* **sourcemaps:** copy for prod and dev ([a1ccc17](https://github.com/ionic-team/ionic-app-scripts/commit/a1ccc17))
* **sourcemaps:** preserve prod sourcemaps out of code dir ([ee3e41b](https://github.com/ionic-team/ionic-app-scripts/commit/ee3e41b))



<a name="2.1.3"></a>
## [2.1.3](https://github.com/ionic-team/ionic-app-scripts/compare/v2.1.2...v2.1.3) (2017-07-27)


### Bug Fixes

* **lab:** remove es6 features from lab ([41a1335](https://github.com/ionic-team/ionic-app-scripts/commit/41a1335))



<a name="2.1.2"></a>
## [2.1.2](https://github.com/ionic-team/ionic-app-scripts/compare/v2.1.1...v2.1.2) (2017-07-27)


### Bug Fixes

* **generators:** handle old cli ([6fd622c](https://github.com/ionic-team/ionic-app-scripts/commit/6fd622c))



<a name="2.1.1"></a>
## [2.1.1](https://github.com/ionic-team/ionic-app-scripts/compare/v2.1.0...v2.1.1) (2017-07-27)


### Bug Fixes

* **generator:** write file sync ([b0bcb05](https://github.com/ionic-team/ionic-app-scripts/commit/b0bcb05))
* **generators:** add exception for providers ([db9c793](https://github.com/ionic-team/ionic-app-scripts/commit/db9c793))


### Features

* **webpack:** update to latest webpack ([67907b6](https://github.com/ionic-team/ionic-app-scripts/commit/67907b6))



<a name="2.1.0"></a>
# [2.1.0](https://github.com/ionic-team/ionic-app-scripts/compare/v2.0.2...v2.1.0) (2017-07-25)


### Bug Fixes

* **generators:** handle no ngModule in tabs ([653d9f2](https://github.com/ionic-team/ionic-app-scripts/commit/653d9f2))


### Features

* **generators:** refactor generators ([beaf0d3](https://github.com/ionic-team/ionic-app-scripts/commit/beaf0d3))



<a name="2.0.2"></a>
## [2.0.2](https://github.com/ionic-team/ionic-app-scripts/compare/v2.0.1...v2.0.2) (2017-07-13)

## Upgrading
Make sure you follow the instructions below for upgrading from `1.x` to `2.x`. In the `2.0.2` release, we had to make a small change to the `optimization` config. If you override this config, please review the [change](https://github.com/ionic-team/ionic-app-scripts/commit/785e044) and update your config accordingly.

### Bug Fixes

* **sass:** fix potential null pointer, though it really should never happen ([427e556](https://github.com/ionic-team/ionic-app-scripts/commit/427e556))
* **webpack:** don't output deptree.js, this requires a minor tweak to the optimization config if you have it customized ([785e044](https://github.com/ionic-team/ionic-app-scripts/commit/785e044))
* **webpack:** upgrade to webpack 3.2.0 to fix some bugs within Webpack surrounding the ModuleConcatenationPlugin ([f85ade0](https://github.com/ionic-team/ionic-app-scripts/commit/f85ade0))



<a name="2.0.1"></a>
## [2.0.1](https://github.com/ionic-team/ionic-app-scripts/compare/v2.0.0...v2.0.1) (2017-07-11)

## Upgrading from 1.x

If you're upgrading directly from `1.3.12` or earlier, make sure you review the changelog for `2.0.0` and follow the [instructions here](https://github.com/ionic-team/ionic-app-scripts/releases/tag/v2.0.0). There were some very minor updates you'll need to make to your app.

If you're customizing the build process and have a dependency that utilized `webpack@2.x`, it may be best to add an explicit `devDependency` on `webpack@3.1.0` to the project's `package.json` file. There have been a couple reports of non-standard 3rd party dependencies causing trouble with the `webpack` version.

### Bug Fixes

* **generators:** no module by default ([#1096](https://github.com/ionic-team/ionic-app-scripts/issues/1096)) ([dfcaefa](https://github.com/ionic-team/ionic-app-scripts/commit/dfcaefa))
* **http-server:** revert change for path-based routing since it broke proxies ([065912e](https://github.com/ionic-team/ionic-app-scripts/commit/065912e))
* **sass:** use webpack/rollup modules for non-optimized build, use optimization data for prod/optimized buids ([0554201](https://github.com/ionic-team/ionic-app-scripts/commit/0554201))
* **serve:** fix cached file issue by only using the webpack module concat plugin for prod builds, make sure you update custom configs ([feea7fe](https://github.com/ionic-team/ionic-app-scripts/commit/feea7fe))
* **webpack:** webpack in-memory output file system was breaking some plugins ([574da39](https://github.com/ionic-team/ionic-app-scripts/commit/574da39))



<a name="2.0.0"></a>
# [2.0.0](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.12...v2.0.0) (2017-07-07)

### Breaking Changes

In order to speed up the bundling process, we have separated `node_modules` code into a new, generated file called `vendor.js`. This means that on every change, `ionic-angular`, `@angular`, etc won't need to be processed by `webpack` :tada:

This means that `src/index.html` must be modified to include a new vendor script tag `<script src="build/vendor.js"></script>`. This new script tag must be placed above the `main.js` script tag. For example,

```
...
<body>

  <!-- Ionic's root component and where the app will load -->
  <ion-app></ion-app>

  <script src="cordova.js"></script>

  <!-- The polyfills js is generated during the build process -->
  <script src="build/polyfills.js"></script>

  <!-- all code from node_modules directory is here -->
  <script src="build/vendor.js"></script>

  <!-- The bundle js is generated during the build process -->
  <script src="build/main.js"></script>

</body>
...
```

Another side effect of this change is if you are overriding the `webpack` configuration, you will want to update your custom configuration based on the [new default configuration](https://github.com/ionic-team/ionic-app-scripts/blob/master/config/webpack.config.js). The main changes to the config are adding the `ModuleConcatenationPlugin` for scope hoisting for significantly faster apps, and adding the common chunks plugin for the `vendor.js` bundle.

See commits [e14f819](https://github.com/ionic-team/ionic-app-scripts/commit/e14f819) and [141cb23](https://github.com/ionic-team/ionic-app-scripts/commit/141cb23) for the specifics of the `webpack.config.js` change.

### Bug Fixes

* **config:** updated polyname env variable to match convention and fix typo with it ([d64fcb1](https://github.com/ionic-team/ionic-app-scripts/commit/d64fcb1))
* **lint:** improve linting performance ([106d82c](https://github.com/ionic-team/ionic-app-scripts/commit/106d82c))
* **sass:** dont try to process invalid directories ([8af9430](https://github.com/ionic-team/ionic-app-scripts/commit/8af9430))
* **sass:** fix a bug when calling sass task in stand alone fashion ([54bf3f6](https://github.com/ionic-team/ionic-app-scripts/commit/54bf3f6))


### Features

* **dev-server:** add support for path-based routing ([2441591](https://github.com/ionic-team/ionic-app-scripts/commit/2441591))
* **webpack:** add scope hoisting to webpack, update sass to read scss files from disk ([e14f819](https://github.com/ionic-team/ionic-app-scripts/commit/e14f819))
* **webpack:** use a vendor bundle to minimize code that needs re-bundling and source map generation ([141cb23](https://github.com/ionic-team/ionic-app-scripts/commit/141cb23))
* **webpack:** webpack 3.1.0 holy speed upgrade! ([a3bde4a](https://github.com/ionic-team/ionic-app-scripts/commit/a3bde4a))



<a name="1.3.12"></a>
## [1.3.12](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.11...v1.3.12) (2017-06-29)

## Bug Fixes

* **dependencies:** Added `reflect-metadata` to the list of dependencies ([e6f8481](https://github.com/ionic-team/ionic-app-scripts/commit/e6f8481)


<a name="1.3.11"></a>
## [1.3.11](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.10...v1.3.11) (2017-06-28)

## Bug Fixes

* **dependencies:** Removed `peerDependencies`. ([90cd59d](https://github.com/ionic-team/ionic-app-scripts/commit/90cd59d))


<a name="1.3.10"></a>
## [1.3.10](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.9...v1.3.10) (2017-06-28)

## Notes

Ionic updated to npm 5 across the board, so please update to npm 5 to utilize our lock file when contributing.

### Bug Fixes

* **bonjour:** remove bonjour as its causing trouble for users on Windows without git ([e4b5c59](https://github.com/ionic-team/ionic-app-scripts/commit/e4b5c59))



<a name="1.3.9"></a>
## [1.3.9](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.8...v1.3.9) (2017-06-28)


### Features

* **lab:** first iteration of the new Ionic Lab design
* **scripts:** push npm build to arbitrary tag ([#1060](https://github.com/ionic-team/ionic-app-scripts/issues/1060)) ([4e93f60](https://github.com/ionic-team/ionic-app-scripts/commit/4e93f60))



<a name="1.3.8"></a>
## [1.3.8](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.7...v1.3.8) (2017-06-21)

### Bug Fixes

* **sass:** fixes issue with Node 8 and node-sass
* **bonjour:** updates dependency + better error handling ([#1040](https://github.com/ionic-team/ionic-app-scripts/issues/1040)) ([e2f73c7](https://github.com/ionic-team/ionic-app-scripts/commit/e2f73c7))
* **core:** use lower case attrs and not dash case ([0154791](https://github.com/ionic-team/ionic-app-scripts/commit/0154791))
* **diagnostics:** change direction to always be ltr ([#1004](https://github.com/ionic-team/ionic-app-scripts/issues/1004)) ([6d5ef3c](https://github.com/ionic-team/ionic-app-scripts/commit/6d5ef3c))
* **lab:** allow params to be passed to iframes ([dabfdd1](https://github.com/ionic-team/ionic-app-scripts/commit/dabfdd1))
* **sass:** fix .sass files not being watched ([#957](https://github.com/ionic-team/ionic-app-scripts/issues/957)) ([0803eca](https://github.com/ionic-team/ionic-app-scripts/commit/0803eca))
* **serve:** if a build error occurs, return config if non-fatal ([e5a4134](https://github.com/ionic-team/ionic-app-scripts/commit/e5a4134))



<a name="1.3.7"></a>
## [1.3.7](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.6...v1.3.7) (2017-05-04)


### Bug Fixes

* **config:** create new file cache if not defined, even on existing context object ([4359b3d](https://github.com/ionic-team/ionic-app-scripts/commit/4359b3d))
* **generators:** import paths correct on windows ([d778857](https://github.com/ionic-team/ionic-app-scripts/commit/d778857))
* **optimizations:** don't ever remove menu-types since it's not a side-effect in menu, it is used just for types ([d7a4d1e](https://github.com/ionic-team/ionic-app-scripts/commit/d7a4d1e))
* **optimizations:** fix multiple bugs (components not being purged, overlays not working from providers, etc) for manual tree shaking ([4b538c7](https://github.com/ionic-team/ionic-app-scripts/commit/4b538c7))
* **webpack:** fix issue where bundles output to build dir sub directo… ([#938](https://github.com/ionic-team/ionic-app-scripts/issues/938)) ([aaa9d3c](https://github.com/ionic-team/ionic-app-scripts/commit/aaa9d3c))


### Features

* **bonjour:** adds service auto-discovery ([c17e6df](https://github.com/ionic-team/ionic-app-scripts/commit/c17e6df))



<a name="1.3.6"></a>
## [1.3.6](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.5...v1.3.6) (2017-04-27)


### Bug Fixes

* **webpack:** fix issue PR introduced with lazy loaded modules and webpack throwing an invalid error ([fb8b69a](https://github.com/ionic-team/ionic-app-scripts/commit/fb8b69a))


### Features

* **optimization:** enable manual tree shaking by default ([1c57ee6](https://github.com/ionic-team/ionic-app-scripts/commit/1c57ee6))



<a name="1.3.5"></a>
## [1.3.5](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.4...v1.3.5) (2017-04-26)


### Bug Fixes

* **build:** fix `extends` in `ts-config.json` ([#910](https://github.com/ionic-team/ionic-app-scripts/issues/910)) ([0f01603](https://github.com/ionic-team/ionic-app-scripts/commit/0f01603))
* **deep-linking:** fix issue where deep link config ends up being null when full build is triggered via a change to a template file with the identical content ([68fc463](https://github.com/ionic-team/ionic-app-scripts/commit/68fc463))
* **serve:** Fix for browser not opening on linux, fixes [#425](https://github.com/ionic-team/ionic-app-scripts/issues/425) ([#909](https://github.com/ionic-team/ionic-app-scripts/issues/909)) ([77edbc6](https://github.com/ionic-team/ionic-app-scripts/commit/77edbc6))


### Features

* **sass:** add option to pass addition postcss plugins ([#369](https://github.com/ionic-team/ionic-app-scripts/issues/369)) ([be30a40](https://github.com/ionic-team/ionic-app-scripts/commit/be30a40))



<a name="1.3.4"></a>
## [1.3.4](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.3...v1.3.4) (2017-04-18)


### Bug Fixes

* **webpack:** make ionic-angular/util dir dynamic and use the environment variable of ionic angular ([d3346b3](https://github.com/ionic-team/ionic-app-scripts/commit/d3346b3))



<a name="1.3.3"></a>
## [1.3.3](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.2...v1.3.3) (2017-04-14)


### Bug Fixes

* **optimizations:** temporarily do not purge ctor params from any of angular ([212146c](https://github.com/ionic-team/ionic-app-scripts/commit/212146c))



<a name="1.3.2"></a>
## [1.3.2](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.1...v1.3.2) (2017-04-12)


### Bug Fixes

* **deep-linking:** fix bug with null deep link config when modifying the main NgModule file (app.module.ts) ([759bb4f](https://github.com/ionic-team/ionic-app-scripts/commit/759bb4f))
* **optimization:** don't purge ctorParams for angular core or angular platform browser ([9562181](https://github.com/ionic-team/ionic-app-scripts/commit/9562181))
* **uglifyjs:** only minify files processed by webpack or rollup ([30ecdd8](https://github.com/ionic-team/ionic-app-scripts/commit/30ecdd8))



<a name="1.3.1"></a>
## [1.3.1](https://github.com/ionic-team/ionic-app-scripts/compare/v1.3.0...v1.3.1) (2017-04-06)


### Bug Fixes

* **config:** revert change and once again transpile bundle by default. ([b558584](https://github.com/ionic-team/ionic-app-scripts/commit/b558584))
* **decorators:** don't remove third party transpiled (not static) decorators ([3a3259a](https://github.com/ionic-team/ionic-app-scripts/commit/3a3259a))
* **deep-linking:** don't force the main bundle to be re-built unless the deep link config changed ([02b8e97](https://github.com/ionic-team/ionic-app-scripts/commit/02b8e97))
* **errors:** better error msg reporting from worker threads ([d9d000a](https://github.com/ionic-team/ionic-app-scripts/commit/d9d000a))
* **uglifyjs:** better error msg reporting ([49c0afb](https://github.com/ionic-team/ionic-app-scripts/commit/49c0afb))



<a name="1.3.0"></a>
# [1.3.0](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.5...v1.3.0) (2017-04-05)


### Features

* **optimization:** purge decorators enabled by default ([b626e00](https://github.com/ionic-team/ionic-app-scripts/commit/b626e00))
* **optimizations:** purge transpiled decorators ([ba5e0cd](https://github.com/ionic-team/ionic-app-scripts/commit/ba5e0cd))



<a name="1.2.5"></a>
## [1.2.5](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.4...v1.2.5) (2017-03-31)


### Bug Fixes

* **webpack:** fixes bugs where some third party libs didn't load correctly ([e7559e5](https://github.com/ionic-team/ionic-app-scripts/commit/e7559e5))



<a name="1.2.4"></a>
## [1.2.4](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.3...v1.2.4) (2017-03-30)

### Refactor
* **deep-linking:** set default segment value to filename without extension([5a97ba5](https://github.com/ionic-team/ionic-app-scripts/commit/5a97ba5))

<a name="1.2.3"></a>
## [1.2.3](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.2...v1.2.3) (2017-03-29)


### Bug Fixes

* **deep-linking:** Deep linking fixes for Windows and non-unix paths

* **script:** linux only accepts one argument after shebang, so revert giving app-scripts more memory by default ([0999f23](https://github.com/ionic-team/ionic-app-scripts/commit/0999f23)), closes [#838](https://github.com/ionic-team/ionic-app-scripts/issues/838)



<a name="1.2.2"></a>
## [1.2.2](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.1...v1.2.2) (2017-03-27)


### Bug Fixes

* **generators:** use correct path and handle providers correctly ([e82d5ff](https://github.com/ionic-team/ionic-app-scripts/commit/e82d5ff))
* **rollup:** pass all config options to generate ([3502360](https://github.com/ionic-team/ionic-app-scripts/commit/3502360))



<a name="1.2.1"></a>
## [1.2.1](https://github.com/ionic-team/ionic-app-scripts/compare/v1.2.0...v1.2.1) (2017-03-26)


### Bug Fixes

* **deep-linking:** only attempt to inject deep-link config if there isn't an existing config and the ([507f1a8](https://github.com/ionic-team/ionic-app-scripts/commit/507f1a8))
* **rollup:** fix bug with not generating source-map correctly ([3b1fd16](https://github.com/ionic-team/ionic-app-scripts/commit/3b1fd16))



<a name="1.2.0"></a>
# [1.2.0](https://github.com/ionic-team/ionic-app-scripts/compare/v1.1.4...v1.2.0) (2017-03-24)


### Bug Fixes

* **deep-linking:** Fix issue with deep-linking when attempting to update a template and failing, resulting in a full build but not processing deep links ([6b158d3](https://github.com/ionic-team/ionic-app-scripts/commit/6b158d3))
* **optimization:** fix out of memory errors by providing more memory by default ([b4c287a](https://github.com/ionic-team/ionic-app-scripts/commit/b4c287a))
* **optimizations:** only store ionic and src files in memory ([f51314f](https://github.com/ionic-team/ionic-app-scripts/commit/f51314f))
* **uglify:** check for correct file extension ([d17f2e1](https://github.com/ionic-team/ionic-app-scripts/commit/d17f2e1))
* **uglify:** verify source maps are generated correctly for all bundles, tests ([fc44ca6](https://github.com/ionic-team/ionic-app-scripts/commit/fc44ca6))
* **utils:** assign correct type ([3c3666c](https://github.com/ionic-team/ionic-app-scripts/commit/3c3666c))
* **watch:** fixed bug where options.ignore was being ignored if it's an array ([7f1e54c](https://github.com/ionic-team/ionic-app-scripts/commit/7f1e54c))
* **watch:** queue builds ([06e4971](https://github.com/ionic-team/ionic-app-scripts/commit/06e4971))
* **watch:** queue buildUpdates events to avoid race conditions when bundling/building ([43caefa](https://github.com/ionic-team/ionic-app-scripts/commit/43caefa))
* **webpack:** don't overwrite css files when outputting webpack files ([a32649f](https://github.com/ionic-team/ionic-app-scripts/commit/a32649f))


### Features

* **serve:** change http-server to use request hostname instead of the configured hostname. ([8e1e81a](https://github.com/ionic-team/ionic-app-scripts/commit/8e1e81a))
* **deep-linking:** generate default NgModule when missing by default ([90138fa](https://github.com/ionic-team/ionic-app-scripts/commit/90138fa))
* **deep-linking:** parsing deeplink decorator is now enabled by default, no longer experimental ([e097d4e](https://github.com/ionic-team/ionic-app-scripts/commit/e097d4e))
* **deep-linking:** upgrade script to generate NgModules for pages with [@DeepLink](https://github.com/DeepLink) decorator ([2943188](https://github.com/ionic-team/ionic-app-scripts/commit/2943188))
* **generators:** generators for page, component, directive, pipe, provider ([e2a45e4](https://github.com/ionic-team/ionic-app-scripts/commit/e2a45e4))
* **minification:** code-split bundles will be minified ([#814](https://github.com/ionic-team/ionic-app-scripts/issues/814)) ([d8d9a4e](https://github.com/ionic-team/ionic-app-scripts/commit/d8d9a4e))



<a name="1.1.4"></a>
## [1.1.4](https://github.com/ionic-team/ionic-app-scripts/compare/v1.1.3...v1.1.4) (2017-02-23)


### Bug Fixes

* **optimizations:** comment out code instead of purge it so source-maps don't error out in some edge ([1dedc53](https://github.com/ionic-team/ionic-app-scripts/commit/1dedc53))
* **watch:** make default watch fail-to-start timeout configurable so it works more reliably on slow ([2e2a647](https://github.com/ionic-team/ionic-app-scripts/commit/2e2a647)), closes [#772](https://github.com/ionic-team/ionic-app-scripts/issues/772)



<a name="1.1.3"></a>
## [1.1.3](https://github.com/ionic-team/ionic-app-scripts/compare/v1.1.2...v1.1.3) (2017-02-17)


### Bug Fixes

* **config:** Setting readConfigJson constant wrong ([#761](https://github.com/ionic-team/ionic-app-scripts/issues/761)) ([64bc17f](https://github.com/ionic-team/ionic-app-scripts/commit/64bc17f))
* **source-maps:** source map must correspond to .js file name with a .map at the end ([debd88b](https://github.com/ionic-team/ionic-app-scripts/commit/debd88b))



<a name="1.1.2"></a>
## [1.1.2](https://github.com/ionic-team/ionic-app-scripts/compare/v1.1.1...v1.1.2) (2017-02-16)


### Bug Fixes

* **deep-links:** handle configs with internal arrays ([a7df816](https://github.com/ionic-team/ionic-app-scripts/commit/a7df816))
* **deep-links:** only provide deep links to webpack that contain the import used in code and the abs ([fae4862](https://github.com/ionic-team/ionic-app-scripts/commit/fae4862))
* **optimizations:** remove the js file created by the optimizations bundling pass ([c0bb3f4](https://github.com/ionic-team/ionic-app-scripts/commit/c0bb3f4))



<a name="1.1.1"></a>
## [1.1.1](https://github.com/ionic-team/ionic-app-scripts/compare/v1.1.0...v1.1.1) (2017-02-15)


### Bug Fixes

* **config:** node_modules directory should not be configurable (users were finding it confusing) ([1f58aaa](https://github.com/ionic-team/ionic-app-scripts/commit/1f58aaa))
* **copy:** support overriding config entries with empty objects ([5879a8b](https://github.com/ionic-team/ionic-app-scripts/commit/5879a8b))
* **deeplinks:** make deep link config parsing support 2.x and 3.x deep link config ([1ac7116](https://github.com/ionic-team/ionic-app-scripts/commit/1ac7116))
* **deeplinks:** provide deep-links config to webpack as needed vs via the constructor ([a735e96](https://github.com/ionic-team/ionic-app-scripts/commit/a735e96))
* **http-server:** drive reading ionic.config.json based on config value ([e2d0d83](https://github.com/ionic-team/ionic-app-scripts/commit/e2d0d83))
* **optimizations:** throw error when ionic-angular index file isn't found ([6437005](https://github.com/ionic-team/ionic-app-scripts/commit/6437005))
* **transpile:** get tsconfig.json location from config value ([79b0eeb](https://github.com/ionic-team/ionic-app-scripts/commit/79b0eeb))



<a name="1.1.0"></a>
# [1.1.0](https://github.com/ionic-team/ionic-app-scripts/compare/v1.0.1...v1.1.0) (2017-02-11)

### Optimizations
We are starting to introduce optimizations to improve the size of the `bundle` generated by the build process.

The first set of optimizations are behind flags:

`ionic_experimental_manual_treeshaking` will remove Ionic components and code that are not being used from the bundle.
`ionic_experimental_purge_decorators` helps tree shaking by removing unnecessary `decorator` metadata from AoT code.

Since these are experimental, we are looking for feedback on how the work. Please test them out and [let us know](https://github.com/ionic-team/ionic-app-scripts/issues) how it goes. See the instructions [here](https://github.com/ionic-team/ionic-app-scripts#custom-configuration).


### Features
* **fonts:** remove used fonts for cordova builds ([967f784](https://github.com/ionic-team/ionic-app-scripts/commit/967f784))

### Bug Fixes

* **build:** fix test if linting should trigger on file change ([#719](https://github.com/ionic-team/ionic-app-scripts/issues/719)) ([e13b857](https://github.com/ionic-team/ionic-app-scripts/commit/e13b857))
* **lint:** capture results of all linted files ([eb4314e](https://github.com/ionic-team/ionic-app-scripts/commit/eb4314e)), closes [#725](https://github.com/ionic-team/ionic-app-scripts/issues/725)
* **optimizations:** make optimizations work on windows and mac ([5fe21f3](https://github.com/ionic-team/ionic-app-scripts/commit/5fe21f3))
* **serve:** assign all ports dynamically ([#727](https://github.com/ionic-team/ionic-app-scripts/issues/727)) ([6b4115c](https://github.com/ionic-team/ionic-app-scripts/commit/6b4115c))
* **webpack:** fix bug with using [name] for output file name ([1128c9c](https://github.com/ionic-team/ionic-app-scripts/commit/1128c9c))






<a name="1.0.1"></a>
## [1.0.1](https://github.com/ionic-team/ionic-app-scripts/compare/v1.0.0...v1.0.1) (2017-02-07)

### Breaking Changes

This release was accidentally published with a breaking change for Deep Links. If you're using Deep Links, please don't upgrade to this version. We are in the process of changing the DeepLinks API slightly.

### Bug Fixes

* **angular:** support angular 2.3+ ngc api ([13e930a](https://github.com/ionic-team/ionic-app-scripts/commit/13e930a))
* **deep-linking:** works when there isn't a valid deep link config ([62f05fc](https://github.com/ionic-team/ionic-app-scripts/commit/62f05fc))
* **deep-links:** adjust paths for AoT ([4055d73](https://github.com/ionic-team/ionic-app-scripts/commit/4055d73))
* **sass:** output valid source maps, that chrome can parse ([#306](https://github.com/ionic-team/ionic-app-scripts/issues/306)) ([6589550](https://github.com/ionic-team/ionic-app-scripts/commit/6589550))
* **source-maps:** always generate source map, then purge them if not needed in postprocess step ([d26b44c](https://github.com/ionic-team/ionic-app-scripts/commit/d26b44c))


### Features

* **createWorker:** pass argv and config_argv to spawned processes ([#487](https://github.com/ionic-team/ionic-app-scripts/issues/487)) ([02dfff8](https://github.com/ionic-team/ionic-app-scripts/commit/02dfff8))
* **lint:** new option to have stand alone lint bail ([b3bb906](https://github.com/ionic-team/ionic-app-scripts/commit/b3bb906))



<a name="1.0.0"></a>
# [1.0.0](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.48...v1.0.0) (2017-01-06)


### Upgrade Instructions
Execute the following command from your ionic project. This installs a new peer dependency called `sw-toolbox` that is used to simplify implementing a service-worker.

```
npm install sw-toolbox --save --save-exact
```


### Bug Fixes

* **build:** check to ensure tsconfig contains sourcemaps true. ([e6bcf22](https://github.com/ionic-team/ionic-app-scripts/commit/e6bcf22))
* **config:** resolve any inputs that could be paths to absolute paths ([50876eb](https://github.com/ionic-team/ionic-app-scripts/commit/50876eb))
* **copy:** check for null object and src/dest ([eabd125](https://github.com/ionic-team/ionic-app-scripts/commit/eabd125))
* **ngc:** revert change to purge decorators (Angular CLI did too) ([8aae85c](https://github.com/ionic-team/ionic-app-scripts/commit/8aae85c))
* **webpack:** update environment plugin for webpack 2 RC3 ([be3aac1](https://github.com/ionic-team/ionic-app-scripts/commit/be3aac1))
* **websockets:** fix exception when no ws clients connected during rebuild ([#616](https://github.com/ionic-team/ionic-app-scripts/issues/616)) ([8685bf8](https://github.com/ionic-team/ionic-app-scripts/commit/8685bf8))



<a name="0.0.48"></a>
## [0.0.48](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.47...v0.0.48) (2016-12-19)

### Upgrade Instructions
`@ionic/app-scripts` version `0.0.47` had some breaking changes so please make sure you have performed those upgrade instructions.

### Bug Fixes

* **diagnostics:** fix null pointers ([72adc86](https://github.com/ionic-team/ionic-app-scripts/commit/72adc86))
* **inline-templates:** check for existence of content ([#557](https://github.com/ionic-team/ionic-app-scripts/issues/557)) ([b68e125](https://github.com/ionic-team/ionic-app-scripts/commit/b68e125))
* **logging:** don't log msgs about websocket state ([18185fb](https://github.com/ionic-team/ionic-app-scripts/commit/18185fb))
* **optimization:** stop removing decorators ([45b0255](https://github.com/ionic-team/ionic-app-scripts/commit/45b0255))
* **serve:** find an open port for the notification server if port is used. ([d6de413](https://github.com/ionic-team/ionic-app-scripts/commit/d6de413))
* **copy:** generate project context if it doesn't exist ([26f6db8](https://github.com/ionic-team/ionic-app-scripts/commit/26f6db8a7d3398b940cfb4c4b3eb4a6f141e1be7#diff-b477061dcc036b7490cfc73741747819))


### Features

* **sass:** enable Sass indented files compilation ([#565](https://github.com/ionic-team/ionic-app-scripts/issues/565)) ([f632298](https://github.com/ionic-team/ionic-app-scripts/commit/f632298))



<a name="0.0.47"></a>
## [0.0.47](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.46...v0.0.47) (2016-12-12)

### Upgrade Instructions

#### Install latest Ionic CLI
Install the latest ionic cli. `sudo` may be required depending upon your `npm` set-up.

```
npm install -g ionic@latest
```

#### Entry Point Changes
Delete `main.dev.ts` and `main.prod.ts` and create a `main.ts` file with the following content:

```
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);
```

#### Dev Builds By Default Changes
All builds are now development (non-AoT) builds by default. This allows for a better development experience when testing on a device. To get started, please follow the steps below.

Make sure the `scripts` section of `package.json` looks like this:

```
  "scripts": {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  }
```

`ionic run android --prod` will do a production build that utilizes AoT compiling and minifaction.
`ionic emulate ios --prod` will do a production build that utilizes AoT compiling and minifaction.
`ionic run android` will do a development build
`ionic emulate ios` will do a development build

If you wish to run AoT but disable minifaction, do the following
`ionic run android --aot`
`ionic emulate ios --aot`


#### Source Map Changes
Change `ionic_source_map` to `ionic_source_map_type` in package.json if it is overridden.

#### Config Changes
There were significant improvements/changes to most configs. Please review the changes and make sure any custom configs are up to date.

#### Validate TSConfig settings
Verify that `tsconfig.json` is up to date with recommended settings:

```
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "dom",
      "es2015"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ],
  "compileOnSave": false,
  "atom": {
    "rewriteTsconfig": false
  }
}
```


### Breaking Changes
1. `main.dev.ts` and `main.prod.ts` have been deprecated in favor of `main.ts` with the content of `main.dev.ts`. The content of `main.ts` will be optimized at build time for production builds.
2. Builds are now always development (non-AoT) by default. To enable `prod` builds, use the `--prod` option.
3. `copy.config` and `watch.config` have breaking changes moving to an easier-to-extend configuration style.
4. `copy.config` uses `node-glob` instead of `fs-extra` to do the copy. Migrate from directory/files to globs in any custom configs.
5. `ionic_source_map` configuration has been changed to `ionic_source_map_type`.
6. Source maps now use `source-map` devtool option by default instead of `eval`. Change `ionic_source_map_type` option to return to the faster building `eval`.

### Bug Fixes

* **AoT:** dynamically enable prod mode for AoT builds ([0594803](https://github.com/ionic-team/ionic-app-scripts/commit/0594803))
* **AoT:** use in-memory data store instead of .tmp directory for AoT codegen ([93106ff](https://github.com/ionic-team/ionic-app-scripts/commit/93106ff))
* **build:** every build should run clean sync and copy async. ([6d4eb6e](https://github.com/ionic-team/ionic-app-scripts/commit/6d4eb6e))
* **copy:** Resolve race condition in copy task, move to glob config ([cc99a73](https://github.com/ionic-team/ionic-app-scripts/commit/cc99a73))
* **lab:** add lab to files ([f42c980](https://github.com/ionic-team/ionic-app-scripts/commit/f42c980))
* **livereload:** livereload now correctly serves cordova plugins on run and emulate. ([a0c3f5d](https://github.com/ionic-team/ionic-app-scripts/commit/a0c3f5d))
* **livereload:** on project build all pages connected should reload. ([#513](https://github.com/ionic-team/ionic-app-scripts/issues/513)) ([62d6b23](https://github.com/ionic-team/ionic-app-scripts/commit/62d6b23))
* **livereload:** use localhost instead of 0.0.0.0 when injecting live reload script ([#450](https://github.com/ionic-team/ionic-app-scripts/issues/450)) ([7f8a0c3](https://github.com/ionic-team/ionic-app-scripts/commit/7f8a0c3))
* **logging:** remove unnecessary websocket error msg, clean up copy error msg ([1517b06](https://github.com/ionic-team/ionic-app-scripts/commit/1517b06))
* **ngc:** simpler AoT error reporting ([1b0f163](https://github.com/ionic-team/ionic-app-scripts/commit/1b0f163))
* **serve:** add flag to indicate to serve for a cordova app ([93782e7](https://github.com/ionic-team/ionic-app-scripts/commit/93782e7))
* **source-maps:** use detailed source-map as default, fix windows path issue ([19464b3](https://github.com/ionic-team/ionic-app-scripts/commit/19464b3))
* **workers:** generate context in worker threads ([af036ec](https://github.com/ionic-team/ionic-app-scripts/commit/af036ec))


### Features

* **build:** replace --dev flag with --prod and add flags --aot, --minifyJs, --minifyCss, --optimizeJs ([99922ce](https://github.com/ionic-team/ionic-app-scripts/commit/99922ce))
* **bundle:** pre and post bundle hooks ([4835550](https://github.com/ionic-team/ionic-app-scripts/commit/4835550))
* **copy:** update copy config to move web workers ([a909fc4](https://github.com/ionic-team/ionic-app-scripts/commit/a909fc4))
* **lab:** fresh coat of paint ([edb6f09](https://github.com/ionic-team/ionic-app-scripts/commit/edb6f09))
* **replacePathVars:** support interpolation of objects and arrays ([#449](https://github.com/ionic-team/ionic-app-scripts/issues/449)) ([e039d46](https://github.com/ionic-team/ionic-app-scripts/commit/e039d46))
* all arguments passed should be compared as case insensitive ([085c897](https://github.com/ionic-team/ionic-app-scripts/commit/085c897))



<a name="0.0.46"></a>
## [0.0.46](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.44...v0.0.46) (2016-11-21)


### Bug Fixes

* **build:** better support for saving multiple files at a time ([254bb6c](https://github.com/ionic-team/ionic-app-scripts/commit/254bb6c))
* **copy:** ionicons copied from ionicons ([69f89a8](https://github.com/ionic-team/ionic-app-scripts/commit/69f89a8))
* **errors:** skip HTTP errors ([5906167](https://github.com/ionic-team/ionic-app-scripts/commit/5906167))
* **proxies:** Wrong parameter in Logger.info, in setupProxies function causing proxies not to load ([#395](https://github.com/ionic-team/ionic-app-scripts/issues/395)) ([316b1de](https://github.com/ionic-team/ionic-app-scripts/commit/316b1de))
* **typescript:** lock typescript version to 2.0.x for now due to build error with 2.1.x ([ef7203b](https://github.com/ionic-team/ionic-app-scripts/commit/ef7203b))
* **webpack:** fix path resolution ([97c23f9](https://github.com/ionic-team/ionic-app-scripts/commit/97c23f9))
* **webpack:** reference json-loader to account for webpack breaking change ([d6fe709](https://github.com/ionic-team/ionic-app-scripts/commit/d6fe709))
* **webpack:** resolve modules to rootDir ([#365](https://github.com/ionic-team/ionic-app-scripts/issues/365)) ([64eb845](https://github.com/ionic-team/ionic-app-scripts/commit/64eb845))


### Features

* **options:** allow users to pass their own cleanCss Options ([#377](https://github.com/ionic-team/ionic-app-scripts/issues/377)) ([20df6d4](https://github.com/ionic-team/ionic-app-scripts/commit/20df6d4))


<a name="0.0.45"></a>
## [0.0.45](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.44...v0.0.45) (2016-11-17)


### Bug Fixes

* **errors:** runtime error immediately, selectable stack ([70f68da](https://github.com/ionic-team/ionic-app-scripts/commit/70f68da))
* **inline-templates:** update bundle and memory file representation on template change ([11a949d](https://github.com/ionic-team/ionic-app-scripts/commit/11a949d))
* **rollup:** invalidate cache on template change ([80c0eb6](https://github.com/ionic-team/ionic-app-scripts/commit/80c0eb6))
* **webpack:** invalidate cache by use of timestamps ([4d6bbd5](https://github.com/ionic-team/ionic-app-scripts/commit/4d6bbd5))


### Features

* **run-build-update:** handle linked npm modules ([#375](https://github.com/ionic-team/ionic-app-scripts/issues/375)) ([0f113c8](https://github.com/ionic-team/ionic-app-scripts/commit/0f113c8))
* **serve:** add '/ionic-lab' as an alias for the lab html file path. ([c319404](https://github.com/ionic-team/ionic-app-scripts/commit/c319404))



<a name="0.0.44"></a>
## [0.0.44](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.43...v0.0.44) (2016-11-15)


### Bug Fixes

* **debug:** cmd+shift+8 to show debug menu ([a26d729](https://github.com/ionic-team/ionic-app-scripts/commit/a26d729))
* **error:** (cmd/ctrl)+8 for debug menu ([89550af](https://github.com/ionic-team/ionic-app-scripts/commit/89550af))
* **error:** add header padding for cordova iOS ([5c4c547](https://github.com/ionic-team/ionic-app-scripts/commit/5c4c547))
* **error:** apply correct css for runtime error close ([81f1d75](https://github.com/ionic-team/ionic-app-scripts/commit/81f1d75))
* **error:** fix content scrolling ([3b82465](https://github.com/ionic-team/ionic-app-scripts/commit/3b82465))
* **error:** reload immediately after js/html update ([07f918e](https://github.com/ionic-team/ionic-app-scripts/commit/07f918e))
* **error:** safari css fixes ([7c2fb59](https://github.com/ionic-team/ionic-app-scripts/commit/7c2fb59))
* **serve:** correct paths so that --lab works ([1d99a98](https://github.com/ionic-team/ionic-app-scripts/commit/1d99a98))
* **serve:** open browser to localhost ([14275c7](https://github.com/ionic-team/ionic-app-scripts/commit/14275c7))
* **transpile:** normalize and resolve paths always for OS independence ([ca6c889](https://github.com/ionic-team/ionic-app-scripts/commit/ca6c889))
* **watch:** fallback for when chokidar watch ready/error don't fire (happens on windows when file is ([519cd7f](https://github.com/ionic-team/ionic-app-scripts/commit/519cd7f)), closes [#282](https://github.com/ionic-team/ionic-app-scripts/issues/282)
* **watch:** watch now ignores Mac OS meta data files ([02d0b8d](https://github.com/ionic-team/ionic-app-scripts/commit/02d0b8d)), closes [#331](https://github.com/ionic-team/ionic-app-scripts/issues/331)
* **webpack:** source maps link to original src for ide debugging ([39edd2e](https://github.com/ionic-team/ionic-app-scripts/commit/39edd2e))


### Features

* **debug:** debug menu options ([53d6e30](https://github.com/ionic-team/ionic-app-scripts/commit/53d6e30))
* **debug:** shake device to show debug menu ([770f4e3](https://github.com/ionic-team/ionic-app-scripts/commit/770f4e3))
* **error:** client runtime error reporting ([fc40b92](https://github.com/ionic-team/ionic-app-scripts/commit/fc40b92))
* **error:** syntax and error highlighting ([8836310](https://github.com/ionic-team/ionic-app-scripts/commit/8836310))



<a name="0.0.43"></a>
## [0.0.43](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.42...v0.0.43) (2016-11-10)


### Bug Fixes

* **rollup:** removing rollup metadata prefix for paths ([350a288](https://github.com/ionic-team/ionic-app-scripts/commit/350a288))
* **watch:** remove shorthand arg for watch ([0685c0b](https://github.com/ionic-team/ionic-app-scripts/commit/0685c0b)), closes [#290](https://github.com/ionic-team/ionic-app-scripts/issues/290)
* **webpack:** typo in import, close [#326](https://github.com/ionic-team/ionic-app-scripts/issues/326) ([#341](https://github.com/ionic-team/ionic-app-scripts/issues/341)) ([6b89fa2](https://github.com/ionic-team/ionic-app-scripts/commit/6b89fa2))



<a name="0.0.42"></a>
## [0.0.42](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.41...v0.0.42) (2016-11-09)

## Upgrade Steps
To use this version of `@ionic/app-scripts`, follow these steps to upgrade:

1. Install the latest version of the ionic cli

  ```
    npm install ionic@latest -g
  ```

  Note: sudo may be required depending on your workstation set-up

2. Update the project's `package.json` file's `script` section to look like this:

  ```
  ...
  "scripts" : {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  }
  ...
  ```

  Note: This is removing several deprecated Ionic scripts. If you have any of your own custom scripts, don't remove them.


3. Install the latest version of `@ionic/app-scripts`

  ```
  npm install @ionic/app-scripts@latest --save-dev
  ```

### Bug Fixes

* **bundling:** execute bundle updates if full bundle has completed at least once ([fbe56dc](https://github.com/ionic-team/ionic-app-scripts/commit/fbe56dc))
* **sass:** remove broken sass caching ([91faf0b](https://github.com/ionic-team/ionic-app-scripts/commit/91faf0b))


### Features

* **error:** use datauri for favicon build status ([892cf4a](https://github.com/ionic-team/ionic-app-scripts/commit/892cf4a))
* **errors:** overlay build errors during development ([87f7648](https://github.com/ionic-team/ionic-app-scripts/commit/87f7648))



<a name="0.0.41"></a>
## [0.0.41](https://github.com/ionic-team/ionic-app-scripts/compare/v0.0.40...v0.0.41) (2016-11-07)


### Bug Fixes

* **webpack:** use source-maps instead of eval for prod builds ([fdd86be](https://github.com/ionic-team/ionic-app-scripts/commit/fdd86be))



<a name="0.0.40"></a>
## 0.0.40 (2016-11-07)

### Breaking Changes

`ionic_source_map` variable is now used to drive the `devtool` (sourcemap) value for webpack. It now defaults to `eval` for faster builds. Set it to `source-map` for `typescript` sourcemaps.

### Bug Fixes
* **sourcemaps:** fix source maps for all files ([066de6d](https://github.com/ionic-team/ionic-app-scripts/commit/066de6d))
* **sourcemaps:** webpack .ts sourcemaps ([bfca1be](https://github.com/ionic-team/ionic-app-scripts/commit/bfca1be))
* **webpack:** modify config to use IONIC_APP_SCRIPTS_DIR variable ([2b7c606](https://github.com/ionic-team/ionic-app-scripts/commit/2b7c606))


### Features
* **events:** emit bundler events ([8d73da9](https://github.com/ionic-team/ionic-app-scripts/commit/8d73da9))
* **exports:** add templateUpdate and fullBuildUpdate ([a31897d](https://github.com/ionic-team/ionic-app-scripts/commit/a31897d))
* **webpack source maps:** make it easy to configure source map type ([03565b7](https://github.com/ionic-team/ionic-app-scripts/commit/03565b7))


### Performance Improvements

* **webpack:** speed up webpack build by not using file-system and watches ([23ad195](https://github.com/ionic-team/ionic-app-scripts/commit/23ad195))


# 0.0.39 (2016-10-31)
* Switch default bundler to Webpack

# 0.0.36 (2016-10-15)

* Fix handling multiple async template updates


# 0.0.35 (2016-10-15)

* Fix resolving index files correctly
* Fix template rebuilds for multiple templates in one file
* Fix ability to watchers to ignore paths


# 0.0.34 (2016-10-15)

* Fix silently failed bundles
* Fix template path resolving issues


# 0.0.33 (2016-10-14)

* Improve build times for template changes
* Fix bundle updates on template changes


# 0.0.32 (2016-10-14)

* Fix Windows entry path normalization


# 0.0.31 (2016-10-13)

* Add ability use multiple processor cores for various subtasks
* Use typescript `createProgram` to transpile entire app
* Add syntax highlighting and colors to typescript, sass and tslint errors
* Improved error messages for typescript errors
* `clean` task only cleans out the `www/build/` directory rather than all of `www/`
* Add task to copy `src/service-worker.js` to `www/service-worker.js`
* Add task to copy `src/manifest.json` to `www/manifest.json`


# 0.0.30 (2016-10-06)

* Fix JS source maps
* Fix template inlining


# 0.0.29 (2016-10-05)

* Addressed memory usage error
* Dev builds no longer use the `.tmp` directory
* Dev build entry files should be the source `main.dev.ts` file
* Custom rollup configs should remove the `ngTemplate()` plugin


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 Drifty Co

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
================================================
[![npm version](https://img.shields.io/npm/v/@ionic/app-scripts.svg)](https://www.npmjs.com/package/@ionic/app-scripts)
[![Circle CI](https://circleci.com/gh/ionic-team/ionic-app-scripts.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/ionic-team/ionic-app-scripts)

# DISCLAIMER: NO LONGER MAINTAINED
Oh, [hello there](https://media.giphy.com/media/8JTFsZmnTR1Rs1JFVP/giphy.gif)! Ionic App Scripts is a tool tied specifically to version 3.x of Ionic Framework. Since the release of version 4.0 of Ionic Framework, we are no longer using Ionic App Scripts for building in Ionic Framework. Version 3 of Ionic Framework is no longer actively maintained by us. For more information on which versions are active, see our [support policy](https://ionicframework.com/docs/reference/support#framework-maintenance-and-support-status).
Due to this, we are no longer maintaining Ionic App Scripts and we recommend developers update their apps to the latest framework release. This provides several new features, bug fixes, performance improvements, as well as up to date tooling for Ionic apps. For more details on how to upgrade, check out our [migration guide](https://ionicframework.com/docs/reference/migration).

# Ionic App Scripts

Helper scripts to get [Ionic apps](https://ionicframework.com/) up and running quickly (minus the config overload).

To get the latest `@ionic/app-scripts`, please run:

```
npm install @ionic/app-scripts@latest --save-dev
```

### Config Defaults

Out of the box, Ionic starters have been preconfigured with great defaults for building fast apps, including:

- Multi-core processing tasks in parallel for faster builds
- In-memory file transpiling and bundling
- Transpiling source code to ES5 JavaScript
- Ahead of Time (AoT) template compiling
- Just in Time (JiT) template compiling
- Template inlining for JiT builds
- Bundling modules for faster runtime execution
- Treeshaking unused components and dead-code removal
- Generating CSS from bundled component Sass files
- Autoprefixing vendor CSS prefixes
- Minifying JavaScript files
- Compressing CSS files
- Copying `src` static assets to `www`
- Linting source files
- Watching source files for live-reloading

Just the bullet list above is a little overwhelming, and each task requires quite a bit of development time just to get started. Ionic App Script's intention is to make it easier to complete common tasks so developers can focus on building their app, rather than building build scripts.

Note that the [Ionic Framework's](https://github.com/ionic-team/ionic) source is made up of modules and can be packaged by any bundler or build process. However, this project's goal is provide simple scripts to make building Ionic apps easier, while also allowing developers to further configure their build process.


### npm Scripts

Instead of depending on external task runners, Ionic App Scripts now prefers being executed from [npm scripts](https://docs.npmjs.com/misc/scripts). Ionic's npm scripts come preconfigured in the project's `package.json` file. For example, this is the default setup for npm scripts in each starter:

```
  "scripts": {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  },
```

To run the `build` script found in the `package.json` `scripts` property, execute:

```
npm run build
```

## Environments

You can use Node style `process.env.MY_VAR` syntax directly in your typescript
and when the application is bundled it'll be replaced with the following order of precedence:
* If the variable exists in the process environment it will be replaced with that value.
* If the variable is not defined in the process environment it will be read from a `.env.dev`
file for dev builds or `.env.prod` file for prod builds which are located in the root of the app
* If the variable is not defined in either place it will be `undefined`

In order to take advantage of this apps will need a `src/declarations.d.ts` file with the following declaration:
```typescript
declare var process: { env: { [key: string]: string | undefined; } };
```

*Note*: This declaration may conflict if `@types/node` is installed in your project. See [#3541](https://github.com/ionic-team/ionic-cli/issues/3541).

## Custom Configuration

In many cases, the defaults which Ionic provides cover most of the scenarios required by developers; however, Ionic App Scripts does provide multiple ways to configure and override the defaults for each of the various tasks. Note that Ionic will always apply its defaults for any property that was not provided by custom configuration.

[Default Config Files](https://github.com/ionic-team/ionic-app-scripts/tree/master/config)

### package.json Config

Ionic projects use the `package.json` file for configuration. There's a handy [config](https://docs.npmjs.com/misc/config#per-package-config-settings) property which can be used. Below is an example of setting a custom config file using the `config` property in a project's `package.json`.

```
  "config": {
    "ionic_cleancss": "./config/cleancss.config.js"
  },
```

### Command-line Flags

Remember how we're actually running `ionic-app-scripts` from the `scripts` property of a project's `package.json` file? Well we can also add command-line flags to each script, or make new scripts with these custom flags. For example:

```
  "scripts": {
    "build": "ionic-app-scripts build --webpack ./config/webpack.dev.config.js",
    "minify": "ionic-app-scripts minify --cleancss ./config/cleancss.config.js",
  },
```

The same command-line flags can be also applied to `npm run` commands too, such as:

```
npm run build --webpack ./config/webpack.dev.config.js
```


### Overriding Config Files

| Config File | package.json Config | Cmd-line Flag         |
|-------------|---------------------|-----------------------|
| CleanCss    | `ionic_cleancss`    | `--cleancss` or `-e`  |
| Copy        | `ionic_copy`        | `--copy` or `-y`      |
| Generator   | `ionic_generator`   | `--generator` or `-g` |
| NGC         | `ionic_ngc`         | `--ngc` or `-n`       |
| Sass        | `ionic_sass`        | `--sass` or `-s`      |
| TSLint      | `ionic_tslint`      | `--tslint` or `-i`    |
| UglifyJS    | `ionic_uglifyjs`    | `--uglifyjs` or `-u`  |
| Watch       | `ionic_watch`       | `--watch`             |
| Webpack     | `ionic_webpack`     | `--webpack` or `-w`   |


### Overriding Config Values

| Config Values   | package.json Config | Cmd-line Flag | Defaults        | Details        |
|-----------------|---------------------|---------------|-----------------|----------------|
| root directory  | `ionic_root_dir`    | `--rootDir`   | `process.cwd()` | The directory path of the Ionic app |
| src directory   | `ionic_src_dir`     | `--srcDir`    | `src`           | The directory holding the Ionic src code |
| www directory   | `ionic_www_dir`     | `--wwwDir`    | `www`           | The deployable directory containing everything needed to run the app |
| build directory | `ionic_build_dir`   | `--buildDir`  | `build`         | The build process uses this directory to store generated files, etc |
| temp directory   | `ionic_tmp_dir`     | `--tmpDir`    | `.tmp`           | Temporary directory for writing files for debugging and various build tasks |
| ionic-angular directory | `ionic_angular_dir` | `--ionicAngularDir` | `ionic-angular` | ionic-angular directory |
| ionic-angular entry point | `ionic_angular_entry_point` | `--ionicAngularEntryPoint` | `index.js` | entry point file for ionic-angular |
| source map type | `ionic_source_map_type`  | `--sourceMapType` | `source-map` | Chooses the webpack `devtool` option. `eval` and `source-map` are supported |
| generate source map | `ionic_generate_source_map`  | `--generateSourceMap` | `true` | Determines whether to generate a source map or not |
| tsconfig path | `ionic_ts_config`  | `--tsconfig` | `{{rootDir}}/tsconfig.json` | absolute path to tsconfig.json |
| app entry point | `ionic_app_entry_point`  | `--appEntryPoint` | `{{srcDir}}/app/main.ts` | absolute path to app's entrypoint bootstrap file |
| app ng module path | `ionic_app_ng_module_path`  | `--appNgModulePath` | `{{srcDir}}/app/app.module.ts` | absolute path to app's primary `NgModule` |
| app ng module class | `ionic_app_ng_module_class`  | `--appNgModuleClass` | `AppModule` | Exported class name for app's primary `NgModule` |
| clean before copy | `ionic_clean_before_copy`  | `--cleanBeforeCopy` | `false` | clean out existing files before copy task runs |
| output js file | `ionic_output_js_file_name`  | `--outputJsFileName` | `main.js` | name of js file generated in `buildDir` |
| output css file | `ionic_output_css_file_name`  | `--outputCssFileName` | `main.css` | name of css file generated in `buildDir` |
| bail on lint error | `ionic_bail_on_lint_error`  | `--bailOnLintError` | `null` | Set to `true` to make stand-alone lint commands fail with non-zero status code |
| enable type checking during lint | `ionic_type_check_on_lint`  | `--typeCheckOnLint` | `null` | Set to `true` to enable [type checking](https://palantir.github.io/tslint/usage/type-checking) during lint |
| write AoT files to disk | `ionic_aot_write_to_disk` | `--aotWriteToDisk` | `null` | Set to `true` to write files to disk for debugging |
| print webpack dependency tree | `ionic_print_webpack_dependency_tree` | `--printWebpackDependencyTree` | `null` | Set to `true` to print out a dependency tree after running Webpack |
| parse deeplink config | `ionic_parse_deeplinks` | `--parseDeepLinks` | `true` | Parses and extracts data from the `@IonicPage` decorator |
| convert bundle to ES5 | `ionic_build_to_es5` | `--buildToEs5` | `true` | Convert bundle to ES5 for production deployments |
| default watch timeout | `ionic_start_watch_timeout` | `--startWatchTimeout` | `3000` | Milliseconds controlling the default watch timeout |
| choose the polyfill  | `ionic_polyfill_name` | `--polyfillName` | `polyfills` | Change with polyfills.modern or polyfills.ng (all options)[https://github.com/driftyco/ionic/tree/master/scripts/polyfill] |
| enable linting | `ionic_enable_lint` | `--enableLint` | `true` | Set to `false` for skipping the linting after the build |





### Ionic Environment Variables

These environment variables are automatically set to [Node's `process.env`](https://nodejs.org/api/process.html#process_process_env) property. These variables can be useful from within custom configuration files, such as custom `webpack.config.js` file.

| Environment Variable       | Description                                                          |
|----------------------------|----------------------------------------------------------------------|
| `IONIC_ENV`                | Value can be either `prod` or `dev`.                                 |
| `IONIC_ROOT_DIR`           | The absolute path to the project's root directory.                   |
| `IONIC_SRC_DIR`            | The absolute path to the app's source directory.                     |
| `IONIC_WWW_DIR`            | The absolute path to the app's public distribution directory.        |
| `IONIC_BUILD_DIR`          | The absolute path to the app's bundled js and css files.             |
| `IONIC_TMP_DIR`            | Temp directory for debugging generated/optimized code and various build tasks |
| `IONIC_NODE_MODULES_DIR`   | The absolute path to the `node_modules` directory.                   |
| `IONIC_ANGULAR_DIR`        | The absolute path to the `ionic-angular` node_module directory.      |
| `IONIC_APP_SCRIPTS_DIR`    | The absolute path to the `@ionic/app-scripts` node_module directory. |
| `IONIC_SOURCE_MAP_TYPE`    | The Webpack `devtool` setting. `eval` and `source-map` are supported.|
| `IONIC_GENERATE_SOURCE_MAP`| Determines whether to generate a sourcemap or not.                   |
| `IONIC_TS_CONFIG`          | The absolute path to the project's `tsconfig.json` file              |
| `IONIC_APP_ENTRY_POINT`    | The absolute path to the project's `main.ts` entry point file        |
| `IONIC_APP_NG_MODULE_PATH` | The absolute path to app's primary `NgModule`                        |
| `IONIC_APP_NG_MODULE_CLASS`    | The exported class name for app's primary `NgModule`             |
| `IONIC_GLOB_UTIL`          | The path to Ionic's `glob-util` script. Used within configs.         |
| `IONIC_CLEAN_BEFORE_COPY`  | Attempt to clean existing directories before copying files.          |
| `IONIC_CLOSURE_JAR`        | The absolute path ot the closure compiler jar file                   |
| `IONIC_OUTPUT_JS_FILE_NAME` | The file name of the generated javascript file                      |
| `IONIC_OUTPUT_CSS_FILE_NAME` | The file name of the generated css file                            |
| `IONIC_WEBPACK_FACTORY`    | The absolute path to Ionic's `webpack-factory` script                |
| `IONIC_WEBPACK_LOADER`     | The absolute path to Ionic's custom webpack loader                   |
| `IONIC_BAIL_ON_LINT_ERROR`     | Boolean determining whether to exit with a non-zero status code on error |
| `IONIC_TYPE_CHECK_ON_LINT` | Boolean determining whether to type check code during lint or not |
| `IONIC_AOT_WRITE_TO_DISK` | `--aotWriteToDisk` | `null` | Set to `true` to write files to disk for debugging |
| `IONIC_PRINT_WEBPACK_DEPENDENCY_TREE` | boolean to print out a dependency tree after running Webpack |
| `IONIC_PARSE_DEEPLINKS` | boolean to enable parsing the Ionic 3.x deep links API for lazy loading |
| `IONIC_BUILD_TO_ES5` | boolean to enable converting bundle to ES5 for production deployments |
| `IONIC_START_WATCH_TIMEOUT` | Milliseconds controlling the default watch timeout |


The `process.env.IONIC_ENV` environment variable can be used to test whether it is a `prod` or `dev` build, which automatically gets set by any command. By default the `build` and `serve` tasks produce `dev` builds (a build that does not include Ahead of Time (AoT) compilation or minification). To force a `prod` build you should use the `--prod` command line flag.

`process.env.IONIC_ENV` environment variable is set to `prod` for `--prod` builds, otherwise `dev` for all other builds.


## All Available Tasks

These tasks are available within `ionic-app-scripts` and can be added to npm scripts or any Node command.

| Task       | Description                                                                                         |
|------------|-----------------------------------------------------------------------------------------------------|
| `build`    | A complete build of the application. It uses `development` settings by default. Use `--prod` to create an optimized build |
| `clean`    | Empty the `www/build` directory.                                                                          |
| `cleancss` | Compress the output CSS with [CleanCss](https://github.com/jakubpawlowicz/clean-css)                |
| `copy`     | Run the copy tasks, which by defaults copies the `src/assets/` and `src/index.html` files to `www`. |
| `lint`     | Run the linter against the source `.ts` files, using the `tslint.json` config file at the root.     |
| `minify`   | Minifies the output JS bundle and compresses the compiled CSS.                                      |
| `sass`     | Sass compilation of used modules. Bundling must have at least ran once before Sass compilation.     |
| `watch`    | Runs watch for dev builds.                                                                          |

Example NPM Script:

```
  "scripts": {
    "minify": "ionic-app-scripts minify"
  },
```

## Tips
1. The Webpack `devtool` setting is driven by the `ionic_source_map_type` variable. It defaults to `source-map` for the best quality source map. Developers can enable significantly faster builds by setting `ionic_source_map_type` to `eval`.
2. By default, the `lint` command does not exit with a non-zero status code on error. To enable this, pass `--bailOnLintError true` to the command.

```
"scripts" : {
  ...
  "lint": "ionic-app-scripts lint"
  ...
}
```

```
npm run lint --bailOnLintError true
```

## The Stack

- [Ionic Framework](https://ionicframework.com/)
- [TypeScript Compiler](https://www.typescriptlang.org/)
- [Angular Compiler (NGC)](https://github.com/angular/angular/tree/master/modules/%40angular/compiler-cli)
- [Webpack Module Bundler](https://webpack.js.org/)
- Ionic Component Sass
- [Node Sass](https://www.npmjs.com/package/node-sass)
- [Autoprefixer](https://github.com/postcss/autoprefixer)
- [UglifyJS](https://lisperator.net/uglifyjs/)
- [CleanCss](https://github.com/jakubpawlowicz/clean-css)
- [TSLint](https://palantir.github.io/tslint/)

## Contributing

We welcome any PRs, issues, and feedback! Please be respectful and follow the [Code of Conduct](https://github.com/ionic-team/ionic/blob/master/CODE_OF_CONDUCT.md).

We use Node 6, and NPM 5 for contributing.

### Publish a Nightly Build

1. Run `npm run build` to generate the `dist` directory
2. Run `npm run test` to validate the `dist` works
3. Tick the `package.json` version
4. Run `npm run nightly` to generate a nightly build on npm



### Publish a release

Execute the following steps to publish a release:

1. Ensure your branch has been merged into `master`
2. Run `npm run build` to generate the `dist` directory
3. Run `npm run test` to validate the `dist` works
4. Temporarily tick the `package.json` version
5. Run `npm run changelog` to append the latest additions to the changelog
6. Manually verify and commit the changelog changes. Often times you'll want to manually add content/instructions
7. Revert the `package.json` version to the original version
8. Run `npm version patch` to tick the version and generate a git tag
9. Run `npm run github-release` to create the github release entry
10. Run `npm publish` to publish the package to npm
11. `git push origin master` - push changes to master

================================================
FILE: bin/ion-dev.js
================================================
window.IonicDevServerConfig = window.IonicDevServerConfig || {};

window.IonicDevServer = {
  start: function() {
    this.msgQueue = [];

    this.consoleLog = console.log;
    this.consoleError = console.error;
    this.consoleWarn = console.warn;

    IonicDevServerConfig.systemInfo.push('Navigator Platform: ' + window.navigator.platform);
    IonicDevServerConfig.systemInfo.push('User Agent: ' + window.navigator.userAgent);

    if (IonicDevServerConfig.sendConsoleLogs) {
      this.patchConsole();
    }

    this.openConnection();
    this.bindEvents();

    var self = this;
    document.addEventListener("DOMContentLoaded", function() {
      var diagnosticsEle = document.getElementById('ion-diagnostics');
      if (diagnosticsEle) {
        self.buildStatus('error');
      } else {
        self.buildStatus('success');
      }
    });

    if (window.cordova && document.documentElement) {
      document.documentElement.classList.add('ion-diagnostics-cordova');

      var ua = window.navigator.userAgent.toLowerCase();
      if ((ua.indexOf('ipad') > -1 || ua.indexOf('iphone') > -1 || ua.indexOf('ipod') > -1) && ua.indexOf('windows phone') === -1) {
        document.documentElement.classList.add('ion-diagnostics-cordova-ios');
      }
    }

    window.onerror = function(msg, url, lineNo, columnNo, error) {
      self.handleError(error);
    };
  },

  handleError: function(err) {
    if (!err) return;

    // Ignore HTTP errors
    if(err.url || err.headers) return;

    // Socket is ready so send this error to the server for prettifying
    if (this.socketReady) {
      var msg = {
        category: 'runtimeError',
        type: 'runtimeError',
        data: {
          message: err.message ? err.message.toString() : null,
          stack: err.stack ? err.stack.toString() : null
        }
      };
      this.queueMessageSend(msg);

    } else {
      var c = [];

      c.push('<div class="ion-diagnostics-header">');
      c.push(' <div class="ion-diagnostics-header-content">');
      c.push('  <div class="ion-diagnostics-header-inner">Error</div>');
      c.push('  <div class="ion-diagnostics-buttons">');
      c.push('   <button id="ion-diagnostic-close">Close</button>');
      c.push('  </div>');
      c.push(' </div>');
      c.push('</div>');

      c.push('<div class="ion-diagnostics-content">');
      c.push(' <div class="ion-diagnostic">');
      c.push('  <div class="ion-diagnostic-masthead">');
      c.push('   <div class="ion-diagnostic-header">Runtime Error</div>');
      c.push('   <div class="ion-diagnostic-message">' + this.escapeHtml(err.message) + '</div>');
      c.push('  </div>');
      c.push('  <div class="ion-diagnostic-stack-header">Stack</div>');
      c.push('  <div class="ion-diagnostic-stack">' + this.escapeHtml(err.stack) + '</div>');
      c.push(' </div>');
      c.push('</div>');

      this.buildUpdate({
        type: 'clientError',
        data: {
          diagnosticsHtml: c.join('')
        }
      });
    }
  },

  reloadApp: function() {
    window.location.reload(true);
  },

  openConnection: function() {
    var self = this;
    var socketProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    this.socket = new WebSocket(socketProtocol + '//' + window.location.hostname + ':' + IonicDevServerConfig.wsPort);

    this.socket.onopen = function(ev) {
      self.socketReady = true;

      self.socket.onmessage = function(ev) {
        try {
          var msg = JSON.parse(ev.data);
          switch (msg.category) {
            case 'buildUpdate':
              self.buildUpdate(msg);
              break;
          }
        } catch (e) {
          self.consoleError('error receiving ws message', e);
        }
      };

      self.socket.onclose = function() {
        self.consoleLog('Dev server logger closed');
        self.socketReady = false;
      };

      self.drainMessageQueue();
    };
  },

  queueMessageSend: function(msg) {
    this.msgQueue.push(msg);
    this.drainMessageQueue();
  },

  drainMessageQueue: function() {
    if (this.socketReady) {
      var msg;
      while (msg = this.msgQueue.shift()) {
        try {
          this.socket.send(JSON.stringify(msg));
        } catch(e) {
          if (e instanceof TypeError) {

          } else {
            this.consoleError('ws error: ' + e);
          }
        }
      }
    }
  },

  patchConsole: function() {
    var self = this;
    function patchConsole(consoleType) {
      console[consoleType] = (function() {
        var orgConsole = console[consoleType];
        return function() {
          orgConsole.apply(console, arguments);
          var msg = {
            category: 'console',
            type: consoleType,
            data: []
          };
          for (var i = 0; i < arguments.length; i++) {
            msg.data.push(arguments[i]);
          }
          if (msg.data.length) {
            self.queueMessageSend(msg);
          }
        };
      })();
    }

    // https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-console/#supported-methods
    var consoleFns = ['log', 'error', 'exception', 'warn', 'info', 'debug', 'assert', 'dir', 'dirxml', 'time', 'timeEnd', 'table'];
    for (var i in consoleFns) {
      patchConsole(consoleFns[i]);
    }
  },

  /**
   * Process a build update message and display something to the friendly user.
   */
  buildUpdate: function(msg) {
    var status = 'success';

    if (msg.type === 'started') {
      status = 'active';
      this.buildingNotification(true);

    } else {

      if (msg.data.reloadApp) {
        this.reloadApp();
        return;
      }

      status = msg.data.diagnosticsHtml ? 'error' : 'success';

      this.buildingNotification(false);

      var diagnosticsEle = document.getElementById('ion-diagnostics');

      // If we have an element but no html created yet
      if (diagnosticsEle && !msg.data.diagnosticsHtml) {
        diagnosticsEle.classList.add('ion-diagnostics-fade-out');

        this.diagnosticsTimerId = setTimeout(function() {
          var diagnosticsEle = document.getElementById('ion-diagnostics');
          if (diagnosticsEle) {
            diagnosticsEle.parentElement.removeChild(diagnosticsEle);
          }
        }, 100);

      } else if (msg.data.diagnosticsHtml) {

        // We don't have an element but we have diagnostics HTML, so create the error

        if (!diagnosticsEle) {
          diagnosticsEle = document.createElement('div');
          diagnosticsEle.id = 'ion-diagnostics';
          diagnosticsEle.className = 'ion-diagnostics-fade-out';
          document.body.insertBefore(diagnosticsEle, document.body.firstChild);
        }

        // Show the last error
        clearTimeout(this.diagnosticsTimerId);
        this.diagnosticsTimerId = setTimeout(function() {
          var diagnosticsEle = document.getElementById('ion-diagnostics');
          if (diagnosticsEle) {
            diagnosticsEle.classList.remove('ion-diagnostics-fade-out');
          }
        }, 24);

        diagnosticsEle.innerHTML = msg.data.diagnosticsHtml
      }
    }

    this.buildStatus(status);
  },

  buildStatus: function (status) {
    var iconLinks = document.querySelectorAll('link[rel="icon"]');
    for (var i = 0; i < iconLinks.length; i++) {
      iconLinks[i].parentElement.removeChild(iconLinks[i]);
    }

    var iconLink = document.createElement('link');
    iconLink.rel = 'icon';
    iconLink.type = 'image/png';
    iconLink.href = this[status + 'Icon'];
    document.head.appendChild(iconLink);

    if (status === 'error') {
      var diagnosticsEle = document.getElementById('ion-diagnostics');
      if (diagnosticsEle) {
        var systemInfoEle = diagnosticsEle.querySelector('#ion-diagnostics-system-info');
        if (!systemInfoEle) {
          systemInfoEle = document.createElement('div');
          systemInfoEle.id = 'ion-diagnostics-system-info';
          systemInfoEle.innerHTML = IonicDevServerConfig.systemInfo.join('\n');
          diagnosticsEle.querySelector('.ion-diagnostics-content').appendChild(systemInfoEle);
        }
      }
    }
  },

  buildingNotification: function(showToast) {
    clearTimeout(this.toastTimerId);

    var toastEle = document.getElementById('ion-diagnostics-toast');

    if (showToast) {
      if (!toastEle) {
        toastEle = document.createElement('div');
        toastEle.id = 'ion-diagnostics-toast';
        var c = []
        c.push('<div class="ion-diagnostics-toast-content">');
        c.push(' <div class="ion-diagnostics-toast-message">Building...</div>');
        c.push(' <div class="ion-diagnostics-toast-spinner">');
        c.push('  <svg viewBox="0 0 64 64"><circle transform="translate(32,32)" r="26"></circle></svg>');
        c.push(' </div>');
        c.push('</div>');
        toastEle.innerHTML = c.join('');
        document.body.insertBefore(toastEle, document.body.firstChild);
      }

      this.toastTimerId = setTimeout(function() {
        var toastEle = document.getElementById('ion-diagnostics-toast');
        if (toastEle) {
          toastEle.classList.add('ion-diagnostics-toast-active');
        }
      }, 16);

    } else if (!showToast && toastEle) {
      toastEle.classList.remove('ion-diagnostics-toast-active');
    }
  },

  toggleOptionsMenu: function() {
    var optsEle = document.getElementById('ion-diagnostics-options');
    this.optionsMenu(!optsEle);
  },

  optionsMenu: function(showMenu) {
    clearTimeout(this.optionsMenuTimerId);

    var optsEle = document.getElementById('ion-diagnostics-options');
    if (showMenu) {

      if (!optsEle) {
        var c = [];

        c.push('<div id="ion-diagnostics-backdrop"></div>');
        c.push('<div class="ion-diagnostics-sheet-wrapper">');
        c.push(  '<div class="ion-diagnostics-sheet-container">');
        c.push(    '<div class="ion-diagnostics-sheet-group">');
        c.push(      '<div class="ion-diagnostics-sheet-title">Ionic App Debugger</div>');
        c.push(      '<button id="ion-diagnostics-options-reload-app" class="ion-diagnostics-sheet-button">Reload App</button>');
        c.push(    '</div>');
        c.push(    '<div class="ion-diagnostics-sheet-group">');
        c.push(      '<button id="ion-diagnostics-options-close" class="ion-diagnostics-sheet-button">Close Menu</button>');
        c.push(    '</div>');
        c.push(  '</div>');
        c.push('</div>');

        optsEle = document.createElement('div');
        optsEle.id = 'ion-diagnostics-options';
        optsEle.innerHTML = c.join('\n');
        document.body.insertBefore(optsEle, document.body.firstChild);
      }
      this.optionsMenuTimerId = setTimeout(function() {
        var optsEle = document.getElementById('ion-diagnostics-options');
        optsEle.classList.add('ion-diagnostics-options-show');
      }, 16);

    } else if (!showMenu && optsEle) {
      optsEle.classList.remove('ion-diagnostics-options-show');

      this.optionsMenuTimerId = setTimeout(function() {
        optsEle.parentElement.removeChild(optsEle);
      }, 300);

    }
  },

  bindEvents: function() {
    var self = this;

    document.addEventListener('keyup', function(ev) {
      var key = ev.keyCode || ev.charCode;

      if (key == 27) {
        // escape key
        self.optionsMenu(false);
      }
    });

    document.addEventListener('keydown', function(ev) {
      var key = ev.keyCode || ev.charCode;

      if ((ev.metaKey || ev.ctrlKey) && ev.shiftKey && key == 56) {
        // mac: command + shift + 8
        // win: ctrl + shift + 8
        self.toggleOptionsMenu();
      }
    });

    document.addEventListener('click', function(ev) {
      if (!ev.target) return;

      switch (ev.target.id) {
        case 'ion-diagnostic-close':
          self.buildUpdate({
            type: 'closeDiagnostics',
            data: {
              diagnosticsHtml: null
            }
          });
          break;

        case 'ion-diagnostics-options-reload-app':
          self.reloadApp();
          break;

        case 'ion-diagnostics-backdrop':
          self.optionsMenu(false);
          break;

        case 'ion-diagnostics-options-close':
          self.optionsMenu(false);
          break;
      }
    });

    if (location.href.indexOf('devapp=true') < 0) {
      this.enableShake();
    }
  },

  enableShake: function() {
    /*
    * Author: Alex Gibson
    * https://github.com/alexgibson/shake.js
    * License: MIT license
    */
    var self = this;
    var threshold = 15;
    var timeout = 1000;

    self.shakeTime = new Date();
    self.shakeX = null;
    self.shakeY = null;
    self.shakeZ = null;

    window.addEventListener('devicemotion', function(ev) {
      var current = ev.accelerationIncludingGravity;
      var currentTime;
      var timeDifference;
      var deltaX = 0;
      var deltaY = 0;
      var deltaZ = 0;

      if (self.shakeX === null) {
        self.shakeX = current.x;
        self.shakeY = current.y;
        self.shakeZ = current.z;
        return;
      }

      deltaX = Math.abs(self.shakeX - current.x);
      deltaY = Math.abs(self.shakeY - current.y);
      deltaZ = Math.abs(self.shakeZ - current.z);

      if (((deltaX > threshold) && (deltaY > threshold)) || ((deltaX > threshold) && (deltaZ > threshold)) || ((deltaY > threshold) && (deltaZ > threshold))) {
        currentTime = new Date();
        timeDifference = currentTime.getTime() - self.shakeTime.getTime();

        if (timeDifference > timeout) {
          self.optionsMenu(true);
          self.shakeTime = new Date();
        }
      }

      self.shakeX = current.x;
      self.shakeY = current.y;
      self.shakeZ = current.z;
    });

  },

  escapeHtml: function (unsafe) {
    return unsafe
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#039;');
  },

  activeIcon: 'data:image/png;base64,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',

  errorIcon: 'data:image/png;base64,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',

  successIcon: 'data:image/png;base64,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'

};

IonicDevServer.start();


================================================
FILE: bin/ionic-app-scripts.js
================================================
#!/usr/bin/env node

if (process.argv.length > 2) {

  if (process.env.npm_config_argv && process.env.npm_config_argv.length > 0 && process.env.npm_config_argv !== 'undefined') {
    try {
      var npmRunArgs = JSON.parse(process.env.npm_config_argv);
      if (npmRunArgs && npmRunArgs.original && npmRunArgs.original.length > 2) {
        // add flags from original "npm run" command
        for (var i = 2; i < npmRunArgs.original.length; i++) {
          process.argv.push(npmRunArgs.original[i]);
        }
      }
    } catch (e) {
      console.log(e)
    }
  }

  require('../dist/index').run(process.argv[2]);

} else {
  console.error('Missing ionic app script task name');
}


================================================
FILE: circle.yml
================================================
machine:
  node:
    version: 6.9.5
  post:
    - npm install -g npm@3.x.x
test:
  override:
    - nvm use 6 && npm test


================================================
FILE: config/cleancss.config.js
================================================

// https://www.npmjs.com/package/clean-css

module.exports = {
  /**
   * sourceFileName: the file name of the src css file
   */
  sourceFileName: process.env.IONIC_OUTPUT_CSS_FILE_NAME,

  /**
   * destFileName: the file name for the generated minified file
   */
  destFileName: process.env.IONIC_OUTPUT_CSS_FILE_NAME

};


================================================
FILE: config/copy.config.js
================================================
// this is a custom dictionary to make it easy to extend/override
// provide a name for an entry, it can be anything such as 'copyAssets' or 'copyFonts'
// then provide an object with a `src` array of globs and a `dest` string
module.exports = {
  copyAssets: {
    src: ['{{SRC}}/assets/**/*'],
    dest: '{{WWW}}/assets'
  },
  copyIndexContent: {
    src: ['{{SRC}}/index.html', '{{SRC}}/manifest.json', '{{SRC}}/service-worker.js'],
    dest: '{{WWW}}'
  },
  copyFonts: {
    src: ['{{ROOT}}/node_modules/ionicons/dist/fonts/**/*', '{{ROOT}}/node_modules/ionic-angular/fonts/**/*'],
    dest: '{{WWW}}/assets/fonts'
  },
  copyPolyfills: {
    src: [`{{ROOT}}/node_modules/ionic-angular/polyfills/${process.env.IONIC_POLYFILL_FILE_NAME}`],
    dest: '{{BUILD}}'
  },
  copySwToolbox: {
    src: ['{{ROOT}}/node_modules/sw-toolbox/sw-toolbox.js'],
    dest: '{{BUILD}}'
  }
}


================================================
FILE: config/sass.config.js
================================================

// https://www.npmjs.com/package/node-sass

module.exports = {

  /**
   * outputFilename: The filename of the saved CSS file
   * from the sass build. The directory which it is saved in
   * is set within the "buildDir" config options.
   */
  outputFilename: process.env.IONIC_OUTPUT_CSS_FILE_NAME,

  /**
   * sourceMap: If source map should be built or not.
   */
  sourceMap: false,

  /**
   * outputStyle: How node-sass should output the css file.
   */
  outputStyle: 'expanded',

  /**
   * autoprefixer: The config options for autoprefixer.
   * Excluding this config will skip applying autoprefixer.
   * https://www.npmjs.com/package/autoprefixer
   */
  autoprefixer: {
    browsers: [
      'last 2 versions',
      'iOS >= 8',
      'Android >= 4.4',
      'Explorer >= 11',
      'ExplorerMobile >= 11'
    ],
    cascade: false
  },

  /**
   * includePaths: Used by node-sass for additional
   * paths to search for sass imports by just name.
   */
  includePaths: [
    'node_modules/ionic-angular/themes',
    'node_modules/ionicons/dist/scss',
    'node_modules/ionic-angular/fonts'
  ],

  /**
   * includeFiles: An array of regex patterns to search for
   * sass files in the same directory as the component module.
   * If a file matches both include and exclude patterns, then
   * the file will be excluded.
   */
  includeFiles: [
    /\.(s(c|a)ss)$/i
  ],

  /**
   * excludeFiles: An array of regex patterns for files which
   * should be excluded. If a file matches both include and exclude
   * patterns, then the file will be excluded.
   */
  excludeFiles: [
    /*  /\.(wp).(scss)$/i  */
  ],

  /**
   * variableSassFiles: Lists out the files which include
   * only sass variables. These variables are the first sass files
   * to be imported so their values override default variables.
   */
  variableSassFiles: [
    '{{SRC}}/theme/variables.scss'
  ],

  /**
   * directoryMaps: Compiled JS modules may be within a different
   * directory than its source file and sibling component sass files.
   * For example, NGC places it's files within the .tmp directory
   * but doesn't copy over its sass files. This is useful so sass
   * also checks the JavaScript's source directory for sass files.
   */
  directoryMaps: {
    '{{TMP}}': '{{SRC}}'
  },

  /**
   * excludeModules: Used just as a way to skip over
   * modules which we know wouldn't have any sass to be
   * bundled. "excludeModules" isn't necessary, but is a
   * good way to speed up build times by skipping modules.
   */
  excludeModules: [
    '@angular',
    'commonjs-proxy',
    'core-js',
    'ionic-native',
    'rxjs',
    'zone.js'
  ]

};


================================================
FILE: config/uglifyjs.config.js
================================================

// https://www.npmjs.com/package/uglify-es

module.exports = {

  /**
   * mangle: uglify 2's mangle option
   */
  mangle: true,

  /**
   * compress: uglify 2's compress option
   */
  compress: {
    toplevel: true,
    pure_getters: true
  }
};

================================================
FILE: config/watch.config.js
================================================
var watch = require('../dist/watch');
var copy = require('../dist/copy');
var copyConfig = require('./copy.config');

// this is a custom dictionary to make it easy to extend/override
// provide a name for an entry, it can be anything such as 'srcFiles' or 'copyConfig'
// then provide an object with the paths, options, and callback fields populated per the Chokidar docs
// https://www.npmjs.com/package/chokidar

module.exports = {
  srcFiles: {
    paths: ['{{SRC}}/**/*.(ts|html|s(c|a)ss)'],
    options: { ignored: ['{{SRC}}/**/*.spec.ts', '{{SRC}}/**/*.e2e.ts', '**/*.DS_Store', '{{SRC}}/index.html'] },
    callback: watch.buildUpdate
  },
  copyConfig: copy.copyConfigToWatchConfig()
};


================================================
FILE: config/webpack.config.js
================================================
/*
 * The webpack config exports an object that has a valid webpack configuration
 * For each environment name. By default, there are two Ionic environments:
 * "dev" and "prod". As such, the webpack.config.js exports a dictionary object
 * with "keys" for "dev" and "prod", where the value is a valid webpack configuration
 * For details on configuring webpack, see their documentation here
 * https://webpack.js.org/configuration/
 */

var path = require('path');
var webpack = require('webpack');
var ionicWebpackFactory = require(process.env.IONIC_WEBPACK_FACTORY);
const Dotenv = require('dotenv-webpack');

var ModuleConcatPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
var PurifyPlugin = require('@angular-devkit/build-optimizer').PurifyPlugin;

var optimizedProdLoaders = [
  {
    test: /\.json$/,
    loader: 'json-loader'
  },
  {
    test: /\.js$/,
    loader: [
      {
        loader: process.env.IONIC_CACHE_LOADER
      },

      {
        loader: '@angular-devkit/build-optimizer/webpack-loader',
        options: {
          sourceMap: true
        }
      },
    ]
  },
  {
    test: /\.ts$/,
    loader: [
      {
        loader: process.env.IONIC_CACHE_LOADER
      },

      {
        loader: '@angular-devkit/build-optimizer/webpack-loader',
        options: {
          sourceMap: true
        }
      },

      {
        loader: process.env.IONIC_WEBPACK_LOADER
      }
    ]
  }
];

function getProdLoaders() {
  if (process.env.IONIC_OPTIMIZE_JS === 'true') {
    return optimizedProdLoaders;
  }
  return devConfig.module.loaders;
}

var devConfig = {
  entry: process.env.IONIC_APP_ENTRY_POINT,
  output: {
    path: '{{BUILD}}',
    publicPath: 'build/',
    filename: '[name].js',
    devtoolModuleFilenameTemplate: ionicWebpackFactory.getSourceMapperFunction(),
  },
  devtool: process.env.IONIC_SOURCE_MAP_TYPE,

  resolve: {
    extensions: ['.ts', '.js', '.json'],
    modules: [path.resolve('node_modules')]
  },

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.ts$/,
        loader: process.env.IONIC_WEBPACK_LOADER
      }
    ]
  },

  plugins: [
    new Dotenv({
      path: '.env.dev', // load this now instead of the ones in '.env'
      systemvars: true, // load all the predefined 'process.env' variables which will trump anything local per dotenv specs.
      silent: true // hide any errors
    }),
    ionicWebpackFactory.getIonicEnvironmentPlugin(),
    ionicWebpackFactory.getCommonChunksPlugin()
  ],

  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  node: {
    fs: 'empty',
    net: 'empty',
    tls: 'empty'
  }
};

var prodConfig = {
  entry: process.env.IONIC_APP_ENTRY_POINT,
  output: {
    path: '{{BUILD}}',
    publicPath: 'build/',
    filename: '[name].js',
    devtoolModuleFilenameTemplate: ionicWebpackFactory.getSourceMapperFunction(),
  },
  devtool: process.env.IONIC_SOURCE_MAP_TYPE,

  resolve: {
    extensions: ['.ts', '.js', '.json'],
    modules: [path.resolve('node_modules')]
  },

  module: {
    loaders: getProdLoaders()
  },

  plugins: [
    new Dotenv({
      path: '.env.prod', // load this now instead of the ones in '.env'
      systemvars: true, // load all the predefined 'process.env' variables which will trump anything local per dotenv specs.
      silent: true // hide any errors
    }),
    ionicWebpackFactory.getIonicEnvironmentPlugin(),
    ionicWebpackFactory.getCommonChunksPlugin(),
    new ModuleConcatPlugin(),
    new PurifyPlugin()
  ],

  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  node: {
    fs: 'empty',
    net: 'empty',
    tls: 'empty'
  }
};


module.exports = {
  dev: devConfig,
  prod: prodConfig
}



================================================
FILE: lab/index.html
================================================
<!doctype html>
<html>
  <head>
    <title>Ionic Lab</title>
    <meta charset="utf-8">
    <link rel="icon" type="image/png" href="/ionic-lab/static/img/favicon.png" />
    <link rel="stylesheet" href="/ionic-lab/static/css/style.css" />
    <link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" />
  </head>
  <body>
    <div id="app">
      <div id="header">
        <div id="header-left">
          <a href="#" id="menu-toggle">
            <i class="icon ion-navicon-round"></i>
          </a>
          <div id="logo">
          </div>
        </div>

        <div id="header-right">
          <a href="/" target="_blank" id="open-fullscreen">Open fullscreen <i class="icon ion-share"></i></a>
          <div class="dropdown">
            <button class="dropdown-toggle" type="button">Platforms <span class="dropdown-caret"></span></button>
            <ul class="dropdown-menu">
              <li><input type="checkbox" id="device-iphone" name="iphone"><label for="device-iphone">iPhone</label></li>
              <li><input type="checkbox" id="device-android" name="android"><label for="device-android">Android</label></li>
              <li><input type="checkbox" id="device-windows" name="windows"><label for="device-windows">Windows</label></li>
            </ul>
          </div>
        </div>
      </div>
      <div id="main">
        <div id="sidebar" class="hidden">
          <div class="title">Quick reference</div>
          <div class="close"><i class="icon ion-close-circled"></i></div>
          <ul id="menu" class="menu">
            <li><a>Components</a>
              <ul id="components-menu">
              </ul>
            </li>
            <li><a target="_blank" href="https://ionicframework.com/docs/api">API Reference</a></li>
            <li><a target="_blank" href="https://ionicframework.com/docs/native">Ionic Native</a></li>
            <li><a target="_blank" href="https://ionicframework.com/docs/">All Documentation</a></li>
          </ul>
          <div id="view-ad" class="ad">
            <img class="logo" src="/ionic-lab/static/img/view-logo.jpg" style="height: 64px"/>
            <div class="ad-content">
              Test and share your app live on iOS and Android
              with the Ionic View app!
              <br>
              <a href="http://view.ionic.io">Download View</a>
            </div>
          </div>
        </div>
        <preview>
        </preview>
      </div>
      <div id="footer">
        <div id="footer-left">
          <span id="app-info"></span>
        </div>
        <div id="footer-right">
          <a target="_blank" href="http://twitter.com/ionicframework">Twitter</a>
          <a target="_blank" href="http://ionicframework.com/docs">Documentation</a>
          <a target="_blank" href="https://forum.ionicframework.com/">Forum</a>
          <a target="_blank" href="https://github.com/ionic-team/ionic">GitHub</a>
          <a target="_blank" class="view-link" href="http://view.ionic.io/">Ionic View</a>
        </div>
      </div>

      <div id="view-popup">
        <div class="view-popup-wrapper">
          <div class="close"></div>
          <div class="content">
            <h2>Psssst...</h2>
            <p>
              You can test your app live on iOS and Android
              with the <a href="http://view.ionic.io" target="_blank">Ionic View</a> app!
            </p>
          </div>
          <div class="ionitron"></div>
        </div>
      </div>
    </div>
    <template id="iphone-frame-template">
      <div class="phone" id="iphone">
        <div class="phone-frame">
          <h2><div class="phone-icon"></div> <a href="/?ionicplatform=ios" target="_blank">iOS</a></h2>
          <div id="iphone-frame" class="phone-frame-wrap">
            <div class="statusbar"></div>
            <iframe src="/?ionicplatform=ios&amp;ionicstatusbarpadding=true" class="frame"></iframe>
          </div>
        </div>
      </div>
    </template>
    <template id="android-frame-template">
      <div class="phone" id="android">
        <div class="phone-frame">
          <h2><div class="phone-icon"></div> <a href="/?ionicplatform=android" target="_blank">Android</a></h2>
          <div id="android-frame" class="phone-frame-wrap">
            <div class="statusbar"></div>
            <iframe src="/?ionicplatform=android" class="frame"></iframe>
          </div>
        </div>
      </div>
    </template>
    <template id="windows-frame-template">
      <div class="phone" id="windows">
        <div class="phone-frame">
          <h2><div class="phone-icon"></div> <a href="/?ionicplatform=windows" target="_blank">Windows</a></h2>
          <div id="windows-frame" class="phone-frame-wrap">
            <div class="statusbar"></div>
            <iframe src="/?ionicplatform=windows" class="frame"></iframe>
          </div>
        </div>
      </div>
    </template>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js"></script>
    <script src="/ionic-lab/static/js/lab.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-44023830-9', {
        'cookieDomain': 'none'
      })
      ga('send', 'pageview');
    </script>
  </body>
</html>


================================================
FILE: lab/static/css/style.css
================================================
@font-face {font-family: 'AvenirNextLTPro-Regular';src: url('http://code.ionicframework.com/assets/fonts/28882F_0_0.eot');src: url('http://code.ionicframework.com/assets/fonts/28882F_0_0.eot?#iefix') format('embedded-opentype'),url('http://code.ionicframework.com/assets/fonts/28882F_0_0.woff') format('woff'),url('http://code.ionicframework.com/assets/fonts/28882F_0_0.ttf') format('truetype');}


@font-face {font-family: 'AvenirNextLTPro-Medium';src: url('http://code.ionicframework.com/assets/fonts/28882F_1_0.eot');src: url('http://code.ionicframework.com/assets/fonts/28882F_1_0.eot?#iefix') format('embedded-opentype'),url('http://code.ionicframework.com/assets/fonts/28882F_1_0.woff') format('woff'),url('http://code.ionicframework.com/assets/fonts/28882F_1_0.ttf') format('truetype');}


@font-face {font-family: 'AvenirNextLTPro-UltLt';src: url('http://code.ionicframework.com/assets/fonts/29CC36_0_0.eot');src: url('http://code.ionicframework.com/assets/fonts/29CC36_0_0.eot?#iefix') format('embedded-opentype'),url('http://code.ionicframework.com/assets/fonts/29CC36_0_0.woff') format('woff'),url('http://code.ionicframework.com/assets/fonts/29CC36_0_0.ttf') format('truetype');}

html, body {
  height: 100%;
}

body {
  background-color: #242A31;
  font-family: 'AvenirNextLTPro-Regular', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
  padding: 0;
  margin: 0;
  -webkit-font-smoothing: antialiased;
}
h2 {
  color: #fff;
  font-family: 'AvenirNextLTPro-Regular', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
}

h2 a {
  font-size: 14px;
  color: #727a87;
  text-decoration: none;
}

.dropdown {
  height: 100%;
  position: relative;
}
.dropdown-toggle {
  color: #858D9B;
  display: block;
  height: 100%;
  background: none;
  border: none;
  font-size: 13px;
  cursor: pointer;
  padding-left: 15px;
  font-weight: bold;
  outline: none;
  font-family: 'AvenirNextLTPro-Medium', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
}
.dropdown-menu {
  display: none;
  position: absolute;
  z-index: 999;
  width: 150px;
  right: -10px;
  background-color: white;
  box-shadow: 0 6px 10px rgba(0,0,0,.08), 0 0px 6px rgba(0,0,0,.05);
}
.dropdown-menu > li {
  padding: 6px 5px;
}
.dropdown:hover .dropdown-toggle {
  /* increase the hit box when hovering */
  /*padding-left: 100px;*/
}
.dropdown:hover .dropdown-menu {
  display: block;
}
.dropdown li {
  list-style: none;
}
.dropdown ul {
  margin: 0;
  padding: 0;
}
.dropdown-caret {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;

  border-top: 5px solid #858D9B;
  display: inline-block;
}
.dropdown-menu input {
  cursor: pointer;
  background-color: #4D82E9;
}
.dropdown-menu label {
  font-size: 13px;
  margin-left: 5px;
  color: #858D9B;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

#app {
  display: flex;
  flex-direction: column;
  height: 100%;
}

#header {
  width: 100%;
  height: 50px;
  background-color: #151A21;
  box-shadow: 0px 1px 3px rgba(0,0,0, 0.15);
}
#header a {
  color: #858D9B;
  font-family: 'AvenirNextLTPro-Medium', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
  font-size: 13px;
  text-decoration: none;
  display: inline-block;
  font-weight: bold;
}
#header .icon {
  display: inline-block;
  font-size: 22px;
  vertical-align: middle;
  margin-bottom: 3px;
  margin-left: 3px;
}
#header .dropdown {
  display: inline-block;
}

#header-left {
  float: left;
  line-height: 50px;
}
#header-left #menu-toggle {
  margin-left: 13px;
}
#header a:hover {
  opacity: 1;
}
#header-right {
  float: right;
  margin-right: 15px;
  height: 100%;
}
#footer {
  width: 100%;
  border-top: 1px solid rgba(0,0,0,0.06);
  background-color: #151A21;
}
#footer-left {
  float: left;
  padding: 14px 0 14px 15px;
  font-size: 13px;
}
#app-info {
  color: #828080;
}
#footer-right {
  float: right;
  padding: 14px 15px 14px 5px;
  font-size: 13px;
}
#footer-right a {
  margin-left: 10px;
  color: #a2a9b4;
  text-decoration: none;
  font-family: 'AvenirNextLTPro-Medium', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
}
#logo {
  display: inline-block;
  vertical-align: middle;

  width: 64px;
  height: 28px;
  margin-left: 15px;
  background-size: 100%;
  background-repeat: no-repeat;
  background-image: url(data:image/png;base64,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);
}

#logo img {
  max-width: 100%;
}

preview {
  flex: 1;
  width: 100%;
  display: flex;
  vertical-align: middle;
  overflow: auto;
  text-align: center;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  flex-direction: row;
}

.phone {
  display: inline-block;
  margin: 0px 20px 0 20px;
  vertical-align: middle;
}
.phone h2 {
  text-align: left;
  vertical-align: middle;
  margin-top: 0;
}
.phone-icon {
  display: inline-block;
  vertical-align: middle;
  background-repeat: no-repeat;
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAABgCAYAAAB8InCYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABFlJREFUeNrsmmdoFEEUxzeagIXYomKNhUv8YMPoBzGRKBpEgxoFBSGRiKDYsWFMAuqHqCAW0OgHlSgaRcSICoqFKMEPSuyIiAVLbIgFUcESPf+PvNNh2Nub3Z05EtwHP27uZnbnvzuzb96bvYRwOGxFbHnJRsuHJYAZYD74CsZFa7i5rOhvuZmlxzqB86ASZLo5b6KGzltx54OF326rHqzjDqyROic7Ei8BHcBC6bczoDZeAnJ4CCL2Fsx1cwK/AgYI5ZsgC9S5OYHKJOwGJoCe4Bu4Bi6Bn+Axz/zj4ARIApPBQL4zz8Fp/nQtoD3YBApBc6nuI6gCp/BM58N/TEF5H8gDraW25GgOgmXgnaqAEDgL+jqIm00oOC9yUAUgG4wBj2LNgRRwzqFzr5bK520RS8B20MfSb3T7Z/I8ijoE/dmf67YfPJFrYz2G0y0zti2ac5IFjDYkYIeqI0o30PlDJ+ckC+hsQMArN644wYCAJDcCvhkQ0M9pzZEr6gwIIMc2QlXAfUNPQbGqgKuGBIwHc1QEnLPM2S6wVJ7osoDr4IUhAdTXFnDZScBvsMcya7dirYa7DT2OZL/A1lgCyHOVGxKwUyUgISsDHwzEA2tVo2KK+RZrFjDf7qKcwvJKRofRxD7qJSyfzStkjk0dheU3wBsOUodJSUrEToIFXhOT7yAXlILX/NsDsJLzheEIy/M44u0C5oE73O4loDx8Kodk9iEz7Q8ohNaFvE5cUbzllCH15nzActonUE3PKekgle3oqkEG6C4kLPWc/Vzj2C+b75q2/YH+vKSucmgzFEzh8nlObh7pSE5z+apGusyaaYKO8iuAruIQaMmPEY1rjUP7Gk5qjoFk/uzpRwCtXm2EYOUZZ8TRjOqegnvCBsYmrwLo6icK30v5EZzlcMwsblMqJTupXgTk2UTMaQrjnyYFHVSe5ChA3LcTbLDGdWCI42MIR9SLA0dar8sg6CXn9AU6VyP0Q76jhP3HeppTET9Qxc6FbBAaZvHOhk6joaDtu0z+TmvH0MgcyBAaZhoMx8RzZ+jYJdMSqQYCAgGBgEYhoEL4rdxgf+K5K8SQjMLvw7wWXDQoYBG7fVoLLogCwhzHmTbqp7rJTMJqjf1UexGwxGp4C+LXTvDWjHpewBHSXTEsQ4wQltokSMFG1HrKvOicdhlY3OZAtPSvSXnCL0K53kO9bwH7hfIBD/W+klNbL+ay3j5SXVa8wfQw09PQgzMtIl0ohxLj0YklvarzOgRiJ5R654OxKp24mQOqV0Kp1jTeCfFliZw+h/xeiR8BK4KQLBAQCAgE/NcCyBOu83AcvaTYZzX8n8i3gKcejvvBIrTcgQoPx9FqWKRjNQwmYSAgEBAIaBRrwWqr4T1PiD+7xluAvHOQLCUm6UK5owkBsn22Gv6ie9Omri0LecIpeJ0gsp0uAU72yfr3x8S9TMRSeAjT+VMkWZcAJ3vP2L3i7yLMM3FYQ38EGAB86eMs4sfk/QAAAABJRU5ErkJggg==');
  width: 16px;
  height: 16px;
  background-size: 100%;
}
#iphone .phone-icon {
  background-position: 0px 0px;
}
#android .phone-icon {
  background-position: 0px -16px;
}
#windows .phone-icon {
  background-position: 0px -32px;
}
.frame {
  border: none;
}
.phone-frame-wrap {
  position: relative;
  width: 375px;
  height: 667px;
  border-radius: 3px;
  box-shadow: 0 8px 24px rgba(0,0,0,.08), 0 0px 6px rgba(0,0,0,.1);
  overflow: hidden;
}
.phone-frame-wrap iframe {
  width: 100%;
  height: 100%;
}
.statusbar {
  position: absolute;
  top: 0;
  width: 375px;
  height: 10px;
  padding: 5px 0;
  background-size: 100%;
  background-repeat: no-repeat;
  background-color: transparent;
  background-position: center;
  border-radius: 3px 3px 0 0;
}
#iphone-frame .statusbar {
  background-image: url(../img/ios-statusbar.png);
}
#android-frame .statusbar {
  background-image: url(../img/android-statusbar.png);
}
#windows-frame .statusbar {
  background-image: url(../img/wp-statusbar.png)
}

/* Android and windows don't make space for the statusbar like iOS does */
#android-frame iframe, #windows-frame iframe {
  height: 647px;
  margin-top: 20px;
}

#view-popup {
  display: none;
  opacity: 0;
  transition: 400ms linear opacity;
  position: fixed;
  bottom: 15px;
  left: 15px;
}
#view-popup .view-popup-wrapper {
  position: relative;
}
#view-popup .ionitron {
  background: url('../img/popup-ionitron.png') no-repeat transparent;
  width: 90px;
  height: 90px;
  background-size: 100%;
}
#view-popup .content {
  box-sizing: border-box;
  background: url('../img/popup-view-bubble.png') no-repeat transparent;
  width: 350px;
  height: 350px;
  background-size: 100%;
  margin-bottom: -50px;
  padding-top: 25px;
  text-align: center;
  color: white;
}
#view-popup .content a {
  color: #fff;
  font-weight: bold;
}
#view-popup .content h2 {
  margin-bottom: 5px;
}
#view-popup .content p {
  font-size: 13px;
  max-width: 220px;
  margin: auto;
}

#view-popup .close {
  cursor: pointer;
  background: url('../img/popup-close.png') no-repeat transparent;
  position: absolute;
  right: 35px;
  top: 20px;
  width: 60px;
  height: 60px;
  background-size: 100%;
  position: absolute;
}

#main {
  display: flex;
  flex-direction: row;
  flex: 1;
}

#sidebar {
  position: relative;
  z-index: 1;
  background-color: #141A21;
  height: 100%;
  width: 300px;
  box-sizing: border-box;
  padding: 15px;
  overflow: auto;
}

#sidebar.hidden {
  display: none;
}

#sidebar .close {
  cursor: pointer;
  position: absolute;
  top: 15px;
  right: 15px;
  color: #a2a9b4;
  font-size: 24px;
}

#sidebar .title {
  font-size: 20px;
  margin-top: 5px;
  color: white;
}

.menu {
  padding: 0;
  margin: 0;
  -webkit-touch-callout: none; /* iOS Safari */
  -webkit-user-select: none; /* Safari */
   -khtml-user-select: none; /* Konqueror HTML */
     -moz-user-select: none; /* Firefox */
      -ms-user-select: none; /* Internet Explorer/Edge */
          user-select: none; /* Non-prefixed version, currently
                                supported by Chrome and Opera */
}
.menu li {
  list-style: none;
  margin: 15px 0;
}
.menu li a {
  color: #a2a9b4;
  text-decoration: none;
  cursor: pointer;
}
.menu > li > ul {
  display: none;
  padding: 0;
  margin: 0;
}
.menu > li > ul li {
  padding-left: 15px;
}
.menu > li.expanded > ul {
  display: block;
}
.menu hr {
  height: 1px;
  border: 0;
  background-color: #2b3642;
}
.menu .version {
  color: #a2a9b4;
  opacity: 0.5;
  font-size: 12px;
}

#menu {
}

.ad {
  background-color: #232A31;
  cursor: pointer;
  border-radius: 2px;
  border: 1px solid #3f4650;
  font-size: 13px;
  color: white;
  padding: 10px;
  display: flex;
  margin-top: 55px;
}
.ad .logo {
  display: block;
  margin-right: 15px;
}
.ad .content {
  flex: 1;
}
.ad a {
  color: #308EFD;
}

@media screen and (max-height: 800px) {
  #header {
    height: 40px;
  }
  #header-left {
    line-height: 40px;
  }
  #logo {
    width: 50px;
    height: 22px;
  }
  #footer-left {
    float: left;
    padding: 7px 0 7px 15px;
    font-size: 12px;
  }
  #app-info {
    color: #828080;
  }
  #footer-right {
    float: right;
    padding: 7px 15px 7px 5px;
    font-size: 13px;
  }
  #footer-right .view-link {
    color: #4D82E9;
  }
  .phone-frame h2 {
    display: none;
  }

  @media screen and (max-width: 500px) {
    #footer {
      display: none;
    }
  }
}

@media screen and (max-height: 780px) {
  .statusbar {
    width: 340px;
  }
  .phone-frame-wrap {
    width: 340px;
    height: 605px;
  }
  #android-frame iframe, #windows-frame iframe {
    height: 585px;
    margin-top: 20px;
  }
}
@media screen and (max-height: 680px) {
  .statusbar {
    width: 325px;
  }
  .phone-frame-wrap {
    width: 325px;
    height: 578px;
  }
  #android-frame iframe, #windows-frame iframe {
    height: 558px;
    margin-top: 20px;
  }
}


================================================
FILE: lab/static/js/lab.js
================================================
var $ = document.querySelector.bind(document);

var API_ROOT = '/ionic-lab/api/v1';

var APP_CONFIG = {};

function loadAppConfig() {
  var req = new XMLHttpRequest();
  req.addEventListener('load', function(e) {
    setAppConfig(JSON.parse(req.response));
  });
  req.open('GET', API_ROOT + '/app-config', true);
  req.send(null);
}

function setAppConfig(data) {
  APP_CONFIG = data;
}

function buildMenu() {
  buildComponentsMenu();
  var sidebar = $('#sidebar');
  var topLevels = sidebar.querySelectorAll('#menu > li > a');

  var lastMenuConfig = window.localStorage.getItem('ionic_labmenu');
  if (lastMenuConfig === 'true' || lastMenuConfig === null) {
    sidebar.classList.remove('hidden');
  }

  Array.prototype.map.call(topLevels, function(a) {
    if (!a.href) {
      a.addEventListener('click', function(e) {
        if (a.parentNode.classList.contains('expanded')) {
          a.parentNode.classList.remove('expanded');
        } else {
          a.parentNode.classList.add('expanded');
        }
        e.preventDefault();
      });
    }
  });

  $('#view-ad').addEventListener('click', function(e) {
    var win = window.open('http://view.ionic.io/', '_blank');
    win.focus();
  });

  var toggleMenu = function(e) {
    if (sidebar.classList.contains('hidden')) {
      sidebar.classList.remove('hidden');
      window.localStorage.setItem('ionic_labmenu', 'true');
    } else {
      sidebar.classList.add('hidden');
      window.localStorage.setItem('ionic_labmenu', 'false');
    }
  };

  $('#menu-toggle').addEventListener('click', toggleMenu);
  $('#sidebar .close').addEventListener('click', toggleMenu);
}

function buildComponentsMenu() {
  var items = [{"href":"http://ionicframework.com/docs/components/#overview","title":"Overview"},{"href":"http://ionicframework.com/docs/components/#action-sheets","title":"Action Sheets"},{"href":"http://ionicframework.com/docs/components/#alert","title":"Alerts"},{"href":"http://ionicframework.com/docs/components/#badges","title":"Badges"},{"href":"http://ionicframework.com/docs/components/#buttons","title":"Buttons"},{"href":"http://ionicframework.com/docs/components/#cards","title":"Cards"},{"href":"http://ionicframework.com/docs/components/#checkbox","title":"Checkbox"},{"href":"http://ionicframework.com/docs/components/#datetime","title":"DateTime"},{"href":"http://ionicframework.com/docs/components/#fabs","title":"FABs"},{"href":"http://ionicframework.com/docs/components/#gestures","title":"Gestures"},{"href":"http://ionicframework.com/docs/components/#grid","title":"Grid"},{"href":"http://ionicframework.com/docs/components/#icons","title":"Icons"},{"href":"http://ionicframework.com/docs/components/#inputs","title":"Inputs"},{"href":"http://ionicframework.com/docs/components/#lists","title":"Lists"},{"href":"http://ionicframework.com/docs/components/#loading","title":"Loading"},{"href":"http://ionicframework.com/docs/components/#menus","title":"Menus"},{"href":"http://ionicframework.com/docs/components/#modals","title":"Modals"},{"href":"http://ionicframework.com/docs/components/#navigation","title":"Navigation"},{"href":"http://ionicframework.com/docs/components/#popovers","title":"Popover"},{"href":"http://ionicframework.com/docs/components/#radio","title":"Radio"},{"href":"http://ionicframework.com/docs/components/#range","title":"Range"},{"href":"http://ionicframework.com/docs/components/#searchbar","title":"Searchbar"},{"href":"http://ionicframework.com/docs/components/#segment","title":"Segment"},{"href":"http://ionicframework.com/docs/components/#select","title":"Select"},{"href":"http://ionicframework.com/docs/components/#slides","title":"Slides"},{"href":"http://ionicframework.com/docs/components/#tabs","title":"Tabs"},{"href":"http://ionicframework.com/docs/components/#toast","title":"Toast"},{"href":"http://ionicframework.com/docs/components/#toggle","title":"Toggle"},{"href":"http://ionicframework.com/docs/components/#toolbar","title":"Toolbar"}];

  var componentsMenu = $('#components-menu');
  items.map(function (i) {
    var l = document.createElement('li');
    var a = document.createElement('a');
    a.href = i.href;
    a.target = "_blank";
    a.innerText = i.title;
    l.appendChild(a);
    componentsMenu.appendChild(l);
  });
}

function tryShowViewPopup() {
  var view = window.localStorage.getItem('ionic_viewpop');

  if (!view) {
    $('#view-popup').style.display = 'block';
    $('#view-popup .close').addEventListener('click', function(e) {
      window.localStorage.setItem('ionic_viewpop', true);
      $('#view-popup').style.opacity = 0;
      setTimeout(function() {
        $('#view-popup').style.display = 'none';
      }, 200);
    });
    window.requestAnimationFrame(function() {
      $('#view-popup').style.opacity = 1;
    });
  }
}

// Bind the dropdown platform toggles
function bindToggles() {
  // Watch for changes on the checkboxes in the device dropdown
  var iphone = $('#device-iphone');
  var android = $('#device-android');
  var windows = $('#device-windows');

  var devices = [iphone, android, windows];
  for(var i in devices) {
    devices[i].addEventListener('change', function(e) {
      var device = this.name;
      console.log('Device changed', device, this.checked);

      showDevice(device, this.checked);
      saveLastDevices(device, this.checked);
    });
  }
}

// Show one of the devices
function showDevice(device, isShowing) {
  $('#device-' + device).checked = isShowing;

  var rendered = $('#' + device);
  if(!rendered) {
    var template = $('#' + device + '-frame-template');
    var clone = document.importNode(template, true);
    $('preview').appendChild(clone.content);
    //check for extra params in location.url to pass on to iframes
    var params = document.location.href.split('?');
    if (params) {
      var newparams = params[params.length - 1];
      var oldsrc = $('preview .frame').getAttribute('src');
      $('preview .frame').setAttribute('src', oldsrc + '&' + newparams);
    }
  } else {
    rendered.style.display = isShowing ? '' : 'none';
  }
}

function saveLastDevices(newDevice, didAdd) {
  var last = window.localStorage.getItem('ionic_lastdevices');
  if(!last && didAdd) {
    window.localStorage.setItem('ionic_lastdevices', newDevice);
    return;
  }
  var devices = last.split(',');
  var di = devices.indexOf(newDevice);
  if(di == -1 && didAdd) {
    window.localStorage.setItem('ionic_lastdevices', devices.join(',') + ',' + newDevice);
  } else if(di >= 0) {
    devices.splice(di, 1);
    window.localStorage.setItem('ionic_lastdevices', devices.join(','));
  }
}

function showLastDevices() {
  var last = window.localStorage.getItem('ionic_lastdevices');
  if(!last) {
    showDevice('iphone', true);
    return;
  }

  var devices = last.split(',');
  for(var i = 0; i < devices.length; i++) {
    showDevice(devices[i], true);
  }
}

function setCordovaInfo(data) {
  var el = $('#app-info');
  el.innerHTML = data.name + ' - v' + data.version;
  if(data.name) {
    document.title = data.name + ' - Ionic Lab';
  }
}

function loadCordova() {
  var req = new XMLHttpRequest();
  req.addEventListener('load', function(e) {
    setCordovaInfo(JSON.parse(req.response));
  });
  req.open('GET', API_ROOT + '/cordova', true);
  req.send(null);
}

//loadSearchIndex();
loadAppConfig();
buildMenu();
showLastDevices();
loadCordova();
bindToggles();
//tryShowViewPopup();


================================================
FILE: package.json
================================================
{
  "name": "@ionic/app-scripts",
  "version": "3.2.4",
  "description": "Scripts for Ionic Projects",
  "homepage": "https://ionicframework.com/",
  "author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
  "license": "MIT",
  "files": [
    "bin/",
    "config/",
    "dist/",
    "lab",
    "LICENSE",
    "README.md"
  ],
  "bin": {
    "ionic-app-scripts": "./bin/ionic-app-scripts.js"
  },
  "scripts": {
    "build": "npm run clean && tsc && npm run sass",
    "build-and-test": "jest",
    "changelog": "./node_modules/.bin/conventional-changelog -p angular -i CHANGELOG.md -s",
    "clean": "rimraf ./dist",
    "github-release": "node ./scripts/create-github-release.js",
    "lint": "tslint -c ./tslint.json --project ./tsconfig.json --type-check -t stylish",
    "nightly": "npm run build && node ./scripts/publish-nightly.js",
    "sass": "node-sass ./src/dev-client/sass/ion-dev.scss --output ./bin/ --output-style compressed",
    "sass-watch": "npm run sass && node-sass ./src/dev-client/sass/ion-dev.scss --watch --output ./bin/ --output-style compressed",
    "test": "jest",
    "watch": "npm run clean && tsc --watch & npm run sass-watch"
  },
  "main": "dist/index.js",
  "dependencies": {
    "@angular-devkit/build-optimizer": "0.0.35",
    "autoprefixer": "^7.2.6",
    "chalk": "^2.4.0",
    "chokidar": "^2.0.4",
    "clean-css": "^4.1.11",
    "cross-spawn": "^5.1.0",
    "dotenv-webpack": "^1.5.7",
    "express": "^4.16.3",
    "fs-extra": "^4.0.2",
    "glob": "^7.1.2",
    "json-loader": "^0.5.7",
    "node-sass": "^4.10.0",
    "os-name": "^2.0.1",
    "postcss": "^6.0.21",
    "proxy-middleware": "^0.15.0",
    "reflect-metadata": "^0.1.10",
    "rollup": "0.50.0",
    "rollup-plugin-commonjs": "8.2.6",
    "rollup-plugin-node-resolve": "3.0.0",
    "source-map": "^0.6.1",
    "tiny-lr": "^1.1.1",
    "tslint": "^5.8.0",
    "tslint-eslint-rules": "^4.1.1",
    "uglify-es": "3.2.2",
    "webpack": "3.12.0",
    "ws": "3.3.2",
    "xml2js": "^0.4.19"
  },
  "devDependencies": {
    "@angular/animations": "5.0.3",
    "@angular/common": "5.0.3",
    "@angular/compiler": "5.0.3",
    "@angular/compiler-cli": "5.0.3",
    "@angular/core": "5.0.3",
    "@angular/forms": "5.0.3",
    "@angular/http": "5.0.3",
    "@angular/platform-browser": "5.0.3",
    "@angular/platform-browser-dynamic": "5.0.3",
    "@angular/platform-server": "5.0.3",
    "@types/chokidar": "^1.7.5",
    "@types/clean-css": "^3.4.29",
    "@types/express": "^4.11.1",
    "@types/fs-extra": "^4.0.8",
    "@types/glob": "^5.0.35",
    "@types/jest": "^21.1.5",
    "@types/mock-fs": "^3.6.30",
    "@types/node": "^8.10.9",
    "@types/node-sass": "^3.10.32",
    "@types/rewire": "^2.5.27",
    "@types/webpack": "^3.8.11",
    "@types/ws": "^3.2.0",
    "conventional-changelog-cli": "^1.3.22",
    "github": "0.2.4",
    "ionic-cz-conventional-changelog": "^1.0.0",
    "jest": "^21.2.1",
    "mock-fs": "^4.4.2",
    "rewire": "^2.5.2",
    "rimraf": "^2.6.1",
    "rxjs": "^5.5.10",
    "sw-toolbox": "^3.6.0",
    "tslint-ionic-rules": "0.0.8",
    "typescript": "~2.4.2",
    "zone.js": "^0.8.26"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ionic-team/ionic-app-scripts.git"
  },
  "bugs": {
    "url": "https://github.com/ionic-team/ionic-app-scripts/issues"
  },
  "config": {
    "commitizen": {
      "path": "node_modules/ionic-cz-conventional-changelog"
    }
  },
  "typings": "dist/index.d.ts",
  "jest": {
    "testEnvironment": "node",
    "moduleFileExtensions": [
      "ts",
      "js"
    ],
    "transform": {
      "^.+\\.(ts)$": "<rootDir>/preprocessor.js"
    },
    "testRegex": "/src/.*\\.spec\\.(ts|js)$",
    "coverageDirectory": "coverage"
  }
}


================================================
FILE: preprocessor.js
================================================
const tsc = require('typescript');
const tsConfig = require('./tsconfig.json');

module.exports = {
  process(src, path) {
    if (path.endsWith('.ts')) {
      return tsc.transpile(
        src,
        tsConfig.compilerOptions,
        path,
        []
      );
    }
    return src;
  },
};


================================================
FILE: scripts/commit-changelog.js
================================================
var execSync = require('child_process').execSync;

function main() {
  try {
    execSync('git add ./CHANGELOG.md');
    execSync('git commit -m "chore(changelog): update changelog for release"');
  } catch (ex) {
    console.log('Failed to complete commiting changelog - ', ex.message);
    process.exit(1);
  }
}

================================================
FILE: scripts/create-github-release.js
================================================
var path = require('path');
var execSync = require('child_process').execSync;

var GithubApi = require('github');

var changelogCommand = './node_modules/.bin/conventional-changelog -p angular';

var packageJsonPath = path.join(__dirname, '..', 'package.json');
var packageJson = require(packageJsonPath);

var github = new GithubApi({ version: '3.0.0'});

github.authenticate({ type: 'oauth', token: process.env.GH_TOKEN });

var changelogContent = execSync(changelogCommand).toString();

github.releases.createRelease({
  owner: 'ionic-team',
  repo: 'ionic-app-scripts',
  target_commitish: 'master',
  tag_name: 'v' + packageJson.version,
  name: packageJson.version,
  body: changelogContent,
  prerelease: false
}, function(err, result) {
  if (err) {
    console.log('[create-github-release] An error occurred: ' + err.message);
    process.exit(1);
  }
  else {
    console.log('[create-github-release]: Process succeeded');
  }
});

================================================
FILE: scripts/publish-nightly.js
================================================
var execSync = require('child_process').execSync;
var fs = require('fs');
var path = require('path');

var packageJsonPath = path.join(__dirname, '..', 'package.json');
var tempPackageJsonPath = path.join(__dirname, '..', 'package-orig.json');
var originalPackageJson = require(packageJsonPath);

/*
 * This script assumes the `build` step was run prior to it
 */

function backupOriginalPackageJson() {
  var originalContent = JSON.stringify(originalPackageJson, null, 2);
  fs.writeFileSync(tempPackageJsonPath, originalContent);
}

function createNightlyVersionInPackageJson() {
  var originalVersion = originalPackageJson.version;
  originalPackageJson.version = originalVersion + '-' + createTimestamp();
  fs.writeFileSync(packageJsonPath, JSON.stringify(originalPackageJson, null, 2));
}

function revertPackageJson() {
  var fileContent = fs.readFileSync(tempPackageJsonPath);
  fileContent = fileContent + '\n';
  fs.writeFileSync(packageJsonPath, fileContent);
  fs.unlinkSync(tempPackageJsonPath);
}

function createTimestamp() {
  // YYYYMMDDHHMM
  var d = new Date();
  return d.getUTCFullYear() + // YYYY
          ('0' + (d.getUTCMonth() + 1)).slice(-2) + // MM
          ('0' + (d.getUTCDate())).slice(-2) + // DD
          ('0' + (d.getUTCHours())).slice(-2) + // HH
          ('0' + (d.getUTCMinutes())).slice(-2); // MM
}

function publishToNpm(tagName) {
  var command = `npm publish --tag=${tagName} ${process.cwd()}`;
  execSync(command);
}


function mainFunction() {
  try {
    let tagName = 'nightly';
    if (process.argv.length >= 3) {
      tagName = process.argv[2];
    }
    console.log(`Building ${tagName} ... BEGIN`);
    console.log('Backing up the original package.json');
    backupOriginalPackageJson();
    console.log('Creating the nightly version of package.json');
    createNightlyVersionInPackageJson();
    console.log('Publishing to npm');
    publishToNpm(tagName);
    console.log('Restoring original package.json');
    revertPackageJson();
    console.log(`Building ${tagName}... DONE`);
  }
  catch (ex) {
    console.log(`Something went wrong with publishing the nightly. This process modifies the package.json, so restore it before committing code! - ${ex.message}`);
    process.exit(1);
  }
}

mainFunction();

================================================
FILE: src/aot/aot-compiler.ts
================================================
import { readFileSync } from 'fs-extra';
import { extname, normalize, resolve } from 'path';

import 'reflect-metadata';

import {
  CompilerHost,
  CompilerOptions,
  DiagnosticCategory,
  ParsedCommandLine,
  Program,
  transpileModule,
  TranspileOptions,
  TranspileOutput,
  createProgram
} from 'typescript';

import { HybridFileSystem } from '../util/hybrid-file-system';
import { getInstance as getHybridFileSystem } from '../util/hybrid-file-system-factory';
import { getFileSystemCompilerHostInstance } from './compiler-host-factory';
import { FileSystemCompilerHost } from './compiler-host';
import { getFallbackMainContent, replaceBootstrapImpl } from './utils';
import { Logger } from '../logger/logger';
import { printDiagnostics, clearDiagnostics, DiagnosticsType } from '../logger/logger-diagnostics';
import { runTypeScriptDiagnostics } from '../logger/logger-typescript';
import { getTsConfig, TsConfig } from '../transpile';
import { BuildError } from '../util/errors';
import { changeExtension, readFileAsync } from '../util/helpers';
import { BuildContext, CodegenOptions, File, SemverVersion } from '../util/interfaces';

export async function runAot(context: BuildContext, options: AotOptions) {
  const tsConfig = getTsConfig(context);

  const angularCompilerOptions = Object.assign({}, {
    basePath: options.rootDir,
    genDir: options.rootDir,
    entryPoint: options.entryPoint
  });

  const aggregateCompilerOption = Object.assign(tsConfig.options, angularCompilerOptions);

  const fileSystem = getHybridFileSystem(false);
  const compilerHost = getFileSystemCompilerHostInstance(tsConfig.options);
  // todo, consider refactoring at some point
  const tsProgram = createProgram(tsConfig.fileNames, tsConfig.options, compilerHost);

  clearDiagnostics(context, DiagnosticsType.TypeScript);

  if (isNg5(context.angularVersion)) {
    await runNg5Aot(context, tsConfig, aggregateCompilerOption, compilerHost);
  } else {
    await runNg4Aot({
      angularCompilerOptions: aggregateCompilerOption,
      cliOptions: {
        i18nFile: undefined,
        i18nFormat: undefined,
        locale: undefined,
        basePath: options.rootDir,
        missingTranslation: null
      },
      program: tsProgram,
      compilerHost: compilerHost,
      compilerOptions: tsConfig.options
    });
  }

  errorCheckProgram(context, tsConfig, compilerHost, tsProgram);

  // update bootstrap in main.ts
  const mailFilePath = isNg5(context.angularVersion) ? changeExtension(options.entryPoint, '.js') : options.entryPoint;
  const mainFile = context.fileCache.get(mailFilePath);
  const modifiedBootstrapContent = replaceBootstrap(mainFile, options.appNgModulePath, options.appNgModuleClass, options);
  mainFile.content = modifiedBootstrapContent;

  if (isTranspileRequired(context.angularVersion)) {
    transpileFiles(context, tsConfig, fileSystem);
  }
}

function errorCheckProgram(context: BuildContext, tsConfig: TsConfig, compilerHost: FileSystemCompilerHost, cachedProgram: Program) {
  // Create a new Program, based on the old one. This will trigger a resolution of all
  // transitive modules, which include files that might just have been generated.
  const program = createProgram(tsConfig.fileNames, tsConfig.options, compilerHost, cachedProgram);
  const globalDiagnostics = program.getGlobalDiagnostics();
  const tsDiagnostics = program.getSyntacticDiagnostics()
                    .concat(program.getSemanticDiagnostics())
                    .concat(program.getOptionsDiagnostics());

  if (globalDiagnostics.length) {
    const diagnostics = runTypeScriptDiagnostics(context, globalDiagnostics);
    printDiagnostics(context, DiagnosticsType.TypeScript, diagnostics, true, false);
    throw new BuildError(new Error('Failed to transpile TypeScript'));
  }
  if (tsDiagnostics.length) {
    const diagnostics = runTypeScriptDiagnostics(context, tsDiagnostics);
    printDiagnostics(context, DiagnosticsType.TypeScript, diagnostics, true, false);
    throw new BuildError(new Error('Failed to transpile TypeScript'));
  }
  return program;
}

function replaceBootstrap(mainFile: File, appNgModulePath: string, appNgModuleClass: string, options: AotOptions) {
  if (!mainFile) {
    throw new BuildError(new Error(`Could not find entry point (bootstrap file) ${options.entryPoint}`));
  }
  let modifiedFileContent: string = null;
  try {
    Logger.debug('[AotCompiler] compile: Dynamically changing entry point content to AOT mode content');
    modifiedFileContent = replaceBootstrapImpl(mainFile.path, mainFile.content, appNgModulePath, appNgModuleClass);
  } catch (ex) {
    Logger.debug(`Failed to parse bootstrap: `, ex.message);
    Logger.warn(`Failed to parse and update ${options.entryPoint} content for AoT compilation.
                For now, the default fallback content will be used instead.
                Please consider updating ${options.entryPoint} with the content from the following link:
                https://github.com/ionic-team/ionic2-app-base/tree/master/src/app/main.ts`);
    modifiedFileContent = getFallbackMainContent();
  }
  return modifiedFileContent;
}

export function isTranspileRequired(angularVersion: SemverVersion) {
  return angularVersion.major <= 4;
}

export function transpileFiles(context: BuildContext, tsConfig: TsConfig, fileSystem: HybridFileSystem) {
  const tsFiles = context.fileCache.getAll().filter(file => extname(file.path) === '.ts' && file.path.indexOf('.d.ts') === -1);
  for (const tsFile of tsFiles) {
    Logger.debug(`[AotCompiler] transpileFiles: Transpiling file ${tsFile.path} ...`);
    const transpileOutput = transpileFileContent(tsFile.path, tsFile.content, tsConfig.options);
    const diagnostics = runTypeScriptDiagnostics(context, transpileOutput.diagnostics);
    if (diagnostics.length) {
      // darn, we've got some things wrong, transpile failed :(
      printDiagnostics(context, DiagnosticsType.TypeScript, diagnostics, true, true);
      throw new BuildError(new Error('Failed to transpile TypeScript'));
    }

    const jsFilePath = changeExtension(tsFile.path, '.js');
    fileSystem.addVirtualFile(jsFilePath, transpileOutput.outputText);
    fileSystem.addVirtualFile(jsFilePath + '.map', transpileOutput.sourceMapText);

    Logger.debug(`[AotCompiler] transpileFiles: Transpiling file ${tsFile.path} ... DONE`);
  }
}

function transpileFileContent(fileName: string, sourceText: string, options: CompilerOptions): TranspileOutput {
  const transpileOptions: TranspileOptions = {
    compilerOptions: options,
    fileName: fileName,
    reportDiagnostics: true
  };

  return transpileModule(sourceText, transpileOptions);
}

export function isNg5(version: SemverVersion) {
  return version.major >= 5;
}

export async function runNg4Aot(options: CodegenOptions) {
  const module = await import('@angular/compiler-cli');
  return await module.__NGTOOLS_PRIVATE_API_2.codeGen({
    angularCompilerOptions: options.angularCompilerOptions,
    basePath: options.cliOptions.basePath,
    program: options.program,
    host: options.compilerHost,
    compilerOptions: options.compilerOptions,
    i18nFile: options.cliOptions.i18nFile,
    i18nFormat: options.cliOptions.i18nFormat,
    locale: options.cliOptions.locale,
    readResource: (fileName: string) => {
      return readFileAsync(fileName);
    }
  });
}

export async function runNg5Aot(context: BuildContext, tsConfig: TsConfig, aggregateCompilerOptions: CompilerOptions, compilerHost: CompilerHost) {
  const ngTools2 = await import('@angular/compiler-cli/ngtools2');
  const angularCompilerHost = ngTools2.createCompilerHost({options: aggregateCompilerOptions, tsHost: compilerHost});
  const program = ngTools2.createProgram({
    rootNames: tsConfig.fileNames,
    options: aggregateCompilerOptions,
    host: angularCompilerHost,
    oldProgram: null
  });

  await program.loadNgStructureAsync();

  const transformations: any[] = [];

  const transformers = {
    beforeTs: transformations
  };

  const result = program.emit({ emitFlags: ngTools2.EmitFlags.Default, customTransformers: transformers });

  const tsDiagnostics = program.getTsSyntacticDiagnostics()
                                .concat(program.getTsOptionDiagnostics())
                                .concat(program.getTsSemanticDiagnostics());

  const angularDiagnostics = program.getNgStructuralDiagnostics()
                              .concat(program.getNgOptionDiagnostics());


  if (tsDiagnostics.length) {
    const diagnostics = runTypeScriptDiagnostics(context, tsDiagnostics);
    printDiagnostics(context, DiagnosticsType.TypeScript, diagnostics, true, false);
    throw new BuildError(new Error('The Angular AoT build failed. See the issues above'));
  }

  if (angularDiagnostics.length) {
    const diagnostics = runTypeScriptDiagnostics(context, angularDiagnostics as any[]);
    printDiagnostics(context, DiagnosticsType.TypeScript, diagnostics, true, false);
    throw new BuildError(new Error('The Angular AoT build failed. See the issues above'));
  }
}

export interface AotOptions {
  tsConfigPath: string;
  rootDir: string;
  entryPoint: string;
  appNgModulePath: string;
  appNgModuleClass: string;
}


================================================
FILE: src/aot/compiler-host-factory.ts
================================================
import { CompilerOptions } from 'typescript';
import { FileSystemCompilerHost } from './compiler-host';
import { getInstance as getFileSystemInstance } from '../util/hybrid-file-system-factory';

let instance: FileSystemCompilerHost = null;

export function getFileSystemCompilerHostInstance(options: CompilerOptions) {
  if (!instance) {
    instance = new FileSystemCompilerHost(options, getFileSystemInstance(false));
  }
  return instance;
}


================================================
FILE: src/aot/compiler-host.ts
================================================
import { normalize } from 'path';
import { CancellationToken, CompilerHost, CompilerOptions, createCompilerHost, ScriptTarget, SourceFile } from 'typescript';
import { VirtualFileSystem } from '../util/interfaces';
import { getTypescriptSourceFile } from '../util/typescript-utils';
import { Logger } from '../logger/logger';

export interface OnErrorFn {
  (message: string): void;
}

export class FileSystemCompilerHost implements CompilerHost {
  private diskCompilerHost: CompilerHost;

  constructor(private options: CompilerOptions, private fileSystem: VirtualFileSystem, private setParentNodes = true) {
    this.diskCompilerHost = createCompilerHost(this.options, this.setParentNodes);
  }

  fileExists(filePath: string): boolean {
    filePath = normalize(filePath);
    const fileContent = this.fileSystem.getFileContent(filePath);
    if (fileContent) {
      return true;
    }
    return this.diskCompilerHost.fileExists(filePath);
  }

  readFile(filePath: string): string {
    filePath = normalize(filePath);
    const fileContent = this.fileSystem.getFileContent(filePath);
    if (fileContent) {
      return fileContent;
    }
    return this.diskCompilerHost.readFile(filePath);
  }

  directoryExists(directoryPath: string): boolean {
    directoryPath = normalize(directoryPath);
    const stats = this.fileSystem.getDirectoryStats(directoryPath);
    if (stats) {
      return true;
    }
    return this.diskCompilerHost.directoryExists(directoryPath);
  }

  getFiles(directoryPath: string): string[] {
    directoryPath = normalize(directoryPath);
    return this.fileSystem.getFileNamesInDirectory(directoryPath);
  }

  getDirectories(directoryPath: string): string[] {
    directoryPath = normalize(directoryPath);
    const subdirs = this.fileSystem.getSubDirs(directoryPath);

    let delegated: string[];
    try {
      delegated = this.diskCompilerHost.getDirectories(directoryPath);
    } catch (e) {
      delegated = [];
    }
    return delegated.concat(subdirs);
  }

  getSourceFile(filePath: string, languageVersion: ScriptTarget, onError?: OnErrorFn) {
    filePath = normalize(filePath);
    // we haven't created a source file for this yet, so try to use what's in memory
    const fileContentFromMemory = this.fileSystem.getFileContent(filePath);
    if (fileContentFromMemory) {
      const typescriptSourceFile = getTypescriptSourceFile(filePath, fileContentFromMemory, languageVersion, this.setParentNodes);
      return typescriptSourceFile;
    }
    const diskSourceFile = this.diskCompilerHost.getSourceFile(filePath, languageVersion, onError);
    return diskSourceFile;
  }

  getCancellationToken(): CancellationToken {
    return this.diskCompilerHost.getCancellationToken();
  }

  getDefaultLibFileName(options: CompilerOptions) {
    return this.diskCompilerHost.getDefaultLibFileName(options);
  }

  writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: OnErrorFn) {
    fileName = normalize(fileName);
    Logger.debug(`[NgcCompilerHost] writeFile: adding ${fileName} to virtual file system`);
    this.fileSystem.addVirtualFile(fileName, data);
  }

  getCurrentDirectory(): string {
    return this.diskCompilerHost.getCurrentDirectory();
  }

  getCanonicalFileName(fileName: string): string {
    return this.diskCompilerHost.getCanonicalFileName(fileName);
  }

  useCaseSensitiveFileNames(): boolean {
    return this.diskCompilerHost.useCaseSensitiveFileNames();
  }

  getNewLine(): string {
    return this.diskCompilerHost.getNewLine();
  }
}


================================================
FILE: src/aot/utils.ts
================================================
import { basename, dirname, join, normalize, relative, resolve } from 'path';
import {
  CallExpression,
  Identifier,
  PropertyAccessExpression,
  SyntaxKind,
  ScriptTarget
} from 'typescript';

import { appendBefore, checkIfFunctionIsCalled, getTypescriptSourceFile, findNodes, insertNamedImportIfNeeded, replaceImportModuleSpecifier, replaceNamedImport, replaceNode } from '../util/typescript-utils';

export function getFallbackMainContent() {
  return `
import { platformBrowser } from '@angular/platform-browser';
import { enableProdMode } from '@angular/core';

import { AppModuleNgFactory } from './app.module.ngfactory';

enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);`;
}

function getBootstrapNodes(allCalls: CallExpression[]) {
  return allCalls
    .filter(call => call.expression.kind === SyntaxKind.PropertyAccessExpression)
    .map(call => call.expression as PropertyAccessExpression)
    .filter(access => {
      return access.name.kind === SyntaxKind.Identifier
          && access.name.text === 'bootstrapModule';
    });
}

function replaceNgModuleClassName(filePath: string, fileContent: string, className: string) {
  const sourceFile = getTypescriptSourceFile(filePath, fileContent, ScriptTarget.Latest, false);
  const allCalls = findNodes(sourceFile, sourceFile, SyntaxKind.CallExpression, true) as CallExpression[];
  const bootstraps = getBootstrapNodes(allCalls);
  let modifiedContent = fileContent;
  allCalls.filter(call => bootstraps.some(bs => bs === call.expression)).forEach((call: CallExpression) => {
    modifiedContent = replaceNode(filePath, modifiedContent, call.arguments[0], className + 'NgFactory');
  });
  return modifiedContent;
}

function replacePlatformBrowser(filePath: string, fileContent: string) {
  const sourceFile = getTypescriptSourceFile(filePath, fileContent, ScriptTarget.Latest, false);
  const allCalls = findNodes(sourceFile, sourceFile, SyntaxKind.CallExpression, true) as CallExpression[];
  const bootstraps = getBootstrapNodes(allCalls);
  const calls: CallExpression[] = bootstraps.reduce((previous, access) => {
      const expressions = findNodes(sourceFile, access, SyntaxKind.CallExpression, true) as CallExpression[];
      return previous.concat(expressions);
    }, [])
    .filter((call: CallExpression) => {
      return call.expression.kind === SyntaxKind.Identifier
          && (call.expression as Identifier).text === 'platformBrowserDynamic';
    });
  let modifiedContent = fileContent;
  calls.forEach(call => {
    modifiedContent = replaceNode(filePath, modifiedContent, call.expression, 'platformBrowser');
  });
  return modifiedContent;
}

function checkForPlatformDynamicBrowser(filePath: string, fileContent: string) {
  const sourceFile = getTypescriptSourceFile(filePath, fileContent, ScriptTarget.Latest, false);
  const allCalls = findNodes(sourceFile, sourceFile, SyntaxKind.CallExpression, true) as CallExpression[];
  const bootstraps = getBootstrapNodes(allCalls);
  const calls: CallExpression[] = bootstraps.reduce((previous, access) => {
      const expressions = findNodes(sourceFile, access, SyntaxKind.CallExpression, true) as CallExpression[];
      return previous.concat(expressions);
    }, [])
    .filter((call: CallExpression) => {
      return call.expression.kind === SyntaxKind.Identifier
          && (call.expression as Identifier).text === 'platformBrowserDynamic';
    });
  return calls && calls.length;
}

function replaceBootstrapModuleFactory(filePath: string, fileContent: string) {
  const sourceFile = getTypescriptSourceFile(filePath, fileContent, ScriptTarget.Latest, false);
  const allCalls = findNodes(sourceFile, sourceFile, SyntaxKind.CallExpression, true) as CallExpression[];
  const bootstraps = getBootstrapNodes(allCalls);
  let modifiedContent = fileContent;
  bootstraps.forEach((bs: PropertyAccessExpression) => {
    modifiedContent = replaceNode(filePath, modifiedContent, bs.name, 'bootstrapModuleFactory');
  });
  return modifiedContent;
}

function getPlatformBrowserFunctionNode(filePath: string, fileContent: string) {
  let modifiedFileContent = fileContent;
  const sourceFile = getTypescriptSourceFile(filePath, modifiedFileContent, ScriptTarget.Latest, false);
  const allCalls = findNodes(sourceFile, sourceFile, SyntaxKind.CallExpression, true) as CallExpression[];
  const callsToPlatformBrowser = allCalls.filter(call => call.expression && call.expression.kind === SyntaxKind.Identifier && (call.expression as Identifier).text === 'platformBrowser');
  const toAppend = `enableProdMode();\n`;
  if (callsToPlatformBrowser.length) {
    modifiedFileContent = appendBefore(filePath, modifiedFileContent, callsToPlatformBrowser[0].expression, toAppend);
  } else {
    // just throw it at the bottom
    modifiedFileContent += toAppend;
  }
  return modifiedFileContent;
}

function importAndEnableProdMode(filePath: string, fileContent: string) {
  let modifiedFileContent = fileContent;
  modifiedFileContent = insertNamedImportIfNeeded(filePath, modifiedFileContent, 'enableProdMode', '@angular/core');

  const isCalled = checkIfFunctionIsCalled(filePath, modifiedFileContent, 'enableProdMode');
  if (!isCalled) {
    // go ahead and insert this
    modifiedFileContent = getPlatformBrowserFunctionNode(filePath, modifiedFileContent);
  }

  return modifiedFileContent;
}

export function replaceBootstrapImpl(filePath: string, fileContent: string, appNgModulePath: string, appNgModuleClassName: string) {
  if (!fileContent.match(/\bbootstrapModule\b/)) {
    throw new Error(`Could not find bootstrapModule in ${filePath}`);
  }

  const withoutExtension = join(dirname(appNgModulePath), basename(appNgModulePath, '.ts'));
  const appModuleAbsoluteFileName = normalize(resolve(withoutExtension));
  const withNgFactory = appModuleAbsoluteFileName + '.ngfactory';
  const originalImport = './' + relative(dirname(filePath), appModuleAbsoluteFileName);
  const ngFactryImport = './' + relative(dirname(filePath), withNgFactory);

  if (!checkForPlatformDynamicBrowser(filePath, fileContent)) {
    throw new Error(`Could not find any references to "platformBrowserDynamic" in ${filePath}`);
  }

  let modifiedFileContent = fileContent;
  modifiedFileContent = replaceNgModuleClassName(filePath, modifiedFileContent, appNgModuleClassName);
  modifiedFileContent = replacePlatformBrowser(filePath, modifiedFileContent);
  modifiedFileContent = replaceBootstrapModuleFactory(filePath, modifiedFileContent);

  modifiedFileContent = replaceNamedImport(filePath, modifiedFileContent, 'platformBrowserDynamic', 'platformBrowser');
  modifiedFileContent = replaceNamedImport(filePath, modifiedFileContent, appNgModuleClassName, appNgModuleClassName + 'NgFactory');
  modifiedFileContent = replaceImportModuleSpecifier(filePath, modifiedFileContent, '@angular/platform-browser-dynamic', '@angular/platform-browser');
  modifiedFileContent = replaceImportModuleSpecifier(filePath, modifiedFileContent, originalImport, ngFactryImport);

  // check if prod mode is imported and enabled
  modifiedFileContent = importAndEnableProdMode(filePath, modifiedFileContent);

  return modifiedFileContent;
}


================================================
FILE: src/build/util.ts
================================================
import { join } from 'path';

import { getTsConfigAsync, TsConfig } from '../transpile';
import * as Constants from '../util/constants';
import { BuildError } from '../util/errors';
import { GlobResult, globAll } from '../util/glob-util';
import { getBooleanPropertyValue, getStringPropertyValue, readFileAsync, readJsonAsync, semverStringToObject } from '../util/helpers';
import { BuildContext, } from '../util/interfaces';

export function scanSrcTsFiles(context: BuildContext) {
  const srcGlob = join(context.srcDir, '**', '*.ts');
  const globs: string[] = [srcGlob];
  const deepLinkDir = getStringPropertyValue(Constants.ENV_VAR_DEEPLINKS_DIR);
  // these two will only not be equal in some weird cases like for building Ionic's demos with our current repository set-up
  if (deepLinkDir !== context.srcDir) {
    globs.push(join(deepLinkDir, '**', '*.ts'));
  }
  return globAll(globs).then((results: GlobResult[]) => {
    const promises = results.map(result => {
      const promise = readFileAsync(result.absolutePath);
      promise.then((fileContent: string) => {
        context.fileCache.set(result.absolutePath, { path: result.absolutePath, content: fileContent});
      });
      return promise;
    });
    return Promise.all(promises);
  });
}


export function validateTsConfigSettings(tsConfigFileContents: TsConfig) {
  return new Promise((resolve, reject) => {
    try {
      const isValid = tsConfigFileContents.options &&
        tsConfigFileContents.options.sourceMap === true;
      if (!isValid) {
        const error = new BuildError(['The "tsconfig.json" file must have compilerOptions.sourceMap set to true.',
          'For more information please see the default Ionic project tsconfig.json file here:',
          'https://github.com/ionic-team/ionic2-app-base/blob/master/tsconfig.json'].join('\n'));
        error.isFatal = true;
        return reject(error);
      }
      resolve();
    } catch (e) {
      const error = new BuildError('The "tsconfig.json" file contains malformed JSON.');
      error.isFatal = true;
      return reject(error);
    }
  });
}

export function validateRequiredFilesExist(context: BuildContext) {
  return Promise.all([
    readFileAsync(process.env[Constants.ENV_APP_ENTRY_POINT]),
    getTsConfigAsync(context, process.env[Constants.ENV_TS_CONFIG])
  ]).catch((error) => {
    if (error.code === 'ENOENT' && error.path === process.env[Constants.ENV_APP_ENTRY_POINT]) {
      error = new BuildError(`${error.path} was not found. The "main.dev.ts" and "main.prod.ts" files have been deprecated. Please create a new file "main.ts" containing the content of "main.dev.ts", and then delete the deprecated files.
                            For more information, please see the default Ionic project main.ts file here:
                            https://github.com/ionic-team/ionic2-app-base/tree/master/src/app/main.ts`);
      error.isFatal = true;
      throw error;
    }
    if (error.code === 'ENOENT' && error.path === process.env[Constants.ENV_TS_CONFIG]) {
      error = new BuildError([`${error.path} was not found. The "tsconfig.json" file is missing. This file is required.`,
        'For more information please see the default Ionic project tsconfig.json file here:',
        'https://github.com/ionic-team/ionic2-app-base/blob/master/tsconfig.json'].join('\n'));
      error.isFatal = true;
      throw error;
    }
    error.isFatal = true;
    throw error;
  });
}

export async function readVersionOfDependencies(context: BuildContext) {
  // read the package.json version from ionic, angular/core, and typescript
  const promises: Promise<any>[] = [];
  promises.push(readPackageVersion(context.angularCoreDir));
  if (!getBooleanPropertyValue(Constants.ENV_SKIP_IONIC_ANGULAR_VERSION)) {
    promises.push(readPackageVersion(context.ionicAngularDir));
  }
  promises.push(readPackageVersion(context.typescriptDir));

  const versions = await Promise.all(promises);
  context.angularVersion = semverStringToObject(versions[0]);
  if (!getBooleanPropertyValue(Constants.ENV_SKIP_IONIC_ANGULAR_VERSION)) {
    context.ionicAngularVersion = semverStringToObject(versions[1]);
  }
  // index could be 1 or 2 depending on if you read ionic-angular, its always the last one bro
  context.typescriptVersion = semverStringToObject(versions[versions.length - 1]);
}

export async function readPackageVersion(packageDir: string) {
  const packageJsonPath = join(packageDir, 'package.json');
  const packageObject = await readJsonAsync(packageJsonPath);
  return packageObject['version'];
}


================================================
FILE: src/build.spec.ts
================================================
import * as Constants from './util/constants';
import { BuildContext } from './util/interfaces';
import * as helpers from './util/helpers';
import * as build from './build';
import * as buildUtils from './build/util';

import * as bundle from './bundle';
import * as copy from './copy';
import * as clean from './clean';
import * as deepLinking from './deep-linking';
import * as lint from './lint';
import * as minify from './minify';
import * as ngc from './ngc';
import * as postprocess from './postprocess';
import * as preprocess from './preprocess';
import * as sass from './sass';
import * as transpile from './transpile';

describe('build', () => {
  beforeEach(() => {
    spyOn(clean, 'clean');
    spyOn(helpers, helpers.readFileAsync.name).and.returnValue(Promise.resolve());
    spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => {
      return Promise.resolve({
        'options': {
          'sourceMap': true
        }
      });
    });

    spyOn(buildUtils, buildUtils.scanSrcTsFiles.name).and.returnValue(Promise.resolve());
    spyOn(buildUtils, buildUtils.validateRequiredFilesExist.name).and.returnValue(Promise.resolve(['fileOneContent', 'fileTwoContent']));
    spyOn(buildUtils, buildUtils.validateTsConfigSettings.name).and.returnValue(Promise.resolve());
    spyOn(buildUtils, buildUtils.readVersionOfDependencies.name).and.returnValue(Promise.resolve());
    spyOn(bundle, bundle.bundle.name).and.returnValue(Promise.resolve());
    spyOn(copy, copy.copy.name).and.returnValue(Promise.resolve());
    spyOn(deepLinking, deepLinking.deepLinking.name).and.returnValue(Promise.resolve());
    spyOn(minify, minify.minifyCss.name).and.returnValue(Promise.resolve());
    spyOn(minify, minify.minifyJs.name).and.returnValue(Promise.resolve());
    spyOn(lint, lint.lint.name).and.returnValue(Promise.resolve());
    spyOn(ngc, ngc.ngc.name).and.returnValue(Promise.resolve());
    spyOn(postprocess, postprocess.postprocess.name).and.returnValue(Promise.resolve());
    spyOn(preprocess, preprocess.preprocess.name).and.returnValue(Promise.resolve());
    spyOn(sass, sass.sass.name).and.returnValue(Promise.resolve());
    spyOn(transpile, transpile.transpile.name).and.returnValue(Promise.resolve());
  });

  it('should do a prod build', () => {
    let context: BuildContext = {
      isProd: true,
      optimizeJs: true,
      runMinifyJs: true,
      runMinifyCss: true,
      runAot: true
    };

    const getBooleanPropertyValueSpy = spyOn(helpers, helpers.getBooleanPropertyValue.name).and.returnValue(true);

    return build.build(context).then(() => {
      expect(buildUtils.scanSrcTsFiles).toHaveBeenCalled();
      expect(copy.copy).toHaveBeenCalled();
      expect(deepLinking.deepLinking).toHaveBeenCalled();
      expect(ngc.ngc).toHaveBeenCalled();
      expect(bundle.bundle).toHaveBeenCalled();
      expect(minify.minifyJs).toHaveBeenCalled();
      expect(sass.sass).toHaveBeenCalled();
      expect(minify.minifyCss).toHaveBeenCalled();
      expect(lint.lint).toHaveBeenCalled();
      expect(getBooleanPropertyValueSpy.calls.all()[1].args[0]).toEqual(Constants.ENV_ENABLE_LINT);

      expect(transpile.transpile).not.toHaveBeenCalled();
    });
  });

  it('should do a dev build', () => {
    let context: BuildContext = {
      isProd: false,
      optimizeJs: false,
      runMinifyJs: false,
      runMinifyCss: false,
      runAot: false
    };

    const getBooleanPropertyValueSpy = spyOn(helpers, helpers.getBooleanPropertyValue.name).and.returnValue(true);

    return build.build(context).then(() => {
      expect(buildUtils.scanSrcTsFiles).toHaveBeenCalled();
      expect(copy.copy).toHaveBeenCalled();
      expect(deepLinking.deepLinking).toHaveBeenCalled();
      expect(transpile.transpile).toHaveBeenCalled();
      expect(bundle.bundle).toHaveBeenCalled();
      expect(sass.sass).toHaveBeenCalled();
      expect(lint.lint).toHaveBeenCalled();
      expect(getBooleanPropertyValueSpy.calls.all()[1].args[0]).toEqual(Constants.ENV_ENABLE_LINT);
      expect(postprocess.postprocess).toHaveBeenCalled();
      expect(preprocess.preprocess).toHaveBeenCalled();
      expect(ngc.ngc).not.toHaveBeenCalled();
      expect(minify.minifyJs).not.toHaveBeenCalled();
      expect(minify.minifyCss).not.toHaveBeenCalled();
    });
  });

  it('should skip lint', () => {
    let context: BuildContext = {
      isProd: false,
      optimizeJs: false,
      runMinifyJs: false,
      runMinifyCss: false,
      runAot: false
    };

    const getBooleanPropertyValueSpy = spyOn(helpers, helpers.getBooleanPropertyValue.name).and.returnValue(false);

    return build.build(context).then(() => {
      expect(buildUtils.scanSrcTsFiles).toHaveBeenCalled();
      expect(copy.copy).toHaveBeenCalled();
      expect(transpile.transpile).toHaveBeenCalled();
      expect(bundle.bundle).toHaveBeenCalled();
      expect(sass.sass).toHaveBeenCalled();
      expect(lint.lint).not.toHaveBeenCalled();
      expect(getBooleanPropertyValueSpy.calls.all()[1].args[0]).toEqual(Constants.ENV_ENABLE_LINT);
      expect(postprocess.postprocess).toHaveBeenCalled();
      expect(preprocess.preprocess).toHaveBeenCalled();
      expect(ngc.ngc).not.toHaveBeenCalled();
      expect(minify.minifyJs).not.toHaveBeenCalled();
      expect(minify.minifyCss).not.toHaveBeenCalled();
    });
  });
});

describe('test project requirements before building', () => {
  it('should fail if APP_ENTRY_POINT file does not exist', () => {
    process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts';
    process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js';
    const error = new Error('App entry point was not found');

    spyOn(helpers, 'readFileAsync').and.returnValue(Promise.reject(error));

    return build.build({}).catch((e) => {
      expect(helpers.readFileAsync).toHaveBeenCalledTimes(1);
      expect(e).toEqual(error);
    });
  });

  it('should fail if IONIC_TS_CONFIG file does not exist', () => {
    process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts';
    process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js';
    const error = new Error('Config was not found');

    spyOn(helpers, helpers.readFileAsync.name).and.returnValues(Promise.resolve());
    spyOn(transpile, transpile.getTsConfigAsync.name).and.returnValues(Promise.reject(error));

    return build.build({}).catch((e) => {
      expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1);
      expect(helpers.readFileAsync).toHaveBeenCalledTimes(1);
      expect(e).toEqual(error);
    });
  });

  it('should fail fataly if IONIC_TS_CONFIG file does not contain valid JSON', () => {
    process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts';
    process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js';
    spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => {
      return Promise.resolve(`{
        "options" {
          "sourceMap": false
        }
      }
      `);
    });
    spyOn(buildUtils, buildUtils.scanSrcTsFiles.name).and.returnValue(Promise.resolve());
    spyOn(buildUtils, buildUtils.readVersionOfDependencies.name).and.returnValue(Promise.resolve());

    return build.build({}).catch((e) => {
      expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1);
      expect(e.isFatal).toBeTruthy();
    });
  });

  it('should fail fataly if IONIC_TS_CONFIG file does not contain compilerOptions.sourceMap === true', () => {
    process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts';
    process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js';
    spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => {
      return Promise.resolve(`{
        "options": {
          "sourceMap": false
        }
      }
      `);
    });
    spyOn(buildUtils, buildUtils.scanSrcTsFiles.name).and.returnValue(Promise.resolve());
    spyOn(buildUtils, buildUtils.readVersionOfDependencies.name).and.returnValue(Promise.resolve());

    return build.build({}).catch((e) => {
      expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1);
      expect(e.isFatal).toBeTruthy();
    });
  });
});


================================================
FILE: src/build.ts
================================================
import { join } from 'path';

import {
  readVersionOfDependencies,
  scanSrcTsFiles,
  validateRequiredFilesExist,
  validateTsConfigSettings
} from './build/util';


import { bundle, bundleUpdate } from './bundle';
import { clean } from './clean';
import { copy } from './copy';
import { deepLinking, deepLinkingUpdate } from './deep-linking';
import { lint, lintUpdate } from './lint';
import { Logger } from './logger/logger';
import { minifyCss, minifyJs } from './minify';
import { ngc } from './ngc';
import { getTsConfigAsync, TsConfig } from './transpile';
import { postprocess } from './postprocess';
import { preprocess, preprocessUpdate } from './preprocess';
import { sass, sassUpdate } from './sass';
import { templateUpdate } from './template';
import { transpile, transpileUpdate, transpileDiagnosticsOnly } from './transpile';
import * as Constants from './util/constants';
import { BuildError } from './util/errors';
import { emit, EventType } from './util/events';
import { getBooleanPropertyValue, readFileAsync, setContext } from './util/helpers';
import { BuildContext, BuildState, BuildUpdateMessage, ChangedFile } from './util/interfaces';

export function build(context: BuildContext) {
  setContext(context);
  const logger = new Logger(`build ${(context.isProd ? 'prod' : 'dev')}`);

  return buildWorker(context)
    .then(() => {
      // congrats, we did it!  (•_•) / ( •_•)>⌐■-■ / (⌐■_■)
      logger.finish();
    })
    .catch(err => {
      if (err.isFatal) { throw err; }
      throw logger.fail(err);
    });
}

async function buildWorker(context: BuildContext) {
  const promises: Promise<any>[] = [];
  promises.push(validateRequiredFilesExist(context));
  promises.push(readVersionOfDependencies(context));
  const results = await Promise.all(promises);
  const tsConfigContents = results[0][1];
  await validateTsConfigSettings(tsConfigContents);
  await buildProject(context);

}

function buildProject(context: BuildContext) {
  // sync empty the www/build directory
  clean(context);

  buildId++;

  const copyPromise = copy(context);

  return scanSrcTsFiles(context)
    .then(() => {
      if (getBooleanPropertyValue(Constants.ENV_PARSE_DEEPLINKS)) {
        return deepLinking(context);
      }
    })
    .then(() => {
      const compilePromise = (context.runAot) ? ngc(context) : transpile(context);
      return compilePromise;
    })
    .then(() => {
      return preprocess(context);
    })
    .then(() => {
      return bundle(context);
    })
    .then(() => {
      const minPromise = (context.runMinifyJs) ? minifyJs(context) : Promise.resolve();
      const sassPromise = sass(context)
        .then(() => {
          return (context.runMinifyCss) ? minifyCss(context) : Promise.resolve();
        });

      return Promise.all([
        minPromise,
        sassPromise,
        copyPromise
      ]);
    })
    .then(() => {
      return postprocess(context);
    })
    .then(() => {
      if (getBooleanPropertyValue(Constants.ENV_ENABLE_LINT)) {
        // kick off the tslint after everything else
        // nothing needs to wait on its completion unless bailing on lint error is enabled
        const result = lint(context, null, false);
        if (getBooleanPropertyValue(Constants.ENV_BAIL_ON_LINT_ERROR)) {
          return result;
        }
      }
    })
    .catch(err => {
      throw new BuildError(err);
    });
}

export function buildUpdate(changedFiles: ChangedFile[], context: BuildContext) {
  return new Promise(resolve => {
    const logger = new Logger('build');

    buildId++;

    const buildUpdateMsg: BuildUpdateMessage = {
      buildId: buildId,
      reloadApp: false
    };
    emit(EventType.BuildUpdateStarted, buildUpdateMsg);

    function buildTasksDone(resolveValue: BuildTaskResolveValue) {
      // all build tasks have been resolved or one of them
      // bailed early, stopping all others to not run

      parallelTasksPromise.then(() => {
        // all parallel tasks are also done
        // so now we're done done
        const buildUpdateMsg: BuildUpdateMessage = {
          buildId: buildId,
          reloadApp: resolveValue.requiresAppReload
        };
        emit(EventType.BuildUpdateCompleted, buildUpdateMsg);

        if (!resolveValue.requiresAppReload) {
          // just emit that only a certain file changed
          // this one is useful when only a sass changed happened
          // and the webpack only needs to livereload the css
          // but does not need to do a full page refresh
          emit(EventType.FileChange, resolveValue.changedFiles);
        }

        let requiresLintUpdate = false;
        for (const changedFile of changedFiles) {
          if (changedFile.ext === '.ts') {
            if (changedFile.event === 'change' || changedFile.event === 'add') {
              requiresLintUpdate = true;
              break;
            }
          }
        }
        if (requiresLintUpdate) {
          // a ts file changed, so let's lint it too, however
          // this task should run as an after thought
          if (getBooleanPropertyValue(Constants.ENV_ENABLE_LINT)) {
            lintUpdate(changedFiles, context, false);
          }
        }

        logger.finish('green', true);
        Logger.newLine();

        // we did it!
        resolve();
      });
    }

    // kick off all the build tasks
    // and the tasks that can run parallel to all the build tasks
    const buildTasksPromise = buildUpdateTasks(changedFiles, context);
    const parallelTasksPromise = buildUpdateParallelTasks(changedFiles, context);

    // whether it was resolved or rejected, we need to do the same thing
    buildTasksPromise
      .then(buildTasksDone)
      .catch(() => {
        buildTasksDone({
          requiresAppReload: false,
          changedFiles: changedFiles
        });
      });
  });
}

/**
 * Collection of all the build tasks than need to run
 * Each task will only run if it's set with eacn BuildState.
 */
function buildUpdateTasks(changedFiles: ChangedFile[], context: BuildContext) {
  const resolveValue: BuildTaskResolveValue = {
    requiresAppReload: false,
    changedFiles: []
  };

  return loadFiles(changedFiles, context)
    .then(() => {
      // DEEP LINKING
      if (getBooleanPropertyValue(Constants.ENV_PARSE_DEEPLINKS)) {
        return deepLinkingUpdate(changedFiles, context);
      }
    })
    .then(() => {
      // TEMPLATE
      if (context.templateState === BuildState.RequiresUpdate) {
        resolveValue.requiresAppReload = true;
        return templateUpdate(changedFiles, context);
      }
      // no template updates required
      return Promise.resolve();

    })
    .then(() => {
      // TRANSPILE
      if (context.transpileState === BuildState.RequiresUpdate) {
        resolveValue.requiresAppReload = true;
        // we've already had a successful transpile once, only do an update
        // not that we've also already started a transpile diagnostics only
        // build that only needs to be completed by the end of buildUpdate
        return transpileUpdate(changedFiles, context);

      } else if (context.transpileState === BuildState.RequiresBuild) {
        // run the whole transpile
        resolveValue.requiresAppReload = true;
        return transpile(context);
      }
      // no transpiling required
      return Promise.resolve();

    })
    .then(() => {
      // PREPROCESS
      return preprocessUpdate(changedFiles, context);
    })
    .then(() => {
      // BUNDLE
      if (context.bundleState === BuildState.RequiresUpdate) {
        // we need to do a bundle update
        resolveValue.requiresAppReload = true;
        return bundleUpdate(changedFiles, context);

      } else if (context.bundleState === BuildState.RequiresBuild) {
        // we need to do a full bundle build
        resolveValue.requiresAppReload = true;
        return bundle(context);
      }
      // no bundling required
      return Promise.resolve();

    })
    .then(() => {
      // SASS
      if (context.sassState === BuildState.RequiresUpdate) {
        // we need to do a sass update
        return sassUpdate(changedFiles, context).then(outputCssFile => {
          const changedFile: ChangedFile = {
            event: Constants.FILE_CHANGE_EVENT,
            ext: '.css',
            filePath: outputCssFile
          };

          context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile });

          resolveValue.changedFiles.push(changedFile);
        });

      } else if (context.sassState === BuildState.RequiresBuild) {
        // we need to do a full sass build
        return sass(context).then(outputCssFile => {
          const changedFile: ChangedFile = {
            event: Constants.FILE_CHANGE_EVENT,
            ext: '.css',
            filePath: outputCssFile
          };

          context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile });

          resolveValue.changedFiles.push(changedFile);
        });
      }
      // no sass build required
      return Promise.resolve();
    })
    .then(() => {
      return resolveValue;
    });
}

function loadFiles(changedFiles: ChangedFile[], context: BuildContext) {
  // UPDATE IN-MEMORY FILE CACHE
  let promises: Promise<any>[] = [];
  for (const changedFile of changedFiles) {
    if (changedFile.event === Constants.FILE_DELETE_EVENT) {
      // remove from the cache on delete
      context.fileCache.remove(changedFile.filePath);
    } else {
      // load the latest since the file changed
      const promise = readFileAsync(changedFile.filePath);
      promises.push(promise);
      promise.then((content: string) => {
        context.fileCache.set(changedFile.filePath, { path: changedFile.filePath, content: content });
      });
    }
  }

  return Promise.all(promises);
}

interface BuildTaskResolveValue {
  requiresAppReload: boolean;
  changedFiles: ChangedFile[];
}

/**
 * parallelTasks are for any tasks that can run parallel to the entire
 * build, but we still need to make sure they've completed before we're
 * all done, it's also possible there are no parallelTasks at all
 */
function buildUpdateParallelTasks(changedFiles: ChangedFile[], context: BuildContext) {
  const parallelTasks: Promise<any>[] = [];

  if (context.transpileState === BuildState.RequiresUpdate) {
    parallelTasks.push(transpileDiagnosticsOnly(context));
  }

  return Promise.all(parallelTasks);
}

let buildId = 0;


================================================
FILE: src/bundle.spec.ts
================================================
import * as bundle from './bundle';
import * as webpack from './webpack';
import * as Constants from './util/constants';
import { ChangedFile } from './util/interfaces';

describe('bundle task', () => {

  describe('bundle', () => {

    it('should return the value webpack task returns', () => {
      // arrange
      spyOn(webpack, webpack.webpack.name).and.returnValue(Promise.resolve());
      const context = { bundler: Constants.BUNDLER_WEBPACK};

      // act
      return bundle.bundle(context).then(() => {
        // assert
        expect(webpack.webpack).toHaveBeenCalled();
      });
    });

    it('should throw when webpack throws', () => {
      const errorText = 'simulating an error';
      // arrange
      spyOn(webpack, webpack.webpack.name).and.returnValue(Promise.reject(new Error(errorText)));
      const context = { bundler: Constants.BUNDLER_WEBPACK};

      // act
      return bundle.bundle(context).then(() => {
        throw ne
Download .txt
gitextract_525rclba/

├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .npmrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bin/
│   ├── ion-dev.js
│   └── ionic-app-scripts.js
├── circle.yml
├── config/
│   ├── cleancss.config.js
│   ├── copy.config.js
│   ├── sass.config.js
│   ├── uglifyjs.config.js
│   ├── watch.config.js
│   └── webpack.config.js
├── lab/
│   ├── index.html
│   └── static/
│       ├── css/
│       │   └── style.css
│       └── js/
│           └── lab.js
├── package.json
├── preprocessor.js
├── scripts/
│   ├── commit-changelog.js
│   ├── create-github-release.js
│   └── publish-nightly.js
├── src/
│   ├── aot/
│   │   ├── aot-compiler.ts
│   │   ├── compiler-host-factory.ts
│   │   ├── compiler-host.ts
│   │   └── utils.ts
│   ├── build/
│   │   └── util.ts
│   ├── build.spec.ts
│   ├── build.ts
│   ├── bundle.spec.ts
│   ├── bundle.ts
│   ├── clean.spec.ts
│   ├── clean.ts
│   ├── cleancss.spec.ts
│   ├── cleancss.ts
│   ├── copy.spec.ts
│   ├── copy.ts
│   ├── core/
│   │   ├── bundle-components.ts
│   │   ├── inject-script.spec.ts
│   │   ├── inject-scripts.ts
│   │   ├── ionic-global.spec.ts
│   │   └── ionic-global.ts
│   ├── declarations.d.ts
│   ├── deep-linking/
│   │   ├── util.spec.ts
│   │   └── util.ts
│   ├── deep-linking.spec.ts
│   ├── deep-linking.ts
│   ├── dev-client/
│   │   └── sass/
│   │       ├── _code-block.scss
│   │       ├── _diagnostics.scss
│   │       ├── _header.scss
│   │       ├── _options-menu.scss
│   │       ├── _stack-block.scss
│   │       ├── _system-info.scss
│   │       ├── _toast.scss
│   │       └── ion-dev.scss
│   ├── dev-server/
│   │   ├── http-server.ts
│   │   ├── injector.ts
│   │   ├── lab.ts
│   │   ├── live-reload.ts
│   │   ├── notification-server.ts
│   │   └── serve-config.ts
│   ├── generators/
│   │   ├── constants.ts
│   │   ├── util.spec.ts
│   │   └── util.ts
│   ├── generators.ts
│   ├── highlight/
│   │   ├── github-gist.scss
│   │   ├── highlight.spec.ts
│   │   └── highlight.ts
│   ├── index.ts
│   ├── lint/
│   │   ├── lint-factory.spec.ts
│   │   ├── lint-factory.ts
│   │   ├── lint-utils.spec.ts
│   │   └── lint-utils.ts
│   ├── lint.spec.ts
│   ├── lint.ts
│   ├── logger/
│   │   ├── logger-diagnostics.ts
│   │   ├── logger-runtime.ts
│   │   ├── logger-sass.ts
│   │   ├── logger-tslint.ts
│   │   ├── logger-typescript.ts
│   │   └── logger.ts
│   ├── minify.ts
│   ├── mocks/
│   │   └── mock-helpers.ts
│   ├── ngc.ts
│   ├── optimization/
│   │   ├── remove-unused-fonts.spec.ts
│   │   └── remove-unused-fonts.ts
│   ├── postprocess.ts
│   ├── preprocess.spec.ts
│   ├── preprocess.ts
│   ├── sass.ts
│   ├── serve.spec.ts
│   ├── serve.ts
│   ├── template.spec.ts
│   ├── template.ts
│   ├── transpile-worker.ts
│   ├── transpile.spec.ts
│   ├── transpile.ts
│   ├── uglifyjs.ts
│   ├── upgrade-scripts/
│   │   ├── add-default-ngmodules.spec.ts
│   │   └── add-default-ngmodules.ts
│   ├── util/
│   │   ├── clean-css-factory.ts
│   │   ├── config.spec.ts
│   │   ├── config.ts
│   │   ├── constants.ts
│   │   ├── cordova-config.spec.ts
│   │   ├── cordova-config.ts
│   │   ├── errors.spec.ts
│   │   ├── errors.ts
│   │   ├── events.ts
│   │   ├── file-cache.ts
│   │   ├── glob-util.ts
│   │   ├── helpers/
│   │   │   ├── camel-case-regexp.ts
│   │   │   ├── camel-case-upper-regexp.ts
│   │   │   └── non-word-regexp.ts
│   │   ├── helpers.spec.ts
│   │   ├── helpers.ts
│   │   ├── hybrid-file-system-factory.ts
│   │   ├── hybrid-file-system.ts
│   │   ├── interfaces.ts
│   │   ├── ionic-project.ts
│   │   ├── network.ts
│   │   ├── open.ts
│   │   ├── promisify.ts
│   │   ├── source-maps.spec.ts
│   │   ├── source-maps.ts
│   │   ├── typescript-utils.spec.ts
│   │   ├── typescript-utils.ts
│   │   └── virtual-file-utils.ts
│   ├── watch.spec.ts
│   ├── watch.ts
│   ├── webpack/
│   │   ├── cache-loader-impl.ts
│   │   ├── cache-loader.ts
│   │   ├── common-chunks-plugins.ts
│   │   ├── ionic-environment-plugin.ts
│   │   ├── ionic-webpack-factory.ts
│   │   ├── loader-impl.spec.ts
│   │   ├── loader-impl.ts
│   │   ├── loader.ts
│   │   ├── source-mapper.ts
│   │   └── watch-memory-system.ts
│   ├── webpack.ts
│   ├── worker-client.ts
│   └── worker-process.ts
├── tsconfig.json
└── tslint.json
Download .txt
SYMBOL INDEX (814 symbols across 90 files)

FILE: bin/ion-dev.js
  function patchConsole (line 153) | function patchConsole(consoleType) {

FILE: config/webpack.config.js
  function getProdLoaders (line 59) | function getProdLoaders() {

FILE: lab/static/js/lab.js
  function loadAppConfig (line 7) | function loadAppConfig() {
  function setAppConfig (line 16) | function setAppConfig(data) {
  function buildMenu (line 20) | function buildMenu() {
  function buildComponentsMenu (line 62) | function buildComponentsMenu() {
  function tryShowViewPopup (line 77) | function tryShowViewPopup() {
  function bindToggles (line 96) | function bindToggles() {
  function showDevice (line 115) | function showDevice(device, isShowing) {
  function saveLastDevices (line 135) | function saveLastDevices(newDevice, didAdd) {
  function showLastDevices (line 151) | function showLastDevices() {
  function setCordovaInfo (line 164) | function setCordovaInfo(data) {
  function loadCordova (line 172) | function loadCordova() {

FILE: preprocessor.js
  method process (line 5) | process(src, path) {

FILE: scripts/commit-changelog.js
  function main (line 3) | function main() {

FILE: scripts/publish-nightly.js
  function backupOriginalPackageJson (line 13) | function backupOriginalPackageJson() {
  function createNightlyVersionInPackageJson (line 18) | function createNightlyVersionInPackageJson() {
  function revertPackageJson (line 24) | function revertPackageJson() {
  function createTimestamp (line 31) | function createTimestamp() {
  function publishToNpm (line 41) | function publishToNpm(tagName) {
  function mainFunction (line 47) | function mainFunction() {

FILE: src/aot/aot-compiler.ts
  function runAot (line 31) | async function runAot(context: BuildContext, options: AotOptions) {
  function errorCheckProgram (line 80) | function errorCheckProgram(context: BuildContext, tsConfig: TsConfig, co...
  function replaceBootstrap (line 102) | function replaceBootstrap(mainFile: File, appNgModulePath: string, appNg...
  function isTranspileRequired (line 121) | function isTranspileRequired(angularVersion: SemverVersion) {
  function transpileFiles (line 125) | function transpileFiles(context: BuildContext, tsConfig: TsConfig, fileS...
  function transpileFileContent (line 145) | function transpileFileContent(fileName: string, sourceText: string, opti...
  function isNg5 (line 155) | function isNg5(version: SemverVersion) {
  function runNg4Aot (line 159) | async function runNg4Aot(options: CodegenOptions) {
  function runNg5Aot (line 176) | async function runNg5Aot(context: BuildContext, tsConfig: TsConfig, aggr...
  type AotOptions (line 217) | interface AotOptions {

FILE: src/aot/compiler-host-factory.ts
  function getFileSystemCompilerHostInstance (line 7) | function getFileSystemCompilerHostInstance(options: CompilerOptions) {

FILE: src/aot/compiler-host.ts
  type OnErrorFn (line 7) | interface OnErrorFn {
  class FileSystemCompilerHost (line 11) | class FileSystemCompilerHost implements CompilerHost {
    method constructor (line 14) | constructor(private options: CompilerOptions, private fileSystem: Virt...
    method fileExists (line 18) | fileExists(filePath: string): boolean {
    method readFile (line 27) | readFile(filePath: string): string {
    method directoryExists (line 36) | directoryExists(directoryPath: string): boolean {
    method getFiles (line 45) | getFiles(directoryPath: string): string[] {
    method getDirectories (line 50) | getDirectories(directoryPath: string): string[] {
    method getSourceFile (line 63) | getSourceFile(filePath: string, languageVersion: ScriptTarget, onError...
    method getCancellationToken (line 75) | getCancellationToken(): CancellationToken {
    method getDefaultLibFileName (line 79) | getDefaultLibFileName(options: CompilerOptions) {
    method writeFile (line 83) | writeFile(fileName: string, data: string, writeByteOrderMark: boolean,...
    method getCurrentDirectory (line 89) | getCurrentDirectory(): string {
    method getCanonicalFileName (line 93) | getCanonicalFileName(fileName: string): string {
    method useCaseSensitiveFileNames (line 97) | useCaseSensitiveFileNames(): boolean {
    method getNewLine (line 101) | getNewLine(): string {

FILE: src/aot/utils.ts
  function getFallbackMainContent (line 12) | function getFallbackMainContent() {
  function getBootstrapNodes (line 23) | function getBootstrapNodes(allCalls: CallExpression[]) {
  function replaceNgModuleClassName (line 33) | function replaceNgModuleClassName(filePath: string, fileContent: string,...
  function replacePlatformBrowser (line 44) | function replacePlatformBrowser(filePath: string, fileContent: string) {
  function checkForPlatformDynamicBrowser (line 63) | function checkForPlatformDynamicBrowser(filePath: string, fileContent: s...
  function replaceBootstrapModuleFactory (line 78) | function replaceBootstrapModuleFactory(filePath: string, fileContent: st...
  function getPlatformBrowserFunctionNode (line 89) | function getPlatformBrowserFunctionNode(filePath: string, fileContent: s...
  function importAndEnableProdMode (line 104) | function importAndEnableProdMode(filePath: string, fileContent: string) {
  function replaceBootstrapImpl (line 117) | function replaceBootstrapImpl(filePath: string, fileContent: string, app...

FILE: src/build.ts
  function build (line 31) | function build(context: BuildContext) {
  function buildWorker (line 46) | async function buildWorker(context: BuildContext) {
  function buildProject (line 57) | function buildProject(context: BuildContext) {
  function buildUpdate (line 112) | function buildUpdate(changedFiles: ChangedFile[], context: BuildContext) {
  function buildUpdateTasks (line 191) | function buildUpdateTasks(changedFiles: ChangedFile[], context: BuildCon...
  function loadFiles (line 290) | function loadFiles(changedFiles: ChangedFile[], context: BuildContext) {
  type BuildTaskResolveValue (line 310) | interface BuildTaskResolveValue {
  function buildUpdateParallelTasks (line 320) | function buildUpdateParallelTasks(changedFiles: ChangedFile[], context: ...

FILE: src/build/util.ts
  function scanSrcTsFiles (line 10) | function scanSrcTsFiles(context: BuildContext) {
  function validateTsConfigSettings (line 31) | function validateTsConfigSettings(tsConfigFileContents: TsConfig) {
  function validateRequiredFilesExist (line 52) | function validateRequiredFilesExist(context: BuildContext) {
  function readVersionOfDependencies (line 76) | async function readVersionOfDependencies(context: BuildContext) {
  function readPackageVersion (line 94) | async function readPackageVersion(packageDir: string) {

FILE: src/bundle.ts
  function bundle (line 7) | function bundle(context: BuildContext, configFile?: string) {
  function bundleWorker (line 15) | function bundleWorker(context: BuildContext, configFile: string) {
  function bundleUpdate (line 20) | function bundleUpdate(changedFiles: ChangedFile[], context: BuildContext) {
  function buildJsSourceMaps (line 31) | function buildJsSourceMaps(context: BuildContext) {
  function getJsOutputDest (line 37) | function getJsOutputDest(context: BuildContext) {

FILE: src/clean.ts
  function clean (line 7) | function clean(context: BuildContext) {

FILE: src/cleancss.ts
  function cleancss (line 11) | function cleancss(context: BuildContext, configFile?: string) {
  function cleancssWorker (line 22) | function cleancssWorker(context: BuildContext, configFile: string): Prom...
  function runCleanCss (line 37) | function runCleanCss(cleanCssConfig: CleanCssConfig, fileContent: string...

FILE: src/copy.ts
  constant FILTER_OUT_DIRS_FOR_CLEAN (line 14) | const FILTER_OUT_DIRS_FOR_CLEAN = ['{{WWW}}', '{{BUILD}}'];
  function copy (line 16) | function copy(context: BuildContext, configFile?: string) {
  function copyWorker (line 30) | function copyWorker(context: BuildContext, configFile: string) {
  function copyUpdate (line 70) | function copyUpdate(changedFiles: ChangedFile[], context: BuildContext) {
  function cleanDirectories (line 122) | function cleanDirectories(context: BuildContext, directoriesToCreate: Se...
  function deleteDirectories (line 137) | function deleteDirectories(directoryPaths: string[]) {
  function processRemoveFile (line 145) | function processRemoveFile(changedFile: ChangedFile) {
  function processRemoveDir (line 168) | function processRemoveDir(changedFile: ChangedFile): Promise<any> {
  function cacheCopyData (line 188) | function cacheCopyData(copyObject: CopyToFrom) {
  function getFilesPathsForConfig (line 197) | function getFilesPathsForConfig(copyConfigKeys: string[], copyConfig: Co...
  function populateFileAndDirectoryInfo (line 217) | function populateFileAndDirectoryInfo(resultMap: Map<string, GlobResult[...
  function cleanConfigContent (line 235) | function cleanConfigContent(dictionaryKeys: string[], copyConfig: CopyCo...
  function copyConfigToWatchConfig (line 247) | function copyConfigToWatchConfig(context: BuildContext): Watcher {
  type CopySrcToDestResult (line 279) | interface CopySrcToDestResult {
  type CopyConfig (line 295) | interface CopyConfig {
  type CopyToFrom (line 299) | interface CopyToFrom {
  type CopyOptions (line 304) | interface CopyOptions {

FILE: src/core/bundle-components.ts
  function bundleCoreComponents (line 12) | function bundleCoreComponents(context: BuildContext) {
  function getCoreCompiler (line 61) | function getCoreCompiler(context: BuildContext): CoreCompiler {

FILE: src/core/inject-scripts.ts
  function updateIndexHtml (line 7) | function updateIndexHtml(context: BuildContext) {
  function injectCoreScripts (line 22) | function injectCoreScripts(context: BuildContext, indexHtml: string) {
  function injectCoreHtml (line 35) | function injectCoreHtml(indexHtml: string, inject: string) {

FILE: src/core/ionic-global.ts
  function buildIonicGlobal (line 5) | function buildIonicGlobal(context: BuildContext) {

FILE: src/deep-linking.ts
  function setExistingDeepLinkConfig (line 18) | function setExistingDeepLinkConfig(newString: string) {
  function deepLinking (line 22) | function deepLinking(context: BuildContext) {
  function deepLinkingWorker (line 37) | function deepLinkingWorker(context: BuildContext) {
  function deepLinkingWorkerImpl (line 41) | async function deepLinkingWorkerImpl(context: BuildContext, changedFiles...
  function deepLinkingUpdate (line 73) | function deepLinkingUpdate(changedFiles: ChangedFile[], context: BuildCo...
  function deepLinkingUpdateImpl (line 81) | function deepLinkingUpdateImpl(changedFiles: ChangedFile[], context: Bui...
  function deepLinkingWorkerFullUpdate (line 98) | function deepLinkingWorkerFullUpdate(context: BuildContext) {
  function getAppMainNgModuleFile (line 111) | async function getAppMainNgModuleFile(appNgModulePath: string) {
  function hasAppModuleChanged (line 119) | function hasAppModuleChanged(changedFiles: ChangedFile[], appNgModulePat...

FILE: src/deep-linking/util.spec.ts
  function transformSourceFile (line 2252) | function transformSourceFile(sourceText: string, transformers: ts.Transf...

FILE: src/deep-linking/util.ts
  function getDeepLinkData (line 55) | function getDeepLinkData(appNgModuleFilePath: string, fileCache: FileCac...
  function filterTypescriptFilesForDeepLinks (line 86) | function filterTypescriptFilesForDeepLinks(fileCache: FileCache): File[] {
  function isDeepLinkingFile (line 90) | function isDeepLinkingFile(filePath: string) {
  function getNgModulePathFromCorrespondingPage (line 97) | function getNgModulePathFromCorrespondingPage(filePath: string) {
  function getRelativePathToPageNgModuleFromAppNgModule (line 102) | function getRelativePathToPageNgModuleFromAppNgModule(pathToAppNgModule:...
  function getNgModuleDataFromPage (line 106) | function getNgModuleDataFromPage(appNgModuleFilePath: string, filePath: ...
  function getDeepLinkDecoratorContentForSourceFile (line 127) | function getDeepLinkDecoratorContentForSourceFile(sourceFile: SourceFile...
  function getStringValueFromDeepLinkDecorator (line 176) | function getStringValueFromDeepLinkDecorator(sourceFile: SourceFile, pro...
  function getArrayValueFromDeepLinkDecorator (line 199) | function getArrayValueFromDeepLinkDecorator(sourceFile: SourceFile, prop...
  function hasExistingDeepLinkConfig (line 227) | function hasExistingDeepLinkConfig(appNgModuleFilePath: string, appNgMod...
  function getIonicModuleForRootCall (line 250) | function getIonicModuleForRootCall(decorator: Decorator) {
  function convertDeepLinkConfigEntriesToString (line 290) | function convertDeepLinkConfigEntriesToString(entries: Map<string, DeepL...
  function convertDeepLinkEntryToJsObjectString (line 305) | function convertDeepLinkEntryToJsObjectString(entry: DeepLinkConfigEntry) {
  function updateAppNgModuleWithDeepLinkConfig (line 311) | function updateAppNgModuleWithDeepLinkConfig(context: BuildContext, deep...
  function getUpdatedAppNgModuleContentWithDeepLinkConfig (line 331) | function getUpdatedAppNgModuleContentWithDeepLinkConfig(appNgModuleFileP...
  function getUpdatedAppNgModuleFactoryContentWithDeepLinksConfig (line 351) | function getUpdatedAppNgModuleFactoryContentWithDeepLinksConfig(appNgMod...
  function addDefaultSecondArgumentToAppNgModule (line 365) | function addDefaultSecondArgumentToAppNgModule(appNgModuleFileContent: s...
  function addDeepLinkArgumentToAppNgModule (line 371) | function addDeepLinkArgumentToAppNgModule(appNgModuleFileContent: string...
  function generateDefaultDeepLinkNgModuleContent (line 377) | function generateDefaultDeepLinkNgModuleContent(pageFilePath: string, cl...
  function purgeDeepLinkDecoratorTSTransform (line 398) | function purgeDeepLinkDecoratorTSTransform(): TransformerFactory<SourceF...
  function purgeDeepLinkDecoratorTSTransformImpl (line 402) | function purgeDeepLinkDecoratorTSTransformImpl(transformContext: Transfo...
  function purgeDeepLinkDecorator (line 482) | function purgeDeepLinkDecorator(inputText: string): string {
  function purgeDeepLinkImport (line 503) | function purgeDeepLinkImport(inputText: string): string {
  function getInjectDeepLinkConfigTypescriptTransform (line 545) | function getInjectDeepLinkConfigTypescriptTransform() {
  function injectDeepLinkConfigTypescriptTransform (line 551) | function injectDeepLinkConfigTypescriptTransform(deepLinkString: string,...
  constant DEEPLINK_DECORATOR_TEXT (line 618) | const DEEPLINK_DECORATOR_TEXT = 'IonicPage';
  constant DEEPLINK_DECORATOR_NAME_ATTRIBUTE (line 619) | const DEEPLINK_DECORATOR_NAME_ATTRIBUTE = 'name';
  constant DEEPLINK_DECORATOR_SEGMENT_ATTRIBUTE (line 620) | const DEEPLINK_DECORATOR_SEGMENT_ATTRIBUTE = 'segment';
  constant DEEPLINK_DECORATOR_PRIORITY_ATTRIBUTE (line 621) | const DEEPLINK_DECORATOR_PRIORITY_ATTRIBUTE = 'priority';
  constant DEEPLINK_DECORATOR_DEFAULT_HISTORY_ATTRIBUTE (line 622) | const DEEPLINK_DECORATOR_DEFAULT_HISTORY_ATTRIBUTE = 'defaultHistory';
  constant NG_MODULE_IMPORT_DECLARATION (line 624) | const NG_MODULE_IMPORT_DECLARATION = 'imports';
  constant IONIC_MODULE_NAME (line 625) | const IONIC_MODULE_NAME = 'IonicModule';
  constant FOR_ROOT_METHOD (line 626) | const FOR_ROOT_METHOD = 'forRoot';
  constant LOAD_CHILDREN_SEPARATOR (line 627) | const LOAD_CHILDREN_SEPARATOR = '#';

FILE: src/dev-server/http-server.ts
  function createHttpServer (line 27) | function createHttpServer(config: ServeConfig): express.Application {
  function setupProxies (line 53) | function setupProxies(app: express.Application) {
  function serveIndex (line 77) | function serveIndex(req: express.Request, res: express.Response) {
  function serveMockCordovaJS (line 103) | function serveMockCordovaJS(req: express.Request, res: express.Response) {
  function servePlatformResource (line 111) | async function servePlatformResource(req: express.Request, res: express....
  function getResourcePath (line 132) | async function getResourcePath(url: string, config: ServeConfig, userAge...
  function checkFile (line 152) | function checkFile(filePath: string): Promise<void> {
  function isUserAgentIOS (line 163) | function isUserAgentIOS(ua: string): boolean {
  function isUserAgentAndroid (line 168) | function isUserAgentAndroid(ua: string): boolean {

FILE: src/dev-server/injector.ts
  constant LOGGER_HEADER (line 5) | const LOGGER_HEADER = '<!-- Ionic Dev Server: Injected Logger Script -->';
  function injectNotificationScript (line 7) | function injectNotificationScript(rootDir: string, content: any, notifyO...
  function getDevLoggerScript (line 29) | function getDevLoggerScript(rootDir: string, notifyOnConsoleLog: boolean...

FILE: src/dev-server/live-reload.ts
  function createLiveReloadServer (line 9) | function createLiveReloadServer(config: ServeConfig) {
  function injectLiveReloadScript (line 33) | function injectLiveReloadScript(content: any, host: string, port: Number...
  function getLiveReloadScript (line 55) | function getLiveReloadScript(host: string, port: Number) {

FILE: src/dev-server/notification-server.ts
  function createNotificationServer (line 11) | function createNotificationServer(config: ServeConfig) {

FILE: src/dev-server/serve-config.ts
  type ServeConfig (line 3) | interface ServeConfig {
  constant LOGGER_DIR (line 22) | const LOGGER_DIR = '__ion-dev-server';
  constant IONIC_LAB_URL (line 23) | const IONIC_LAB_URL = '/ionic-lab';
  constant IOS_PLATFORM_PATHS (line 25) | const IOS_PLATFORM_PATHS = [path.join('platforms', 'ios', 'www')];
  constant ANDROID_PLATFORM_PATHS (line 26) | const ANDROID_PLATFORM_PATHS = [

FILE: src/generators.ts
  function processPageRequest (line 7) | function processPageRequest(context: BuildContext, name: string, command...
  function processPipeRequest (line 17) | function processPipeRequest(context: BuildContext, name: string, ngModul...
  function processDirectiveRequest (line 21) | function processDirectiveRequest(context: BuildContext, name: string, ng...
  function processComponentRequest (line 25) | function processComponentRequest(context: BuildContext, name: string, ng...
  function processProviderRequest (line 29) | function processProviderRequest(context: BuildContext, name: string, ngM...
  function processTabsRequest (line 33) | function processTabsRequest(context: BuildContext, name: string, tabs: a...
  function listOptions (line 52) | function listOptions() {

FILE: src/generators/constants.ts
  constant CLASSNAME_VARIABLE (line 1) | const CLASSNAME_VARIABLE = '$CLASSNAME';
  constant TAB_CONTENT_VARIABLE (line 2) | const TAB_CONTENT_VARIABLE = '$TAB_CONTENT';
  constant TAB_VARIABLES_VARIABLE (line 3) | const TAB_VARIABLES_VARIABLE = '$TAB_VARIABLES';
  constant TABS_IMPORTSTATEMENT_VARIABLE (line 4) | const TABS_IMPORTSTATEMENT_VARIABLE = '$TABS_IMPORTSTATEMENT';
  constant FILENAME_VARIABLE (line 5) | const FILENAME_VARIABLE = '$FILENAME';
  constant PIPENAME_VARIABLE (line 6) | const PIPENAME_VARIABLE = '$PIPENAME';
  constant SUPPLIEDNAME_VARIABLE (line 7) | const SUPPLIEDNAME_VARIABLE = '$SUPPLIEDNAME';
  constant IMPORTSTATEMENT_VARIABLE (line 8) | const IMPORTSTATEMENT_VARIABLE = '$IMPORTSTATEMENT';
  constant IONICPAGE_VARIABLE (line 9) | const IONICPAGE_VARIABLE = '$IONICPAGE';
  constant KNOWN_FILE_EXTENSION (line 10) | const KNOWN_FILE_EXTENSION = '.tmpl';
  constant SPEC_FILE_EXTENSION (line 12) | const SPEC_FILE_EXTENSION = 'spec.ts';
  constant NG_MODULE_FILE_EXTENSION (line 13) | const NG_MODULE_FILE_EXTENSION = 'module.ts';

FILE: src/generators/util.ts
  function hydrateRequest (line 14) | function hydrateRequest(context: BuildContext, request: GeneratorRequest) {
  function createCommonModule (line 43) | function createCommonModule(envVar: string, requestType: string) {
  function hydrateTabRequest (line 49) | function hydrateTabRequest(context: BuildContext, request: GeneratorTabR...
  function readTemplates (line 85) | function readTemplates(pathToRead: string): Promise<Map<string, string>> {
  function filterOutTemplates (line 103) | function filterOutTemplates(request: HydratedGeneratorRequest, templates...
  function applyTemplates (line 115) | function applyTemplates(request: HydratedGeneratorRequest, templates: Ma...
  function writeGeneratedFiles (line 132) | function writeGeneratedFiles(request: HydratedGeneratorRequest, processe...
  function createDirAndWriteFile (line 148) | function createDirAndWriteFile(filePath: string, fileContent: string) {
  function getNgModules (line 155) | function getNgModules(context: BuildContext, types: string[]): Promise<G...
  function getSuffixFromGeneratorType (line 161) | function getSuffixFromGeneratorType(context: BuildContext, type: string) {
  function getDirToWriteToByType (line 176) | function getDirToWriteToByType(context: BuildContext, type: string) {
  function nonPageFileManipulation (line 191) | async function nonPageFileManipulation(context: BuildContext, name: stri...
  function tabsModuleManipulation (line 222) | function tabsModuleManipulation(tabs: string[][], hydratedRequest: Hydra...
  function generateTemplates (line 247) | function generateTemplates(context: BuildContext, request: HydratedGener...
  function createConstStatments (line 272) | function createConstStatments(pageConstantFile: string, request: Hydrate...
  function createPageConstants (line 279) | function createPageConstants(context: BuildContext) {
  type GeneratorOption (line 284) | interface GeneratorOption {
  type GeneratorRequest (line 289) | interface GeneratorRequest {
  type GeneratorTabRequest (line 296) | interface GeneratorTabRequest extends GeneratorRequest {
  type HydratedGeneratorRequest (line 300) | interface HydratedGeneratorRequest extends GeneratorRequest {

FILE: src/highlight/highlight.ts
  function escape (line 37) | function escape(value: string) {
  function testRe (line 43) | function testRe(re: any, lexeme: any) {
  function inherit (line 48) | function inherit(parent: any, obj: any) {
  function compileLanguage (line 62) | function compileLanguage(language: any) {
  function highlightError (line 156) | function highlightError(htmlInput: string, errorCharStart: number, error...
  function highlight (line 220) | function highlight(name: string, value: string, ignore_illegals?: boolea...
  function highlightAuto (line 450) | function highlightAuto(text: any, languageSubset?: any) {
  function configure (line 477) | function configure(user_options: any) {
  function registerLanguage (line 481) | function registerLanguage(name: any, language: any) {
  function listLanguages (line 488) | function listLanguages() {
  function getLanguage (line 492) | function getLanguage(name: any) {
  function typescript (line 613) | function typescript(hljs: any) {
  function scss (line 725) | function scss(hljs: any) {
  function xml (line 826) | function xml(hljs: any) {

FILE: src/index.ts
  function run (line 26) | function run(task: string) {
  function errorLog (line 42) | function errorLog(task: string, e: any) {

FILE: src/lint.ts
  type LintWorkerConfig (line 15) | interface LintWorkerConfig {
  function lint (line 32) | function lint(context: BuildContext, tsLintConfig?: string | null, typeC...
  function lintWorker (line 46) | function lintWorker(context: BuildContext, {tsConfig, tsLintConfig, type...
  function lintUpdate (line 56) | function lintUpdate(changedFiles: ChangedFile[], context: BuildContext, ...
  function lintUpdateWorker (line 66) | function lintUpdateWorker(context: BuildContext, {tsConfig, tsLintConfig...
  function lintApp (line 75) | function lintApp(context: BuildContext, {tsConfig, tsLintConfig, typeChe...
  function getLintConfig (line 82) | function getLintConfig(context: BuildContext, tsLintConfig: string | nul...

FILE: src/lint/lint-factory.ts
  type LinterOptions (line 7) | interface LinterOptions {
  type LinterConfig (line 11) | interface LinterConfig {
  function lint (line 23) | function lint(linter: Linter, config: LinterConfig, filePath: string, fi...
  function getLintResult (line 32) | function getLintResult(linter: Linter): LintResult {
  function typeCheck (line 44) | function typeCheck(context: BuildContext, program: Program, linterOption...
  function createProgram (line 58) | function createProgram(context: BuildContext, tsConfig: string): Program {
  function getFileNames (line 69) | function getFileNames(context: BuildContext, program: Program): string[] {
  function getTsLintConfig (line 80) | function getTsLintConfig(tsLintConfig: string, linterOptions?: LinterOpt...
  function createLinter (line 92) | function createLinter(context: BuildContext, program: Program): Linter {

FILE: src/lint/lint-utils.spec.ts
  method getFileName (line 102) | getFileName() {
  method getFileName (line 136) | getFileName() {

FILE: src/lint/lint-utils.ts
  function lintFiles (line 29) | function lintFiles(context: BuildContext, program: Program, tsLintConfig...
  function lintFile (line 42) | function lintFile(linter: Linter, config: any, filePath: string): Promis...
  function processTypeCheckDiagnostics (line 57) | function processTypeCheckDiagnostics(context: BuildContext, tsDiagnostic...
  function processLintResult (line 74) | function processLintResult(context: BuildContext, result: LintResult) {
  function generateErrorMessageForFiles (line 91) | function generateErrorMessageForFiles(failingFiles: string[], message?: ...
  function getFileNames (line 95) | function getFileNames(context: BuildContext, failures: RuleFailure[]): s...
  function removeDuplicateFileNames (line 101) | function removeDuplicateFileNames(fileNames: string[]) {
  function isMpegFile (line 105) | function isMpegFile(file: string) {

FILE: src/logger/logger-diagnostics.ts
  function printDiagnostics (line 10) | function printDiagnostics(context: BuildContext, diagnosticsType: string...
  function consoleLogDiagnostic (line 26) | function consoleLogDiagnostic(d: Diagnostic) {
  function consoleHighlightError (line 73) | function consoleHighlightError(errorLine: string, errorCharStart: number...
  function clearDiagnosticsCache (line 107) | function clearDiagnosticsCache() {
  function clearDiagnostics (line 111) | function clearDiagnostics(context: BuildContext, type: string) {
  function hasDiagnostics (line 119) | function hasDiagnostics(buildDir: string) {
  function loadBuildDiagnosticsHtml (line 133) | function loadBuildDiagnosticsHtml(buildDir: string) {
  function injectDiagnosticsHtml (line 152) | function injectDiagnosticsHtml(buildDir: string, content: any) {
  function getDiagnosticsHtmlContent (line 178) | function getDiagnosticsHtmlContent(buildDir: string, includeDiagnosticsH...
  function generateDiagnosticHtml (line 214) | function generateDiagnosticHtml(d: Diagnostic) {
  function generateCodeBlock (line 236) | function generateCodeBlock(d: Diagnostic) {
  function jsConsoleSyntaxHighlight (line 269) | function jsConsoleSyntaxHighlight(text: string) {
  function cssConsoleSyntaxHighlight (line 285) | function cssConsoleSyntaxHighlight(text: string, errorCharStart: number) {
  function prepareLines (line 312) | function prepareLines(orgLines: PrintLine[], code: 'text'|'html') {
  function eachLineHasLeadingWhitespace (line 332) | function eachLineHasLeadingWhitespace(lines: PrintLine[], code: 'text'|'...
  constant JS_KEYWORDS (line 349) | const JS_KEYWORDS = [
  function getDiagnosticsFileName (line 361) | function getDiagnosticsFileName(buildDir: string, type: string) {
  function isMeaningfulLine (line 366) | function isMeaningfulLine(line: string) {
  constant MEH_LINES (line 376) | const MEH_LINES = [';', ':', '{', '}', '(', ')', '/**', '/*', '*/', '*',...

FILE: src/logger/logger-runtime.ts
  function generateRuntimeDiagnosticContent (line 9) | function generateRuntimeDiagnosticContent(rootDir: string, buildDir: str...
  function generateRuntimeStackDiagnostics (line 40) | function generateRuntimeStackDiagnostics(rootDir: string, stack: string) {
  constant WEBPACK_FILE_REGEX (line 147) | const WEBPACK_FILE_REGEX = /\(webpack:\/\/\/(.*?)\)/;

FILE: src/logger/logger-sass.ts
  function runSassDiagnostics (line 9) | function runSassDiagnostics(context: BuildContext, sassError: SassError) {
  constant STOP_CHARS (line 125) | const STOP_CHARS = ['', '\n', '\r', '\t', ' ', ':', ';', ',', '{', '}', ...

FILE: src/logger/logger-tslint.ts
  constant STOP_CHARS (line 7) | const STOP_CHARS = [' ', '=', ',', '.', '\t', '{', '}', '(', ')', '"', '...
  function runTsLintDiagnostics (line 10) | function runTsLintDiagnostics(context: BuildContext, failures: RuleFailu...
  function loadDiagnostic (line 15) | function loadDiagnostic(context: BuildContext, failure: RuleFailure) {

FILE: src/logger/logger-typescript.ts
  function runTypeScriptDiagnostics (line 13) | function runTypeScriptDiagnostics(context: BuildContext, tsDiagnostics: ...
  function loadDiagnostic (line 20) | function loadDiagnostic(context: BuildContext, tsDiagnostic: ts.Diagnost...

FILE: src/logger/logger.ts
  class Logger (line 6) | class Logger {
    method constructor (line 10) | constructor(scope: string) {
    method ready (line 20) | ready(color?: string, bold?: boolean) {
    method finish (line 24) | finish(color?: string, bold?: boolean) {
    method completed (line 28) | private completed(type: string, color: string, bold: boolean) {
    method fail (line 61) | fail(err: Error) {
    method setStartTime (line 92) | setStartTime(startTime: number) {
    method log (line 100) | static log(...msg: any[]) {
    method info (line 110) | static info(msg: string, color?: string, bold?: boolean) {
    method warn (line 139) | static warn(...msg: any[]) {
    method error (line 153) | static error(...msg: any[]) {
    method unformattedError (line 167) | static unformattedError(msg: string) {
    method unformattedDebug (line 171) | static unformattedDebug(msg: string) {
    method debug (line 178) | static debug(...msg: any[]) {
    method wordWrap (line 193) | static wordWrap(msg: any[]) {
    method formatFileName (line 266) | static formatFileName(rootDir: string, fileName: string) {
    method formatHeader (line 278) | static formatHeader(type: string, fileName: string, rootDir: string, s...
    method newLine (line 293) | static newLine() {
  function timePrefix (line 303) | function timePrefix() {
  function memoryUsage (line 309) | function memoryUsage() {

FILE: src/minify.ts
  function minify (line 9) | function minify(context: BuildContext) {
  function minifyWorker (line 23) | function minifyWorker(context: BuildContext) {
  function minifyJs (line 31) | function minifyJs(context: BuildContext): Promise<any> {
  function runUglify (line 35) | function runUglify(context: BuildContext) {
  function minifyCss (line 40) | function minifyCss(context: BuildContext) {

FILE: src/mocks/mock-helpers.ts
  function setContext (line 3) | function setContext(context: BuildContext) {
  function readFileAsync (line 6) | function readFileAsync(filePath: string) {

FILE: src/ngc.ts
  function ngc (line 17) | function ngc(context: BuildContext, configFile?: string) {
  function ngcWorker (line 31) | function ngcWorker(context: BuildContext, configFile: string): Promise<a...
  function runNgc (line 37) | function runNgc(context: BuildContext, configFile: string): Promise<any> {
  function transformTsForDeepLinking (line 46) | function transformTsForDeepLinking(context: BuildContext) {

FILE: src/optimization/remove-unused-fonts.spec.ts
  function getMockFontDirData (line 96) | function getMockFontDirData() {

FILE: src/optimization/remove-unused-fonts.ts
  function removeUnusedFonts (line 27) | function removeUnusedFonts(context: BuildContext): Promise<any> {
  function getFontFileNamesToPurge (line 38) | function getFontFileNamesToPurge(target: string, platform: string, fileN...
  function isIonicons (line 61) | function isIonicons(fileName: string) {
  function isWoof (line 66) | function isWoof(fileName: string) {

FILE: src/postprocess.ts
  function postprocess (line 13) | function postprocess(context: BuildContext) {
  function postprocessWorker (line 24) | function postprocessWorker(context: BuildContext) {
  function writeFilesToDisk (line 40) | function writeFilesToDisk(context: BuildContext) {

FILE: src/preprocess.ts
  function preprocess (line 12) | function preprocess(context: BuildContext) {
  function preprocessWorker (line 24) | function preprocessWorker(context: BuildContext) {
  function preprocessUpdate (line 30) | function preprocessUpdate(changedFiles: ChangedFile[], context: BuildCon...

FILE: src/sass.ts
  function sass (line 15) | function sass(context: BuildContext, configFile?: string) {
  function sassUpdate (line 33) | function sassUpdate(changedFiles: ChangedFile[], context: BuildContext) {
  function sassWorker (line 51) | function sassWorker(context: BuildContext, configFile: string) {
  function getSassConfig (line 92) | function getSassConfig(context: BuildContext, configFile: string): SassC...
  function generateSassData (line 97) | function generateSassData(context: BuildContext, sassConfig: SassConfig) {
  function getComponentSassFiles (line 142) | function getComponentSassFiles(moduleDirectories: string[], context: Bui...
  function addComponentSassFiles (line 159) | function addComponentSassFiles(componentPath: string, collectedSassFiles...
  function getSiblingSassFiles (line 190) | function getSiblingSassFiles(componentPath: string, sassConfig: SassConf...
  function isValidSassFile (line 204) | function isValidSassFile(filename: string, sassConfig: SassConfig) {
  function getComponentDirectories (line 222) | function getComponentDirectories(moduleDirectories: string[], sassConfig...
  function render (line 239) | function render(context: BuildContext, sassConfig: SassConfig): Promise<...
  function renderSassSuccess (line 270) | function renderSassSuccess(context: BuildContext, sassResult: Result, sa...
  function generateSourceMaps (line 323) | function generateSourceMaps(sassResult: Result, sassConfig: SassConfig):...
  function writeOutput (line 360) | function writeOutput(context: BuildContext, sassConfig: SassConfig, cssO...
  function defaultSortComponentPathsFn (line 402) | function defaultSortComponentPathsFn(a: any, b: any): number {
  function defaultSortComponentFilesFn (line 422) | function defaultSortComponentFilesFn(a: any, b: any): number {
  type SassConfig (line 453) | interface SassConfig {
  type SassMap (line 475) | interface SassMap {

FILE: src/serve.ts
  constant DEV_LOGGER_DEFAULT_PORT (line 15) | const DEV_LOGGER_DEFAULT_PORT = 53703;
  constant LIVE_RELOAD_DEFAULT_PORT (line 16) | const LIVE_RELOAD_DEFAULT_PORT = 35729;
  constant DEV_SERVER_DEFAULT_PORT (line 17) | const DEV_SERVER_DEFAULT_PORT = 8100;
  constant DEV_SERVER_DEFAULT_HOST (line 18) | const DEV_SERVER_DEFAULT_HOST = '0.0.0.0';
  function serve (line 20) | function serve(context: BuildContext) {
  function onReady (line 88) | function onReady(config: ServeConfig, context: BuildContext) {
  function getHttpServerPort (line 106) | function getHttpServerPort(context: BuildContext): number {
  function getHttpServerHost (line 114) | function getHttpServerHost(context: BuildContext): string {
  function getLiveReloadServerPort (line 122) | function getLiveReloadServerPort(context: BuildContext): number {
  function getNotificationPort (line 130) | function getNotificationPort(context: BuildContext): number {
  function useServerLogs (line 138) | function useServerLogs(context: BuildContext): boolean {
  function isCordovaServe (line 142) | function isCordovaServe(context: BuildContext): boolean {
  function launchBrowser (line 146) | function launchBrowser(context: BuildContext): boolean {
  function browserToLaunch (line 150) | function browserToLaunch(context: BuildContext): string {
  function browserOption (line 154) | function browserOption(context: BuildContext): string {
  function launchLab (line 158) | function launchLab(context: BuildContext): boolean {
  function platformOption (line 162) | function platformOption(context: BuildContext): string {
  function useLiveReload (line 166) | function useLiveReload(context: BuildContext): boolean {
  function useProxy (line 170) | function useProxy(context: BuildContext): boolean {
  function sendClientConsoleLogs (line 174) | function sendClientConsoleLogs(context: BuildContext): boolean {

FILE: src/template.ts
  function templateUpdate (line 11) | function templateUpdate(changedFiles: ChangedFile[], context: BuildConte...
  function updateCorrespondingJsFile (line 57) | function updateCorrespondingJsFile(context: BuildContext, newTemplateCon...
  function inlineTemplate (line 75) | function inlineTemplate(sourceText: string, sourcePath: string): string {
  function updateTemplate (line 104) | function updateTemplate(componentDir: string, match: TemplateUrlMatch): ...
  function replaceTemplateUrl (line 118) | function replaceTemplateUrl(match: TemplateUrlMatch, htmlFilePath: strin...
  function replaceExistingJsTemplate (line 126) | function replaceExistingJsTemplate(existingSourceText: string, newTempla...
  function stringify (line 167) | function stringify(str: string) {
  function getTemplateFormat (line 173) | function getTemplateFormat(htmlFilePath: string, content: string) {
  function getTemplatePrefix (line 182) | function getTemplatePrefix(htmlFilePath: string) {
  function getTemplateSuffix (line 187) | function getTemplateSuffix(htmlFilePath: string) {
  function getTemplateMatch (line 192) | function getTemplateMatch(str: string): TemplateUrlMatch {
  constant COMPONENT_REGEX (line 207) | const COMPONENT_REGEX = /Component\s*?\(\s*?(\{([\s\S]*?)(\s*templateUrl...
  type TemplateUrlMatch (line 209) | interface TemplateUrlMatch {

FILE: src/transpile.ts
  function transpile (line 34) | function transpile(context: BuildContext) {
  function transpileUpdate (line 59) | function transpileUpdate(changedFiles: ChangedFile[], context: BuildCont...
  function transpileWorker (line 94) | function transpileWorker(context: BuildContext, workerConfig: TranspileW...
  function canRunTranspileUpdate (line 179) | function canRunTranspileUpdate(event: string, filePath: string, context:...
  function transpileUpdateWorker (line 191) | function transpileUpdateWorker(event: string, filePath: string, context:...
  function transpileDiagnosticsOnly (line 257) | function transpileDiagnosticsOnly(context: BuildContext) {
  function runDiagnosticsWorker (line 270) | function runDiagnosticsWorker(context: BuildContext) {
  type TranspileWorkerMessage (line 301) | interface TranspileWorkerMessage {
  function cleanFileNames (line 309) | function cleanFileNames(context: BuildContext, fileNames: string[]) {
  function writeTranspiledFilesCallback (line 314) | function writeTranspiledFilesCallback(fileCache: FileCache, sourcePath: ...
  function getTsConfigAsync (line 343) | async function getTsConfigAsync(context: BuildContext, tsConfigPath?: st...
  function getTsConfig (line 347) | function getTsConfig(context: BuildContext, tsConfigPath?: string): TsCo...
  function transpileTsString (line 385) | function transpileTsString(context: BuildContext, filePath: string, stri...
  function transformSource (line 403) | function transformSource(filePath: string, input: string) {
  function copyOriginalSourceFiles (line 413) | function copyOriginalSourceFiles(fileCache: FileCache) {
  function resetSourceFiles (line 425) | function resetSourceFiles(fileCache: FileCache) {
  function getTsConfigPath (line 443) | function getTsConfigPath(context: BuildContext) {
  type TsConfig (line 447) | interface TsConfig {
  type TranspileWorkerConfig (line 453) | interface TranspileWorkerConfig {

FILE: src/uglifyjs.ts
  function uglifyjs (line 12) | function uglifyjs(context: BuildContext, configFile?: string) {
  function uglifyjsWorker (line 26) | function uglifyjsWorker(context: BuildContext, configFile: string): Prom...
  function uglifyjsWorkerImpl (line 34) | async function uglifyjsWorkerImpl(context: BuildContext, uglifyJsConfig:...
  function runUglifyInternal (line 49) | async function runUglifyInternal(sourceFilePath: string, destFilePath: s...
  type UglifyJsConfig (line 72) | interface UglifyJsConfig {
  type UglifyResponse (line 83) | interface UglifyResponse {

FILE: src/upgrade-scripts/add-default-ngmodules.spec.ts
  function getClassContent (line 172) | function getClassContent(className: string, folderName: string) {

FILE: src/upgrade-scripts/add-default-ngmodules.ts
  function getTsFilePaths (line 14) | function getTsFilePaths(context: BuildContext) {
  function readTsFiles (line 21) | function readTsFiles(context: BuildContext, tsFilePaths: string[]) {
  function generateAndWriteNgModules (line 32) | function generateAndWriteNgModules(fileCache: FileCache) {
  function run (line 50) | function run() {

FILE: src/util/clean-css-factory.ts
  function getCleanCssInstance (line 3) | function getCleanCssInstance(options: cleanCss.Options) {
  type CleanCssConfig (line 7) | interface CleanCssConfig {

FILE: src/util/config.ts
  function generateContext (line 24) | function generateContext(context?: BuildContext): BuildContext {
  function getUserConfigFile (line 379) | function getUserConfigFile(context: BuildContext, task: TaskInfo, userCo...
  function fillConfigDefaults (line 397) | function fillConfigDefaults(userConfigFile: string, defaultConfigFile: s...
  function bundlerStrategy (line 429) | function bundlerStrategy(context: BuildContext): string {
  function isValidBundler (line 434) | function isValidBundler(bundler: any) {
  function getConfigValue (line 439) | function getConfigValue(context: BuildContext, argFullName: string, argS...
  function getArgValue (line 467) | function getArgValue(fullName: string, shortName: string): string {
  function hasConfigValue (line 481) | function hasConfigValue(context: BuildContext, argFullName: string, argS...
  function hasArg (line 507) | function hasArg(fullName: string, shortName: string = null): boolean {
  function replacePathVars (line 513) | function replacePathVars(context: BuildContext, filePath: string | strin...
  function getNodeBinExecutable (line 533) | function getNodeBinExecutable(context: BuildContext, cmd: string) {
  function checkDebugMode (line 547) | function checkDebugMode() {
  function isDebugMode (line 557) | function isDebugMode() {
  function setProcessArgs (line 562) | function setProcessArgs(argv: string[]) {
  function addArgv (line 567) | function addArgv(value: string) {
  function setProcessEnv (line 572) | function setProcessEnv(env: any) {
  function setProcessEnvVar (line 577) | function setProcessEnvVar(key: string, value: any) {
  function getProcessEnvVar (line 583) | function getProcessEnvVar(key: string): any {
  function setCwd (line 598) | function setCwd(cwd: string) {
  function getPackageJsonConfig (line 604) | function getPackageJsonConfig(context: BuildContext, key: string): any {
  function setAppPackageJsonData (line 623) | function setAppPackageJsonData(data: any) {
  function getAppPackageJsonData (line 627) | function getAppPackageJsonData(context: BuildContext) {

FILE: src/util/constants.ts
  constant FILE_CHANGE_EVENT (line 1) | const FILE_CHANGE_EVENT = 'change';
  constant FILE_ADD_EVENT (line 2) | const FILE_ADD_EVENT = 'add';
  constant FILE_DELETE_EVENT (line 3) | const FILE_DELETE_EVENT = 'unlink';
  constant DIRECTORY_ADD_EVENT (line 4) | const DIRECTORY_ADD_EVENT = 'addDir';
  constant DIRECTORY_DELETE_EVENT (line 5) | const DIRECTORY_DELETE_EVENT = 'unlinkDir';
  constant SOURCE_MAP_TYPE_CHEAP (line 7) | const SOURCE_MAP_TYPE_CHEAP = 'eval';
  constant SOURCE_MAP_TYPE_EXPENSIVE (line 8) | const SOURCE_MAP_TYPE_EXPENSIVE = 'source-map';
  constant BUILD_DIR (line 10) | const BUILD_DIR = 'build';
  constant SRC_DIR (line 11) | const SRC_DIR = 'src';
  constant TMP_DIR (line 12) | const TMP_DIR = '.tmp';
  constant SOURCEMAP_DIR (line 13) | const SOURCEMAP_DIR = '.sourcemaps';
  constant WWW_DIR (line 14) | const WWW_DIR = 'www';
  constant NODE_MODULES (line 15) | const NODE_MODULES = 'node_modules';
  constant IONIC_ANGULAR (line 16) | const IONIC_ANGULAR = 'ionic-angular';
  constant COMPONENT (line 17) | const COMPONENT = 'component';
  constant DIRECTIVE (line 18) | const DIRECTIVE = 'directive';
  constant PAGE (line 19) | const PAGE = 'page';
  constant PIPE (line 20) | const PIPE = 'pipe';
  constant PROVIDER (line 21) | const PROVIDER = 'provider';
  constant TABS (line 22) | const TABS = 'tabs';
  constant AT_ANGULAR (line 23) | const AT_ANGULAR = '@angular';
  constant RXJS (line 24) | const RXJS = 'rxjs';
  constant CORDOVA (line 25) | const CORDOVA = 'cordova';
  constant TYPESCRIPT (line 26) | const TYPESCRIPT = 'typescript';
  constant ENV_VAR_PROD (line 28) | const ENV_VAR_PROD = 'prod';
  constant ENV_VAR_DEV (line 29) | const ENV_VAR_DEV = 'dev';
  constant ENV_VAR_IONIC_ENV (line 30) | const ENV_VAR_IONIC_ENV = 'IONIC_ENV';
  constant ENV_VAR_IONIC_AOT (line 32) | const ENV_VAR_IONIC_AOT = 'IONIC_AOT';
  constant ENV_VAR_IONIC_MINIFY_JS (line 33) | const ENV_VAR_IONIC_MINIFY_JS = 'IONIC_MINIFY_JS';
  constant ENV_VAR_IONIC_MINIFY_CSS (line 34) | const ENV_VAR_IONIC_MINIFY_CSS = 'IONIC_MINIFY_CSS';
  constant ENV_VAR_IONIC_OPTIMIZE_JS (line 35) | const ENV_VAR_IONIC_OPTIMIZE_JS = 'IONIC_OPTIMIZE_JS';
  constant ENV_VAR_ROOT_DIR (line 37) | const ENV_VAR_ROOT_DIR = 'IONIC_ROOT_DIR';
  constant ENV_VAR_SRC_DIR (line 38) | const ENV_VAR_SRC_DIR = 'IONIC_SRC_DIR';
  constant ENV_VAR_DEEPLINKS_DIR (line 39) | const ENV_VAR_DEEPLINKS_DIR = 'IONIC_DEEPLINKS_DIR';
  constant ENV_VAR_PAGES_DIR (line 40) | const ENV_VAR_PAGES_DIR = 'IONIC_PAGES_DIR';
  constant ENV_VAR_COMPONENTS_DIR (line 41) | const ENV_VAR_COMPONENTS_DIR = 'IONIC_COMPONENTS_DIR';
  constant ENV_VAR_DIRECTIVES_DIR (line 42) | const ENV_VAR_DIRECTIVES_DIR = 'IONIC_DIRECTIVES_DIR';
  constant ENV_VAR_PIPES_DIR (line 43) | const ENV_VAR_PIPES_DIR = 'IONIC_PIPES_DIR';
  constant ENV_VAR_PROVIDERS_DIR (line 44) | const ENV_VAR_PROVIDERS_DIR = 'IONIC_PROVIDERS_DIR';
  constant ENV_VAR_TMP_DIR (line 45) | const ENV_VAR_TMP_DIR = 'IONIC_TMP_DIR';
  constant ENV_VAR_WWW_DIR (line 46) | const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR';
  constant ENV_VAR_FONTS_DIR (line 47) | const ENV_VAR_FONTS_DIR = 'IONIC_FONTS_DIR';
  constant ENV_VAR_SOURCEMAP_DIR (line 48) | const ENV_VAR_SOURCEMAP_DIR = 'IONIC_SOURCEMAP_DIR';
  constant ENV_VAR_HTML_TO_SERVE (line 49) | const ENV_VAR_HTML_TO_SERVE = 'IONIC_HTML_TO_SERVE';
  constant ENV_VAR_BUILD_DIR (line 50) | const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR';
  constant ENV_VAR_NODE_MODULES_DIR (line 51) | const ENV_VAR_NODE_MODULES_DIR = 'IONIC_NODE_MODULES_DIR';
  constant ENV_VAR_ANGULAR_CORE_DIR (line 52) | const ENV_VAR_ANGULAR_CORE_DIR = 'IONIC_ANGULAR_CORE_DIR';
  constant ENV_VAR_TYPESCRIPT_DIR (line 53) | const ENV_VAR_TYPESCRIPT_DIR = 'IONIC_TYPESCRIPT_DIR';
  constant ENV_VAR_RXJS_DIR (line 54) | const ENV_VAR_RXJS_DIR = 'IONIC_RXJS_DIR';
  constant ENV_VAR_IONIC_ANGULAR_DIR (line 55) | const ENV_VAR_IONIC_ANGULAR_DIR = 'IONIC_ANGULAR_DIR';
  constant ENV_VAR_CORE_COMPILER_FILE_PATH (line 56) | const ENV_VAR_CORE_COMPILER_FILE_PATH = 'IONIC_CORE_COMPILER_FILE_PATH';
  constant ENV_VAR_CORE_DIR (line 57) | const ENV_VAR_CORE_DIR = 'IONIC_CORE_DIR';
  constant ENV_VAR_IONIC_ANGULAR_TEMPLATE_DIR (line 58) | const ENV_VAR_IONIC_ANGULAR_TEMPLATE_DIR = 'IONIC_ANGULAR_TEMPLATE_DIR';
  constant ENV_VAR_TARGET (line 59) | const ENV_VAR_TARGET = 'IONIC_TARGET';
  constant ENV_VAR_PLATFORM (line 60) | const ENV_VAR_PLATFORM = 'IONIC_PLATFORM';
  constant ENV_VAR_IONIC_ANGULAR_ENTRY_POINT (line 61) | const ENV_VAR_IONIC_ANGULAR_ENTRY_POINT = 'IONIC_ANGULAR_ENTRY_POINT';
  constant ENV_VAR_APP_SCRIPTS_DIR (line 62) | const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR';
  constant ENV_VAR_GENERATE_SOURCE_MAP (line 63) | const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP';
  constant ENV_VAR_SOURCE_MAP_TYPE (line 64) | const ENV_VAR_SOURCE_MAP_TYPE = 'IONIC_SOURCE_MAP_TYPE';
  constant ENV_VAR_MOVE_SOURCE_MAPS (line 65) | const ENV_VAR_MOVE_SOURCE_MAPS = 'IONIC_MOVE_SOURCE_MAPS';
  constant ENV_TS_CONFIG (line 66) | const ENV_TS_CONFIG = 'IONIC_TS_CONFIG';
  constant ENV_APP_ENTRY_POINT (line 67) | const ENV_APP_ENTRY_POINT = 'IONIC_APP_ENTRY_POINT';
  constant ENV_APP_NG_MODULE_PATH (line 68) | const ENV_APP_NG_MODULE_PATH = 'IONIC_APP_NG_MODULE_PATH';
  constant ENV_APP_NG_MODULE_CLASS (line 69) | const ENV_APP_NG_MODULE_CLASS = 'IONIC_APP_NG_MODULE_CLASS';
  constant ENV_COMPONENTS_NG_MODULE_PATH (line 71) | const ENV_COMPONENTS_NG_MODULE_PATH = 'IONIC_COMPONENTS_NG_MODULE_PATH';
  constant ENV_PIPES_NG_MODULE_PATH (line 72) | const ENV_PIPES_NG_MODULE_PATH = 'IONIC_PIPES_NG_MODULE_PATH';
  constant ENV_DIRECTIVES_NG_MODULE_PATH (line 73) | const ENV_DIRECTIVES_NG_MODULE_PATH = 'IONIC_DIRECTIVES_NG_MODULE_PATH';
  constant ENV_GLOB_UTIL (line 75) | const ENV_GLOB_UTIL = 'IONIC_GLOB_UTIL';
  constant ENV_CLEAN_BEFORE_COPY (line 76) | const ENV_CLEAN_BEFORE_COPY = 'IONIC_CLEAN_BEFORE_COPY';
  constant ENV_READ_CONFIG_JSON (line 77) | const ENV_READ_CONFIG_JSON = 'IONIC_READ_CONFIG_JSON';
  constant ENV_OUTPUT_JS_FILE_NAME (line 78) | const ENV_OUTPUT_JS_FILE_NAME = 'IONIC_OUTPUT_JS_FILE_NAME';
  constant ENV_OUTPUT_CSS_FILE_NAME (line 79) | const ENV_OUTPUT_CSS_FILE_NAME = 'IONIC_OUTPUT_CSS_FILE_NAME';
  constant ENV_WEBPACK_FACTORY (line 80) | const ENV_WEBPACK_FACTORY = 'IONIC_WEBPACK_FACTORY';
  constant ENV_WEBPACK_LOADER (line 81) | const ENV_WEBPACK_LOADER = 'IONIC_WEBPACK_LOADER';
  constant ENV_CACHE_LOADER (line 82) | const ENV_CACHE_LOADER = 'IONIC_CACHE_LOADER';
  constant ENV_AOT_WRITE_TO_DISK (line 83) | const ENV_AOT_WRITE_TO_DISK = 'IONIC_AOT_WRITE_TO_DISK';
  constant ENV_BAIL_ON_LINT_ERROR (line 84) | const ENV_BAIL_ON_LINT_ERROR = 'IONIC_BAIL_ON_LINT_ERROR';
  constant ENV_TYPE_CHECK_ON_LINT (line 85) | const ENV_TYPE_CHECK_ON_LINT = 'IONIC_TYPE_CHECK_ON_LINT';
  constant ENV_ENABLE_LINT (line 86) | const ENV_ENABLE_LINT = 'IONIC_ENABLE_LINT';
  constant ENV_DISABLE_LOGGING (line 87) | const ENV_DISABLE_LOGGING = 'IONIC_DISABLE_LOGGING';
  constant ENV_START_WATCH_TIMEOUT (line 88) | const ENV_START_WATCH_TIMEOUT = 'IONIC_START_WATCH_TIMEOUT';
  constant ENV_NG_MODULE_FILE_NAME_SUFFIX (line 89) | const ENV_NG_MODULE_FILE_NAME_SUFFIX = 'IONIC_NG_MODULE_FILENAME_SUFFIX';
  constant ENV_POLYFILL_FILE_NAME (line 90) | const ENV_POLYFILL_FILE_NAME = 'IONIC_POLYFILL_FILE_NAME';
  constant ENV_PRINT_WEBPACK_DEPENDENCY_TREE (line 91) | const ENV_PRINT_WEBPACK_DEPENDENCY_TREE = 'IONIC_PRINT_WEBPACK_DEPENDENC...
  constant ENV_PARSE_DEEPLINKS (line 92) | const ENV_PARSE_DEEPLINKS = 'IONIC_PARSE_DEEPLINKS';
  constant ENV_PURGE_UNUSED_FONTS (line 93) | const ENV_PURGE_UNUSED_FONTS = 'IONIC_PURGE_UNUSED_FONTS';
  constant ENV_SKIP_IONIC_ANGULAR_VERSION (line 94) | const ENV_SKIP_IONIC_ANGULAR_VERSION = 'IONIC_SKIP_IONIC_ANGULAR_VERSION';
  constant ENV_ACTION_SHEET_CONTROLLER_CLASSNAME (line 98) | const ENV_ACTION_SHEET_CONTROLLER_CLASSNAME = 'IONIC_ACTION_SHEET_CONTRO...
  constant ENV_ACTION_SHEET_CONTROLLER_PATH (line 99) | const ENV_ACTION_SHEET_CONTROLLER_PATH = 'IONIC_ACTION_SHEET_CONTROLLER_...
  constant ENV_ACTION_SHEET_VIEW_CONTROLLER_PATH (line 100) | const ENV_ACTION_SHEET_VIEW_CONTROLLER_PATH = 'IONIC_ACTION_SHEET_VIEW_C...
  constant ENV_ACTION_SHEET_COMPONENT_PATH (line 101) | const ENV_ACTION_SHEET_COMPONENT_PATH = 'IONIC_ACTION_SHEET_COMPONENT_PA...
  constant ENV_ACTION_SHEET_COMPONENT_FACTORY_PATH (line 102) | const ENV_ACTION_SHEET_COMPONENT_FACTORY_PATH = 'IONIC_ACTION_SHEET_COMP...
  constant ENV_ALERT_CONTROLLER_CLASSNAME (line 104) | const ENV_ALERT_CONTROLLER_CLASSNAME = 'IONIC_ALERT_CONTROLLER_CLASSNAME';
  constant ENV_ALERT_CONTROLLER_PATH (line 105) | const ENV_ALERT_CONTROLLER_PATH = 'IONIC_ALERT_CONTROLLER_PATH';
  constant ENV_ALERT_VIEW_CONTROLLER_PATH (line 106) | const ENV_ALERT_VIEW_CONTROLLER_PATH = 'IONIC_ALERT_VIEW_CONTROLLER_PATH';
  constant ENV_ALERT_COMPONENT_PATH (line 107) | const ENV_ALERT_COMPONENT_PATH = 'IONIC_ALERT_COMPONENT_PATH';
  constant ENV_ALERT_COMPONENT_FACTORY_PATH (line 108) | const ENV_ALERT_COMPONENT_FACTORY_PATH = 'IONIC_ALERT_COMPONENT_FACTORY_...
  constant ENV_APP_ROOT_COMPONENT_PATH (line 110) | const ENV_APP_ROOT_COMPONENT_PATH = 'IONIC_APP_ROOT_COMPONENT_PATH';
  constant ENV_LOADING_CONTROLLER_CLASSNAME (line 112) | const ENV_LOADING_CONTROLLER_CLASSNAME = 'IONIC_LOADING_CONTROLLER_CLASS...
  constant ENV_LOADING_CONTROLLER_PATH (line 113) | const ENV_LOADING_CONTROLLER_PATH = 'IONIC_LOADING_CONTROLLER_PATH';
  constant ENV_LOADING_VIEW_CONTROLLER_PATH (line 114) | const ENV_LOADING_VIEW_CONTROLLER_PATH = 'IONIC_LOADING_VIEW_CONTROLLER_...
  constant ENV_LOADING_COMPONENT_PATH (line 115) | const ENV_LOADING_COMPONENT_PATH = 'IONIC_LOADING_COMPONENT_PATH';
  constant ENV_LOADING_COMPONENT_FACTORY_PATH (line 116) | const ENV_LOADING_COMPONENT_FACTORY_PATH = 'IONIC_LOADING_COMPONENT_FACT...
  constant ENV_MODAL_CONTROLLER_CLASSNAME (line 118) | const ENV_MODAL_CONTROLLER_CLASSNAME = 'IONIC_MODAL_CONTROLLER_CLASSNAME';
  constant ENV_MODAL_CONTROLLER_PATH (line 119) | const ENV_MODAL_CONTROLLER_PATH = 'IONIC_MODAL_CONTROLLER_PATH';
  constant ENV_MODAL_VIEW_CONTROLLER_PATH (line 120) | const ENV_MODAL_VIEW_CONTROLLER_PATH = 'IONIC_MODAL_VIEW_CONTROLLER_PATH';
  constant ENV_MODAL_COMPONENT_PATH (line 121) | const ENV_MODAL_COMPONENT_PATH = 'IONIC_MODAL_COMPONENT_PATH';
  constant ENV_MODAL_COMPONENT_FACTORY_PATH (line 122) | const ENV_MODAL_COMPONENT_FACTORY_PATH = 'IONIC_MODAL_COMPONENT_FACTORY_...
  constant ENV_PICKER_CONTROLLER_CLASSNAME (line 124) | const ENV_PICKER_CONTROLLER_CLASSNAME = 'IONIC_PICKER_CONTROLLER_CLASSNA...
  constant ENV_PICKER_CONTROLLER_PATH (line 125) | const ENV_PICKER_CONTROLLER_PATH = 'IONIC_PICKER_CONTROLLER_PATH';
  constant ENV_PICKER_VIEW_CONTROLLER_PATH (line 126) | const ENV_PICKER_VIEW_CONTROLLER_PATH = 'IONIC_PICKER_VIEW_CONTROLLER_PA...
  constant ENV_PICKER_COMPONENT_PATH (line 127) | const ENV_PICKER_COMPONENT_PATH = 'IONIC_PICKER_COMPONENT_PATH';
  constant ENV_PICKER_COMPONENT_FACTORY_PATH (line 128) | const ENV_PICKER_COMPONENT_FACTORY_PATH = 'IONIC_PICKER_COMPONENT_FACTOR...
  constant ENV_POPOVER_CONTROLLER_CLASSNAME (line 130) | const ENV_POPOVER_CONTROLLER_CLASSNAME = 'IONIC_POPOVER_CONTROLLER_CLASS...
  constant ENV_POPOVER_CONTROLLER_PATH (line 131) | const ENV_POPOVER_CONTROLLER_PATH = 'IONIC_POPOVER_CONTROLLER_PATH';
  constant ENV_POPOVER_VIEW_CONTROLLER_PATH (line 132) | const ENV_POPOVER_VIEW_CONTROLLER_PATH = 'IONIC_POPOVER_VIEW_CONTROLLER_...
  constant ENV_POPOVER_COMPONENT_PATH (line 133) | const ENV_POPOVER_COMPONENT_PATH = 'IONIC_POPOVER_COMPONENT_PATH';
  constant ENV_POPOVER_COMPONENT_FACTORY_PATH (line 134) | const ENV_POPOVER_COMPONENT_FACTORY_PATH = 'IONIC_POPOVER_COMPONENT_FACT...
  constant ENV_SELECT_POPOVER_CLASSNAME (line 136) | const ENV_SELECT_POPOVER_CLASSNAME = 'IONIC_SELECT_POPOVER_CLASSNAME';
  constant ENV_SELECT_POPOVER_COMPONENT_PATH (line 137) | const ENV_SELECT_POPOVER_COMPONENT_PATH = 'IONIC_SELECT_POPOVER_COMPONEN...
  constant ENV_SELECT_POPOVER_COMPONENT_FACTORY_PATH (line 138) | const ENV_SELECT_POPOVER_COMPONENT_FACTORY_PATH = 'IONIC_SELECT_POPOVER_...
  constant ENV_TOAST_CONTROLLER_CLASSNAME (line 140) | const ENV_TOAST_CONTROLLER_CLASSNAME = 'IONIC_TOAST_CONTROLLER_CLASSNAME';
  constant ENV_TOAST_CONTROLLER_PATH (line 141) | const ENV_TOAST_CONTROLLER_PATH = 'IONIC_TOAST_CONTROLLER_PATH';
  constant ENV_TOAST_VIEW_CONTROLLER_PATH (line 142) | const ENV_TOAST_VIEW_CONTROLLER_PATH = 'IONIC_TOAST_VIEW_CONTROLLER_PATH';
  constant ENV_TOAST_COMPONENT_PATH (line 143) | const ENV_TOAST_COMPONENT_PATH = 'IONIC_TOAST_COMPONENT_PATH';
  constant ENV_TOAST_COMPONENT_FACTORY_PATH (line 144) | const ENV_TOAST_COMPONENT_FACTORY_PATH = 'IONIC_TOAST_COMPONENT_FACTORY_...
  constant BUNDLER_WEBPACK (line 146) | const BUNDLER_WEBPACK = 'webpack';

FILE: src/util/cordova-config.ts
  type CordovaProject (line 4) | interface CordovaProject {

FILE: src/util/errors.ts
  class BuildError (line 2) | class BuildError extends Error {
    method constructor (line 6) | constructor(error: Error | string) {
  class IgnorableError (line 23) | class IgnorableError extends Error {
    method constructor (line 24) | constructor(msg?: string) {

FILE: src/util/events.ts
  function on (line 7) | function on(eventType: string, listener: {(data?: any): void}) {
  function emit (line 13) | function emit(eventType: string, val?: any) {

FILE: src/util/file-cache.ts
  class FileCache (line 4) | class FileCache {
    method constructor (line 8) | constructor() {
    method set (line 12) | set(key: string, file: File) {
    method get (line 17) | get(key: string): File {
    method has (line 21) | has(key: string) {
    method remove (line 25) | remove(key: string): Boolean {
    method getAll (line 30) | getAll() {
    method getRawStore (line 38) | getRawStore(): Map<string, File> {

FILE: src/util/glob-util.ts
  function isNegative (line 6) | function isNegative(pattern: string) {
  function isString (line 10) | function isString(pattern: string) {
  function assertPatternsInput (line 14) | function assertPatternsInput(patterns: string[]) {
  function generateGlobTasks (line 20) | function generateGlobTasks(patterns: string[], opts: any) {
  function globWrapper (line 59) | function globWrapper(task: GlobObject): Promise<GlobResult[]> {
  function globAll (line 76) | function globAll(globs: string[]): Promise<GlobResult[]> {
  function getBasePath (line 95) | function getBasePath(pattern: string) {
  function isNegatedGlob (line 108) | function isNegatedGlob(pattern: string) {
  function toAbsoluteGlob (line 118) | function toAbsoluteGlob(pattern: string) {
  function globParent (line 152) | function globParent(pattern: string) {
  function isGlob (line 171) | function isGlob(pattern: string) {
  function isExtglob (line 189) | function isExtglob(pattern: string) {
  type GlobObject (line 203) | interface GlobObject {
  type GlobResult (line 209) | interface GlobResult {
  type GlobOptions (line 214) | interface GlobOptions {
  constant DEFAULT_IGNORE_ARRAY (line 218) | const DEFAULT_IGNORE_ARRAY = ['**/*.DS_Store'];

FILE: src/util/helpers.ts
  function getAppScriptsPackageJson (line 18) | function getAppScriptsPackageJson() {
  function getAppScriptsVersion (line 27) | function getAppScriptsVersion(): string {
  function getUserPackageJson (line 32) | function getUserPackageJson(userRootDir: string) {
  function getSystemText (line 39) | function getSystemText(userRootDir: string) {
  function getSystemData (line 57) | function getSystemData(userRootDir: string) {
  function splitLineBreaks (line 85) | function splitLineBreaks(sourceText: string) {
  function titleCase (line 110) | function titleCase(str: string) {
  function writeFileAsync (line 115) | function writeFileAsync(filePath: string, content: string) {
  function readFileAsync (line 126) | function readFileAsync(filePath: string) {
  function readJsonAsync (line 137) | function readJsonAsync(filePath: string): Promise<any> {
  function readAndCacheFile (line 149) | function readAndCacheFile(filePath: string, purge: boolean = false): Pro...
  function unlinkAsync (line 160) | function unlinkAsync(filePath: string|string[]): Promise<any> {
  function rimRafAsync (line 185) | function rimRafAsync(directoryPath: string) {
  function copyFileAsync (line 196) | function copyFileAsync(srcPath: string, destPath: string) {
  function mkDirpAsync (line 212) | function mkDirpAsync(directoryPath: string) {
  function readDirAsync (line 223) | function readDirAsync(pathToDir: string) {
  function setContext (line 234) | function setContext(context: BuildContext) {
  function getContext (line 238) | function getContext() {
  function setParsedDeepLinkConfig (line 242) | function setParsedDeepLinkConfig(map: Map<string, DeepLinkConfigEntry>) {
  function getParsedDeepLinkConfig (line 246) | function getParsedDeepLinkConfig(): Map<string, DeepLinkConfigEntry> {
  function transformSrcPathToTmpPath (line 250) | function transformSrcPathToTmpPath(originalPath: string, context: BuildC...
  function transformTmpPathToSrcPath (line 254) | function transformTmpPathToSrcPath(originalPath: string, context: BuildC...
  function changeExtension (line 258) | function changeExtension(filePath: string, newExtension: string) {
  function escapeHtml (line 266) | function escapeHtml(unsafe: string) {
  function escapeStringForRegex (line 275) | function escapeStringForRegex(input: string) {
  function rangeReplace (line 279) | function rangeReplace(source: string, startIndex: number, endIndex: numb...
  function stringSplice (line 283) | function stringSplice(source: string, startIndex: number, numToDelete: n...
  function toUnixPath (line 287) | function toUnixPath(filePath: string) {
  function generateRandomHexString (line 291) | function generateRandomHexString(numCharacters: number) {
  function getStringPropertyValue (line 295) | function getStringPropertyValue(propertyName: string): string {
  function getIntPropertyValue (line 300) | function getIntPropertyValue(propertyName: string): number {
  function getBooleanPropertyValue (line 305) | function getBooleanPropertyValue(propertyName: string): boolean {
  function convertFilePathToNgFactoryPath (line 310) | function convertFilePathToNgFactoryPath(filePath: string) {
  function printDependencyMap (line 318) | function printDependencyMap(map: Map<string, Set<string>>) {
  function webpackStatsToDependencyMap (line 328) | function webpackStatsToDependencyMap(context: BuildContext, stats: any) {
  function processStatsImpl (line 340) | function processStatsImpl(webpackStats: WebpackStats) {
  function purgeWebpackPrefixFromPath (line 357) | function purgeWebpackPrefixFromPath(filePath: string) {
  function replaceAll (line 361) | function replaceAll(input: string, toReplace: string, replacement: strin...
  function ensureSuffix (line 369) | function ensureSuffix(input: string, suffix: string) {
  function removeSuffix (line 377) | function removeSuffix(input: string, suffix: string) {
  function buildErrorToJson (line 385) | function buildErrorToJson(buildError: BuildError) {
  function jsonToBuildError (line 395) | function jsonToBuildError(nonTypedBuildError: any) {
  function upperCaseFirst (line 404) | function upperCaseFirst(input: string) {
  function sentenceCase (line 411) | function sentenceCase(input: string) {
  function snakeCase (line 416) | function snakeCase(input: string) {
  function constantCase (line 420) | function constantCase(input: string) {
  function camelCase (line 424) | function camelCase(input: string) {
  function paramCase (line 432) | function paramCase(input: string) {
  function pascalCase (line 436) | function pascalCase(input: string) {
  function removeCaseFromString (line 440) | function removeCaseFromString(input: string, inReplacement?: string) {
  function semverStringToObject (line 462) | function semverStringToObject(semverString: string): SemverVersion {

FILE: src/util/helpers/camel-case-regexp.ts
  constant CAMEL_CASE_REGEXP (line 2) | const CAMEL_CASE_REGEXP = /([a-z\xB5\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105...

FILE: src/util/helpers/camel-case-upper-regexp.ts
  constant CAMEL_CASE_UPPER_REGEXP (line 1) | const CAMEL_CASE_UPPER_REGEXP = /([A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u01...

FILE: src/util/helpers/non-word-regexp.ts
  constant NON_WORD_REGEXP (line 1) | const NON_WORD_REGEXP = /[^A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02...

FILE: src/util/hybrid-file-system-factory.ts
  function getInstance (line 6) | function getInstance(writeToDisk: boolean) {

FILE: src/util/hybrid-file-system.ts
  class HybridFileSystem (line 6) | class HybridFileSystem implements FileSystem, VirtualFileSystem {
    method constructor (line 14) | constructor(private fileCache: FileCache) {
    method setInputFileSystem (line 17) | setInputFileSystem(fs: FileSystem) {
    method setOutputFileSystem (line 21) | setOutputFileSystem(fs: FileSystem) {
    method setWriteToDisk (line 25) | setWriteToDisk(write: boolean) {
    method isSync (line 29) | isSync() {
    method stat (line 33) | stat(path: string, callback: Function): any {
    method readdir (line 48) | readdir(path: string, callback: Function): any {
    method readJson (line 52) | readJson(path: string, callback: Function): any {
    method readlink (line 56) | readlink(path: string, callback: Function): any {
    method purge (line 62) | purge(pathsToPurge: string[]): void {
    method readFile (line 70) | readFile(path: string, callback: Function): any {
    method addVirtualFile (line 79) | addVirtualFile(filePath: string, fileContent: string) {
    method getFileContent (line 88) | getFileContent(filePath: string) {
    method getDirectoryStats (line 96) | getDirectoryStats(path: string): VirtualDirStats {
    method getSubDirs (line 100) | getSubDirs(directoryPath: string): string[] {
    method getFileNamesInDirectory (line 106) | getFileNamesInDirectory(directoryPath: string): string[] {
    method getAllFileStats (line 110) | getAllFileStats(): { [filePath: string]: VirtualFileStats } {
    method getAllDirStats (line 114) | getAllDirStats():  { [filePath: string]: VirtualDirStats } {
    method mkdirp (line 118) | mkdirp(filePath: string, callback: Function) {
    method mkdir (line 125) | mkdir(filePath: string, callback: Function) {
    method rmdir (line 132) | rmdir(filePath: string, callback: Function) {
    method unlink (line 139) | unlink(filePath: string, callback: Function) {
    method join (line 146) | join(dirPath: string, fileName: string) {
    method writeFile (line 150) | writeFile(filePath: string, fileContent: Buffer, callback: Function) {

FILE: src/util/interfaces.ts
  type SemverVersion (line 7) | interface SemverVersion {
  type BuildContext (line 13) | interface BuildContext {
  type BuildState (line 70) | enum BuildState {
  type WorkerMessage (line 77) | interface WorkerMessage {
  type WorkerProcess (line 89) | interface WorkerProcess {
  type TaskInfo (line 95) | interface TaskInfo {
  type File (line 104) | interface File {
  type Diagnostic (line 111) | interface Diagnostic {
  type PrintLine (line 124) | interface PrintLine {
  type WsMessage (line 134) | interface WsMessage {
  type BuildUpdateMessage (line 141) | interface BuildUpdateMessage {
  type ChangedFile (line 147) | interface ChangedFile {
  type FileSystem (line 154) | interface FileSystem {
  type VirtualFileSystem (line 170) | interface VirtualFileSystem {
  type DeepLinkDecoratorAndClass (line 180) | interface DeepLinkDecoratorAndClass {
  type DeepLinkPathInfo (line 189) | interface DeepLinkPathInfo {
  type DeepLinkConfigEntry (line 195) | interface DeepLinkConfigEntry extends DeepLinkDecoratorAndClass, DeepLin...
  type AppNgModuleInfo (line 198) | interface AppNgModuleInfo {
  type CodegenOptions (line 203) | interface CodegenOptions {
  type TreeShakeCalcResults (line 211) | interface TreeShakeCalcResults {
  type WebpackStats (line 216) | interface WebpackStats {
  type WebpackModule (line 220) | interface WebpackModule {
  type WebpackDependency (line 225) | interface WebpackDependency {
  type MagicString (line 229) | interface MagicString {
  type CoreCompiler (line 236) | interface CoreCompiler {
  type Packages (line 248) | interface Packages {

FILE: src/util/ionic-project.ts
  type IonicProject (line 5) | interface IonicProject {
  function getProjectJson (line 20) | function getProjectJson(): Promise<IonicProject> {

FILE: src/util/network.ts
  function findClosestOpenPorts (line 3) | function findClosestOpenPorts(host: string, ports: number[]): Promise<nu...
  function findClosestOpenPort (line 8) | function findClosestOpenPort(host: string, port: number): Promise<number> {
  function isPortTaken (line 21) | function isPortTaken(host: string, port: number): Promise<boolean> {

FILE: src/util/open.ts
  function escape (line 57) | function escape(s: string) {

FILE: src/util/promisify.ts
  type Promisify (line 1) | interface Promisify {

FILE: src/util/source-maps.ts
  function copySourcemaps (line 7) | async function copySourcemaps(context: BuildContext, shouldPurge: boolea...
  function purgeSourceMapsIfNeeded (line 44) | function purgeSourceMapsIfNeeded(context: BuildContext): Promise<any> {

FILE: src/util/typescript-utils.ts
  function getTypescriptSourceFile (line 27) | function getTypescriptSourceFile(filePath: string, fileContent: string, ...
  function removeDecorators (line 31) | function removeDecorators(fileName: string, source: string): string {
  function findNodes (line 42) | function findNodes(sourceFile: SourceFile, node: Node, kind: SyntaxKind,...
  function replaceNode (line 52) | function replaceNode(filePath: string, fileContent: string, node: Node, ...
  function removeNode (line 60) | function removeNode(filePath: string, fileContent: string, node: Node) {
  function getNodeStringContent (line 68) | function getNodeStringContent(sourceFile: SourceFile, node: Node) {
  function appendAfter (line 72) | function appendAfter(source: string, node: Node, toAppend: string): stri...
  function appendEmpty (line 76) | function appendEmpty(source: string, position: number, toAppend: string)...
  function appendBefore (line 80) | function appendBefore(filePath: string, fileContent: string, node: Node,...
  function insertNamedImportIfNeeded (line 85) | function insertNamedImportIfNeeded(filePath: string, fileContent: string...
  function replaceNamedImport (line 126) | function replaceNamedImport(filePath: string, fileContent: string, named...
  function replaceImportModuleSpecifier (line 147) | function replaceImportModuleSpecifier(filePath: string, fileContent: str...
  function checkIfFunctionIsCalled (line 159) | function checkIfFunctionIsCalled(filePath: string, fileContent: string, ...
  function getClassDeclarations (line 166) | function getClassDeclarations(sourceFile: SourceFile) {
  function getNgModuleClassName (line 170) | function getNgModuleClassName(filePath: string, fileContent: string) {
  function getNgModuleDecorator (line 197) | function getNgModuleDecorator(fileName: string, sourceFile: SourceFile) {
  function getNgModuleObjectLiteralArg (line 221) | function getNgModuleObjectLiteralArg(decorator: Decorator) {
  function findObjectLiteralElementByName (line 229) | function findObjectLiteralElementByName(properties: NodeArray<ObjectLite...
  function appendNgModuleDeclaration (line 235) | function appendNgModuleDeclaration(filePath: string, fileContent: string...
  function appendNgModuleProvider (line 248) | function appendNgModuleProvider(filePath: string, fileContent: string, d...
  function appendNgModuleExports (line 262) | function appendNgModuleExports(filePath: string, fileContent: string, de...
  constant NG_MODULE_DECORATOR_TEXT (line 276) | const NG_MODULE_DECORATOR_TEXT = 'NgModule';

FILE: src/util/virtual-file-utils.ts
  class VirtualStats (line 5) | class VirtualStats {
    method constructor (line 16) | constructor(protected _path: string) {}
    method isFile (line 18) | isFile() { return false; }
    method isDirectory (line 19) | isDirectory() { return false; }
    method isBlockDevice (line 20) | isBlockDevice() { return false; }
    method isCharacterDevice (line 21) | isCharacterDevice() { return false; }
    method isSymbolicLink (line 22) | isSymbolicLink() { return false; }
    method isFIFO (line 23) | isFIFO() { return false; }
    method isSocket (line 24) | isSocket() { return false; }
    method dev (line 26) | get dev() { return this._dev; }
    method ino (line 27) | get ino() { return this._ino; }
    method mode (line 28) | get mode() { return this._mode; }
    method nlink (line 29) | get nlink() { return 1; }  // Default to 1 hard link.
    method uid (line 30) | get uid() { return this._uid; }
    method gid (line 31) | get gid() { return this._gid; }
    method rdev (line 32) | get rdev() { return 0; }
    method size (line 33) | get size() { return 0; }
    method blksize (line 34) | get blksize() { return 512; }
    method blocks (line 35) | get blocks() { return Math.ceil(this.size / this.blksize); }
    method atime (line 36) | get atime() { return this._atime; }
    method mtime (line 37) | get mtime() { return this._mtime; }
    method ctime (line 38) | get ctime() { return this._ctime; }
    method birthtime (line 39) | get birthtime() { return this._btime; }
  class VirtualDirStats (line 42) | class VirtualDirStats extends VirtualStats {
    method constructor (line 43) | constructor(_fileName: string) {
    method isDirectory (line 47) | isDirectory() { return true; }
    method size (line 49) | get size() { return 1024; }
  class VirtualFileStats (line 52) | class VirtualFileStats extends VirtualStats {
    method constructor (line 54) | constructor(_fileName: string, private _content: string) {
    method content (line 58) | get content() { return this._content; }
    method content (line 59) | set content(v: string) {
    method isFile (line 64) | isFile() { return true; }
    method size (line 66) | get size() { return this._content.length; }

FILE: src/watch.ts
  function watch (line 18) | function watch(context?: BuildContext, configFile?: string) {
  function startWatchers (line 58) | function startWatchers(context: BuildContext, configFile: string) {
  function startWatcher (line 70) | function startWatcher(name: string, watcher: Watcher, context: BuildCont...
  function prepareWatcher (line 151) | function prepareWatcher(context: BuildContext, watcher: Watcher) {
  function buildUpdate (line 184) | function buildUpdate(event: string, filePath: string, context: BuildCont...
  function queueWatchUpdatesForBuild (line 188) | function queueWatchUpdatesForBuild(event: string, filePath: string, cont...
  function queueOrRunBuildUpdate (line 224) | function queueOrRunBuildUpdate(changedFiles: ChangedFile[], context: Bui...
  function copyUpdate (line 268) | function copyUpdate(event: string, filePath: string, context: BuildConte...
  function runBuildUpdate (line 299) | function runBuildUpdate(context: BuildContext, changedFiles: ChangedFile...
  type WatchConfig (line 388) | interface WatchConfig {
  type Watcher (line 392) | interface Watcher {
  constant BUILD_UPDATE_DEBOUNCE_MS (line 409) | const BUILD_UPDATE_DEBOUNCE_MS = 20;

FILE: src/webpack.ts
  constant INCREMENTAL_BUILD_FAILED (line 16) | const INCREMENTAL_BUILD_FAILED = 'incremental_build_failed';
  constant INCREMENTAL_BUILD_SUCCESS (line 17) | const INCREMENTAL_BUILD_SUCCESS = 'incremental_build_success';
  function webpack (line 30) | function webpack(context: BuildContext, configFile: string) {
  function webpackUpdate (line 47) | function webpackUpdate(changedFiles: ChangedFile[], context: BuildContex...
  function webpackWorker (line 72) | function webpackWorker(context: BuildContext, configFile: string): Promi...
  function webpackBuildComplete (line 88) | function webpackBuildComplete(stats: any, context: BuildContext, webpack...
  function setBundledFiles (line 118) | function setBundledFiles(context: BuildContext) {
  function runWebpackFullBuild (line 125) | function runWebpackFullBuild(config: WebpackConfig) {
  function runWebpackIncrementalBuild (line 148) | function runWebpackIncrementalBuild(initializeWatch: boolean, context: B...
  function handleWebpackBuildFailure (line 173) | function handleWebpackBuildFailure(resolve: Function, reject: Function, ...
  function handleWebpackBuildSuccess (line 184) | function handleWebpackBuildSuccess(resolve: Function, reject: Function, ...
  function startWebpackWatch (line 196) | function startWebpackWatch(context: BuildContext, config: WebpackConfig) {
  function getWebpackConfig (line 208) | function getWebpackConfig(context: BuildContext, configFile: string): We...
  function getWebpackConfigFromDictionary (line 218) | function getWebpackConfigFromDictionary(context: BuildContext, webpackCo...
  function getOutputDest (line 227) | function getOutputDest(context: BuildContext) {
  type WebpackConfig (line 241) | interface WebpackConfig {
  type WebpackOutputObject (line 249) | interface WebpackOutputObject {
  type WebpackResolveObject (line 254) | interface WebpackResolveObject {

FILE: src/webpack/cache-loader-impl.ts
  function cacheLoader (line 7) | function cacheLoader(source: string, map: any, webpackContex: any) {

FILE: src/webpack/common-chunks-plugins.ts
  function getCommonChunksPlugin (line 6) | function getCommonChunksPlugin() {
  function checkIfInNodeModules (line 13) | function checkIfInNodeModules(webpackModule: any) {

FILE: src/webpack/ionic-environment-plugin.ts
  class IonicEnvironmentPlugin (line 11) | class IonicEnvironmentPlugin {
    method constructor (line 12) | constructor(private context: BuildContext, private writeToDisk: boolea...
    method apply (line 15) | apply(compiler: any) {
    method initializeWebpackFileSystemCaches (line 83) | private initializeWebpackFileSystemCaches(webpackFileSystem: any) {
  function convertDeepLinkConfigToWebpackFormat (line 108) | function convertDeepLinkConfigToWebpackFormat(parsedDeepLinkConfigs: Map...

FILE: src/webpack/ionic-webpack-factory.ts
  function getIonicEnvironmentPlugin (line 6) | function getIonicEnvironmentPlugin() {
  function getSourceMapperFunction (line 11) | function getSourceMapperFunction(): Function {

FILE: src/webpack/loader-impl.spec.ts
  function getMockContext (line 5) | function getMockContext() {
  function getMockFileCache (line 11) | function getMockFileCache() {
  function getMockWebpackObject (line 18) | function getMockWebpackObject(resourcePath: string) {

FILE: src/webpack/loader-impl.ts
  function webpackLoader (line 6) | function webpackLoader(source: string, map: any, webpackContex: any) {
  function readFile (line 43) | function readFile(fileCache: FileCache, filePath: string) {

FILE: src/webpack/source-mapper.ts
  function provideCorrectSourcePath (line 6) | function provideCorrectSourcePath(webpackObj: any) {
  function provideCorrectSourcePathInternal (line 11) | function provideCorrectSourcePathInternal(webpackObj: any, context: Buil...

FILE: src/webpack/watch-memory-system.ts
  class WatchMemorySystem (line 6) | class WatchMemorySystem {
    method constructor (line 21) | constructor(private fileCache: FileCache, private srcDir: string) {
    method close (line 24) | close() {
    method pause (line 28) | pause() {
    method watch (line 32) | watch(filePathsBeingWatched: string[], dirPaths: string[], missing: st...
    method startListening (line 52) | startListening() {
    method processChanges (line 63) | processChanges(filePaths: string[]) {
    method doneAggregating (line 73) | doneAggregating(changes: Set<string>) {
    method getTimes (line 84) | getTimes(allFiles: string[], startTime: number, fileCache: FileCache) {

FILE: src/worker-client.ts
  function runWorker (line 9) | function runWorker(taskModule: string, taskWorker: string, context: Buil...
  function killWorker (line 65) | function killWorker(pid: number) {
  function createWorker (line 81) | function createWorker(taskModule: string): any {

FILE: src/worker-process.ts
  function taskResolve (line 29) | function taskResolve(taskModule: string, taskWorker: string, val: any) {
  function taskReject (line 43) | function taskReject(taskModule: string, taskWorker: string, error: Error) {
  function taskError (line 59) | function taskError(taskModule: string, taskWorker: string, error: Error) {
Condensed preview — 148 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (871K chars).
[
  {
    "path": ".editorconfig",
    "chars": 244,
    "preview": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 504,
    "preview": "**Note: for support questions, please use one of these channels:**\n\nhttps://forum.ionicframework.com/\nhttp://ionicworldw"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 113,
    "preview": "#### Short description of what this resolves:\n\n\n#### Changes proposed in this pull request:\n\n-\n-\n-\n\n**Fixes**: #\n"
  },
  {
    "path": ".gitignore",
    "chars": 663,
    "preview": ".DS_Store\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generat"
  },
  {
    "path": ".npmrc",
    "chars": 19,
    "preview": "package-lock=false\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 56430,
    "preview": "<a name=\"3.2.4\"></a>\n## [3.2.4](https://github.com/ionic-team/ionic-app-scripts/compare/v3.2.3...v3.2.4) (2019-05-24)\n\n\n"
  },
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2016 Drifty Co\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 17960,
    "preview": "[![npm version](https://img.shields.io/npm/v/@ionic/app-scripts.svg)](https://www.npmjs.com/package/@ionic/app-scripts)\n"
  },
  {
    "path": "bin/ion-dev.js",
    "chars": 30392,
    "preview": "window.IonicDevServerConfig = window.IonicDevServerConfig || {};\n\nwindow.IonicDevServer = {\n  start: function() {\n    th"
  },
  {
    "path": "bin/ionic-app-scripts.js",
    "chars": 687,
    "preview": "#!/usr/bin/env node\n\nif (process.argv.length > 2) {\n\n  if (process.env.npm_config_argv && process.env.npm_config_argv.le"
  },
  {
    "path": "circle.yml",
    "chars": 121,
    "preview": "machine:\n  node:\n    version: 6.9.5\n  post:\n    - npm install -g npm@3.x.x\ntest:\n  override:\n    - nvm use 6 && npm test"
  },
  {
    "path": "config/cleancss.config.js",
    "chars": 326,
    "preview": "\n// https://www.npmjs.com/package/clean-css\n\nmodule.exports = {\n  /**\n   * sourceFileName: the file name of the src css "
  },
  {
    "path": "config/copy.config.js",
    "chars": 880,
    "preview": "// this is a custom dictionary to make it easy to extend/override\n// provide a name for an entry, it can be anything suc"
  },
  {
    "path": "config/sass.config.js",
    "chars": 2655,
    "preview": "\n// https://www.npmjs.com/package/node-sass\n\nmodule.exports = {\n\n  /**\n   * outputFilename: The filename of the saved CS"
  },
  {
    "path": "config/uglifyjs.config.js",
    "chars": 249,
    "preview": "\n// https://www.npmjs.com/package/uglify-es\n\nmodule.exports = {\n\n  /**\n   * mangle: uglify 2's mangle option\n   */\n  man"
  },
  {
    "path": "config/watch.config.js",
    "chars": 696,
    "preview": "var watch = require('../dist/watch');\nvar copy = require('../dist/copy');\nvar copyConfig = require('./copy.config');\n\n//"
  },
  {
    "path": "config/webpack.config.js",
    "chars": 3920,
    "preview": "/*\n * The webpack config exports an object that has a valid webpack configuration\n * For each environment name. By defau"
  },
  {
    "path": "lab/index.html",
    "chars": 5566,
    "preview": "<!doctype html>\n<html>\n  <head>\n    <title>Ionic Lab</title>\n    <meta charset=\"utf-8\">\n    <link rel=\"icon\" type=\"image"
  },
  {
    "path": "lab/static/css/style.css",
    "chars": 13909,
    "preview": "@font-face {font-family: 'AvenirNextLTPro-Regular';src: url('http://code.ionicframework.com/assets/fonts/28882F_0_0.eot'"
  },
  {
    "path": "lab/static/js/lab.js",
    "chars": 7413,
    "preview": "var $ = document.querySelector.bind(document);\n\nvar API_ROOT = '/ionic-lab/api/v1';\n\nvar APP_CONFIG = {};\n\nfunction load"
  },
  {
    "path": "package.json",
    "chars": 3729,
    "preview": "{\n  \"name\": \"@ionic/app-scripts\",\n  \"version\": \"3.2.4\",\n  \"description\": \"Scripts for Ionic Projects\",\n  \"homepage\": \"ht"
  },
  {
    "path": "preprocessor.js",
    "chars": 294,
    "preview": "const tsc = require('typescript');\nconst tsConfig = require('./tsconfig.json');\n\nmodule.exports = {\n  process(src, path)"
  },
  {
    "path": "scripts/commit-changelog.js",
    "chars": 314,
    "preview": "var execSync = require('child_process').execSync;\n\nfunction main() {\n  try {\n    execSync('git add ./CHANGELOG.md');\n   "
  },
  {
    "path": "scripts/create-github-release.js",
    "chars": 940,
    "preview": "var path = require('path');\nvar execSync = require('child_process').execSync;\n\nvar GithubApi = require('github');\n\nvar c"
  },
  {
    "path": "scripts/publish-nightly.js",
    "chars": 2265,
    "preview": "var execSync = require('child_process').execSync;\nvar fs = require('fs');\nvar path = require('path');\n\nvar packageJsonPa"
  },
  {
    "path": "src/aot/aot-compiler.ts",
    "chars": 9209,
    "preview": "import { readFileSync } from 'fs-extra';\nimport { extname, normalize, resolve } from 'path';\n\nimport 'reflect-metadata';"
  },
  {
    "path": "src/aot/compiler-host-factory.ts",
    "chars": 446,
    "preview": "import { CompilerOptions } from 'typescript';\nimport { FileSystemCompilerHost } from './compiler-host';\nimport { getInst"
  },
  {
    "path": "src/aot/compiler-host.ts",
    "chars": 3543,
    "preview": "import { normalize } from 'path';\nimport { CancellationToken, CompilerHost, CompilerOptions, createCompilerHost, ScriptT"
  },
  {
    "path": "src/aot/utils.ts",
    "chars": 7186,
    "preview": "import { basename, dirname, join, normalize, relative, resolve } from 'path';\nimport {\n  CallExpression,\n  Identifier,\n "
  },
  {
    "path": "src/build/util.ts",
    "chars": 4567,
    "preview": "import { join } from 'path';\n\nimport { getTsConfigAsync, TsConfig } from '../transpile';\nimport * as Constants from '../"
  },
  {
    "path": "src/build.spec.ts",
    "chars": 8097,
    "preview": "import * as Constants from './util/constants';\nimport { BuildContext } from './util/interfaces';\nimport * as helpers fro"
  },
  {
    "path": "src/build.ts",
    "chars": 10480,
    "preview": "import { join } from 'path';\n\nimport {\n  readVersionOfDependencies,\n  scanSrcTsFiles,\n  validateRequiredFilesExist,\n  va"
  },
  {
    "path": "src/bundle.spec.ts",
    "chars": 3824,
    "preview": "import * as bundle from './bundle';\nimport * as webpack from './webpack';\nimport * as Constants from './util/constants';"
  },
  {
    "path": "src/bundle.ts",
    "chars": 1132,
    "preview": "import { BuildContext, ChangedFile } from './util/interfaces';\nimport { BuildError, IgnorableError } from './util/errors"
  },
  {
    "path": "src/clean.spec.ts",
    "chars": 867,
    "preview": "import * as fs from 'fs-extra';\nimport * as clean from './clean';\n\ndescribe('clean task', () => {\n\n  describe('clean', ("
  },
  {
    "path": "src/clean.ts",
    "chars": 607,
    "preview": "import { BuildContext } from './util/interfaces';\nimport { BuildError } from './util/errors';\nimport { emptyDirSync } fr"
  },
  {
    "path": "src/cleancss.spec.ts",
    "chars": 6651,
    "preview": "import { join } from 'path';\nimport * as cleanCss from './cleancss';\n\nimport * as cleanCssFactory from './util/clean-css"
  },
  {
    "path": "src/cleancss.ts",
    "chars": 2413,
    "preview": "import { join } from 'path';\nimport { BuildContext, TaskInfo } from './util/interfaces';\nimport { BuildError } from './u"
  },
  {
    "path": "src/copy.spec.ts",
    "chars": 2037,
    "preview": "import * as copy from './copy';\n\nimport * as config from './util/config';\n\ndescribe('copy task', () => {\n  describe('cop"
  },
  {
    "path": "src/copy.ts",
    "chars": 11974,
    "preview": "import { mkdirpSync } from 'fs-extra';\nimport { dirname as pathDirname, join as pathJoin, relative as pathRelative, reso"
  },
  {
    "path": "src/core/bundle-components.ts",
    "chars": 1825,
    "preview": "import { BuildContext, CoreCompiler } from '../util/interfaces';\nimport { Logger } from '../logger/logger';\nimport * as "
  },
  {
    "path": "src/core/inject-script.spec.ts",
    "chars": 4129,
    "preview": "import { injectCoreHtml } from './inject-scripts';\n\n\ndescribe('Inject Scripts', () => {\n\n  describe('injectCoreHtml', ()"
  },
  {
    "path": "src/core/inject-scripts.ts",
    "chars": 1631,
    "preview": "import { BuildContext } from '../util/interfaces';\nimport { buildIonicGlobal } from './ionic-global';\nimport { readFileA"
  },
  {
    "path": "src/core/ionic-global.spec.ts",
    "chars": 495,
    "preview": "import { BuildContext } from '../util/interfaces';\nimport { buildIonicGlobal } from './ionic-global';\n\n\ndescribe('Ionic "
  },
  {
    "path": "src/core/ionic-global.ts",
    "chars": 1127,
    "preview": "import { BuildContext } from '../util/interfaces';\nimport { getSystemData, toUnixPath } from '../util/helpers';\n\n\nexport"
  },
  {
    "path": "src/declarations.d.ts",
    "chars": 365,
    "preview": "declare module 'autoprefixer';\ndeclare module 'chalk';\ndeclare module 'cross-spawn';\ndeclare module 'mime-types';\ndeclar"
  },
  {
    "path": "src/deep-linking/util.spec.ts",
    "chars": 67468,
    "preview": "import { join } from 'path';\n\nimport * as ts from 'typescript';\n\nimport * as util from './util';\nimport * as transpile f"
  },
  {
    "path": "src/deep-linking/util.ts",
    "chars": 26044,
    "preview": "import { basename, dirname, extname, relative, sep } from 'path';\n\nimport {\n  ArrayLiteralExpression,\n  CallExpression,\n"
  },
  {
    "path": "src/deep-linking.spec.ts",
    "chars": 1482,
    "preview": "import { join } from 'path';\n\nimport * as deepLinking from './deep-linking';\nimport * as deeplinkUtils from './deep-link"
  },
  {
    "path": "src/deep-linking.ts",
    "chars": 4430,
    "preview": "import { extname } from 'path';\n\nimport { scanSrcTsFiles } from './build/util';\nimport { Logger } from './logger/logger'"
  },
  {
    "path": "src/dev-client/sass/_code-block.scss",
    "chars": 1874,
    "preview": "\n#ion-diagnostics .ion-diagnostic-blob {\n  overflow-x: auto;\n  overflow-y: hidden;\n  border-bottom-right-radius: 3px;\n  "
  },
  {
    "path": "src/dev-client/sass/_diagnostics.scss",
    "chars": 1699,
    "preview": "\n#ion-diagnostics * {\n  box-sizing: border-box;\n}\n\n#ion-diagnostics {\n  direction: ltr;\n  \n  position: absolute;\n  top: "
  },
  {
    "path": "src/dev-client/sass/_header.scss",
    "chars": 1126,
    "preview": "\n.ion-diagnostics-header {\n  background: $header-background;\n  border-bottom: $hairlines-width solid $header-border-colo"
  },
  {
    "path": "src/dev-client/sass/_options-menu.scss",
    "chars": 1707,
    "preview": "\n$action-sheet-width:                             100% !default;\n$action-sheet-max-width:                         500px "
  },
  {
    "path": "src/dev-client/sass/_stack-block.scss",
    "chars": 456,
    "preview": "\n#ion-diagnostics .ion-diagnostic-stack-header {\n  padding: 5px 10px;\n  border-top: 1px solid $diagnostics-border;\n  bor"
  },
  {
    "path": "src/dev-client/sass/_system-info.scss",
    "chars": 195,
    "preview": "\n#ion-diagnostics-system-info {\n  margin: 0 20px 20px 20px;\n  padding: 0px 0 20px 0;\n\n  font-family: $code-font-family;\n"
  },
  {
    "path": "src/dev-client/sass/_toast.scss",
    "chars": 2055,
    "preview": "\n#ion-diagnostics-toast {\n  position: absolute;\n  top: 10px;\n  right: 10px;\n  left: 10px;\n  z-index: $z-index-toast;\n  m"
  },
  {
    "path": "src/dev-client/sass/ion-dev.scss",
    "chars": 1373,
    "preview": "\n// Font Family\n// -----------------------------\n$body-font-family: -apple-system, \"Roboto\", BlinkMacSystemFont, \"Segoe "
  },
  {
    "path": "src/dev-server/http-server.ts",
    "chars": 5402,
    "preview": "import * as path from 'path';\nimport { injectNotificationScript } from './injector';\nimport { injectLiveReloadScript } f"
  },
  {
    "path": "src/dev-server/injector.ts",
    "chars": 1502,
    "preview": "import { getAppScriptsVersion, getSystemText } from '../util/helpers';\nimport { LOGGER_DIR } from './serve-config';\n\n\nco"
  },
  {
    "path": "src/dev-server/lab.ts",
    "chars": 707,
    "preview": "import * as path from 'path';\n\nimport { buildCordovaConfig, CordovaProject } from '../util/cordova-config';\n\n/**\n * Main"
  },
  {
    "path": "src/dev-server/live-reload.ts",
    "chars": 1876,
    "preview": "import { ChangedFile } from '../util/interfaces';\nimport { hasDiagnostics } from '../logger/logger-diagnostics';\nimport "
  },
  {
    "path": "src/dev-server/notification-server.ts",
    "chars": 4333,
    "preview": "// Ionic Dev Server: Server Side Logger\nimport { BuildUpdateMessage, WsMessage } from '../util/interfaces';\nimport { Log"
  },
  {
    "path": "src/dev-server/serve-config.ts",
    "chars": 795,
    "preview": "import * as path from 'path';\n\nexport interface ServeConfig {\n  httpPort: number;\n  host: string;\n  hostBaseUrl: string;"
  },
  {
    "path": "src/generators/constants.ts",
    "chars": 626,
    "preview": "export const CLASSNAME_VARIABLE = '$CLASSNAME';\nexport const TAB_CONTENT_VARIABLE = '$TAB_CONTENT';\nexport const TAB_VAR"
  },
  {
    "path": "src/generators/util.spec.ts",
    "chars": 22048,
    "preview": "import { BuildContext } from '../util/interfaces';\nimport { basename, join } from 'path';\nimport * as fs from 'fs';\nimpo"
  },
  {
    "path": "src/generators/util.ts",
    "chars": 13639,
    "preview": "import { basename, dirname, extname, join, relative, sep } from 'path';\nimport { readdirSync, existsSync, writeFileSync,"
  },
  {
    "path": "src/generators.ts",
    "chars": 2945,
    "preview": "import * as Constants from './util/constants';\nimport { BuildContext } from './util/interfaces';\nimport { hydrateRequest"
  },
  {
    "path": "src/highlight/github-gist.scss",
    "chars": 841,
    "preview": "/**\n * GitHub Gist Theme\n * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro\n * https://highlightjs.or"
  },
  {
    "path": "src/highlight/highlight.spec.ts",
    "chars": 6082,
    "preview": "import { highlight, highlightError } from './highlight';\n\n\ndescribe('highlight.js', () => {\n\n  describe('highlightError'"
  },
  {
    "path": "src/highlight/highlight.ts",
    "chars": 30350,
    "preview": "/**\n * Ported from highlight.js\n * Syntax highlighting with language autodetection.\n * https://highlightjs.org/\n * Copyr"
  },
  {
    "path": "src/index.ts",
    "chars": 1474,
    "preview": "export { build } from './build';\nexport { bundle, bundleUpdate } from './bundle';\nexport { clean } from './clean';\nexpor"
  },
  {
    "path": "src/lint/lint-factory.spec.ts",
    "chars": 5031,
    "preview": "import { Configuration, Linter } from 'tslint';\nimport { DiagnosticCategory } from 'typescript';\nimport * as ts from 'ty"
  },
  {
    "path": "src/lint/lint-factory.ts",
    "chars": 2524,
    "preview": "import { Configuration, Linter, LintResult } from 'tslint';\nimport { Program, getPreEmitDiagnostics, Diagnostic } from '"
  },
  {
    "path": "src/lint/lint-utils.spec.ts",
    "chars": 4834,
    "preview": "import * as fs from 'fs';\nimport { DiagnosticCategory } from 'typescript';\nimport * as helpers from '../util/helpers';\ni"
  },
  {
    "path": "src/lint/lint-utils.ts",
    "chars": 4485,
    "preview": "import * as fs from 'fs';\nimport { Linter, LintResult, RuleFailure } from 'tslint';\nimport { Diagnostic, Program } from "
  },
  {
    "path": "src/lint.spec.ts",
    "chars": 1226,
    "preview": "import * as Constants from './util/constants';\nimport * as workerClient from './worker-client';\nimport { lint } from './"
  },
  {
    "path": "src/lint.ts",
    "chars": 3471,
    "preview": "import { access } from 'fs';\nimport { join } from 'path';\n\nimport { lintFiles } from './lint/lint-utils';\nimport { creat"
  },
  {
    "path": "src/logger/logger-diagnostics.ts",
    "chars": 10188,
    "preview": "import { BuildContext, Diagnostic, PrintLine } from '../util/interfaces';\nimport { escapeHtml, titleCase } from '../util"
  },
  {
    "path": "src/logger/logger-runtime.ts",
    "chars": 4745,
    "preview": "import { Diagnostic, PrintLine } from '../util/interfaces';\nimport { escapeHtml, splitLineBreaks } from '../util/helpers"
  },
  {
    "path": "src/logger/logger-sass.ts",
    "chars": 3843,
    "preview": "import { BuildContext, Diagnostic, PrintLine } from '../util/interfaces';\nimport { highlight } from '../highlight/highli"
  },
  {
    "path": "src/logger/logger-tslint.ts",
    "chars": 2778,
    "preview": "import { IRuleFailurePositionJson, RuleFailure } from 'tslint';\nimport { splitLineBreaks } from '../util/helpers';\nimpor"
  },
  {
    "path": "src/logger/logger-typescript.ts",
    "chars": 3450,
    "preview": "import { BuildContext, Diagnostic, PrintLine } from '../util/interfaces';\nimport { Logger } from './logger';\nimport { hi"
  },
  {
    "path": "src/logger/logger.ts",
    "chars": 7452,
    "preview": "import { BuildError, IgnorableError } from '../util/errors';\nimport { isDebugMode } from '../util/config';\nimport * as c"
  },
  {
    "path": "src/minify.ts",
    "chars": 1021,
    "preview": "import * as Constants from './util/constants';\nimport { getBooleanPropertyValue } from './util/helpers';\nimport { BuildC"
  },
  {
    "path": "src/mocks/mock-helpers.ts",
    "chars": 188,
    "preview": "import { BuildContext } from '../util/interfaces';\n\nexport function setContext(context: BuildContext) {\n}\n\nexport functi"
  },
  {
    "path": "src/ngc.ts",
    "chars": 2453,
    "preview": "import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map';\n\nimport { runAot } from './aot/aot-com"
  },
  {
    "path": "src/optimization/remove-unused-fonts.spec.ts",
    "chars": 7442,
    "preview": "import { join } from 'path';\n\nimport { removeUnusedFonts } from './remove-unused-fonts';\nimport * as helpers from '../ut"
  },
  {
    "path": "src/optimization/remove-unused-fonts.ts",
    "chars": 2858,
    "preview": "import { extname, join } from 'path';\n\nimport { Logger } from '../logger/logger';\nimport * as Constants from '../util/co"
  },
  {
    "path": "src/postprocess.ts",
    "chars": 1756,
    "preview": "import { basename, dirname, join, relative } from 'path';\nimport { emptyDirSync, mkdirpSync, writeFileSync } from 'fs-ex"
  },
  {
    "path": "src/preprocess.spec.ts",
    "chars": 1060,
    "preview": "import { join } from 'path';\nimport * as preprocess from './preprocess';\nimport * as deeplink from './deep-linking';\nimp"
  },
  {
    "path": "src/preprocess.ts",
    "chars": 1171,
    "preview": "import { join } from 'path';\n\nimport { Logger } from './logger/logger';\nimport * as Constants from './util/constants';\ni"
  },
  {
    "path": "src/sass.ts",
    "chars": 15529,
    "preview": "import { basename, dirname, join, sep } from 'path';\nimport { BuildContext, BuildState, ChangedFile, TaskInfo } from './"
  },
  {
    "path": "src/serve.spec.ts",
    "chars": 4644,
    "preview": "import * as serve from './serve';\nimport * as config from './util/config';\nimport { BuildContext } from './util/interfac"
  },
  {
    "path": "src/serve.ts",
    "chars": 6113,
    "preview": "import * as express from 'express';\nimport { BuildContext } from './util/interfaces';\nimport { getConfigValue, hasConfig"
  },
  {
    "path": "src/template.spec.ts",
    "chars": 10936,
    "preview": "import { join, resolve } from 'path';\n\nimport * as mockFs from 'mock-fs';\n\nimport { Logger } from './logger/logger';\nimp"
  },
  {
    "path": "src/template.ts",
    "chars": 7453,
    "preview": "import { readFileSync, writeFileSync } from 'fs';\nimport { dirname, extname, join, parse, resolve } from 'path';\n\nimport"
  },
  {
    "path": "src/transpile-worker.ts",
    "chars": 893,
    "preview": "import { BuildContext } from './util/interfaces';\nimport { transpileWorker, TranspileWorkerMessage, TranspileWorkerConfi"
  },
  {
    "path": "src/transpile.spec.ts",
    "chars": 1058,
    "preview": "import * as transpile from './transpile';\n\nimport { FileCache } from './util/file-cache';\nimport { BuildContext } from '"
  },
  {
    "path": "src/transpile.ts",
    "chars": 15309,
    "preview": "import { fork, ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport { readFileSync } from "
  },
  {
    "path": "src/uglifyjs.ts",
    "chars": 2949,
    "preview": "import * as Uglify from 'uglify-es';\n\nimport { Logger } from './logger/logger';\nimport { fillConfigDefaults, generateCon"
  },
  {
    "path": "src/upgrade-scripts/add-default-ngmodules.spec.ts",
    "chars": 7268,
    "preview": "import * as fs from 'fs';\nimport { join } from 'path';\n\nimport * as upgradeScript from './add-default-ngmodules';\nimport"
  },
  {
    "path": "src/upgrade-scripts/add-default-ngmodules.ts",
    "chars": 2521,
    "preview": "import { writeFileSync } from 'fs';\nimport { join } from 'path';\n\nimport { generateDefaultDeepLinkNgModuleContent, getDe"
  },
  {
    "path": "src/util/clean-css-factory.ts",
    "chars": 367,
    "preview": "import * as cleanCss from 'clean-css';\n\nexport function getCleanCssInstance(options: cleanCss.Options) {\n  return new cl"
  },
  {
    "path": "src/util/config.spec.ts",
    "chars": 21458,
    "preview": "import { join, resolve } from 'path';\n\nimport * as helpers from './helpers';\nimport { BuildContext } from './interfaces'"
  },
  {
    "path": "src/util/config.ts",
    "chars": 33183,
    "preview": "import { join, resolve } from 'path';\nimport { accessSync, readJSONSync, statSync } from 'fs-extra';\n\nimport { Logger } "
  },
  {
    "path": "src/util/constants.ts",
    "chars": 8039,
    "preview": "export const FILE_CHANGE_EVENT = 'change';\nexport const FILE_ADD_EVENT = 'add';\nexport const FILE_DELETE_EVENT = 'unlink"
  },
  {
    "path": "src/util/cordova-config.spec.ts",
    "chars": 1508,
    "preview": "import * as cordovaConfig from './cordova-config';\n\ndescribe('parseConfig function', () => {\n  it('should return {} when"
  },
  {
    "path": "src/util/cordova-config.ts",
    "chars": 1119,
    "preview": "import * as fs from 'fs';\nimport * as xml2js from 'xml2js';\n\nexport interface CordovaProject {\n  name?: string;\n  id?: s"
  },
  {
    "path": "src/util/errors.spec.ts",
    "chars": 1046,
    "preview": "import { BuildError } from './errors';\n\n\ndescribe('Errors', () => {\n\n  describe('BuildError', () => {\n\n    it('should cr"
  },
  {
    "path": "src/util/errors.ts",
    "chars": 771,
    "preview": "\nexport class BuildError extends Error {\n  hasBeenLogged = false;\n  isFatal: boolean = false;\n\n  constructor(error: Erro"
  },
  {
    "path": "src/util/events.ts",
    "chars": 776,
    "preview": "import { EventEmitter } from 'events';\nimport { Logger } from '../logger/logger';\n\nconst emmitter = new EventEmitter();\n"
  },
  {
    "path": "src/util/file-cache.ts",
    "chars": 675,
    "preview": "import { File } from './interfaces';\n\n\nexport class FileCache {\n\n  private map: Map<string, File>;\n\n  constructor() {\n  "
  },
  {
    "path": "src/util/glob-util.ts",
    "chars": 5577,
    "preview": "import { dirname, isAbsolute, join, normalize, resolve as pathResolve, sep } from 'path';\nimport * as globFunction from "
  },
  {
    "path": "src/util/helpers/camel-case-regexp.ts",
    "chars": 8891,
    "preview": "/* https://raw.githubusercontent.com/blakeembrey/no-case/master/vendor/camel-case-regexp.js */\nexport const CAMEL_CASE_R"
  },
  {
    "path": "src/util/helpers/camel-case-upper-regexp.ts",
    "chars": 11900,
    "preview": "export const CAMEL_CASE_UPPER_REGEXP = /([A-Z\\xC0-\\xD6\\xD8-\\xDE\\u0100\\u0102\\u0104\\u0106\\u0108\\u010A\\u010C\\u010E\\u0110\\u0"
  },
  {
    "path": "src/util/helpers/non-word-regexp.ts",
    "chars": 5088,
    "preview": "export const NON_WORD_REGEXP = /[^A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\"
  },
  {
    "path": "src/util/helpers.spec.ts",
    "chars": 12167,
    "preview": "import { BuildError } from './errors';\nimport * as helpers from './helpers';\n\nlet originalEnv: any = null;\ndescribe('hel"
  },
  {
    "path": "src/util/helpers.ts",
    "chars": 13521,
    "preview": "import { randomBytes } from 'crypto';\nimport { basename, dirname, extname, join } from 'path';\nimport { createReadStream"
  },
  {
    "path": "src/util/hybrid-file-system-factory.ts",
    "chars": 335,
    "preview": "import { HybridFileSystem } from './hybrid-file-system';\nimport { getContext } from './helpers';\n\nlet instance: HybridFi"
  },
  {
    "path": "src/util/hybrid-file-system.ts",
    "chars": 4462,
    "preview": "import { basename, dirname, join } from 'path';\nimport { FileSystem, VirtualFileSystem } from './interfaces';\nimport { F"
  },
  {
    "path": "src/util/interfaces.ts",
    "chars": 5430,
    "preview": "import * as CompilerCLI from '@angular/compiler-cli';\nimport { CompilerHost, CompilerOptions, Program } from 'typescript"
  },
  {
    "path": "src/util/ionic-project.ts",
    "chars": 654,
    "preview": "import * as path from 'path';\nimport * as fs from 'fs';\nimport { promisify } from './promisify';\n\nexport interface Ionic"
  },
  {
    "path": "src/util/network.ts",
    "chars": 998,
    "preview": "import * as net from 'net';\n\nexport function findClosestOpenPorts(host: string, ports: number[]): Promise<number[]> {\n  "
  },
  {
    "path": "src/util/open.ts",
    "chars": 1687,
    "preview": "import * as childProcess from 'child_process';\n\n\n/**\n * open a file or uri using the default application for the file ty"
  },
  {
    "path": "src/util/promisify.ts",
    "chars": 1250,
    "preview": "export interface Promisify {\n  <T>(func: (callback: (err: any, result: T) => void) => void): () => Promise<T>;\n  <T, A1>"
  },
  {
    "path": "src/util/source-maps.spec.ts",
    "chars": 4892,
    "preview": "import { join } from 'path';\nimport * as Constants from './constants';\nimport * as sourceMaps from './source-maps';\nimpo"
  },
  {
    "path": "src/util/source-maps.ts",
    "chars": 1895,
    "preview": "import { join, relative, basename } from 'path';\nimport { ensureDir, mkdirpSync } from 'fs-extra';\nimport * as Constants"
  },
  {
    "path": "src/util/typescript-utils.spec.ts",
    "chars": 9549,
    "preview": "import * as tsUtils from './typescript-utils';\n\ndescribe('typescript-utils', () => {\n  describe('getNgModuleClassName', "
  },
  {
    "path": "src/util/typescript-utils.ts",
    "chars": 12438,
    "preview": "import * as path from 'path';\n\nimport {\n  CallExpression,\n  ClassDeclaration,\n  Decorator,\n  Identifier,\n  ImportClause,"
  },
  {
    "path": "src/util/virtual-file-utils.ts",
    "chars": 1876,
    "preview": "import { Stats } from 'fs';\n\nconst dev = Math.floor(Math.random() * 10000);\n\nexport class VirtualStats {\n  protected _ct"
  },
  {
    "path": "src/watch.spec.ts",
    "chars": 30597,
    "preview": "import { join, resolve } from 'path';\n\nimport * as build from './build';\nimport { BuildContext, BuildState, ChangedFile "
  },
  {
    "path": "src/watch.ts",
    "chars": 13666,
    "preview": "import { extname, join, normalize, resolve as pathResolve } from 'path';\n\nimport * as chokidar from 'chokidar';\n\nimport "
  },
  {
    "path": "src/webpack/cache-loader-impl.ts",
    "chars": 1015,
    "preview": "import { normalize, resolve } from 'path';\nimport * as Constants from '../util/constants';\nimport { changeExtension, get"
  },
  {
    "path": "src/webpack/cache-loader.ts",
    "chars": 150,
    "preview": "import { cacheLoader } from './cache-loader-impl';\n\nmodule.exports = function loader(source: string, map: any) {\n  cache"
  },
  {
    "path": "src/webpack/common-chunks-plugins.ts",
    "chars": 536,
    "preview": " const CommonChunksPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');\n\nimport * as Constants from '../util/con"
  },
  {
    "path": "src/webpack/ionic-environment-plugin.ts",
    "chars": 5219,
    "preview": "import { join } from 'path';\nimport * as Constants from '../util/constants';\nimport { changeExtension, getParsedDeepLink"
  },
  {
    "path": "src/webpack/ionic-webpack-factory.ts",
    "chars": 500,
    "preview": "import { getCommonChunksPlugin } from './common-chunks-plugins';\nimport { IonicEnvironmentPlugin } from './ionic-environ"
  },
  {
    "path": "src/webpack/loader-impl.spec.ts",
    "chars": 6280,
    "preview": "import { join } from 'path';\nimport * as loader from './loader-impl';\nimport *  as helpers from '../util/helpers';\n\nfunc"
  },
  {
    "path": "src/webpack/loader-impl.ts",
    "chars": 1952,
    "preview": "import { normalize, resolve } from 'path';\nimport { changeExtension, getContext, readAndCacheFile} from '../util/helpers"
  },
  {
    "path": "src/webpack/loader.ts",
    "chars": 148,
    "preview": "import { webpackLoader } from './loader-impl';\n\nmodule.exports = function loader(source: string, map: any) {\n  webpackLo"
  },
  {
    "path": "src/webpack/source-mapper.ts",
    "chars": 1077,
    "preview": "import { BuildContext } from '../util/interfaces';\nimport { getContext, toUnixPath} from '../util/helpers';\nimport { joi"
  },
  {
    "path": "src/webpack/watch-memory-system.ts",
    "chars": 3378,
    "preview": "import { extname } from 'path';\nimport { FileCache } from '../util/file-cache';\nimport { on, EventType } from '../util/e"
  },
  {
    "path": "src/webpack.ts",
    "chars": 9298,
    "preview": "import { EventEmitter } from 'events';\nimport { dirname, join } from 'path';\n\nimport * as webpackApi from 'webpack';\n\nim"
  },
  {
    "path": "src/worker-client.ts",
    "chars": 3253,
    "preview": "import { BuildContext, WorkerProcess, WorkerMessage } from './util/interfaces';\nimport { BuildError } from './util/error"
  },
  {
    "path": "src/worker-process.ts",
    "chars": 1901,
    "preview": "import { BuildError } from './util/errors';\nimport { buildErrorToJson } from './util/helpers';\nimport { Logger } from '."
  },
  {
    "path": "tsconfig.json",
    "chars": 351,
    "preview": "{\n  \"compilerOptions\": {\n    \"allowSyntheticDefaultImports\": true,\n    \"declaration\": true,\n    \"lib\": [\"dom\", \"es2015\"]"
  },
  {
    "path": "tslint.json",
    "chars": 38,
    "preview": "{\n  \"extends\": \"tslint-ionic-rules\"\n}\n"
  }
]

About this extraction

This page contains the full source code of the driftyco/ionic-app-scripts GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 148 files (814.5 KB), approximately 228.7k tokens, and a symbol index with 814 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.

Copied to clipboard!