Compare commits

..

130 Commits

Author SHA1 Message Date
1e1af7ffcb docs: changelog for 5.0.0-beta.2 release 2017-08-02 13:23:27 -07:00
a84b2bc945 release: cut the 5.0.0-beta.2 release 2017-08-02 13:21:07 -07:00
7abcb99d57 docs: add changelog for 4.3.3 2017-08-02 13:19:00 -07:00
49cd8513e4 feat(router): add events tracking activation of individual routes
* Adds `ChildActivationStart` and `ChildActivationEnd`
* Adds test to verify the PreActivation phase of routing
2017-08-01 10:44:00 -07:00
82b067fc40 build: ignore node_modules for tslint 2017-08-01 10:13:44 -07:00
9479a106bb build: enable TSLint on the packages folder 2017-07-31 15:47:57 -07:00
e64b54b67b fix(compiler): do not consider arguments when determining recursion
The static reflectory check for macro function recursion was too
agressive and disallowed calling a function with argument that also
calls the same function. For example, it disallowed nested animation
groups.

Fixes: #17467
2017-07-31 13:42:31 -07:00
cc2a4c41f9 build(aio): fix warning about missing <h1>
Fixes #17549
2017-07-31 13:40:07 -07:00
a11542a375 docs(aio): fixed list format in FormArray section 2017-07-31 11:31:05 -07:00
b6c4af6495 feat(compiler-cli): automatically lower lambda expressions in metadata 2017-07-31 11:30:44 -07:00
67dff7bd5d feat(tsc-wrapped): allow values to be substituted by collector clients
Also reenabled tests that were unintentionally disabled when they were
moved from tools/@angular.
2017-07-31 11:30:44 -07:00
381471d338 fix(compiler): fix for element needing implicit parent placed in top-level ng-container
fixes #18314
2017-07-31 11:30:19 -07:00
ebef5e697a feat(forms): add options arg to abstract controls
FormControls, FormGroups, and FormArrays now optionally accept an options
object as their second argument. Validators and async validators can be
passed in as part of this options object (though they can still be passed
in as the second and third arg as before).

```ts
const c = new FormControl(, {
   validators: [Validators.required],
   asyncValidators: [myAsyncValidator]
});
```

This commit also adds support for passing arrays of validators and async
validators to FormGroups and FormArrays, which formerly only accepted
individual functions.

```ts
const g = new FormGroup({
   one: new FormControl()
}, [myPasswordValidator, myOtherValidator]);
```

This change paves the way for adding more options to AbstractControls,
such as more fine-grained control of validation timing.
2017-07-31 11:29:32 -07:00
d71ae278ef fix(aio): fix links to source for paths with symlinks
Fixes #18353
2017-07-28 15:28:59 -07:00
46207538ef ci: short-circuit npm install for aio builds that use yarn only 2017-07-28 15:28:28 -07:00
71eb7437b6 docs(aio): delay ngUpgrade e2e test to avoid flakes 2017-07-28 15:28:28 -07:00
b5ffbe342b build: short-circuit build for AIO tasks 2017-07-28 15:28:28 -07:00
0f79223008 docs(aio): fix deprecated protractor API usage
`browser.getLocationAbsUrl()` is deprecated.
We should use `browser.getCurrentUrl()` instead.
2017-07-28 15:28:28 -07:00
a085223331 ci(aio): test the example e2e files using local build of Angular 2017-07-28 15:28:28 -07:00
c383048259 build(aio): ignore generated aot files
Assets such as images and data which are generated
by the aot build were not being ignored.
2017-07-28 15:28:28 -07:00
b18eb04b46 docs(aio): remove generated styles.css file
This file should have been ignored as it is created
during the build of the example
2017-07-28 15:28:28 -07:00
c8c2ab012a build(aio): support overriding the Angular packages in examples with locally built ones 2017-07-28 15:28:28 -07:00
ecff8e6c93 build(aio): refactor and test the example-boilerplate tool 2017-07-28 15:28:28 -07:00
51f1da1b85 ci: shard the aio example e2e tests 2017-07-28 15:28:28 -07:00
a5e18c4cdf ci(aio): support sharding of example e2e tests 2017-07-28 15:28:28 -07:00
cf6284656f build(aio): upgrade @angular/material to 2.0.0-meta.8 2017-07-28 15:26:45 -07:00
3182ddaf3e build(aio): upgrade @angular/* to 4.3.1 2017-07-28 15:26:45 -07:00
416ed691e5 docs(aio): fix URLSearchParams interface link to MDN
Fixes #18367
2017-07-28 15:26:04 -07:00
0fb7484d51 refactor(aio): move content-specific images to content/images/
Fixes #17053
2017-07-28 15:06:49 -07:00
6a3454e81e refactor(aio): rename unused directories to _unused 2017-07-28 15:06:49 -07:00
c3fbe87012 fix(aio): fix link to logo in example 2017-07-28 15:06:49 -07:00
24117d7a49 refactor(aio): move unused images to unused directories
This prevents the ServiceWorker from prefetching unnecessary files.
2017-07-28 15:06:49 -07:00
5808153359 docs: add changelog for 5.0.0.-beta.1 2017-07-27 14:59:24 -07:00
9030c8a03e release: cut the 5.0.0-beta.1 release 2017-07-27 14:57:38 -07:00
b14fc06fa2 docs: add changelog for 4.3.2 2017-07-27 14:52:35 -07:00
a7f2468184 Revert "fix(router): should throw when lazy loaded module doesn't define any routes (#15001)"
This reverts commit 82923a381d.
2017-07-27 10:53:01 -07:00
fae47d86b3 refactor(forms): move value accessor tests into own spec (#18356)
PR Close #18356
2017-07-26 17:55:37 -05:00
d20ac14fe2 refactor(compiler-cli): allow custom error checking function in ngc (#18355)
PR Close #18355
2017-07-26 17:55:31 -05:00
cae3e6dca0 ci: give ownership of ngc-wrapped to compiler-cli maintainers (#18354)
PR Close #18354
2017-07-26 17:55:24 -05:00
086f4aa72c fix(router): child CanActivate guard should wait for parent to complete (#18110)
Closes #15670

PR Close #18110
2017-07-26 17:11:22 -05:00
82923a381d fix(router): should throw when lazy loaded module doesn't define any routes (#15001)
Closes #14596

PR Close #15001
2017-07-26 17:11:07 -05:00
5152abb037 docs(aio): add my details as a contributor (#18315)
PR Close #18315
2017-07-26 17:11:07 -05:00
67f7032321 fix(aio): correctly process markdown link in "Browser Support" (#18349)
The markdown processor expects an empty line between an opening tag and the
markdown content. (If there is no empty line, the content is interpreted as
plain HTML.)
Previously, the line between the opening `<td>` and the content contained
whitespace, which caused the content to be interpreted as HTML and not markdown.

Fixes #18312

PR Close #18349
2017-07-26 16:07:26 -05:00
205abe8140 build: fix broken bazel build (#18335) 2017-07-26 09:40:33 -07:00
b582e2b311 docs(aio): update examples to 4.3 2017-07-25 15:32:38 -07:00
91ab39cc55 docs(aio) - Fixed link to the glossary dash-case term (#18311)
PR Close #18311
2017-07-25 15:59:28 -05:00
38ec05f533 fix(compiler): add equiv & disp attributes to Xliff2 ICU placeholders (#18283)
Fixes #17344

PR Close #18283
2017-07-25 15:58:53 -05:00
b3085e96c2 feat(compiler): add representation of placeholders to xliff & xmb
Closes #17345
2017-07-25 15:58:53 -05:00
4cea2bd612 docs(platform-server): inline PlatformOptions and add doc strings (#18264)
Fix documentation for the options passed into renderModule and
renderModuleFactory.

PR Close #18264
2017-07-25 15:58:13 -05:00
ce47546188 refactor(compiler-cli): add support for browser compiler bundle (#17979)
PR Close #17979
2017-07-25 15:51:46 -05:00
6279e50d78 perf(core): use native addEventListener for faster rendering. (#18107)
Angular can make many assumptions about its event handlers. As a result
the bookkeeping for native addEventListener is significantly cheaper
than Zone's addEventLister which can't make such assumptions.

This change bypasses the Zone's addEventListener if present and always
uses the native addEventHandler. As a result registering event listeners
is about 3 times faster.

PR Close #18107
2017-07-25 15:35:44 -05:00
8bcb268140 ci: use chrome stable (#18307) 2017-07-25 11:18:24 -07:00
6fc5940959 build: Bazel builds ngfactories for packages/core (#18289)
PR Close #18289
2017-07-21 18:09:47 -05:00
0317c4c478 build: update bazel rules to latest (#18289) 2017-07-21 18:09:44 -05:00
b7a6f52d59 perf: latest tsickle to tree shake: abstract class methods & interfaces (#18236)
In previous version of tsickle abstract class methods were materialized.
The change resulted in 6Kb savings in angular.io bundle.

This change also required the removal of `@private` and `@return` type
annotation as it is explicitly dissalowed by tsickle.

NOTE: removed casts in front of `makeDecorator` due to:
https://github.com/angular/devkit/issues/45

```
 14938 Jul 19 13:16 0.b19e913fbdd6507d346b.chunk.js
  1535 Jul 19 13:16 inline.d8e019ea3cfdd86c2bd0.bundle.js
589178 Jul 19 13:16 main.54c97bcb6f254776b678.bundle.js
 34333 Jul 19 13:16 polyfills.4a3c9ca9481d53803157.bundle.js

 14938 Jul 18 16:55 0.b19e913fbdd6507d346b.chunk.js
  1535 Jul 18 16:55 inline.0c83abb44fad9a2768a7.bundle.js
582786 Jul 18 16:55 main.ea290db71b051813e156.bundle.js
 34333 Jul 18 16:55 polyfills.4a3c9ca9481d53803157.bundle.js

main savings: 589178 - 582786 = 6,392
```

PR Close #18236
2017-07-21 16:35:37 -05:00
7ae7573bc8 fix(core): invoke error handler outside of the Angular Zone (#18269)
In Node.JS console.log/error/warn functions actually resuls in a socket
write which in turn is considered by Zone.js as an async task.

This means that if there is any exception during change detection in a platform-server
application the error handler will make the Angular Zone unstable which
in turn will cause change detection to run on next tick and cause an
infinite loop.

It is also better to run the error handler outside of the Angular Zone
in general on all platforms so that an error in the error handler itself doesn't cause an
infinite loop.

Fixes #17073, #7774.

PR Close #18269
2017-07-21 16:35:23 -05:00
abee785821 refactor(tsc-wrapped): update tsc-wrapped to pass strictNullCheck (#18160)
PR Close #18160
2017-07-21 12:26:20 -05:00
619e625ee2 refactor(tsc-wrapped): move tsc-wrapped to the packages directory (#18160) 2017-07-21 12:26:16 -05:00
a6c635e69e ci: force precise on Travis (#18282)
PR Close #18282
2017-07-21 12:20:27 -05:00
e0a9625e46 test: fix bad merge (#18267)
PR Close #18267
2017-07-21 11:53:34 -05:00
fd0cc01eed fix(animations): export BrowserModule as apart of BrowserAnimationsModule (#18263)
PR Close #18263
2017-07-20 17:47:49 -05:00
1bfc77bf8c docs(aio): pngcrush all pngs (#18243)
PR Close #18243
2017-07-20 17:47:06 -05:00
a094769bca fix(platform-server): don't clobber parse5 properties when setting (#18237)
element properties.

Fixes #17050.

We now store all element properties in a separate 'properties' bag.

PR Close #18237
2017-07-20 17:46:37 -05:00
b4c98305da refactor(common): CleanUp HttpClient's imports (#18120)
PR Close #18120
2017-07-20 17:43:23 -05:00
a3a54299af fix(compiler): allow numbers for ICU message cases in lexer (#18095)
Closes #18095
Fixes #17799
2017-07-20 17:41:54 -05:00
15a3e2d307 ci(aio): fix aio payload script 2017-07-20 15:32:32 -07:00
54e0244954 Revert "docs: Remove unneeded file (#18106)"
This reverts commit 72fe45db2b.
2017-07-20 16:46:47 -05:00
43c33d5663 fix(upgrade): ensure downgraded components are created in the Angular zone (#18209)
PR Close #18209
2017-07-20 16:25:11 -05:00
6d7799fce9 test(upgrade): fail tests when there are AngularJS errors (#18209) 2017-07-20 16:25:07 -05:00
d31dc7b2b3 fix(upgrade): throw error if trying to get injector before setting (#18209)
Previously, `undefined` would be returned.
This change makes it easier to identify incorrect uses/bugs.
(Discussed in https://github.com/angular/angular/pull/18213#issuecomment-316191308.)
2017-07-20 16:24:45 -05:00
4cd4f7a208 aio: debounce search and delay index building (#18134)
* feat(aio): debounce search requests

* feat(aio): delay loading search worker and index
2017-07-20 09:51:40 -07:00
72fe45db2b docs: Remove unneeded file (#18106) 2017-07-20 09:50:17 -07:00
8d2819121b fix(aio): invalid formatting in architecure.md (#18159)
Introduced in e110a80caf (diff-9ac9c6a9277eea9856d75249a7c0a40aL127)
2017-07-20 09:48:02 -07:00
073e8ba2f2 docs(aio): replace old blog link (#18252)
Fixes #18233
* Docs(aio): Replaced old blog link Now with the Link to the new Angular.io Blog
* Removed double braces
2017-07-20 09:45:14 -07:00
5d1864fe68 docs: fixing invisible tag in README (#18245) 2017-07-20 09:43:42 -07:00
eaa843b55f ci: test bazel builds on travis (#18240) 2017-07-20 09:40:40 -07:00
c6cf678a07 docs(aio): Fixed typo with closing div 2017-07-20 09:38:28 -07:00
31cb418370 docs(aio): Fix http guide 2017-07-20 09:35:27 -07:00
8de44cf5e3 docs: fix wrong link in CONTRIBUTING.md (#18228)
The link to the CONTRIBUTING.md file was not correct
2017-07-20 09:33:15 -07:00
c67bad4f43 docs(router): minor typo (#18226)
Fix a minor typo in the description of a router spec.
2017-07-20 09:32:34 -07:00
410f21c75c docs(aio): fix typo in NgModule FAQs (#18211)
Fix #18133. Fix typo 'added' to 'add' in the 'Why does lazy loading create a child injector' section.
2017-07-20 09:07:30 -07:00
54ea5b6ffd docs: add changelog for 5.0.0-beta.0 2017-07-19 13:16:43 -07:00
0af03beaed release: cut the 5.0.0-beta.0 release 2017-07-19 13:12:50 -07:00
d71fa734f5 docs: add changelog for 4.3.1 2017-07-19 12:55:08 -07:00
6f45519d6f feat(animations): support :increment and :decrement transition aliases 2017-07-19 11:24:00 -07:00
65c9e13105 fix(compiler-cli): don't generate empty <target/> when extracting xliff
Fixes #15754
2017-07-19 09:45:52 -07:00
9208f0beea docs(aio): fix typo in Router documentation
Fix title and link to RouteConfigLoadEnd documentation
2017-07-19 15:01:50 +01:00
5344be5182 fix(animations): make sure @.disabled works in non-animation components
Note 4.3 only!

Prior to this fix when [@.disabled] was used in a component that
contained zero animation code it wouldn't register properly because the
renderer associated with that component was not an animation renderer.
This patch ensures that it gets registered even when there are no
animations set.
2017-07-18 16:37:04 -07:00
5db6f38b73 fix(animations): do not crash animations if a nested component fires CD during CD
Closes #18193
2017-07-18 15:22:43 -07:00
d22f8f54db fix(animations): always camelcase style property names that contain auto styles
Closes #17938
2017-07-18 15:22:30 -07:00
23146c9201 fix(animations): capture cancelled animation styles within grouped animations
Closes #17170
2017-07-18 15:22:10 -07:00
a5205c686e fix(upgrade): allow accessing AngularJS injector from downgraded module 2017-07-18 14:00:19 -07:00
807648251f fix(platform-server): provide XhrFactory for HttpClient 2017-07-18 13:59:26 -07:00
5c62e300e1 fix(common): send flushed body as error instead of null
fix #18181
2017-07-18 10:57:51 -07:00
256bc8acdd docs(http): Make name of injected HttpTestingController consistent 2017-07-18 10:35:56 -07:00
59c23c7bd7 feat(upgrade): propagate touched state of NgModelController 2017-07-18 10:35:35 -07:00
e03adb9edd docs(platform-server): add doc string for PlatformOptions 2017-07-18 10:34:57 -07:00
b399cb26d9 fix(router): terminal route in custom matcher 2017-07-18 10:25:18 -07:00
3b588fe2b0 docs: fix typo 2017-07-18 10:11:55 -07:00
95635c18c7 fix(compiler): ensure jit external id arguments names are unique
Fixes: #17558, #17378, #8676
2017-07-18 10:11:32 -07:00
e20cfe1bbc fix(router): canDeactivate guards should run from bottom to top
Closes #15657.
2017-07-18 10:04:39 -07:00
eb6fb5f87e fix(router): should navigate to the same url when config changes
Closes #15535
2017-07-18 10:04:11 -07:00
ad3029e786 fix(router): should run resolvers for the same route concurrently
Fixes #14279
2017-07-18 10:03:33 -07:00
2a2fe11e8d docs(aio): fix HttpClient setting new header sample 2017-07-18 10:02:27 -07:00
7d0f2cd51e fix(aio): remove title attribute from CodeExampleComponent
This was causing browser to add an unwanted tooltip that appeared
when the user hovers over the code.

See #17524
2017-07-18 17:55:28 +01:00
36faba1aab fix(aio): add quote to module 2017-07-18 17:48:04 +01:00
92179bcc64 fix(aio): do not wrap <code-tabs> tab labels
Fixes #17751
2017-07-18 17:43:59 +01:00
cdb069ab0e docs(aio): fix cheatsheet layout for narrow screens
* Tell the app that this will have no Table of Contents, since we have no
h2 headings anyway.
* Remove all the `nbsp;` from the code since that doesn't help with layout
* Remove side padding from sidenav-content when screen is narrow
* Restyle the cheatsheet table when the screen is narrow
2017-07-18 17:32:43 +01:00
c453b7bcfa build(aio): fail doc-gen if referenced images are missing 2017-07-18 11:45:05 +01:00
9d97163c64 docs(aio): fix broken image sources 2017-07-18 11:45:05 +01:00
f054c8360b docs(aio): fix up broken links 2017-07-18 11:45:05 +01:00
758848961e build(aio): abort doc-gen on dangling links 2017-07-18 11:45:05 +01:00
99b666614d build(aio): abort doc-gen if an example is missing
Closes #16936
2017-07-18 11:45:05 +01:00
3f331b53b2 docs(aio): update jelbourn photo 2017-07-17 14:51:11 -07:00
375d598a9f docs(aio): add George's fixes 2017-07-17 14:49:19 -07:00
cd67fced1c docs(aio): add npm install to Sublime instructions 2017-07-17 14:49:19 -07:00
a77cf7ee37 docs(aio): add Chuck's comments 2017-07-17 14:49:19 -07:00
2150b45954 docs(aio): add language service doc 2017-07-17 14:49:19 -07:00
9f99f4fae2 docs: fix HttpClient sample 2017-07-17 14:03:32 -07:00
c6ad212a98 docs(aio): fix HttpClient's interceptor sample 2017-07-17 14:03:16 -07:00
47b3ecd9a3 docs(http): fix "Expecting and answering requests" example mistake
Possibly overlooked testing documentation mistake fixed:
- `http.get('/data')` probably ought to be paired with `httpMock.expectOne('/data')` instead of `httpMock.expectOne('/data')`.
2017-07-17 14:01:44 -07:00
8c81c62d46 docs: fix HttpClient logging's sample 2017-07-17 14:01:24 -07:00
7e72317059 docs(http): fixed syntax error in AuthInterceptor example 2017-07-17 14:00:59 -07:00
0bb8423df9 ci: add GK and PBD to aio content and marketing groups 2017-07-17 10:52:34 -07:00
95698d93ad fix(aio): remove title from callout 2017-07-15 15:35:15 +01:00
c649da9f0a fix(aio): remove unused news.html file
Although outdated and not used, the file would be picked up and showed in search
results.
2017-07-15 15:29:20 +01:00
0bf0c35bca build(aio): render type parameters of API function exports
Fixes #18123
2017-07-15 08:52:35 +01:00
97e6901ded Revert "revert: revert: ci(aio): exclude changes in aio/content folder"
This reverts commit 3d85f72652.

Still causing repeated flakes on master.
2017-07-14 14:54:31 -07:00
30e76fcd80 feat(upgrade): support lazy-loading Angular module into AngularJS app 2017-07-14 14:10:30 -07:00
44b50427d9 refactor(upgrade): clean up some types 2017-07-14 14:10:30 -07:00
283 changed files with 6140 additions and 3186 deletions

View File

@ -42,7 +42,7 @@ jobs:
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }} key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
- run: bazel run @build_bazel_rules_typescript_node//:bin/npm install - run: bazel run @build_bazel_rules_typescript_node//:bin/npm install
- run: bazel build ... - run: bazel build packages/...
- save_cache: - save_cache:
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }} key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
paths: paths:

View File

@ -69,8 +69,8 @@ groups:
- "*.lock" - "*.lock"
- "tools/*" - "tools/*"
exclude: exclude:
- "tools/@angular/tsc-wrapped/*"
- "tools/public_api_guard/*" - "tools/public_api_guard/*"
- "tools/ngc-wrapped/*"
- "aio/*" - "aio/*"
users: users:
- IgorMinar #primary - IgorMinar #primary
@ -136,8 +136,9 @@ groups:
compiler-cli: compiler-cli:
conditions: conditions:
files: files:
- "tools/@angular/tsc-wrapped/*" - "packages/tsc-wrapped/*"
- "packages/compiler-cli/*" - "packages/compiler-cli/*"
- "tools/ngc-wrapped/*"
users: users:
- alexeagle - alexeagle
- chuckjaz - chuckjaz

View File

@ -55,7 +55,8 @@ env:
- CI_MODE=browserstack_optional - CI_MODE=browserstack_optional
- CI_MODE=docs_test - CI_MODE=docs_test
- CI_MODE=aio - CI_MODE=aio
- CI_MODE=aio_e2e - CI_MODE=aio_e2e AIO_SHARD=0
- CI_MODE=aio_e2e AIO_SHARD=1
- CI_MODE=bazel - CI_MODE=bazel
matrix: matrix:
@ -63,7 +64,6 @@ matrix:
allow_failures: allow_failures:
- env: "CI_MODE=saucelabs_optional" - env: "CI_MODE=saucelabs_optional"
- env: "CI_MODE=browserstack_optional" - env: "CI_MODE=browserstack_optional"
- env: "CI_MODE=aio_e2e"
before_install: before_install:
# source the env.sh script so that the exported variables are available to other scripts later on # source the env.sh script so that the exported variables are available to other scripts later on

View File

@ -1,3 +1,59 @@
<a name="5.0.0-beta.2"></a>
# [5.0.0-beta.2](https://github.com/angular/angular/compare/5.0.0-beta.1...5.0.0-beta.2) (2017-08-02)
### Bug Fixes
* **compiler:** do not consider arguments when determining recursion ([e64b54b](https://github.com/angular/angular/commit/e64b54b))
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([381471d](https://github.com/angular/angular/commit/381471d)), closes [#18314](https://github.com/angular/angular/issues/18314)
### Features
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
* **router:** add events tracking activation of individual routes ([49cd851](https://github.com/angular/angular/commit/49cd851))
<a name="4.3.3"></a>
## [4.3.3](https://github.com/angular/angular/compare/4.3.2...4.3.3) (2017-08-02)
### Bug Fixes
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([f5cbc2e](https://github.com/angular/angular/commit/f5cbc2e)), closes [#18314](https://github.com/angular/angular/issues/18314)
<a name="5.0.0-beta.1"></a>
# [5.0.0-beta.1](https://github.com/angular/angular/compare/5.0.0-beta.0...5.0.0-beta.1) (2017-07-27)
### Bug Fixes
* **animations:** export BrowserModule as apart of BrowserAnimationsModule ([#18263](https://github.com/angular/angular/issues/18263)) ([fd0cc01](https://github.com/angular/angular/commit/fd0cc01))
* **compiler:** add equiv & disp attributes to Xliff2 ICU placeholders ([#18283](https://github.com/angular/angular/issues/18283)) ([38ec05f](https://github.com/angular/angular/commit/38ec05f)), closes [#17344](https://github.com/angular/angular/issues/17344)
* **compiler:** allow numbers for ICU message cases in lexer ([#18095](https://github.com/angular/angular/issues/18095)) ([a3a5429](https://github.com/angular/angular/commit/a3a5429)), closes [#17799](https://github.com/angular/angular/issues/17799)
* **core:** invoke error handler outside of the Angular Zone ([#18269](https://github.com/angular/angular/issues/18269)) ([7ae7573](https://github.com/angular/angular/commit/7ae7573)), closes [#17073](https://github.com/angular/angular/issues/17073) [#7774](https://github.com/angular/angular/issues/7774)
* **platform-server:** don't clobber parse5 properties when setting ([#18237](https://github.com/angular/angular/issues/18237)) ([a094769](https://github.com/angular/angular/commit/a094769)), closes [#17050](https://github.com/angular/angular/issues/17050)
* **router:** child CanActivate guard should wait for parent to complete ([#18110](https://github.com/angular/angular/issues/18110)) ([086f4aa](https://github.com/angular/angular/commit/086f4aa)), closes [#15670](https://github.com/angular/angular/issues/15670)
* **router:** should throw when lazy loaded module doesn't define any routes ([#15001](https://github.com/angular/angular/issues/15001)) ([82923a3](https://github.com/angular/angular/commit/82923a3)), closes [#14596](https://github.com/angular/angular/issues/14596)
* **upgrade:** ensure downgraded components are created in the Angular zone ([#18209](https://github.com/angular/angular/issues/18209)) ([43c33d5](https://github.com/angular/angular/commit/43c33d5))
* **upgrade:** throw error if trying to get injector before setting ([#18209](https://github.com/angular/angular/issues/18209)) ([d31dc7b](https://github.com/angular/angular/commit/d31dc7b))
### Features
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
### Performance Improvements
* latest tsickle to tree shake: abstract class methods & interfaces ([#18236](https://github.com/angular/angular/issues/18236)) ([b7a6f52](https://github.com/angular/angular/commit/b7a6f52))
* **core:** use native addEventListener for faster rendering. ([#18107](https://github.com/angular/angular/issues/18107)) ([6279e50](https://github.com/angular/angular/commit/6279e50))
<a name="4.3.2"></a> <a name="4.3.2"></a>
## [4.3.2](https://github.com/angular/angular/compare/4.3.1...4.3.2) (2017-07-26) ## [4.3.2](https://github.com/angular/angular/compare/4.3.1...4.3.2) (2017-07-26)
@ -15,6 +71,35 @@
<a name="5.0.0-beta.0"></a>
# [5.0.0-beta.0](https://github.com/angular/angular/compare/4.3.0...5.0.0-beta.0) (2017-07-19)
### Bug Fixes
* **animations:** always camelcase style property names that contain auto styles ([d22f8f5](https://github.com/angular/angular/commit/d22f8f5)), closes [#17938](https://github.com/angular/angular/issues/17938)
* **animations:** capture cancelled animation styles within grouped animations ([23146c9](https://github.com/angular/angular/commit/23146c9)), closes [#17170](https://github.com/angular/angular/issues/17170)
* **animations:** do not crash animations if a nested component fires CD during CD ([5db6f38](https://github.com/angular/angular/commit/5db6f38)), closes [#18193](https://github.com/angular/angular/issues/18193)
* **animations:** make sure @.disabled works in non-animation components ([5344be5](https://github.com/angular/angular/commit/5344be5))
* **common:** send flushed body as error instead of null ([5c62e30](https://github.com/angular/angular/commit/5c62e30)), closes [#18181](https://github.com/angular/angular/issues/18181)
* **compiler:** ensure jit external id arguments names are unique ([95635c1](https://github.com/angular/angular/commit/95635c1))
* **compiler-cli:** don't generate empty <target/> when extracting xliff ([65c9e13](https://github.com/angular/angular/commit/65c9e13)), closes [#15754](https://github.com/angular/angular/issues/15754)
* **platform-server:** provide XhrFactory for HttpClient ([8076482](https://github.com/angular/angular/commit/8076482))
* **router:** canDeactivate guards should run from bottom to top ([e20cfe1](https://github.com/angular/angular/commit/e20cfe1)), closes [#15657](https://github.com/angular/angular/issues/15657)
* **router:** should navigate to the same url when config changes ([eb6fb5f](https://github.com/angular/angular/commit/eb6fb5f)), closes [#15535](https://github.com/angular/angular/issues/15535)
* **router:** should run resolvers for the same route concurrently ([ad3029e](https://github.com/angular/angular/commit/ad3029e)), closes [#14279](https://github.com/angular/angular/issues/14279)
* **router:** terminal route in custom matcher ([b399cb2](https://github.com/angular/angular/commit/b399cb2))
* **upgrade:** allow accessing AngularJS injector from downgraded module ([a5205c6](https://github.com/angular/angular/commit/a5205c6))
### Features
* **animations:** support :increment and :decrement transition aliases ([6f45519](https://github.com/angular/angular/commit/6f45519))
* **upgrade:** propagate touched state of NgModelController ([59c23c7](https://github.com/angular/angular/commit/59c23c7))
* **upgrade:** support lazy-loading Angular module into AngularJS app ([30e76fc](https://github.com/angular/angular/commit/30e76fc))
<a name="4.3.1"></a> <a name="4.3.1"></a>
## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19) ## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19)

View File

@ -43,13 +43,9 @@ dist/
**/app/**/*.ajs.js **/app/**/*.ajs.js
# aot # aot
**/*.ngfactory.ts */aot/**/*
**/*.ngsummary.json !*/aot/bs-config.json
**/*.ngsummary.ts !*/aot/index.html
**/*.shim.ngstyle.ts
**/*.metadata.json
!aot/bs-config.json
!aot/index.html
!rollup-config.js !rollup-config.js
# i18n # i18n

View File

@ -9,7 +9,7 @@ export class AppComponent {
wolves = 0; wolves = 0;
gender = 'f'; gender = 'f';
fly = true; fly = true;
logo = 'https://angular.io/resources/images/logos/angular/angular.png'; logo = 'https://angular.io/assets/images/logos/angular/angular.png';
count = 3; count = 3;
heroes: string[] = ['Magneta', 'Celeritas', 'Dynama']; heroes: string[] = ['Magneta', 'Celeritas', 'Dynama'];
inc(i: number) { inc(i: number) {

View File

@ -1,116 +0,0 @@
/* #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;
}

View File

@ -9,7 +9,8 @@ describe('PhoneCat Application', function() {
it('should redirect `index.html` to `index.html#!/phones', function() { it('should redirect `index.html` to `index.html#!/phones', function() {
browser.get('index.html'); browser.get('index.html');
expect(browser.getLocationAbsUrl()).toBe('/phones'); browser.sleep(1000); // Not sure why this is needed but it is. The route change works fine.
expect(browser.getCurrentUrl()).toMatch(/\/phones$/);
}); });
describe('View: Phone list', function() { describe('View: Phone list', function() {
@ -65,7 +66,7 @@ describe('PhoneCat Application', function() {
element.all(by.css('.phones li a')).first().click(); element.all(by.css('.phones li a')).first().click();
browser.sleep(1000); // Not sure why this is needed but it is. The route change works fine. browser.sleep(1000); // Not sure why this is needed but it is. The route change works fine.
expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s'); expect(browser.getCurrentUrl()).toMatch(/\/phones\/nexus-s$/);
}); });
}); });

View File

@ -0,0 +1,176 @@
# Angular Language Service
The Angular Language Service is a way to get completions, errors,
hints, and navigation inside your Angular templates whether they
are external in an HTML file or embedded in annotations/decorators
in a string. The Angular Language Service autodetects that you are
opening an Angular file, reads your `tsconfig.json` file, finds all the
templates you have in your application, and then provides language
services for any templates that you open.
## Autocompletion
Autocompletion can speed up your development time by providing you with
contextual possibilities and hints as you type. This example shows
autocomplete in an interpolation. As you type it out,
you can hit tab to complete.
<figure>
<img src="generated/images/guide/language-service/language-completion.gif" alt="autocompletion">
</figure>
There are also completions within
elements. Any elements you have as a component selector will
show up in the completion list.
## Error checking
The Angular Language Service can also forewarn you of mistakes in your code.
In this example, Angular doesn't know what `orders` is or where it comes from.
<figure>
<img src="generated/images/guide/language-service/language-error.gif" alt="error checking">
</figure>
## Navigation
Navigation allows you to hover to
see where a component, directive, module, etc. is from and then
click and press F12 to go directly to its definition.
<figure>
<img src="generated/images/guide/language-service/language-navigation.gif" alt="navigation">
</figure>
## Angular Language Service in your editor
Angular Language Service is currently available for [Visual Studio Code](https://code.visualstudio.com/) and
[WebStorm](https://www.jetbrains.com/webstorm).
### Visual Studio Code
In Visual Studio Code, install Angular Language Service from the store,
which is accessible from the bottom icon on the left menu pane.
You can also use the VS Quick Open (⌘+P) to search for the extension. When you've opened it,
enter the following command:
```sh
ext install ng-template
```
Then click the install button to install the Angular Language Service.
### WebStorm
In webstorm, you have to install the language service as a dev dependency.
When Angular sees this dev dependency, it provides the
language service inside of WebStorm. Webstorm then gives you
colorization inside the template and autocomplete in addition to the Angular Language Service.
Here's the dev dependency
you need to have in `package.json`:
```json
devDependencies {
"@angular/language-service": "^4.0.0"
}
```
Then in the terminal window at the root of your project,
install the `devDependencies` with `npm` or `yarn`:
```sh
npm install
```
*OR*
```sh
yarn
```
*OR*
```sh
yarn install
```
### Sublime Text
In [Sublime Text](https://www.sublimetext.com/), you first need an extension to allow Typescript.
Install the latest version of typescript in a local `node_modules` directory:
```sh
npm install --save-dev typescript
```
Then install the Angular Language Service in the same location:
```sh
npm install --save-dev @angular/language-service
```
Starting with TypeScript 2.3, TypeScript has a language service plugin model that the language service can use.
Next, in your user preferences (`Cmd+,` or `Ctrl+,`), add:
```json
"typescript-tsdk": "<path to your folder>/node_modules/typescript/lib"
```
## Installing in your project
You can also install Angular Language Service in your project with the
following `npm` command:
```sh
npm install --save-dev @angular/language-service
```
Additionally, add the following to the `"compilerOptions"` section of
your project's `tsconfig.json`.
```json
"plugins": [
{"name": "@angular/language-service"}
]
```
Note that this only provides diagnostics and completions in `.ts`
files. You need a custom sublime plugin (or modifications to the current plugin)
for completions in HTML files.
## How the Language Service works
When you use an editor with a language service, there's an
editor process which starts a separate language process/service
to which it speaks through an [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call).
Any time you type inside of the editor, it sends information to the other process to
track the state of your project. When you trigger a completion list within a template, the editor process first parses the template into an HTML AST, or [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree). Then the Angular compiler interprets
what module the template is part of, the scope you're in, and the component selector. Then it figures out where in the template AST your cursor is. When it determines the
context, it can then determine what the children can be.
It's a little more involved if you are in an interpolation. If you have an interpolation of `{{data.---}}` inside a `div` and need the completion list after `data.---`, the compiler can't use the HTML AST to find the answer. The HTML AST can only tell the compiler that there is some text with the characters "`{{data.---}}`". That's when the template parser produces an expression AST, which resides within the template AST. The Angular Language Services then looks at `data.---` within its context and asks the TypeScript Language Service what the members of data are. TypeScript then returns the list of possibilities.
For more in-depth information, see the
[Angular Language Service API](https://github.com/angular/angular/blob/master/packages/language-service/src/types.ts)
<hr>
## More on Information
For more information, see [Chuck Jazdzewski's presentation](https://www.youtube.com/watch?v=ez3R0Gi4z5A&t=368s) on the Angular Language
Service from [ng-conf](https://www.ng-conf.org/) 2017.

View File

@ -1080,8 +1080,11 @@ To get access to the `FormArray` class, import it into `hero-detail.component.ts
To _work_ with a `FormArray` you do the following: To _work_ with a `FormArray` you do the following:
1. Define the items (`FormControls` or `FormGroups`) in the array. 1. Define the items (`FormControls` or `FormGroups`) in the array.
1. Initialize the array with items created from data in the _data model_. 1. Initialize the array with items created from data in the _data model_.
1. Add and remove items as the user requires. 1. Add and remove items as the user requires.
In this guide, you define a `FormArray` for `Hero.addresses` and In this guide, you define a `FormArray` for `Hero.addresses` and

View File

@ -1830,7 +1830,7 @@ Finally, you activate the observable with `subscribe` method and (re)set the com
#### _ParamMap_ API #### _ParamMap_ API
The `ParamMap` API is inspired by the [URLSearchParams interface](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParamsOPut). It provides methods The `ParamMap` API is inspired by the [URLSearchParams interface](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams). It provides methods
to handle parameter access for both route parameters (`paramMap`) and query parameters (`queryParamMap`). to handle parameter access for both route parameters (`paramMap`) and query parameters (`queryParamMap`).
<table> <table>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 257 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -8,7 +8,7 @@
<div class="feature-section"> <div class="feature-section">
<div class="feature-header"> <div class="feature-header">
<div class="text-headline">Cross Platform</div> <div class="text-headline">Cross Platform</div>
<img src="assets/images/icons/feature-icon.svg" height="70px"> <img src="generated/images/marketing/features/feature-icon.svg" height="70px">
</div> </div>
<div class="feature-row"> <div class="feature-row">
@ -34,7 +34,7 @@
<div class="feature-section"> <div class="feature-section">
<div class="feature-header"> <div class="feature-header">
<div class="text-headline">Speed and Performance</div> <div class="text-headline">Speed and Performance</div>
<img src="assets/images/icons/feature-icon.svg" height="70px"> <img src="generated/images/marketing/features/feature-icon.svg" height="70px">
</div> </div>
<div class="feature-row"> <div class="feature-row">
@ -59,7 +59,7 @@
<div class="feature-section"> <div class="feature-section">
<div class="feature-header"> <div class="feature-header">
<div class="text-headline">Productivity</div> <div class="text-headline">Productivity</div>
<img src="assets/images/icons/feature-icon.svg" height="70px"> <img src="generated/images/marketing/features/feature-icon.svg" height="70px">
</div> </div>
<div class="feature-row"> <div class="feature-row">
@ -84,7 +84,7 @@
<div class="feature-section"> <div class="feature-section">
<div class="feature-header"> <div class="feature-header">
<div class="text-headline">Full Development Story</div> <div class="text-headline">Full Development Story</div>
<img src="assets/images/icons/feature-icon.svg" height="70px"> <img src="generated/images/marketing/features/feature-icon.svg" height="70px">
</div> </div>
<div class="feature-row"> <div class="feature-row">

View File

@ -1,10 +1,10 @@
<!--FULL HEADER BLOCK--> <!-- FULL HEADER BLOCK -->
<header> <header>
<!--BACKGROUND IMAGE--> <!-- BACKGROUND IMAGE -->
<div class="background-sky hero"></div> <div class="background-sky hero"></div>
<!--INTRO SECTION --> <!-- INTRO SECTION -->
<section id="intro"> <section id="intro">
<!-- LOGO --> <!-- LOGO -->
@ -12,35 +12,37 @@
<img src="assets/images/logos/angular/angular.svg"/> <img src="assets/images/logos/angular/angular.svg"/>
</div> </div>
<!-- CONTAINER --> <!-- CONTAINER -->
<div class="homepage-container"> <div class="homepage-container">
<!-- container content starts -->
<div class="hero-headline no-toc">One framework.<br>Mobile &amp; desktop.</div> <div class="hero-headline no-toc">One framework.<br>Mobile &amp; desktop.</div>
<a class="button hero-cta" href="guide/quickstart">Get Started</a> <a class="button hero-cta" href="guide/quickstart">Get Started</a>
</div><!-- CONTAINER END --> </div>
</section>
</section>
</header> </header>
<!-- MAIN CONTENT -->
<article> <article>
<h1 class="no-toc" style="display: none"></h1>
<div class="home-rows"> <div class="home-rows">
<!--Announcement Bar--> <!-- Announcement Bar -->
<div class="homepage-container"> <div class="homepage-container">
<div class="announcement-bar"> <div class="announcement-bar">
<img src="generated/images/marketing/angular-mix.png" height="40" width="151"> <img src="generated/images/marketing/home/angular-mix.png" height="40" width="151">
<p>Join us at our newest event, October 2017</p> <p>Join us at our newest event, October 2017</p>
<a class="button" href="https://angularmix.com/">Learn More</a> <a class="button" href="https://angularmix.com/">Learn More</a>
</div> </div>
</div> </div>
<!-- Group 1--> <!-- Group 1 -->
<div layout="row" layout-xs="column" class="home-row homepage-container"> <div layout="row" layout-xs="column" class="home-row homepage-container">
<div class="promo-img-container promo-1"> <div class="promo-img-container promo-1">
<div> <div>
<img height="222" width="340" src="assets/images/home/responsive-framework.svg" alt="responsive framework"> <img height="222" width="340" src="generated/images/marketing/home/responsive-framework.svg" alt="responsive framework">
</div> </div>
</div> </div>
@ -53,7 +55,8 @@
</div> </div>
</div> </div>
<hr> <hr>
<!-- Group 2-->
<!-- Group 2 -->
<div layout="row" layout-xs="column" class="home-row"> <div layout="row" layout-xs="column" class="home-row">
<div class="text-container"> <div class="text-container">
<div class="text-block"> <div class="text-block">
@ -65,16 +68,16 @@
<div class="promo-img-container promo-2"> <div class="promo-img-container promo-2">
<div> <div>
<img height="222" width="323" src="assets/images/home/speed-performance.svg" alt="speed and performance"> <img height="222" width="323" src="generated/images/marketing/home/speed-performance.svg" alt="speed and performance">
</div> </div>
</div> </div>
</div> </div>
<hr> <hr>
<!-- Group 3--> <!-- Group 3 -->
<div layout="row" layout-xs="column" class="home-row"> <div layout="row" layout-xs="column" class="home-row">
<div class="promo-img-container promo-3"> <div class="promo-img-container promo-3">
<div><img src="assets/images/home/joyful-development.png" alt="IDE example"></div> <div><img src="generated/images/marketing/home/joyful-development.svg" alt="IDE example"></div>
</div> </div>
<div class="text-container"> <div class="text-container">
@ -88,9 +91,8 @@
</div> </div>
<hr> <hr>
<!-- Group 4--> <!-- Group 4 -->
<div layout="row" layout-xs="column" class="home-row"> <div layout="row" layout-xs="column" class="home-row">
<div class="text-container"> <div class="text-container">
<div class="text-block l-pad-top-2"> <div class="text-block l-pad-top-2">
<div class="text-headline">Loved by Millions</div> <div class="text-headline">Loved by Millions</div>
@ -100,25 +102,24 @@
<div class="promo-img-container promo-4"> <div class="promo-img-container promo-4">
<div> <div>
<img src="assets/images/home/loved-by-millions.png" alt="angular on the map" width="455" height="228"> <img src="generated/images/marketing/home/loved-by-millions.svg" alt="angular on the map" width="455" height="228">
</div> </div>
</div> </div>
</div> </div>
<!-- CTA CARDS --> <!-- CTA CARDS -->
<div layout="row" layout-xs="column" class="home-row"> <div layout="row" layout-xs="column" class="home-row">
<a href="guide/quickstart">
<a href="guide/quickstart"> <div class="card">
<div class="card"> <img src="generated/images/marketing/home/code-icon.svg" height="70px">
<img src="assets/images/icons/code-icon.svg" height="70px">
<div class="card-text-container"> <div class="card-text-container">
<div class="text-headline">Get Started</div> <div class="text-headline">Get Started</div>
<p>Start building your Angular application.</p> <p>Start building your Angular application.</p>
</div> </div>
</div> </div>
</a> </a>
</div> </div>
</div> <!-- end of home rows --> </div><!-- end of home rows -->
</article> </article>

View File

@ -282,6 +282,11 @@
"title": "Internationalization (i18n)", "title": "Internationalization (i18n)",
"tooltip": "Translate the app's template text into multiple languages." "tooltip": "Translate the app's template text into multiple languages."
}, },
{
"url": "guide/language-service",
"title": "Language Service",
"tooltip": "Use Angular Language Service to speed up dev time."
},
{ {
"url": "guide/security", "url": "guide/security",
"title": "Security", "title": "Security",

View File

@ -10,8 +10,8 @@
}, },
"static.ignore": [ "static.ignore": [
"\\.js\\.map$", "\\.js\\.map$",
"^/assets/images/.*/unused/", "^(?:/|\\\\)assets(?:/|\\\\)images(?:/|\\\\).*(?:/|\\\\)_unused(?:/|\\\\)",
"^/generated/(?:docs/(?!api/api-list\\.json).*|images|live-examples|zips)/" "^(?:/|\\\\)generated(?:/|\\\\)(?:docs(?:/|\\\\)(?!api(?:/|\\\\)api-list\\.json).*|images(?:/|\\\\)(?!marketing(?:/|\\\\)).*|live-examples|zips)(?:/|\\\\)"
], ],
"static.versioned": [ "static.versioned": [
"\\.[0-9a-z]{20}\\." "\\.[0-9a-z]{20}\\."

View File

@ -33,8 +33,9 @@
"docs-test": "node tools/transforms/test.js", "docs-test": "node tools/transforms/test.js",
"serve-and-sync": "concurrently --kill-others \"yarn docs-watch\" \"yarn start\"", "serve-and-sync": "concurrently --kill-others \"yarn docs-watch\" \"yarn start\"",
"~~update-webdriver": "webdriver-manager update --standalone false --gecko false", "~~update-webdriver": "webdriver-manager update --standalone false --gecko false",
"boilerplate:add": "node ./tools/examples/add-example-boilerplate add", "boilerplate:add": "node ./tools/examples/example-boilerplate add",
"boilerplate:remove": "node ./tools/examples/add-example-boilerplate remove", "boilerplate:remove": "node ./tools/examples/example-boilerplate remove",
"boilerplate:test": "node tools/examples/test.js",
"generate-plunkers": "node ./tools/plunker-builder/generatePlunkers", "generate-plunkers": "node ./tools/plunker-builder/generatePlunkers",
"generate-zips": "node ./tools/example-zipper/generateZips", "generate-zips": "node ./tools/example-zipper/generateZips",
"sw-manifest": "ngu-sw-manifest --dist dist --in ngsw-manifest.json --out dist/ngsw-manifest.json", "sw-manifest": "ngu-sw-manifest --dist dist --in ngsw-manifest.json --out dist/ngsw-manifest.json",
@ -48,17 +49,18 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^4.2.4", "@angular/animations": "^4.3.1",
"@angular/common": "^4.2.4", "@angular/cdk": "^2.0.0-beta.8",
"@angular/compiler": "^4.2.4", "@angular/common": "^4.3.1",
"@angular/core": "^4.2.4", "@angular/compiler": "^4.3.1",
"@angular/forms": "^4.2.4", "@angular/core": "^4.3.1",
"@angular/http": "^4.2.4", "@angular/forms": "^4.3.1",
"@angular/material": "^2.0.0-beta.7", "@angular/http": "^4.3.1",
"@angular/platform-browser": "^4.2.4", "@angular/material": "^2.0.0-beta.8",
"@angular/platform-browser-dynamic": "^4.2.4", "@angular/platform-browser": "^4.3.1",
"@angular/platform-server": "^4.2.4", "@angular/platform-browser-dynamic": "^4.3.1",
"@angular/router": "^4.2.4", "@angular/platform-server": "^4.3.1",
"@angular/router": "^4.3.1",
"@angular/service-worker": "^1.0.0-beta.16", "@angular/service-worker": "^1.0.0-beta.16",
"classlist.js": "^1.1.20150312", "classlist.js": "^1.1.20150312",
"core-js": "^2.4.1", "core-js": "^2.4.1",
@ -72,7 +74,7 @@
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "angular/cli-builds#webpack-next", "@angular/cli": "angular/cli-builds#webpack-next",
"@angular/compiler-cli": "^4.2.4", "@angular/compiler-cli": "^4.3.1",
"@types/jasmine": "^2.5.52", "@types/jasmine": "^2.5.52",
"@types/node": "~6.0.60", "@types/node": "~6.0.60",
"archiver": "^1.3.0", "archiver": "^1.3.0",
@ -81,7 +83,7 @@
"concurrently": "^3.4.0", "concurrently": "^3.4.0",
"cross-spawn": "^5.1.0", "cross-spawn": "^5.1.0",
"dgeni": "^0.4.7", "dgeni": "^0.4.7",
"dgeni-packages": "^0.20.0-rc.6", "dgeni-packages": "^0.20.0",
"entities": "^1.1.1", "entities": "^1.1.1",
"eslint": "^3.19.0", "eslint": "^3.19.0",
"eslint-plugin-jasmine": "^2.2.0", "eslint-plugin-jasmine": "^2.2.0",

View File

@ -76,8 +76,8 @@ export class AppComponent implements OnInit {
get homeImageUrl() { get homeImageUrl() {
return this.isSideBySide ? return this.isSideBySide ?
'assets/images/logos/standard/logo-nav@2x.png' : 'assets/images/logos/angular/logo-nav@2x.png' :
'assets/images/logos/standard/shield-large.svg'; 'assets/images/logos/angular/shield-large.svg';
} }
get isOpened() { return this.isSideBySide && this.isSideNavDoc; } get isOpened() { return this.isSideBySide && this.isSideNavDoc; }
get mode() { return this.isSideBySide ? 'side' : 'over'; } get mode() { return this.isSideBySide ? 'side' : 'over'; }

View File

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 519 B

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 422 B

After

Width:  |  Height:  |  Size: 422 B

View File

Before

Width:  |  Height:  |  Size: 783 B

After

Width:  |  Height:  |  Size: 783 B

View File

Before

Width:  |  Height:  |  Size: 452 B

After

Width:  |  Height:  |  Size: 452 B

View File

Before

Width:  |  Height:  |  Size: 864 B

After

Width:  |  Height:  |  Size: 864 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 782 B

After

Width:  |  Height:  |  Size: 782 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,148 +0,0 @@
const fs = fsExtra = require('fs-extra');
const globby = require('globby');
const path = require('path');
const Q = require("q");
const shelljs = require('shelljs');
const EXAMPLES_PATH = path.join(__dirname, '/../../content/examples');
const SHARED_PATH = path.join(__dirname, '/shared');
const BOILERPLATE_PATH = path.join(SHARED_PATH, 'boilerplate');
const EXAMPLES_TESTING_PATH = path.join(EXAMPLES_PATH, 'testing');
const files = {
exampleBoilerplate: [
'src/styles.css',
'src/systemjs-angular-loader.js',
'src/systemjs.config.js',
'src/tsconfig.json',
'bs-config.json',
'bs-config.e2e.json',
'package.json',
'tslint.json'
],
exampleUnitTestingBoilerplate: [
'src/browser-test-shim.js',
'karma-test-shim.js',
'karma.conf.js'
],
exampleConfigFilename: 'example-config.json'
};
// requires admin access because it adds symlinks
function add() {
const realPath = path.join(SHARED_PATH, '/node_modules');
const nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH);
// we install the examples modules first
installNodeModules();
nodeModulesPaths.map((linkPath) => {
fs.ensureSymlinkSync(realPath, linkPath);
});
return copyExampleBoilerplate();
}
function copyExampleBoilerplate() {
console.log('Copying example boilerplate files');
const examplePaths = getExamplePaths(EXAMPLES_PATH);
// Make boilerplate files read-only to avoid that they be edited by mistake.
const destFileMode = '444';
let foo = copyFiles(files.exampleBoilerplate, BOILERPLATE_PATH, examplePaths, destFileMode)
// copy the unit test boilerplate
.then(() => {
const unittestPaths = getUnitTestingPaths(EXAMPLES_PATH);
return copyFiles(files.exampleUnitTestingBoilerplate, EXAMPLES_TESTING_PATH, unittestPaths, destFileMode);
})
.catch((err) => {
console.error(err);
throw err;
});
}
// Copies fileNames into destPaths, setting the mode of the
// files at the destination as optional_destFileMode if given.
// returns a promise
function copyFiles(fileNames, originPath, destPaths, optional_destFileMode) {
const copy = Q.denodeify(fsExtra.copy);
const chmod = Q.denodeify(fsExtra.chmod);
let copyPromises = [];
destPaths.map((destPath) => {
fileNames.forEach((fileName) => {
const originName = path.join(originPath, fileName);
const destName = path.join(destPath, fileName);
let p = copy(originName, destName, { clobber: true});
if(optional_destFileMode !== undefined) {
p = p.then(() => {
return chmod(destName, optional_destFileMode);
});
}
copyPromises.push(p);
});
});
return Q.all(copyPromises);
}
function getExamplePaths(basePath, includeBase) {
// includeBase defaults to false
return getPaths(basePath, files.exampleConfigFilename, includeBase);
}
function getFilenames(basePath, filename, includeBase) {
let includePatterns = [path.join(basePath, "**/" + filename)];
if (!includeBase) {
// ignore (skip) the top level version.
includePatterns.push("!" + path.join(basePath, "/" + filename));
}
// ignore (skip) the files in BOILERPLATE_PATH.
includePatterns.push("!" + path.join(BOILERPLATE_PATH, "/" + filename));
const nmPattern = path.join(basePath, "**/node_modules/**");
return globby.sync(includePatterns, {ignore: [nmPattern]});
}
function getNodeModulesPaths(basePath) {
return getExamplePaths(basePath).map((examplePath) => {
return path.join(examplePath, "/node_modules");
});
}
function getPaths(basePath, filename, includeBase) {
const filenames = getFilenames(basePath, filename, includeBase);
return filenames.map((fileName) => {
return path.dirname(fileName);
});
}
function getUnitTestingPaths(basePath) {
const examples = getPaths(basePath, files.exampleConfigFilename, true);
return examples.filter((example) => {
const exampleConfig = fs.readJsonSync(`${example}/${files.exampleConfigFilename}`, {throws: false});
return exampleConfig && !!exampleConfig.unittesting;
});
}
function installNodeModules() {
shelljs.exec('yarn', {cwd: SHARED_PATH});
}
function remove() {
shelljs.exec('git clean -xdf', {cwd: EXAMPLES_PATH});
}
module.exports = {
add: add,
remove: remove
};
// being executed from shell script
switch (process.argv[2]) {
case 'add':
add();
break;
case 'remove':
remove();
break;
default:
console.error(`There is no function with the name: ${process.argv}`);
}

View File

@ -0,0 +1,140 @@
const fs = require('fs-extra');
const glob = require('glob');
const path = require('canonical-path');
const shelljs = require('shelljs');
const yargs = require('yargs');
const SHARED_PATH = path.resolve(__dirname, 'shared');
const SHARED_NODE_MODULES_PATH = path.resolve(SHARED_PATH, 'node_modules');
const BOILERPLATE_BASE_PATH = path.resolve(SHARED_PATH, 'boilerplate');
const EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples');
const TESTING_BASE_PATH = path.resolve(EXAMPLES_BASE_PATH, 'testing');
const BOILERPLATE_SRC_PATHS = [
'src/styles.css',
'src/systemjs-angular-loader.js',
'src/systemjs.config.js',
'src/tsconfig.json',
'bs-config.json',
'bs-config.e2e.json',
'package.json',
'tslint.json'
];
const BOILERPLATE_TEST_PATHS = [
'src/browser-test-shim.js',
'karma-test-shim.js',
'karma.conf.js'
];
const ANGULAR_DIST_PATH = path.resolve(__dirname, '../../../dist');
const ANGULAR_PACKAGES_PATH = path.resolve(ANGULAR_DIST_PATH, 'packages-dist');
const ANGULAR_PACKAGES = [
'animations',
'common',
'compiler',
'compiler-cli',
'core',
'forms',
'http',
'platform-browser',
'platform-browser-dynamic',
'platform-server',
'router',
'upgrade',
];
const ANGULAR_TOOLS_PACKAGES_PATH = path.resolve(ANGULAR_DIST_PATH, 'tools', '@angular');
const ANGULAR_TOOLS_PACKAGES = [
'tsc-wrapped'
];
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
class ExampleBoilerPlate {
/**
* Add boilerplate files to all the examples
*
* @param useLocal if true then overwrite the Angular library files with locally built ones
*/
add(useLocal) {
// first install the shared node_modules
this.installNodeModules(SHARED_PATH);
// Replace the Angular packages with those from the dist folder, if necessary
if (useLocal) {
ANGULAR_PACKAGES.forEach(packageName => this.overridePackage(ANGULAR_PACKAGES_PATH, packageName));
ANGULAR_TOOLS_PACKAGES.forEach(packageName => this.overridePackage(ANGULAR_TOOLS_PACKAGES_PATH, packageName));
}
// Get all the examples folders, indicated by those that contain a `example-config.json` file
const exampleFolders = this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
exampleFolders.forEach(exampleFolder => {
// Link the node modules - requires admin access (on Windows) because it adds symlinks
const destinationNodeModules = path.resolve(exampleFolder, 'node_modules');
fs.ensureSymlinkSync(SHARED_NODE_MODULES_PATH, destinationNodeModules);
// Copy the boilerplate source files
BOILERPLATE_SRC_PATHS.forEach(filePath => this.copyFile(BOILERPLATE_BASE_PATH, exampleFolder, filePath));
// Copy the boilerplate test files (if the example is configured to do unit testing)
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
if (exampleConfig.unittesting) {
BOILERPLATE_TEST_PATHS.forEach(filePath => this.copyFile(TESTING_BASE_PATH, exampleFolder, filePath));
}
});
}
/**
* Remove all the boilerplate files from all the examples
*/
remove() {
shelljs.exec('git clean -xdfq', {cwd: EXAMPLES_BASE_PATH});
}
main() {
yargs
.usage('$0 <cmd> [args]')
.command('add [--local]', 'add the boilerplate to each example',
{ local: { describe: 'Use the locally built Angular libraries, rather than ones from npm.' } },
argv => this.add(argv.local))
.command('remove', 'remove the boilerplate from each example', () => this.remove())
.demandCommand(1, 'Please supply a command from the list above')
.argv;
}
installNodeModules(basePath) {
shelljs.exec('yarn', {cwd: basePath});
}
overridePackage(basePath, packageName) {
const sourceFolder = path.resolve(basePath, packageName);
const destinationFolder = path.resolve(SHARED_NODE_MODULES_PATH, '@angular', packageName);
shelljs.rm('-rf', destinationFolder);
fs.ensureSymlinkSync(sourceFolder, destinationFolder);
}
getFoldersContaining(basePath, filename, ignore) {
const pattern = path.resolve(basePath, '**', filename);
const ignorePattern = path.resolve(basePath, '**', ignore, '**');
return glob.sync(pattern, { ignore: [ignorePattern] }).map(file => path.dirname(file));
}
copyFile(sourceFolder, destinationFolder, filePath) {
const sourcePath = path.resolve(sourceFolder, filePath);
const destinationPath = path.resolve(destinationFolder, filePath);
fs.copySync(sourcePath, destinationPath, { overwrite: true });
fs.chmodSync(destinationPath, 444);
}
loadJsonFile(filePath) {
return fs.readJsonSync(filePath, {throws: false}) || {};
}
}
module.exports = new ExampleBoilerPlate();
// If this file was run directly then run the main function,
if (require.main === module) {
module.exports.main();
}

View File

@ -0,0 +1,143 @@
const exampleBoilerPlate = require('./example-boilerplate');
const shelljs = require('shelljs');
const fs = require('fs-extra');
const glob = require('glob');
const path = require('canonical-path');
describe('example-boilerplate tool', () => {
describe('add', () => {
const numberOfBoilerPlateFiles = 8;
const numberOfBoilerPlateTestFiles = 3;
const exampleFolders = ['a/b', 'c/d'];
beforeEach(() => {
spyOn(exampleBoilerPlate, 'installNodeModules');
spyOn(exampleBoilerPlate, 'overridePackage');
spyOn(exampleBoilerPlate, 'getFoldersContaining').and.returnValue(exampleFolders);
spyOn(fs, 'ensureSymlinkSync');
spyOn(exampleBoilerPlate, 'copyFile');
spyOn(exampleBoilerPlate, 'loadJsonFile').and.returnValue({});
});
it('should install the node modules', () => {
exampleBoilerPlate.add();
expect(exampleBoilerPlate.installNodeModules).toHaveBeenCalledWith(path.resolve(__dirname, 'shared'));
});
it('should override the Angular node_modules with the locally built Angular packages if `useLocal` is true', () => {
const numberOfAngularPackages = 12;
const numberOfAngularToolsPackages = 1;
exampleBoilerPlate.add(true);
expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledTimes(numberOfAngularPackages + numberOfAngularToolsPackages);
// for example
expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledWith(path.resolve(__dirname, '../../../dist/packages-dist'), 'core');
expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledWith(path.resolve(__dirname, '../../../dist/tools/@angular'), 'tsc-wrapped');
});
it('should process all the example folders', () => {
exampleBoilerPlate.add();
expect(exampleBoilerPlate.getFoldersContaining).toHaveBeenCalledWith(path.resolve(__dirname, '../../content/examples'), 'example-config.json', 'node_modules');
});
it('should symlink the node_modules', () => {
exampleBoilerPlate.add();
expect(fs.ensureSymlinkSync).toHaveBeenCalledTimes(exampleFolders.length);
expect(fs.ensureSymlinkSync).toHaveBeenCalledWith(path.resolve(__dirname, 'shared/node_modules'), path.resolve('a/b/node_modules'));
expect(fs.ensureSymlinkSync).toHaveBeenCalledWith(path.resolve(__dirname, 'shared/node_modules'), path.resolve('c/d/node_modules'));
});
it('should copy all the source boilerplate files', () => {
exampleBoilerPlate.add();
expect(exampleBoilerPlate.copyFile).toHaveBeenCalledTimes(numberOfBoilerPlateFiles * exampleFolders.length);
// for example
expect(exampleBoilerPlate.copyFile).toHaveBeenCalledWith(path.resolve(__dirname, 'shared/boilerplate'), 'a/b', 'package.json');
});
it('should try to load the example config file', () => {
exampleBoilerPlate.add();
expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledTimes(exampleFolders.length);
expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledWith(path.resolve('a/b/example-config.json'));
expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledWith(path.resolve('c/d/example-config.json'));
});
it('should copy all the test boilerplate files if unit testing is configured', () => {
// configure unit testing for example a/b and not c/d
exampleBoilerPlate.loadJsonFile.and.callFake(filePath => filePath.indexOf('a/b') !== -1 ? { unittesting: true } : {});
exampleBoilerPlate.add();
expect(exampleBoilerPlate.copyFile).toHaveBeenCalledTimes((numberOfBoilerPlateFiles * 2) + numberOfBoilerPlateTestFiles);
// for example
expect(exampleBoilerPlate.copyFile).toHaveBeenCalledWith(path.resolve(__dirname, '../../content/examples/testing'), 'a/b', 'karma.conf.js');
expect(exampleBoilerPlate.copyFile).not.toHaveBeenCalledWith(path.resolve(__dirname, '../../content/examples/testing'), 'c/d', 'karma.conf.js');
});
});
describe('remove', () => {
it('should run `git clean`', () => {
spyOn(shelljs, 'exec');
exampleBoilerPlate.remove();
expect(shelljs.exec).toHaveBeenCalledWith('git clean -xdfq', {cwd: path.resolve(__dirname, '../../content/examples') });
});
});
describe('installNodeModules', () => {
it('should run `yarn` in the base path', () => {
spyOn(shelljs, 'exec');
exampleBoilerPlate.installNodeModules('some/base/path');
expect(shelljs.exec).toHaveBeenCalledWith('yarn', { cwd: 'some/base/path' });
});
});
describe('overridePackage', () => {
beforeEach(() => {
spyOn(shelljs, 'rm');
spyOn(fs, 'ensureSymlinkSync');
});
it('should remove the original package from the shared node_modules folder', () => {
exampleBoilerPlate.overridePackage('base/path', 'somePackage');
expect(shelljs.rm).toHaveBeenCalledWith('-rf', path.resolve(__dirname, 'shared/node_modules/@angular/somePackage'));
});
it('should symlink the source folder to the shared node_modules folder', () => {
exampleBoilerPlate.overridePackage('base/path', 'somePackage');
expect(fs.ensureSymlinkSync).toHaveBeenCalledWith(path.resolve('base/path/somePackage'), path.resolve(__dirname, 'shared/node_modules/@angular/somePackage'));
});
});
describe('getFoldersContaining', () => {
it('should use glob.sync', () => {
spyOn(glob, 'sync').and.returnValue(['a/b/config.json', 'c/d/config.json']);
const result = exampleBoilerPlate.getFoldersContaining('base/path', 'config.json', 'node_modules');
expect(glob.sync).toHaveBeenCalledWith(path.resolve('base/path/**/config.json'), { ignore: [path.resolve('base/path/**/node_modules/**')] });
expect(result).toEqual(['a/b', 'c/d']);
});
});
describe('copyFile', () => {
it('should use copySync and chmodSync', () => {
spyOn(fs, 'copySync');
spyOn(fs, 'chmodSync');
exampleBoilerPlate.copyFile('source/folder', 'destination/folder', 'some/file/path');
expect(fs.copySync).toHaveBeenCalledWith(
path.resolve('source/folder/some/file/path'),
path.resolve('destination/folder/some/file/path'),
{ overwrite: true });
expect(fs.chmodSync).toHaveBeenCalledWith(path.resolve('destination/folder/some/file/path'), 444);
});
});
describe('loadJsonFile', () => {
it('should use fs.readJsonSync', () => {
spyOn(fs, 'readJsonSync').and.returnValue({ some: 'value' });
const result = exampleBoilerPlate.loadJsonFile('some/file');
expect(fs.readJsonSync).toHaveBeenCalledWith('some/file', {throws: false});
expect(result).toEqual({ some: 'value' });
});
it('should return an empty object if readJsonSync fails', () => {
spyOn(fs, 'readJsonSync').and.returnValue(null);
const result = exampleBoilerPlate.loadJsonFile('some/file');
expect(result).toEqual({});
});
});
});

View File

@ -22,15 +22,24 @@ const IGNORED_EXAMPLES = [
* --filter to filter/select _example app subdir names * --filter to filter/select _example app subdir names
* e.g. --filter=foo // all example apps with 'foo' in their folder names. * e.g. --filter=foo // all example apps with 'foo' in their folder names.
* *
* --setup run yarn install, copy boilerplate and update webdriver * --setup run yarn install, copy boilerplate and update webdriver
* e.g. --setup * e.g. --setup
*
* --local to use the locally built Angular packages, rather than versions from npm
* Must be used in conjunction with --setup as this is when the packages are copied.
* e.g. --setup --local
*
* --shard to shard the specs into groups to allow you to run them in parallel
* e.g. --shard=0/2 // the even specs: 0, 2, 4, etc
* e.g. --shard=1/2 // the odd specs: 1, 3, 5, etc
* e.g. --shard=1/3 // the second of every three specs: 1, 4, 7, etc
*/ */
function runE2e() { function runE2e() {
let promise = Promise.resolve(); let promise = Promise.resolve();
if (argv.setup) { if (argv.setup) {
// Run setup. // Run setup.
console.log('runE2e: copy boilerplate'); console.log('runE2e: copy boilerplate');
const spawnInfo = spawnExt('yarn', ['boilerplate:add'], { cwd: AIO_PATH }); const spawnInfo = spawnExt('yarn', ['boilerplate:add', argv.local ? '-- --local': ''], { cwd: AIO_PATH });
promise = spawnInfo.promise promise = spawnInfo.promise
.then(() => { .then(() => {
console.log('runE2e: update webdriver'); console.log('runE2e: update webdriver');
@ -41,7 +50,7 @@ function runE2e() {
const outputFile = path.join(AIO_PATH, './protractor-results.txt'); const outputFile = path.join(AIO_PATH, './protractor-results.txt');
return promise return promise
.then(() => findAndRunE2eTests(argv.filter, outputFile)) .then(() => findAndRunE2eTests(argv.filter, outputFile, argv.shard))
.then((status) => { .then((status) => {
reportStatus(status, outputFile); reportStatus(status, outputFile);
if (status.failed.length > 0) { if (status.failed.length > 0) {
@ -55,7 +64,12 @@ function runE2e() {
// Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps // Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps
// that they should run under. Then run each app/spec collection sequentially. // that they should run under. Then run each app/spec collection sequentially.
function findAndRunE2eTests(filter, outputFile) { function findAndRunE2eTests(filter, outputFile, shard) {
const shardParts = shard ? shard.split('/') : [0,1];
const shardModulo = parseInt(shardParts[0], 10);
const shardDivider = parseInt(shardParts[1], 10);
// create an output file with header. // create an output file with header.
const startTime = new Date().getTime(); const startTime = new Date().getTime();
let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`; let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`;
@ -65,7 +79,9 @@ function findAndRunE2eTests(filter, outputFile) {
// Run the tests sequentially. // Run the tests sequentially.
const status = { passed: [], failed: [] }; const status = { passed: [], failed: [] };
return getE2eSpecPaths(EXAMPLES_PATH, filter) return getE2eSpecPaths(EXAMPLES_PATH, filter)
.then(e2eSpecPaths => e2eSpecPaths.reduce((promise, specPath) => { .then(e2eSpecPaths => e2eSpecPaths
.filter((paths, index) => index % shardDivider === shardModulo)
.reduce((promise, specPath) => {
return promise.then(() => { return promise.then(() => {
const examplePath = path.dirname(specPath); const examplePath = path.dirname(specPath);
return runE2eTests(examplePath, outputFile).then((ok) => { return runE2eTests(examplePath, outputFile).then((ok) => {

View File

@ -0,0 +1,17 @@
/*
* Use this script to run the tests for the doc generation
* We cannot use the Jasmine CLI directly because it doesn't seem to
* understand the glob and only runs one spec file.
*
* Equally we cannot use a jasmine.json config file because it doesn't
* allow us to set the projectBaseDir, which means that you have to run
* jasmine CLI from this directory.
*
* Using a file like this gives us full control and keeps the package.json
* file clean and simple.
*/
const Jasmine = require('jasmine');
const jasmine = new Jasmine({ projectBaseDir: __dirname });
jasmine.loadConfig({ spec_files: ['*.spec.js'] });
jasmine.execute();

View File

@ -34,5 +34,5 @@ function getText(h1) {
(node.properties.ariaHidden === 'true' || node.properties['aria-hidden'] === 'true') (node.properties.ariaHidden === 'true' || node.properties['aria-hidden'] === 'true')
)); ));
return toString(cleaned); return cleaned ? toString(cleaned) : '';
} }

Some files were not shown because too many files have changed in this diff Show More