Compare commits

..

292 Commits

Author SHA1 Message Date
5298b2bda3 docs: add changelog for 5.2.9 2018-03-14 14:59:27 -07:00
25ae886cad release: cut the 5.2.9 release 2018-03-14 14:56:14 -07:00
fc6dfc2e08 fix(platform-server): add styles to elements correctly (#22527)
* Partially reverts #22263 due to lack of total spec compliance
  on the server
* Maintains the camel-case styles fix

PR Close #22527
2018-03-14 14:12:32 -07:00
c0670ef52d docs(aio): add ng-japan 2018 to events (#22750)
ng-japan 2018 will be held at June 16 in Tokyo, Japan! 

https://ngjapan.org/en.html
PR Close #22750
2018-03-14 10:59:57 -07:00
fe96cafd03 fix(aio): constrain error logging to improve reporting (#22713)
The `Logger.error()` method now only accepts a single `Error` parameter
and passes this through to the error handler.
This allows the error handler to serialize the error more accurately.

The various places that use `Logger.error()` have been updated.

See #21943#issuecomment-370230047

PR Close #22713
2018-03-14 10:52:12 -07:00
ad674dad37 docs: testing - highlight dispatchEvent (#22726)
PR Close #22726
2018-03-14 10:21:42 -07:00
86517f2ad5 fix(router): correct over-encoding of URL fragment (#22687)
Relates to: #10280 #22337

PR Close #22687
2018-03-11 22:15:02 -07:00
6d9a4f8aea docs: refactor revert() and call to lifecylce hook, edit doc to changes (#22094)
PR Close #22094
2018-03-08 10:58:43 -08:00
a1efc27ff2 ci: double our cores on CircleCI (#22641)
This should cut our build time in ~half, assuming it's widely parallel.
See
https://circleci.com/docs/2.0/configuration-reference/#resource_class

Also enable bazel repository caching, and store the external
repositories in the CircleCI cache for later builds.

PR Close #22641
2018-03-07 21:00:04 -08:00
311232004c docs: add HeroService to code tabs and fix headers (#22373)
PR Close #22373
2018-03-07 18:20:54 -08:00
2a236b4066 docs: add changelog for 5.2.8 2018-03-07 14:45:07 -08:00
bdee824292 release: cut the 5.2.8 release 2018-03-07 14:44:18 -08:00
4aeb04dcb0 docs: update RELEASE_SCHEDULE.md by pushing out v6 rc by one week
We are pushing RC and Final out by one week because of RxJS v6 complications that are blocking the release. No further delays are currently expected.
2018-03-07 10:51:30 -08:00
5876fb0125 docs(aio): update deprecated Http reference to HttpClientModule, remove Http reference because another context is used (#21984)
docs(aio): change HttpClientModule reference to HttpClient

docs(aio): capitalize Http to HTTP

docs(aio): fix typo mistake in 'universal' guide

docs(aio): gets rid of the parentheses and the "e.g." in 'universal' guide

PR Close #21984
2018-03-06 15:03:54 -08:00
5b7b208637 docs: fix cli-quickstart doc and specs (#22338)
* tests were broken
* incorrect instructions.
* didn't match current CLI template for new project

PR Close #22338
2018-03-06 09:41:54 -08:00
789a47ec44 fix(router): fix URL serialization so special characters are only encoded where needed (#22337)
This change brings Angular largely in line with how AngularJS previously serialized URLs. This is based on RFC 3986 and resolves issues such as the above #10280 where URLs could be parsed, re-serialized, then parsed again producing a different result on the second parsing.

Adjustments to be aware of in this commit:

* URI fragments will now serialize the same as query strings
* In the URI path or segments (portion prior to query string and/or fragment), the plus sign (`+`) and ampersand (`&`) will appear decoded
* In the URL path or segments, parentheses values (`(` and `)`) will now appear percent encoded as `%28` and `%29` respectively
* In the URL path or segments, semicolons will be encoded in their percent encoding `%3B`

NOTE: Parentheses and semicolons denoting auxillary routes or matrix params will still appear in their decoded form -- only parentheses and semicolons used as values in a segment or key/value pair for matrix params will be encoded.

While these changes are not considered breaking because applications should be decoding URLs and key/value pairs, it is possible that some unit tests will break if comparing hard-coded URLs in tests since that hard coded string will represent the old encoding. Therefore we are releasing this fix in the upcoming Angular v6 rather than adding it to a patch for v5.

Fixes: #10280

PR Close #22337
2018-03-06 06:58:08 -08:00
984a13e45b docs(aio): fix table header (#22553)
PR Close #22553
2018-03-05 10:13:17 -08:00
a3f7e30153 build: update to latest bazel rules (#22558)
PR Close #22558
2018-03-02 13:28:01 -08:00
ff7e2e3f1e ci: speed up lint job on CircleCI (#22526)
When I enabled bazel remote caching, I also switched to running
buildifier and skylint from the package.json script, which builds them
from head. With remote caching, we do get cache hits for these, but
looking up the action inputs actually takes quite a bit of time since we
have to first fetch the remote repository, then do loading and
analysis, then read the inputs to determine the cache key.

It's more important to keep the lint job fast, so I'm reverting that
part of the change for now. We can experiment with building them from
head in a less critical repo.

PR Close #22526
2018-03-01 09:12:59 -08:00
fe0d53f3a9 build: Add support for bazelOptions.maxCacheSizeMb in ngc-wrapped. (#22511)
PR Close #22511
2018-03-01 08:41:11 -08:00
27962f8949 build(aio): improve accuracy of code auto-linking (#22494)
The new version of `dgeni-packages/typescript` no longer strips
out "namespaces" from types, which was part of the problem of
not autolinking correctly to `HttpEventType.Response`.

Another part of the problem was that we did not include `.`
characters when matching potential code blocks for auto-linking,
which precluded properties of enums from being linked.

Finally, members we not being given a `path` property, which is
needed to effectively autolink to them. This is now set in
the `simplifyMemberAnchors` processor.

Closes #21375

PR Close #22494
2018-03-01 08:12:25 -08:00
855e3a65db build(aio): move link disambiguation from getLinkInfo to getDocFromAlias (#22494)
The disambiguation needs to be done earlier so that the auto-link-code
post-processor can benefit from it.

PR Close #22494
2018-03-01 08:11:19 -08:00
f8e70fb0c6 build(aio): initialise exampleMap correctly (#22502)
The `exampleMap` needs to hold an hash object for each
of the `collectExamples.exampleFolders` paths.

Previously these hash objects were only created if there
was actually an example file the hash's respective
example folder.  This could cause crashes during
`yarn docs-watch` (and so also `yarn sync-and-serve`)
if no examples were read in for a particular run of
the doc-gen.

PR Close #22502
2018-03-01 08:10:15 -08:00
697d31a38c docs: add changelog for 5.2.7 2018-02-28 15:11:02 -08:00
1593bff1b0 release: cut the 5.2.7 release 2018-02-28 15:11:02 -08:00
0ec11e3223 docs: fix dynamic component loader example (#22181)
closes #21903

PR Close #22181
2018-02-28 10:46:38 -08:00
089769d5c3 build: update ts-api-guardian version (#22402)
PR Close #22402
2018-02-28 09:29:30 -08:00
9137650dba build: update api golden files (#22402)
`ts-api-guardion` has been updated to accept new TypeScript syntax

PR Close #22402
2018-02-28 09:29:30 -08:00
eccce1772d docs: fix community tab in GitHub by copying CoC 2018-02-27 19:04:00 -08:00
4aef9de37e fix(upgrade): correctly destroy nested downgraded component (#22400)
Previously, when a downgraded component was destroyed in a way that did
not trigger the `$destroy` event on the element (e.g. when a parent
element was removed from the DOM by Angular, not AngularJS), the
`ComponentRef` was not destroyed and unregistered.
This commit fixes it by listening for the `$destroy` event on both the
element and the scope.

Fixes #22392

PR Close #22400
2018-02-27 18:41:03 -08:00
f2fa7a289f docs(aio): add Observable and Rx docs (#21423)
PR Close #21423
2018-02-27 11:24:31 -08:00
e1fbe20d98 style(aio): updated padding-right for the .alert class in _heading-anchors.scss (#22431)
The h3 element is overflowing over its surrounding div element. Modified padding-right to align consistently with the remainder of div contents.

fixes: #22407

PR Close #22431
2018-02-26 17:52:30 -08:00
38bd8d49a5 style(aio): added padding-left to h3 in _subsection.scss (#22431)
The h3 element is overflowing over its surrounding div element. Modified padding-left to align consistently with the remainder of div contents.

fixes: #22407

PR Close #22431
2018-02-26 17:52:30 -08:00
d033106adb docs: update i18n guide for projects that don't use the cli (#21767)
PR Close #21767
2018-02-26 17:51:58 -08:00
de02a7a5de fix(platform-server): generate correct stylings for camel case names (#22263)
* Add correct mapping from camel case to kebab case for CSS style
names
* Remove internal CSS methods in favor of native Domino APIs

Fixes #19235

PR Close #22263
2018-02-26 17:46:21 -08:00
c30a942329 docs: testing guide for CLI (#20697)
- updates tests
- heavy prose revisions
- uses HttpClient (with angular-in-memory-web-api)
- test HeroService using `HttpClientTestingModule`
- scrub away most By.CSS
- fake async observable with `asyncData()`
- extensive Twain work
- different take on retryWhen
- remove app barrels (& systemjs.extras) which troubled plunker/systemjs
- add dummy export const to hero.ts (plunkr/systemjs fails w/o it)
- shrink and re-organize TOC
- add marble testing package and tests
- demonstrate the "no beforeEach()" test coding style
- add section on Http service testing
- prepare for stackblitz
- confirm works in plunker except excluded marble test
- add tests for avoidFile class feature of CodeExampleComponent

PR Close #20697
2018-02-26 13:40:24 -08:00
2a38d93171 docs(aio): fix doc typo referring to httpOptions (#22456)
The variable name mention should match the actual tutorial code.

PR Close #22456
2018-02-26 13:32:44 -08:00
a9a0e27e94 fix(upgrade): fix empty transclusion content with AngularJS@>=1.5.8 (#22167)
The function provided by `ngUpgrade` as `parentBoundTranscludeFn` when
upgrading a component with transclusion, will break in AngularJS v1.5.8+
if no transclusion content is provided. The reason is that AngularJS
will try to destroy the transclusion scope (which would not be needed
any more). But since the transcluded content comes from Angular, not
AngularJS, there is no transclusion scope to destroy.
This commit fixes it by providing a dummy scope object with a no-op
`$destroy()` method.

Fixes #22175

PR Close #22167
2018-02-25 10:06:14 -08:00
66383901a6 fix(upgrade): correctly handle = bindings in @angular/upgrade (#22167)
Previously, having a `=` binding on an upgraded components would result
in setting the corresponding property to an EventEmitter function. This
should only happen for `&` bindings.
This commit rstrores the correct behavior.

Note:
The issue was only present in the dynamic version of `ngUpgrade`. The
static version worked as expected.
The error did not show up in tests, because in AngularJS v1.5.x a
function would be serialized to an empty string in interpolations, thus
making them indistinguishable from uninitialized properties (in the
view). The serialization behavior changed in AngularJS v1.6.x, making
the errors visible.

PR Close #22167
2018-02-25 10:06:14 -08:00
1eb54132e4 test(upgrade): run tests against multiple AngularJS versions (#22167)
Fixes #19332

PR Close #22167
2018-02-25 10:06:14 -08:00
6c9c173e1e refactor(upgrade): use correct paths for imports (#22167)
`packages/upgrade/static/src` is anymlink to `packages/upgrade/src`.
Still, using the correct paths (e.g. using
`@angular/upgrade/static/src/...` for `@angula/upgrade/static` specs
ensures that the module loader (e.g. SystemJS) can map the imports to
the same instances.

PR Close #22167
2018-02-25 10:06:14 -08:00
1e08a945e1 test(platform-browser): remove stray debugger statement (#22167)
PR Close #22167
2018-02-25 10:06:14 -08:00
4a08745d3e build: add support for the "merge-assistance" label in merge-pr (#22414)
fixes #22256

PR Close #22414
2018-02-23 12:58:30 -08:00
cf91906d8f docs(aio): Essential JS 2 url updated (#19739)
PR Close #19739
2018-02-23 11:18:12 -08:00
0723c04a01 docs(aio): Essential JS 2 UI Components. (#19739)
PR Close #19739
2018-02-23 11:18:12 -08:00
2b7188906b build: fix 5.2.x merge (#22408)
PR Close #22408
2018-02-23 10:21:33 -08:00
17c1577de9 ci: don't use bazel git_repository rule (#22406)
It's currently broken on CircleCI because of a TLS change made by GitHub.
This is okay as a permanent change, we don't really want bazel to fetch a full git history.

Fixes #22405

PR Close #22406
2018-02-23 09:41:11 -08:00
150bac310f docs: fix deployment sample path (#22048)
PR Close #22048
2018-02-22 13:40:57 -08:00
8f0a0641e2 fix(router): don't mutate route configs (#22358)
Fixes #22203

PR Close #22358
2018-02-22 13:35:38 -08:00
17762390c9 build: disable bazel-out symlink (#22375)
It causes headaches on MacOS High Sierra, see https://github.com/bazelbuild/bazel/issues/4603

PR Close #22375
2018-02-22 13:33:12 -08:00
da1b4d5ea7 docs: fix ngmodules-jsmodules pre-req (#22316)
closes #22157

PR Close #22316
2018-02-22 11:20:48 -08:00
aa100f69f2 docs: edit styleguide recommendation on components as elements (#22074)
Change recommendation on using attributes for components since there are use cases including the use of <button mat-button> in MD

Closes #19401.

PR Close #22074
2018-02-22 11:20:21 -08:00
9cca5a8c9c build: allow passing node options to ngc. (#22245)
PR Close #22245
2018-02-22 10:23:54 -08:00
7c3b95b4ab docs: add changelog for 5.2.6 2018-02-21 16:45:10 -08:00
e4e8a68c06 release: cut the 5.2.6 release 2018-02-21 16:45:09 -08:00
6460ac0add Revert "feat(platform-browser): fix #19604, can config hammerOptions (#21979)"
This reverts commit fdbfd21bcd.
2018-02-21 16:45:09 -08:00
ee91de9d5a feat(core): support metadata reflection for native class types (#22356)
closes #21731

PR Close #22356
2018-02-21 16:09:27 -08:00
5ec38f2f47 fix(core): properly handle function without prototype in reflector (#22284)
closes #19978

PR Close #22284
2018-02-21 14:52:05 -08:00
612cfeca14 docs(aio): updates directive event hooks real capabilities (#16654)
Minor documentation update to include event hooks that were assumed to only work on components.

Closes angular/angular#10221

PR Close #16654
2018-02-21 14:51:05 -08:00
dfdade25ea docs(aio): Wrong code example. Form status field was added later in the guide. (#21275)
PR Close #21275
2018-02-21 11:06:48 -08:00
c2f78e1ca3 docs(http): fix a typo in code comment (#22327)
PR Close #22327
2018-02-21 11:06:06 -08:00
484802cd2a build: make git revert messages valid (#22339)
`git revert` default message is "Revert <original message>" (no semi-colon)

PR Close #22339
2018-02-21 11:05:35 -08:00
ee535777bb docs: add ngStyle to cheat sheet (#22070)
PR Close #22070
2018-02-20 16:08:16 -08:00
94756eb4bd docs(aio): fix incorrect quote mark usage (#22335)
PR Close #22335
2018-02-20 15:42:55 -08:00
23b0707707 docs(aio): fix the css of the heroes component's buttons (#22333)
Fixes #22222

PR Close #22333
2018-02-20 15:41:57 -08:00
a2cb0109f1 docs(aio): Fix name of component (#22332)
PR Close #22332
2018-02-20 15:41:35 -08:00
d20a08bc48 docs(aio): update installed mobile tool list (#22331)
PR Close #22331
2018-02-20 15:41:15 -08:00
5bdb3acace build: update tsickle dep from compiler-cli (#22295)
PR Close #22295
2018-02-20 15:40:45 -08:00
c5418c7abe fix(compiler-cli): add missing entry point to package, update tsickle (#22295)
PR Close #22295
2018-02-20 15:40:45 -08:00
09b4612bdd docs(aio): add Nx and Angular Enterprise Playbook to resources (#22321)
PR Close #22321
2018-02-20 10:09:34 -08:00
a346d28df6 test(language-service): fix minor typos (#21372)
PR Close #21372
2018-02-20 10:08:55 -08:00
bf07837d5d test(common): fix ngIf tests
The failing test was ported for the master branch which ignores whitespaces
2018-02-18 20:12:47 -08:00
cdfedc1e49 fix(common): fix merge error in ng_if.ts 2018-02-18 19:51:15 -08:00
af6a0563de fix(common): then and else template might be set to null (#22298)
PR Close #22298
2018-02-18 19:28:36 -08:00
c726d1d6d3 docs(aio): add angular-buch to resources (#22163)
adds a link to the website of our book. second version of the text. thanks!

PR Close #22163
2018-02-18 15:12:14 -08:00
2030846df7 docs(aio): add angular-buch to resources (#22163)
adds a link to the website of our book. many thanks for reviewing this

PR Close #22163
2018-02-18 15:12:14 -08:00
9dae97c5d9 docs: correct grammar mistakes in CONTRIBUTING.md (#22285)
Various grammar mistakes were present in the contribution guidelines
This commit corrects some of them

PR Close #22285
2018-02-18 13:27:24 -08:00
228eb9feef fix(aio): improve announcement-bar layout with wide logos (#22272)
PR Close #22272
2018-02-18 13:16:30 -08:00
debf01d7a6 docs(aio): added ngconf announcement (#22272)
PR Close #22272
2018-02-18 13:16:30 -08:00
51abe69b60 fix: merge-pr script (#22290)
PR Close #22290
2018-02-18 13:13:29 -08:00
396bc0d9e9 build: use authenticated mode for the merge script (#22269)
`TOKEN` is the name with use for other GH scripts

PR Close #22269
2018-02-18 13:01:51 -08:00
861250b4e2 docs: fix changelog errors (#22228)
PR Close #22228
2018-02-16 18:03:04 -08:00
81c1e0a3c3 docs: replace plnkr with StackBlitz (#20365)
PR Close #20365
2018-02-16 15:12:10 -08:00
ce5e8fad9e fix(common): correct mapping of Observable methods (#20518)
fixes #20516
PR Close #20518
2018-02-16 15:10:31 -08:00
185a6ab562 build: add esm5 build (#22258)
This is a partial cherry-pick of 370ab66c4f
which included this along with a new feature for ivy.

PR Close #22258
2018-02-16 14:49:24 -08:00
6b457843b9 test(aio): increase docs-test timeouts to prevent flakes on Travis (#22261)
PR Close #22261
2018-02-16 14:46:23 -08:00
5f52ea3d06 feat(bazel): ng_module produces bundle index (#22176)
It creates the bundle index .d.ts and .metadata.json files.
The names are based on the ng_module target.

PR Close #22176
2018-02-15 14:17:16 -08:00
6c1e7ac40e feat(bazel): introduce a binary stamping feature (#22176)
This grabs version control metadata and makes it available in the build, eg. to put in the version field for released artifacts

PR Close #22176
2018-02-15 14:08:54 -08:00
6597616aac refactor(bazel): convert most ts_library to ng_module (#22176)
This is necessary so we can produce ng metadata for our packages that are published as libraries

PR Close #22176
2018-02-15 14:08:54 -08:00
6a57264d38 Revert: "build: allow bazel build ... (#22168)"
This reverts commit 3237f1dbfc.
2018-02-15 14:07:41 -08:00
1e3e0fad49 fix(aio): improve printing styles (#19651)
printfix

PR Close #19651
2018-02-14 18:49:59 -05:00
0c88d5dedd style: fix typos boostrap to bootstrap (#21917)
PR Close #21917
2018-02-14 18:21:52 -05:00
0b8b06ee8b build: comment-out chromium version checking code temporarily (#22232)
Related #22231

PR Close #22232
2018-02-14 17:26:43 -05:00
Pat
edd6cd4e29 docs: typo - components should be possessive (#22172)
PR Close #22172
2018-02-14 15:06:52 -05:00
fdbfd21bcd feat(platform-browser): fix #19604, can config hammerOptions (#21979)
PR Close #21979
2018-02-14 15:02:59 -05:00
0a5283da1a docs(aio): fix extraneous divs (#22069)
PR Close #22069
2018-02-14 15:02:36 -05:00
3237f1dbfc build: allow bazel build ... (#22168)
Note, the reason this commit removes `firebase-tools` is:

1) firebase-tools has an optional dependency on
https://www.npmjs.com/package/@google-cloud/functions-emulator
2) yarn's `--ignore-optional` doesn't work for transitive deps, so
there's no way to yarn install without getting that functions-emulator
package
3) functions-emulator has a transitive dep on `grpc`
4) the version of `grpc` we get has `BUILD` files and no `WORKSPACE`
file so it always breaks `bazel build ...`

It could be solved by any of:
1) remove firebase-tools - this is what I did
2) fix yarn so you can omit optional deps of a transitive dep
3) make functions-emulator depend transitively on a more recent `grpc`
version
4) patch `grpc` after install by doing an `rm` command in our
postinstall or something

In its place we must install protobufjs. This is needed by the
ngc-wrapped test, which needs jasmine as well as bazel's worker mode
dependencies, and therefore cannot simply rely on
node_modules =
"@build_bazel_rules_typescript_tsc_wrapped_deps//:node_modules"

PR Close #22168
2018-02-14 15:01:42 -05:00
106b435297 docs: add changelog for 5.2.5 2018-02-13 21:07:53 -08:00
ca69dfde31 release: cut the 5.2.5 release 2018-02-13 21:06:54 -08:00
1b8ea1005a fix(compiler): make unary plus operator consistent to JavaScript (#22154)
fixes #22089

PR Close #22154
2018-02-13 13:04:30 -08:00
da6ab91095 fix(platform-browser): support 0/false/null values in transfer_state (#22179)
Issue #22178

PR Close #22179
2018-02-13 11:28:22 -08:00
c4f841f031 fix(core): add stacktrace in log when error during cleanup component in TestBed (#22162)
PR Close #22162
2018-02-13 11:28:08 -08:00
e576b69d10 ci: update ngbot config file (#22173)
Fixes #22053
PR Close #22173
2018-02-13 10:26:06 -08:00
f938774748 ci: remove conditional clause for bazel install (#22170)
No longer needed since we don't have a bazel job
PR Close #22170
2018-02-13 10:25:51 -08:00
c0b78067c4 ci: remove bazel job from Travis (#22170)
This saves us an executor on Travis.

Note that we still do a bazel build on travis when we run the integration tests under e2e_2.

We expect that CircleCI is the only place we'll ever consume bazel-built artifacts.

PR Close #22170
2018-02-13 10:25:51 -08:00
2931018b84 ci: enable bazel remote caching on CircleCI (#21784)
This should cause Bazel builds to be incremental, only re-building parts of Angular affected by changes since the last build.
It also fixes a potential version skew, where CI was running the Bazel linter binaries in the ngcontainer docker image, but developers built them using the versions in WORKSPACE

PR Close #21784
2018-02-13 10:14:22 -08:00
e97afae67a docs(aio): fix typo in "preserveWhitespaces" example (#22182)
Fixes #22147

PR Close #22182
2018-02-12 15:57:42 -08:00
c6bdc831c1 fix(common): weaken AsyncPipe transform signature (#22169)
The AsyncPipe type signature was changed to allow
deferred creation of promises and observalbes that
is supported by the implementation by allowing
`Promise<T>|null|undefined` and by allowing
`Observable<T>|null|undefined`.

PR Close #22169
2018-02-12 15:57:29 -08:00
1a897e4f48 docs(aio): add angular-playground to resources (#22042)
PR Close #22042
2018-02-12 14:30:58 -08:00
603e50d3bf refactor(router): move activation to private method (#22144)
PR Close #22144
2018-02-12 10:41:18 -08:00
ca5b72461c docs(aio): add angular.schule to resources (#22164)
adds a link to our website. many thanks for reviewing this

PR Close #22164
2018-02-12 10:01:23 -08:00
a616dd6c17 fix(aio): remove broken span closing tag (#22146)
PR Close #22146
2018-02-12 10:01:10 -08:00
0ed64af5bc docs(aio): put structural directives back in the nav (#21856)
PR Close #21856
2018-02-12 10:00:14 -08:00
d57fd0b84f fix(bazel): allow TS to read ambient typings (#21876)
Same fix as e70d7a2a7c
This is because the CompilerOptions needs to have directoryExists undefined in order to get the google3 behavior,
so we have to set the property outside the constructor.

Fixes #21872

PR Close #21876
2018-02-09 17:16:25 -08:00
9b280eef63 build: merge-pr new checks that all requested changes have been addressed (#21817)
PR Close #21817
2018-02-09 17:14:17 -08:00
d4a9db2af5 fix(aio): do not rewrite /styleguide URL in Service Worker (#22104)
This URL needs to be redirected via the server, so
we must exclude it from being rewitten.

Closes #22078

PR Close #22104
2018-02-09 13:10:48 -08:00
2740b69023 docs(aio): update docs changelog with links to ts-to-js guide (#21763) (#22104)
PR Close #21763

PR Close #22104
2018-02-09 13:10:48 -08:00
15ff7ba880 fix(aio): update Firebase redirects and SW routes (#21763) (#22104)
Closes #21377

PR Close #21763

PR Close #22104
2018-02-09 13:10:48 -08:00
615bb95138 build(aio): test Service Worker "routing" configuration (#21763) (#22104)
PR Close #21763

PR Close #22104
2018-02-09 13:10:48 -08:00
2b67400652 build(aio): test Firebase hosting redirection configuration (#21763) (#22104)
PR Close #21763

PR Close #22104
2018-02-09 13:10:48 -08:00
ac815f7281 docs: fix typo in http.md (#22058)
PR Close #22058
2018-02-09 13:10:24 -08:00
854f0ff33a feat(aio): enable data driven homepage announcements (#22043)
PR Close #22043
2018-02-09 13:10:12 -08:00
c55523466f docs(aio): several fix for ngmodule guides (#21517)
PR Close #21517
2018-02-09 13:03:47 -08:00
f80b9da18a Revert "docs(common): add HttpParamsOptions to the public API (#20332)"
This reverts commit de561f36e1.
2018-02-08 14:38:13 -08:00
c5ec8d952a fix(bazel): improve error message for missing assets (#22096)
fixes #22095

PR Close #22096
2018-02-08 10:01:27 -08:00
de561f36e1 docs(common): add HttpParamsOptions to the public API (#20332)
Fixes #20276

PR Close #20332
2018-02-08 09:44:37 -08:00
47b71d98ae fix(core): use appropriate inert document strategy for Firefox & Safari (#17019)
Both Firefox and Safari are vulnerable to XSS if we use an inert document
created via `document.implementation.createHTMLDocument()`.

Now we check for those vulnerabilities and then use a DOMParser or XHR
strategy if needed.

Further the platform-server has its own library for parsing HTML, so we
sniff for that (by checking whether DOMParser exists) and fall back to
the standard strategy.

Thanks to @cure53 for the heads up on this issue.

PR Close #17019
2018-02-08 08:55:15 -08:00
22d548f4ed docs(aio): remove ngATL banner from homepage (#22060)
Closes #22029

PR Close #22060
2018-02-07 16:10:18 -08:00
799edd1e2f docs(aio): remove lifecycle hooks img (#21425)
PR Close #21425
2018-02-07 16:09:44 -08:00
ffcb5dd264 build(aio): update examples to CLI to 1.6.5 (#21222)
PR Close #21222
2018-02-07 16:09:27 -08:00
75897d4977 feat(aio): report logger.error calls to Google Analytics (#22011)
We have a number of observables that have `catch` handlers to recover
from errors without causing the stream to close, and breaking the app.
We also have some `try ... catch` blocks for synchronous code for a
similar reason.

In these cases we conventionally then call `logger.error` in the catch
handler. We are interested in these errors so we are going to capture them
by reporting them to Google Analytics via the new `ReportingErrorHandler`.

PR Close #22011
2018-02-07 12:09:38 -08:00
eb0da530a7 feat(aio): report application errors to Google Analytics (#22011)
This is a basic implementation of error logging using the limited
facilities provided by Google Analytics.

Errors within the Angular app itself will be handled by a new
`ReportingErrorHandler` service, which overrides and extends the
built-in `ErrorHandler`.

Further, errors outside the app, which arrive at `window.onerror`
will also be reported to Google Analytics.

Closes #21943

PR Close #22011
2018-02-07 12:09:38 -08:00
0b23573573 fix(language-service): correct instructions to install the language service (#22000)
Fixes: #21956

PR Close #22000
2018-02-07 12:09:00 -08:00
47b73fd153 fix(core): ensure initial value of QueryList length (#21980) (#21982)
Set initial value of `length` to `0`.

Fixes regression introduced by e544742156 (diff-a85dbe0991a7577ea24b49374e9ae90b) where the `length` property ceased to have initial value.

Closes #21980

PR Close #21982
2018-02-07 12:08:44 -08:00
07769e5caa test(common): disable deprecated date pipe tests on chrome mobile (#21933)
Closes #21907
PR Close #21933
2018-02-07 12:07:31 -08:00
9fdb804b63 test(forms): update test name with correct wording (#21833)
Use the term primitive value instead of standalone

Fixes #21831

PR Close #21833
2018-02-07 12:07:15 -08:00
9d02db3254 fix(aio): ignore .header-link when selecting the heading text (#21695)
Implemented @maxkorz's
[suggestion](https://github.com/angular/angular/issues/21515#issuecomment-357453634).

Fixes #21515

PR Close #21695
2018-02-07 12:06:45 -08:00
920b0df32a fix(aio): prevent heading misplacement while styles load (#21695)
During the initial load of the page (probably until the icon styles are
loaded and/or applied), the `.header-link` element is wider, pushing the
heading text slightly to the right (for a brief moment).

This commit prevents this slight shift by explicitly setting the width
for the `.header-link` element.

PR Close #21695
2018-02-07 12:06:45 -08:00
b313976ac1 fix(aio): ensure header-links are visible at <600px (#21695)
PR Close #21695
2018-02-07 12:06:45 -08:00
2d19e7bbea refactor(aio): simplify .header-link styles (#21695)
PR Close #21695
2018-02-07 12:06:45 -08:00
c3c92d7796 fix(aio): reduce flicker and reflows for initial rendering (#21695)
For the initial rendering, where there is no transition from a previous
visual state to a new one, animations make little sense. The page should
load with as few reflows as possible.
Similarly, while we typically want to defer updating the SideNav state
(e.g. opened/closed) until the "leaving" document is animated out of the
page, on the initial rendering (where there is no "leaving" document)
this leads to the SideNav flashing (from closed to open).

These worked as expected before, but several parts (mostly related to
documents with a SideNav) have been accidentally broken in recent
commits (e.g. when upgraded to latest material, or enabled animations
for DocViewer transitions, etc.).

This commit restores the previous behavior by ensuring that (on the
initial rendering) the SideNav state is updated as soon as possible and
that there will be no animations when:

1. The hamburger button appears.
2. The SideNav is opened.
3. The main section's width is adjusted to make room for the SideNav.

PR Close #21695
2018-02-07 12:06:45 -08:00
a887c9339f refactor(aio): preserve HttpClient asynchronicity in tests (#21695)
Previously, the mocked `HttpClient` was synchronous in tests (despite
the actual `HttpClient` being asynchronous). Although we use observables
(which generally make the implementation sync/async-agnostic), the fact
that we have no control over when Angular updates/checks views and calls
lifecycle hooks resulted in different behavior (and errors) in tests
(with sync `HttpClient`) vs actual app (with async `HttpClient`).

This commit ensures that the behavior (and errors) are consistent
between the tests and the actual app by making the mocked `HttpClient`
asynchronous.

PR Close #21695
2018-02-07 12:06:45 -08:00
89051a0452 fix(aio): remove links from sub-menu toggles (#21695)
Navigating to a document while trying to expand or collapse a sub-menu
is undesirable and confusing. All sub-menu toggles should have no other
effect than expanding/collapsing the corresponding sub-menu.

PR Close #21695
2018-02-07 12:06:45 -08:00
97dafa8460 docs(animations): fix typo (disbled --> disabled) (#21695)
PR Close #21695
2018-02-07 12:06:45 -08:00
56b9591746 fix(forms): prevent event emission on enable/disable when emitEvent is false (#12366) (#21018)
Previously, the emitEvent flag was only checked when emitting on the current control.
Thus, if  the control was part of a hierarchy, events were emitted on the parent and the childrens.
This fixes the issue by properly passing the emitEvent flag to both parent and childrens.

Fixes #12366

PR Close #21018
2018-02-07 12:05:26 -08:00
b0ddb5ad0e build(aio): blacklist unwanted URLs from the generated sitemap.xml (#22061)
Closes #22017

PR Close #22061
2018-02-07 12:02:01 -08:00
103727aadf docs(aio): fix TOH inclusion of HeroesService. (#21228)
Change docs where the MessageService is referenced

Fixes #20398

PR Close #21228
2018-02-07 12:01:32 -08:00
44ea80b797 docs(forms): Custom Validator example selector name incorrect. (#20464)
Added bobby e2e test for template form.

Fixes: #20206

PR Close #20464
2018-02-07 12:01:12 -08:00
41046e4a90 docs(forms): Custom Validator example selector name incorrect. (#20464)
Name of selector in ForbiddenName example is not consistent with Validator class nor Html selector example. Added the selector name 'appForbiddenName' as an alias name for the input of the Validator class, and updated the view accordingly.

Fixes: #20206

PR Close #20464
2018-02-07 12:01:12 -08:00
530b824faa docs: add changelog for 5.2.4 2018-02-07 10:19:39 -08:00
e22d3a605c release: cut the 5.2.4 release 2018-02-07 10:16:42 -08:00
c6645e7a04 fix(core): fix proper propagation of subscriptions in EventEmitter (#22016)
Closes #21999

PR Close #22016
2018-02-06 07:56:34 -08:00
f0396f1e54 docs(aio): fix swap value (#20905)
'http.get' has been swapped in for 'of'

PR Close #20905
2018-02-05 13:05:58 -08:00
adb1d62967 docs: clarify npm/yarn commands, add blank lines to mix md/html in table (#21606)
PR Close #21606
2018-02-05 13:02:14 -08:00
cfe83939a4 docs: update browser support (#21606)
PR Close #21606
2018-02-05 13:02:14 -08:00
973607fe9d ci: mark PRs with rejection as not green (#21922)
PR Close #21922
2018-02-05 13:01:12 -08:00
664f7fa477 build(aio): add API static members to search index (#21988)
Previously searching for `compose` did not include `Validators`
in the search results because we were not including all the
`static` members of API docs in the index.

PR Close #21988
2018-02-05 13:00:47 -08:00
b155ae116b ci: add config for g3 status (#21996)
Ref #21642
PR Close #21996
2018-02-05 12:59:59 -08:00
ce51ea93a1 fix(core): fix #20582, don't need to wrap zone in location change listener (#22007)
PR Close #22007
2018-02-05 12:59:05 -08:00
d38e08812e feat(aio): dynamically, pre-emptively, add noindex (#21992)
These tags are removed when the doc is ready and valid, but this will
allow us to block indexing in the case that the Angular app fails to
bootstrap or load the document for some non-404 reason.

This should get around the problem with hardcoded tags. See
c3fb820473

Closes #21941

PR Close #21992
2018-02-05 12:58:27 -08:00
aa9ba7f9fe fix(core): should check Zone existance when scheduleMicroTask (#20656)
PR Close #20656
2018-02-02 07:53:55 -08:00
102d06b974 docs: consistency fix in describing a custom tag (#21747)
PR Close #21747
2018-02-02 07:53:18 -08:00
11ec80a053 docs: add docs for IE (#21824)
PR Close #21824
2018-02-02 07:51:47 -08:00
75eecdc351 docs: add missing underline (#21892)
PR Close #21892
2018-02-02 07:49:33 -08:00
965eecc587 build(aio): move zip and live-example generation to yarn predocs task (#21970)
This will prevent the confusing errors for first time users who
try to generate the docs with `yarn docs` and are told there are
dangling links.

Closes #21944

PR Close #21970
2018-02-02 07:48:42 -08:00
c4fb696189 fix(common): don't convert null to a string when flushing a mock request (#21417)
A bug in TestRequest caused null response bodies to be stringified. This
change causes null to be treated faithfully.

Fixes #20744

PR Close #21417
2018-02-01 08:32:44 -08:00
72df747dd6 docs(aio): add missing closing <code-examle> tag (#21771)
PR Close #21771
2018-02-01 08:31:21 -08:00
579bed1a7a docs: add changelog for 5.2.3 2018-01-31 12:47:02 -08:00
b59fb23f4a release: cut the 5.2.3 release 2018-01-31 12:45:17 -08:00
2aa460b30e docs: add http guide sample and adjust text (#21326)
PR Close #21326
2018-01-31 10:24:43 -08:00
e0022ae9cd docs: Fix platform-detection example for Universal (#21796)
PR Close #21796
2018-01-31 10:21:04 -08:00
f2e923edd8 build(aio): upgrade to dgeni-packages 0.24.0 (#21802)
This has two benefits:

* it prepares the way for the API docs update, which need parameter docs
* it doesn't incorrectly report dangling links for non-latin anchors

Closes #21306

PR Close #21802
2018-01-31 10:20:37 -08:00
c2f5ed545c fix(common): generate closure-locale data file with exported plural functions (#21873)
Fixes #21870
PR Close #21873
2018-01-30 11:42:31 -08:00
5d75df8fb1 ci: unblock master by ignoring date pipe tests while we fix it (#21906)
PR Close #21906
2018-01-30 11:33:46 -08:00
ed2b71799c fix(common): allow HttpInterceptors to inject HttpClient (#19809)
Previously, an interceptor attempting to inject HttpClient directly
would receive a circular dependency error, as HttpClient was
constructed via a factory which injected the interceptor instances.
Users want to inject HttpClient into interceptors to make supporting
requests (ex: to retrieve an authentication token). Currently this is
only possible by injecting the Injector and using it to resolve
HttpClient at request time.

Either HttpClient or the user has to deal specially with the circular
dependency. This change moves that responsibility into HttpClient
itself. By utilizing a new class HttpInterceptingHandler which lazily
loads the set of interceptors at request time, it's possible to inject
HttpClient directly into interceptors as construction of HttpClient no
longer requires the interceptor chain to be constructed.

Fixes #18224.

PR Close #19809
2018-01-29 16:12:32 -08:00
fad99cca0e fix(forms): inserting and removing controls should work in re-bound form arrays (#21822)
Closes #21501

PR Close #21822
2018-01-29 16:11:41 -08:00
3f5ead3845 fix(aio): missing plural s in preserveWhiteSpaces example (#21854)
PR Close #21854
2018-01-29 11:35:13 -08:00
a89e709515 docs: change ”it's" to "its" as needed in several docs. (#21867)
Most of them are in content but one is in common and needs special approval.

PR Close #21867
2018-01-29 11:34:47 -08:00
6a7689d4ea build: update to latest bazel rules (#21821)
PR Close #21821
2018-01-27 10:55:45 -08:00
696ba01a4e fix(aio): don't set noindex metatag in the static index.html (#21816)
This seems to be causing crawling issues for google.

Ref #21665

PR Close #21816
2018-01-26 16:08:31 -08:00
81d64d6bec fix(core): fix retrieving the binding name when an expression changes (#21814)
fixes #21735
fixes #21788

PR Close #21814
2018-01-26 15:34:48 -08:00
7410941a7c build: merge-pr now checks that PR status is green before proceeding (#21810)
Optionally one can use `--force` to override and merge no non-green PR.

PR Close #21810
2018-01-26 14:50:41 -08:00
d159ad8b88 build(aio): prevent Windows error on serve-and-sync (#21806)
Running `yarn start` (which watches the `src/` directory) and
`yarn docs-watch` (which cleans up files in `src/generated/api/`) often
results in `ENOTEMPTY` errors.

This commit solves it by ensuring that `yarn docs` has been completed
before running `yarn start`.

PR Close #21806
2018-01-26 14:50:15 -08:00
250c8da768 fix(language-service): ensure correct paths are passed to TypeScript (#21812)
The 2.6 version of TypeScript's `resolveModuleName`  started to
require paths passed to be separated by '/' instead of being
able to handle '\'.

`ngc` and `ng` already do this transformation.

Fixes: #21811

PR Close #21812
2018-01-26 14:49:23 -08:00
778e6e759f fix(language-service): spell diagnostics correctly (#21812)
PR Close #21812
2018-01-26 14:49:23 -08:00
35a0721217 fix(router): remove @internal tag on ParamInheritanceType (#21773)
This is a more defensive approach to ensure that references to
ParamInheritanceType from the published declarations do not cause
compilation errors when compiling Angular from the published packages.

Fixes #21456

PR Close #21773
2018-01-26 10:28:34 -08:00
ba045e88d7 docs: add notes on email used for CLA (#21754)
Closes #20034

PR Close #21754
2018-01-26 10:28:18 -08:00
67806a7b25 fix(aio): close SideNav on non-sidenav doc on wide screen (#21538)
Partly addresses #21520.

PR Close #21538
2018-01-26 10:25:16 -08:00
9778a23be8 fix(aio): fix SideNav height on narrow screens (#21538)
Since we specify `bottom: 0`, specifying the height is unnecessary and
leads to wrong height (unless updated) on narrow screens where the
topbar height is decreased.

Partly addresses #21520.

PR Close #21538
2018-01-26 10:25:15 -08:00
87e06d765e ci: Add back the CLI integration test with pinning (#21555)
The CLI app is now checked in, rather than generated dynamically with
`ng new`. This loses some assertion power, but gains hermeticity.
It also checks in lock files for all integration tests, avoiding
floating version numbers.

We'll need another place to integration test between changes in
the various repositories - but the angular/angular PR-blocking status
is not the right place to do this.

PR Close #21555
2018-01-25 22:18:56 -08:00
56f3e18c1c fix(forms): allow FormBuilder to create controls with any formState type (#20917)
Align formState type in FormBuilder#control with FormControl#constructor

Fixes #20368

PR Close #20917
2018-01-25 22:17:43 -08:00
637515e71b build: autosquashes SHAs as part of merge-pr script (#21791)
To support `git checkin --fixup` and `git checkin —squash`
we need to make sure that `merge-pr` squashes the sepecial
commits before they are merged.

For more details see:
https://robots.thoughtbot.com/autosquashing-git-commits

PR Close #21791
2018-01-25 22:12:11 -08:00
27ecd077d4 docs(aio): fix missing stylesheet in component-styles example (#21772)
The code in the example was referring to `hero-app.component.css` but this did
not exist.

PR Close #21772
2018-01-25 13:38:14 -08:00
4db1be0292 docs(aio): fix paths to imported CSS stylesheets (#21772)
The AOT compiler needs relative paths so that it can find
the imported stylesheets.

PR Close #21772
2018-01-25 13:38:14 -08:00
a0dbef9ea4 build(aio): upgrade CLI version to cope with new Angular 6.0.0-beta.1 release (#21772)
Before version 1.6 of Angular CLI there was a check that prevented use of Angular
compiler CLI with major version 6.

PR Close #21772
2018-01-25 13:38:13 -08:00
3aaf43f73c docs: add changelog for 5.2.2 2018-01-24 21:26:17 -08:00
d952ae24dd release: cut the 5.2.2 release 2018-01-24 21:23:04 -08:00
da9e57b3d5 build: Update to latest rules_typescript. (#21675)
Fixes #21481

PR Close #21675
2018-01-24 20:47:41 -08:00
44d4f82dae docs(aio): added a link to Angular-RU (#21687)
Angular-RU Community on GitHub is a single point for all resources, chats, podcasts and meetups for Angular in Russia

PR Close #21687
2018-01-24 20:47:40 -08:00
bde2b4425c ci: use sudo: false on Travis (#21641)
Related to #21422.

PR Close #21641
2018-01-24 20:47:40 -08:00
2a3de802a0 fix(aio): fix code highlight in API docs templates (#21630)
Fixes #21108

PR Close #21630
2018-01-24 20:47:40 -08:00
71f9eaa743 fix(common): extract plural function from i18n locale data files for TS 2.6 (#21626)
Fixes #21608

PR Close #21626
2018-01-24 20:47:40 -08:00
a62c186d15 fix(common): don't remove special characters when extracting CLDR data (#21626)
PR Close #21626
2018-01-24 20:47:40 -08:00
c8bf281174 build(aio): generate sitemap from the generated pages (#21689)
Closes #21684

PR Close #21689
2018-01-24 20:47:40 -08:00
de6c6445af fix(compiler): Don't strip /*# sourceURL ... */ (#16088)
Currently, `shimCssText` only keep `/*# sourceMappingUrl ... */` comments and strip `/*# sourceURL ... */` comments. So, Chrome can't find the source maps for component style(that's created in new `style` tags)

PR Close #16088
2018-01-24 12:35:31 -08:00
54238822e6 build: merge PR to all branches per target: label (#21739)
PR Close #21739
2018-01-24 12:35:13 -08:00
8b3fbb5bf4 fix(router): don't use ParamsInheritanceStrategy in declarations (#21574)
ParamsInheritanceStrategy is internal, so any references to it from the
published .d.ts files will fail.

Fixes #21456.

PR Close #21574
2018-01-23 21:34:37 -08:00
2f61d3c320 fix(aio): remove remaining plnkr references (#20165)
PR Close #20165
2018-01-23 21:33:55 -08:00
5894f6ee1c build(aio): check for obsolete plnkr.json and missing main files (#20165)
Also, remove `plnkr.json` for `service-worker-getting-started` guide,
since it is not used and ServiceWorker cannot work correctly in
plnkr/stackblitz anyway (e.g. no build step to re-compute hashes).
A zipper might be useful and can be added in a subsequent PR, but it is
currently broken (e.g. no dependency on `@angular/service-worker`).

PR Close #20165
2018-01-23 21:33:55 -08:00
6d9fcd62de build(aio): upgrade sample package.json files to jasmine@~2.8.0 (#20165)
- Update tooling to support revised testing guide (PR #20697).
- Require jasmine upgrade for examples that use marble testing.
- Copy `cli/package.json` to `testing/` and add `jasmine-marbles`.
- Resolve merge conflicts created by `NgModules` guides.

PR Close #20165
2018-01-23 21:33:55 -08:00
0cbccc06dd build(aio): migrate plunker to stackblitz (#20165)
PR Close #20165
2018-01-23 21:33:52 -08:00
ed670a36fb docs: update ICU select messages to use male/female (#21713)
fixes #21694

PR Close #21713
2018-01-23 16:32:24 -08:00
8e44577df3 fix(compiler): fix ICU select messages to use male/female/other (#21713)
related to #21694

PR Close #21713
2018-01-23 16:32:24 -08:00
6921c20ea1 test(forms): Better description and coverage for #19256 (#21652)
fixes #21575

PR Close #21652
2018-01-23 16:31:45 -08:00
52970c09e1 fix(compiler-cli): do not fold errors past calls in the collector (#21708)
Folding errors passed calls prevented the static reflector from
begin able to ignore errors in annotations it doesn't know as
the call to the unknown annotation was elided from the metadata.

Fixes: #21273

PR Close #21708
2018-01-23 13:33:26 -08:00
eecdf3414e docs: fix #19989, add zone flags(blacklist/module) in guide (#21701)
PR Close #21701
2018-01-23 13:33:11 -08:00
21f766968d refactor(bazel): pass around tsconfig as a file, not a path (#21614)
this unlocks the ability to replay ts compilations with different settings

PR Close #21614
2018-01-23 10:06:05 -08:00
4b68fdce6f build: Update to latest rules_typescript. (#21675)
Fixes #21481

PR Close #21675
2018-01-22 15:34:48 -08:00
c12ea3a1f0 fix(common): A null value should remove the style on IE (#21679)
fixes #21064

PR Close #21679
2018-01-22 12:57:23 -08:00
d7dbdc5c36 docs: fix stray div and reformat paragraph (#21676)
PR Close #21676
2018-01-19 20:42:04 -08:00
0112a903f9 ci: add github bot config to triage issues (#21672)
Fixes #21635
PR Close #21672
2018-01-19 20:41:15 -08:00
66bbc84127 ci(aio): do not limit size of gzip7 and gzip 9 (#21601)
PR Close #21601
2018-01-19 20:41:01 -08:00
554129d6fe feat(aio): update metatags to control search engine crawling (#21665)
The `<meta name="robots" content="noindex">` tag is used
to indicate to search engine crawlers that they should not index
the current page. This is set dynamically by the the document
viewer component to ensure that 404 and other erroring pages
are not added to the search index.

This relies upon the idea that the crawling bot will run the JS
and wait to see if this meta tag has been added or not.

Since we believe that the `googebot` will do this, we also
pre-emptively add a hard-coded noindex tag specifically for
this bot, so that if anything else fails in bootstrapping the app,
the failed page will not be added to the index.

Closes #21317

PR Close #21665
2018-01-19 20:31:45 -08:00
e32a0cabfe fix(aio): add a required comma in firebase.json (#21618)
PR Close #21618
2018-01-19 20:31:30 -08:00
c828e5627b build: Remove angular_src nested workspace (#21096)
PR Close #21096
2018-01-19 13:10:09 -08:00
1626e74c59 docs: clarify the use of classes and interfaces in style guide (#20919)
PR Close #20919
2018-01-19 13:09:58 -08:00
a15a2b46d1 ci: add "PR action: cleanup" to the bot's forbiddenLabels list (#21562)
PR Close #21562
2018-01-19 13:09:41 -08:00
379ed75593 docs: improve/simplify example for providers guide (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
0f619896b3 docs: fix/improve example for singleton-services guide (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
7060655806 docs: several minor NgModule guide fixes/improvements (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
b5fc3eb9de docs: minor fixes (anchor tags, redundant whitespace, consistent code-snippets lang) (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
451bdb9a75 docs: change titles to sentence case (#21620)
PR Close #21620
2018-01-19 13:09:25 -08:00
983ccc02ad build(aio): fix zips testing commands (#21629)
PR Close #21629
2018-01-19 13:09:17 -08:00
00f99b3c4c ci: update github bot messages (#21634)
Fixes #21633
PR Close #21634
2018-01-19 13:09:11 -08:00
ba4ea82f68 fix(compiler-cli): do not lower expressions in non-modules (#21649)
Fixes: #21651

PR Close #21649
2018-01-19 13:09:04 -08:00
982eb7bba8 fix(common): fallback to last defined value for named date and time formats (#21299)
closes #21282

PR Close #21299
2018-01-19 13:08:57 -08:00
3606c55410 docs: edit entry component FAQ (#21487)
PR Close #21487
2018-01-19 13:08:50 -08:00
2c65027391 docs: add server side redirect and fix NgModule FAQ links (#21487)
PR Close #21487
2018-01-19 13:08:50 -08:00
4ee92f14a6 docs: fix lazy loading example dir name (#21475)
PR Close #21475
2018-01-19 13:08:30 -08:00
c9b65914d3 build: add mhevery to bazel approvers (#21314)
PR Close #21314
2018-01-19 13:08:19 -08:00
02352bcd9e fix(compiler): add support for marker tags in xliff serializers (#21250)
The Xliff serializer now supports the tags `seg-source` and `mrk`, while the Xliff2 serializer now supports `mrk`.
Fixes #21078
PR Close #21250
2018-01-19 13:08:10 -08:00
0d55600fd8 Revert "fix(core): fix chained http call (#20924)"
This reverts commit 54e75766ad.
2018-01-19 13:06:33 -08:00
af4eb00c91 docs: add changelog for 5.2.1 2018-01-17 09:39:46 -08:00
d3e7ebb3b4 release: cut the 5.2.1 release 2018-01-17 09:37:50 -08:00
420f5c4275 build(bazel): remove spurious file (#21455)
PR Close #21455
2018-01-17 08:24:34 -08:00
b773a4ab98 docs(aio): change df-question to app-question (#21438)
closes: #21404
PR Close #21438
2018-01-17 07:20:52 -08:00
55f15c54d9 docs(aio): add description and docs links for code samples (#21561)
PR Close #21561
2018-01-17 07:19:37 -08:00
4556532c26 feat(core): add binding name to content changed error (#20352)
Adding the binding name to the error message recieved by the user gives
extra context on what exactly changed. The tests are also updated to
reflect the new error message.

PR Close #20352
2018-01-17 07:17:00 -08:00
54e75766ad fix(core): fix chained http call (#20924)
Fixes an issue where chained http calls would prematurely call
testability whenStable callbacks after the first http call.

Fixes #20921

PR Close #20924
2018-01-17 07:14:55 -08:00
d3333f04ba refactor(core): refactor WrappedValue (#20997)
- Improve `WrappedValue` by adding `unwrap` symetrical to `wrap`.
- remove dead code - `ValueUnwrapper`

The property `wrapped` is an implementation details and should never be accessed
directly - use `unwrap(wrappedValue)`. Will change to protected in Angular 7.

PR Close #20997
2018-01-16 07:13:24 -08:00
75f8522b8d feat(forms): handle string with and without line boundary on pattern validator (#19256)
PR Close #19256
2018-01-16 07:12:14 -08:00
a771ee5d90 build(aio): move file cleaning to later in the doc gen (#21540)
Previously the generated files were cleaned out before
doc-gen began (via a yarn pre-script). This can cause a
race condition in the CLI server, which prevents the new
generated files from being picked up.

Now we delay the cleaning until the last minute to ensure
that they ar still picked up by the webpack server.

PR Close #21540
2018-01-16 07:11:01 -08:00
a4cbe3542a ci: disable integration/cli-hello-world test (#21492)
it is non-hermetic and breaks often due to unpinned dependencies.

PR Close #21492
2018-01-12 14:57:45 -08:00
cc9419d1ca fix(language-service): Clear caches when program changes (#21337)
This commit fixes a bug whereby the caches are not cleared when the
program changes. This subsequently produces the incorrect error of
'Component ... is not included in a module ...'.

PR Close #19405

PR Close #21337
2018-01-12 14:43:34 -08:00
d5393c7f91 docs(compiler): document the $any type cast function (#20968)
Closes #20966

PR Close #20968
2018-01-12 14:38:42 -08:00
71dd92bbb8 style(aio): enforce strict TypeScript checks (#21342)
Closes #20646

PR Close #21342
2018-01-12 14:37:02 -08:00
977978edb5 test(common): make date pipe tests work in more timezones (#21379)
Fixes #21112
PR Close #21379
2018-01-12 13:50:06 -08:00
eb70966065 fix(aio): correctly handle redirects (#21416)
- Fixes handling of some redirects by the ServiceWorker.
- Fixes redirect for old `NgFor` to new `NgForOf` URL.

Fixes #21318

PR Close #21416
2018-01-12 13:49:10 -08:00
cf4bea587d ci(aio): run e2e tests in production mode (#21470)
This will enable catching errors introduced by build optimizations that
do not appear in `development` mode.

Fixes #21446

PR Close #21470
2018-01-12 13:46:00 -08:00
8e9cd57951 fix(common): set correct timezone for ISO8601 dates in Safari (#21506)
Fixes #21491
PR Close #21506
2018-01-12 13:21:11 -08:00
f23896f519 docs: fix release schedule date (#21474)
PR Close #21474
2018-01-12 12:10:26 -08:00
0e59d18fc2 ci: add angular robot config file (#21489)
PR Close #21489
2018-01-12 10:12:28 -08:00
54c8a321a9 ci: update pullapprove rules now that we allow selfapprovals (#21494)
PR Close #21494
2018-01-12 10:11:37 -08:00
9005a6f3cd feat(aio): implement survey notification link (#21371)
Closes #21094

PR Close #21371
2018-01-12 10:06:08 -08:00
3c6a5063f7 fix(benchpress): should still support selenium_webdriver < 3.6.0 (#21477)
PR Close #21477
2018-01-11 10:54:11 -08:00
b49d54e606 docs(forms): clarify note in reactive forms doc (#21134)
PR Close #21134
2018-01-11 07:04:15 -08:00
55fd82e587 docs: fix release schedule date (#21469)
PR Close #21469
2018-01-11 06:45:49 -08:00
7f3d0bbf97 build: update polyfill size (#21461)
PR Close #21461
2018-01-10 17:07:32 -08:00
3db02d244a docs: fix lazy-loading example (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
50b605686e docs: fix yarn.lock (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
64d4aafbc7 docs(aio): add NgModule docs (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
a931a419fa fix(compiler): make .ngsummary.json files idempotent (#21448)
Fixes: #21432

PR Close #21448
2018-01-10 16:21:32 -08:00
6a97b5b722 docs(ivy): add Ivy as a recognized label (#21428)
PR Close #21428
2018-01-10 15:32:59 -08:00
aad1126446 docs: update the release schedule with v6 info (#21435)
Fixes #20649

PR Close #21435
2018-01-10 15:20:27 -08:00
7b463df52b fix(aio): preserve static Observable methods (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
a2432c9f10 build(aio): turn on namedChunks option to make debugging, profiling and tracking easier (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
e500484ccc build(aio): upgrade to angular@5.2.0 (#21351)
-rw-r--r--  1 iminar  eng   72498 Jan  9 22:20 dist/0.0d2802b63e9f4f4615cd.chunk.js
-rw-r--r--  1 iminar  eng   14872 Jan  9 22:20 dist/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  9 22:20 dist/inline.cb4b7a639193fc489d3b.bundle.js
-rw-r--r--  1 iminar  eng  454654 Jan  9 22:20 dist/main.b65f32ffc92e075e64e0.bundle.js
-rw-r--r--  1 iminar  eng   40264 Jan  9 22:20 dist/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  9 22:20 dist/worker-basic.min.js

PR Close #21351
2018-01-10 14:30:42 -08:00
a0dcb0b828 ci(aio): track sizes of all js files (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
c4b71920d1 build(aio): upgrade to angular@5.2.0-rc.0 (#21351)
Because of c2b3792 one of the test assertions had to be adjusted (more info: https://github.com/angular/angular/pull/21351#issuecomment-356083940).

PR Close #21351
2018-01-10 14:30:42 -08:00
650f5fb5c7 build(bazel): fix merge conflict between c4f02e2 and ef956a2 (#21453)
PR Close #21453
2018-01-10 12:57:38 -08:00
c32e83334b fix(compiler): cache external reference resolution (#21359)
Cache reference resolution for external references as finding
the declaration of a symbol is expensive and does not change
for a program once created.

This resolves a signficant performance regression in the langauge
service.

PR Close #21359
2018-01-10 12:34:07 -08:00
7bdd9aecbd build: upgrade yarn to 1.3.2 (#21406)
Fixes #20566
PR Close #21406
2018-01-10 12:32:47 -08:00
5ede67c345 build: move repeated tsconfig attributes to a macro (#20964)
This helps ensure we use the same tsconfig.json file for all compilations.
Next steps are to make it the same tsconfig.json file used by the editor

PR Close #20964
2018-01-10 12:30:44 -08:00
31b671ab54 fix(aio): support multibyte character in heading (#21414)
PR Close #21414
2018-01-10 12:25:45 -08:00
3804d20b6d docs(bazel): document an installation issue (#21401)
observed by Igor on a Mac

PR Close #21401
2018-01-10 12:24:03 -08:00
0a5a87887e build(aio): upgrade to uglify-es@3.3.5 (#21350)
This should fix the size regression spotted via the previous commit.

-rw-r--r--  1 iminar  eng   72498 Jan  8 00:03 dist/0.86a7a08f7866e6cdc36f.chunk.js
-rw-r--r--  1 iminar  eng   14872 Jan  8 00:03 dist/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  8 00:03 dist/inline.7722895d8c844f710bcd.bundle.js
-rw-r--r--  1 iminar  eng  453905 Jan  8 00:03 dist/main.faff0e2da95443f759f5.bundle.js
-rw-r--r--  1 iminar  eng   40264 Jan  8 00:03 dist/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  8 00:03 dist/worker-basic.min.js

PR Close #21350
2018-01-10 12:22:12 -08:00
c46afce0f5 build(aio): upgrade to @angular/cli@1.6.3 (#21350)
This change introduces a size regression of 9kb for main.js :-(

I filed an issue for this: https://github.com/angular/angular-cli/issues/9108

-rw-r--r--  1 iminar  eng   72546 Jan  5 19:27 dist.cli-1.6.3/0.86a7a08f7866e6cdc36f.chunk.js
-rw-r--r--  1 iminar  eng   14893 Jan  5 19:27 dist.cli-1.6.3/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  5 19:27 dist.cli-1.6.3/inline.7722895d8c844f710bcd.bundle.js
-rw-r--r--  1 iminar  eng  466484 Jan  5 19:27 dist.cli-1.6.3/main.faff0e2da95443f759f5.bundle.js
-rw-r--r--  1 iminar  eng   40363 Jan  5 19:27 dist.cli-1.6.3/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  5 19:27 dist.cli-1.6.3/worker-basic.min.js

PR Close #21350
2018-01-10 12:22:12 -08:00
76c781fd37 docs(router): remove extra brackets (#21294)
PR Close #21294
2018-01-10 12:20:48 -08:00
51eb3d418e fix(service-worker): properly handle invalid hashes in all scenarios (#21288)
When the SW fetches URLs listed in a manifest with hashes, it checks
the content hash against the manifest to make sure it has the correct
version of the URL. In the event of a mismatch, the SW is supposed to
consider the manifest invalid, and avoid using it. There are 3 cases
to consider by which this can happen.

Case 1: during the initial SW installation, a manifest is activated
without waiting for every URL to be fully loaded. In the background,
every prefetch URL listed by the manifest is requested and cached.
One such prefetch request could fail the hash test, and cause the
manifest to be treated as invalid. In such a case, the SW should
enter a state of EXISTING_CLIENTS_ONLY, as the latest manifest is
invalid.

This case works today.

Case 2: during the initial SW installation, as in Case 1, a manifest
is activated without waiting for each URL to fully load. However,
it's possible that the application could request a URL with a bad
hash before background initialization tries to load that URL. This
happens if, for example, the application has a broken index.html.

In this case, the SW should enter a state of EXISTING_CLIENTS_ONLY,
and serve the request from the network instead.

What happens today is that the internal error escapes the SW and
is returned as a rejected Promise to respondWith(), causing a
browser-level error that the site cannot be loaded, breaking the
site.

This change allows the SW to detect the error and enter the correct
state, falling back on the network if needed.

Case 3: during checkForUpdate(), the SW will try to fully cache the
new update before making it the latest version. Failure here is
complicated - if the page fails to load due to transient network
conditions (timeouts, 500s, etc), then it makes sense to continue
serving the existing cached version, and attempt to activate the
update on the next cycle.

If the page fails due to non-transient conditions though (400 error,
hash mismatch, etc), then the SW should consider the updated
manifest invalid, and enter a state of EXISTING_CLIENTS_ONLY.

Currently, all errors are treated as transient.

This change causes the SW to treat all errors during updates as
non-transient, which can cause the SW to unnecessarily enter a
safe mode. A future change can allow the SW to remain in normal mode
if the error is provably transient.

PR Close #21288
2018-01-10 12:18:55 -08:00
48c18985cc fix(animations): fix increment/decrement aliases example (#18323)
PR Close #18323
2018-01-10 12:07:24 -08:00
167cbed266 build: add bazel rulse for benchmarks (#21436)
PR Close #21436
2018-01-10 12:01:17 -08:00
70e8802540 docs(core): provide note for unit test changes with the ng-star-inserted className (#21450)
PR Close #21450
2018-01-10 11:14:28 -08:00
1035 changed files with 7580 additions and 38378 deletions

View File

@ -15,11 +15,16 @@ build --experimental_remote_spawn_cache --remote_rest_cache=http://localhost:764
# Prevent unstable environment variables from tainting cache keys
build --experimental_strict_action_env
# Save downloaded repositories such as the go toolchain
# This directory can then be included in the CircleCI cache
# It should save time running the first build
build --experimental_repository_cache=/home/circleci/bazel_repository_cache
# Workaround https://github.com/bazelbuild/bazel/issues/3645
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
# Limit Bazel to consuming resources that fit in CircleCI "medium" class which is the default:
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
build --local_resources=3072,2.0,1.0
build --local_resources=14336,8.0,1.0
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
test --flaky_test_attempts=2

View File

@ -13,7 +13,7 @@
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
var_1: &docker_image angular/ngcontainer:0.1.0
var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.1.0
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.1.0
# See remote cache documentation in /docs/BAZEL.md
var_3: &setup-bazel-remote-cache
@ -41,14 +41,14 @@ jobs:
steps:
- checkout:
<<: *post_checkout
# See remote cache documentation in /docs/BAZEL.md
- run: .circleci/setup_cache.sh
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
- *setup-bazel-remote-cache
- run: 'yarn buildifier -mode=check ||
(echo -e "\nBUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
- run: 'yarn skylint ||
# Check BUILD.bazel formatting before we have a node_modules directory
# Then we don't need any exclude pattern to avoid checking those files
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) ||
(echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
# Run the skylark linter to check our Bazel rules
- run: 'find . -type f -name "*.bzl" |
xargs java -jar /usr/local/bin/Skylint_deploy.jar ||
(echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)'
- restore_cache:
@ -59,7 +59,7 @@ jobs:
build:
<<: *job_defaults
resource_class: large
resource_class: xlarge
steps:
- checkout:
<<: *post_checkout
@ -71,6 +71,7 @@ jobs:
- restore_cache:
key: *cache_key
- run: ls /home/circleci/bazel_repository_cache || true
- run: bazel info release
- run: bazel run @yarn//:yarn
# Use bazel query so that we explicitly ask for all buildable targets to be built as well
@ -78,19 +79,11 @@ jobs:
# See https://github.com/bazelbuild/bazel/issues/4257
- run: bazel query --output=label '//modules/... union //packages/... union //tools/...' | xargs bazel test
# CircleCI will allow us to go back and view/download these artifacts from past builds.
# Also we can use a service like https://buildsize.org/ to automatically track binary size of these artifacts.
- store_artifacts:
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
destination: packages/core/test/bundling/hello_world/bundle.min.js
- store_artifacts:
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.brotli
destination: packages/core/test/bundling/hello_world/bundle.min.js.brotli
- save_cache:
key: *cache_key
paths:
- "node_modules"
- "~/bazel_repository_cache"
workflows:
version: 2

View File

@ -80,14 +80,12 @@ merge:
# options for the triage plugin
triage:
# number of the milestone to apply when the issue has not been triaged yet
needsTriageMilestone: 83,
# number of the milestone to apply when the issue is triaged
defaultMilestone: 82,
# arrays of labels that determine if an issue is triaged
triagedLabels:
-
- "type: bug/fix"
- "type: bug"
- "severity*"
- "freq*"
- "comp: *"

View File

@ -207,12 +207,6 @@ groups:
conditions:
files:
- "packages/forms/*"
- "aio/content/guide/forms.md"
- "aio/content/guide/form-validation.md"
- "aio/content/guide/reactive-forms.md"
- "aio/content/examples/forms/*"
- "aio/content/examples/form-validation/*"
- "aio/content/examples/reactive-forms/*"
users:
- kara #primary
- tinayuangao #secondary

View File

@ -1,69 +1,42 @@
<a name="6.0.0-beta.5"></a>
# [6.0.0-beta.5](https://github.com/angular/angular/compare/6.0.0-beta.4...6.0.0-beta.5) (2018-02-22)
<a name="5.2.9"></a>
## [5.2.9](https://github.com/angular/angular/compare/5.2.8...5.2.9) (2018-03-14)
### Bug Fixes
* **animations:** report correct totalTime value even during noOp animations ([#22225](https://github.com/angular/angular/issues/22225)) ([e1bf067](https://github.com/angular/angular/commit/e1bf067))
* **common:** correct mapping of Observable methods ([#20518](https://github.com/angular/angular/issues/20518)) ([2639b4b](https://github.com/angular/angular/commit/2639b4b)), closes [#20516](https://github.com/angular/angular/issues/20516)
* **common:** then and else template might be set to null ([#22298](https://github.com/angular/angular/issues/22298)) ([8115edc](https://github.com/angular/angular/commit/8115edc))
* **compiler-cli:** add missing entry point to package, update tsickle ([#22295](https://github.com/angular/angular/issues/22295)) ([28ac244](https://github.com/angular/angular/commit/28ac244))
* **core:** properly handle function without prototype in reflector ([#22284](https://github.com/angular/angular/issues/22284)) ([a7ebf5a](https://github.com/angular/angular/commit/a7ebf5a)), closes [#19978](https://github.com/angular/angular/issues/19978)
* **core:** require factory to be provided for shakeable InjectionToken ([#22207](https://github.com/angular/angular/issues/22207)) ([f755db7](https://github.com/angular/angular/commit/f755db7)), closes [#22205](https://github.com/angular/angular/issues/22205)
* **forms:** set state before emitting a value from ngModelChange ([#21514](https://github.com/angular/angular/issues/21514)) ([3e6a86f](https://github.com/angular/angular/commit/3e6a86f)), closes [#21513](https://github.com/angular/angular/issues/21513)
* **core:** set `preserveWhitespaces` to false by default ([#22046](https://github.com/angular/angular/issues/22046)) ([f1a0632](https://github.com/angular/angular/commit/f1a0632)), closes [#22027](https://github.com/angular/angular/issues/22027)
* **platform-server:** add styles to elements correctly ([#22527](https://github.com/angular/angular/issues/22527)) ([fc6dfc2](https://github.com/angular/angular/commit/fc6dfc2))
* **router:** correct over-encoding of URL fragment ([#22687](https://github.com/angular/angular/issues/22687)) ([86517f2](https://github.com/angular/angular/commit/86517f2))
### Features
* **common:** better error message when non-template element used in NgIf ([#22274](https://github.com/angular/angular/issues/22274)) ([67cf11d](https://github.com/angular/angular/commit/67cf11d)), closes [#16410](https://github.com/angular/angular/issues/16410)
* **compiler-cli:** Check unvalidated combination of ngc and TypeScript ([#22293](https://github.com/angular/angular/issues/22293)) ([3ceee99](https://github.com/angular/angular/commit/3ceee99)), closes [#20669](https://github.com/angular/angular/issues/20669)
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([5c89d6b](https://github.com/angular/angular/commit/5c89d6b)), closes [#21731](https://github.com/angular/angular/issues/21731)
* **platform-browser:** do not throw error when Hammer.js not loaded ([#22257](https://github.com/angular/angular/issues/22257)) ([991300b](https://github.com/angular/angular/commit/991300b)), closes [#16992](https://github.com/angular/angular/issues/16992)
* **platform-browser:** fix [#19604](https://github.com/angular/angular/issues/19604), can config hammerOptions ([#21979](https://github.com/angular/angular/issues/21979)) ([1d571b2](https://github.com/angular/angular/commit/1d571b2))
### BREAKING CHANGES
<a name="5.2.8"></a>
## [5.2.8](https://github.com/angular/angular/compare/5.2.7...5.2.8) (2018-03-07)
* **animations:** When animation is triggered within a disabled zone, the
associated event (which an instance of AnimationEvent) will no longer
report the totalTime as 0 (it will emit the actual time of the
animation). To detect if an animation event is reporting a disabled
animation then the `event.disabled` property can be used instead.
* **forms:** ngModelChange is now emitted after the value/validity is updated on its control.
### Bug Fixes
Previously, ngModelChange was emitted before its underlying control was updated.
This was fine if you passed through the value directly through the $event keyword, e.g.
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280)
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
```
<input [(ngModel)]="name" (ngModelChange)="onChange($event)">
onChange(value) {
console.log(value); // would log updated value
}
```
However, if you had a handler for the ngModelChange event that checked the value through the control,
you would get the old value rather than the updated value. e.g:
<a name="5.2.7"></a>
## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28)
```
<input #modelDir="ngModel" [(ngModel)]="name" (ngModelChange)="onChange(modelDir)">
onChange(ngModel: NgModel) {
console.log(ngModel.value); // would log old value, not updated value
}
```
### Bug Fixes
Now the value and validity will be updated before the ngModelChange event is emitted,
so the same setup will log the updated value.
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
```
onChange(ngModel: NgModel) {
console.log(ngModel.value); // will log updated value
}
```
We think this order will be less confusing when the control is checked directly.
You will only need to update your app if it has relied on this bug to keep track of the old control value.
If that is the case, you should be able to track the old value directly by saving it on your component.
<a name="5.2.6"></a>
## [5.2.6](https://github.com/angular/angular/compare/5.2.5...5.2.6) (2018-02-22)
@ -76,35 +49,6 @@ If that is the case, you should be able to track the old value directly by savin
* **core:** properly handle function without prototype in reflector ([#22284](https://github.com/angular/angular/issues/22284)) ([5ec38f2](https://github.com/angular/angular/commit/5ec38f2)), closes [#19978](https://github.com/angular/angular/issues/19978)
* **core:** support metadata reflection for native class types ([#22356](https://github.com/angular/angular/issues/22356)) ([ee91de9](https://github.com/angular/angular/commit/ee91de9)), closes [#21731](https://github.com/angular/angular/issues/21731)
<a name="6.0.0-beta.4"></a>
# [6.0.0-beta.4](https://github.com/angular/angular/compare/6.0.0-beta.3...6.0.0-beta.4) (2018-02-14)
### Bug Fixes
* **bazel:** allow TS to read ambient typings ([#21876](https://github.com/angular/angular/issues/21876)) ([b081dfe](https://github.com/angular/angular/commit/b081dfe)), closes [#21872](https://github.com/angular/angular/issues/21872)
* **bazel:** improve error message for missing assets ([#22096](https://github.com/angular/angular/issues/22096)) ([dcf64a0](https://github.com/angular/angular/commit/dcf64a0)), closes [#22095](https://github.com/angular/angular/issues/22095)
* **common:** add locale currency values ([#21783](https://github.com/angular/angular/issues/21783)) ([420cc7a](https://github.com/angular/angular/commit/420cc7a)), closes [#20385](https://github.com/angular/angular/issues/20385)
* **common:** round currencies based on decimal digits in `CurrencyPipe` ([#21783](https://github.com/angular/angular/issues/21783)) ([44154e7](https://github.com/angular/angular/commit/44154e7)), closes [#10189](https://github.com/angular/angular/issues/10189)
* **common:** weaken AsyncPipe transform signature ([#22169](https://github.com/angular/angular/issues/22169)) ([be59c3a](https://github.com/angular/angular/commit/be59c3a))
* **compiler:** make unary plus operator consistent to JavaScript ([#22154](https://github.com/angular/angular/issues/22154)) ([72f8abd](https://github.com/angular/angular/commit/72f8abd)), closes [#22089](https://github.com/angular/angular/issues/22089)
* **core:** add stacktrace in log when error during cleanup component in TestBed ([#22162](https://github.com/angular/angular/issues/22162)) ([16d1700](https://github.com/angular/angular/commit/16d1700))
* **core:** ensure initial value of QueryList length ([#21980](https://github.com/angular/angular/issues/21980)) ([#21982](https://github.com/angular/angular/issues/21982)) ([e56de10](https://github.com/angular/angular/commit/e56de10)), closes [#21980](https://github.com/angular/angular/issues/21980)
* **core:** use appropriate inert document strategy for Firefox & Safari ([#17019](https://github.com/angular/angular/issues/17019)) ([a751649](https://github.com/angular/angular/commit/a751649))
* **forms:** make Validators.email support optional controls ([#20869](https://github.com/angular/angular/issues/20869)) ([140e7c0](https://github.com/angular/angular/commit/140e7c0))
* **forms:** prevent event emission on enable/disable when emitEvent is false ([#12366](https://github.com/angular/angular/issues/12366)) ([#21018](https://github.com/angular/angular/issues/21018)) ([0bcfae7](https://github.com/angular/angular/commit/0bcfae7))
* **forms:** set state before emitting a value from ngModelChange ([#21514](https://github.com/angular/angular/issues/21514)) ([9744a1c](https://github.com/angular/angular/commit/9744a1c)), closes [#21513](https://github.com/angular/angular/issues/21513)
* **language-service:** correct instructions to install the language service ([#22000](https://github.com/angular/angular/issues/22000)) ([b37cee3](https://github.com/angular/angular/commit/b37cee3))
* **platform-browser:** add @Injectable where it was missing ([#22005](https://github.com/angular/angular/issues/22005)) ([0a1a397](https://github.com/angular/angular/commit/0a1a397))
* **platform-browser:** support 0/false/null values in transfer_state ([#22179](https://github.com/angular/angular/issues/22179)) ([6435ecd](https://github.com/angular/angular/commit/6435ecd))
### Features
* **bazel:** allow explicit specification of factories ([#22003](https://github.com/angular/angular/issues/22003)) ([e442881](https://github.com/angular/angular/commit/e442881))
* **compiler:** mark @NgModules in provider lists for identification at runtime ([#22005](https://github.com/angular/angular/issues/22005)) ([2d5e7d1](https://github.com/angular/angular/commit/2d5e7d1))
* **forms:** multiple validators for array method ([#20766](https://github.com/angular/angular/issues/20766)) ([941e88f](https://github.com/angular/angular/commit/941e88f)), closes [#20665](https://github.com/angular/angular/issues/20665)
* change @Injectable() to support tree-shakeable tokens ([#22005](https://github.com/angular/angular/issues/22005)) ([235a235](https://github.com/angular/angular/commit/235a235))
<a name="5.2.5"></a>
## [5.2.5](https://github.com/angular/angular/compare/5.2.4...5.2.5) (2018-02-14)
@ -122,33 +66,6 @@ If that is the case, you should be able to track the old value directly by savin
* **language-service:** correct instructions to install the language service ([#22000](https://github.com/angular/angular/issues/22000)) ([0b23573](https://github.com/angular/angular/commit/0b23573))
* **platform-browser:** support 0/false/null values in transfer_state ([#22179](https://github.com/angular/angular/issues/22179)) ([da6ab91](https://github.com/angular/angular/commit/da6ab91))
<a name="6.0.0-beta.3"></a>
# [6.0.0-beta.3](https://github.com/angular/angular/compare/6.0.0-beta.2...6.0.0-beta.3) (2018-02-07)
### Bug Fixes
* **common:** don't convert null to a string when flushing a mock request ([#21417](https://github.com/angular/angular/issues/21417)) ([8b14488](https://github.com/angular/angular/commit/8b14488)), closes [#20744](https://github.com/angular/angular/issues/20744)
* **core:** fix [#20582](https://github.com/angular/angular/issues/20582), don't need to wrap zone in location change listener ([#20640](https://github.com/angular/angular/issues/20640)) ([f791e9f](https://github.com/angular/angular/commit/f791e9f))
* **core:** fix proper propagation of subscriptions in EventEmitter ([#22016](https://github.com/angular/angular/issues/22016)) ([e81606c](https://github.com/angular/angular/commit/e81606c)), closes [#21999](https://github.com/angular/angular/issues/21999)
* **core:** should check Zone existance when scheduleMicroTask ([#20656](https://github.com/angular/angular/issues/20656)) ([3a86940](https://github.com/angular/angular/commit/3a86940))
* **forms:** publish missing types ([#19941](https://github.com/angular/angular/issues/19941)) ([2707012](https://github.com/angular/angular/commit/2707012))
* **ivy:** generate correct interpolations ([#21946](https://github.com/angular/angular/issues/21946)) ([3cc1d76](https://github.com/angular/angular/commit/3cc1d76))
* **ivy:** generate lifecycle pattern ([#21865](https://github.com/angular/angular/issues/21865)) ([f816666](https://github.com/angular/angular/commit/f816666))
* **ivy:** improve `bindV` perf and memory usage ([#21881](https://github.com/angular/angular/issues/21881)) ([0846784](https://github.com/angular/angular/commit/0846784))
* **ivy:** remove unnecessary parameter of NgOnChangesFeature ([#21879](https://github.com/angular/angular/issues/21879)) ([65cf1ad](https://github.com/angular/angular/commit/65cf1ad))
### Features
* **compiler-cli:** reflect static methods added to classes in metadata ([#21926](https://github.com/angular/angular/issues/21926)) ([eb8ddd2](https://github.com/angular/angular/commit/eb8ddd2))
* **ivy:** add canonical example of a pipe. ([#21834](https://github.com/angular/angular/issues/21834)) ([743d8bc](https://github.com/angular/angular/commit/743d8bc))
* **ivy:** add support for attributes on ng-content nodes ([#21935](https://github.com/angular/angular/issues/21935)) ([1aa2947](https://github.com/angular/angular/commit/1aa2947))
* **ivy:** memoize array literals in render3 ([#21973](https://github.com/angular/angular/issues/21973)) ([4d62be6](https://github.com/angular/angular/commit/4d62be6))
### Performance Improvements
* **ivy:** improve Uglify configuration in hello world integration test ([#21985](https://github.com/angular/angular/issues/21985)) ([7e51e52](https://github.com/angular/angular/commit/7e51e52))
@ -165,17 +82,6 @@ If that is the case, you should be able to track the old value directly by savin
<a name="6.0.0-beta.2"></a>
# [6.0.0-beta.2](https://github.com/angular/angular/compare/6.0.0-beta.1...6.0.0-beta.2) (2018-01-31)
### Features
* **router:** add navigationSource and restoredState to NavigationStart event ([#21728](https://github.com/angular/angular/issues/21728)) ([c40ae7f](https://github.com/angular/angular/commit/c40ae7f))
* **service-worker:** add helper script which will uninstall SW ([#21863](https://github.com/angular/angular/issues/21863)) ([b10540a](https://github.com/angular/angular/commit/b10540a))
<a name="5.2.3"></a>
## [5.2.3](https://github.com/angular/angular/compare/5.2.2...5.2.3) (2018-01-31)
@ -193,32 +99,6 @@ If that is the case, you should be able to track the old value directly by savin
<a name="6.0.0-beta.1"></a>
# [6.0.0-beta.1](https://github.com/angular/angular/compare/6.0.0-beta.0...6.0.0-beta.1) (2018-01-25)
### Bug Fixes
* **common:** A null value should remove the style on IE ([#21679](https://github.com/angular/angular/issues/21679)) ([7d49443](https://github.com/angular/angular/commit/7d49443)), closes [#21064](https://github.com/angular/angular/issues/21064)
* avoid triggering a cli bug ([#21611](https://github.com/angular/angular/issues/21611)) ([0eabd07](https://github.com/angular/angular/commit/0eabd07))
* **common:** don't remove special characters when extracting CLDR data ([#21626](https://github.com/angular/angular/issues/21626)) ([135a282](https://github.com/angular/angular/commit/135a282))
* **common:** extract plural function from i18n locale data files for TS 2.6 ([#21626](https://github.com/angular/angular/issues/21626)) ([97b18b2](https://github.com/angular/angular/commit/97b18b2)), closes [#21608](https://github.com/angular/angular/issues/21608)
* **common:** fallback to last defined value for named date and time formats ([#21299](https://github.com/angular/angular/issues/21299)) ([879756d](https://github.com/angular/angular/commit/879756d)), closes [#21282](https://github.com/angular/angular/issues/21282)
* **compiler:** add support for marker tags in xliff serializers ([#21250](https://github.com/angular/angular/issues/21250)) ([f74130c](https://github.com/angular/angular/commit/f74130c)), closes [#21078](https://github.com/angular/angular/issues/21078)
* **compiler:** Don't strip `/*# sourceURL ... */` ([#16088](https://github.com/angular/angular/issues/16088)) ([5f681f9](https://github.com/angular/angular/commit/5f681f9))
* **compiler:** fix ICU select messages to use male/female/other ([#21713](https://github.com/angular/angular/issues/21713)) ([cb5090c](https://github.com/angular/angular/commit/cb5090c))
* **compiler-cli:** do not fold errors past calls in the collector ([#21708](https://github.com/angular/angular/issues/21708)) ([dd86790](https://github.com/angular/angular/commit/dd86790))
* **compiler-cli:** do not lower expressions in non-modules ([#21649](https://github.com/angular/angular/issues/21649)) ([7f93aad](https://github.com/angular/angular/commit/7f93aad))
* **router:** don't use ParamsInheritanceStrategy in declarations ([#21574](https://github.com/angular/angular/issues/21574)) ([925e654](https://github.com/angular/angular/commit/925e654)), closes [#21456](https://github.com/angular/angular/issues/21456)
### Features
* **compiler:** implement "enableIvy" compiler option ([#21427](https://github.com/angular/angular/issues/21427)) ([64d16de](https://github.com/angular/angular/commit/64d16de))
* **core:** optional generic type for ElementRef ([#20765](https://github.com/angular/angular/issues/20765)) ([d3d9aac](https://github.com/angular/angular/commit/d3d9aac)), closes [#13139](https://github.com/angular/angular/issues/13139)
<a name="5.2.2"></a>
## [5.2.2](https://github.com/angular/angular/compare/5.2.1...5.2.2) (2018-01-25)
@ -238,36 +118,6 @@ If that is the case, you should be able to track the old value directly by savin
<a name="6.0.0-beta.0"></a>
# [6.0.0-beta.0](https://github.com/angular/angular/compare/5.2.0...6.0.0-beta.0) (2018-01-17)
### Bug Fixes
* **animations:** fix increment/decrement aliases example ([#18323](https://github.com/angular/angular/issues/18323)) ([d2aa8ac](https://github.com/angular/angular/commit/d2aa8ac))
* **benchpress:** should still support selenium_webdriver < 3.6.0 ([#21477](https://github.com/angular/angular/issues/21477)) ([9b84a32](https://github.com/angular/angular/commit/9b84a32))
* **common:** set correct timezone for ISO8601 dates in Safari ([#21506](https://github.com/angular/angular/issues/21506)) ([05208b8](https://github.com/angular/angular/commit/05208b8)), closes [#21491](https://github.com/angular/angular/issues/21491)
* **compiler:** cache external reference resolution ([#21359](https://github.com/angular/angular/issues/21359)) ([e3e2fc0](https://github.com/angular/angular/commit/e3e2fc0))
* **compiler:** make `.ngsummary.json` files idempotent ([#21448](https://github.com/angular/angular/issues/21448)) ([e64b1e9](https://github.com/angular/angular/commit/e64b1e9))
* **core:** fix chained http call ([#20924](https://github.com/angular/angular/issues/20924)) ([7e3f9a4](https://github.com/angular/angular/commit/7e3f9a4)), closes [#20921](https://github.com/angular/angular/issues/20921)
* **ivy:** Add workaround for AJD in google3 ([#21488](https://github.com/angular/angular/issues/21488)) ([6af3672](https://github.com/angular/angular/commit/6af3672))
* **language-service:** Clear caches when program changes ([#21337](https://github.com/angular/angular/issues/21337)) ([43e1520](https://github.com/angular/angular/commit/43e1520)), closes [#19405](https://github.com/angular/angular/issues/19405)
* **service-worker:** properly handle invalid hashes in all scenarios ([#21288](https://github.com/angular/angular/issues/21288)) ([3951098](https://github.com/angular/angular/commit/3951098))
### Features
* **bazel:** allow ng_module rules to control whether type checking is enabled ([#21460](https://github.com/angular/angular/issues/21460)) ([cffa0fe](https://github.com/angular/angular/commit/cffa0fe))
* **core:** add binding name to content changed error ([#20352](https://github.com/angular/angular/issues/20352)) ([d3bf54b](https://github.com/angular/angular/commit/d3bf54b))
* **forms:** handle string with and without line boundary on pattern validator ([#19256](https://github.com/angular/angular/issues/19256)) ([54bf179](https://github.com/angular/angular/commit/54bf179))
### Performance Improvements
* **ivy:** add missing dom element in render3_function tree benchmark ([#21476](https://github.com/angular/angular/issues/21476)) ([9b5a485](https://github.com/angular/angular/commit/9b5a485))
<a name="5.2.1"></a>
## [5.2.1](https://github.com/angular/angular/compare/5.2.0...5.2.1) (2018-01-17)

View File

@ -1,14 +1,10 @@
workspace(name = "angular")
# Using a pre-release snapshot to pick up a commit that makes all nodejs_binary
# programs produce source-mapped stack traces and uglify sourcemaps.
RULES_NODEJS_VERSION = "4303cbef12e5e252ad66cc35cff1123e3a44ee83"
http_archive(
name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/%s.zip" % RULES_NODEJS_VERSION,
strip_prefix = "rules_nodejs-%s" % RULES_NODEJS_VERSION,
sha256 = "fccb9a7122f339d89c9994dc0fea33c737dd76e66281d0da0cb841da5f1edec7",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip",
strip_prefix = "rules_nodejs-0.5.0",
sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
@ -16,13 +12,11 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_reposi
check_bazel_version("0.9.0")
node_repositories(package_json = ["//:package.json"])
RULES_TYPESCRIPT_VERSION = "d3cc5cd72d89aee0e4c2553ae1b99c707ecbef4e"
http_archive(
name = "build_bazel_rules_typescript",
url = "https://github.com/bazelbuild/rules_typescript/archive/%s.zip" % RULES_TYPESCRIPT_VERSION,
strip_prefix = "rules_typescript-%s" % RULES_TYPESCRIPT_VERSION,
sha256 = "a233fcca41c3e59f639ac71c396edb30e9e9716cf8ed5fb20b51ff8910d5d895",
url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.0.zip",
strip_prefix = "rules_typescript-0.11.0",
sha256 = "ce7bac7b5287d5162fcbe4f7c14ff507ae7d506ceb44626ad09f6b7e27d3260b",
)
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
@ -65,23 +59,3 @@ http_archive(
strip_prefix = "bazel-9755c72b48866ed034bd28aa033e9abd27431b1e",
sha256 = "5b8443fc3481b5fcd9e7f348e1dd93c1397f78b223623c39eb56494c55f41962",
)
# We have a source dependency on the Devkit repository, because it's built with
# Bazel.
# This allows us to edit sources and have the effect appear immediately without
# re-packaging or "npm link"ing.
# Even better, things like aspects will visit the entire graph including
# ts_library rules in the devkit repository.
http_archive(
name = "angular_devkit",
url = "https://github.com/angular/devkit/archive/v0.3.1.zip",
strip_prefix = "devkit-0.3.1",
sha256 = "31d4b597fe9336650acf13df053c1c84dcbe9c29c6a833bcac3819cd3fd8cad3",
)
http_archive(
name = "org_brotli",
url = "https://github.com/google/brotli/archive/v1.0.2.zip",
strip_prefix = "brotli-1.0.2",
sha256 = "b43d5d6bc40f2fa6c785b738d86c6bbe022732fe25196ebbe43b9653a025920d",
)

View File

@ -39,7 +39,7 @@
],
"e2e": {
"protractor": {
"config": "tests/e2e/protractor.conf.js"
"config": "./protractor.conf.js"
}
},
"lint": [
@ -50,12 +50,12 @@
"project": "src/tsconfig.spec.json"
},
{
"project": "tests/e2e/tsconfig.e2e.json"
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "src/karma.conf.js"
"config": "./karma.conf.js"
}
},
"defaults": {

View File

@ -1,20 +1,19 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{title}}!!
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular logo" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" href="http://angularjs.blogspot.ca/">Angular blog</a></h2>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>

View File

@ -1,7 +1,5 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
@ -20,13 +18,13 @@ describe('AppComponent', () => {
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
expect(app.title).toMatch(/app/i);
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!');
expect(compiled.querySelector('h1').textContent).toMatch(/app/i);
}));
});

View File

@ -11,6 +11,6 @@ import { Component } from '@angular/core';
// #enddocregion metadata
// #docregion title, class
export class AppComponent {
title = 'My First Angular App';
title = 'My First Angular App!';
}
// #enddocregion title, class

View File

@ -6,32 +6,38 @@ import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
import { AppComponent } from './app.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component'; // <-- #1 import component
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
// #enddocregion v1
// #docregion hero-service-list
// add JavaScript imports
import { HeroListComponent } from './hero-list/hero-list.component';
import { HeroService } from './hero.service'; // <-- #1 import service
import { HeroService } from './hero.service';
// #docregion v1
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule // <-- #2 add to @NgModule imports
],
declarations: [
AppComponent,
HeroDetailComponent,
// #enddocregion v1
HeroListComponent
HeroListComponent // <--declare HeroListComponent
// #docregion v1
],
// #enddocregion v1
exports: [ // export for the DemoModule
// #enddocregion hero-service-list
imports: [
BrowserModule,
ReactiveFormsModule // <-- #2 add to @NgModule imports
],
// #enddocregion v1
// export for the DemoModule
// #docregion hero-service-list
// ...
exports: [
AppComponent,
HeroDetailComponent,
HeroListComponent
HeroListComponent // <-- export HeroListComponent
],
providers: [ HeroService ], // <-- #4 provide HeroService
providers: [ HeroService ], // <-- provide HeroService
// #enddocregion hero-service-list
// #docregion v1
bootstrap: [ AppComponent ]
})

View File

@ -1,7 +1,7 @@
<!-- #docregion basic-form-->
<h2>Hero Detail</h2>
<h3><i>FormControl in a FormGroup</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">

View File

@ -1,7 +1,7 @@
<!-- #docregion basic-form-->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with a single FormControl using FormBuilder</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
@ -13,4 +13,4 @@
<!-- #docregion form-value-json -->
<p>Form value: {{ heroForm.value | json }}</p>
<p>Form status: {{ heroForm.status | json }}</p>
<!-- #enddocregion form-value-json -->
<!-- #enddocregion form-value-json -->

View File

@ -1,7 +1,7 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">

View File

@ -1,5 +1,5 @@
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">

View File

@ -1,7 +1,7 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>PatchValue to initialize a value</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">

View File

@ -44,7 +44,13 @@ export class HeroDetailComponent6 implements OnChanges {
}
// #docregion patch-value-on-changes
ngOnChanges() { // <-- wrap patchValue in ngOnChanges
ngOnChanges() { // <-- call rebuildForm in ngOnChanges
this.rebuildForm();
}
// #enddocregion patch-value-on-changes
// #docregion patch-value-rebuildform
rebuildForm() { // <-- wrap patchValue in rebuildForm
this.heroForm.reset();
// #docregion patch-value
this.heroForm.patchValue({
@ -52,7 +58,9 @@ export class HeroDetailComponent6 implements OnChanges {
});
// #enddocregion patch-value
}
// #enddocregion patch-value-on-changes
// #enddocregion patch-value-rebuildform
}
// #enddocregion v6

View File

@ -1,7 +1,7 @@
<!-- #docregion -->
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">

View File

@ -38,32 +38,31 @@ export class HeroDetailComponent7 implements OnChanges {
// #docregion ngOnChanges
ngOnChanges() {
this.rebuildForm();
}
// #enddocregion ngOnChanges
// #docregion rebuildForm
rebuildForm() {
this.heroForm.reset({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
}
// #enddocregion ngOnChanges
/* First version of ngOnChanges
// #docregion ngOnChanges-1
ngOnChanges()
// #enddocregion ngOnChanges-1
*/
ngOnChanges1() {
// #docregion reset
this.heroForm.reset();
// #enddocregion reset
// #docregion ngOnChanges-1
// #docregion set-value
this.heroForm.setValue({
name: this.hero.name,
// #docregion set-value-address
address: this.hero.addresses[0] || new Address()
// #enddocregion set-value-address
});
}
// #enddocregion rebuildForm
/* First version of rebuildForm */
rebuildForm1() {
// #docregion reset
this.heroForm.reset();
// #enddocregion reset
// #docregion set-value
this.heroForm.setValue({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
// #enddocregion set-value
}
// #enddocregion ngOnChanges-1
}

View File

@ -1,7 +1,7 @@
<!-- #docplaster-->
<h3><i>Using FormArray to add groups</i></h3>
<form [formGroup]="heroForm" novalidate>
<form [formGroup]="heroForm">
<p>Form Changed: {{ heroForm.dirty }}</p>
<div class="form-group">
@ -11,7 +11,9 @@
</div>
<!-- #docregion form-array-->
<!-- #docregion form-array-skeleton -->
<!-- #docregion form-array-name -->
<div formArrayName="secretLairs" class="well well-lg">
<!-- #enddocregion form-array-name -->
<div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
<!-- The repeated address template -->
<!-- #enddocregion form-array-skeleton -->

View File

@ -39,12 +39,18 @@ export class HeroDetailComponent8 implements OnChanges {
// #docregion onchanges
ngOnChanges() {
this.rebuildForm();
}
// #enddocregion onchanges
// #docregion rebuildform
rebuildForm() {
this.heroForm.reset({
name: this.hero.name
});
this.setAddresses(this.hero.addresses);
}
// #enddocregion onchanges
// #enddocregion rebuildform
// #docregion get-secret-lairs
get secretLairs(): FormArray {

View File

@ -1,11 +1,11 @@
<!-- #docplaster -->
<!-- #docregion -->
<!-- #docregion buttons -->
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()" novalidate>
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
<div style="margin-bottom: 1em">
<button type="submit"
[disabled]="heroForm.pristine" class="btn btn-success">Save</button> &nbsp;
<button type="reset" (click)="revert()"
<button type="button" (click)="revert()"
[disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
</div>

View File

@ -13,7 +13,10 @@ import { HeroService } from '../hero.service';
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
// #docregion onchanges-implementation
export class HeroDetailComponent implements OnChanges {
// #enddocregion onchanges-implementation
@Input() hero: Hero;
heroForm: FormGroup;
@ -42,6 +45,10 @@ export class HeroDetailComponent implements OnChanges {
}
ngOnChanges() {
this.rebuildForm();
}
rebuildForm() {
this.heroForm.reset({
name: this.hero.name
});
@ -66,7 +73,7 @@ export class HeroDetailComponent implements OnChanges {
onSubmit() {
this.hero = this.prepareSaveHero();
this.heroService.updateHero(this.hero).subscribe(/* error handling */);
this.ngOnChanges();
this.rebuildForm();
}
// #enddocregion on-submit
@ -92,7 +99,7 @@ export class HeroDetailComponent implements OnChanges {
// #enddocregion prepare-save-hero
// #docregion revert
revert() { this.ngOnChanges(); }
revert() { this.rebuildForm(); }
// #enddocregion revert
// #docregion log-name-change

View File

@ -197,20 +197,21 @@ function heroModuleSetup() {
// #docregion title-case-pipe
it('should convert hero name to Title Case', () => {
const inputName = 'quick BROWN fox';
const titleCaseName = 'Quick Brown Fox';
const { nameInput, nameDisplay } = page;
// get the name's input and display elements from the DOM
const hostElement = fixture.nativeElement;
const nameInput: HTMLInputElement = hostElement.querySelector('input');
const nameDisplay: HTMLElement = hostElement.querySelector('span');
// simulate user entering new name into the input box
nameInput.value = inputName;
// simulate user entering a new name into the input box
nameInput.value = 'quick BROWN fOx';
// dispatch a DOM event so that Angular learns of input value change.
nameInput.dispatchEvent(newEvent('input'));
// Tell Angular to update the output span through the title pipe
// Tell Angular to update the display binding through the title pipe
fixture.detectChanges();
expect(nameDisplay.textContent).toBe(titleCaseName);
expect(nameDisplay.textContent).toBe('Quick Brown Fox');
});
// #enddocregion title-case-pipe
// #enddocregion selected-tests

View File

@ -16,10 +16,8 @@ animation logic with the rest of your application code, for ease of control.
Angular animations are built on top of the standard [Web Animations API](https://w3c.github.io/web-animations/)
and run natively on [browsers that support it](http://caniuse.com/#feat=web-animation).
As of Angular 6, If the Web Animations API is not supported natively by the browser, then Angular will use CSS
keyframes as a fallback instead (automatically). This means that the polyfill is no longer required unless any
code uses [AnimationBuilder](/api/animations/AnimationBuilder). If your code does use AnimationBuilder, then
uncomment the `web-animations-js` polyfill from the `polyfills.ts` file generated by Angular CLI.
For other browsers, a polyfill is required. Uncomment the `web-animations-js` polyfill from the `polyfills.ts` file.
</div>
<div class="l-sub-section">

View File

@ -92,7 +92,7 @@ You can control your app compilation by providing template compiler options in t
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"preserveWhitespaces": true,
"preserveWhitespaces": false,
...
}
}
@ -234,7 +234,9 @@ done manually.
### *preserveWhitespaces*
This option tells the compiler whether to remove blank text nodes from compiled templates.
As of v6, this option is `false` by default, which results in smaller emitted template factory modules.
This option is `true` by default.
*Note*: It is recommended to set this explicitly to `false` as it emits smaller template factory modules and might be set to `false` by default in the future.
### *allowEmptyCodegenFiles*
@ -243,16 +245,6 @@ Tells the compiler to generate all the possible generated files even if they are
how `bazel` rules track file dependencies. It is not recommended to use this option outside of the `bazel`
rules.
### *enableIvy*
Tells the compiler to generate definitions using the Render3 style code generation. This option defaults to `false`.
Not all features are supported with this option enabled. It is only supported
for experimentation and testing of Render3 style code generation.
*Note*: Is it not recommended to use this option as it is not yet feature complete with the Render2 code generation.
## Angular Metadata and AOT
The Angular **AOT compiler** extracts and interprets **metadata** about the parts of the application that Angular is supposed to manage.

View File

@ -1,175 +0,0 @@
<div class="breadcrumb">
<a href="#">API<a> / <a href="#">@core<a>
</div>
<header class="api-header">
<h1><label class="api-status-label experimental">experimental</label><label class="api-type-label class">class</label>Class Name</h1>
</header>
<div class="page-actions">
<a href="#"><label class="raised page-label"><i class="material-icons">mode_edit</i>suggest edits</label></a>
<a href="#"><label class="raised page-label"><i class="material-icons">code</i>view source</label></a>
</div>
<p>Class description goes here. This is a short and to the point one or two sentence description that easily introduces the reader to the class.</p>
<div class="api-body">
<section>
<h2>Overview</h2>
<code-example language="ts" hidecopy="true" ng-version="5.2.0"><aio-code class="simple-code" ng-reflect-ng-class="[object Object]" ng-reflect-code="
class <a href=&quot;api/core/Compi" ng-reflect-hide-copy="true" ng-reflect-language="ts" ng-reflect-linenums="" ng-reflect-path="" ng-reflect-region="" ng-reflect-title=""><pre class="prettyprint lang-ts">
<code class="animated fadeIn"><span class="kwd">class</span><span class="pln"> </span><a href="api/core/Compiler" class="code-anchor"><span class="typ">Compiler</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#compileModuleSync"><span class="pln">compileModuleSync</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">moduleType</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;):</span><span class="pln"> </span><span class="typ">NgModuleFactory</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span></a><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#compileModuleAsync"><span class="pln">compileModuleAsync</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">moduleType</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;):</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">&lt;</span><span class="typ">NgModuleFactory</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&gt;</span></a><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#compileModuleAndAllComponentsSync"><span class="pln">compileModuleAndAllComponentsSync</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">moduleType</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;):</span><span class="pln"> </span><span class="typ">ModuleWithComponentFactories</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span></a><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#compileModuleAndAllComponentsAsync"><span class="pln">compileModuleAndAllComponentsAsync</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">moduleType</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;):</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">&lt;</span><span class="typ">ModuleWithComponentFactories</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&gt;</span></a><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#clearCache"><span class="pln">clearCache</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span></a><span class="pln">
</span><a class="code-anchor" href="api/core/Compiler#clearCacheFor"><span class="pln">clearCacheFor</span><span class="pun">(</span><span class="pln">type</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">&lt;</span><span class="pln">any</span><span class="pun">&gt;)</span></a><span class="pln">
</span><span class="pun">}</span></code>
</pre></aio-code></code-example>
</section>
<section>
<h2>Description</h2>
<p>The longer class description goes here which can include multiple paragraphs.</p>
</p>Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball. Ham hock picanha burgdoggen pork belly rump bacon cupim. Bacon kielbasa sirloin shank strip steak ground round. Bresaola cow salami meatloaf pork chop leberkas flank turducken biltong meatball chuck pork tri-tip chicken. Ribeye corned beef shoulder, meatloaf strip steak jerky porchetta capicola alcatra ham.</p>
<h3>Subclasses</h3>
<ul>
<li><a href="#">Subclass1</a></li>
<li><a href="#">Subclass2</a></li>
<li><a href="#">Subclass3</a></li>
</ul>
<h3>See Also</h3>
<ul>
<li><a href="#">Link1</a></li>
<li><a href="#">Link2</a></li>
</ul>
</section>
<section>
<h2>Constructor</h2>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}[],</span><span class="pln"> duration</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> easing</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> previousPlayers</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">[])</span></code>
</pre></aio-code></code-example>
</section>
<section>
<h2>Properties</h2>
<table class="is-full-width list-table">
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code><strong>Property1</strong></code>
</td>
<td><label class="property-type-label type">Type</label></td>
<td>Description goes here</td>
</tr>
<tr>
<td>
<code><strong>Property2</strong></code>
</td>
<td>Type</td>
<td>Description goes here</td>
</tr>
<tr>
<td>
<code><strong>Property3</strong></code>
</td>
<td>Type</td>
<td>Description goes here</td>
</tr>
</tbody>
</table>
</section>
<section class="api-method">
<h2>Methods</h2>
<table class="is-full-width item-table">
<thead>
<tr>
<th>Method1Name( )</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>Description goes here</p>
<br>
<p>Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball. Ham hock picanha burgdoggen pork belly rump bacon cupim. Bacon kielbasa sirloin shank strip steak ground round. Bresaola cow salami meatloaf pork chop leberkas flank turducken biltong meatball chuck pork tri-tip chicken. Ribeye corned beef shoulder, meatloaf strip steak jerky porchetta capicola alcatra ham.</p>
</td>
</tr>
</tbody>
</table>
<table class="is-full-width api-method item-table">
<thead>
<tr>
<th>Method2Name( )</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>Description goes here</p>
<hr>
<h5>Declaration</h5>
<code-example language="ts" hidecopy="true" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-ts">
<code class="animated fadeIn"><span class="kwd">class</span><span class="pln"> </span><a href="api/animations/AnimationBuilder" class="code-anchor"><span class="typ">AnimationBuilder</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln"></span><a class="code-anchor" href="api/animations/AnimationBuilder#build"><span class="pln">build</span><span class="pun">(</span><span class="pln">animation</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AnimationMetadata</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">AnimationMetadata</span><span class="pun">[]):</span><span class="pln"> </span><span class="typ">AnimationFactory</span></a><span class="pln"></span><span class="pun">}</span></code></pre>
</aio-code>
</code-example>
<h6>Parameters</h6>
<h6>Returns</h6>
<p>Returns information and results goes here.</p>
<h6>Errors</h6>
<p>Error information goes here</p>
<hr>
<p>Further details provided as needed. Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball.</p><hr>
<h6>Overloads</h6>
<table class="is-full-width">
<tbody>
<tr>
<td>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}[],</span><span class="pln"> duration</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> easing</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> previousPlayers</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">[])</span></code>
</pre></aio-code></code-example>
</td>
<td>Description goes here</td>
</tr>
<tr>
<td>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}[],</span><span class="pln"> duration</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> easing</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> previousPlayers</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">[])</span></code>
</pre></aio-code></code-example>
</td>
<td>Description goes here</td>
</tr>
</tbody>
</table>
<hr>
<h5>Example: Descriptive Title of Method Example</h5>
<p>Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball. Ham hock picanha burgdoggen pork belly rump bacon cupim. Bacon kielbasa sirloin shank strip steak ground round. Bresaola cow salami meatloaf pork chop leberkas flank turducken biltong meatball chuck pork tri-tip chicken. Ribeye corned beef shoulder, meatloaf strip steak jerky porchetta capicola alcatra ham.</p>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h2>Example: Descriptive Title of Combined Example Goes Here</h2>
<p>Intro description text about what the example is and how it can be used.</p>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}[],</span><span class="pln"> duration</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln"> easing</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> previousPlayers</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">[])</span></code>
</pre></aio-code></code-example>
<p>Further explanation provided as needed. Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball.</p>
</section>
</div>

View File

@ -133,8 +133,6 @@ But if you need an optional polyfill, you'll have to install its npm package.
For example, [if you need the web animations polyfill](http://caniuse.com/#feat=web-animation), you could install it with `npm`, using the following command (or the `yarn` equivalent):
<code-example language="sh" class="code-shell">
# note that the web-animations-js polyfill is only here as an example
# it isn't a strict requirement of Angular anymore (more below)
npm install --save web-animations-js
</code-example>
@ -228,8 +226,7 @@ These are the polyfills required to run an Angular application on each supported
Some features of Angular may require additional polyfills.
For example, the animations library relies on the standard web animation API, which is only available in Chrome and Firefox today.
(note that the dependency of web-animations-js in Angular is only necessary if `AnimationBuilder` is used.)
For example, the animations library relies on the standard web animation API, which is only available in Chrome and Firefox today. You'll need a polyfill to use animations in other browsers.
Here are the features which may require additional polyfills:
@ -279,8 +276,6 @@ Here are the features which may require additional polyfills:
<td>
[Animations](guide/animations)
<br>Only if `Animation Builder` is used within the application--standard
animation support in Angular doesn't require any polyfills (as of NG6).
</td>
@ -291,8 +286,7 @@ Here are the features which may require additional polyfills:
</td>
<td>
<p>If AnimationBuilder is used then the polyfill will enable scrubbing
support for IE/Edge and Safari (Chrome and Firefox support this natively).</p>
All but Chrome and Firefox<br>Not supported in IE9
</td>
</tr>

View File

@ -89,11 +89,11 @@ promise.then(() => {
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
<table>
<th>
<td>Operation</td>
<td>Observable</td>
<td>Promise</td>
</th>
<tr>
<th>Operation</th>
<th>Observable</th>
<th>Promise</th>
</tr>
<tr>
<td>Creation</td>
<td>
@ -141,10 +141,11 @@ Using observables to handle events and asynchronous operations can have the adva
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
<table>
<th>
<td>Observable</td>
<td>Events API</td>
</th>
<tr>
<th></th>
<th>Observable</th>
<th>Events API</th>
</tr>
<tr>
<td>Creation & cancellation</td>
<td>
@ -203,10 +204,11 @@ button.removeEventListener(click, handler);
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
<table>
<th>
<td>Observable</td>
<td>Array</td>
</th>
<tr>
<th></th>
<th>Observable</th>
<th>Array</th>
</tr>
<tr>
<td>Given</td>
<td>

View File

@ -126,7 +126,7 @@ This is the _root component_ and it is named `app-root`.
You can find it in `./src/app/app.component.ts`.
Open the component file and change the `title` property from _Welcome to app!!_ to _Welcome to My First Angular App!!_:
Open the component file and change the `title` property from `'app'` to `'My First Angular App!'`.
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>

File diff suppressed because it is too large Load Diff

View File

@ -290,42 +290,20 @@ out of date. Right click the Cache Storage title and refresh the caches.
Stopping and starting the service worker in the Service Worker
pane triggers a check for updates.
## Service Worker Safety
## Fail-safe
Like any complex system, bugs or broken configurations can cause
the Angular service worker to act in unforeseen ways. While its
design attempts to minimize the impact of such problems, the
Angular service worker contains several failsafe mechanisms in case
Angular service worker contains a failsafe mechanism in case
an administrator ever needs to deactivate the service worker quickly.
## Fail-safe
To deactivate the service worker, remove or rename the
`ngsw-config.json` file. When the service worker's request
for `ngsw.json` returns a `404`, then the service worker
removes all of its caches and de-registers itself,
essentially self-destructing.
### Safety Worker
Also included in the `@angular/service-worker` NPM package is a small
script `safety-worker.js`, which when loaded will unregister itself
from the browser. This script can be used as a last resort to get rid
of unwanted service workers already installed on client pages.
It's important to note that you cannot register this worker directly,
as old clients with cached state may not see a new `index.html` which
installs the different worker script. Instead, you must serve the
contents of `safety-worker.js` at the URL of the Service Worker script
you are trying to unregister, and must continue to do so until you are
certain all users have successfully unregistered the old worker. For
most sites, this means that you should serve the safety worker at the
old Service Worker URL forever.
This script can be used both to deactivate `@angular/service-worker`
as well as any other Service Workers which might have been served in
the past on your site.
## More on Angular service workers
You may also be interested in the following:

View File

@ -785,6 +785,25 @@ There is no harm in calling `detectChanges()` more often than is strictly necess
<hr>
{@a dispatch-event}
#### Change an input value with _dispatchEvent()_
To simulate user input, you can find the input element and set its `value` property.
You will call `fixture.detectChanges()` to trigger Angular's change detection.
But there is an essential, intermediate step.
Angular doesn't know that you set the input element's `value` property.
It won't read that property until you raise the element's `input` event by calling `dispatchEvent()`.
_Then_ you call `detectChanges()`.
The following example demonstrates the proper sequence.
<code-example path="testing/src/app/hero/hero-detail.component.spec.ts" region="title-case-pipe" title="app/hero/hero-detail.component.spec.ts (pipe test)"></code-example>
<hr>
### Component with external files
The `BannerComponent` above is defined with an _inline template_ and _inline css_, specified in the `@Component.template` and `@Component.styles` properties respectively.

View File

@ -210,10 +210,10 @@ You can get runtime information about the current platform and the `appId` by in
#### Absolute HTTP URLs
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `Http` module to fetch application data.
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data.
These services send requests to _relative_ URLs such as `api/heroes`.
In a Universal app, `Http` URLs must be _absolute_ (e.g., `https://my-server.com/api/heroes`)
In a Universal app, HTTP URLs must be _absolute_, for example, `https://my-server.com/api/heroes`
even when the Universal web server is capable of handling those requests.
You'll have to change the services to make requests with absolute URLs when running on the server
@ -416,7 +416,7 @@ Create a `tsconfig.server.json` file in the project root directory to configure
This config extends from the root's `tsconfig.json` file. Certain settings are noteworthy for their differences.
* The `module` property must be **commonjs** which can be require()'d into our server application.
* The `module` property must be **commonjs** which can be required into our server application.
* The `angularCompilerOptions` section guides the AOT compiler:
* `entryModule` - the root module of the server application, expressed as `path/to/file#ClassName`.

View File

@ -49,6 +49,12 @@
<td>Vienna</td>
<td>May 16-18, 2018</td>
</tr>
<!-- ngJapan-->
<tr>
<th><a href="https://ngjapan.org/en.html" title="ng-japan">ng-japan</a></th>
<td>Tokyo, Japan</td>
<td>Jun 16, 2018</td>
</tr>
<!-- AngularConnect-->
<tr>
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>

View File

@ -15,7 +15,7 @@ When youre done, users will be able to navigate the app like this:
</figure>
## Add the _AppRoutingModule_
## Add the `AppRoutingModule`
An Angular best practice is to load and configure the router in a separate, top-level module
that is dedicated to routing and imported by the root `AppModule`.
@ -138,7 +138,7 @@ You should see the familiar heroes master/detail view.
{@a routerlink}
## Add a navigation link (_routerLink_)
## Add a navigation link (`routerLink`)
Users shouldn't have to paste a route URL into the address bar.
They should be able to click a link to navigate.
@ -283,7 +283,7 @@ The user should be able to get to these details in three ways.
In this section, you'll enable navigation to the `HeroDetailsComponent`
and liberate it from the `HeroesComponent`.
### Delete _hero details_ from _HeroesComponent_
### Delete _hero details_ from `HeroesComponent`
When the user clicks a hero item in the `HeroesComponent`,
the app should navigate to the `HeroDetailComponent`,
@ -325,7 +325,7 @@ At this point, all application routes are in place.
title="src/app/app-routing.module.ts (all routes)">
</code-example>
### _DashboardComponent_ hero links
### `DashboardComponent` hero links
The `DashboardComponent` hero links do nothing at the moment.
@ -343,7 +343,7 @@ to insert the current interation's `hero.id` into each
[`routerLink`](#routerlink).
{@a heroes-component-links}
### _HeroesComponent_ hero links
### `HeroesComponent` hero links
The hero items in the `HeroesComponent` are `<li>` elements whose click events
are bound to the component's `onSelect()` method.
@ -446,7 +446,7 @@ The browser refreshes and the app crashes with a compiler error.
`HeroService` doesn't have a `getHero()` method.
Add it now.
### Add *HeroService.getHero()*
### Add `HeroService.getHero()`
Open `HeroService` and add this `getHero()` method
@ -518,7 +518,7 @@ Here are the code files discussed on this page and your app should look like thi
{@a approutingmodule}
{@a appmodule}
#### _AppRoutingModule_ and _AppModule_
#### _AppRoutingModule_, _AppModule_, and _HeroService_
<code-tabs>
<code-pane
@ -529,6 +529,10 @@ Here are the code files discussed on this page and your app should look like thi
title="src/app/app.module.ts"
path="toh-pt5/src/app/app.module.ts">
</code-pane>
<code-pane
title="src/app/hero.service.ts"
path="toh-pt5/src/app/hero.service.ts">
</code-pane>
</code-tabs>
{@a appcomponent}
@ -565,6 +569,7 @@ Here are the code files discussed on this page and your app should look like thi
{@a heroescomponent}
#### _HeroesComponent_
<code-tabs>
<code-pane
title="src/app/heroes/heroes.component.html" path="toh-pt5/src/app/heroes/heroes.component.html">

View File

@ -40,14 +40,4 @@ describe('Api pages', function() {
const page = new ApiPage('api/common/HashLocationStrategy');
expect(page.getOverview('class').getText()).toContain('path(includeHash: boolean = false): string');
});
it('should show a "Properties" section if there are public properties', () => {
const page = new ApiPage('api/core/ViewContainerRef');
expect(page.getSection('instance-properties').isPresent()).toBe(true);
});
it('should not show a "Properties" section if there are only internal properties', () => {
const page = new ApiPage('api/forms/FormControl');
expect(page.getSection('instance-properties').isPresent()).toBe(false);
});
});

View File

@ -24,15 +24,11 @@ export class ApiPage extends SitePage {
//
// and we want to be able to pull out the code elements from only the first level
// if `onlyDirect` is set to `true`.
const selector = `.descendants.${docType} ${onlyDirect ? '>' : ''} ul > li > code`;
const selector = `.descendants.${docType} ${onlyDirect ? '>' : ''} li > :not(ul) code`;
return element.all(by.css(selector)).map<string>(item => item && item.getText());
}
getOverview(docType) {
return element(by.css(`.${docType}-overview`));
}
getSection(cls) {
return element(by.css(`section.${cls}`));
}
}

View File

@ -107,7 +107,7 @@
"cross-spawn": "^5.1.0",
"css-selector-parser": "^1.3.0",
"dgeni": "^0.4.7",
"dgeni-packages": "^0.24.3",
"dgeni-packages": "^0.25.0",
"entities": "^1.1.1",
"eslint": "^3.19.0",
"eslint-plugin-jasmine": "^2.2.0",

View File

@ -6,7 +6,7 @@ const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./*.e2e-spec.ts'
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome',
@ -26,7 +26,7 @@ exports.config = {
},
beforeLaunch: function() {
require('ts-node').register({
project: 'tests/e2e/tsconfig.e2e.json'
project: 'e2e/tsconfig.e2e.json'
});
},
onPrepare() {

View File

@ -69,15 +69,20 @@ describe('DocumentService', () => {
it('should emit the not-found document if the document is not found on the server', () => {
let currentDocument: DocumentContents|undefined;
const notFoundDoc = { id: FILE_NOT_FOUND_ID, contents: '<h1>Page Not Found</h1>' };
const { docService } = getServices('missing/doc');
const { docService, logger } = getServices('missing/doc');
docService.currentDocument.subscribe(doc => currentDocument = doc);
// Initial request return 404.
httpMock.expectOne({}).flush(null, {status: 404, statusText: 'NOT FOUND'});
expect(logger.output.error).toEqual([
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`Document file not found at 'missing/doc'`);
// Subsequent request for not-found document.
logger.output.error = [];
httpMock.expectOne(CONTENT_URL_PREFIX + 'file-not-found.json').flush(notFoundDoc);
expect(logger.output.error).toEqual([]); // does not report repeate errors
expect(currentDocument).toEqual(notFoundDoc);
});
@ -102,12 +107,17 @@ describe('DocumentService', () => {
let latestDocument: DocumentContents|undefined;
const doc1 = { contents: 'doc 1' };
const doc2 = { contents: 'doc 2' };
const { docService, locationService } = getServices('initial/doc');
const { docService, locationService, logger } = getServices('initial/doc');
docService.currentDocument.subscribe(doc => latestDocument = doc);
httpMock.expectOne({}).flush(null, {status: 500, statusText: 'Server Error'});
expect(latestDocument!.id).toEqual(FETCHING_ERROR_ID);
expect(logger.output.error).toEqual([
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message)
.toEqual(`Error fetching document 'initial/doc': (Http failure response for generated/docs/initial/doc.json: 500 Server Error)`);
locationService.go('new/doc');
httpMock.expectOne({}).flush(doc1);

View File

@ -78,7 +78,7 @@ export class DocumentService {
private getFileNotFoundDoc(id: string): Observable<DocumentContents> {
if (id !== FILE_NOT_FOUND_ID) {
this.logger.error(`Document file not found at '${id}'`);
this.logger.error(new Error(`Document file not found at '${id}'`));
// using `getDocument` means that we can fetch the 404 doc contents from the server and cache it
return this.getDocument(FILE_NOT_FOUND_ID);
} else {
@ -90,7 +90,7 @@ export class DocumentService {
}
private getErrorDoc(id: string, error: HttpErrorResponse): Observable<DocumentContents> {
this.logger.error('Error fetching document', error);
this.logger.error(new Error(`Error fetching document '${id}': (${error.message})`));
this.cache.delete(id);
return Observable.of({
id: FETCHING_ERROR_ID,

View File

@ -66,7 +66,10 @@ describe('AnnouncementBarComponent', () => {
const request = httpMock.expectOne('generated/announcements.json');
request.flush('some random response');
expect(component.announcement).toBeUndefined();
expect(mockLogger.output.error[0][0]).toContain('generated/announcements.json contains invalid data:');
expect(mockLogger.output.error).toEqual([
[jasmine.any(Error)]
]);
expect(mockLogger.output.error[0][0].message).toMatch(/^generated\/announcements\.json contains invalid data:/);
});
it('should handle a failed request for `announcements.json`', () => {
@ -74,7 +77,10 @@ describe('AnnouncementBarComponent', () => {
const request = httpMock.expectOne('generated/announcements.json');
request.error(new ErrorEvent('404'));
expect(component.announcement).toBeUndefined();
expect(mockLogger.output.error[0][0]).toContain('generated/announcements.json request failed:');
expect(mockLogger.output.error).toEqual([
[jasmine.any(Error)]
]);
expect(mockLogger.output.error[0][0].message).toMatch(/^generated\/announcements\.json request failed:/);
});
});

View File

@ -59,12 +59,12 @@ export class AnnouncementBarComponent implements OnInit {
ngOnInit() {
this.http.get<Announcement[]>(announcementsPath)
.catch(error => {
this.logger.error(`${announcementsPath} request failed: ${error.message}`);
this.logger.error(new Error(`${announcementsPath} request failed: ${error.message}`));
return [];
})
.map(announcements => this.findCurrentAnnouncement(announcements))
.catch(error => {
this.logger.error(`${announcementsPath} contains invalid data: ${error.message}`);
this.logger.error(new Error(`${announcementsPath} contains invalid data: ${error.message}`));
return [];
})
.subscribe(announcement => this.announcement = announcement);

View File

@ -254,10 +254,14 @@ describe('CodeComponent', () => {
it('should display an error when copy fails', () => {
const snackBar: MatSnackBar = TestBed.get(MatSnackBar);
const copierService: CopierService = TestBed.get(CopierService);
const logger: TestLogger = TestBed.get(Logger);
spyOn(snackBar, 'open');
spyOn(copierService, 'copyText').and.returnValue(false);
getButton().click();
expect(snackBar.open).toHaveBeenCalledWith('Copy failed. Please try again!', '', { duration: 800 });
expect(logger.error).toHaveBeenCalledTimes(1);
expect(logger.error).toHaveBeenCalledWith(jasmine.any(Error));
expect(logger.error.calls.mostRecent().args[0].message).toMatch(/^ERROR copying code to clipboard:/);
});
});
});

View File

@ -148,7 +148,7 @@ export class CodeComponent implements OnChanges {
duration: 800,
});
} else {
this.logger.error('ERROR copying code to clipboard:', code);
this.logger.error(new Error(`ERROR copying code to clipboard: "${code}"`));
// failure snackbar alert
this.snackbar.open('Copy failed. Please try again!', '', {
duration: 800,

View File

@ -33,8 +33,8 @@ export class PrettyPrinter {
.then(
() => (window as any)['prettyPrintOne'],
err => {
const msg = 'Cannot get prettify.js from server';
this.logger.error(msg, err);
const msg = `Cannot get prettify.js from server: ${err.message}`;
this.logger.error(new Error(msg));
// return a pretty print fn that always fails.
return () => { throw new Error(msg); };
});

View File

@ -555,8 +555,9 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).not.toHaveBeenCalled();
expect(docViewer.nextViewContainer.innerHTML).toBe('');
expect(logger.output.error).toEqual([
[`[DocViewer] Error preparing document 'foo': ${error.stack}`],
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'foo': ${error.stack}`);
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'googlebot', content: 'noindex' });
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });
});
@ -576,8 +577,9 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).not.toHaveBeenCalled();
expect(docViewer.nextViewContainer.innerHTML).toBe('');
expect(logger.output.error).toEqual([
[`[DocViewer] Error preparing document 'bar': ${error.stack}`],
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'bar': ${error.stack}`);
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'googlebot', content: 'noindex' });
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });
});
@ -597,8 +599,9 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).not.toHaveBeenCalled();
expect(docViewer.nextViewContainer.innerHTML).toBe('');
expect(logger.output.error).toEqual([
[`[DocViewer] Error preparing document 'baz': ${error.stack}`],
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'baz': ${error.stack}`);
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'googlebot', content: 'noindex' });
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });
});
@ -618,8 +621,9 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).toHaveBeenCalledTimes(1);
expect(docViewer.nextViewContainer.innerHTML).toBe('');
expect(logger.output.error).toEqual([
[`[DocViewer] Error preparing document 'qux': ${error.stack}`],
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'qux': ${error.stack}`);
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'googlebot', content: 'noindex' });
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });
});
@ -636,8 +640,9 @@ describe('DocViewerComponent', () => {
expect(swapViewsSpy).toHaveBeenCalledTimes(1);
expect(docViewer.nextViewContainer.innerHTML).toBe('');
expect(logger.output.error).toEqual([
[`[DocViewer] Error preparing document 'qux': ${error}`],
[jasmine.any(Error)]
]);
expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'qux': ${error}`);
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'googlebot', content: 'noindex' });
expect(TestBed.get(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });
});

View File

@ -157,7 +157,7 @@ export class DocViewerComponent implements DoCheck, OnDestroy {
.do(() => this.docRendered.emit())
.catch(err => {
const errorMessage = (err instanceof Error) ? err.stack : err;
this.logger.error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`);
this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`));
this.nextViewContainer.innerHTML = '';
this.setNoIndex(true);
return this.void$;

View File

@ -34,8 +34,9 @@ describe('logger service', () => {
describe('error', () => {
it('should delegate to ErrorHandler', () => {
logger.error('param1', 'param2', 'param3');
expect(errorHandler.handleError).toHaveBeenCalledWith('param1 param2 param3');
const err = new Error('some error message');
logger.error(err);
expect(errorHandler.handleError).toHaveBeenCalledWith(err);
});
});
});

View File

@ -13,9 +13,8 @@ export class Logger {
}
}
error(value: any, ...rest: any[]) {
const message = [value, ...rest].join(' ');
this.errorHandler.handleError(message);
error(error: Error) {
this.errorHandler.handleError(error);
}
warn(value: any, ...rest: any[]) {

View File

@ -12,10 +12,16 @@ h1 {
font-size: 24px;
font-weight: 500;
margin: 8px 0px;
}
@media screen and (max-width: 600px) {
margin-top: 0;
}
h1:after {
content: "";
display: block;
height: 1px;
width: 40%;
margin: 24px 0px 10px;
background: $lightgray;
clear: both;
}
h2 {
@ -54,7 +60,13 @@ h6 {
clear: both;
}
h2, h3, h4, h5, h6 {
h1 {
@media screen and (max-width: 600px) {
margin: 0;
}
}
h1:after, h2, h3, h4, h5, h6 {
@media screen and (max-width: 600px) {
margin: 8px 0;
}
@ -131,13 +143,13 @@ th {
text-align: left;
}
p > code, li > code, td > code, th > code {
p > code, li > code, table code {
font-family: $code-font;
font-size: 85%;
color: $darkgray;
letter-spacing: 0;
line-height: 1;
padding: 2px 0;
padding: 2px 6px;
background-color: $backgroundgray;
border-radius: 4px;
}

View File

@ -16,7 +16,7 @@
text-transform: none;
padding: 8px 24px;
}
tbody {
pre {
white-space: normal;
@ -36,44 +36,34 @@
}
}
.api-body {
max-width: 1200px;
.api-header label {
border-radius: 4px;
padding: 4px 16px;
display: inline;
font-size: 14px;
color: white;
margin: 0 8px 0 16px;
font-weight: 500;
text-transform: uppercase;
@media screen and (max-width: 600px) {
display: block;
margin: 8px 0;
}
table {
&.api-status-label {
background-color: $mediumgray;
}
th {
text-transform: none;
font-size: 16px;
font-weight: bold;
}
&.api-type-label {
background-color: $accentblue;
tr {
border-bottom: 1px solid $lightgray;
}
td {
vertical-align: middle;
}
hr {
margin: 16px 0;
}
tr:last-child {
border-bottom: none;
}
&.item-table {
td {
padding: 32px;
@each $name, $symbol in $api-symbols {
&.#{$name} {
background: map-get($symbol, background);
}
}
&.list-table {
td {
padding: 16px 24px;
}
}
}
}

View File

@ -37,11 +37,3 @@ aio-shell.page-docs {
margin: 24px 0px;
background: $lightgray;
}
.page-actions {
display: flex;
flex-direction: column;
position: absolute;
top: 80px;
right: 24px;
}

View File

@ -20,6 +20,10 @@
transform: none;
}
h1:after {
content: none;
}
.hero-title {
display: inline-block;
font-size: 28px;

View File

@ -1,71 +1,23 @@
.api-body {
.api-info-bar {
max-width: 800px;
text-align: left;
.class-overview {
position: relative;
span {
margin: 0 16px 0 0;
code-example {
clear: left;
@media screen and (max-width: 600px) {
display: block;
}
}
.method-table {
h3 {
margin: 6px 0;
font-weight: bold;
}
h4 {
font-size: 14px;
font-weight: bold;
margin-top: 12px;
}
}
.api-heading {
padding: 5px 0;
font-size: 16px;
}
.properties-table {
font-size: 14px;
thead th {
&:nth-child(1) {
width: 20%;
}
&:nth-child(2) {
width: 20%;
}
}
}
.parameters-table {
margin-top: 0;
font-size: 14px;
td:nth-child(1) {
width: 20%;
}
}
details.overloads {
margin-left: -8px;
summary {
height: inherit;
padding: 8px 12px;
h4 {
margin: 0;
clear: left;
}
}
}
.api-section aio-code {
background-color: rgba(241, 241, 241, 0.2);
}
.from-constructor {
font-style: italic;
color: $blue;
}
.api-heading {
margin-top: 24px;
margin-bottom: 18px;
font-size: 16px;
}
.overloads .detail-contents {
padding-top: 0;
}

View File

@ -0,0 +1,25 @@
/* BANNER */
.info-banner {
margin: 16px 0;
justify-content: center;
background: $white;
border: 1px solid rgba($lightgray, 0.5);
border-radius: 4px;
box-sizing: border-box;
padding: 16px;
background: $white;
height: auto;
overflow: visible;
@media screen and (max-width: 600px) {
text-align: center;
}
p, .text-body {
color: $darkgray;
line-height: 32px;
margin: 0;
text-align: center;
}
}

View File

@ -69,7 +69,7 @@ code-tabs mat-tab-body-content .fadeIn {
aio-code pre {
display: flex;
min-height: 32px;
margin: 16px 24px;
margin: 16px 32px;
white-space: pre-wrap;
align-items: center;

View File

@ -25,13 +25,16 @@ summary {
display: none; // Remove the built in details marker in webkit
}
&::before {
&::after {
content: '\E5CE'; // See https://material.io/icons/#ic_expand_less
font-family: 'Material Icons';
font-size: 24px;
-webkit-font-smoothing: antialiased;
@include rotate(0deg); // We will rotate 180 degrees when details is open
float: right;
position: absolute;
top: 12px;
right: 22px;
}
}
@ -42,7 +45,7 @@ details {
padding: 16px 24px;
}
&[open] > summary::before {
&[open] > summary::after {
@include rotate(180deg); // Rotate the icon
}
}

View File

@ -1,18 +1,48 @@
.sidenav-content {
h1, h2, h3, h4, h5, h6 {
&.no-anchor .header-link {
display: none;
}
.header-link {
box-sizing: border-box;
color: $mediumgray;
margin-left: 8px;
display: inline-block;
margin-left: -42px;
padding: 0 8px;
text-decoration: none;
user-select: none;
vertical-align: middle;
visibility: hidden;
display: inline-block;
vertical-align: text-top;
width: 40px;
@media (max-width: 600px) {
float: right;
margin-left: 0;
}
}
&:hover .header-link {
visibility: visible;
}
}
.l-sub-section {
h1, h2, h3, h4, h5, h6 {
a {
padding-right: 64px;
margin-left: -74px;
}
}
}
.alert {
h1, h2, h3, h4, h5, h6 {
a {
padding-right: 80px;
margin-left: -90px;
}
}
}
}

View File

@ -1,55 +0,0 @@
label.raised, .api-header label {
border-radius: 4px;
padding: 4px 16px;
display: inline;
font-size: 14px;
color: white;
margin-right: 8px;
font-weight: 500;
text-transform: uppercase;
@media screen and (max-width: 600px) {
display: block;
margin: 8px 0;
}
&.page-label {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: $mist;
color: $mediumgray;
margin-bottom: 8px;
width: 140px;
.material-icons {
margin-right: 8px;
}
}
&.property-type-label {
font-size: 12px;
background-color: $darkgray;
color: $white;
text-transform: none;
}
}
.api-header label {
&.api-status-label {
background-color: $mediumgray;
}
&.api-type-label {
background-color: $accentblue;
@each $name, $symbol in $api-symbols {
&.#{$name} {
background: map-get($symbol, background);
}
}
}
}

View File

@ -5,6 +5,7 @@
@import 'alert';
@import 'api-pages';
@import 'api-list';
@import 'banner';
@import 'buttons';
@import 'callout';
@import 'card';
@ -29,4 +30,3 @@
@import 'select-menu';
@import 'deploy-theme';
@import 'notification';
@import 'label';

View File

@ -12,7 +12,7 @@ table {
table-layout: fixed;
}
thead > {
thead {
vertical-align: middle;
border-color: inherit;
@ -21,20 +21,20 @@ table {
border-color: inherit;
}
tr > th {
th {
background: rgba($lightgray, 0.2);
border-bottom: 1px solid $lightgray;
color: $darkgray;
font-size: 12px;
font-weight: 500;
padding: 8px 24px;
padding: 8px 32px;
text-align: left;
text-transform: uppercase;
line-height: 28px;
}
}
tbody > tr > {
tbody {
th,
td {
border-bottom: 1px solid $lightgray;
@ -70,7 +70,7 @@ table {
max-width: 100px;
}
&:last-child td {
tr:last-child td {
border: none;
@media (max-width: 480px) {

View File

@ -30,7 +30,7 @@
box-shadow: 0 2px 2px rgba(0,0,0,0.24), 0 0 2px rgba(0,0,0,0.12);
}
table > tbody > tr > th {
table tbody th{
border: 1px solid rgba(mat-color($foreground, secondary-text), .03);
}

View File

@ -1,14 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

View File

@ -14,8 +14,6 @@ const { API_SOURCE_PATH, API_TEMPLATES_PATH, requireFolder } = require('../confi
module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
// Register the processors
.processor(require('./processors/migrateLegacyJSDocTags'))
.processor(require('./processors/splitDescription'))
.processor(require('./processors/convertPrivateClassesToInterfaces'))
.processor(require('./processors/generateApiListDoc'))
.processor(require('./processors/addNotYetDocumentedProperty'))
@ -23,9 +21,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
.processor(require('./processors/extractDecoratedClasses'))
.processor(require('./processors/matchUpDirectiveDecorators'))
.processor(require('./processors/addMetadataAliases'))
.processor(require('./processors/computeApiBreadCrumbs'))
.processor(require('./processors/filterContainedDocs'))
.processor(require('./processors/processClassLikeMembers'))
.processor(require('./processors/markBarredODocsAsPrivate'))
.processor(require('./processors/filterPrivateDocs'))
.processor(require('./processors/computeSearchTitle'))
@ -90,12 +86,17 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
// Load up all the tag definitions in the tag-defs folder
parseTagsProcessor.tagDefinitions =
parseTagsProcessor.tagDefinitions.concat(getInjectables(requireFolder(__dirname, './tag-defs')));
// We actually don't want to parse param docs in this package as we are getting the data out using TS
// TODO: rewire the param docs to the params extracted from TS
parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
if (tagDef.name === 'param') {
tagDef.docProperty = 'paramData';
tagDef.transforms = [];
}
});
})
.config(function(splitDescription, EXPORT_DOC_TYPES) {
// Only split the description on the API docs
splitDescription.docTypes = EXPORT_DOC_TYPES;
})
.config(function(computePathsProcessor, EXPORT_DOC_TYPES, generateApiListDoc) {
@ -130,6 +131,6 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
]);
convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
autoLinkCode.docTypes = DOCS_TO_CONVERT;
autoLinkCode.docTypes = DOCS_TO_CONVERT.concat(['member']);
autoLinkCode.codeElements = ['code', 'code-example', 'code-pane'];
});

View File

@ -1,19 +0,0 @@
module.exports = function computeApiBreadCrumbs(EXPORT_DOC_TYPES) {
return {
$runAfter: ['paths-computed'],
$runBefore: ['rendering-docs'],
$process(docs) {
// Compute the breadcrumb for each doc by processing its containers
docs.forEach(doc => {
if (EXPORT_DOC_TYPES.indexOf(doc.docType) !== -1) {
doc.breadCrumbs = [
{ text: 'API', path: '/api' },
{ text: '@angular/' + doc.moduleDoc.id, path: doc.moduleDoc.path },
{ text: doc.name, path: doc.path }
];
}
});
}
};
};

View File

@ -1,39 +0,0 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./computeApiBreadCrumbs');
const Dgeni = require('dgeni');
describe('angular-api-package: computeApiBreadCrumbs processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('computeApiBreadCrumbs');
expect(processor.$process).toBeDefined();
expect(processor.$runAfter).toEqual(['paths-computed']);
expect(processor.$runBefore).toEqual(['rendering-docs']);
});
it('should attach a breadCrumbs property to each of the EXPORT_DOC_TYPES docs', () => {
const EXPORT_DOC_TYPES = ['class', 'interface'];
const processor = processorFactory(EXPORT_DOC_TYPES);
const docs = [
{ docType: 'class', name: 'ClassA', path: 'module-1/class-a', moduleDoc: { id: 'moduleOne', path: 'module-1' } },
{ docType: 'interface', name: 'InterfaceB', path: 'module-2/interface-b', moduleDoc: { id: 'moduleTwo', path: 'module-2' } },
{ docType: 'guide', name: 'Guide One', path: 'guide/guide-1' },
];
processor.$process(docs);
expect(docs[0].breadCrumbs).toEqual([
{ text: 'API', path: '/api' },
{ text: '@angular/moduleOne', path: 'module-1' },
{ text: 'ClassA', path: 'module-1/class-a' },
]);
expect(docs[1].breadCrumbs).toEqual([
{ text: 'API', path: '/api' },
{ text: '@angular/moduleTwo', path: 'module-2' },
{ text: 'InterfaceB', path: 'module-2/interface-b' },
]);
expect(docs[2].breadCrumbs).toBeUndefined();
});
});

View File

@ -1,36 +0,0 @@
module.exports = function migrateLegacyJSDocTags(log, createDocMessage) {
return {
$runAfter: ['tags-extracted'],
$runBefore: ['processing-docs'],
$process(docs) {
let migrated = false;
docs.forEach(doc => {
if (doc.howToUse) {
if (doc.usageNotes) {
throw new Error(createDocMessage('`@usageNotes` and the deprecated `@howToUse` are not allowed on the same doc', doc));
}
log.debug(createDocMessage('Using deprecated `@howToUse` tag as though it was `@usageNotes` tag', doc));
doc.usageNotes = doc.howToUse;
doc.howToUse = null;
migrated = true;
}
if (doc.whatItDoes) {
log.debug(createDocMessage('Merging the content of `@whatItDoes` tag into the description.', doc));
if (doc.description) {
doc.description = `${doc.whatItDoes}\n\n${doc.description}`;
} else {
doc.description = doc.whatItDoes;
}
doc.whatItDoes = null;
migrated = true;
}
});
if (migrated) {
log.warn('Some deprecated tags were migrated.');
log.warn('This automatic handling will be removed in a future version of the doc generation.\n');
}
}
};
};

View File

@ -1,66 +0,0 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./migrateLegacyJSDocTags');
const log = require('dgeni/lib/mocks/log')(false);
const createDocMessage = require('dgeni-packages/base/services/createDocMessage')();
const Dgeni = require('dgeni');
describe('migrateLegacyJSDocTags processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('migrateLegacyJSDocTags');
expect(processor.$process).toBeDefined();
});
it('should run before the correct processor', () => {
const processor = processorFactory(log, createDocMessage);
expect(processor.$runBefore).toEqual(['processing-docs']);
});
it('should run after the correct processor', () => {
const processor = processorFactory(log, createDocMessage);
expect(processor.$runAfter).toEqual(['tags-extracted']);
});
it('should migrate `howToUse` property to `usageNotes` property', () => {
const processor = processorFactory(log, createDocMessage);
const docs = [
{ howToUse: 'this is how to use it' }
];
processor.$process(docs);
expect(docs[0].howToUse).toBe(null);
expect(docs[0].usageNotes).toEqual('this is how to use it');
});
it('should migrate `whatItDoes` property to the `description`', () => {
const processor = processorFactory(log, createDocMessage);
const docs = [
{ whatItDoes: 'what it does' },
{ whatItDoes: 'what it does', description: 'the description' },
{ description: 'the description' }
];
processor.$process(docs);
expect(docs[0].whatItDoes).toBe(null);
expect(docs[0].description).toEqual('what it does');
expect(docs[1].whatItDoes).toBe(null);
expect(docs[1].description).toEqual('what it does\n\nthe description');
expect(docs[2].whatItDoes).toBeUndefined();
expect(docs[2].description).toEqual('the description');
});
it('should ignore docs that have neither `howToUse` nor `whatItDoes` properties', () => {
const processor = processorFactory(log, createDocMessage);
const docs = [
{ },
{ description: 'the description' }
];
processor.$process(docs);
expect(docs).toEqual([
{ },
{ description: 'the description' }
]);
});
});

View File

@ -1,59 +0,0 @@
/**
* A class like API doc contains members, but these can be either properties or method.
* Separate the members into two new collections: `doc.properties` and `doc.methods`.
*/
module.exports = function processClassLikeMembers() {
return {
$runAfter: ['filterContainedDocs'],
$runBefore: ['rendering-docs'],
$process(docs) {
docs.forEach(doc => {
if (doc.members) {
doc.properties = [];
doc.methods = [];
doc.members.forEach(member => {
if (isMethod(member)) {
doc.methods.push(member);
computeMemberDescription(member);
} else {
doc.properties.push(member);
if (!member.description) {
// Is this property defined as a constructor parameter e.g. `constructor(public property: string) { ... }`?
const constructorDoc = member.containerDoc.constructorDoc;
if (constructorDoc) {
const matchingParameterDoc = constructorDoc.parameterDocs.filter(doc => doc.declaration === member.declaration)[0];
member.constructorParamDoc = matchingParameterDoc;
}
}
}
});
}
if (doc.statics) {
doc.staticProperties = [];
doc.staticMethods = [];
doc.statics.forEach(member => {
if (isMethod(member)) {
doc.staticMethods.push(member);
computeMemberDescription(member);
} else {
doc.staticProperties.push(member);
}
});
}
});
}
};
};
function isMethod(doc) {
return doc.hasOwnProperty('parameters') && !doc.isGetAccessor && !doc.isSetAccessor;
}
function computeMemberDescription(member) {
if (!member.description && member.overloads) {
// Perhaps the description is on one of the overloads - take the first non-empty one
member.description = member.overloads.map(overload => overload.description).filter(description => !!description)[0];
}
}

View File

@ -1,81 +0,0 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./processClassLikeMembers');
const Dgeni = require('dgeni');
const property1 = { description: 'property 1' };
const property2 = { description: 'property 2' };
const getter1 = { parameters: [], isGetAccessor: true, description: 'getter 1' };
const setter1 = { parameters: [], isSetAccessor: true, description: 'setter 1' };
const method1 = { parameters: [] };
const method2 = { parameters: [] };
const method3 = { parameters: [] };
describe('angular-api-packge: processClassLikeMembers processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('processClassLikeMembers');
expect(processor.$process).toBeDefined();
expect(processor.$runAfter).toEqual(['filterContainedDocs']);
expect(processor.$runBefore).toEqual(['rendering-docs']);
});
it('should copy instance members into properties and methods', () => {
const processor = processorFactory();
const docs = [
{ members: [ property1, method1, getter1] },
{ members: [ method2, property2, method3, setter1] },
{ }
];
processor.$process(docs);
expect(docs[0].properties).toEqual([property1, getter1]);
expect(docs[0].methods).toEqual([method1]);
expect(docs[1].properties).toEqual([property2, setter1]);
expect(docs[1].methods).toEqual([method2, method3]);
expect(docs[2].properties).toBeUndefined();
expect(docs[2].methods).toBeUndefined();
});
it('should copy static members into properties and methods', () => {
const processor = processorFactory();
const docs = [
{ statics: [ property1, method1, getter1] },
{ statics: [ method2, property2, method3, setter1] },
{ }
];
processor.$process(docs);
expect(docs[0].staticProperties).toEqual([property1, getter1]);
expect(docs[0].staticMethods).toEqual([method1]);
expect(docs[1].staticProperties).toEqual([property2, setter1]);
expect(docs[1].staticMethods).toEqual([method2, method3]);
expect(docs[2].staticProperties).toBeUndefined();
expect(docs[2].staticMethods).toBeUndefined();
});
it('should wire up properties that are declared as parameters on the constructor to its associated parameter doc', () => {
const processor = processorFactory();
const propertyDeclaration = {};
const parameterDoc1 = { declaration: {} };
const parameterDoc2 = { declaration: propertyDeclaration };
const parameterDoc3 = { declaration: {} };
const property = {
declaration: propertyDeclaration,
containerDoc: {
constructorDoc: {
parameterDocs: [ parameterDoc1, parameterDoc2, parameterDoc3 ]
}
}
};
const docs = [{ members: [ property] }];
processor.$process(docs);
expect(property.constructorParamDoc).toEqual(parameterDoc2);
});
});

View File

@ -5,15 +5,21 @@
*/
module.exports = function simplifyMemberAnchors() {
return {
$runAfter: ['extra-docs-added'],
$runBefore: ['computing-paths'],
$runAfter: ['paths-computed'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
return docs.forEach(doc => {
if (doc.members) {
doc.members.forEach(member => member.anchor = computeAnchor(member));
doc.members.forEach(member => {
member.anchor = computeAnchor(member);
member.path = doc.path + '#' + member.anchor;
});
}
if (doc.statics) {
doc.statics.forEach(member => member.anchor = computeAnchor(member));
doc.statics.forEach(member => {
member.anchor = computeAnchor(member);
member.path = doc.path + '#' + member.anchor;
});
}
});
}

View File

@ -0,0 +1,72 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./simplifyMemberAnchors');
const Dgeni = require('dgeni');
describe('simplifyMemberAnchors processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('simplifyMemberAnchors');
expect(processor.$process).toBeDefined();
expect(processor.$runAfter).toEqual(['paths-computed']);
expect(processor.$runBefore).toEqual(['rendering-docs']);
});
describe('$process', () => {
describe('docs without members', () => {
it('should ignore the docs', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc' },
{ id: 'some-other' }
];
processor.$process(docs);
expect(docs).toEqual([
{ id: 'some-doc' },
{ id: 'some-other' }
]);
});
});
describe('docs with members', () => {
it('should compute an anchor for each instance member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].members.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);
});
it('should compute a path for each instance member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', path: 'a/b/c', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].members.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);
});
});
describe('docs with static members', () => {
it('should compute an anchor for each static member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].statics.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);
});
it('should compute a path for each static member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', path: 'a/b/c', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].statics.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);
});
});
});
});

View File

@ -1,28 +0,0 @@
/**
* Split the descripton (of selected docs) into:
* * `shortDescription`: the first paragraph
* * `description`: the rest of the paragraphs
*/
module.exports = function splitDescription() {
return {
$runAfter: ['tags-extracted', 'migrateLegacyJSDocTags'],
$runBefore: ['processing-docs'],
docTypes: [],
$process(docs) {
docs.forEach(doc => {
if (this.docTypes.indexOf(doc.docType) !== -1 && doc.description !== undefined) {
const description = doc.description.trim();
const endOfParagraph = description.search(/\n\s*\n/);
if (endOfParagraph === -1) {
doc.shortDescription = description;
doc.description = '';
} else {
doc.shortDescription = description.substr(0, endOfParagraph).trim();
doc.description = description.substr(endOfParagraph).trim();
}
}
});
}
};
};

View File

@ -1,71 +0,0 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./splitDescription');
const Dgeni = require('dgeni');
describe('splitDescription processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('splitDescription');
expect(processor.$process).toBeDefined();
});
it('should run before the correct processor', () => {
const processor = processorFactory();
expect(processor.$runBefore).toEqual(['processing-docs']);
});
it('should run after the correct processor', () => {
const processor = processorFactory();
expect(processor.$runAfter).toEqual(['tags-extracted', 'migrateLegacyJSDocTags']);
});
it('should split the `description` property into the first paragraph and other paragraphs', () => {
const processor = processorFactory();
processor.docTypes = ['test'];
const docs = [
{ docType: 'test' },
{ docType: 'test', description: '' },
{ docType: 'test', description: 'abc' },
{ docType: 'test', description: 'abc\n' },
{ docType: 'test', description: 'abc\n\n' },
{ docType: 'test', description: 'abc\ncde' },
{ docType: 'test', description: 'abc\ncde\n' },
{ docType: 'test', description: 'abc\n\ncde' },
{ docType: 'test', description: 'abc\n \ncde' },
{ docType: 'test', description: 'abc\n\n\ncde' },
{ docType: 'test', description: 'abc\n\ncde\nfgh' },
{ docType: 'test', description: 'abc\n\ncde\n\nfgh' },
];
processor.$process(docs);
expect(docs).toEqual([
{ docType: 'test' },
{ docType: 'test', shortDescription: '', description: '' },
{ docType: 'test', shortDescription: 'abc', description: '' },
{ docType: 'test', shortDescription: 'abc', description: '' },
{ docType: 'test', shortDescription: 'abc', description: '' },
{ docType: 'test', shortDescription: 'abc\ncde', description: '' },
{ docType: 'test', shortDescription: 'abc\ncde', description: '' },
{ docType: 'test', shortDescription: 'abc', description: 'cde' },
{ docType: 'test', shortDescription: 'abc', description: 'cde' },
{ docType: 'test', shortDescription: 'abc', description: 'cde' },
{ docType: 'test', shortDescription: 'abc', description: 'cde\nfgh' },
{ docType: 'test', shortDescription: 'abc', description: 'cde\n\nfgh' },
]);
});
it('should ignore docs that do not match the specified doc types', () => {
const processor = processorFactory();
processor.docTypes = ['test'];
const docs = [
{ docType: 'test', description: 'abc\n\ncde' },
{ docType: 'other', description: 'abc\n\ncde' }
];
processor.$process(docs);
expect(docs).toEqual([
{ docType: 'test', shortDescription: 'abc', description: 'cde' },
{ docType: 'other', description: 'abc\n\ncde' }
]);
});
});

View File

@ -1,10 +1,3 @@
module.exports = function(log, createDocMessage) {
return {
name: 'howToUse',
transforms(doc, tag, value) {
log.warn(createDocMessage('Deprecated `@howToUse` tag found', doc));
log.warn('PLEASE FIX by renaming to `@usageNotes.');
return value;
}
};
module.exports = function() {
return {name: 'howToUse'};
};

View File

@ -1,8 +0,0 @@
module.exports = function(extractTypeTransform, wholeTagTransform) {
return {
name: 'throws',
aliases: ['exception'],
multi: true,
transforms: [ extractTypeTransform, wholeTagTransform ]
};
};

View File

@ -1,5 +0,0 @@
module.exports = function() {
return {
name: 'usageNotes'
};
};

View File

@ -1,10 +1,3 @@
module.exports = function(log, createDocMessage) {
return {
name: 'whatItDoes',
transforms(doc, tag, value) {
log.warn(createDocMessage('Deprecated `@whatItDoes` tag found', doc));
log.warn('PLEASE FIX by adding the content of this tag as the first paragraph of the `@description` tag.');
return value;
}
};
module.exports = function() {
return {name: 'whatItDoes'};
};

View File

@ -45,7 +45,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {
parent.children.splice(index, 1, createLinkNode(docs[0], node.value));
} else {
// Parse the text for words that we can convert to links
const nodes = textContent(node).split(/([A-Za-z0-9_-]+)/)
const nodes = textContent(node).split(/([A-Za-z0-9_.-]+)/)
.filter(word => word.length)
.map((word, index, words) => {
// remove docs that fail the custom filter tests

View File

@ -9,7 +9,7 @@ describe('autoLinkCode post-processor', () => {
const dgeni = new Dgeni([testPackage]);
const injector = dgeni.configureInjector();
autoLinkCode = injector.get('autoLinkCode');
autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const'];
autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const', 'member'];
aliasMap = injector.get('aliasMap');
processor = injector.get('postProcessHtml');
processor.docTypes = ['test-doc'];
@ -31,6 +31,13 @@ describe('autoLinkCode post-processor', () => {
expect(doc.renderedContent).toEqual('<code><a href="a/b/myclass" class="code-anchor">foo.MyClass</a></code>');
});
it('should match code items within a block of code that contain a dot in their identifier', () => {
aliasMap.addDoc({ docType: 'member', id: 'MyEnum.Value', aliases: ['Value', 'MyEnum.Value'], path: 'a/b/myenum' });
const doc = { docType: 'test-doc', renderedContent: '<code>someFn(): MyEnum.Value</code>' };
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code>someFn(): <a href="a/b/myenum" class="code-anchor">MyEnum.Value</a></code>');
});
it('should ignore code items that do not match a link to an API doc', () => {
aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });
const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };

View File

@ -20,7 +20,7 @@ const hasClass = (node, cls) => {
const link = options =>
tree => visit(tree, node => {
if (is(node, HEADINGS) && has(node, 'id') && !hasClass(node, NO_ANCHOR_CLASS)) {
node.children.push({
node.children.unshift({
type: 'element',
tagName: 'a',
properties: Object.assign(clone(options.properties), {href: `#${node.properties.id}`}),

View File

@ -20,9 +20,9 @@ describe('autolink-headings postprocessor', () => {
<h3>Heading with encoded chars &#x26;</h3>
`;
const processedContent = `
<h1 id="heading-1">Heading 1<a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-1"><i class="material-icons">link</i></a></h1>
<h2 id="heading-with-bold">Heading with <strong>bold</strong><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-bold"><i class="material-icons">link</i></a></h2>
<h3 id="heading-with-encoded-chars-">Heading with encoded chars &#x26;<a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-encoded-chars-"><i class="material-icons">link</i></a></h3>
<h1 id="heading-1"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-1"><i class="material-icons">link</i></a>Heading 1</h1>
<h2 id="heading-with-bold"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-bold"><i class="material-icons">link</i></a>Heading with <strong>bold</strong></h2>
<h3 id="heading-with-encoded-chars-"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-encoded-chars-"><i class="material-icons">link</i></a>Heading with encoded chars &#x26;</h3>
`;
const docs = [{docType: 'a', renderedContent: originalContent}];

View File

@ -12,7 +12,6 @@ describe('authors-package (integration tests)', () => {
originalJasmineTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
});
afterAll(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = originalJasmineTimeout);
beforeEach(() => {

View File

@ -27,6 +27,7 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD
},
$process(docs) {
const exampleFolders = this.exampleFolders;
exampleFolders.forEach(folder => exampleMap[folder] = exampleMap[folder] || {});
const regionDocs = [];
docs = docs.filter((doc) => {
if (doc.docType === 'example-file') {
@ -36,7 +37,6 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD
if (doc.fileInfo.relativePath.indexOf(folder) === 0) {
const relativePath =
doc.fileInfo.relativePath.substr(folder.length).replace(/^\//, '');
exampleMap[folder] = exampleMap[folder] || {};
exampleMap[folder][relativePath] = doc;
// We treat files that end in `.annotated` specially

View File

@ -25,6 +25,12 @@ describe('collectExampleRegions processor', () => {
describe('$process', () => {
it('should initialise the `exampleMap` even if there are no examples to collect', () => {
processor.$process([]);
expect(exampleMap['examples-1']).toEqual(jasmine.any(Object));
expect(exampleMap['examples-2']).toEqual(jasmine.any(Object));
});
it('should identify example files that are in the exampleFolders', () => {
const docs = [
createDoc('A', 'examples-1/x/app.js'), createDoc('B', 'examples-1/y/index.html'),

View File

@ -8,15 +8,16 @@ module.exports =
.factory(require('./services/getAliases'))
.factory(require('./services/getDocFromAlias'))
.factory(require('./services/getLinkInfo'))
.factory(require('./services/moduleScopeLinkDisambiguator'))
.factory(require('./services/deprecatedDocsLinkDisambiguator'))
.factory(require('./services/disambiguators/disambiguateByDeprecated'))
.factory(require('./services/disambiguators/disambiguateByModule'))
.config(function(inlineTagProcessor, linkInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);
})
.config(function(
getLinkInfo, moduleScopeLinkDisambiguator, deprecatedDocsLinkDisambiguator) {
getLinkInfo.disambiguators.push(moduleScopeLinkDisambiguator);
getLinkInfo.disambiguators.push(deprecatedDocsLinkDisambiguator);
.config(function(getDocFromAlias, disambiguateByDeprecated, disambiguateByModule) {
getDocFromAlias.disambiguators = [
disambiguateByDeprecated,
disambiguateByModule
];
});

View File

@ -1,12 +0,0 @@
var _ = require('lodash');
module.exports = function deprecatedDocsLinkDisambiguator() {
return function(url, title, currentDoc, docs) {
if (docs.length != 2) return docs;
var filteredDocs = _.filter(
docs, function(doc) { return !doc.fileInfo.relativePath.match(/\/(\w+)-deprecated\//); });
return filteredDocs.length > 0 ? filteredDocs : docs;
};
};

View File

@ -0,0 +1,3 @@
module.exports = function disambiguateByDeprecated() {
return (alias, originatingDoc, docs) => docs.filter(doc => doc.deprecated === undefined);
};

View File

@ -0,0 +1,17 @@
const disambiguateByDeprecated = require('./disambiguateByDeprecated')();
const docs = [
{ id: 'doc1' },
{ id: 'doc2', deprecated: true },
{ id: 'doc3', deprecated: '' },
{ id: 'doc4' },
{ id: 'doc5', deprecated: 'Some text' },
];
describe('disambiguateByDeprecated', () => {
it('should filter out docs whose `deprecated` property is defined', () => {
expect(disambiguateByDeprecated('alias', {}, docs)).toEqual([
{ id: 'doc1' },
{ id: 'doc4' },
]);
});
});

View File

@ -0,0 +1,12 @@
module.exports = function disambiguateByModule() {
return (alias, originatingDoc, docs) => {
const originatingModule = originatingDoc && originatingDoc.moduleDoc;
if (originatingModule) {
const filteredDocs = docs.filter(doc => doc.moduleDoc === originatingModule);
if (filteredDocs.length > 0) {
return filteredDocs;
}
}
return docs;
};
};

View File

@ -0,0 +1,29 @@
const disambiguateByModule = require('./disambiguateByModule')();
const moduleA = { name: 'a' };
const moduleB = { name: 'b' };
const docs = [
{ id: 'doc1', moduleDoc: moduleA },
{ id: 'doc2', moduleDoc: moduleA },
{ id: 'doc3', moduleDoc: moduleB },
];
describe('disambiguateByModule', () => {
it('should return all docs if the originating doc has no moduleDoc', () => {
expect(disambiguateByModule('alias', { }, docs)).toEqual(docs);
});
it('should return all docs if no docs match the originating doc moduleDoc', () => {
expect(disambiguateByModule('alias', { moduleDoc: { name: 'c' } }, docs)).toEqual(docs);
});
it('should return only docs that match the moduleDoc of the originating doc', () => {
expect(disambiguateByModule('alias', { moduleDoc: moduleA }, docs)).toEqual([
{ id: 'doc1', moduleDoc: moduleA },
{ id: 'doc2', moduleDoc: moduleA },
]);
expect(disambiguateByModule('alias', { moduleDoc: moduleB }, docs)).toEqual([
{ id: 'doc3', moduleDoc: moduleB },
]);
});
});

View File

@ -1,31 +1,23 @@
var _ = require('lodash');
/**
* @dgService getDocFromAlias
* @description Get an array of docs that match this alias, relative to the originating doc.
*
* @property {Array<(alias: string, originatingDoc: Doc, ambiguousDocs: Doc[]) => Doc[]>} disambiguators
* a collection of functions that attempt to resolve ambiguous links. Each disambiguator returns
* a new collection of docs with unwanted ambiguous docs removed (see links-package/service/disambiguators
* for examples).
*/
module.exports = function getDocFromAlias(aliasMap) {
return function getDocFromAlias(alias, originatingDoc) {
var docs = aliasMap.getDocs(alias);
getDocFromAlias.disambiguators = [];
return getDocFromAlias;
// If there is more than one item with this name then try to filter them by the originatingDoc's
// area
if (docs.length > 1 && originatingDoc && originatingDoc.area) {
docs = _.filter(docs, function(doc) { return doc.area === originatingDoc.area; });
}
// If filtering by area left us with none then let's start again
if (docs.length === 0) {
docs = aliasMap.getDocs(alias);
}
// If there is more than one item with this name then try to filter them by the originatingDoc's
// module
if (docs.length > 1 && originatingDoc && originatingDoc.module) {
docs = _.filter(docs, function(doc) { return doc.module === originatingDoc.module; });
}
return docs;
};
function getDocFromAlias(alias, originatingDoc) {
return getDocFromAlias.disambiguators.reduce(
// Run the disambiguators while there is more than 1 doc found
(docs, disambiguater) => docs.length > 1 ? disambiguater(alias, originatingDoc, docs) : docs,
// Start with the docs that match the alias
aliasMap.getDocs(alias)
);
}
};

View File

@ -3,15 +3,15 @@ var Dgeni = require('dgeni');
var getDocFromAlias, aliasMap;
describe('getDocFromAlias', function() {
beforeEach(function() {
describe('getDocFromAlias', () => {
beforeEach(() => {
var dgeni = new Dgeni([testPackage('links-package', true)]);
var injector = dgeni.configureInjector();
aliasMap = injector.get('aliasMap');
getDocFromAlias = injector.get('getDocFromAlias');
});
it('should return an array of docs that match the alias', function() {
it('should return an array of docs that match the alias', () => {
var doc1 = {aliases: ['a', 'b', 'c']};
var doc2 = {aliases: ['a', 'b']};
var doc3 = {aliases: ['a']};
@ -24,25 +24,24 @@ describe('getDocFromAlias', function() {
expect(getDocFromAlias('c')).toEqual([doc1]);
});
it('should return docs that match the alias and originating doc\'s area', function() {
var doc1 = {aliases: ['a'], area: 'api'};
var doc2 = {aliases: ['a'], area: 'api'};
var doc3 = {aliases: ['a'], area: 'other'};
it('should filter ambiguous docs by calling each disambiguator', () => {
getDocFromAlias.disambiguators = [
(alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('X') !== -1), // only if X appears in name
(alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('Y') !== -1) // only if Y appears in name
];
var doc1 = {name: 'X', aliases: ['a', 'b', 'c']};
var doc2 = {name: 'Y', aliases: ['a', 'b']};
var doc3 = {name: 'XY', aliases: ['a', 'c']};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a', {area: 'api'})).toEqual([doc1, doc2]);
});
it('should return docs that match the alias and originating doc\'s area and module', function() {
var doc1 = {aliases: ['a'], area: 'api', module: 'ng'};
var doc2 = {aliases: ['a'], area: 'api', module: 'ngMock'};
var doc3 = {aliases: ['a'], area: 'other', module: 'ng'};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a', {area: 'api', module: 'ng'})).toEqual([doc1]);
// doc1 and doc2 get removed as they don't both have X and Y in name
expect(getDocFromAlias('a')).toEqual([doc3]);
// doc2 gets removed as it has no X; then we have only one doc left so second disambiguator never runs
expect(getDocFromAlias('b')).toEqual([doc1]);
// doc1 gets removed as it has no Y; then we have only one doc left (which would anyway pass 2nd disambiguator)
expect(getDocFromAlias('c')).toEqual([doc3]);
});
});

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