Compare commits
185 Commits
4.0.0-rc.4
...
4.0.3
Author | SHA1 | Date | |
---|---|---|---|
6ccb93728e | |||
b54a957ef4 | |||
21c14a79fa | |||
eed2d456d7 | |||
719c232321 | |||
bd033b69c1 | |||
5b92f7ee6d | |||
20ffb4196d | |||
11e6f45387 | |||
a30a73c2aa | |||
fb94c9937c | |||
b3259e26fe | |||
be406f8464 | |||
5cab3b146e | |||
eff6216319 | |||
88b2ab09ea | |||
5ad6d55a45 | |||
c81c7c0920 | |||
6f8e23b061 | |||
dc9711107d | |||
4c0c1e5fa0 | |||
06ef0908c7 | |||
a893d5e0a9 | |||
44afa5a03a | |||
0733f8d3e1 | |||
6604a4dc40 | |||
96c63a92e2 | |||
c444b1575f | |||
2b676192f6 | |||
14a2d1a6f7 | |||
61e089931f | |||
cbf30cb101 | |||
2f41b52e78 | |||
dcf60da16d | |||
9c9f409364 | |||
b44b983c1f | |||
978f80985c | |||
c10e50cf38 | |||
168a2eb5bf | |||
c9c7acd484 | |||
5b99533315 | |||
037805b741 | |||
0861fda69c | |||
feae7b6059 | |||
e4277a0869 | |||
1864ccb3dd | |||
6b79ab5abe | |||
53c12a84dc | |||
ca665303f4 | |||
0fe4985756 | |||
74087cb39d | |||
902bb2f026 | |||
23bf34853c | |||
8c4b963927 | |||
bfa4f70204 | |||
d481f6d150 | |||
fd6114561b | |||
c82851172e | |||
75478b2078 | |||
cdbb3dbd2a | |||
e72124c888 | |||
b8c0a97e35 | |||
5597fd3180 | |||
a88413f871 | |||
aa116524e6 | |||
4a5ad7ba30 | |||
d74e4d0633 | |||
a2c2b87aa3 | |||
8f4ea3e4b8 | |||
bf25e94f19 | |||
7983414e6a | |||
8248eba3e2 | |||
a65487528f | |||
426b3a19b7 | |||
2360676a7b | |||
ce3e03ff1a | |||
858c11cf7b | |||
95afaf495b | |||
d92930e975 | |||
c2892dada3 | |||
b2b1195534 | |||
e1b09e3bcc | |||
c65b75443e | |||
db0dca3fc1 | |||
7a715b2403 | |||
1ba296644d | |||
b800a0c824 | |||
0dda01e37c | |||
c8ab5cb0c5 | |||
92084f2b6a | |||
08f2f08d74 | |||
376088da70 | |||
73808dd38b | |||
ee03418b10 | |||
da700d1842 | |||
de87c47dd9 | |||
1060805a1f | |||
08d86751b9 | |||
9319b5f329 | |||
26f6bd4d3b | |||
edb2571a59 | |||
98cb974796 | |||
8b414222aa | |||
ea49a95bd9 | |||
a50d79df47 | |||
64285a2171 | |||
941f194a83 | |||
8b4edcc7ad | |||
c58499786c | |||
1bcbcfd56f | |||
90d2518d9a | |||
7354949763 | |||
5efc86069f | |||
97149f9424 | |||
bac265fdc2 | |||
e59e5e24b9 | |||
9e5d4781cb | |||
fc1f6efe0d | |||
c9710d4fb5 | |||
cf16f3b0dd | |||
a9e91115bf | |||
90f699fdcf | |||
fd7b855cfc | |||
20aab64c65 | |||
2eb027a793 | |||
b0a7bc77ee | |||
4e10faf1eb | |||
a0c6d44e18 | |||
9bc998c7a1 | |||
1a0c6d89b1 | |||
8c12374c4c | |||
45e2126273 | |||
41497b052d | |||
068cad1c1b | |||
31ef92fc36 | |||
b4081e3713 | |||
c8b4a33a7f | |||
a13ddf2e8a | |||
64beae9527 | |||
15a082c74e | |||
fbccd5cd38 | |||
1e8b132ade | |||
431eb309f3 | |||
8e6995c91e | |||
0759911431 | |||
1d7693c1e1 | |||
16e0423085 | |||
c2ffb6bfcd | |||
2489e4ba1b | |||
94da80148e | |||
764e90f9bb | |||
9bf2fb4a74 | |||
de3d2eeeba | |||
a805d00256 | |||
61135bc842 | |||
fa36ffda14 | |||
d3eda7a5b5 | |||
a755b715ed | |||
a9d5de0e56 | |||
f634c62cb3 | |||
f8c075ae27 | |||
aeb99645bb | |||
0d3e314df0 | |||
28ce68a13d | |||
80075afe8a | |||
bcc29ffdd1 | |||
0c43535ccc | |||
49829b4a4d | |||
5c5c2ae405 | |||
6e9264a79c | |||
a6fb78ee3c | |||
d0bc83ca27 | |||
b5b2fed54d | |||
4cef5dddc6 | |||
f92591054b | |||
2a0e55ffb5 | |||
9429032da1 | |||
791534f2f4 | |||
604546c287 | |||
c66437fc13 | |||
8415910375 | |||
5486e5417b | |||
2d78c8cc05 | |||
52bed7f9b3 | |||
7fb45283df |
4
.gitignore
vendored
4
.gitignore
vendored
@ -26,7 +26,3 @@ yarn-error.log
|
||||
|
||||
# rollup-test output
|
||||
/modules/rollup-test/dist/
|
||||
|
||||
# angular.io
|
||||
/aio/src/content/docs
|
||||
/aio/dist
|
||||
|
@ -21,6 +21,7 @@
|
||||
# vicb - Victor Berchet
|
||||
# vikerman - Vikram Subramanian
|
||||
# wardbell - Ward Bell
|
||||
# tinayuangao - Tina Gao
|
||||
|
||||
version: 2
|
||||
|
||||
@ -155,7 +156,7 @@ groups:
|
||||
- "packages/forms/*"
|
||||
users:
|
||||
- kara #primary
|
||||
# needs secondary
|
||||
- tinayuangao #secondary
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
|
||||
@ -175,7 +176,8 @@ groups:
|
||||
- "packages/language-service/*"
|
||||
users:
|
||||
- chuckjaz #primary
|
||||
# needs secondary
|
||||
- tbosch #secondary
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
|
||||
@ -184,8 +186,8 @@ groups:
|
||||
files:
|
||||
- "packages/router/*"
|
||||
users:
|
||||
- vicb #primary
|
||||
# needs secondary
|
||||
- jasonaden
|
||||
- vicb
|
||||
- IgorMinar #fallback
|
||||
- mhevery #fallback
|
||||
|
||||
|
@ -19,7 +19,7 @@ addons:
|
||||
- secure: "L7nrZwkAtFtYrP2DykPXgZvEKjkv0J/TwQ/r2QGxFTaBq4VZn+2Dw0YS7uCxoMqYzDwH0aAOqxoutibVpk8Z/16nE3tNmU5RzltMd6Xmt3qU2f/JDQLMo6PSlBodnjOUsDHJgmtrcbjhqrx/znA237BkNUu6UZRT7mxhXIZpn0U="
|
||||
branches:
|
||||
except:
|
||||
- g3_v2_0
|
||||
- g3
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
|
180
CHANGELOG.md
180
CHANGELOG.md
@ -1,3 +1,181 @@
|
||||
<a name="4.0.3"></a>
|
||||
## [4.0.3](https://github.com/angular/angular/compare/4.0.2...4.0.3) (2017-04-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **benchpress:** chrome - prevent trace buffer overflow ([d216f94](https://github.com/angular/angular/commit/d216f94))
|
||||
* **compiler:** fix build error in xliff2 ([1870347](https://github.com/angular/angular/commit/1870347))
|
||||
* **compiler:** ignore calls to unresolved symbols in metadata ([d4038ab](https://github.com/angular/angular/commit/d4038ab)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
||||
* **compiler:** ignore calls to unresolved symbols in metadata ([#15970](https://github.com/angular/angular/issues/15970)) ([db25f08](https://github.com/angular/angular/commit/db25f08)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
||||
* **compiler:** Inform user where Quoted error was thrown ([3184cc5](https://github.com/angular/angular/commit/3184cc5))
|
||||
* **compiler:** suppress another closure warning ([#16137](https://github.com/angular/angular/issues/16137)) ([72e240a](https://github.com/angular/angular/commit/72e240a))
|
||||
* **core:** benchmarks - enable ng1 benchmark again ([ccac4c6](https://github.com/angular/angular/commit/ccac4c6))
|
||||
* **core:** distribute externs for testability API ([#16179](https://github.com/angular/angular/issues/16179)) ([e377d9d](https://github.com/angular/angular/commit/e377d9d))
|
||||
* **core:** key-value differ changes iteration ([#15968](https://github.com/angular/angular/issues/15968)) ([a8600dc](https://github.com/angular/angular/commit/a8600dc)), closes [#14997](https://github.com/angular/angular/issues/14997)
|
||||
* **language-service:** only use canonical symbols ([786093a](https://github.com/angular/angular/commit/786093a))
|
||||
* **packaging:** increased buffer size ([#15840](https://github.com/angular/angular/issues/15840)) ([88ad490](https://github.com/angular/angular/commit/88ad490))
|
||||
* **platform-server:** handle innerText ([#15818](https://github.com/angular/angular/issues/15818)) ([7de340d](https://github.com/angular/angular/commit/7de340d))
|
||||
* **router:** prevent `RouterLinkActive` from causing an infinite CD loop ([4479c42](https://github.com/angular/angular/commit/4479c42)), closes [#15825](https://github.com/angular/angular/issues/15825)
|
||||
* **tsc-wrapped:** collect new expressions with no arguments ([#15908](https://github.com/angular/angular/issues/15908)) ([41cac9e](https://github.com/angular/angular/commit/41cac9e)), closes [#15906](https://github.com/angular/angular/issues/15906)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler:** Implement i18n XLIFF 2.0 serializer ([#14185](https://github.com/angular/angular/issues/14185)) ([a7d8edd](https://github.com/angular/angular/commit/a7d8edd)), closes [#11735](https://github.com/angular/angular/issues/11735)
|
||||
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([a75d056](https://github.com/angular/angular/commit/a75d056))
|
||||
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([4f172b0](https://github.com/angular/angular/commit/4f172b0))
|
||||
* **upgrade:** fixes for allow setting the angularjs lib at runtime ([bb6932d](https://github.com/angular/angular/commit/bb6932d))
|
||||
* add support for TS 2.3 ([5cf101f](https://github.com/angular/angular/commit/5cf101f))
|
||||
|
||||
|
||||
|
||||
<a name="4.1.0-beta.1"></a>
|
||||
# [4.1.0-beta.1](https://github.com/angular/angular/compare/4.1.0-beta.0...4.1.0-beta.1) (2017-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** fix inheritance for AOT with summaries ([#15583](https://github.com/angular/angular/issues/15583)) ([8ef621a](https://github.com/angular/angular/commit/8ef621a))
|
||||
* **language-service:** avoid throwing exceptions when reporting metadata errors ([7764c5c](https://github.com/angular/angular/commit/7764c5c))
|
||||
* **language-service:** detect when there isn't a tsconfig.json ([258d539](https://github.com/angular/angular/commit/258d539)), closes [#15874](https://github.com/angular/angular/issues/15874)
|
||||
* **language-service:** improve resilience to incomplete information ([71a8627](https://github.com/angular/angular/commit/71a8627))
|
||||
* **language-service:** initialize static reflector correctly ([fe0d02f](https://github.com/angular/angular/commit/fe0d02f)), closes [#15768](https://github.com/angular/angular/issues/15768)
|
||||
* **language-service:** parse extended i18n forms ([bde9771](https://github.com/angular/angular/commit/bde9771))
|
||||
* **language-service:** resolve any parameter types to any result ([5fbb0d0](https://github.com/angular/angular/commit/5fbb0d0))
|
||||
* **router:** fix query param parsing ([a487563](https://github.com/angular/angular/commit/a487563))
|
||||
* **router:** the preloader use the module from the loaded config ([6d12aa9](https://github.com/angular/angular/commit/6d12aa9))
|
||||
* **tsc-wrapped:** ensure valid path separators in metadata ([96aa236](https://github.com/angular/angular/commit/96aa236))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **animations:** Update types for TypeScript nullability support ([38d75d4](https://github.com/angular/angular/commit/38d75d4)), closes [#15870](https://github.com/angular/angular/issues/15870)
|
||||
* **benchpress:** Update types for TypeScript nullability support ([14669f2](https://github.com/angular/angular/commit/14669f2))
|
||||
* **common:** Update types for TypeScript nullability support ([d8b73e4](https://github.com/angular/angular/commit/d8b73e4))
|
||||
* **compiler:** Update types for TypeScript nullability support ([09d9f5f](https://github.com/angular/angular/commit/09d9f5f))
|
||||
* **language-service:** Update types for TypeScript nullability support ([540581d](https://github.com/angular/angular/commit/540581d))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.2"></a>
|
||||
## [4.0.2](https://github.com/angular/angular/compare/4.0.1...4.0.2) (2017-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** fix inheritance for AOT with summaries ([#15583](https://github.com/angular/angular/issues/15583)) ([1864ccb](https://github.com/angular/angular/commit/1864ccb))
|
||||
* **language-service:** avoid throwing exceptions when reporting metadata errors ([0861fda](https://github.com/angular/angular/commit/0861fda))
|
||||
* **language-service:** detect when there isn't a tsconfig.json ([168a2eb](https://github.com/angular/angular/commit/168a2eb)), closes [#15874](https://github.com/angular/angular/issues/15874)
|
||||
* **language-service:** improve resilience to incomplete information ([e4277a0](https://github.com/angular/angular/commit/e4277a0))
|
||||
* **language-service:** initialize static reflector correctly ([5b99533](https://github.com/angular/angular/commit/5b99533)), closes [#15768](https://github.com/angular/angular/issues/15768)
|
||||
* **language-service:** parse extended i18n forms ([c9c7acd](https://github.com/angular/angular/commit/c9c7acd))
|
||||
* **language-service:** resolve any parameter types to any result ([feae7b6](https://github.com/angular/angular/commit/feae7b6))
|
||||
* **router:** fix query param parsing ([2f41b52](https://github.com/angular/angular/commit/2f41b52))
|
||||
* **router:** the preloader use the module from the loaded config ([978f809](https://github.com/angular/angular/commit/978f809))
|
||||
* **tsc-wrapped:** ensure valid path separators in metadata ([c10e50c](https://github.com/angular/angular/commit/c10e50c))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.1"></a>
|
||||
## [4.0.1](https://github.com/angular/angular/compare/4.0.0...4.0.1) (2017-03-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** make sure style calculations are not computed too early ([#15540](https://github.com/angular/angular/issues/15540)) ([c828511](https://github.com/angular/angular/commit/c828511)), closes [#15507](https://github.com/angular/angular/issues/15507)
|
||||
* **compiler:** allow single quotes into named interpolations ([#15461](https://github.com/angular/angular/issues/15461)) ([a654875](https://github.com/angular/angular/commit/a654875)), closes [#15318](https://github.com/angular/angular/issues/15318)
|
||||
* **compiler:** ignore errors when evaluating base classes ([#15560](https://github.com/angular/angular/issues/15560)) ([a88413f](https://github.com/angular/angular/commit/a88413f)), closes [#15536](https://github.com/angular/angular/issues/15536)
|
||||
* **compiler:** throw when a component defines both template and templateUrl ([#15572](https://github.com/angular/angular/issues/15572)) ([902bb2f](https://github.com/angular/angular/commit/902bb2f)), closes [#15566](https://github.com/angular/angular/issues/15566)
|
||||
* **core:** check for undefined on normalizeDebugBindingValue ([#15503](https://github.com/angular/angular/issues/15503)) ([b8c0a97](https://github.com/angular/angular/commit/b8c0a97)), closes [#15494](https://github.com/angular/angular/issues/15494)
|
||||
* **core:** fix inheritance in JIT mode for TS 2.1 ([#15599](https://github.com/angular/angular/issues/15599)) ([ca66530](https://github.com/angular/angular/commit/ca66530)), closes [#15502](https://github.com/angular/angular/issues/15502)
|
||||
* **core:** fix the key/value differ ([#15539](https://github.com/angular/angular/issues/15539)) ([e72124c](https://github.com/angular/angular/commit/e72124c)), closes [#15457](https://github.com/angular/angular/issues/15457)
|
||||
* **core:** improve error msg for invalid KeyValueDiffer.diff arg ([#15489](https://github.com/angular/angular/issues/15489)) ([d74e4d0](https://github.com/angular/angular/commit/d74e4d0)), closes [#15402](https://github.com/angular/angular/issues/15402)
|
||||
* **core:** Update types for TypeScript nullability support ([#15472](https://github.com/angular/angular/issues/15472)) ([8c4b963](https://github.com/angular/angular/commit/8c4b963))
|
||||
* **language-service:** be resilient to invalidate ordering ([#15470](https://github.com/angular/angular/issues/15470)) ([a2c2b87](https://github.com/angular/angular/commit/a2c2b87)), closes [#15466](https://github.com/angular/angular/issues/15466)
|
||||
* **language-service:** correctly determine base members of types ([#15600](https://github.com/angular/angular/issues/15600)) ([0fe4985](https://github.com/angular/angular/commit/0fe4985)), closes [#15460](https://github.com/angular/angular/issues/15460)
|
||||
* **language-service:** don't require `reflect-metadata` module to be provided ([#15569](https://github.com/angular/angular/issues/15569)) ([bfa4f70](https://github.com/angular/angular/commit/bfa4f70)), closes [#15568](https://github.com/angular/angular/issues/15568)
|
||||
* **language-service:** guard access to `Symbol.members` ([#15529](https://github.com/angular/angular/issues/15529)) ([bf25e94](https://github.com/angular/angular/commit/bf25e94)), closes [#15528](https://github.com/angular/angular/issues/15528)
|
||||
* **language-service:** improve performance of `updateModuleAnalysis()` ([#15543](https://github.com/angular/angular/issues/15543)) ([5597fd3](https://github.com/angular/angular/commit/5597fd3))
|
||||
* **router:** should run CanActivate after CanDeactivate guards ([75478b2](https://github.com/angular/angular/commit/75478b2)), closes [#14059](https://github.com/angular/angular/issues/14059) [#15467](https://github.com/angular/angular/issues/15467)
|
||||
* **router:** shouldn't execute CanLoad when a route has been loaded ([2360676](https://github.com/angular/angular/commit/2360676)), closes [#14475](https://github.com/angular/angular/issues/14475) [#15438](https://github.com/angular/angular/issues/15438)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **router:** don't create new serializer every time UrlTree.toString is called ([#15565](https://github.com/angular/angular/issues/15565)) ([fd61145](https://github.com/angular/angular/commit/fd61145))
|
||||
|
||||
<a name="4.0.0"></a>
|
||||
# [4.0.0](https://github.com/angular/angular/compare/4.0.0-rc.6...4.0.0) invisible-makeover (2017-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** assume queries with no matches as static ([#15429](https://github.com/angular/angular/issues/15429)) ([c8ab5cb](https://github.com/angular/angular/commit/c8ab5cb)), closes [#15417](https://github.com/angular/angular/issues/15417)
|
||||
* **compiler:** correctly handle when `toString` is exported ([#15430](https://github.com/angular/angular/issues/15430)) ([0dda01e](https://github.com/angular/angular/commit/0dda01e)), closes [#15420](https://github.com/angular/angular/issues/15420)
|
||||
* **platform-browser:** setAttribute should work with xmlns namespace ([#14874](https://github.com/angular/angular/issues/14874)) ([92084f2](https://github.com/angular/angular/commit/92084f2)), closes [#14865](https://github.com/angular/angular/issues/14865)
|
||||
* **router:** should pass new data to Observable when query params change ([#15387](https://github.com/angular/angular/issues/15387)) ([08f2f08](https://github.com/angular/angular/commit/08f2f08)), closes [#15290](https://github.com/angular/angular/issues/15290)
|
||||
* prevent strictNullChecks support until [#15432](https://github.com/angular/angular/issues/15432) is fixed ([#15434](https://github.com/angular/angular/issues/15434)) ([b800a0c](https://github.com/angular/angular/commit/b800a0c))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.0-rc.6"></a>
|
||||
# [4.0.0-rc.6](https://github.com/angular/angular/compare/4.0.0-rc.5...4.0.0-rc.6) (2017-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** correct the main entry path in package.json ([#15300](https://github.com/angular/angular/issues/15300)) ([2489e4b](https://github.com/angular/angular/commit/2489e4b))
|
||||
* **animations:** ensure empty animate() steps work at the end of a sequence ([#15328](https://github.com/angular/angular/issues/15328)) ([fbccd5c](https://github.com/angular/angular/commit/fbccd5c)), closes [#15310](https://github.com/angular/angular/issues/15310)
|
||||
* **animations:** ensure enter/leave cancellations work ([#15323](https://github.com/angular/angular/issues/15323)) ([9bf2fb4](https://github.com/angular/angular/commit/9bf2fb4)), closes [#15315](https://github.com/angular/angular/issues/15315)
|
||||
* **animations:** make sure easing values work with web-animations ([#15195](https://github.com/angular/angular/issues/15195)) ([f925910](https://github.com/angular/angular/commit/f925910)), closes [#15115](https://github.com/angular/angular/issues/15115)
|
||||
* **animations:** make sure non-transitioned leave operations cancel existing animations ([#15254](https://github.com/angular/angular/issues/15254)) ([a6fb78e](https://github.com/angular/angular/commit/a6fb78e)), closes [#15213](https://github.com/angular/angular/issues/15213)
|
||||
* **animations:** only process element nodes through the animation engine ([#15268](https://github.com/angular/angular/issues/15268)) ([80075af](https://github.com/angular/angular/commit/80075af)), closes [#15267](https://github.com/angular/angular/issues/15267)
|
||||
* **animations:** only treat view removals as `void` state transitions ([#15245](https://github.com/angular/angular/issues/15245)) ([c66437f](https://github.com/angular/angular/commit/c66437f)), closes [#15223](https://github.com/angular/angular/issues/15223)
|
||||
* **animations:** stringify boolean values as `1` and `0` ([#15311](https://github.com/angular/angular/issues/15311)) ([94da801](https://github.com/angular/angular/commit/94da801)), closes [#15247](https://github.com/angular/angular/issues/15247)
|
||||
* **compiler:** add an empty content for source file of non mapped code. ([#15246](https://github.com/angular/angular/issues/15246)) ([8415910](https://github.com/angular/angular/commit/8415910))
|
||||
* **compiler:** don’t call `check` if we don’t need to ([#15322](https://github.com/angular/angular/issues/15322)) ([764e90f](https://github.com/angular/angular/commit/764e90f))
|
||||
* **compiler:** look for flat module resources using declaration module path ([#15367](https://github.com/angular/angular/issues/15367)) ([90d2518](https://github.com/angular/angular/commit/90d2518)), closes [#15221](https://github.com/angular/angular/issues/15221)
|
||||
* **compiler:** only log template deprecation warning once ([#15364](https://github.com/angular/angular/issues/15364)) ([08d8675](https://github.com/angular/angular/commit/08d8675))
|
||||
* **compiler:** use attribute id to merge translations ([#15302](https://github.com/angular/angular/issues/15302)) ([1d7693c](https://github.com/angular/angular/commit/1d7693c)), closes [#15234](https://github.com/angular/angular/issues/15234)
|
||||
* **compiler-cli:** adding missing format xliff for the extractor ([#15386](https://github.com/angular/angular/issues/15386)) ([a50d79d](https://github.com/angular/angular/commit/a50d79d))
|
||||
* **core:** allow tree shaking of component factories and styles ([#15214](https://github.com/angular/angular/issues/15214)) ([2a0e55f](https://github.com/angular/angular/commit/2a0e55f)), closes [#15181](https://github.com/angular/angular/issues/15181)
|
||||
* **core:** don’t create a comment for components with empty template. ([#15260](https://github.com/angular/angular/issues/15260)) ([f8c075a](https://github.com/angular/angular/commit/f8c075a)), closes [#15143](https://github.com/angular/angular/issues/15143)
|
||||
* **core:** mark components for check when host events trigger. ([#15359](https://github.com/angular/angular/issues/15359)) ([64beae9](https://github.com/angular/angular/commit/64beae9)), closes [#15352](https://github.com/angular/angular/issues/15352)
|
||||
* **core:** only apply `WrappedValue` to the binding of the pipe ([#15257](https://github.com/angular/angular/issues/15257)) ([0c43535](https://github.com/angular/angular/commit/0c43535)), closes [#15116](https://github.com/angular/angular/issues/15116)
|
||||
* **core:** provide `NgModuleRef` in `ViewContainerRef.createComponent`. ([#15350](https://github.com/angular/angular/issues/15350)) ([431eb30](https://github.com/angular/angular/commit/431eb30)), closes [#15241](https://github.com/angular/angular/issues/15241)
|
||||
* **core:** stringify shouldn't throw when toString returns null/undefined ([#14975](https://github.com/angular/angular/issues/14975)) ([8e6995c](https://github.com/angular/angular/commit/8e6995c)), closes [#14948](https://github.com/angular/angular/issues/14948)
|
||||
* **core:** trigger host animations for elements that are removed. ([#15251](https://github.com/angular/angular/issues/15251)) ([0d3e314](https://github.com/angular/angular/commit/0d3e314)), closes [#14813](https://github.com/angular/angular/issues/14813) [#15193](https://github.com/angular/angular/issues/15193)
|
||||
* **core:** update peer dep on zone.js to ^0.8.5 ([#15365](https://github.com/angular/angular/issues/15365)) ([97149f9](https://github.com/angular/angular/commit/97149f9)), closes [#15185](https://github.com/angular/angular/issues/15185)
|
||||
* **forms:** make composition event buffering configurable ([#15256](https://github.com/angular/angular/issues/15256)) ([5efc860](https://github.com/angular/angular/commit/5efc860)), closes [#15079](https://github.com/angular/angular/issues/15079)
|
||||
* **platform-server:** interpret Native view encapsulation as Emulated on the server ([#15155](https://github.com/angular/angular/issues/15155)) ([de3d2ee](https://github.com/angular/angular/commit/de3d2ee))
|
||||
* **platform-server:** setup NoopAnimationsModule in ServerModule by default ([#15131](https://github.com/angular/angular/issues/15131)) ([5c5c2ae](https://github.com/angular/angular/commit/5c5c2ae)), closes [#15098](https://github.com/angular/angular/issues/15098) [#14784](https://github.com/angular/angular/issues/14784)
|
||||
* **platform-server:** throw a better error message for relative URLs ([#15357](https://github.com/angular/angular/issues/15357)) ([15a082c](https://github.com/angular/angular/commit/15a082c)), closes [#15349](https://github.com/angular/angular/issues/15349)
|
||||
* **tsc-wrapped:** emit flat module format correctly on Windows ([#15215](https://github.com/angular/angular/issues/15215)) ([6e9264a](https://github.com/angular/angular/commit/6e9264a)), closes [#15192](https://github.com/angular/angular/issues/15192)
|
||||
* **tsc-wrapped:** use windows friendly path normalization in bundler ([#15374](https://github.com/angular/angular/issues/15374)) ([c584997](https://github.com/angular/angular/commit/c584997)), closes [#15289](https://github.com/angular/angular/issues/15289)
|
||||
* **upgrade:** component injectors should not link the module injector tree ([#15385](https://github.com/angular/angular/issues/15385)) ([ea49a95](https://github.com/angular/angular/commit/ea49a95))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** expose `inputs`, `outputs` and `ngContentSelectors` on `ComponentFactory`. ([#15214](https://github.com/angular/angular/issues/15214)) ([791534f](https://github.com/angular/angular/commit/791534f))
|
||||
* **router:** add `ParamMap.keys` to get a list of parameters ([d3eda7a](https://github.com/angular/angular/commit/d3eda7a))
|
||||
* **router:** introduce `ParamMap` to access parameters ([a755b71](https://github.com/angular/angular/commit/a755b71))
|
||||
* **tsc-wrapped:** record original location of flattened symbols ([#15367](https://github.com/angular/angular/issues/15367)) ([7354949](https://github.com/angular/angular/commit/7354949))
|
||||
* **upgrade:** use `ComponentFactory.inputs/outputs/ngContentSelectors` ([#15214](https://github.com/angular/angular/issues/15214)) ([9429032](https://github.com/angular/angular/commit/9429032))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.0-rc.5"></a>
|
||||
# [4.0.0-rc.5](https://github.com/angular/angular/compare/4.0.0-rc.4...4.0.0-rc.5) (2017-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** update the tsc-wrapped dependency version ([#15226](https://github.com/angular/angular/issues/15226)) ([7fb4528](https://github.com/angular/angular/commit/7fb4528))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.0-rc.4"></a>
|
||||
# [4.0.0-rc.4](https://github.com/angular/angular/compare/4.0.0-rc.3...4.0.0-rc.4) (2017-03-17)
|
||||
|
||||
@ -67,7 +245,7 @@
|
||||
Also, providers that are used by a directive / pipe / ngModule stay eager.
|
||||
So the impact should be rather small.
|
||||
|
||||
* DebugNode.source no longer returns the source location of a node.
|
||||
* DebugNode.source no longer returns the source location of a node.
|
||||
|
||||
Closes 14013
|
||||
|
||||
|
@ -147,7 +147,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
||||
* All public API methods **must be documented**. (Details TBC).
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||
**100 characters**. An automated formatter is available, see
|
||||
[DEVELOPER.md](DEVELOPER.md#clang-format).
|
||||
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
## <a name="commit"></a> Commit Message Guidelines
|
||||
|
||||
@ -263,7 +263,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[dev-doc]: https://github.com/angular/angular/blob/master/DEVELOPER.md
|
||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||
[github]: https://github.com/angular/angular
|
||||
[gitter]: https://gitter.im/angular/angular
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
|
11
aio/.gitignore
vendored
Normal file
11
aio/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Ignore node_modules
|
||||
node_modules
|
||||
|
||||
# Ignore npm/yarn debug log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Ignore generated content
|
||||
/dist
|
||||
/src/content
|
||||
/.sass-cache
|
@ -1,18 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Bootstrapping
|
||||
@cheatsheetIndex 0
|
||||
@description
|
||||
{@target ts}`import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';`{@endtarget}
|
||||
{@target js}Available from the `ng.platformBrowserDynamic` namespace{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`platformBrowserDynamic().bootstrapModule(AppModule);`|`platformBrowserDynamic().bootstrapModule`
|
||||
syntax(js):
|
||||
`document.addEventListener('DOMContentLoaded', function() {
|
||||
ng.platformBrowserDynamic
|
||||
.platformBrowserDynamic()
|
||||
.bootstrapModule(app.AppModule);
|
||||
});`|`platformBrowserDynamic().bootstrapModule`
|
||||
description:
|
||||
Bootstraps the app, using the root component from the specified `NgModule`. {@target js}Must be wrapped in the event listener to fire when the page loads.{@endtarget}
|
@ -1,34 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Built-in directives
|
||||
@cheatsheetIndex 3
|
||||
@description
|
||||
{@target ts}`import { CommonModule } from '@angular/common';`{@endtarget}
|
||||
{@target js}Available using the `ng.common.CommonModule` module{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<section *ngIf="showSection">`|`*ngIf`
|
||||
description:
|
||||
Removes or recreates a portion of the DOM tree based on the `showSection` expression.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<li *ngFor="let item of list">`|`*ngFor`
|
||||
description:
|
||||
Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div [ngSwitch]="conditionExpression">
|
||||
<ng-template [ngSwitchCase]="case1Exp">...</ng-template>
|
||||
<ng-template ngSwitchCase="case2LiteralString">...</ng-template>
|
||||
<ng-template ngSwitchDefault>...</ng-template>
|
||||
</div>`|`[ngSwitch]`|`[ngSwitchCase]`|`ngSwitchCase`|`ngSwitchDefault`
|
||||
description:
|
||||
Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of `conditionExpression`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div [ngClass]="{active: isActive, disabled: isDisabled}">`|`[ngClass]`
|
||||
description:
|
||||
Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.
|
@ -1,49 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Class decorators
|
||||
@cheatsheetIndex 5
|
||||
@description
|
||||
{@target ts}`import { Directive, ... } from '@angular/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Component({...})
|
||||
class MyComponent() {}`|`@Component({...})`
|
||||
syntax(js):
|
||||
`var MyComponent = ng.core.Component({...}).Class({...})`|`ng.core.Component({...})`
|
||||
description:
|
||||
Declares that a class is a component and provides metadata about the component.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Directive({...})
|
||||
class MyDirective() {}`|`@Directive({...})`
|
||||
syntax(js):
|
||||
`var MyDirective = ng.core.Directive({...}).Class({...})`|`ng.core.Directive({...})`
|
||||
description:
|
||||
Declares that a class is a directive and provides metadata about the directive.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Pipe({...})
|
||||
class MyPipe() {}`|`@Pipe({...})`
|
||||
syntax(js):
|
||||
`var MyPipe = ng.core.Pipe({...}).Class({...})`|`ng.core.Pipe({...})`
|
||||
description:
|
||||
Declares that a class is a pipe and provides metadata about the pipe.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Injectable()
|
||||
class MyService() {}`|`@Injectable()`
|
||||
syntax(js):
|
||||
`var OtherService = ng.core.Class(
|
||||
{constructor: function() { }});
|
||||
var MyService = ng.core.Class(
|
||||
{constructor: [OtherService, function(otherService) { }]});`|`var MyService = ng.core.Class({constructor: [OtherService, function(otherService) { }]});`
|
||||
description:
|
||||
{@target ts}Declares that a class has dependencies that should be injected into the constructor when the dependency injector is creating an instance of this class.
|
||||
{@endtarget}
|
||||
{@target js}
|
||||
Declares a service to inject into a class by providing an array with the services, with the final item being the function to receive the injected services.
|
||||
{@endtarget}
|
@ -1,38 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Component configuration
|
||||
@cheatsheetIndex 7
|
||||
@description
|
||||
{@target js}`ng.core.Component` extends `ng.core.Directive`,
|
||||
so the `ng.core.Directive` configuration applies to components as well{@endtarget}
|
||||
{@target ts}`@Component` extends `@Directive`,
|
||||
so the `@Directive` configuration applies to components as well{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`moduleId: module.id`|`moduleId:`
|
||||
description:
|
||||
If set, the `templateUrl` and `styleUrl` are resolved relative to the component.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
|
||||
syntax(js):
|
||||
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
|
||||
description:
|
||||
List of dependency injection providers scoped to this component's view.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`template: 'Hello {{name}}'
|
||||
templateUrl: 'my-component.html'`|`template:`|`templateUrl:`
|
||||
description:
|
||||
Inline template or external template URL of the component's view.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`styles: ['.primary {color: red}']
|
||||
styleUrls: ['my-component.css']`|`styles:`|`styleUrls:`
|
||||
description:
|
||||
List of inline CSS styles or external stylesheet URLs for styling the component’s view.
|
@ -1,30 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Dependency injection configuration
|
||||
@cheatsheetIndex 10
|
||||
@description
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
|
||||
syntax(js):
|
||||
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
|
||||
description:
|
||||
Sets or overrides the provider for `MyService` to the `MyMockService` class.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
|
||||
syntax(js):
|
||||
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
|
||||
description:
|
||||
Sets or overrides the provider for `MyService` to the `myFactory` factory function.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
|
||||
syntax(js):
|
||||
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
|
||||
description:
|
||||
Sets or overrides the provider for `MyValue` to the value `41`.
|
@ -1,86 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Class field decorators for directives and components
|
||||
@cheatsheetIndex 8
|
||||
@description
|
||||
{@target ts}`import { Input, ... } from '@angular/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Input() myProperty;`|`@Input()`
|
||||
syntax(js):
|
||||
`ng.core.Input(myProperty, myComponent);`|`ng.core.Input(`|`);`
|
||||
description:
|
||||
Declares an input property that you can update via property binding (example:
|
||||
`<my-cmp [myProperty]="someExpression">`).
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@Output() myEvent = new EventEmitter();`|`@Output()`
|
||||
syntax(js):
|
||||
`myEvent = new ng.core.EventEmitter();
|
||||
ng.core.Output(myEvent, myComponent);`|`ng.core.Output(`|`);`
|
||||
description:
|
||||
Declares an output property that fires events that you can subscribe to with an event binding (example: `<my-cmp (myEvent)="doSomething()">`).
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@HostBinding('class.valid') isValid;`|`@HostBinding('class.valid')`
|
||||
syntax(js):
|
||||
`ng.core.HostBinding('class.valid',
|
||||
'isValid', myComponent);`|`ng.core.HostBinding('class.valid', 'isValid'`|`);`
|
||||
description:
|
||||
Binds a host element property (here, the CSS class `valid`) to a directive/component property (`isValid`).
|
||||
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@HostListener('click', ['$event']) onClick(e) {...}`|`@HostListener('click', ['$event'])`
|
||||
syntax(js):
|
||||
`ng.core.HostListener('click',
|
||||
['$event'], onClick(e) {...}, myComponent);`|`ng.core.HostListener('click', ['$event'], onClick(e)`|`);`
|
||||
description:
|
||||
Subscribes to a host element event (`click`) with a directive/component method (`onClick`), optionally passing an argument (`$event`).
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@ContentChild(myPredicate) myChildComponent;`|`@ContentChild(myPredicate)`
|
||||
syntax(js):
|
||||
`ng.core.ContentChild(myPredicate,
|
||||
'myChildComponent', myComponent);`|`ng.core.ContentChild(myPredicate,`|`);`
|
||||
description:
|
||||
Binds the first result of the component content query (`myPredicate`) to a property (`myChildComponent`) of the class.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@ContentChildren(myPredicate) myChildComponents;`|`@ContentChildren(myPredicate)`
|
||||
syntax(js):
|
||||
`ng.core.ContentChildren(myPredicate,
|
||||
'myChildComponents', myComponent);`|`ng.core.ContentChildren(myPredicate,`|`);`
|
||||
description:
|
||||
Binds the results of the component content query (`myPredicate`) to a property (`myChildComponents`) of the class.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@ViewChild(myPredicate) myChildComponent;`|`@ViewChild(myPredicate)`
|
||||
syntax(js):
|
||||
`ng.core.ViewChild(myPredicate,
|
||||
'myChildComponent', myComponent);`|`ng.core.ViewChild(myPredicate,`|`);`
|
||||
description:
|
||||
Binds the first result of the component view query (`myPredicate`) to a property (`myChildComponent`) of the class. Not available for directives.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@ViewChildren(myPredicate) myChildComponents;`|`@ViewChildren(myPredicate)`
|
||||
syntax(js):
|
||||
`ng.core.ViewChildren(myPredicate,
|
||||
'myChildComponents', myComponent);`|`ng.core.ViewChildren(myPredicate,`|`);`
|
||||
description:
|
||||
Binds the results of the component view query (`myPredicate`) to a property (`myChildComponents`) of the class. Not available for directives.
|
@ -1,23 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Directive configuration
|
||||
@cheatsheetIndex 6
|
||||
@description
|
||||
{@target ts}`@Directive({ property1: value1, ... })`{@endtarget}
|
||||
{@target js}`ng.core.Directive({ property1: value1, ... }).Class({...})`{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`selector: '.cool-button:not(a)'`|`selector:`
|
||||
description:
|
||||
Specifies a CSS selector that identifies this directive within a template. Supported selectors include `element`,
|
||||
`[attribute]`, `.class`, and `:not()`.
|
||||
|
||||
Does not support parent-child relationship selectors.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`providers: [MyService, { provide: ... }]`|`providers:`
|
||||
syntax(js):
|
||||
`providers: [MyService, { provide: ... }]`|`providers:`
|
||||
description:
|
||||
List of dependency injection providers for this directive and its children.
|
@ -1,12 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Forms
|
||||
@cheatsheetIndex 4
|
||||
@description
|
||||
{@target ts}`import { FormsModule } from '@angular/forms';`{@endtarget}
|
||||
{@target js}Available using the `ng.forms.FormsModule` module{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<input [(ngModel)]="userName">`|`[(ngModel)]`
|
||||
description:
|
||||
Provides two-way data-binding, parsing, and validation for form controls.
|
@ -1,86 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Directive and component change detection and lifecycle hooks
|
||||
@cheatsheetIndex 9
|
||||
@description
|
||||
{@target ts}(implemented as class methods){@endtarget}
|
||||
{@target js}(implemented as component properties){@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`constructor(myService: MyService, ...) { ... }`|`constructor(myService: MyService, ...)`
|
||||
syntax(js):
|
||||
`constructor: function(MyService, ...) { ... }`|`constructor: function(MyService, ...)`
|
||||
description:
|
||||
Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngOnChanges(changeRecord) { ... }`|`ngOnChanges(changeRecord)`
|
||||
syntax(js):
|
||||
`ngOnChanges: function(changeRecord) { ... }`|`ngOnChanges: function(changeRecord)`
|
||||
description:
|
||||
Called after every change to input properties and before processing content or child views.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngOnInit() { ... }`|`ngOnInit()`
|
||||
syntax(js):
|
||||
`ngOnInit: function() { ... }`|`ngOnInit: function()`
|
||||
description:
|
||||
Called after the constructor, initializing input properties, and the first call to `ngOnChanges`.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngDoCheck() { ... }`|`ngDoCheck()`
|
||||
syntax(js):
|
||||
`ngDoCheck: function() { ... }`|`ngDoCheck: function()`
|
||||
description:
|
||||
Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngAfterContentInit() { ... }`|`ngAfterContentInit()`
|
||||
syntax(js):
|
||||
`ngAfterContentInit: function() { ... }`|`ngAfterContentInit: function()`
|
||||
description:
|
||||
Called after `ngOnInit` when the component's or directive's content has been initialized.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngAfterContentChecked() { ... }`|`ngAfterContentChecked()`
|
||||
syntax(js):
|
||||
`ngAfterContentChecked: function() { ... }`|`ngAfterContentChecked: function()`
|
||||
description:
|
||||
Called after every check of the component's or directive's content.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngAfterViewInit() { ... }`|`ngAfterViewInit()`
|
||||
syntax(js):
|
||||
`ngAfterViewInit: function() { ... }`|`ngAfterViewInit: function()`
|
||||
description:
|
||||
Called after `ngAfterContentInit` when the component's view has been initialized. Applies to components only.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngAfterViewChecked() { ... }`|`ngAfterViewChecked()`
|
||||
syntax(js):
|
||||
`ngAfterViewChecked: function() { ... }`|`ngAfterViewChecked: function()`
|
||||
description:
|
||||
Called after every check of the component's view. Applies to components only.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`ngOnDestroy() { ... }`|`ngOnDestroy()`
|
||||
syntax(js):
|
||||
`ngOnDestroy: function() { ... }`|`ngOnDestroy: function()`
|
||||
description:
|
||||
Called once, before the instance is destroyed.
|
@ -1,58 +0,0 @@
|
||||
@cheatsheetSection
|
||||
NgModules
|
||||
@cheatsheetIndex 1
|
||||
@description
|
||||
{@target ts}`import { NgModule } from '@angular/core';`{@endtarget}
|
||||
{@target js}Available from the `ng.core` namespace{@endtarget}
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`@NgModule({ declarations: ..., imports: ...,
|
||||
exports: ..., providers: ..., bootstrap: ...})
|
||||
class MyModule {}`|`NgModule`
|
||||
description:
|
||||
Defines a module that contains components, directives, pipes, and providers.
|
||||
|
||||
syntax(js):
|
||||
`ng.core.NgModule({declarations: ..., imports: ...,
|
||||
exports: ..., providers: ..., bootstrap: ...}).
|
||||
Class({ constructor: function() {}})`
|
||||
description:
|
||||
Defines a module that contains components, directives, pipes, and providers.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`declarations: [MyRedComponent, MyBlueComponent, MyDatePipe]`|`declarations:`
|
||||
description:
|
||||
List of components, directives, and pipes that belong to this module.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`imports: [BrowserModule, SomeOtherModule]`|`imports:`
|
||||
description:
|
||||
List of modules to import into this module. Everything from the imported modules
|
||||
is available to `declarations` of this module.
|
||||
|
||||
syntax(js):
|
||||
`imports: [ng.platformBrowser.BrowserModule, SomeOtherModule]`|`imports:`
|
||||
description:
|
||||
List of modules to import into this module. Everything from the imported modules
|
||||
is available to `declarations` of this module.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`exports: [MyRedComponent, MyDatePipe]`|`exports:`
|
||||
description:
|
||||
List of components, directives, and pipes visible to modules that import this module.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`providers: [MyService, { provide: ... }]`|`providers:`
|
||||
description:
|
||||
List of dependency injection providers visible both to the contents of this module and to importers of this module.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`bootstrap: [MyAppComponent]`|`bootstrap:`
|
||||
description:
|
||||
List of components to bootstrap when this module is bootstrapped.
|
@ -1,170 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Routing and navigation
|
||||
@cheatsheetIndex 11
|
||||
@description
|
||||
{@target ts}`import { Routes, RouterModule, ... } from '@angular/router';`{@endtarget}
|
||||
{@target js}Available from the `ng.router` namespace{@endtarget}
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`const routes: Routes = [
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: 'path/:routeParam', component: MyComponent },
|
||||
{ path: 'staticPath', component: ... },
|
||||
{ path: '**', component: ... },
|
||||
{ path: 'oldPath', redirectTo: '/staticPath' },
|
||||
{ path: ..., component: ..., data: { message: 'Custom' } }
|
||||
]);
|
||||
|
||||
const routing = RouterModule.forRoot(routes);`|`Routes`
|
||||
syntax(js):
|
||||
`var routes = [
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: ':routeParam', component: MyComponent },
|
||||
{ path: 'staticPath', component: ... },
|
||||
{ path: '**', component: ... },
|
||||
{ path: 'oldPath', redirectTo: '/staticPath' },
|
||||
{ path: ..., component: ..., data: { message: 'Custom' } }
|
||||
]);
|
||||
|
||||
var routing = ng.router.RouterModule.forRoot(routes);`|`ng.router.Routes`
|
||||
description:
|
||||
Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`
|
||||
<router-outlet></router-outlet>
|
||||
<router-outlet name="aux"></router-outlet>
|
||||
`|`router-outlet`
|
||||
description:
|
||||
Marks the location to load the component of the active route.
|
||||
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`
|
||||
<a routerLink="/path">
|
||||
<a [routerLink]="[ '/path', routeParam ]">
|
||||
<a [routerLink]="[ '/path', { matrixParam: 'value' } ]">
|
||||
<a [routerLink]="[ '/path' ]" [queryParams]="{ page: 1 }">
|
||||
<a [routerLink]="[ '/path' ]" fragment="anchor">
|
||||
`|`[routerLink]`
|
||||
description:
|
||||
Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the `/` prefix; for a child route, use the `./`prefix; for a sibling or parent, use the `../` prefix.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<a [routerLink]="[ '/path' ]" routerLinkActive="active">`
|
||||
description:
|
||||
The provided classes are added to the element when the `routerLink` becomes the current active route.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`class CanActivateGuard implements CanActivate {
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean>|Promise<boolean>|boolean { ... }
|
||||
}
|
||||
|
||||
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
|
||||
syntax(js):
|
||||
`var CanActivateGuard = ng.core.Class({
|
||||
canActivate: function(route, state) {
|
||||
// return Observable/Promise boolean or boolean
|
||||
}
|
||||
});
|
||||
|
||||
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
|
||||
description:
|
||||
An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean or an Observable/Promise that resolves to a boolean.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`class CanDeactivateGuard implements CanDeactivate<T> {
|
||||
canDeactivate(
|
||||
component: T,
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean>|Promise<boolean>|boolean { ... }
|
||||
}
|
||||
|
||||
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
|
||||
syntax(js):
|
||||
`var CanDeactivateGuard = ng.core.Class({
|
||||
canDeactivate: function(component, route, state) {
|
||||
// return Observable/Promise boolean or boolean
|
||||
}
|
||||
});
|
||||
|
||||
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
|
||||
description:
|
||||
An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean or an Observable/Promise that resolves to a boolean.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`class CanActivateChildGuard implements CanActivateChild {
|
||||
canActivateChild(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean>|Promise<boolean>|boolean { ... }
|
||||
}
|
||||
|
||||
{ path: ..., canActivateChild: [CanActivateGuard],
|
||||
children: ... }`|`CanActivateChild`
|
||||
syntax(js):
|
||||
`var CanActivateChildGuard = ng.core.Class({
|
||||
canActivateChild: function(route, state) {
|
||||
// return Observable/Promise boolean or boolean
|
||||
}
|
||||
});
|
||||
|
||||
{ path: ..., canActivateChild: [CanActivateChildGuard],
|
||||
children: ... }`|`CanActivateChild`
|
||||
description:
|
||||
An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean or an Observable/Promise that resolves to a boolean.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`class ResolveGuard implements Resolve<T> {
|
||||
resolve(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<any>|Promise<any>|any { ... }
|
||||
}
|
||||
|
||||
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
|
||||
syntax(js):
|
||||
`var ResolveGuard = ng.core.Class({
|
||||
resolve: function(route, state) {
|
||||
// return Observable/Promise value or value
|
||||
}
|
||||
});
|
||||
|
||||
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
|
||||
description:
|
||||
An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax(ts):
|
||||
`class CanLoadGuard implements CanLoad {
|
||||
canLoad(
|
||||
route: Route
|
||||
): Observable<boolean>|Promise<boolean>|boolean { ... }
|
||||
}
|
||||
|
||||
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
|
||||
syntax(js):
|
||||
`var CanLoadGuard = ng.core.Class({
|
||||
canLoad: function(route) {
|
||||
// return Observable/Promise boolean or boolean
|
||||
}
|
||||
});
|
||||
|
||||
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
|
||||
description:
|
||||
An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean or an Observable/Promise that resolves to a boolean.
|
||||
|
@ -1,94 +0,0 @@
|
||||
@cheatsheetSection
|
||||
Template syntax
|
||||
@cheatsheetIndex 2
|
||||
@description
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<input [value]="firstName">`|`[value]`
|
||||
description:
|
||||
Binds property `value` to the result of expression `firstName`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div [attr.role]="myAriaRole">`|`[attr.role]`
|
||||
description:
|
||||
Binds attribute `role` to the result of expression `myAriaRole`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div [class.extra-sparkle]="isDelightful">`|`[class.extra-sparkle]`
|
||||
description:
|
||||
Binds the presence of the CSS class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div [style.width.px]="mySize">`|`[style.width.px]`
|
||||
description:
|
||||
Binds style property `width` to the result of expression `mySize` in pixels. Units are optional.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<button (click)="readRainbow($event)">`|`(click)`
|
||||
description:
|
||||
Calls method `readRainbow` when a click event is triggered on this button element (or its children) and passes in the event object.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<div title="Hello {{ponyName}}">`|`{{ponyName}}`
|
||||
description:
|
||||
Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
|
||||
`<div [title]="'Hello ' + ponyName">`
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<p>Hello {{ponyName}}</p>`|`{{ponyName}}`
|
||||
description:
|
||||
Binds text content to an interpolated string, for example, "Hello Seabiscuit".
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<my-cmp [(title)]="name">`|`[(title)]`
|
||||
description:
|
||||
Sets up two-way data binding. Equivalent to: `<my-cmp [title]="name" (titleChange)="name=$event">`
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<video #movieplayer ...>
|
||||
<button (click)="movieplayer.play()">
|
||||
</video>`|`#movieplayer`|`(click)`
|
||||
description:
|
||||
Creates a local variable `movieplayer` that provides access to the `video` element instance in data-binding and event-binding expressions in the current template.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<p *myUnless="myExpression">...</p>`|`*myUnless`
|
||||
description:
|
||||
The `*` symbol turns the current element into an embedded template. Equivalent to:
|
||||
`<ng-template [myUnless]="myExpression"><p>...</p></ng-template>`
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>`|`{{cardNumber | myCardNumberFormatter}}`
|
||||
description:
|
||||
Transforms the current value of expression `cardNumber` via the pipe called `myCardNumberFormatter`.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<p>Employer: {{employer?.companyName}}</p>`|`{{employer?.companyName}}`
|
||||
description:
|
||||
The safe navigation operator (`?`) means that the `employer` field is optional and if `undefined`, the rest of the expression should be ignored.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<svg:rect x="0" y="0" width="100" height="100"/>`|`svg:`
|
||||
description:
|
||||
An SVG snippet template needs an `svg:` prefix on its root element to disambiguate the SVG element from an HTML component.
|
||||
|
||||
@cheatsheetItem
|
||||
syntax:
|
||||
`<svg>
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
</svg>`|`svg`
|
||||
description:
|
||||
An `<svg>` root element is detected as an SVG element automatically, without the prefix.
|
@ -10,12 +10,41 @@ describe('site App', function() {
|
||||
});
|
||||
|
||||
it('should show features text after clicking "Features"', () => {
|
||||
page.featureLink.click().then(() => {
|
||||
page.getLink('features').click().then(() => {
|
||||
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a doc with a code-example');
|
||||
it('should show the tutorial index page at `/tutorial/`', () => {
|
||||
// check that we can navigate directly to the tutorial page
|
||||
page.navigateTo('tutorial/');
|
||||
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
||||
|
||||
// navigate to a different page
|
||||
page.getLink('features').click();
|
||||
|
||||
// check that we can navigate to the tutorial page via a link in the navigation
|
||||
const heading = page.getNavHeading(/tutorial/i);
|
||||
expect(heading.getText()).toMatch(/tutorial/i);
|
||||
heading.click();
|
||||
page.getLink('tutorial/').click();
|
||||
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
||||
});
|
||||
|
||||
it('should render `{@example}` dgeni tags as `<code-example>` elements with HTML escaped content', () => {
|
||||
page.navigateTo('guide/component-styles');
|
||||
const codeExample = element.all(by.css('code-example')).first();
|
||||
expect(page.getInnerHtml(codeExample))
|
||||
.toContain('@Component({\n selector: \'hero-app\',\n template: `\n <h1>Tour of Heroes</h1>');
|
||||
});
|
||||
|
||||
describe('api-docs', () => {
|
||||
it('should show a link to github', () => {
|
||||
page.navigateTo('api/common/NgClass');
|
||||
expect(page.ghLink.getAttribute('href'))
|
||||
.toMatch(/https:\/\/github.com\/angular\/angular\/tree\/.+\/packages\/common\/src\/directives\/ng_class\.ts/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('google analytics', () => {
|
||||
beforeEach(done => page.gaReady.then(done));
|
||||
|
@ -1,22 +1,39 @@
|
||||
import { browser, element, by, promise } from 'protractor';
|
||||
import { browser, element, by, promise, ElementFinder } from 'protractor';
|
||||
|
||||
const githubRegex = /https:\/\/github.com\/angular\/angular\//;
|
||||
|
||||
export class SitePage {
|
||||
links = element.all(by.css('md-toolbar a'));
|
||||
docViewer = element(by.css('aio-doc-viewer'));
|
||||
codeExample = element.all(by.css('aio-doc-viewer pre > code'));
|
||||
featureLink = element(by.css('md-toolbar a[href="features"]'));
|
||||
ghLink = this.docViewer
|
||||
.all(by.css('a'))
|
||||
.filter((a: ElementFinder) => a.getAttribute('href').then(href => githubRegex.test(href)))
|
||||
.first();
|
||||
gaReady: promise.Promise<any>;
|
||||
ga = () => browser.executeScript('return window["gaCalls"]') as promise.Promise<any[][]>;
|
||||
locationPath = () => browser.executeScript('return document.location.pathname') as promise.Promise<string>;
|
||||
getNavHeading(pattern: RegExp) {
|
||||
return element.all(by.css('aio-nav-item a'))
|
||||
.filter(element => element.getText().then(text => pattern.test(text)))
|
||||
.first();
|
||||
}
|
||||
getLink(path) { return element(by.css(`a[href="${path}"]`)); }
|
||||
ga() { return browser.executeScript('return window["gaCalls"]') as promise.Promise<any[][]>; }
|
||||
locationPath() { return browser.executeScript('return document.location.pathname') as promise.Promise<string>; }
|
||||
|
||||
navigateTo() {
|
||||
return browser.get('/').then(_ => this.replaceGa(_));
|
||||
navigateTo(pageUrl = '') {
|
||||
return browser.get('/' + pageUrl).then(_ => this.replaceGa(_));
|
||||
}
|
||||
|
||||
getDocViewerText() {
|
||||
return this.docViewer.getText();
|
||||
}
|
||||
|
||||
getInnerHtml(element) {
|
||||
// `getInnerHtml` was removed from webDriver and this is the workaround.
|
||||
// See https://github.com/angular/protractor/blob/master/CHANGELOG.md#breaking-changes
|
||||
return browser.executeScript('return arguments[0].innerHTML;', element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the ambient Google Analytics tracker with homebrew spy
|
||||
* don't send commands to GA during e2e testing!
|
||||
|
@ -7,7 +7,7 @@
|
||||
"cleanUrls": true,
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "**",
|
||||
"source": "**/!(*.*)",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
]
|
||||
|
@ -12,15 +12,17 @@
|
||||
"build": "yarn check-env && yarn docs && ng build -prod -sm",
|
||||
"test": "yarn check-env && ng test --sourcemap=false",
|
||||
"lint": "yarn check-env && ng lint",
|
||||
"pree2e": "webdriver-manager update --standalone false --gecko false",
|
||||
"pree2e": "yarn ~~update-webdriver",
|
||||
"e2e": "yarn check-env && ng e2e --no-webdriver-update",
|
||||
"deploy-preview": "scripts/deploy-preview.sh",
|
||||
"deploy-staging": "firebase use staging --token \"$FIREBASE_TOKEN\" && yarn ~~deploy",
|
||||
"pre~~deploy": "yarn build",
|
||||
"~~deploy": "firebase deploy --message \"Commit: $TRAVIS_COMMIT\" --non-interactive --token \"$FIREBASE_TOKEN\"",
|
||||
"check-env": "node ../tools/check-environment.js",
|
||||
"predocs": "rimraf src/content",
|
||||
"docs": "dgeni ./transforms/angular.io-package",
|
||||
"docs-test": "node ../dist/tools/cjs-jasmine/index-tools ../../transforms/**/*.spec.js"
|
||||
"docs-test": "node ../dist/tools/cjs-jasmine/index-tools ../../transforms/**/*.spec.js",
|
||||
"~~update-webdriver": "webdriver-manager update --standalone false --gecko false",
|
||||
"pre~~deploy": "yarn build",
|
||||
"~~deploy": "firebase deploy --message \"Commit: $TRAVIS_COMMIT\" --non-interactive --token \"$FIREBASE_TOKEN\""
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@ -35,21 +37,22 @@
|
||||
"@angular/platform-browser-dynamic": "next",
|
||||
"@angular/platform-server": "next",
|
||||
"@angular/router": "next",
|
||||
"@angular/service-worker": "^1.0.0-beta.6",
|
||||
"@angular/service-worker": "^1.0.0-beta.7",
|
||||
"core-js": "^2.4.1",
|
||||
"rxjs": "^5.1.0",
|
||||
"rho": "https://github.com/petebacondarwin/rho#heading-fix",
|
||||
"rxjs": "^5.2.0",
|
||||
"ts-helpers": "^1.1.1",
|
||||
"zone.js": "0.7.8"
|
||||
"zone.js": "^0.8.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "^1.0.0-rc.0",
|
||||
"@angular/cli": "^1.0.0-rc.4",
|
||||
"@angular/compiler-cli": "next",
|
||||
"@types/jasmine": "2.5.38",
|
||||
"@types/node": "~6.0.60",
|
||||
"canonical-path": "^0.0.2",
|
||||
"codelyzer": "~2.0.0-beta.4",
|
||||
"dgeni": "^0.4.7",
|
||||
"dgeni-packages": "^0.16.8",
|
||||
"dgeni-packages": "0.17.0",
|
||||
"entities": "^1.1.1",
|
||||
"firebase-tools": "^3.2.1",
|
||||
"gulp": "^3.9.1",
|
||||
@ -63,7 +66,7 @@
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"lodash": "^4.17.4",
|
||||
"protractor": "~5.1.0",
|
||||
"rho": "^0.3.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"ts-node": "~2.0.0",
|
||||
"tslint": "~4.4.2",
|
||||
"typescript": "2.1.6"
|
||||
|
@ -8,6 +8,7 @@
|
||||
<md-sidenav-container class="sidenav-container">
|
||||
|
||||
<md-sidenav #sidenav class="sidenav" [opened]="isSideBySide" [mode] = "isSideBySide ? 'side' : 'over'">
|
||||
<div class="version-info vertical-menu-item">{{ (versionInfo | async)?.full }}</div>
|
||||
<aio-top-menu *ngIf="!isSideBySide" class="small" [nodes]="(navigationViews | async)?.TopBar" [homeImageUrl]="homeImageUrl"></aio-top-menu>
|
||||
<aio-nav-menu [nodes]="(navigationViews | async)?.SideNav" [selectedNodes]="selectedNodes | async"></aio-nav-menu>
|
||||
</md-sidenav>
|
||||
@ -16,5 +17,4 @@
|
||||
<aio-search-results #searchResults></aio-search-results>
|
||||
<aio-doc-viewer [doc]="currentDocument | async" (docRendered)="onDocRendered($event)"></aio-doc-viewer>
|
||||
</section>
|
||||
|
||||
</md-sidenav-container>
|
@ -11,6 +11,8 @@ import { AutoScrollService } from 'app/shared/auto-scroll.service';
|
||||
import { MockSearchService } from 'testing/search.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { MockLocationService } from 'testing/location.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
import { MockLogger } from 'testing/logger.service';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let component: AppComponent;
|
||||
@ -24,7 +26,8 @@ describe('AppComponent', () => {
|
||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||
{ provide: SearchService, useClass: MockSearchService },
|
||||
{ provide: GaService, useClass: TestGaService },
|
||||
{ provide: LocationService, useFactory: () => new MockLocationService(initialUrl) }
|
||||
{ provide: LocationService, useFactory: () => new MockLocationService(initialUrl) },
|
||||
{ provide: Logger, useClass: MockLogger }
|
||||
]
|
||||
});
|
||||
TestBed.compileComponents();
|
||||
|
@ -5,7 +5,7 @@ import { GaService } from 'app/shared/ga.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { DocumentService, DocumentContents } from 'app/documents/document.service';
|
||||
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
|
||||
import { NavigationService, NavigationViews, NavigationNode } from 'app/navigation/navigation.service';
|
||||
import { NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
|
||||
import { SearchService } from 'app/search/search.service';
|
||||
import { SearchResultsComponent } from 'app/search/search-results/search-results.component';
|
||||
import { AutoScrollService } from 'app/shared/auto-scroll.service';
|
||||
@ -24,6 +24,7 @@ export class AppComponent implements OnInit {
|
||||
currentDocument: Observable<DocumentContents>;
|
||||
navigationViews: Observable<NavigationViews>;
|
||||
selectedNodes: Observable<NavigationNode[]>;
|
||||
versionInfo: Observable<VersionInfo>;
|
||||
|
||||
@ViewChildren('searchBox, searchResults', { read: ElementRef })
|
||||
searchElements: QueryList<ElementRef>;
|
||||
@ -45,6 +46,7 @@ export class AppComponent implements OnInit {
|
||||
locationService.currentUrl.subscribe(url => gaService.locationChanged(url));
|
||||
this.navigationViews = navigationService.navigationViews;
|
||||
this.selectedNodes = navigationService.selectedNodes;
|
||||
this.versionInfo = navigationService.versionInfo;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -155,5 +155,12 @@ describe('DocumentService', () => {
|
||||
|
||||
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'index.json');
|
||||
});
|
||||
|
||||
it('should map the "folder" locations to the correct document request', () => {
|
||||
const { service, backend, location } = getServices('guide/');
|
||||
service.currentDocument.subscribe();
|
||||
|
||||
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'guide.json');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -63,8 +63,11 @@ export class DocumentService {
|
||||
|
||||
private computePath(url: string) {
|
||||
url = url.match(/[^#?]*/)[0]; // strip off fragment and query
|
||||
url = '/' + url;
|
||||
url = url.endsWith('/') ? url + 'index' : url;
|
||||
return 'content/docs' + url + '.json';
|
||||
url = url.replace(/\/$/, ''); // strip off trailing slash
|
||||
if (url === '') {
|
||||
// deal with root url
|
||||
url = 'index';
|
||||
}
|
||||
return 'content/docs/' + url + '.json';
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ export class NavItemComponent implements OnChanges {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['selectedNodes'] || changes['node']) {
|
||||
this.isSelected = this.selectedNodes.indexOf(this.node) !== -1;
|
||||
this.isExpanded = this.isExpanded || this.isSelected;
|
||||
}
|
||||
this.setClasses();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ReflectiveInjector } from '@angular/core';
|
||||
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
|
||||
import { MockBackend } from '@angular/http/testing';
|
||||
import { NavigationService, NavigationViews, NavigationNode } from 'app/navigation/navigation.service';
|
||||
import { NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { MockLocationService } from 'testing/location.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
@ -125,4 +125,22 @@ describe('NavigationService', () => {
|
||||
expect(currentNodes).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('versionInfo', () => {
|
||||
let service: NavigationService, versionInfo: VersionInfo;
|
||||
|
||||
beforeEach(() => {
|
||||
service = injector.get(NavigationService);
|
||||
service.versionInfo.subscribe(info => versionInfo = info);
|
||||
|
||||
const backend = injector.get(ConnectionBackend);
|
||||
backend.connectionsArray[0].mockRespond(createResponse({
|
||||
__versionInfo: { raw: '4.0.0' }
|
||||
}));
|
||||
});
|
||||
|
||||
it('should extract the version info', () => {
|
||||
expect(versionInfo).toEqual({ raw: '4.0.0' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -12,28 +12,63 @@ import { LocationService } from 'app/shared/location.service';
|
||||
import { NavigationNode } from './navigation-node';
|
||||
export { NavigationNode } from './navigation-node';
|
||||
|
||||
|
||||
export type NavigationResponse = {__versionInfo: VersionInfo } & { [name: string]: NavigationNode[]|VersionInfo };
|
||||
|
||||
export interface NavigationViews {
|
||||
[name: string]: NavigationNode[];
|
||||
}
|
||||
|
||||
export interface NavigationMap {
|
||||
[url: string]: NavigationNode;
|
||||
}
|
||||
|
||||
export interface VersionInfo {
|
||||
raw: string;
|
||||
major: number;
|
||||
minor: number;
|
||||
patch: number;
|
||||
prerelease: string[];
|
||||
build: string;
|
||||
version: string;
|
||||
codeName: string;
|
||||
isSnapshot: boolean;
|
||||
full: string;
|
||||
branch: string;
|
||||
commitSHA: string;
|
||||
}
|
||||
|
||||
const navigationPath = 'content/navigation.json';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class NavigationService {
|
||||
|
||||
/**
|
||||
* An observable collection of NavigationNode trees, which can be used to render navigational menus
|
||||
*/
|
||||
navigationViews = this.fetchNavigationViews();
|
||||
navigationViews: Observable<NavigationViews>;
|
||||
|
||||
/**
|
||||
* The current version of doc-app that we are running
|
||||
*/
|
||||
versionInfo: Observable<VersionInfo>;
|
||||
|
||||
/**
|
||||
* An observable array of nodes that indicate which nodes in the `navigationViews` match the current URL location
|
||||
*/
|
||||
selectedNodes = this.getSelectedNodes();
|
||||
selectedNodes: Observable<NavigationNode[]>;
|
||||
|
||||
constructor(private http: Http, private location: LocationService, private logger: Logger) { }
|
||||
constructor(private http: Http, private location: LocationService, private logger: Logger) {
|
||||
const navigationInfo = this.fetchNavigationInfo();
|
||||
// The version information is packaged inside the navigation response to save us an extra request.
|
||||
this.versionInfo = this.getVersionInfo(navigationInfo);
|
||||
this.navigationViews = this.getNavigationViews(navigationInfo);
|
||||
this.selectedNodes = this.getSelectedNodes(this.navigationViews);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an observable that fetches the `NavigationViews` from the server.
|
||||
* Get an observable that fetches the `NavigationResponse` from the server.
|
||||
* We create an observable by calling `http.get` but then publish it to share the result
|
||||
* among multiple subscribers, without triggering new requests.
|
||||
* We use `publishLast` because once the http request is complete the request observable completes.
|
||||
@ -43,10 +78,22 @@ export class NavigationService {
|
||||
* another request to the server.
|
||||
* We are not storing the subscription from connecting as we do not expect this service to be destroyed.
|
||||
*/
|
||||
private fetchNavigationViews(): Observable<NavigationViews> {
|
||||
const navigationViews = this.http.get(navigationPath)
|
||||
.map(res => res.json() as NavigationViews)
|
||||
private fetchNavigationInfo(): Observable<NavigationResponse> {
|
||||
const navigationInfo = this.http.get(navigationPath)
|
||||
.map(res => res.json() as NavigationResponse)
|
||||
.publishLast();
|
||||
navigationInfo.connect();
|
||||
return navigationInfo;
|
||||
}
|
||||
|
||||
private getVersionInfo(navigationInfo: Observable<NavigationResponse>) {
|
||||
const versionInfo = navigationInfo.map(response => response.__versionInfo).publishReplay(1);
|
||||
versionInfo.connect();
|
||||
return versionInfo;
|
||||
}
|
||||
|
||||
private getNavigationViews(navigationInfo: Observable<NavigationResponse>): Observable<NavigationViews> {
|
||||
const navigationViews = navigationInfo.map(response => unpluck(response, '__versionInfo')).publishReplay(1);
|
||||
navigationViews.connect();
|
||||
return navigationViews;
|
||||
}
|
||||
@ -57,9 +104,9 @@ export class NavigationService {
|
||||
* URL change before they receive an emission.
|
||||
* See above for discussion of using `connect`.
|
||||
*/
|
||||
private getSelectedNodes() {
|
||||
private getSelectedNodes(navigationViews: Observable<NavigationViews>) {
|
||||
const selectedNodes = combineLatest(
|
||||
this.navigationViews.map(this.computeUrlToNodesMap),
|
||||
navigationViews.map(this.computeUrlToNodesMap),
|
||||
this.location.currentUrl,
|
||||
(navMap, url) => navMap[url] || [])
|
||||
.publishReplay(1);
|
||||
@ -74,7 +121,7 @@ export class NavigationService {
|
||||
* @param navigation A collection of navigation nodes that are to be mapped
|
||||
*/
|
||||
private computeUrlToNodesMap(navigation: NavigationViews) {
|
||||
const navMap = {};
|
||||
const navMap: NavigationMap = {};
|
||||
Object.keys(navigation).forEach(key => navigation[key].forEach(node => walkNodes(node)));
|
||||
return navMap;
|
||||
|
||||
@ -90,3 +137,9 @@ export class NavigationService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function unpluck(obj: any, property: string) {
|
||||
const result = Object.assign({}, obj);
|
||||
delete result[property];
|
||||
return result;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
sizes="16x16">
|
||||
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Lato:300,400" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
|
||||
|
||||
<!-- Google Analytics -->
|
||||
|
@ -1,10 +1,8 @@
|
||||
import 'core-js/es7/reflect';
|
||||
import 'zone.js/dist/zone';
|
||||
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { environment } from './environments/environment';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
|
@ -1,7 +1,24 @@
|
||||
/**
|
||||
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||
* You can add your own extra polyfills to this file.
|
||||
*
|
||||
* This file is divided into 2 sections:
|
||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||
* file.
|
||||
*
|
||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
// This file includes polyfills needed by Angular and is loaded before the app.
|
||||
// You can add your own extra polyfills to this file.
|
||||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||
// import 'core-js/es6/symbol';
|
||||
// import 'core-js/es6/object';
|
||||
// import 'core-js/es6/function';
|
||||
@ -15,24 +32,37 @@
|
||||
// import 'core-js/es6/regexp';
|
||||
// import 'core-js/es6/map';
|
||||
// import 'core-js/es6/set';
|
||||
import 'reflect-metadata';
|
||||
|
||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/** IE10 and IE11 requires the following to support `@angular/animation`. */
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
|
||||
// If you need to support the browsers/features below, uncomment the import
|
||||
// and run `npm install import-name-here';
|
||||
// Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
||||
/** Evergreen browsers require these. **/
|
||||
import 'core-js/es6/reflect';
|
||||
import 'core-js/es7/reflect';
|
||||
|
||||
// Needed for: IE9
|
||||
// import 'classlist.js';
|
||||
|
||||
// Animations
|
||||
// Needed for: All but Chrome and Firefox, Not supported in IE9
|
||||
// import 'web-animations-js';
|
||||
/** ALL Firefox browsers require the following to support `@angular/animation`. **/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
// Date, currency, decimal and percent pipes
|
||||
// Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
|
||||
// import 'intl';
|
||||
|
||||
// NgClass on SVG elements
|
||||
// Needed for: IE10, IE11
|
||||
// import 'classlist.js';
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Date, currency, decimal and percent pipes.
|
||||
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
|
||||
*/
|
||||
// import 'intl'; // Run `npm install --save intl`.
|
||||
|
@ -68,7 +68,7 @@
|
||||
font-size: 18px;
|
||||
font-weight: 300;
|
||||
color: white;
|
||||
font-family: $support-font;
|
||||
font-family: $main-font;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,9 @@
|
||||
}
|
||||
|
||||
.level-1 {
|
||||
font-family: $support-font;
|
||||
font-weight: 500;
|
||||
font-family: $main-font;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
padding-left: 10px;
|
||||
transition: background-color 0.2s;
|
||||
@ -148,22 +149,12 @@
|
||||
}
|
||||
|
||||
.level-3 {
|
||||
font-family: $support-font;
|
||||
font-family: $main-font;
|
||||
font-size: 14px;
|
||||
color: $mediumgray;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
@mixin rotate($degrees) {
|
||||
-moz-transform: rotate($degrees);
|
||||
-webkit-transform: rotate($degrees);
|
||||
-o-transform: rotate($degrees);
|
||||
-ms-transform: rotate($degrees);
|
||||
transform: rotate($degrees);
|
||||
transition: transform 150ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
.level-1.expanded .material-icons, .level-2.expanded .material-icons {
|
||||
@include rotate(90deg);
|
||||
}
|
||||
@ -171,3 +162,7 @@
|
||||
.level-1:not(.expanded) .material-icons, .level-2:not(.expanded) .material-icons {
|
||||
@include rotate(0deg);
|
||||
}
|
||||
|
||||
.version-info {
|
||||
border: 3px $blue solid;
|
||||
}
|
@ -20,7 +20,9 @@ aio-top-menu li {
|
||||
}
|
||||
|
||||
md-toolbar.mat-toolbar {
|
||||
box-shadow: 6px 0 6px rgba(0,0,0,0.10);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.30);
|
||||
padding: 0 16px 0px 0px;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ $small-breakpoint-width: 840px;
|
||||
|
||||
// TYPOGRAPHY
|
||||
$main-font: "Roboto","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
|
||||
$support-font: "Lato","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
|
||||
$code-font: "Droid Sans Mono", monospace;
|
||||
|
||||
// COLOR PALETTE
|
||||
|
@ -6,6 +6,7 @@
|
||||
@import './constants';
|
||||
|
||||
// import global mixins
|
||||
@import './mixins';
|
||||
|
||||
// import directories
|
||||
@import './0-base/base-dir';
|
||||
|
9
aio/src/styles/mixins.scss
Normal file
9
aio/src/styles/mixins.scss
Normal file
@ -0,0 +1,9 @@
|
||||
@mixin rotate($degrees) {
|
||||
-moz-transform: rotate($degrees);
|
||||
-webkit-transform: rotate($degrees);
|
||||
-o-transform: rotate($degrees);
|
||||
-ms-transform: rotate($degrees);
|
||||
transform: rotate($degrees);
|
||||
transition: transform 150ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js/dist/zone';
|
||||
import 'zone.js/dist/long-stack-trace-zone';
|
||||
import 'zone.js/dist/proxy.js';
|
||||
import 'zone.js/dist/sync-test';
|
||||
|
@ -16,7 +16,7 @@ const gitPackage = require('dgeni-packages/git');
|
||||
const linksPackage = require('../links-package');
|
||||
const examplesPackage = require('../examples-package');
|
||||
const targetPackage = require('../target-package');
|
||||
const cheatsheetPackage = require('../cheatsheet-package');
|
||||
const contentPackage = require('../content-package');
|
||||
const rhoPackage = require('../rho-package');
|
||||
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '../../..');
|
||||
@ -31,7 +31,7 @@ module.exports =
|
||||
'angular.io',
|
||||
[
|
||||
jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage, examplesPackage,
|
||||
gitPackage, targetPackage, cheatsheetPackage, rhoPackage
|
||||
gitPackage, targetPackage, contentPackage, rhoPackage
|
||||
])
|
||||
|
||||
// Register the processors
|
||||
@ -47,10 +47,16 @@ module.exports =
|
||||
.processor(require('./processors/filterMemberDocs'))
|
||||
.processor(require('./processors/convertToJson'))
|
||||
.processor(require('./processors/markBarredODocsAsPrivate'))
|
||||
.processor(require('./processors/filterPrivateDocs'))
|
||||
.processor(require('./processors/filterIgnoredDocs'))
|
||||
.processor(require('./processors/fixInternalDocumentLinks'))
|
||||
.processor(require('./processors/processNavigationMap'))
|
||||
|
||||
// overrides base packageInfo and returns the one for the 'angular/angular' repo.
|
||||
.factory('packageInfo', function() { return require(path.resolve(PROJECT_ROOT, 'package.json')); })
|
||||
|
||||
.factory(require('./readers/navigation'))
|
||||
|
||||
.config(function(checkAnchorLinksProcessor, log) {
|
||||
// TODO: re-enable
|
||||
checkAnchorLinksProcessor.$enabled = false;
|
||||
@ -58,12 +64,13 @@ module.exports =
|
||||
|
||||
// Where do we get the source files?
|
||||
.config(function(
|
||||
readTypeScriptModules, readFilesProcessor, collectExamples, generateKeywordsProcessor) {
|
||||
readTypeScriptModules, readFilesProcessor, collectExamples, generateKeywordsProcessor, navigationFileReader) {
|
||||
|
||||
// API files are typescript
|
||||
readTypeScriptModules.basePath = API_SOURCE_PATH;
|
||||
readTypeScriptModules.ignoreExportsMatching = [/^_/];
|
||||
readTypeScriptModules.hidePrivateMembers = true;
|
||||
readFilesProcessor.fileReaders.push(navigationFileReader)
|
||||
readTypeScriptModules.sourceFiles = [
|
||||
'common/index.ts',
|
||||
'common/testing/index.ts',
|
||||
@ -103,7 +110,6 @@ module.exports =
|
||||
include: CONTENTS_PATH + '/file-not-found.md',
|
||||
fileReader: 'contentFileReader'
|
||||
},
|
||||
{basePath: CONTENTS_PATH, include: CONTENTS_PATH + '/cheatsheet/*.md'},
|
||||
{
|
||||
basePath: API_SOURCE_PATH,
|
||||
include: API_SOURCE_PATH + '/examples/**/*',
|
||||
@ -112,8 +118,34 @@ module.exports =
|
||||
{
|
||||
basePath: CONTENTS_PATH,
|
||||
include: CONTENTS_PATH + '/examples/**/*',
|
||||
exclude: [
|
||||
'**/*plnkr.no-link.html',
|
||||
'**/node_modules/**',
|
||||
// _boilerplate files
|
||||
'**/_boilerplate/**',
|
||||
'**/*/src/styles.css',
|
||||
'**/*/src/systemjs-angular-loader.js',
|
||||
'**/*/src/systemjs.config.js',
|
||||
'**/*/src/tsconfig.json',
|
||||
'**/*/bs-config.e2e.json',
|
||||
'**/*/bs-config.json',
|
||||
'**/*/package.json',
|
||||
'**/*/tslint.json',
|
||||
// example files
|
||||
'**/_test-output',
|
||||
'**/protractor-helpers.js',
|
||||
'**/e2e-spec.js',
|
||||
'**/ts/**/*.js',
|
||||
'**/js-es6*/**/*.js',
|
||||
'**/ts-snippets/**/*.js',
|
||||
],
|
||||
fileReader: 'exampleFileReader'
|
||||
},
|
||||
{
|
||||
basePath: CONTENTS_PATH,
|
||||
include: CONTENTS_PATH + '/navigation.json',
|
||||
fileReader: 'navigationFileReader'
|
||||
},
|
||||
];
|
||||
|
||||
collectExamples.exampleFolders = ['examples', 'examples'];
|
||||
@ -122,7 +154,12 @@ module.exports =
|
||||
generateKeywordsProcessor.docTypesToIgnore = ['example-region'];
|
||||
})
|
||||
|
||||
|
||||
// Ignore certain problematic files
|
||||
.config(function(filterIgnoredDocs) {
|
||||
filterIgnoredDocs.ignore = [
|
||||
/\/VERSION$/ // Ignore the `VERSION` const, since it would be written to the same file as the `Version` class
|
||||
];
|
||||
})
|
||||
|
||||
// Where do we write the output files?
|
||||
.config(function(writeFilesProcessor) { writeFilesProcessor.outputFolder = OUTPUT_PATH; })
|
||||
@ -228,13 +265,13 @@ module.exports =
|
||||
pathTemplate: '${moduleDoc.moduleFolder}/${name}',
|
||||
outputPathTemplate: '${moduleDoc.moduleFolder}/${name}.json',
|
||||
},
|
||||
{
|
||||
docTypes: ['cheatsheet-data'],
|
||||
pathTemplate: GUIDE_SEGMENT + '/cheatsheet.json',
|
||||
outputPathTemplate: '${path}'
|
||||
},
|
||||
{docTypes: ['example-region'], getOutputPath: function() {}},
|
||||
{docTypes: ['content'], pathTemplate: '${id}', outputPathTemplate: '${path}.json'}
|
||||
{
|
||||
docTypes: ['content'],
|
||||
getPath: (doc) => `${doc.id.replace(/\/index$/, '')}`,
|
||||
outputPathTemplate: '${path}.json'
|
||||
},
|
||||
{docTypes: ['navigation-map'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}
|
||||
];
|
||||
})
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Filter out docs whose id matches a pattern in the `filterIgnoredDocs.ignore` list
|
||||
*/
|
||||
module.exports = function filterIgnoredDocs() {
|
||||
return {
|
||||
ignore: [],
|
||||
$runAfter: ['ids-computed'],
|
||||
$runBefore: ['computing-paths'],
|
||||
$process: function(docs) {
|
||||
return docs.filter(doc => !this.ignore.some(regexp => regexp.test(doc.id)));
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,39 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./filterIgnoredDocs');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('filterIgnoredDocs processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular.io-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('filterIgnoredDocs');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['computing-paths'])
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['ids-computed']);
|
||||
});
|
||||
|
||||
it('should remove docs that match the ignore list', () => {
|
||||
const processor = processorFactory();
|
||||
processor.ignore = [/\/VERSION$/, /ignore-me/];
|
||||
const docs = [
|
||||
{ id: 'public1'},
|
||||
{ id: 'ignore-me/something' },
|
||||
{ id: 'public2'},
|
||||
{ id: 'and-me/VERSION' }
|
||||
];
|
||||
const filteredDocs = processor.$process(docs);
|
||||
expect(filteredDocs).toEqual([
|
||||
{ id: 'public1'},
|
||||
{ id: 'public2'}
|
||||
]);
|
||||
})
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
module.exports = function filterPrivateDocs() {
|
||||
return {
|
||||
$runAfter: ['extra-docs-added'],
|
||||
$runBefore: ['computing-paths'],
|
||||
$process: function(docs) {
|
||||
return docs.filter(function(doc) { return doc.privateExport !== true });
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./filterPrivateDocs');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('filterPrivateDocs processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular.io-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('filterPrivateDocs');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['computing-paths'])
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||
});
|
||||
|
||||
it('should remove docs that are marked as private exports', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ name: 'public1'},
|
||||
{ name: 'ɵPrivate1', privateExport: true },
|
||||
{ name: 'public2'},
|
||||
{ name: 'ɵPrivate2', privateExport: true },
|
||||
{ id: 'other'}
|
||||
];
|
||||
const filteredDocs = processor.$process(docs);
|
||||
expect(filteredDocs).toEqual([
|
||||
{ name: 'public1'},
|
||||
{ name: 'public2'},
|
||||
{ id: 'other'}
|
||||
]);
|
||||
})
|
||||
});
|
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @dgProcessor fixInternalDocumentLinks
|
||||
* @description
|
||||
* Add in the document path to links that start with a hash.
|
||||
* This is important when the web app has a base href in place,
|
||||
* since links like: `<a href="#some-id">` would get mapped to
|
||||
* the URL `base/#some-id` even if the current location is `base/some/doc`.
|
||||
*/
|
||||
module.exports = function fixInternalDocumentLinks() {
|
||||
|
||||
var INTERNAL_LINK = /(<a [^>]*href=")(#[^"]*)/g;
|
||||
|
||||
return {
|
||||
$runAfter: ['inlineTagProcessor'],
|
||||
$runBefore: ['writeFilesProcessor'],
|
||||
$process: function(docs) {
|
||||
docs.forEach(doc => {
|
||||
doc.renderedContent = doc.renderedContent.replace(INTERNAL_LINK, (_, pre, hash) => {
|
||||
return pre + doc.path + hash;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,52 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./fixInternalDocumentLinks');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('fixInternalDocumentLinks processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular.io-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('fixInternalDocumentLinks');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['writeFilesProcessor'])
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['inlineTagProcessor']);
|
||||
});
|
||||
|
||||
it('should prefix internal hash links with the current doc path', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{
|
||||
path: 'some/doc',
|
||||
renderedContent: `
|
||||
<a href="http://google.com#q=angular">Google</a>
|
||||
<a href="some/relative/path#some-id">Some Id</a>
|
||||
<a href="#some-internal-id">Link to heading</a>
|
||||
<a class="important" href="#some-internal-id">Link to heading</a>
|
||||
<a href="#some-internal-id" target="_blank">Link to heading</a>
|
||||
`
|
||||
},
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs).toEqual([
|
||||
{
|
||||
path: 'some/doc',
|
||||
renderedContent: `
|
||||
<a href="http://google.com#q=angular">Google</a>
|
||||
<a href="some/relative/path#some-id">Some Id</a>
|
||||
<a href="some/doc#some-internal-id">Link to heading</a>
|
||||
<a class="important" href="some/doc#some-internal-id">Link to heading</a>
|
||||
<a href="some/doc#some-internal-id" target="_blank">Link to heading</a>
|
||||
`
|
||||
},
|
||||
]);
|
||||
})
|
||||
});
|
@ -11,12 +11,12 @@ describe('generateApiListDoc processor', () => {
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run after "extra-docs-added"', () => {
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||
});
|
||||
|
||||
it('should run before "rendering-docs"', () => {
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['rendering-docs']);
|
||||
});
|
||||
|
@ -16,12 +16,12 @@ describe('generateKeywords processor', () => {
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run after "paths-computed"', () => {
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory(mockLogger, mockReadFilesProcessor);
|
||||
expect(processor.$runAfter).toEqual(['paths-computed']);
|
||||
});
|
||||
|
||||
it('should run before "rendering-docs"', () => {
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory(mockLogger, mockReadFilesProcessor);
|
||||
expect(processor.$runBefore).toEqual(['rendering-docs']);
|
||||
});
|
||||
|
@ -0,0 +1,50 @@
|
||||
module.exports = function processNavigationMap(versionInfo, log) {
|
||||
return {
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
|
||||
const navigationDoc = docs.find(doc => doc.docType === 'navigation-map');
|
||||
|
||||
if (!navigationDoc) {
|
||||
throw new Error(
|
||||
'Missing navigation map document (docType="navigation-map").' +
|
||||
'Did you forget to add it to the readFileProcessor?');
|
||||
}
|
||||
|
||||
// Verify that all the navigation paths are to valid docs
|
||||
const pathMap = {};
|
||||
docs.forEach(doc => pathMap[doc.path] = true);
|
||||
const errors = walk(navigationDoc.data, pathMap, []);
|
||||
|
||||
if (errors.length) {
|
||||
log.error(`Navigation doc: ${navigationDoc.fileInfo.relativePath} contains invalid urls`);
|
||||
console.log(errors);
|
||||
// TODO(petebd): fail if there are errors: throw new Error('processNavigationMap failed');
|
||||
}
|
||||
|
||||
// Add in the version data in a "secret" field to be extracted in the docs app
|
||||
navigationDoc.data['__versionInfo'] = versionInfo.currentVersion;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function walk(node, map, path) {
|
||||
let errors = [];
|
||||
for(const key in node) {
|
||||
const child = node[key];
|
||||
if (key === 'url') {
|
||||
const url = child.replace(/#.*$/, ''); // strip hash
|
||||
if (isRelative(url) && !map[url]) {
|
||||
errors.push({ path: path.join('.'), url });
|
||||
}
|
||||
} else if (typeof child !== 'string') {
|
||||
errors = errors.concat(walk(child, map, path.concat([key])));
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
function isRelative(url) {
|
||||
return !/^(https?:)?\/\//.test(url);
|
||||
}
|
19
aio/transforms/angular.io-package/readers/navigation.js
Normal file
19
aio/transforms/angular.io-package/readers/navigation.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Read in the navigation JSON
|
||||
*/
|
||||
module.exports = function navigationFileReader() {
|
||||
return {
|
||||
name: 'navigationFileReader',
|
||||
getDocs: function(fileInfo) {
|
||||
|
||||
// We return a single element array because content files only contain one document
|
||||
return [{
|
||||
docType: 'navigation-map',
|
||||
data: JSON.parse(fileInfo.content),
|
||||
template: 'json-doc.template.json',
|
||||
id: 'navigation',
|
||||
aliases: ['navigation', 'navigation.json']
|
||||
}];
|
||||
}
|
||||
};
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
var Package = require('dgeni').Package;
|
||||
|
||||
module.exports = new Package(
|
||||
'cheatsheet',
|
||||
[
|
||||
require('../content-package'), require('../target-package'),
|
||||
require('dgeni-packages/git'), require('dgeni-packages/nunjucks')
|
||||
])
|
||||
|
||||
.factory(require('./services/cheatsheetItemParser'))
|
||||
.processor(require('./processors/createCheatsheetDoc'))
|
||||
|
||||
.config(function(parseTagsProcessor, getInjectables) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat(
|
||||
getInjectables(require('./tag-defs')));
|
||||
});
|
@ -1,48 +0,0 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = function createCheatsheetDoc(
|
||||
createDocMessage, renderMarkdown, versionInfo, targetEnvironments) {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
$process: function(docs) {
|
||||
|
||||
var currentEnvironment = targetEnvironments.isActive('ts') && 'TypeScript' ||
|
||||
targetEnvironments.isActive('js') && 'JavaScript' ||
|
||||
targetEnvironments.isActive('dart') && 'Dart';
|
||||
|
||||
var cheatsheetDoc = {
|
||||
id: 'cheatsheet',
|
||||
aliases: ['cheatsheet'],
|
||||
docType: 'cheatsheet-data',
|
||||
sections: [],
|
||||
version: versionInfo,
|
||||
currentEnvironment: currentEnvironment
|
||||
};
|
||||
|
||||
docs = docs.filter(function(doc) {
|
||||
if (doc.docType === 'cheatsheet-section') {
|
||||
var section = _.pick(doc, ['name', 'description', 'items', 'index']);
|
||||
|
||||
// Let's make sure that the descriptions are rendered as markdown
|
||||
section.description = renderMarkdown(section.description);
|
||||
section.items.forEach(function(item) {
|
||||
item.description = renderMarkdown(item.description);
|
||||
});
|
||||
|
||||
|
||||
cheatsheetDoc.sections.push(section);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Sort the sections by their index
|
||||
cheatsheetDoc.sections.sort(function(a, b) { return a.index - b.index; });
|
||||
|
||||
docs.push(cheatsheetDoc);
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
@ -1,125 +0,0 @@
|
||||
/**
|
||||
* @dgService
|
||||
* @description
|
||||
* Parse the text from a cheatsheetItem tag into a cheatsheet item object
|
||||
* The text must contain a syntax block followed by zero or more bold matchers and finally a
|
||||
* description
|
||||
* The syntax block and bold matchers must be wrapped in backticks and be separated by pipes.
|
||||
* For example
|
||||
*
|
||||
* ```
|
||||
* `<div [ng-switch]="conditionExpression">
|
||||
* <template [ng-switch-when]="case1Exp">...</template>
|
||||
* <template ng-switch-when="case2LiteralString">...</template>
|
||||
* <template ng-switch-default>...</template>
|
||||
* </div>`|`[ng-switch]`|`[ng-switch-when]`|`ng-switch-when`|`ng-switch-default`
|
||||
* Conditionally swaps the contents of the div by selecting one of the embedded templates based on
|
||||
* the current value of conditionExpression.
|
||||
* ```
|
||||
*
|
||||
* will be parsed into
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* syntax: '<div [ng-switch]="conditionExpression">\n'+
|
||||
* ' <template [ng-switch-when]="case1Exp">...</template>\n'+
|
||||
* ' <template ng-switch-when="case2LiteralString">...</template>\n'+
|
||||
* ' <template ng-switch-default>...</template>\n'+
|
||||
* '</div>',
|
||||
* bold: ['[ng-switch]', '[ng-switch-when]', 'ng-switch-when', 'ng-switch-default'],
|
||||
* description: 'Conditionally swaps the contents of the div by selecting one of the embedded
|
||||
* templates based on the current value of conditionExpression.'
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
module.exports =
|
||||
function cheatsheetItemParser(targetEnvironments) {
|
||||
return function(text) {
|
||||
var fields = getFields(text, ['syntax', 'description']);
|
||||
|
||||
var item = {syntax: '', bold: [], description: ''};
|
||||
|
||||
fields.forEach(function(field) {
|
||||
if (!field.languages || targetEnvironments.someActive(field.languages)) {
|
||||
switch (field.name) {
|
||||
case 'syntax':
|
||||
parseSyntax(field.value.trim());
|
||||
break;
|
||||
case 'description':
|
||||
item.description = field.value.trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return item;
|
||||
|
||||
function parseSyntax(text) {
|
||||
var index = 0;
|
||||
|
||||
if (text.charAt(index) !== '`') throw new Error('item syntax must start with a backtick');
|
||||
|
||||
var start = index + 1;
|
||||
index = text.indexOf('`', start);
|
||||
if (index === -1) throw new Error('item syntax must end with a backtick');
|
||||
item.syntax = text.substring(start, index);
|
||||
start = index + 1;
|
||||
|
||||
// skip to next pipe
|
||||
while (index < text.length && text.charAt(index) !== '|') index += 1;
|
||||
|
||||
while (text.charAt(start) === '|') {
|
||||
start += 1;
|
||||
|
||||
// skip whitespace
|
||||
while (start < text.length && /\s/.test(text.charAt(start))) start++;
|
||||
|
||||
if (text.charAt(start) !== '`') throw new Error('bold matcher must start with a backtick');
|
||||
|
||||
start += 1;
|
||||
index = text.indexOf('`', start);
|
||||
if (index === -1) throw new Error('bold matcher must end with a backtick');
|
||||
item.bold.push(text.substring(start, index));
|
||||
start = index + 1;
|
||||
}
|
||||
|
||||
if (start !== text.length) {
|
||||
throw new Error(
|
||||
'syntax field must only contain a syntax code block and zero or more bold ' +
|
||||
'matcher code blocks, delimited by pipes.\n' +
|
||||
'Instead it was "' + text + '"');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getFields(text, fieldNames) {
|
||||
var FIELD_START = /^([^:(]+)\(?([^)]+)?\)?:$/;
|
||||
var lines = text.split('\n');
|
||||
var fields = [];
|
||||
var field, line;
|
||||
while (lines.length) {
|
||||
line = lines.shift();
|
||||
var match = FIELD_START.exec(line);
|
||||
if (match && fieldNames.indexOf(match[1]) !== -1) {
|
||||
// start new field
|
||||
if (field) {
|
||||
fields.push(field);
|
||||
}
|
||||
field = {name: match[1], languages: (match[2] && match[2].split(' ')), value: ''};
|
||||
} else {
|
||||
if (!field)
|
||||
throw new Error(
|
||||
'item must start with one of the following field specifiers:\n' +
|
||||
fieldNames.map(function(field) { return field + ':'; }).join('\n') + '\n' +
|
||||
'but instead it contained: "' + text + '"');
|
||||
field.value += line + '\n';
|
||||
}
|
||||
}
|
||||
if (field) {
|
||||
fields.push(field);
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
var testPackage = require('../../helpers/test-package');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('cheatsheetItemParser', function() {
|
||||
var dgeni, injector, cheatsheetItemParser;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([testPackage('cheatsheet-package')]);
|
||||
injector = dgeni.configureInjector();
|
||||
cheatsheetItemParser = injector.get('cheatsheetItemParser');
|
||||
var targetEnvironments = injector.get('targetEnvironments');
|
||||
targetEnvironments.addAllowed('js');
|
||||
targetEnvironments.addAllowed('ts', true);
|
||||
});
|
||||
|
||||
describe('no language targets', function() {
|
||||
it('should extract the syntax', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`'))
|
||||
.toEqual({syntax: 'abc', bold: [], description: ''});
|
||||
});
|
||||
|
||||
it('should extract the bolds', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`|`bold1`|`bold2`'))
|
||||
.toEqual({syntax: 'abc', bold: ['bold1', 'bold2'], description: ''});
|
||||
});
|
||||
|
||||
it('should extract the description', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`|`bold1`|`bold2`\ndescription:\nsome description'))
|
||||
.toEqual({syntax: 'abc', bold: ['bold1', 'bold2'], description: 'some description'});
|
||||
});
|
||||
|
||||
it('should allow bold to be optional', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`\ndescription:\nsome description'))
|
||||
.toEqual({syntax: 'abc', bold: [], description: 'some description'});
|
||||
});
|
||||
|
||||
it('should allow whitespace between the parts', function() {
|
||||
expect(cheatsheetItemParser(
|
||||
'syntax:\n`abc`| `bold1`| `bold2`\ndescription:\n\nsome description'))
|
||||
.toEqual({syntax: 'abc', bold: ['bold1', 'bold2'], description: 'some description'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with language targets', function() {
|
||||
it('should extract the active language', function() {
|
||||
expect(cheatsheetItemParser(
|
||||
'syntax(ts):\n`abc`|`bold1`|`bold2`\ndescription(ts):\nsome description'))
|
||||
.toEqual({syntax: 'abc', bold: ['bold1', 'bold2'], description: 'some description'});
|
||||
});
|
||||
|
||||
it('should ignore the non-active language', function() {
|
||||
expect(cheatsheetItemParser(
|
||||
'syntax(js):\n`abc`|`bold1`|`bold2`\ndescription(js):\nsome description'))
|
||||
.toEqual({syntax: '', bold: [], description: ''});
|
||||
});
|
||||
|
||||
it('should select the active language and ignore non-active language', function() {
|
||||
expect(cheatsheetItemParser(
|
||||
'syntax(js):\n`JS`|`boldJS``\n' +
|
||||
'syntax(ts):\n`TS`|`boldTS`\n' +
|
||||
'description(js):\nJS description\n' +
|
||||
'description(ts):\nTS description'))
|
||||
.toEqual({syntax: 'TS', bold: ['boldTS'], description: 'TS description'});
|
||||
});
|
||||
|
||||
it('should error if a language target is used that is not allowed', function() {
|
||||
expect(function() {
|
||||
cheatsheetItemParser(
|
||||
'syntax(dart):\n`abc`|`bold1`|`bold2`\ndescription(ts):\nsome description');
|
||||
})
|
||||
.toThrowError(
|
||||
'Error accessing target "dart". It is not in the list of allowed targets: js,ts');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
module.exports = function(createDocMessage) {
|
||||
return {
|
||||
name: 'cheatsheetIndex',
|
||||
docProperty: 'index',
|
||||
transforms: function(doc, tag, value) {
|
||||
try {
|
||||
return parseInt(value, 10);
|
||||
} catch (x) {
|
||||
throw new Error(
|
||||
createDocMessage('"@' + tag.tagName + '" must be followed by a number', doc));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
module.exports = function(createDocMessage, cheatsheetItemParser) {
|
||||
return {
|
||||
name: 'cheatsheetItem',
|
||||
multi: true,
|
||||
docProperty: 'items',
|
||||
transforms: function(doc, tag, value) {
|
||||
try {
|
||||
return cheatsheetItemParser(value);
|
||||
} catch (x) {
|
||||
throw new Error(createDocMessage(
|
||||
'"@' + tag.tagName + '" tag has an invalid format - ' + x.message, doc));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
module.exports = function() {
|
||||
return {
|
||||
name: 'cheatsheetSection',
|
||||
docProperty: 'docType',
|
||||
transforms: function(doc, tag, value) {
|
||||
doc.name = value ? value.trim() : '';
|
||||
return 'cheatsheet-section';
|
||||
}
|
||||
};
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
module.exports =
|
||||
[require('./cheatsheet-section'), require('./cheatsheet-index'), require('./cheatsheet-item')];
|
@ -28,40 +28,48 @@ module.exports = function exampleInlineTagDef(
|
||||
var unnamedArgs = tagArgs._;
|
||||
var relativePath = unnamedArgs[0];
|
||||
var regionName = tagArgs.region || (unnamedArgs.length > 1 ? unnamedArgs[1] : '');
|
||||
var title = tagArgs.title || (unnamedArgs.length > 2 ? unnamedArgs[2] : null);
|
||||
if (regionName === '\'\'') regionName = '';
|
||||
var title = tagArgs.title || (unnamedArgs.length > 2 ? unnamedArgs.slice(2).join(' ') : null);
|
||||
var linenums = tagArgs.linenums;
|
||||
var stylePattern = tagArgs.stylePattern; // TODO: not yet implemented here
|
||||
|
||||
// Find the example in the folders
|
||||
var exampleFile;
|
||||
// Try an "annotated" version first
|
||||
EXAMPLES_FOLDERS.some(
|
||||
EXAMPLES_FOLDER => { return exampleFile = exampleMap[EXAMPLES_FOLDER][relativePath + '.annotated']; });
|
||||
const sourceCode = getExampleRegion();
|
||||
|
||||
// If no annotated version is available then try the actual file
|
||||
if (!exampleFile) {
|
||||
EXAMPLES_FOLDERS.some(
|
||||
EXAMPLES_FOLDER => { return exampleFile = exampleMap[EXAMPLES_FOLDER][relativePath]; });
|
||||
const attributes = [];
|
||||
if (title) attributes.push(` title="${title}"`);
|
||||
if (linenums !== undefined) attributes.push(` linenums="${linenums}"`);
|
||||
|
||||
return '<code-example' + attributes.join('') + '>\n' + sourceCode + '\n</code-example>';
|
||||
|
||||
|
||||
function getExampleRegion() {
|
||||
// Find the example in the folders
|
||||
var exampleFile;
|
||||
// Try an "annotated" version first
|
||||
EXAMPLES_FOLDERS.some(EXAMPLES_FOLDER => { return exampleFile = exampleMap[EXAMPLES_FOLDER][relativePath + '.annotated']; });
|
||||
|
||||
// If no annotated version is available then try the actual file
|
||||
if (!exampleFile) {
|
||||
EXAMPLES_FOLDERS.some(EXAMPLES_FOLDER => { return exampleFile = exampleMap[EXAMPLES_FOLDER][relativePath]; });
|
||||
}
|
||||
|
||||
// If still no file then we error
|
||||
if (!exampleFile) {
|
||||
log.error(createDocMessage('Missing example file... relativePath: "' + relativePath + '".', doc));
|
||||
log.error('Example files can be found in: ' + EXAMPLES_FOLDERS.join(', '));
|
||||
return '';
|
||||
}
|
||||
|
||||
var sourceCodeDoc = exampleFile.regions[regionName];
|
||||
if (!sourceCodeDoc) {
|
||||
log.error(createDocMessage('Missing example region... relativePath: "' + relativePath + '", region: "' + regionName + '".', doc));
|
||||
log.error('Regions available are:', Object.keys[exampleFile.regions]);
|
||||
return '';
|
||||
}
|
||||
|
||||
return sourceCodeDoc.renderedContent;
|
||||
}
|
||||
|
||||
// If still no file then we error
|
||||
if (!exampleFile) {
|
||||
log.error(
|
||||
createDocMessage('Missing example file... relativePath: "' + relativePath + '".', doc));
|
||||
log.error('Example files can be found in: ' + EXAMPLES_FOLDERS.join(', '));
|
||||
return '';
|
||||
}
|
||||
|
||||
var sourceCode = exampleFile.regions[regionName];
|
||||
if (!sourceCode) {
|
||||
log.error(createDocMessage(
|
||||
'Missing example region... relativePath: "' + relativePath + '", region: "' +
|
||||
regionName + '".',
|
||||
doc));
|
||||
log.error('Regions available are:', Object.keys[exampleFile.regions]);
|
||||
return '';
|
||||
}
|
||||
|
||||
return sourceCode.renderedContent;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
var testPackage = require('../../helpers/test-package');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('example inline-tag-def', function() {
|
||||
let injector, tag, collectExamples, exampleMap;
|
||||
|
||||
beforeEach(() => {
|
||||
const dgeni = new Dgeni([testPackage('examples-package', true)]);
|
||||
injector = dgeni.configureInjector();
|
||||
tag = injector.get('exampleInlineTagDef');
|
||||
collectExamples = injector.get('collectExamples');
|
||||
exampleMap = injector.get('exampleMap');
|
||||
});
|
||||
|
||||
it('should be available as a service', () => {
|
||||
expect(tag).toBeDefined();
|
||||
expect(tag.name).toEqual('example');
|
||||
});
|
||||
|
||||
describe('handler', () => {
|
||||
let handler;
|
||||
|
||||
beforeEach(() => {
|
||||
handler = tag.handler;
|
||||
collectExamples.exampleFolders = ['examples'];
|
||||
exampleMap['examples'] = {
|
||||
'test/url': { regions: {
|
||||
'': { renderedContent: 'whole file' },
|
||||
'region-1': { renderedContent: 'region 1 contents' }
|
||||
} }
|
||||
};
|
||||
});
|
||||
|
||||
it('should return a <code-example> tag', () => {
|
||||
expect(handler({}, 'example', 'some/uri')).toEqual('<code-example>\n\n</code-example>');
|
||||
});
|
||||
|
||||
it('should contain the whole contents from the example file if no region is specified', () => {
|
||||
expect(handler({}, 'example', 'test/url')).toEqual('<code-example>\nwhole file\n</code-example>');
|
||||
});
|
||||
|
||||
it('should contain the region contents from the example file if a region is specified', () => {
|
||||
expect(handler({}, 'example', 'test/url region-1')).toEqual('<code-example>\nregion 1 contents\n</code-example>');
|
||||
});
|
||||
|
||||
it('should add a title if specified', () => {
|
||||
expect(handler({}, 'example', 'test/url region-1 \'Some Title\'')).toEqual('<code-example title="Some Title">\nregion 1 contents\n</code-example>');
|
||||
expect(handler({}, 'example', 'test/url region-1 Some Title')).toEqual('<code-example title="Some Title">\nregion 1 contents\n</code-example>');
|
||||
});
|
||||
|
||||
it('should contain the whole contents from the example file if an empty ("") region is specified', () => {
|
||||
expect(handler({}, 'example', 'test/url \'\'')).toEqual('<code-example>\nwhole file\n</code-example>');
|
||||
expect(handler({}, 'example', 'test/url \'\' Some Title')).toEqual('<code-example title="Some Title">\nwhole file\n</code-example>');
|
||||
});
|
||||
|
||||
it('should add in linenum attribute if specified', () => {
|
||||
expect(handler({}, 'example', 'test/url --linenums=\'false\'')).toEqual('<code-example linenums="false">\nwhole file\n</code-example>');
|
||||
expect(handler({}, 'example', 'test/url --linenums=\'true\'')).toEqual('<code-example linenums="true">\nwhole file\n</code-example>');
|
||||
expect(handler({}, 'example', 'test/url --linenums=\'15\'')).toEqual('<code-example linenums="15">\nwhole file\n</code-example>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -39,7 +39,10 @@ module.exports = function parseArgString() {
|
||||
} else {
|
||||
if (arg.substr(arg.length - 1) === '=') {
|
||||
key = arg.substr(0, arg.length - 1);
|
||||
// remove leading '-' if it exists.
|
||||
// remove leading '-' (or '--') if it exists.
|
||||
if (key.substr(0, 1) == '-') {
|
||||
key = key.substr(1);
|
||||
}
|
||||
if (key.substr(0, 1) == '-') {
|
||||
key = key.substr(1);
|
||||
}
|
||||
|
@ -1,7 +1 @@
|
||||
<div class="code-example">
|
||||
{% marked %}
|
||||
```
|
||||
{$ doc.contents $}
|
||||
```
|
||||
{% endmarked %}
|
||||
</div>
|
||||
{$ doc.contents | escape $}
|
@ -1,5 +1,5 @@
|
||||
{% macro githubHref(doc, versionInfo) -%}
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/modules/{$ doc.fileInfo.projectRelativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/packages/{$ doc.fileInfo.projectRelativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro githubViewLink(doc, versionInfo) -%}
|
||||
|
125
aio/yarn.lock
125
aio/yarn.lock
@ -3,19 +3,15 @@
|
||||
|
||||
|
||||
"@angular/animations@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.0.0-rc.2.tgz#b4818712cfb576e831cf9d108754463f00c111b9"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.0.0-rc.6.tgz#a19d7512dd769102453c68b949d2478f69d3520f"
|
||||
|
||||
"@angular/cli@^1.0.0-rc.0":
|
||||
version "1.0.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.0.0-rc.0.tgz#dcf9e1d1f4ed886ca59de30a67fcc5ac98a2b061"
|
||||
"@angular/cli@^1.0.0-rc.4":
|
||||
version "1.0.0-rc.4"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.0.0-rc.4.tgz#e542f95378fd996fb0bc3b9d686bf3a457fe61b4"
|
||||
dependencies:
|
||||
"@angular/compiler" ">=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0"
|
||||
"@angular/compiler-cli" ">=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0"
|
||||
"@angular/core" ">=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0"
|
||||
"@angular/tsc-wrapped" ">=0.5.0 <5.0.0 || >=4.0.0-beta <5.0.0"
|
||||
"@ngtools/json-schema" "1.0.5"
|
||||
"@ngtools/webpack" "1.2.11"
|
||||
"@ngtools/webpack" "1.2.14"
|
||||
autoprefixer "^6.5.3"
|
||||
chalk "^1.1.3"
|
||||
common-tags "^1.3.1"
|
||||
@ -45,7 +41,6 @@
|
||||
lodash "^4.11.1"
|
||||
minimatch "^3.0.3"
|
||||
node-modules-path "^1.0.0"
|
||||
node-sass "^4.3.0"
|
||||
nopt "^4.0.1"
|
||||
opn "4.0.2"
|
||||
portfinder "~1.0.12"
|
||||
@ -72,68 +67,70 @@
|
||||
webpack-dev-server "~2.3.0"
|
||||
webpack-merge "^2.4.0"
|
||||
zone.js "^0.7.2"
|
||||
optionalDependencies:
|
||||
node-sass "^4.3.0"
|
||||
|
||||
"@angular/common@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.0.0-rc.2.tgz#69f68639270d71b2e8c552e4fa939975fcb88304"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.0.0-rc.6.tgz#f6855c36e1c8e1b7ce94c0739a1fa277a9d29584"
|
||||
|
||||
"@angular/compiler-cli@>=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0", "@angular/compiler-cli@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.0.0-rc.2.tgz#49730cb232d48aba25d68541eb9166bf5330dd2b"
|
||||
"@angular/compiler-cli@next":
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.0.0-rc.6.tgz#3d4ed77ea7a37703d1f5bb974619509885f1084b"
|
||||
dependencies:
|
||||
"@angular/tsc-wrapped" "4.0.0-rc.2"
|
||||
"@angular/tsc-wrapped" "4.0.0-rc.6"
|
||||
minimist "^1.2.0"
|
||||
reflect-metadata "^0.1.2"
|
||||
|
||||
"@angular/compiler@>=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0", "@angular/compiler@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.0.0-rc.2.tgz#643e199e6792413f42cf149a9cf1672284787c11"
|
||||
"@angular/compiler@next":
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.0.0-rc.6.tgz#b46cd4c0c732eafac5a8658ca2d5d9b953906e99"
|
||||
|
||||
"@angular/core@>=2.3.1 <5.0.0 || >=4.0.0-beta <5.0.0", "@angular/core@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.0.0-rc.2.tgz#59535050e5d0e6141417186eee571296f8e9c3d0"
|
||||
"@angular/core@next":
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.0.0-rc.6.tgz#ba70534bd45f3bda3ac39fb0a90d552510436dec"
|
||||
|
||||
"@angular/forms@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.0.0-rc.2.tgz#6d9df97783b6023d652d97369db13d6ad6c7fa9e"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.0.0-rc.6.tgz#b075ca2bf0f0a37c84d1dcb67ac59ae334c1a392"
|
||||
|
||||
"@angular/http@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.0.0-rc.2.tgz#145ecd17f483b97e7750bb9e00b60e48ff82b67a"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.0.0-rc.6.tgz#ebeb95a92725d6481b418b4a7beafd9281cc0e5c"
|
||||
|
||||
"@angular/material@https://github.com/angular/material2-builds":
|
||||
version "2.0.0-beta.2"
|
||||
resolved "https://github.com/angular/material2-builds#d7f549850cfd94b31bb624e2702b61305fd6337d"
|
||||
|
||||
"@angular/platform-browser-dynamic@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.0.0-rc.2.tgz#f2bbab322706dc6361d46647e1e2b7c26f036a1c"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.0.0-rc.6.tgz#89dfce31283fb3fc1b484ffa620cd2b5f292ecdd"
|
||||
|
||||
"@angular/platform-browser@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.0.0-rc.2.tgz#bcca05ce85d320ee0b257640f15479b59fed20f0"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.0.0-rc.6.tgz#bce3be3ee8a62b91a591f4b3cb894a1bc39c6da7"
|
||||
|
||||
"@angular/platform-server@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.0.0-rc.2.tgz#3b09f4e2f2dc1b7d723fbbdc6b99117019c0f9de"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.0.0-rc.6.tgz#89bbbae2806252a350b46e18e0d8933618370e47"
|
||||
dependencies:
|
||||
parse5 "^3.0.1"
|
||||
xhr2 "^0.1.4"
|
||||
|
||||
"@angular/router@next":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.0.0-rc.2.tgz#66fc5be012caa38441314d0a0b9c9b6a723c471a"
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.0.0-rc.6.tgz#3a02bb095f73e9db180576f38c73ab2a3a5bf0a0"
|
||||
|
||||
"@angular/service-worker@^1.0.0-beta.6":
|
||||
version "1.0.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-1.0.0-beta.6.tgz#ae3ca0b43ab1cbd572a191b2ef3e1b787f71ed1e"
|
||||
"@angular/service-worker@^1.0.0-beta.7":
|
||||
version "1.0.0-beta.7"
|
||||
resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-1.0.0-beta.7.tgz#e8edd2e993948caffc2d45d6935667f9b5a3c221"
|
||||
dependencies:
|
||||
base64-js "^1.1.2"
|
||||
jshashes "^1.0.5"
|
||||
|
||||
"@angular/tsc-wrapped@4.0.0-rc.2", "@angular/tsc-wrapped@>=0.5.0 <5.0.0 || >=4.0.0-beta <5.0.0":
|
||||
version "4.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.0.0-rc.2.tgz#d7023d93f4576b6f776ffc7175ff760e7e133705"
|
||||
"@angular/tsc-wrapped@4.0.0-rc.6":
|
||||
version "4.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.0.0-rc.6.tgz#95a82148ece7d3ebd9606e9fba2cb7758e3ea8ae"
|
||||
dependencies:
|
||||
tsickle "^0.21.0"
|
||||
|
||||
@ -141,12 +138,12 @@
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.0.5.tgz#ad39037c70c88b245ac7267a71777646b6063d77"
|
||||
|
||||
"@ngtools/webpack@1.2.11":
|
||||
version "1.2.11"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.2.11.tgz#b587b1e7eb88bd68b973681669c00e7b4b7f8ea0"
|
||||
"@ngtools/webpack@1.2.14":
|
||||
version "1.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.2.14.tgz#ff59f504196871e69b5d01a21ea747d6f8e5e546"
|
||||
dependencies:
|
||||
enhanced-resolve "^3.1.0"
|
||||
loader-utils "^0.2.16"
|
||||
loader-utils "^1.0.2"
|
||||
magic-string "^0.19.0"
|
||||
source-map "^0.5.6"
|
||||
|
||||
@ -1559,9 +1556,9 @@ detect-indent@^4.0.0:
|
||||
dependencies:
|
||||
repeating "^2.0.0"
|
||||
|
||||
dgeni-packages@^0.16.8:
|
||||
version "0.16.8"
|
||||
resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.16.8.tgz#e0596f1902ef76799576bed7bcc1d69943f853a3"
|
||||
dgeni-packages@0.17.0:
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.17.0.tgz#b2e5117670e99109f664703af26a460a5064d6cc"
|
||||
dependencies:
|
||||
canonical-path "0.0.2"
|
||||
catharsis "^0.8.1"
|
||||
@ -5308,9 +5305,9 @@ restore-cursor@^2.0.0:
|
||||
onetime "^2.0.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
rho@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/rho/-/rho-0.3.0.tgz#a7ac95df240141936d1bf9d8f8e4880588c73dd3"
|
||||
"rho@https://github.com/petebacondarwin/rho#heading-fix":
|
||||
version "0.4.0"
|
||||
resolved "https://github.com/petebacondarwin/rho#dcc9780a59d6bf6a62abe2fca4b08db6629da2ca"
|
||||
dependencies:
|
||||
html "*"
|
||||
nomnom "*"
|
||||
@ -5327,6 +5324,12 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
|
||||
rimraf@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
|
||||
rimraf@~2.2.6:
|
||||
version "2.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"
|
||||
@ -5377,7 +5380,7 @@ rx@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
|
||||
|
||||
rxjs@^5.0.1, rxjs@^5.1.0:
|
||||
rxjs@^5.0.1, rxjs@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.2.0.tgz#db537de8767c05fa73721587a29e0085307d318b"
|
||||
dependencies:
|
||||
@ -5547,8 +5550,8 @@ sha.js@^2.3.6:
|
||||
inherits "^2.0.1"
|
||||
|
||||
shelljs@^0.7.0:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
|
||||
version "0.7.7"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1"
|
||||
dependencies:
|
||||
glob "^7.0.0"
|
||||
interpret "^1.0.0"
|
||||
@ -6228,14 +6231,10 @@ underscore-contrib@~0.3.0:
|
||||
dependencies:
|
||||
underscore "1.6.0"
|
||||
|
||||
underscore@1.6.0, underscore@~1.6.0:
|
||||
underscore@1.6.0, underscore@1.x, underscore@~1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
|
||||
|
||||
underscore@1.x:
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
|
||||
|
||||
uniq@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
|
||||
@ -6835,10 +6834,10 @@ zip-stream@~0.6.0:
|
||||
lodash "~3.10.1"
|
||||
readable-stream "~1.0.26"
|
||||
|
||||
zone.js@0.7.8:
|
||||
zone.js@^0.7.2:
|
||||
version "0.7.8"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.8.tgz#4f3fe8834d44597f2639053a0fa438df34fffded"
|
||||
|
||||
zone.js@^0.7.2:
|
||||
version "0.7.7"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.7.tgz#0d7b7ae7f68012d03438b8a18f5763441bbf9620"
|
||||
zone.js@^0.8.4:
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.4.tgz#cc40ae5a1c879601c5ebba2096b5c80f0c4c3602"
|
||||
|
7
build.sh
7
build.sh
@ -12,9 +12,9 @@ PACKAGES=(core
|
||||
compiler
|
||||
common
|
||||
animations
|
||||
forms
|
||||
platform-browser
|
||||
platform-browser-dynamic
|
||||
forms
|
||||
http
|
||||
platform-server
|
||||
platform-webworker
|
||||
@ -267,7 +267,7 @@ compilePackage() {
|
||||
$NGC -p ${1}/tsconfig-build.json
|
||||
echo "====== Create ${1}/../${package_name}.d.ts re-export file for Closure"
|
||||
echo "$(cat ${LICENSE_BANNER}) ${N} export * from './${package_name}/index'" > ${2}/../${package_name}.d.ts
|
||||
echo "{\"alias\": \"./${package_name}/index.metadata.json\"}" > ${2}/../${package_name}.metadata.json
|
||||
echo "{\"__symbolic\":\"module\",\"version\":3,\"metadata\":{},\"exports\":[{\"from\":\"./${package_name}/index\"}]}" > ${2}/../${package_name}.metadata.json
|
||||
fi
|
||||
|
||||
for DIR in ${1}/* ; do
|
||||
@ -472,8 +472,9 @@ do
|
||||
rsync -a ${OUT_DIR}/ ${NPM_DIR}
|
||||
fi
|
||||
|
||||
echo "====== Copy ${PACKAGE} package.json files"
|
||||
echo "====== Copy ${PACKAGE} package.json and .externs.js files"
|
||||
rsync -am --include="package.json" --include="*/" --exclude=* ${SRC_DIR}/ ${NPM_DIR}/
|
||||
rsync -am --include="*.externs.js" --include="*/" --exclude=* ${SRC_DIR}/ ${NPM_DIR}/
|
||||
|
||||
cp ${ROOT_DIR}/README.md ${NPM_DIR}/
|
||||
fi
|
||||
|
@ -32,7 +32,7 @@ We explicitly don't consider the following to be our public API surface:
|
||||
|
||||
- any file/import paths within our package except for the `/`, `/testing` and `/bundles/*`
|
||||
- constructors of injectable classes (services and directives) - please use DI to obtain instances of these classes
|
||||
- any class members or symbols marked as `private` or prefixed with underscore
|
||||
- any class members or symbols marked as `private`, or prefixed with underscore (`_`) and [barred latin o](https://en.wikipedia.org/wiki/%C6%9F) (`ɵ`)
|
||||
- extending any of our classes unless the support for this is specifically documented in the API docs
|
||||
- the contents and API surface of the code generated by Angular's compiler (with one notable exception: the existence and name of `NgModuleFactory` instances exported from generated code is guaranteed)
|
||||
|
||||
|
@ -63,6 +63,7 @@ Week Of | Stable Release<br>(@latest npm tag) | Beta/RC Release<br>(@n
|
||||
2017-03-01 | 2.4.9 | 4.0.0-rc.2 |
|
||||
2017-03-08 | 2.4.10 | 4.0.0-rc.3 |
|
||||
2017-03-15 | 2.4.11 | 4.0.0-rc.4 |
|
||||
*2017-03-17* | | *4.0.0-rc.5* | *Unplanned release to fix compiler-cli dependency version*
|
||||
2017-03-22 | 4.0.0 + 2.4.12 | - | Major Version Release
|
||||
|
||||
|
||||
|
@ -34,7 +34,7 @@ CLOSURE_ARGS=(
|
||||
# Uncomment for easier debugging
|
||||
# "--formatting=PRETTY_PRINT"
|
||||
|
||||
e2e/testability.externs.js
|
||||
node_modules/@angular/core/src/testability/testability.externs.js
|
||||
node_modules/zone.js/dist/zone.js
|
||||
$(find -L vendor/rxjs -name *.js)
|
||||
node_modules/@angular/core/@angular/core.js
|
||||
|
@ -1,47 +0,0 @@
|
||||
/** @externs */
|
||||
// Workaround for #11119
|
||||
// TODO(alexeagle): these externs ought to be distributed with Angular.
|
||||
/**
|
||||
* @externs
|
||||
* @suppress {duplicate}
|
||||
*/
|
||||
// NOTE: generated by tsickle, do not edit.
|
||||
|
||||
/** @record @struct */
|
||||
function BrowserNodeGlobal() {}
|
||||
/** @type {?} */
|
||||
BrowserNodeGlobal.prototype.getAngularTestability;
|
||||
/** @type {?} */
|
||||
BrowserNodeGlobal.prototype.getAllAngularTestabilities;
|
||||
/** @type {?} */
|
||||
BrowserNodeGlobal.prototype.getAllAngularRootElements;
|
||||
/** @type {?} */
|
||||
BrowserNodeGlobal.prototype.frameworkStabilizers;
|
||||
|
||||
/**
|
||||
* @param {?} condition
|
||||
* @return {?}
|
||||
*/
|
||||
BrowserNodeGlobal.prototype.assert = function(condition) {};
|
||||
|
||||
/** @record @struct */
|
||||
function PublicTestability() {}
|
||||
|
||||
/**
|
||||
* @return {?}
|
||||
*/
|
||||
PublicTestability.prototype.isStable = function() {};
|
||||
|
||||
/**
|
||||
* @param {?} callback
|
||||
* @return {?}
|
||||
*/
|
||||
PublicTestability.prototype.whenStable = function(callback) {};
|
||||
|
||||
/**
|
||||
* @param {?} using
|
||||
* @param {?} provider
|
||||
* @param {?} exactMatch
|
||||
* @return {?}
|
||||
*/
|
||||
PublicTestability.prototype.findProviders = function(using, provider, exactMatch) {};
|
@ -3,6 +3,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "file:../../dist/packages-dist/animations",
|
||||
"@angular/common": "file:../../dist/packages-dist/common",
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
|
@ -7,7 +7,8 @@
|
||||
"compilerOptions": {
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"strictNullChecks": true,
|
||||
// TODO(i): strictNullChecks should turned on but are temporarily disabled due to #15432
|
||||
"strictNullChecks": false,
|
||||
"target": "es6",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
|
3
integration/hello_world__systemjs_umd/.gitignore
vendored
Normal file
3
integration/hello_world__systemjs_umd/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
**/*.js
|
||||
**/*.js.map
|
||||
!src/systemjs.config.js
|
14
integration/hello_world__systemjs_umd/bs-config.e2e.json
Normal file
14
integration/hello_world__systemjs_umd/bs-config.e2e.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"open": false,
|
||||
"logLevel": "silent",
|
||||
"port": 8000,
|
||||
"server": {
|
||||
"baseDir": "src",
|
||||
"routes": {
|
||||
"/node_modules": "node_modules"
|
||||
},
|
||||
"middleware": {
|
||||
"0": null
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Hello world E2E Tests', function () {
|
||||
it('should display: Hello world!', function () {
|
||||
browser.get('');
|
||||
expect(element(by.css('div')).getText()).toEqual('Hello world!');
|
||||
});
|
||||
});
|
11
integration/hello_world__systemjs_umd/e2e/tsconfig.json
Normal file
11
integration/hello_world__systemjs_umd/e2e/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"lib": [ "es2015", "dom" ],
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true,
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
}
|
||||
}
|
31
integration/hello_world__systemjs_umd/package.json
Normal file
31
integration/hello_world__systemjs_umd/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "angular-integration",
|
||||
"description": "Ensure SystemJS ^0.22 UMD compatibility via __esModule flag.",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "concurrently \"npm run serve\" \"npm run protractor\" --kill-others --success first",
|
||||
"serve": "lite-server -c bs-config.e2e.json",
|
||||
"preprotractor": "tsc -p e2e",
|
||||
"protractor": "protractor protractor.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "file:../../dist/packages-dist/common",
|
||||
"@angular/core": "file:../../dist/packages-dist/core",
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
|
||||
"@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic",
|
||||
"core-js": "2.4.1",
|
||||
"plugin-typescript": "6.0.4",
|
||||
"rxjs": "file:../../node_modules/rxjs",
|
||||
"systemjs": "0.20.2",
|
||||
"typescript": "2.1.6",
|
||||
"zone.js": "0.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "2.5.41",
|
||||
"concurrently": "3.1.0",
|
||||
"lite-server": "2.2.2",
|
||||
"protractor": "file:../../node_modules/protractor"
|
||||
}
|
||||
}
|
16
integration/hello_world__systemjs_umd/protractor.config.js
Normal file
16
integration/hello_world__systemjs_umd/protractor.config.js
Normal file
@ -0,0 +1,16 @@
|
||||
exports.config = {
|
||||
specs: [
|
||||
'./e2e/**/*.e2e-spec.js'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
'args': ['--no-sandbox'],
|
||||
'binary': process.env.CHROME_BIN,
|
||||
}
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:8000/',
|
||||
framework: 'jasmine',
|
||||
useAllAngular2AppRoots: true,
|
||||
};
|
11
integration/hello_world__systemjs_umd/src/app/app.ts
Normal file
11
integration/hello_world__systemjs_umd/src/app/app.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {HelloWorldComponent} from './hello-world.component';
|
||||
|
||||
import {NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HelloWorldComponent],
|
||||
bootstrap: [HelloWorldComponent],
|
||||
imports: [BrowserModule],
|
||||
})
|
||||
export class AppModule {}
|
@ -0,0 +1,10 @@
|
||||
import {Component, Injectable} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'hello-world-app',
|
||||
template: '<div>Hello {{ name }}!</div>',
|
||||
})
|
||||
@Injectable()
|
||||
export class HelloWorldComponent {
|
||||
name: string = 'world';
|
||||
}
|
21
integration/hello_world__systemjs_umd/src/index.html
Normal file
21
integration/hello_world__systemjs_umd/src/index.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hello World</title>
|
||||
<base href="/">
|
||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="systemjs.config.js"></script>
|
||||
<script>
|
||||
System.import('main.ts').catch(function (err) { console.error(err); });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<hello-world-app>Loading...</hello-world-app>
|
||||
</body>
|
||||
|
||||
</html>
|
4
integration/hello_world__systemjs_umd/src/main.ts
Normal file
4
integration/hello_world__systemjs_umd/src/main.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {AppModule} from './app/app';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
45
integration/hello_world__systemjs_umd/src/systemjs.config.js
Normal file
45
integration/hello_world__systemjs_umd/src/systemjs.config.js
Normal file
@ -0,0 +1,45 @@
|
||||
(function (global) {
|
||||
SystemJS.typescriptOptions = {
|
||||
"target": "es5",
|
||||
"module": "system",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
};
|
||||
System.config({
|
||||
transpiler: 'ts',
|
||||
meta: {
|
||||
'typescript': {
|
||||
"exports": "ts"
|
||||
}
|
||||
},
|
||||
paths: {
|
||||
'npm:': 'node_modules/'
|
||||
},
|
||||
map: {
|
||||
app: 'app',
|
||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.min.js',
|
||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.min.js',
|
||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js',
|
||||
'@angular/platform-browser':
|
||||
'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
|
||||
'@angular/platform-browser-dynamic':
|
||||
'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js',
|
||||
'rxjs': 'npm:rxjs',
|
||||
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
|
||||
'ts': 'npm:plugin-typescript/lib/plugin.js',
|
||||
'typescript': 'npm:typescript/lib/typescript.js',
|
||||
},
|
||||
packages: {
|
||||
app: {
|
||||
defaultExtension: 'ts'
|
||||
},
|
||||
rxjs: {
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
})(this);
|
13
integration/hello_world__systemjs_umd/src/tsconfig.json
Normal file
13
integration/hello_world__systemjs_umd/src/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "system",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [ "es2015", "dom" ],
|
||||
"noImplicitAny": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"license": "MIT",
|
||||
"decription": "Angular Langauge Service plugin integration test",
|
||||
"dependencies": {
|
||||
"@angular/animations": "file:../../dist/packages-dist/animations",
|
||||
"@angular/common": "file:../../dist/packages-dist/common",
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "file:../../dist/packages-dist/animations",
|
||||
"@angular/common": "file:../../dist/packages-dist/common",
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
|
@ -9,7 +9,8 @@
|
||||
"target": "es5",
|
||||
"lib": ["es5", "dom", "es2015.collection", "es2015.iterable", "es2015.promise"],
|
||||
"types": [],
|
||||
"strictNullChecks": true
|
||||
// TODO(i): strictNullChecks should turned on but are temporarily disabled due to #15432
|
||||
"strictNullChecks": false
|
||||
},
|
||||
"files": [
|
||||
"include-all.ts",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "file:../../dist/packages-dist/animations",
|
||||
"@angular/common": "file:../../dist/packages-dist/common",
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
|
@ -15,7 +15,8 @@
|
||||
"es2015.promise"
|
||||
],
|
||||
"types": [],
|
||||
"strictNullChecks": true
|
||||
// TODO(i): strictNullChecks should turned on but are temporarily disabled due to #15432
|
||||
"strictNullChecks": false
|
||||
},
|
||||
"files": [
|
||||
"include-all.ts",
|
||||
|
81
modules/benchmarks/e2e_test/tree_data.ts
Normal file
81
modules/benchmarks/e2e_test/tree_data.ts
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {$} from 'protractor';
|
||||
|
||||
export const CreateBtn = '#createDom';
|
||||
export const DestroyBtn = '#destroyDom';
|
||||
export const DetectChangesBtn = '#detectChanges';
|
||||
export const RootEl = '#root';
|
||||
export const NumberOfChecksEl = '#numberOfChecks';
|
||||
|
||||
export interface Benchmark {
|
||||
id: string;
|
||||
url: string;
|
||||
buttons: string[];
|
||||
ignoreBrowserSynchronization?: boolean;
|
||||
extraParams?: {name: string, value: any}[];
|
||||
}
|
||||
|
||||
const CreateDestroyButtons: string[] = [CreateBtn, DestroyBtn];
|
||||
const CreateDestroyDetectChangesButtons: string[] = [...CreateDestroyButtons, DetectChangesBtn];
|
||||
|
||||
export const Benchmarks: Benchmark[] = [
|
||||
{
|
||||
id: `deepTree.ng2`,
|
||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||
buttons: CreateDestroyDetectChangesButtons,
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng2.next`,
|
||||
url: 'all/benchmarks/src/tree/ng2_next/index.html',
|
||||
buttons: CreateDestroyDetectChangesButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
// Can't use bundles as we use non exported code
|
||||
extraParams: [{name: 'bundles', value: false}]
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng2.static`,
|
||||
url: 'all/benchmarks/src/tree/ng2_static/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng2_switch`,
|
||||
url: 'all/benchmarks/src/tree/ng2_switch/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
},
|
||||
{
|
||||
id: `deepTree.baseline`,
|
||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
},
|
||||
{
|
||||
id: `deepTree.incremental_dom`,
|
||||
url: 'all/benchmarks/src/tree/incremental_dom/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
},
|
||||
{
|
||||
id: `deepTree.polymer`,
|
||||
url: 'all/benchmarks/src/tree/polymer/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
},
|
||||
{
|
||||
id: `deepTree.polymer_leaves`,
|
||||
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng1`,
|
||||
url: 'all/benchmarks/src/tree/ng1/index.html',
|
||||
buttons: CreateDestroyDetectChangesButtons,
|
||||
}
|
||||
];
|
@ -7,162 +7,77 @@
|
||||
*/
|
||||
|
||||
import {runBenchmark, verifyNoBrowserErrors} from 'e2e_util/perf_util';
|
||||
import {$} from 'protractor';
|
||||
import {$, browser} from 'protractor';
|
||||
|
||||
interface Worker {
|
||||
id: string;
|
||||
prepare?(): void;
|
||||
work(): void;
|
||||
}
|
||||
|
||||
const CreateOnlyWorker: Worker = {
|
||||
id: 'createOnly',
|
||||
prepare: () => $('#destroyDom').click(),
|
||||
work: () => $('#createDom').click()
|
||||
};
|
||||
|
||||
const CreateAndDestroyWorker: Worker = {
|
||||
id: 'createDestroy',
|
||||
work: () => {
|
||||
$('#createDom').click();
|
||||
$('#destroyDom').click();
|
||||
}
|
||||
};
|
||||
|
||||
const UpdateWorker: Worker = {
|
||||
id: 'update',
|
||||
work: () => $('#createDom').click()
|
||||
};
|
||||
import {Benchmark, Benchmarks, CreateBtn, DestroyBtn, DetectChangesBtn, RootEl} from './tree_data';
|
||||
|
||||
describe('tree benchmark perf', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
let _oldRootEl: any;
|
||||
beforeEach(() => _oldRootEl = browser.rootEl);
|
||||
|
||||
[CreateOnlyWorker, CreateAndDestroyWorker, UpdateWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
afterEach(() => {
|
||||
browser.rootEl = _oldRootEl;
|
||||
verifyNoBrowserErrors();
|
||||
});
|
||||
|
||||
it('should run for ng2', (done) => {
|
||||
Benchmarks.forEach(benchmark => {
|
||||
describe(benchmark.id, () => {
|
||||
it('should work for createOnly', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
id: 'createOnly',
|
||||
benchmark,
|
||||
prepare: () => $(CreateBtn).click(),
|
||||
work: () => $(DestroyBtn).click()
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for ng2 next', (done) => {
|
||||
it('should work for createDestroy', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2.next.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/ng2_next/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
// Can't use bundles as we use non exported code
|
||||
extraParams: [{name: 'bundles', value: false}]
|
||||
id: 'createDestroy',
|
||||
benchmark,
|
||||
work: () => {
|
||||
$(DestroyBtn).click();
|
||||
$(CreateBtn).click();
|
||||
}
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for ng2 static', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2.static.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/ng2_static/index.html',
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
it('should work for update', (done) => {
|
||||
runTreeBenchmark({id: 'update', benchmark, work: () => $(CreateBtn).click()})
|
||||
.then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for ng2 switch', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2_switch.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/ng2_switch/index.html',
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
if (benchmark.buttons.indexOf(DetectChangesBtn) !== -1) {
|
||||
it('should work for detectChanges', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: 'detectChanges',
|
||||
benchmark,
|
||||
work: () => $(DetectChangesBtn).click(),
|
||||
setup: () => $(DestroyBtn).click()
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
}
|
||||
|
||||
it('should run for the baseline', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.baseline.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for incremental-dom', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.incremental_dom.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/incremental_dom/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for polymer binary tree', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.polymer.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/polymer/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for polymer leaves', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.polymer_leaves.${worker.id}`,
|
||||
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
work: worker.work,
|
||||
prepare: worker.prepare,
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should run ng2 changedetection', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2.changedetection`,
|
||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||
work: () => $('#detectChanges').click(),
|
||||
setup: () => $('#createDom').click(),
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run ng2 next changedetection', (done) => {
|
||||
runTreeBenchmark({
|
||||
id: `deepTree.ng2.next.changedetection`,
|
||||
url: 'all/benchmarks/src/tree/ng2_next/index.html',
|
||||
work: () => $('#detectChanges').click(),
|
||||
setup: () => $('#createDom').click(),
|
||||
ignoreBrowserSynchronization: true,
|
||||
// Can't use bundles as we use non exported code
|
||||
extraParams: [{name: 'bundles', value: false}]
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
function runTreeBenchmark(config: {
|
||||
id: string,
|
||||
url: string, ignoreBrowserSynchronization?: boolean,
|
||||
work: () => any,
|
||||
prepare?: () => any,
|
||||
extraParams?: {name: string, value: any}[],
|
||||
setup?: () => any
|
||||
}) {
|
||||
let params = [{name: 'depth', value: 11}];
|
||||
if (config.extraParams) {
|
||||
params = params.concat(config.extraParams);
|
||||
}
|
||||
return runBenchmark({
|
||||
id: config.id,
|
||||
url: config.url,
|
||||
ignoreBrowserSynchronization: config.ignoreBrowserSynchronization,
|
||||
params: params,
|
||||
work: config.work,
|
||||
prepare: config.prepare,
|
||||
setup: config.setup
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function runTreeBenchmark({id, benchmark, prepare, setup, work}: {
|
||||
id: string; benchmark: Benchmark, prepare ? () : void; setup ? () : void; work(): void;
|
||||
}) {
|
||||
let params = [{name: 'depth', value: 11}];
|
||||
if (benchmark.extraParams) {
|
||||
params = params.concat(benchmark.extraParams);
|
||||
}
|
||||
browser.rootEl = RootEl;
|
||||
return runBenchmark({
|
||||
id: `${benchmark.id}.${id}`,
|
||||
url: benchmark.url,
|
||||
ignoreBrowserSynchronization: benchmark.ignoreBrowserSynchronization,
|
||||
params: params,
|
||||
work: work,
|
||||
prepare: prepare,
|
||||
setup: setup
|
||||
});
|
||||
}
|
||||
|
@ -7,107 +7,57 @@
|
||||
*/
|
||||
|
||||
import {openBrowser, verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
||||
import {$} from 'protractor';
|
||||
import {$, browser} from 'protractor';
|
||||
|
||||
import {Benchmark, Benchmarks, CreateBtn, DestroyBtn, DetectChangesBtn, NumberOfChecksEl, RootEl} from './tree_data';
|
||||
|
||||
describe('tree benchmark spec', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
let _oldRootEl: any;
|
||||
beforeEach(() => _oldRootEl = browser.rootEl);
|
||||
|
||||
it('should work for ng2', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||
afterEach(() => {
|
||||
browser.rootEl = _oldRootEl;
|
||||
verifyNoBrowserErrors();
|
||||
});
|
||||
|
||||
Benchmarks.forEach(benchmark => {
|
||||
describe(benchmark.id, () => {
|
||||
it('should work for createDestroy', () => {
|
||||
openTreeBenchmark(benchmark);
|
||||
$(CreateBtn).click();
|
||||
expect($(RootEl).getText()).toContain('0');
|
||||
$(DestroyBtn).click();
|
||||
expect($(RootEl).getText()).toEqual('');
|
||||
});
|
||||
|
||||
it('should work for update', () => {
|
||||
openTreeBenchmark(benchmark);
|
||||
$(CreateBtn).click();
|
||||
$(CreateBtn).click();
|
||||
expect($(RootEl).getText()).toContain('A');
|
||||
});
|
||||
|
||||
if (benchmark.buttons.indexOf(DetectChangesBtn) !== -1) {
|
||||
it('should work for detectChanges', () => {
|
||||
openTreeBenchmark(benchmark);
|
||||
$(DetectChangesBtn).click();
|
||||
expect($(NumberOfChecksEl).getText()).toContain('10');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for ng2 detect changes', () => {
|
||||
function openTreeBenchmark(benchmark: Benchmark) {
|
||||
let params = [{name: 'depth', value: 4}];
|
||||
openBrowser({url: 'all/benchmarks/src/tree/ng2/index.html', params});
|
||||
$('#detectChanges').click();
|
||||
expect($('#numberOfChecks').getText()).toContain('10');
|
||||
});
|
||||
|
||||
it('should work for ng2 next', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/ng2_next/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
// Can't use bundles as we use non exported code
|
||||
extraParams: [{name: 'bundles', value: false}]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for ng2 next detect changes', () => {
|
||||
let params = [
|
||||
{name: 'depth', value: 4},
|
||||
// Can't use bundles as we use non exported code
|
||||
{name: 'bundles', value: false}
|
||||
];
|
||||
openBrowser({
|
||||
url: 'all/benchmarks/src/tree/ng2_next/index.html',
|
||||
ignoreBrowserSynchronization: true, params
|
||||
});
|
||||
$('#detectChanges').click();
|
||||
expect($('#numberOfChecks').getText()).toContain('10');
|
||||
});
|
||||
|
||||
it('should work for ng2 static', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/ng2_static/index.html',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for ng2 switch', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/ng2_switch/index.html',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for the baseline', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for incremental dom', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/incremental_dom/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for polymer binary tree', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/polymer/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for polymer leaves', () => {
|
||||
testTreeBenchmark({
|
||||
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
});
|
||||
});
|
||||
|
||||
function testTreeBenchmark(openConfig: {
|
||||
url: string,
|
||||
ignoreBrowserSynchronization?: boolean,
|
||||
extraParams?: {name: string, value: any}[]
|
||||
}) {
|
||||
let params = [{name: 'depth', value: 4}];
|
||||
if (openConfig.extraParams) {
|
||||
params = params.concat(openConfig.extraParams);
|
||||
if (benchmark.extraParams) {
|
||||
params = params.concat(benchmark.extraParams);
|
||||
}
|
||||
browser.rootEl = RootEl;
|
||||
openBrowser({
|
||||
url: openConfig.url,
|
||||
ignoreBrowserSynchronization: openConfig.ignoreBrowserSynchronization,
|
||||
url: benchmark.url,
|
||||
ignoreBrowserSynchronization: benchmark.ignoreBrowserSynchronization,
|
||||
params: params,
|
||||
});
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('0');
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('A');
|
||||
$('#destroyDom').click();
|
||||
expect($('#root').getText()).toEqual('');
|
||||
}
|
||||
});
|
||||
|
44
modules/benchmarks/src/tree/ng1/index.html
Normal file
44
modules/benchmarks/src/tree/ng1/index.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<h2>Params</h2>
|
||||
<form>
|
||||
Depth:
|
||||
<input type="number" name="depth" placeholder="depth" value="9">
|
||||
<br>
|
||||
<button>Apply</button>
|
||||
</form>
|
||||
|
||||
<h2>Ng1 Tree Benchmark</h2>
|
||||
<p>
|
||||
<button id="destroyDom">destroyDom</button>
|
||||
<button id="createDom">createDom</button>
|
||||
<button id="detectChanges">detectChanges</button>
|
||||
<button id="updateDomProfile">profile updateDom</button>
|
||||
<button id="createDomProfile">profile createDom</button>
|
||||
<button id="detectChangesProfile">profile detectChanges</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
Change detection runs:<span id="numberOfChecks"></span>
|
||||
</div>
|
||||
<div>
|
||||
<tree id="root" data="initData">Loading...</tree>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var mainUrls = [
|
||||
'/all/benchmarks/vendor/angular.js',
|
||||
'../../bootstrap_plain.js'
|
||||
];
|
||||
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1];
|
||||
if (mainUrl) {
|
||||
mainUrls = [mainUrl];
|
||||
}
|
||||
mainUrls.forEach(function(mainUrl) {
|
||||
document.write('<script src="' + mainUrl + '">\u003c/script>');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user