diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..1cf867f786
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,23 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+
+[*.md]
+max_line_length = 0
+trim_trailing_whitespace = false
+
+[*.jade]
+max_line_length = 0
+trim_trailing_whitespace = false
+
+# Indentation override
+#[lib/**.js]
+#[{package.json,.travis.yml}]
+#[**/**.js]
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000000..d1c2c2b349
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,30 @@
+module.exports = {
+ "globals": {
+ "describe": true,
+ "beforeEach": true,
+ "it": true,
+ "expect": true
+ },
+ "env": {
+ "node": true
+ },
+ "extends": "eslint:recommended",
+ "rules": {
+ "indent": [
+ "error",
+ 2
+ ],
+ "linebreak-style": [
+ "error",
+ "unix"
+ ],
+ "quotes": [
+ "error",
+ "single"
+ ],
+ "semi": [
+ "error",
+ "always"
+ ]
+ }
+};
\ No newline at end of file
diff --git a/.firebaserc b/.firebaserc
new file mode 100644
index 0000000000..77c09fb883
--- /dev/null
+++ b/.firebaserc
@@ -0,0 +1,8 @@
+{
+ "projects": {
+ "live": "angular-io",
+ "ngdocsdev": "ngdocsdev",
+ "kw-dev": "kw-angular-io",
+ "dev": "angular-io-dev"
+ }
+}
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..fa749aa3fd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,7 @@
+**Please do not add issues or pull requests to this repo.**
+We are no longer making changes to documentation in this repository.
+We will no longer process new issues or PRs and we will close them automatically.
+
+**Please post new [issues](https://github.com/angular/angular/issues) and [pull requests](https://github.com/angular/angular/pulls) to the content folder in [https://github.com/angular/angular/tree/master/aio/content](https://github.com/angular/angular/tree/master/aio/content)**.
+
+Be sure to prefix your issue/PR title with "**docs(aio):**"
diff --git a/.github/PULL_REQUEST_TEMPLATE.MD b/.github/PULL_REQUEST_TEMPLATE.MD
new file mode 100644
index 0000000000..c4e15a1d58
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.MD
@@ -0,0 +1,7 @@
+**Please do not add issues or pull requests to this repo.**
+We are no longer making changes to documentation in this repository.
+We will no longer process new issues or PRs and we will close them automatically.
+
+**Please post new [issues](https://github.com/angular/angular/issues) and [pull requests](https://github.com/angular/angular/pulls) to the content folder in [https://github.com/angular/angular/tree/master/aio/content](https://github.com/angular/angular/tree/master/aio/content)**.
+
+Be sure to prefix your issue/PR title with "**docs(aio):**"
diff --git a/.gitignore b/.gitignore
index 7d89738919..c327f2acf5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,37 @@
node_modules
+_temp
bower_components
jspm_packages
-typings
+**/packages
+build
+pubspec.lock
+.pub
+.packages
*.map
-www
.DS_Store
+**/*.iml
.idea
+.vscode
**/js/latest/api
+**/ts/latest/api
+**/dart/latest/api
+**/docs/**/_fragments
+_.*
+**/resources/zips
public/docs/xref-*.*
-
-
+_zip-output
+www*
+npm-debug*.log*
+**/debug.log
+*.plnkr.html
+plnkr.html
+*.eplnkr.html
+eplnkr.html
+*plnkr.no-link.html
+public/docs/*/latest/guide/cheatsheet.json
+protractor-results.txt
+link-checker-results.txt
+/dist
+/public/docs/dart
+/public/docs/ts/_cache
+/public/docs/_examples/*/dart
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000000..1e8b314962
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+6
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..edba3b37d8
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,47 @@
+dist: trusty
+sudo: required
+language: node_js
+node_js:
+ - "6"
+os:
+ - linux
+env:
+ global:
+ - DBUS_SESSION_BUS_ADDRESS=/dev/null
+ - DISPLAY=:99.0
+ - CHROME_BIN=chromium-browser
+ - LATEST_RELEASE=4.0.0
+ # Temporarily disabled until there is a new release branch for 4.0.0
+ # - LATEST_RELEASE_BRANCH=2.4.x
+ - TASK_FLAGS="--dgeni-log=warn"
+ matrix:
+ # current angular release jobs
+ - TASK=lint
+ - TASK="run-e2e-tests --fast" SCRIPT=examples-install.sh
+ - TASK=build-compile SCRIPT=deploy-install.sh WAIT="travis_wait 50" POST_SCRIPT="check-docs.sh -v"
+ # current angular release branch jobs
+ # - TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh PREVIEW_BRANCH=$LATEST_RELEASE_BRANCH
+ # - TASK=build-compile SCRIPT=deploy-install-preview.sh PREVIEW_BRANCH=$LATEST_RELEASE_BRANCH WAIT="travis_wait 50" POST_SCRIPT="check-docs.sh -v"
+ # angular master jobs
+ - TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh PREVIEW_BRANCH=master
+ - TASK=build-compile SCRIPT=deploy-install-preview.sh PREVIEW_BRANCH=master WAIT="travis_wait 50" POST_SCRIPT="check-docs.sh -v"
+matrix:
+ fast_finish: true
+ allow_failures:
+ # allow current angular release branch and master to fail
+ # these should be moved to a daily task instead of being ran on every PR
+ # - env: TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh PREVIEW_BRANCH=$LATEST_RELEASE_BRANCH
+ # - env: TASK=build-compile SCRIPT=deploy-install-preview.sh PREVIEW_BRANCH=$LATEST_RELEASE_BRANCH WAIT="travis_wait 50" POST_SCRIPT="check-docs.sh -v"
+ - env: TASK="run-e2e-tests --fast" SCRIPT=examples-install-preview.sh PREVIEW_BRANCH=master
+ - env: TASK=build-compile SCRIPT=deploy-install-preview.sh PREVIEW_BRANCH=master WAIT="travis_wait 50" POST_SCRIPT="check-docs.sh -v"
+before_install:
+ - source ./scripts/env-set.sh
+ - ./scripts/before-install.sh
+install:
+ - npm install --no-optional
+ - if [[ -n "$SCRIPT" ]]; then echo "EXTRA INSTALL $SCRIPT"; ./scripts/$SCRIPT; fi
+before_script:
+ - sh -e /etc/init.d/xvfb start
+script:
+ - $WAIT gulp $TASK $TASK_FLAGS
+ - if [[ -n "$POST_SCRIPT" ]]; then ./scripts/$POST_SCRIPT; fi
diff --git a/LICENSE b/LICENSE
index 48d0699dc3..47bfda24ad 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,13 +1,21 @@
-Copyright 2010-2015 Google, Inc. http://angularjs.org
+The MIT License
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+Copyright (c) 2017 Google, Inc.
- http://www.apache.org/licenses/LICENSE-2.0
+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:
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+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.
diff --git a/README.md b/README.md
index 247c71834e..5a68c5c1b7 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,157 @@
+# This angular.io documentation repository is closed and preserved just for archival purposes
+
+**Please post new [issues](https://github.com/angular/angular/issues) and [pull requests](https://github.com/angular/angular/pulls) to the content folder in [https://github.com/angular/angular/tree/master/aio/content](https://github.com/angular/angular/tree/master/aio/content)**.
+
+
-
\ No newline at end of file
diff --git a/public/doc-shredder/_test/xref-jade.json b/public/doc-shredder/_test/xref-jade.json
deleted file mode 100644
index 04c056e012..0000000000
--- a/public/doc-shredder/_test/xref-jade.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "basePath": "c:/GitHub/angular.io.ideablade/public/doc-shredder/test",
- "jadeToFragMap": {
- "test_jade/guides/setupAlt2.jade": [
- {
- "fragPath": "test_fragments/gettingstarted/ts/index.html.md",
- "examplePath": "test_source/gettingstarted/ts/index.html",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/js/index.html.md",
- "examplePath": "test_source/gettingstarted/js/index.html",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/ts/main.ts.md",
- "examplePath": "test_source/gettingstarted/ts/main.ts",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/js/main.js.md",
- "examplePath": "test_source/gettingstarted/js/main.js",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/ts/main-import.ts.md",
- "examplePath": "test_source/gettingstarted/ts/main.ts",
- "exists": true
- }
- ],
- "test_jade/setupAlt.jade": [
- {
- "fragPath": "test_fragments/gettingstarted/ts/index2.html.md",
- "examplePath": "test_source/gettingstarted/ts/index2.html",
- "exists": false
- },
- {
- "fragPath": "test_fragments/gettingstarted/js/index.html.md",
- "examplePath": "test_source/gettingstarted/js/index.html",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/ts/main.ts.md",
- "examplePath": "test_source/gettingstarted/ts/main.ts",
- "exists": true
- },
- {
- "fragPath": "test_fragments/gettingstarted/js/main2.js.md",
- "examplePath": "test_source/gettingstarted/js/main2.js",
- "exists": false
- },
- {
- "fragPath": "test_fragments/gettingstarted/ts/main-import.ts.md",
- "examplePath": "test_source/gettingstarted/ts/main.ts",
- "exists": true
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/public/doc-shredder/doc-shredder.js b/public/doc-shredder/doc-shredder.js
deleted file mode 100644
index 2eb1d5abe2..0000000000
--- a/public/doc-shredder/doc-shredder.js
+++ /dev/null
@@ -1,234 +0,0 @@
-// Canonical path provides a consistent path (i.e. always forward slashes) across different OSes
-var path = require('canonical-path');
-var Q = require('q');
-var del = require('del');
-// delPromise is a 'promise' version of del
-var delPromise = Q.denodeify(del);
-var Dgeni = require('dgeni');
-var _ = require('lodash');
-
-var shred = function(shredOptions) {
- try {
- var pkg = createShredPackage(shredOptions);
- var dgeni = new Dgeni([ pkg]);
- return dgeni.generate();
- } catch(err) {
- console.log(err);
- console.log(err.stack);
- throw err;
- }
-}
-
-var shredSingleDir = function(shredOptions, filePath) {
- shredOptions = resolveShredOptions(shredOptions);
- var fileDir = path.dirname(filePath);
- var relativePath = path.relative(shredOptions.examplesDir, fileDir);
- var examplesDir = path.join(shredOptions.examplesDir, relativePath);
- var fragmentsDir = path.join(shredOptions.fragmentsDir, relativePath);
- var options = {
- includeSubdirs: false,
- examplesDir: examplesDir,
- fragmentsDir: fragmentsDir
- }
- var cleanPath = path.join(fragmentsDir, '*.*')
- return delPromise([ cleanPath, '!**/*.ovr.*']).then(function(paths) {
- // console.log('Deleted files/folders:\n', paths.join('\n'));
- return shred(options);
- });
-}
-
-var buildShredMap = function(shredMapOptions) {
- try {
- var pkg = createShredMapPackage(shredMapOptions);
- var dgeni = new Dgeni([ pkg]);
- return dgeni.generate();
- } catch(err) {
- console.log(err);
- console.log(err.stack);
- throw err;
- }
-}
-
-module.exports = {
- shred: shred,
- shredSingleDir: shredSingleDir,
- buildShredMap: buildShredMap
-};
-
-function createShredPackage(shredOptions) {
- var pkg = new Dgeni.Package('doc-shredder', [
- // require('dgeni-packages/base') - doesn't work
- ]);
- var options = resolveShredOptions(shredOptions);
-
- initializePackage(pkg)
- .factory(require('./fileShredder'))
- .factory(require('./regionExtractor'))
- .processor(require('./mdWrapperProcessor'))
-
- .config(function(readFilesProcessor, fileShredder ) {
- readFilesProcessor.fileReaders = [ fileShredder];
- })
- // default configs - may be overriden
- .config(function(readFilesProcessor) {
- // Specify the base path used when resolving relative paths to source and output files
- readFilesProcessor.basePath = "/";
-
- // Specify collections of source files that should contain the documentation to extract
- var extns = ['*.js', '*.html', '*.ts', '*.css', '*.json' ];
- var includeFiles = extns.map(function(extn) {
- if (options.includeSubdirs) {
- return path.join(options.examplesDir, '**', extn);
- } else {
- return path.join(options.examplesDir, extn);
- }
- });
- readFilesProcessor.sourceFiles = [ {
- // Process all candidate files in `src` and its subfolders ...
- include: includeFiles,
- exclude: ['**/node_modules/**', '**/typings/**'],
- // When calculating the relative path to these files use this as the base path.
- // So `src/foo/bar.js` will have relative path of `foo/bar.js`
- basePath: options.examplesDir
- } ];
- })
- .config(function(writeFilesProcessor) {
- // Specify where the writeFilesProcessor will write our generated doc files
- writeFilesProcessor.outputFolder = path.resolve(options.fragmentsDir);
- });
- return pkg;
-}
-
-var createShredMapPackage = function(mapOptions) {
- var pkg = new Dgeni.Package('doc-shred-mapper', [
- require('dgeni-packages/base'),
- require('dgeni-packages/nunjucks')
- ]);
- var options = resolveMapOptions(mapOptions);
-
- initializePackage(pkg)
- .factory(require('./extractPathsReader'))
- .processor(require('./shredMapProcessor'))
- .config(function(shredMapProcessor) {
- shredMapProcessor.options = options;
- })
- .config(function(readFilesProcessor, extractPathsReader ) {
- readFilesProcessor.fileReaders = [ extractPathsReader];
- })
- // default configs - may be overriden
- .config(function(readFilesProcessor) {
- // Specify the base path used when resolving relative paths to source and output files
- readFilesProcessor.basePath = '/';
-
- // Specify collections of source files that should contain the documentation to extract
- var extns = ['*.jade' ];
- var includeFiles = extns.map(function(extn) {
- if (options.includeSubdirs) {
- return path.join(options.jadeDir, '**', extn);
- } else {
- return path.join(options.jadeDir, extn);
- }
- });
- readFilesProcessor.sourceFiles = [ {
- // Process all candidate files in `src` and its subfolders ...
- include: includeFiles,
- // When calculating the relative path to these files use this as the base path.
- // So `src/foo/bar.js` will have relative path of `foo/bar.js`
- basePath: options.jadeDir
- } ];
- })
- .config(function(writeFilesProcessor, renderDocsProcessor, unescapeCommentsProcessor) {
- if (!mapOptions.writeFilesEnabled) {
- // dgeni hack to allow a geni task to simply return the results of the shredMapProcessor directly
- renderDocsProcessor.$enabled = false;
- writeFilesProcessor.$enabled = false;
- unescapeCommentsProcessor.$enabled = false;
- } else {
- // Specify where the writeFilesProcessor will write our generated doc files
- writeFilesProcessor.outputFolder = path.resolve(options.outputDir);
- }
- })
- .config(function(templateFinder) {
- // look for templates in this folder
- templateFinder.templateFolders = [ path.resolve(__dirname) ];
-
- // Specify how to match docs to templates.
- // In this case we just use the same static template for all docs
- templateFinder.templatePatterns = [ '${ doc.docType }.template' ];
- })
- .config(function(computePathsProcessor, computeIdsProcessor) {
- computePathsProcessor.$enabled = false;
- computeIdsProcessor.$enabled = false;
- // Unused for now.
- //computePathsProcessor.pathTemplates.push({
- // docTypes: ['foo'],
- // pathTemplate: '',
- // getOutputPath: function () {
- // },
- //});
- //
- //computeIdsProcessor.idTemplates.push({
- // docTypes: ['foo'],
- // getAliases: function (doc) {
- // return [doc.id];
- // }
- //});
- });
-
-
-
- return pkg;
-}
-
-function resolveShredOptions(shredOptions) {
- var so = _.defaults({}, shredOptions, {
- // read files from any subdir under here
- examplesDir: "./docs/_examples",
- // shredded files get copied here with same subdir structure.
- fragmentsDir: "./docs/_fragments",
- // whether to include subdirectories when shredding.
- includeSubdirs: true
- });
-
- so.examplesDir = path.resolve(so.examplesDir);
- so.fragmentsDir = path.resolve(so.fragmentsDir);
- return so;
-}
-
-function resolveMapOptions(mapOptions) {
- var so = _.defaults({}, mapOptions, {
- includeSubdirs: true
- });
- so.jadeDir = path.resolve(so.jadeDir);
- so.devguideExamplesDir = path.resolve(so.devguideExamplesDir);
- so.apiExamplesDir = path.resolve(so.apiExamplesDir);
- so.fragmentsDir = path.resolve(so.fragmentsDir);
- return so;
-}
-
-function initializePackage(pkg) {
- return pkg
- .processor(require('dgeni-packages/base/processors/read-files'))
- .processor(require('dgeni-packages/base/processors/write-files'))
- .factory(require('dgeni-packages/base/services/writefile'))
-
- // Ugh... Boilerplate that dgeni needs to sequence operations
- .processor({ name: 'reading-files' })
- .processor({ name: 'files-read', $runAfter: ['reading-files'] })
- .processor({ name: 'processing-docs', $runAfter: ['files-read'] })
- .processor({ name: 'docs-processed', $runAfter: ['processing-docs'] })
- .processor({ name: 'adding-extra-docs', $runAfter: ['docs-processed'] })
- .processor({ name: 'extra-docs-added', $runAfter: ['adding-extra-docs'] })
- .processor({ name: 'computing-ids', $runAfter: ['extra-docs-added'] })
- .processor({ name: 'ids-computed', $runAfter: ['computing-ids'] })
- .processor({ name: 'computing-paths', $runAfter: ['ids-computed'] })
- .processor({ name: 'paths-computed', $runAfter: ['computing-paths'] })
- .processor({ name: 'rendering-docs', $runAfter: ['paths-computed'] })
- .processor({ name: 'docs-rendered', $runAfter: ['rendering-docs'] })
- .processor({ name: 'writing-files', $runAfter: ['docs-rendered'] })
- .processor({ name: 'files-written', $runAfter: ['writing-files'] })
- .config(function(log) {
- // Set logging level
- log.level = 'info';
- })
-}
\ No newline at end of file
diff --git a/public/doc-shredder/extractPathsReader.js b/public/doc-shredder/extractPathsReader.js
deleted file mode 100644
index 6560ca502d..0000000000
--- a/public/doc-shredder/extractPathsReader.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * @dgService extractPathsReader
- * @description
- */
-
-var path = require('canonical-path');
-
-module.exports = function extractPathsReader(log) {
- // regex for makeTabs line
- var rx = /\s*\+make(?:=Tabs|Example|Json)\(\s*["'](.*?)["']\s*,\s*["'](.*?)["'].*?\)/g
- return {
- name: 'extractPathsReader',
-
- // returns the fragment filePath without the _fragments dir on the front or the '.md'
- getDocs: function (fileInfo) {
- var content = fileInfo.content;
- var fragItems = [];
- var r;
- while ((r = rx.exec(content)) !== null) {
- var filePaths = r[1].split(',');
- var regions = (r.length > 2) ? r[2].split(",") : null;
- filePaths.forEach(function(filePath, ix) {
- var region = regions && regions[ix];
- fragItems.push( { mixinPath: filePath, region: region } );
- });
- }
- if (fragItems.length) {
- return [{
- fragItems: fragItems
- }];
- } else {
- return [];
- }
- }
- }
-}
-
diff --git a/public/doc-shredder/fileShredder.js b/public/doc-shredder/fileShredder.js
deleted file mode 100644
index b0d5b65072..0000000000
--- a/public/doc-shredder/fileShredder.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * @dgService htmlFileShredder
- * @description
- */
-module.exports = function fileShredder(log, regionExtractor) {
- return {
- name: 'fileShredder',
-
- getDocs: function (fileInfo) {
- var commentMarkers;
- switch (fileInfo.extension) {
- case 'ts':
- case 'js':
- commentMarkers = ['//'];
- break;
- case 'html':
- commentMarkers = [' for html
- // or // #docregion foo for js/ts
- // 2) In back: a comment marker followed by '#enddocregion'
- // Regions can be nested and any regions not 'closed' are automatically closed at the end of the doc.
- return function(content, commentPrefixes) {
-
- var lines = result = content.split(/\r?\n/);
- var docs = [];
- var docStack = [];
- var doc = null;
-
- lines.forEach(function(line, ix) {
- if (isCommentLine(line, commentPrefixes)) {
- if (hasRegionTag(line)) {
- if (doc) docStack.push(doc);
- doc = {startIx: ix, regionName: getRegionName(line)};
- lines[ix] = nullLine;
- docs.push(doc);
- } else if (hasEndRegionTag(line)) {
- if (doc) {
- lines[ix] = nullLine;
- doc.endIx = ix;
- doc = docStack.pop();
- }
- }
- }
- });
-
- docs.forEach(function(doc) {
- var fragLines, content;
- if (doc.endIx) {
- fragLines = lines.slice(doc.startIx + 1, doc.endIx);
- } else {
- fragLines = lines.slice(doc.startIx + 1);
- }
- fragLines = trimLeftIndent(fragLines);
- content = fragLines.join('\n');
- // eliminate all #docregion lines
- content = content.replace(nullLinePattern, '');
- if (content.substr(-3) === nullLine) {
- content = content.substr(0, content.length-3);
- }
- doc.content = content;
- });
- return docs;
- }
-
-};
-
-function trimLeftIndent(lines) {
- var minIx = 100;
- var ok = lines.every(function(line) {
- // var ix = line.search(/\S/);
- var ix = line.search(/[^ ]/);
- if (ix === 0) return false;
- if (ix === -1) return true;
- if (ix > 0) {
- minIx = Math.min(minIx, ix);
- }
- return true;
- });
- if ( (!ok) || minIx === 100) return lines;
-
- var result = lines.map(function(line) {
- if (line.length > minIx) {
- return line.substr(minIx);
- } else {
- // this can happen if line is all blanks and shorter than mixIx
- return line;
- }
- });
- return result;
-}
-
-function isCommentLine(line, commentPrefixes) {
- return commentPrefixes.some(function(prefix) {
- return line.trim().indexOf(prefix) == 0;
- });
-}
-
-function hasRegionTag(line) {
- return line.indexOf("#docregion") >= 0;
-}
-
-function hasEndRegionTag(line) {
- return line.indexOf("#enddocregion") >= 0;
-}
-
-function getRegionName(line) {
- try {
- var name = line.match(/#docregion\s*(\S*).*/)[1];
- // Hack for html regions that look like or */
- name = name.replace("-->","").replace('\*\/',"");
- return name;
- } catch (e) {
- return '';
- }
-}
diff --git a/public/doc-shredder/shredMapProcessor.js b/public/doc-shredder/shredMapProcessor.js
deleted file mode 100644
index 5eb9ac1b24..0000000000
--- a/public/doc-shredder/shredMapProcessor.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * dgProcessor shredMapProcessor
- * @description
- *
- */
-var path = require('canonical-path');
-var fs = require('fs');
-var _ = require('lodash');
-
-module.exports = function shredMapProcessor(log, createDocMessage) {
- return {
- $runAfter: ['readFilesProcessor'],
- $runBefore: ['rendering-docs'],
-
- $process: function(docs) {
- var options = this.options;
- var jadeToFragMap = {};
- var fragToJadeMap = {};
-
- docs.forEach(function(doc) {
- var jadePath = path.join(options.jadeDir, doc.fileInfo.relativePath);
- var fragInfoSet = {};
- doc.fragItems.forEach(function(fragItem) {
- var mixinPath = fragItem.mixinPath;
- var fullExamplePath;
- if ( mixinPath.indexOf('_api') >= 0) {
- var sourcePath = mixinPath.replace('_api/','');
- fullExamplePath = path.join(options.apiExamplesDir, sourcePath);
- } else {
- fullExamplePath = path.join(options.devguideExamplesDir, mixinPath);
- }
- var region = fragItem.region ? "-" + fragItem.region : '';
- var extn = path.extname(mixinPath);
- var basename = path.basename(mixinPath, extn);
- var fragDir = path.dirname(mixinPath);
- var fragPath = path.join(fragDir, basename + region + extn) + '.md';
- var fullFragPath = path.join(options.fragmentsDir, fragPath);
-
- var fragInfo = { fragPath: fullFragPath, examplePath: fullExamplePath, exists: fs.existsSync(fullFragPath) };
- fragInfoSet[fragPath] = fragInfo;
- if (fragInfo.exists) {
- var jadePathsSet = fragToJadeMap[fragPath];
- if (!jadePathsSet) {
- jadePathsSet = {};
- fragToJadeMap[fragPath] = jadePathsSet;
- }
- jadePathsSet[jadePath] = jadePath;
- } else {
- var relativePath = path.relative(".", fullFragPath);
- log.warn(createDocMessage('Invalid example (unable to locate fragment file: "' + relativePath + '")', doc));
- }
- });
- jadeToFragMap[jadePath] = _.values(fragInfoSet);
- });
- for (var key in fragToJadeMap) {
- fragToJadeMap[key] = _.keys(fragToJadeMap[key]);
- }
-
- var shredMap = {
- jadeToFragMap: jadeToFragMap
- };
-
- if (!options.writeFilesEnabled) {
- return [ shredMap ];
- } else {
- var newDocs = [ {
- docType: 'xref-doc.json',
- json: JSON.stringify(shredMap, null, 2),
- outputPath: 'xref-jade.json'
- }, {
- docType: 'xref-jade.html',
- jadeToFragMap: jadeToFragMap,
- outputPath: 'xref-jade-to-frag.html'
- }, {
- docType: 'xref-frag.html',
- fragToJadeMap: fragToJadeMap,
- outputPath: 'xref-frag-to-jade.html'
- }];
- return newDocs;
- }
- }
- }
-};
-
-function getExampleName(fragPath) {
- // pattern to isolate base fileName and extension from fragment name
- var rx = /(.*)\-(.*)\.(.s)/;
- var r = rx.exec(fragPath);
- if (r) {
- return r[1] + '.' + r[3];
- } else {
- return fragPath;
- }
-}
\ No newline at end of file
diff --git a/public/docs/ImageGuide.pdf b/public/docs/ImageGuide.pdf
new file mode 100644
index 0000000000..21280dce88
Binary files /dev/null and b/public/docs/ImageGuide.pdf differ
diff --git a/public/docs/README.md b/public/docs/README.md
deleted file mode 100644
index 95d331b115..0000000000
--- a/public/docs/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Why the _fragments dir is checked in
-
-Within this repo files generated as a result of shredding the `_examples` dir ( the contents of the `_fragments` dir) are checked in so that we can avoid running the
-shredder over the entire `_examples` dir each time someone refreshes the repo ( the `shred-full` gulp task).
-The gulp `serve-and-watch` shredder is only a partial shredder. It only shreds files in directories changed during
-the current session.
diff --git a/public/docs/_data.json b/public/docs/_data.json
index daade7e3ea..121e4db32f 100644
--- a/public/docs/_data.json
+++ b/public/docs/_data.json
@@ -3,17 +3,5 @@
"title": "Angular Docs",
"subtitle": "Choose a language for Angular",
"layout": "../_layout"
- },
-
- "search": {
- "title": "Docs Search Results",
- "layout": "../_layout"
- },
-
- "styleguide": {
- "title": "Docs Style Guide",
- "subtitle": "Design & Layout Patterns For Documentation",
- "layout": "../_layout",
- "autoformat": "true"
}
}
diff --git a/public/docs/_examples/.gitignore b/public/docs/_examples/.gitignore
index 288b9aca3a..3fb5ae8562 100644
--- a/public/docs/_examples/.gitignore
+++ b/public/docs/_examples/.gitignore
@@ -1,2 +1,18 @@
-typings
-*.js.map
\ No newline at end of file
+# _boilerplate files
+!_boilerplate/*
+*/*/src/styles.css
+*/*/src/systemjs-angular-loader.js
+*/*/src/systemjs.config.js
+*/*/src/tsconfig.json
+*/*/bs-config.e2e.json
+*/*/bs-config.json
+*/*/package.json
+*/*/tslint.json
+
+# example files
+_test-output
+protractor-helpers.js
+*/e2e-spec.js
+**/ts/**/*.js
+**/js-es6*/**/*.js
+**/ts-snippets/**/*.js
diff --git a/public/docs/_examples/_boilerplate/bs-config.e2e.json b/public/docs/_examples/_boilerplate/bs-config.e2e.json
new file mode 100644
index 0000000000..24570dbcc9
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/bs-config.e2e.json
@@ -0,0 +1,14 @@
+{
+ "open": false,
+ "logLevel": "silent",
+ "port": 8080,
+ "server": {
+ "baseDir": "src",
+ "routes": {
+ "/node_modules": "node_modules"
+ },
+ "middleware": {
+ "0": null
+ }
+ }
+}
diff --git a/public/docs/_examples/_boilerplate/bs-config.json b/public/docs/_examples/_boilerplate/bs-config.json
new file mode 100644
index 0000000000..4e58595267
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/bs-config.json
@@ -0,0 +1,8 @@
+{
+ "server": {
+ "baseDir": "src",
+ "routes": {
+ "/node_modules": "node_modules"
+ }
+ }
+}
diff --git a/public/docs/_examples/_boilerplate/example-config.json b/public/docs/_examples/_boilerplate/example-config.json
new file mode 100644
index 0000000000..ff5403e6ca
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/example-config.json
@@ -0,0 +1,4 @@
+{
+ "build": "build",
+ "run": "serve"
+}
diff --git a/public/docs/_examples/_boilerplate/package.json b/public/docs/_examples/_boilerplate/package.json
new file mode 100644
index 0000000000..2e4bc19f91
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "angular-examples",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Example package.json, only contains needed scripts for examples. See _examples/package.json for master package.json.",
+ "scripts": {
+ "build": "tsc -p src/",
+ "build:watch": "tsc -p src/ -w",
+ "build:e2e": "tsc -p e2e/",
+ "serve": "lite-server -c=bs-config.json",
+ "serve:e2e": "lite-server -c=bs-config.e2e.json",
+ "prestart": "npm run build",
+ "start": "concurrently \"npm run build:watch\" \"npm run serve\"",
+ "pree2e": "webdriver-manager update && npm run build:e2e",
+ "e2e": "concurrently \"npm run serve:e2e\" \"npm run protractor\" --kill-others --success first",
+ "protractor": "protractor protractor.config.js",
+ "pretest": "npm run build",
+ "test": "concurrently \"npm run build:watch\" \"karma start karma.conf.js\"",
+ "pretest:once": "npm run build",
+ "test:once": "karma start karma.conf.js --single-run",
+ "lint": "tslint ./src/**/*.ts -t verbose",
+
+ "build:upgrade": "tsc",
+ "serve:upgrade": "http-server",
+ "build:cli": "ng build --no-progress",
+ "serve:cli": "http-server dist/",
+ "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
+ "serve:aot": "lite-server -c bs-config.aot.json",
+ "start:webpack": "webpack-dev-server --inline --progress --port 8080",
+ "test:webpack": "karma start karma.webpack.conf.js",
+ "build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
+ "build:babel": "babel src -d src --extensions \".es6\" --source-maps",
+ "copy-dist-files": "node ./copy-dist-files.js",
+ "i18n": "ng-xi18n"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "MIT",
+ "dependencies": {},
+ "devDependencies": {
+ "angular-cli": "^1.0.0-rc.0"
+ },
+ "repository": {}
+}
diff --git a/public/docs/_examples/_boilerplate/plnkr.json b/public/docs/_examples/_boilerplate/plnkr.json
new file mode 100644
index 0000000000..5fb55b50ad
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "QuickStart",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.ts",
+ "index.html"
+ ],
+ "open": "app/app.component.ts",
+ "tags": ["quickstart"]
+}
diff --git a/public/docs/_examples/_boilerplate/src/styles.css b/public/docs/_examples/_boilerplate/src/styles.css
new file mode 100644
index 0000000000..d81835d0cd
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/styles.css
@@ -0,0 +1,116 @@
+/* #docregion , quickstart, toh */
+/* Master Styles */
+h1 {
+ color: #369;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 250%;
+}
+h2, h3 {
+ color: #444;
+ font-family: Arial, Helvetica, sans-serif;
+ font-weight: lighter;
+}
+body {
+ margin: 2em;
+}
+/* #enddocregion quickstart */
+body, input[text], button {
+ color: #888;
+ font-family: Cambria, Georgia;
+}
+/* #enddocregion toh */
+a {
+ cursor: pointer;
+ cursor: hand;
+}
+button {
+ font-family: Arial;
+ background-color: #eee;
+ border: none;
+ padding: 5px 10px;
+ border-radius: 4px;
+ cursor: pointer;
+ cursor: hand;
+}
+button:hover {
+ background-color: #cfd8dc;
+}
+button:disabled {
+ background-color: #eee;
+ color: #aaa;
+ cursor: auto;
+}
+
+/* Navigation link styles */
+nav a {
+ padding: 5px 10px;
+ text-decoration: none;
+ margin-right: 10px;
+ margin-top: 10px;
+ display: inline-block;
+ background-color: #eee;
+ border-radius: 4px;
+}
+nav a:visited, a:link {
+ color: #607D8B;
+}
+nav a:hover {
+ color: #039be5;
+ background-color: #CFD8DC;
+}
+nav a.active {
+ color: #039be5;
+}
+
+/* items class */
+.items {
+ margin: 0 0 2em 0;
+ list-style-type: none;
+ padding: 0;
+ width: 24em;
+}
+.items li {
+ cursor: pointer;
+ position: relative;
+ left: 0;
+ background-color: #EEE;
+ margin: .5em;
+ padding: .3em 0;
+ height: 1.6em;
+ border-radius: 4px;
+}
+.items li:hover {
+ color: #607D8B;
+ background-color: #DDD;
+ left: .1em;
+}
+.items li.selected {
+ background-color: #CFD8DC;
+ color: white;
+}
+.items li.selected:hover {
+ background-color: #BBD8DC;
+}
+.items .text {
+ position: relative;
+ top: -3px;
+}
+.items .badge {
+ display: inline-block;
+ font-size: small;
+ color: white;
+ padding: 0.8em 0.7em 0 0.7em;
+ background-color: #607D8B;
+ line-height: 1em;
+ position: relative;
+ left: -1px;
+ top: -4px;
+ height: 1.8em;
+ margin-right: .8em;
+ border-radius: 4px 0 0 4px;
+}
+/* #docregion toh */
+/* everywhere else */
+* {
+ font-family: Arial, Helvetica, sans-serif;
+}
diff --git a/public/docs/_examples/_boilerplate/src/systemjs-angular-loader.js b/public/docs/_examples/_boilerplate/src/systemjs-angular-loader.js
new file mode 100644
index 0000000000..8b1005444e
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/systemjs-angular-loader.js
@@ -0,0 +1,49 @@
+var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm;
+var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g;
+var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g;
+
+module.exports.translate = function(load){
+ if (load.source.indexOf('moduleId') != -1) return load;
+
+ var url = document.createElement('a');
+ url.href = load.address;
+
+ var basePathParts = url.pathname.split('/');
+
+ basePathParts.pop();
+ var basePath = basePathParts.join('/');
+
+ var baseHref = document.createElement('a');
+ baseHref.href = this.baseURL;
+ baseHref = baseHref.pathname;
+
+ if (!baseHref.startsWith('/base/')) { // it is not karma
+ basePath = basePath.replace(baseHref, '');
+ }
+
+ load.source = load.source
+ .replace(templateUrlRegex, function(match, quote, url){
+ var resolvedUrl = url;
+
+ if (url.startsWith('.')) {
+ resolvedUrl = basePath + url.substr(1);
+ }
+
+ return 'templateUrl: "' + resolvedUrl + '"';
+ })
+ .replace(stylesRegex, function(match, relativeUrls) {
+ var urls = [];
+
+ while ((match = stringRegex.exec(relativeUrls)) !== null) {
+ if (match[2].startsWith('.')) {
+ urls.push('"' + basePath + match[2].substr(1) + '"');
+ } else {
+ urls.push('"' + match[2] + '"');
+ }
+ }
+
+ return "styleUrls: [" + urls.join(', ') + "]";
+ });
+
+ return load;
+};
diff --git a/public/docs/_examples/_boilerplate/src/systemjs.config.js b/public/docs/_examples/_boilerplate/src/systemjs.config.js
new file mode 100644
index 0000000000..ea7a3879ac
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/systemjs.config.js
@@ -0,0 +1,52 @@
+/**
+ * System configuration for Angular samples
+ * Adjust as necessary for your application needs.
+ */
+(function (global) {
+ System.config({
+ paths: {
+ // paths serve as alias
+ 'npm:': 'node_modules/'
+ },
+ // map tells the System loader where to look for things
+ map: {
+ // our app is within the app folder
+ 'app': 'app',
+
+ // angular bundles
+ '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
+ '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
+ '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
+ '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
+ '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
+ '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
+ '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
+ '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
+ '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
+ '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
+ '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
+ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
+ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
+ '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
+
+ // other libraries
+ 'rxjs': 'npm:rxjs',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
+ },
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ app: {
+ main: './main.js',
+ defaultExtension: 'js',
+ meta: {
+ './*.js': {
+ loader: 'systemjs-angular-loader.js'
+ }
+ }
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ }
+ }
+ });
+})(this);
diff --git a/public/docs/_examples/_boilerplate/src/systemjs.config.web.build.js b/public/docs/_examples/_boilerplate/src/systemjs.config.web.build.js
new file mode 100644
index 0000000000..5774fd8187
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/systemjs.config.web.build.js
@@ -0,0 +1,96 @@
+/**
+ * WEB VERSION FOR CURRENT ANGULAR BUILD
+ * (based on systemjs.config.js in angular.io)
+ * System configuration for Angular samples
+ * Adjust as necessary for your application needs.
+ *
+ * UNTESTED !
+ */
+(function (global) {
+ System.config({
+ // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
+ transpiler: 'ts',
+ typescriptOptions: {
+ // Copy of compiler options in standard tsconfig.json
+ "target": "es5",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": ["es2015", "dom"],
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true
+ },
+ meta: {
+ 'typescript': {
+ "exports": "ts"
+ }
+ },
+ paths: {
+ // paths serve as alias
+ 'npm:': 'https://unpkg.com/',
+ 'ng:': 'https://cdn.rawgit.com/angular/'
+ },
+ // map tells the System loader where to look for things
+ map: {
+ // our app is within the app folder
+ 'app': 'app',
+
+ // angular bundles
+ '@angular/animations': 'ng:animations-builds/master/bundles/animations.umd.js',
+ '@angular/animations/browser': 'ng:animations-builds/master/bundles/animations-browser.umd.js',
+ '@angular/core': 'ng:core-builds/master/bundles/core.umd.js',
+ '@angular/common': 'ng:common-builds/master/bundles/common.umd.js',
+ '@angular/compiler': 'ng:compiler-builds/master/bundles/compiler.umd.js',
+ '@angular/platform-browser': 'ng:platform-browser-builds/master/bundles/platform-browser.umd.js',
+ '@angular/platform-browser/animations': 'ng:animations-builds/master/bundles/platform-browser-animations.umd.js',
+ '@angular/platform-browser-dynamic': 'ng:platform-browser-dynamic-builds/master/bundles/platform-browser-dynamic.umd.js',
+ '@angular/http': 'ng:http-builds/master/bundles/http.umd.js',
+ '@angular/router': 'ng:router-builds/master/bundles/router.umd.js',
+ '@angular/router/upgrade': 'ng:router-builds/master/bundles/router-upgrade.umd.js',
+ '@angular/forms': 'ng:forms-builds/master/bundles/forms.umd.js',
+ '@angular/upgrade': 'ng:upgrade-builds/master/bundles/upgrade.umd.js',
+ '@angular/upgrade/static': 'ng:upgrade-builds/master/bundles/upgrade-static.umd.js',
+
+ // angular testing umd bundles (overwrite the shim mappings)
+ '@angular/core/testing': 'ng:core-builds/master/bundles/core-testing.umd.js',
+ '@angular/common/testing': 'ng:common-builds/master/bundles/common-testing.umd.js',
+ '@angular/compiler/testing': 'ng:compiler-builds/master/bundles/compiler-testing.umd.js',
+ '@angular/platform-browser/testing': 'ng:platform-browser-builds/master/bundles/platform-browser-testing.umd.js',
+ '@angular/platform-browser-dynamic/testing': 'ng:platform-browser-dynamic-builds/master/bundles/platform-browser-dynamic-testing.umd.js',
+ '@angular/http/testing': 'ng:http-builds/master/bundles/http-testing.umd.js',
+ '@angular/router/testing': 'ng:router-builds/master/bundles/router-testing.umd.js',
+ '@angular/forms/testing': 'ng:forms-builds/master/bundles/forms-testing.umd.js',
+
+ // other libraries
+ 'rxjs': 'npm:rxjs@5.0.1',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
+ 'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
+ 'typescript': 'npm:typescript@2.2.1/lib/typescript.js',
+
+ },
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ app: {
+ main: './main.ts',
+ defaultExtension: 'ts',
+ meta: {
+ './*.ts': {
+ loader: 'systemjs-angular-loader.js'
+ }
+ }
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ }
+ }
+ });
+
+})(this);
+
+/*
+Copyright 2016 Google Inc. All Rights Reserved.
+Use of this source code is governed by an MIT-style license that
+can be found in the LICENSE file at http://angular.io/license
+*/
diff --git a/public/docs/_examples/_boilerplate/src/systemjs.config.web.js b/public/docs/_examples/_boilerplate/src/systemjs.config.web.js
new file mode 100644
index 0000000000..376fcdde8a
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/systemjs.config.web.js
@@ -0,0 +1,83 @@
+/**
+ * WEB ANGULAR VERSION
+ * (based on systemjs.config.js in angular.io)
+ * System configuration for Angular samples
+ * Adjust as necessary for your application needs.
+ */
+(function (global) {
+ System.config({
+ // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
+ transpiler: 'ts',
+ typescriptOptions: {
+ // Copy of compiler options in standard tsconfig.json
+ "target": "es5",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": ["es2015", "dom"],
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true
+ },
+ meta: {
+ 'typescript': {
+ "exports": "ts"
+ }
+ },
+ paths: {
+ // paths serve as alias
+ 'npm:': 'https://unpkg.com/'
+ },
+ // map tells the System loader where to look for things
+ map: {
+ // our app is within the app folder
+ 'app': 'app',
+
+ // angular bundles
+ '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
+ '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
+ '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
+ '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
+ '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
+ '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
+ '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
+ '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
+ '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
+ '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
+ '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
+ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
+ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
+ '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
+
+ // other libraries
+ 'rxjs': 'npm:rxjs@5.0.1',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
+ 'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
+ 'typescript': 'npm:typescript@2.2.1/lib/typescript.js',
+
+ },
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ app: {
+ main: './main.ts',
+ defaultExtension: 'ts',
+ meta: {
+ './*.ts': {
+ loader: 'systemjs-angular-loader.js'
+ }
+ }
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ }
+ }
+ });
+
+})(this);
+
+/*
+Copyright 2016 Google Inc. All Rights Reserved.
+Use of this source code is governed by an MIT-style license that
+can be found in the LICENSE file at http://angular.io/license
+*/
diff --git a/public/docs/_examples/_boilerplate/src/tsconfig.json b/public/docs/_examples/_boilerplate/src/tsconfig.json
new file mode 100644
index 0000000000..05839ec2ff
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/src/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [ "es2015", "dom" ],
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true,
+ "typeRoots": [
+ "../../../node_modules/@types/"
+ ]
+ },
+ "compileOnSave": true,
+ "exclude": [
+ "node_modules/*",
+ "**/*-aot.ts"
+ ]
+}
diff --git a/public/docs/_examples/_boilerplate/tslint.json b/public/docs/_examples/_boilerplate/tslint.json
new file mode 100644
index 0000000000..276453f4f5
--- /dev/null
+++ b/public/docs/_examples/_boilerplate/tslint.json
@@ -0,0 +1,93 @@
+{
+ "rules": {
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "eofline": true,
+ "forin": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "label-position": true,
+ "label-undefined": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ "static-before-instance",
+ "variables-before-functions"
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-key": true,
+ "no-duplicate-variable": true,
+ "no-empty": false,
+ "no-eval": true,
+ "no-inferrable-types": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unused-expression": true,
+ "no-unused-variable": true,
+ "no-unreachable": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
diff --git a/public/docs/_examples/animations/e2e-spec.ts b/public/docs/_examples/animations/e2e-spec.ts
new file mode 100644
index 0000000000..4fba7ec475
--- /dev/null
+++ b/public/docs/_examples/animations/e2e-spec.ts
@@ -0,0 +1,351 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by, ElementFinder } from 'protractor';
+import { logging, promise } from 'selenium-webdriver';
+
+/**
+ * The tests here basically just checking that the end styles
+ * of each animation are in effect.
+ *
+ * Relies on the Angular testability only becoming stable once
+ * animation(s) have finished.
+ *
+ * Ideally we'd use https://developer.mozilla.org/en-US/docs/Web/API/Document/getAnimations
+ * but they're not supported in Chrome at the moment. The upcoming nganimate polyfill
+ * may also add some introspection support.
+ */
+describe('Animation Tests', () => {
+
+ const INACTIVE_COLOR = 'rgba(238, 238, 238, 1)';
+ const ACTIVE_COLOR = 'rgba(207, 216, 220, 1)';
+ const NO_TRANSFORM_MATRIX_REGEX = /matrix\(1,\s*0,\s*0,\s*1,\s*0,\s*0\)/;
+
+ beforeEach(() => {
+ browser.get('');
+ });
+
+ describe('basic states', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-basic'));
+ });
+
+ it('animates between active and inactive', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.1);
+ expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+ });
+
+ });
+
+ describe('styles inline in transitions', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(function() {
+ host = element(by.css('hero-list-inline-styles'));
+ });
+
+ it('are not kept after animation', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+ });
+
+ });
+
+ describe('combined transition syntax', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-combined-transitions'));
+ });
+
+ it('animates between active and inactive', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.1);
+ expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+ });
+
+ });
+
+ describe('two-way transition syntax', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-twoway'));
+ });
+
+ it('animates between active and inactive', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.1);
+ expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+ });
+
+ });
+
+ describe('enter & leave', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-enter-leave'));
+ });
+
+ it('adds and removes element', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+
+ removeHero();
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('enter & leave & states', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(function() {
+ host = element(by.css('hero-list-enter-leave-states'));
+ });
+
+ it('adds and removes and animates between active and inactive', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.1);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+
+ removeHero();
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('auto style calc', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(function() {
+ host = element(by.css('hero-list-auto'));
+ });
+
+ it('adds and removes element', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+ expect(li.getCssValue('height')).toBe('50px');
+
+ removeHero();
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('different timings', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-timings'));
+ });
+
+ it('adds and removes element', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+ expect(li.getCssValue('opacity')).toMatch('1');
+
+ removeHero();
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('multiple keyframes', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-multistep'));
+ });
+
+ it('adds and removes element', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+ expect(li.getCssValue('opacity')).toMatch('1');
+
+ removeHero();
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('parallel groups', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-groups'));
+ });
+
+ it('adds and removes element', () => {
+ addInactiveHero();
+
+ let li = host.element(by.css('li'));
+ expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
+ expect(li.getCssValue('opacity')).toMatch('1');
+
+ removeHero(700);
+ expect(li.isPresent()).toBe(false);
+ });
+
+ });
+
+ describe('adding active heroes', () => {
+
+ let host: ElementFinder;
+
+ beforeEach(() => {
+ host = element(by.css('hero-list-basic'));
+ });
+
+ it('animates between active and inactive', () => {
+ addActiveHero();
+
+ let li = host.element(by.css('li'));
+
+ expect(getScaleX(li)).toBe(1.1);
+ expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.0);
+ expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
+
+ li.click();
+ browser.driver.sleep(300);
+ expect(getScaleX(li)).toBe(1.1);
+ expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
+ });
+ });
+
+ describe('callbacks', () => {
+ it('fires a callback on start and done', () => {
+ addActiveHero();
+ browser.manage().logs().get(logging.Type.BROWSER)
+ .then((logs: logging.Entry[]) => {
+ const animationMessages = logs.filter((log) => {
+ return log.message.indexOf('Animation') !== -1 ? true : false;
+ });
+
+ expect(animationMessages.length).toBeGreaterThan(0);
+ });
+ });
+ });
+
+ function addActiveHero(sleep?: number) {
+ sleep = sleep || 500;
+ element(by.buttonText('Add active hero')).click();
+ browser.driver.sleep(sleep);
+ }
+
+ function addInactiveHero(sleep?: number) {
+ sleep = sleep || 500;
+ element(by.buttonText('Add inactive hero')).click();
+ browser.driver.sleep(sleep);
+ }
+
+ function removeHero(sleep?: number) {
+ sleep = sleep || 500;
+ element(by.buttonText('Remove hero')).click();
+ browser.driver.sleep(sleep);
+ }
+
+ function getScaleX(el: ElementFinder) {
+ return Promise.all([
+ getBoundingClientWidth(el),
+ getOffsetWidth(el)
+ ]).then(function(promiseResolutions) {
+ let clientWidth = promiseResolutions[0];
+ let offsetWidth = promiseResolutions[1];
+ return clientWidth / offsetWidth;
+ });
+ }
+
+ function getBoundingClientWidth(el: ElementFinder): promise.Promise {
+ return browser.executeScript(
+ 'return arguments[0].getBoundingClientRect().width',
+ el.getWebElement()
+ );
+ }
+
+ function getOffsetWidth(el: ElementFinder): promise.Promise {
+ return browser.executeScript(
+ 'return arguments[0].offsetWidth',
+ el.getWebElement()
+ );
+ }
+});
diff --git a/public/docs/_examples/animations/ts/.gitignore b/public/docs/_examples/animations/ts/.gitignore
new file mode 100644
index 0000000000..2cb7d2a2e9
--- /dev/null
+++ b/public/docs/_examples/animations/ts/.gitignore
@@ -0,0 +1 @@
+**/*.js
diff --git a/public/docs/js/latest/guide/reusing-components.jade b/public/docs/_examples/animations/ts/example-config.json
similarity index 100%
rename from public/docs/js/latest/guide/reusing-components.jade
rename to public/docs/_examples/animations/ts/example-config.json
diff --git a/public/docs/_examples/animations/ts/plnkr.json b/public/docs/_examples/animations/ts/plnkr.json
new file mode 100644
index 0000000000..f047395e7f
--- /dev/null
+++ b/public/docs/_examples/animations/ts/plnkr.json
@@ -0,0 +1,8 @@
+{
+ "description": "Angular Animations",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ]
+}
diff --git a/public/docs/_examples/animations/ts/src/app/app.module.ts b/public/docs/_examples/animations/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..0773357c58
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/app.module.ts
@@ -0,0 +1,38 @@
+// #docregion animations-module
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+// #enddocregion animations-module
+
+import { HeroTeamBuilderComponent } from './hero-team-builder.component';
+import { HeroListBasicComponent } from './hero-list-basic.component';
+import { HeroListInlineStylesComponent } from './hero-list-inline-styles.component';
+import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
+import { HeroListEnterLeaveStatesComponent } from './hero-list-enter-leave-states.component';
+import { HeroListCombinedTransitionsComponent } from './hero-list-combined-transitions.component';
+import { HeroListTwowayComponent } from './hero-list-twoway.component';
+import { HeroListAutoComponent } from './hero-list-auto.component';
+import { HeroListGroupsComponent } from './hero-list-groups.component';
+import { HeroListMultistepComponent } from './hero-list-multistep.component';
+import { HeroListTimingsComponent } from './hero-list-timings.component';
+
+// #docregion animation-module
+@NgModule({
+ imports: [ BrowserModule, BrowserAnimationsModule ],
+ // #enddocregion animation-module
+ declarations: [
+ HeroTeamBuilderComponent,
+ HeroListBasicComponent,
+ HeroListInlineStylesComponent,
+ HeroListCombinedTransitionsComponent,
+ HeroListTwowayComponent,
+ HeroListEnterLeaveComponent,
+ HeroListEnterLeaveStatesComponent,
+ HeroListAutoComponent,
+ HeroListTimingsComponent,
+ HeroListMultistepComponent,
+ HeroListGroupsComponent
+ ],
+ bootstrap: [ HeroTeamBuilderComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-auto.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-auto.component.ts
new file mode 100644
index 0000000000..84b25c05de
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-auto.component.ts
@@ -0,0 +1,47 @@
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-auto',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+
+ /* When the element leaves (transition "in => void" occurs),
+ * get the element's current computed height and animate
+ * it down to 0.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('shrinkOut', [
+ state('in', style({height: '*'})),
+ transition('* => void', [
+ style({height: '*'}),
+ animate(250, style({height: 0}))
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListAutoComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-basic.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-basic.component.ts
new file mode 100644
index 0000000000..76d5ba686c
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-basic.component.ts
@@ -0,0 +1,70 @@
+// #docplaster
+// #docregion
+// #docregion imports
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+// #enddocregion imports
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-basic',
+ // #enddocregion
+ /* The click event calls hero.toggleState(), which
+ * causes the state of that hero to switch from
+ * active to inactive or vice versa.
+ */
+ // #docregion
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ // #enddocregion
+ /**
+ * Define two states, "inactive" and "active", and the end
+ * styles that apply whenever the element is in those states.
+ * Then define animations for transitioning between the states,
+ * one in each direction
+ */
+ // #docregion
+ // #docregion animationdef
+ animations: [
+ trigger('heroState', [
+ // #docregion states
+ state('inactive', style({
+ backgroundColor: '#eee',
+ transform: 'scale(1)'
+ })),
+ state('active', style({
+ backgroundColor: '#cfd8dc',
+ transform: 'scale(1.1)'
+ })),
+ // #enddocregion states
+ // #docregion transitions
+ transition('inactive => active', animate('100ms ease-in')),
+ transition('active => inactive', animate('100ms ease-out'))
+ // #enddocregion transitions
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListBasicComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-combined-transitions.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-combined-transitions.component.ts
new file mode 100644
index 0000000000..fc654cbcb5
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-combined-transitions.component.ts
@@ -0,0 +1,59 @@
+// #docregion
+// #docregion imports
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+// #enddocregion imports
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-combined-transitions',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /*
+ * Define two states, "inactive" and "active", and the end
+ * styles that apply whenever the element is in those states.
+ * Then define an animated transition between these two
+ * states, in *both* directions.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('heroState', [
+ state('inactive', style({
+ backgroundColor: '#eee',
+ transform: 'scale(1)'
+ })),
+ state('active', style({
+ backgroundColor: '#cfd8dc',
+ transform: 'scale(1.1)'
+ })),
+ // #docregion transitions
+ transition('inactive => active, active => inactive',
+ animate('100ms ease-out'))
+ // #enddocregion transitions
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListCombinedTransitionsComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave-states.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave-states.component.ts
new file mode 100644
index 0000000000..c01e182e8b
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave-states.component.ts
@@ -0,0 +1,63 @@
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-enter-leave-states',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /* The elements here have two possible states based
+ * on the hero state, "active", or "inactive". We animate
+ * six transitions: Between the two states in both directions,
+ * and between each state and void. With this we can animate
+ * the enter and leave of elements differently based on which
+ * state they are in when they are added and removed.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('heroState', [
+ state('inactive', style({transform: 'translateX(0) scale(1)'})),
+ state('active', style({transform: 'translateX(0) scale(1.1)'})),
+ transition('inactive => active', animate('100ms ease-in')),
+ transition('active => inactive', animate('100ms ease-out')),
+ transition('void => inactive', [
+ style({transform: 'translateX(-100%) scale(1)'}),
+ animate(100)
+ ]),
+ transition('inactive => void', [
+ animate(100, style({transform: 'translateX(100%) scale(1)'}))
+ ]),
+ transition('void => active', [
+ style({transform: 'translateX(0) scale(0)'}),
+ animate(200)
+ ]),
+ transition('active => void', [
+ animate(200, style({transform: 'translateX(0) scale(0)'}))
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListEnterLeaveStatesComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave.component.ts
new file mode 100644
index 0000000000..f27b5f10e1
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-enter-leave.component.ts
@@ -0,0 +1,51 @@
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-enter-leave',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /* The element here always has the state "in" when it
+ * is present. We animate two transitions: From void
+ * to in and from in to void, to achieve an animated
+ * enter and leave transition. The element enters from
+ * the left and leaves to the right using translateX.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('flyInOut', [
+ state('in', style({transform: 'translateX(0)'})),
+ transition('void => *', [
+ style({transform: 'translateX(-100%)'}),
+ animate(100)
+ ]),
+ transition('* => void', [
+ animate(100, style({transform: 'translateX(100%)'}))
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListEnterLeaveComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-groups.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-groups.component.ts
new file mode 100644
index 0000000000..12a57292f7
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-groups.component.ts
@@ -0,0 +1,80 @@
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition,
+ group
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-groups',
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ styleUrls: ['./hero-list.component.css'],
+ styles: [`
+ li {
+ padding: 0 !important;
+ text-align: center;
+ }
+ `],
+ /* The element here always has the state "in" when it
+ * is present. We animate two transitions: From void
+ * to in and from in to void, to achieve an animated
+ * enter and leave transition.
+ *
+ * The transitions have *parallel group* that allow
+ * animating several properties at the same time but
+ * with different timing configurations. On enter
+ * (void => *) we start the opacity animation 0.1s
+ * earlier than the translation/width animation.
+ * On leave (* => void) we do the opposite -
+ * the translation/width animation begins immediately
+ * and the opacity animation 0.1s later.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('flyInOut', [
+ state('in', style({width: 120, transform: 'translateX(0)', opacity: 1})),
+ transition('void => *', [
+ style({width: 10, transform: 'translateX(50px)', opacity: 0}),
+ group([
+ animate('0.3s 0.1s ease', style({
+ transform: 'translateX(0)',
+ width: 120
+ })),
+ animate('0.3s ease', style({
+ opacity: 1
+ }))
+ ])
+ ]),
+ transition('* => void', [
+ group([
+ animate('0.3s ease', style({
+ transform: 'translateX(50px)',
+ width: 10
+ })),
+ animate('0.3s 0.2s ease', style({
+ opacity: 0
+ }))
+ ])
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListGroupsComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-inline-styles.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-inline-styles.component.ts
new file mode 100644
index 0000000000..ed1bdb7646
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-inline-styles.component.ts
@@ -0,0 +1,60 @@
+// #docregion
+// #docregion imports
+import {
+ Component,
+ Input,
+} from '@angular/core';
+import {
+ trigger,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+// #enddocregion imports
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-inline-styles',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /**
+ * Define two states, "inactive" and "active", and the end
+ * styles that apply whenever the element is in those states.
+ * Then define an animation for the inactive => active transition.
+ * This animation has no end styles, but only styles that are
+ * defined inline inside the transition and thus are only kept
+ * as long as the animation is running.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('heroState', [
+ // #docregion transitions
+ transition('inactive => active', [
+ style({
+ backgroundColor: '#cfd8dc',
+ transform: 'scale(1.3)'
+ }),
+ animate('80ms ease-in', style({
+ backgroundColor: '#eee',
+ transform: 'scale(1)'
+ }))
+ ]),
+ // #enddocregion transitions
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListInlineStylesComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-multistep.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-multistep.component.ts
new file mode 100644
index 0000000000..4e57896de5
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-multistep.component.ts
@@ -0,0 +1,71 @@
+import {
+ Component,
+ Input,
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition,
+ keyframes,
+ AnimationEvent
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-multistep',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /* The element here always has the state "in" when it
+ * is present. We animate two transitions: From void
+ * to in and from in to void, to achieve an animated
+ * enter and leave transition. Each transition is
+ * defined in terms of multiple keyframes, to give it
+ * a bounce effect.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('flyInOut', [
+ state('in', style({transform: 'translateX(0)'})),
+ transition('void => *', [
+ animate(300, keyframes([
+ style({opacity: 0, transform: 'translateX(-100%)', offset: 0}),
+ style({opacity: 1, transform: 'translateX(15px)', offset: 0.3}),
+ style({opacity: 1, transform: 'translateX(0)', offset: 1.0})
+ ]))
+ ]),
+ transition('* => void', [
+ animate(300, keyframes([
+ style({opacity: 1, transform: 'translateX(0)', offset: 0}),
+ style({opacity: 1, transform: 'translateX(-15px)', offset: 0.7}),
+ style({opacity: 0, transform: 'translateX(100%)', offset: 1.0})
+ ]))
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListMultistepComponent {
+ @Input() heroes: Heroes;
+
+ animationStarted(event: AnimationEvent) {
+ console.warn('Animation started: ', event);
+ }
+
+ animationDone(event: AnimationEvent) {
+ console.warn('Animation done: ', event);
+ }
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-timings.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-timings.component.ts
new file mode 100644
index 0000000000..3218609b4a
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-timings.component.ts
@@ -0,0 +1,58 @@
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-timings',
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ styleUrls: ['./hero-list.component.css'],
+ /* The element here always has the state "in" when it
+ * is present. We animate two transitions: From void
+ * to in and from in to void, to achieve an animated
+ * enter and leave transition. The element enters from
+ * the left and leaves to the right using translateX,
+ * and fades in/out using opacity. We use different easings
+ * for enter and leave.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('flyInOut', [
+ state('in', style({opacity: 1, transform: 'translateX(0)'})),
+ transition('void => *', [
+ style({
+ opacity: 0,
+ transform: 'translateX(-100%)'
+ }),
+ animate('0.2s ease-in')
+ ]),
+ transition('* => void', [
+ animate('0.2s 10 ease-out', style({
+ opacity: 0,
+ transform: 'translateX(100%)'
+ }))
+ ])
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListTimingsComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list-twoway.component.ts b/public/docs/_examples/animations/ts/src/app/hero-list-twoway.component.ts
new file mode 100644
index 0000000000..46d0c64a68
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list-twoway.component.ts
@@ -0,0 +1,58 @@
+// #docregion
+// #docregion imports
+import {
+ Component,
+ Input
+} from '@angular/core';
+import {
+ trigger,
+ state,
+ style,
+ animate,
+ transition
+} from '@angular/animations';
+// #enddocregion imports
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-list-twoway',
+ // #docregion template
+ template: `
+
+
+ {{hero.name}}
+
+
+ `,
+ // #enddocregion template
+ styleUrls: ['./hero-list.component.css'],
+ /*
+ * Define two states, "inactive" and "active", and the end
+ * styles that apply whenever the element is in those states.
+ * Then define an animated transition between these two
+ * states, in *both* directions.
+ */
+ // #docregion animationdef
+ animations: [
+ trigger('heroState', [
+ state('inactive', style({
+ backgroundColor: '#eee',
+ transform: 'scale(1)'
+ })),
+ state('active', style({
+ backgroundColor: '#cfd8dc',
+ transform: 'scale(1.1)'
+ })),
+ // #docregion transitions
+ transition('inactive <=> active', animate('100ms ease-out'))
+ // #enddocregion transitions
+ ])
+ ]
+ // #enddocregion animationdef
+})
+export class HeroListTwowayComponent {
+ @Input() heroes: Heroes;
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-list.component.css b/public/docs/_examples/animations/ts/src/app/hero-list.component.css
new file mode 100644
index 0000000000..b256521e49
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-list.component.css
@@ -0,0 +1,27 @@
+ul {
+ list-style-type: none;
+ padding: 0;
+}
+
+li {
+ display: block;
+ width: 120px;
+ line-height: 50px;
+ padding: 0 10px;
+ box-sizing: border-box;
+ background-color: #eee;
+ border-radius: 4px;
+ margin: 10px;
+ cursor: pointer;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.active {
+ background-color: #cfd8dc;
+ transform: scale(1.1);
+}
+.inactive {
+ background-color: #eee;
+ transform: scale(1);
+}
diff --git a/public/docs/_examples/animations/ts/src/app/hero-team-builder.component.ts b/public/docs/_examples/animations/ts/src/app/hero-team-builder.component.ts
new file mode 100644
index 0000000000..e5413be50e
--- /dev/null
+++ b/public/docs/_examples/animations/ts/src/app/hero-team-builder.component.ts
@@ -0,0 +1,94 @@
+import { Component } from '@angular/core';
+
+import { Heroes } from './hero.service';
+
+@Component({
+ selector: 'hero-team-builder',
+ template: `
+
+
+
+
+
+
+
+
Basic State
+
Switch between active/inactive on click.
+
+
+
+
Styles inline in transitions
+
Animated effect on click, no persistend end styles.
+
+
+
+
Combined transition syntax
+
Switch between active/inactive on click. Define just one transition used in both directions.
+
+
+
+
Two-way transition syntax
+
Switch between active/inactive on click. Define just one transition used in both directions using the <=> syntax.
+
+
+
+
Enter & Leave
+
Enter and leave animations using the void state.
+
+
+
+
+
+
Enter & Leave & States
+
+ Enter and leave animations combined with active/inactive state animations.
+ Different enter and leave transitions depending on state.
+
+
+
+
+
Auto Style Calc
+
Leave animation from the current computed height using the auto-style value *.
+
+
+
+
Different Timings
+
Enter and leave animations with different easings, ease-in for enter, ease-out for leave.
+
+
+
+
Multiple Keyframes
+
Enter and leave animations with three keyframes in each, to give the transition some bounce.
+
+
+
+
Parallel Groups
+
Enter and leave animations with multiple properties animated in parallel with different timings.