Compare commits
330 Commits
10.0.0-rc.
...
10.1.0-nex
Author | SHA1 | Date | |
---|---|---|---|
1f796e9479 | |||
1237d9cbea | |||
b3969e9654 | |||
6eb868b63a | |||
82a2207f4a | |||
289a96b078 | |||
cb2ab26296 | |||
79850983e6 | |||
fc7e77934f | |||
90b93da743 | |||
ec32eba02c | |||
596fbb3f06 | |||
aed6b131bb | |||
d148fdccf2 | |||
1801d0c650 | |||
a5c30733cb | |||
d7dd2959c8 | |||
a5ffca0576 | |||
196bfa8fae | |||
1d5ca55aab | |||
e0033f1e10 | |||
9206a26e1d | |||
11dd2bef2d | |||
6fc80690ae | |||
f6d2705942 | |||
79dc14199b | |||
71956250dd | |||
e84539f809 | |||
873330b82c | |||
a177b1b7b1 | |||
435a28e937 | |||
c2b4d92708 | |||
a87951a28f | |||
6b565ba8f2 | |||
c29f830c4b | |||
cde4653c62 | |||
e07d940b9b | |||
ee1526029f | |||
eba9dd364e | |||
78a44768e0 | |||
98c047b763 | |||
543b679762 | |||
c00f4ab2ae | |||
2038568f3e | |||
c509243af5 | |||
d4544da804 | |||
b950d4675f | |||
ae5257cda6 | |||
8fd8143ab8 | |||
acf3cff9ee | |||
c5b125b7db | |||
fc5c34d1b8 | |||
0879d2e85d | |||
83fe963a4b | |||
e0eeb4afcb | |||
c942662d79 | |||
6341a837c1 | |||
f954ab6f10 | |||
3ee666580a | |||
dbc2364d16 | |||
eee2fd22e0 | |||
638dd15f61 | |||
9c668e091f | |||
b2816a1536 | |||
2cbc429291 | |||
4c7f32f28c | |||
8572e885b4 | |||
0e3e9cd382 | |||
9118f49a63 | |||
d37049a2a2 | |||
d12cdb5019 | |||
ce879fc416 | |||
712f1bd0b7 | |||
d2fb552116 | |||
5103d908c8 | |||
9318e23e64 | |||
290bc7334d | |||
190561d8a6 | |||
ddb0a4e2e5 | |||
07a07e34bc | |||
dda3f49952 | |||
decd95e7f0 | |||
6abb8d0d91 | |||
2b2146bc58 | |||
3a698e2d08 | |||
8a74508130 | |||
ef1fb6dee4 | |||
e36d5b201a | |||
77b62a52c0 | |||
616543ded0 | |||
2170ea270a | |||
80d0067048 | |||
5218916a7e | |||
1c1eb3045c | |||
4967997536 | |||
666e6d15fa | |||
f3ec37ebbf | |||
cc3b1ebd96 | |||
29490cce30 | |||
bedc0451a0 | |||
a0595f4b4f | |||
8924ec1474 | |||
4481bebb38 | |||
f5bbfd7b8c | |||
41ce5240f2 | |||
243824ef74 | |||
c95802f26f | |||
71c0363bb5 | |||
e03adaf9b0 | |||
38dfbc775f | |||
5229809adb | |||
9d88ca07f8 | |||
97383488e8 | |||
cb566add3c | |||
5c40fd65fa | |||
2b53b07c70 | |||
6de5a12a9d | |||
3a418ab63b | |||
c8c0063499 | |||
34259e90cb | |||
d0c69d207c | |||
1f0818002c | |||
fd65958b88 | |||
12f674f404 | |||
413a0fb1ae | |||
85abfd2171 | |||
1601ee6f6a | |||
6898eab946 | |||
62a85f5e55 | |||
a8af8551ec | |||
7e0eccc4ef | |||
2a970a0af8 | |||
bd7f440357 | |||
d0437b3be0 | |||
1d844b9bd8 | |||
53e95233c3 | |||
879a674420 | |||
71f008f906 | |||
1197965e69 | |||
8154bbd538 | |||
f5e39999d7 | |||
ff33ab1379 | |||
7521834296 | |||
1185aa07a3 | |||
ceca5dded5 | |||
2a145f2463 | |||
e0dfa42d6e | |||
cc37af2314 | |||
87a679b210 | |||
a7359d494a | |||
66e6b932d8 | |||
cc49a91de7 | |||
300c2fec9c | |||
a7faa6bb65 | |||
bcc0a035cc | |||
e99bcbb4d4 | |||
adc9d5cdcb | |||
d330cd85ac | |||
09d6dc50ef | |||
7ac166ff08 | |||
ae4f81cbab | |||
c1fdfd4f14 | |||
62e4acc3d1 | |||
1091ddbb8e | |||
b45acb8d32 | |||
104abe04ba | |||
1bc807c81a | |||
d3b5e5696f | |||
34e4098e85 | |||
8dcf618411 | |||
7cc7955b5d | |||
a075260751 | |||
aba33de5f5 | |||
fe0782afa9 | |||
3545520e81 | |||
5ea9119322 | |||
2e355fd4d3 | |||
12f2101d08 | |||
d3a817549b | |||
c5493c192c | |||
d17084bf97 | |||
f150a304e8 | |||
886e3ebcca | |||
bf682d73d4 | |||
8f3695e20e | |||
829ddf95e5 | |||
fb10f62efc | |||
8197557fcf | |||
e7a0e87c41 | |||
ab9bc8a9ec | |||
469d2b4640 | |||
31796e8e2f | |||
284123c6ba | |||
7259208893 | |||
7e5f6c2dc1 | |||
97dc85ba5e | |||
a937889c3b | |||
aa8f1d569b | |||
5dba3bf1fd | |||
6651b4171d | |||
8c682c52b1 | |||
e5b09cc49a | |||
b199ef6bfc | |||
583a9d38a1 | |||
1fce6d6bae | |||
39f973430a | |||
20346ff192 | |||
bd9c1e6cfc | |||
d76a872efb | |||
a398d6af45 | |||
e836eaf448 | |||
ae364864f6 | |||
cc552dd702 | |||
021dd33ed8 | |||
684726cdac | |||
7b005bb9cf | |||
401ef71ae5 | |||
0a1d078a74 | |||
35502c739c | |||
b2ccc34f9c | |||
eaa38a5adc | |||
cb1373106b | |||
f6ee911cbb | |||
a3313709ea | |||
0eacba5829 | |||
bb924b63e6 | |||
7301e70ddd | |||
7edb026619 | |||
0b7845964b | |||
55979fe0ae | |||
6280cf95b4 | |||
8d817daf78 | |||
946f1179e9 | |||
87fdd23157 | |||
713fb3b587 | |||
0cb0f66c17 | |||
db11a0ddbf | |||
779344012a | |||
650974e1b3 | |||
ed3c549063 | |||
3a116179b1 | |||
5e64c2b1df | |||
d63ecf4c5f | |||
77efddcac3 | |||
d887ba85ad | |||
0c75a06b1e | |||
aaa20093b2 | |||
5568d824dd | |||
17996bf719 | |||
2a330a60ed | |||
569d1ef583 | |||
85b6c94cc6 | |||
818d93d7e9 | |||
d4c0962c7b | |||
e31208beb1 | |||
3569fdf451 | |||
eb6ba9ac80 | |||
4e7a4543b8 | |||
753fed285c | |||
dffcca73e4 | |||
c8f7fc22c7 | |||
b2bd38699b | |||
c025357fb8 | |||
57411c85b9 | |||
07a8016118 | |||
4d69da57ca | |||
7f98b87ca0 | |||
c61decf7e5 | |||
6e7bd939f6 | |||
2021ad12cf | |||
c4f4675ebf | |||
34827559b9 | |||
65c3888d01 | |||
e648a0c4ca | |||
965a688c97 | |||
ab3f4c9fe1 | |||
40f3bb5638 | |||
a08d18a1fe | |||
64d6f35f94 | |||
caa4ab3235 | |||
06a8ad28a7 | |||
382aa50c54 | |||
044a19966d | |||
17e98198f4 | |||
561c0f81a0 | |||
4414be77c4 | |||
1b55da10b1 | |||
78ea2527a1 | |||
4456e7e4de | |||
92c436dd1a | |||
b45f336635 | |||
c3651cec0b | |||
3b52f7066b | |||
8bb741198b | |||
26849ca99d | |||
4d0e175a65 | |||
bd7393fc68 | |||
08ff8aa055 | |||
f60d159d71 | |||
6aa5bfa21a | |||
227ba625e6 | |||
e64176019a | |||
1fc7891add | |||
e7930fcc15 | |||
4b40740324 | |||
a36667d984 | |||
9791c9ecaf | |||
df082307b9 | |||
98d820030c | |||
f001aef2dc | |||
64fc8b8ee5 | |||
a62c1c441c | |||
3d154ab795 | |||
d1ea1f4c7f | |||
5aeb9a4124 | |||
ecce99470a | |||
540c29cd6b | |||
7827501d2a | |||
e28f13a102 | |||
e0002ef9ba | |||
367f6fe12d | |||
9b3ca19675 | |||
9388e47e1e | |||
171d967993 | |||
40e357411e | |||
52c7aae4df | |||
87b1aeac0f | |||
93be1f1543 | |||
cdb5d07606 | |||
3e5fa56956 |
@ -32,7 +32,7 @@ var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelver
|
|||||||
|
|
||||||
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||||
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||||
var_5: &components_repo_unit_tests_cache_key v7-angular-components-189d98e8b01b33974328255f085de04251d61567
|
var_5: &components_repo_unit_tests_cache_key v7-angular-components-f428c00465dfcf8a020237f22532480eedbd2cb6
|
||||||
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
|
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
|
||||||
|
|
||||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||||
@ -377,6 +377,10 @@ jobs:
|
|||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
|
parameters:
|
||||||
|
debugArtifactsDir:
|
||||||
|
type: string
|
||||||
|
default: aio/dist/size-debug-artifacts
|
||||||
steps:
|
steps:
|
||||||
- custom_attach_workspace
|
- custom_attach_workspace
|
||||||
- init_environment
|
- init_environment
|
||||||
@ -395,6 +399,15 @@ jobs:
|
|||||||
- run: yarn --cwd aio test-a11y-score-localhost
|
- run: yarn --cwd aio test-a11y-score-localhost
|
||||||
# Check the bundle sizes.
|
# Check the bundle sizes.
|
||||||
- run: yarn --cwd aio payload-size
|
- run: yarn --cwd aio payload-size
|
||||||
|
# When `payload-size` check fails, copy the files that were checked into `debugArtifactsDir`.
|
||||||
|
- run:
|
||||||
|
when: on_fail
|
||||||
|
name: Prepare JS bundles to be stored as artifacts
|
||||||
|
command: node aio/scripts/prepare-size-debug-artifacts aio << parameters.debugArtifactsDir >>
|
||||||
|
# Store files in `debugArtifactsDir` (if any) as artifacts for debugging purposes.
|
||||||
|
- store_artifacts:
|
||||||
|
path: << parameters.debugArtifactsDir >>
|
||||||
|
destination: aio
|
||||||
# Run unit tests for Firebase redirects
|
# Run unit tests for Firebase redirects
|
||||||
- run: yarn --cwd aio redirects-test
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
@ -410,6 +423,9 @@ jobs:
|
|||||||
|
|
||||||
test_aio_local:
|
test_aio_local:
|
||||||
parameters:
|
parameters:
|
||||||
|
debugArtifactsDir:
|
||||||
|
type: string
|
||||||
|
default: aio/dist/size-debug-artifacts
|
||||||
viewengine:
|
viewengine:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
@ -428,6 +444,15 @@ jobs:
|
|||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Check the bundle sizes.
|
# Check the bundle sizes.
|
||||||
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
||||||
|
# When `payload-size` check fails, copy the files that were checked into `debugArtifactsDir`.
|
||||||
|
- run:
|
||||||
|
when: on_fail
|
||||||
|
name: Prepare JS bundles to be stored as artifacts
|
||||||
|
command: node aio/scripts/prepare-size-debug-artifacts aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >> << parameters.debugArtifactsDir >>
|
||||||
|
# Store files in `debugArtifactsDir` (if any) as artifacts for debugging purposes.
|
||||||
|
- store_artifacts:
|
||||||
|
path: << parameters.debugArtifactsDir >>
|
||||||
|
destination: aio
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -731,8 +756,8 @@ jobs:
|
|||||||
- run: yarn --cwd packages/zone.js promisetest
|
- run: yarn --cwd packages/zone.js promisetest
|
||||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package &&
|
- run: yarn bazel build //packages/zone.js:npm_package &&
|
||||||
cp dist/bin/packages/zone.js/npm_package/dist/zone-mix.js ./packages/zone.js/test/extra/ &&
|
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/ &&
|
||||||
cp dist/bin/packages/zone.js/npm_package/dist/zone-patch-electron.js ./packages/zone.js/test/extra/ &&
|
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
||||||
yarn --cwd packages/zone.js electrontest
|
yarn --cwd packages/zone.js electrontest
|
||||||
- run: yarn --cwd packages/zone.js jesttest
|
- run: yarn --cwd packages/zone.js jesttest
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
|
|||||||
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
||||||
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
||||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
||||||
setPublicVar COMPONENTS_REPO_COMMIT "189d98e8b01b33974328255f085de04251d61567"
|
setPublicVar COMPONENTS_REPO_COMMIT "f428c00465dfcf8a020237f22532480eedbd2cb6"
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
@ -4,6 +4,7 @@ import {MergeConfig} from '../dev-infra/pr/merge/config';
|
|||||||
const commitMessage = {
|
const commitMessage = {
|
||||||
'maxLength': 120,
|
'maxLength': 120,
|
||||||
'minBodyLength': 100,
|
'minBodyLength': 100,
|
||||||
|
'minBodyLengthTypeExcludes': ['docs'],
|
||||||
'types': [
|
'types': [
|
||||||
'build',
|
'build',
|
||||||
'ci',
|
'ci',
|
||||||
@ -56,8 +57,6 @@ const format = {
|
|||||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||||
'!aio/**',
|
'!aio/**',
|
||||||
'!integration/**',
|
'!integration/**',
|
||||||
// TODO: remove this exclusion as part of IE deprecation.
|
|
||||||
'!shims_for_IE.js',
|
|
||||||
// Both third_party and .yarn are directories containing copied code which should
|
// Both third_party and .yarn are directories containing copied code which should
|
||||||
// not be modified.
|
// not be modified.
|
||||||
'!third_party/**',
|
'!third_party/**',
|
||||||
@ -84,6 +83,7 @@ const merge = () => {
|
|||||||
githubApiMerge: false,
|
githubApiMerge: false,
|
||||||
claSignedLabel: 'cla: yes',
|
claSignedLabel: 'cla: yes',
|
||||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||||
|
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||||
commitMessageFixupLabel: 'commit message fixup',
|
commitMessageFixupLabel: 'commit message fixup',
|
||||||
labels: [
|
labels: [
|
||||||
{
|
{
|
||||||
|
179
.pullapprove.yml
179
.pullapprove.yml
@ -34,41 +34,8 @@
|
|||||||
####################################################################################
|
####################################################################################
|
||||||
# GitHub usernames
|
# GitHub usernames
|
||||||
####################################################################################
|
####################################################################################
|
||||||
# aikidave - Dave Shevitz
|
# See reviewer list under `required-minimum-review` group. Team member names and
|
||||||
# alan-agius4 - Alan Agius
|
# usernames are managed there.
|
||||||
# alxhub - Alex Rickabaugh
|
|
||||||
# AndrewKushnir - Andrew Kushnir
|
|
||||||
# andrewseguin - Andrew Seguin
|
|
||||||
# atscott - Andrew Scott
|
|
||||||
# ayazhafiz - Ayaz Hafiz
|
|
||||||
# clydin - Charles Lyding
|
|
||||||
# crisbeto - Kristiyan Kostadinov
|
|
||||||
# dennispbrown - Denny Brown
|
|
||||||
# devversion - Paul Gschwendtner
|
|
||||||
# dgp1130 - Doug Parker
|
|
||||||
# filipesilva - Filipe Silva
|
|
||||||
# gkalpak - Georgios Kalpakas
|
|
||||||
# gregmagolan - Greg Magolan
|
|
||||||
# IgorMinar - Igor Minar
|
|
||||||
# jbogarthyde - Judy Bogart
|
|
||||||
# jelbourn - Jeremy Elbourn
|
|
||||||
# JiaLiPassion - Jia Li
|
|
||||||
# JoostK - Joost Koehoorn
|
|
||||||
# josephperrott - Joey Perrott
|
|
||||||
# juleskremer - Jules Kremer
|
|
||||||
# kapunahelewong - Kapunahele Wong
|
|
||||||
# kara - Kara Erickson
|
|
||||||
# kyliau - Keen Yee Liau
|
|
||||||
# manughub - Manu Murthy
|
|
||||||
# matsko - Matias Niemela
|
|
||||||
# mgechev - Minko Gechev
|
|
||||||
# mhevery - Miško Hevery
|
|
||||||
# michaelprentice - Michael Prentice
|
|
||||||
# mmalerba - Miles Malerba
|
|
||||||
# petebacondarwin - Pete Bacon Darwin
|
|
||||||
# pkozlowski-opensource - Pawel Kozlowski
|
|
||||||
# robwormald - Rob Wormald
|
|
||||||
# StephenFluin - Stephen Fluin
|
|
||||||
|
|
||||||
|
|
||||||
####################################################################################
|
####################################################################################
|
||||||
@ -100,8 +67,16 @@ version: 3
|
|||||||
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
||||||
# used throughout the config.
|
# used throughout the config.
|
||||||
meta:
|
meta:
|
||||||
1: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
||||||
2: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
||||||
|
defaults: &defaults
|
||||||
|
reviews:
|
||||||
|
# Authors provide their approval implicitly, this approval allows for a reviewer
|
||||||
|
# from a group not to need a review specifically for an area of the repository
|
||||||
|
# they own. This is coupled with the `required-minimum-review` group which requires
|
||||||
|
# that all PRs are reviewed by at least one team member who is not the author of
|
||||||
|
# the PR.
|
||||||
|
author_value: 1
|
||||||
|
|
||||||
# turn on 'draft' support
|
# turn on 'draft' support
|
||||||
# https://docs.pullapprove.com/config/github-api-version/
|
# https://docs.pullapprove.com/config/github-api-version/
|
||||||
@ -157,10 +132,63 @@ groups:
|
|||||||
required: 1
|
required: 1
|
||||||
reviewed_for: required
|
reviewed_for: required
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# Require review on all PRs
|
||||||
|
#
|
||||||
|
# All PRs require at least one review. This rule will not
|
||||||
|
# request any reviewers, however will require that at least
|
||||||
|
# one review is provided before the group is satisfied.
|
||||||
|
# =========================================================
|
||||||
|
required-minimum-review:
|
||||||
|
conditions:
|
||||||
|
- *can-be-global-approved
|
||||||
|
- *can-be-global-docs-approved
|
||||||
|
reviews:
|
||||||
|
request: 0 # Do not request any reviews from the reviewer group
|
||||||
|
required: 1 # Require that all PRs have approval from at least one of the users in the group
|
||||||
|
author_value: 0 # The author of the PR cannot provide an approval for themself
|
||||||
|
reviewers:
|
||||||
|
users:
|
||||||
|
- aikidave # Dave Shevitz
|
||||||
|
- alan-agius4 # Alan Agius
|
||||||
|
- alxhub # Alex Rickabaugh
|
||||||
|
- AndrewKushnir # Andrew Kushnir
|
||||||
|
- andrewseguin # Andrew Seguin
|
||||||
|
- atscott # Andrew Scott
|
||||||
|
- ayazhafiz # Ayaz Hafiz
|
||||||
|
- clydin # Charles Lyding
|
||||||
|
- crisbeto # Kristiyan Kostadinov
|
||||||
|
- dennispbrown # Denny Brown
|
||||||
|
- devversion # Paul Gschwendtner
|
||||||
|
- dgp1130 # Doug Parker
|
||||||
|
- filipesilva # Filipe Silva
|
||||||
|
- gkalpak # Georgios Kalpakas
|
||||||
|
- gregmagolan # Greg Magolan
|
||||||
|
- IgorMinar # Igor Minar
|
||||||
|
- jbogarthyde # Judy Bogart
|
||||||
|
- jelbourn # Jeremy Elbourn
|
||||||
|
- JiaLiPassion # Jia Li
|
||||||
|
- JoostK # Joost Koehoorn
|
||||||
|
- josephperrott # Joey Perrott
|
||||||
|
- juleskremer # Jules Kremer
|
||||||
|
- kapunahelewong # Kapunahele Wong
|
||||||
|
- kara # Kara Erickson
|
||||||
|
- kyliau # Keen Yee Liau
|
||||||
|
- manughub # Manu Murthy
|
||||||
|
- matsko # Matias Niemela
|
||||||
|
- mgechev # Minko Gechev
|
||||||
|
- mhevery # Miško Hevery
|
||||||
|
- mmalerba # Miles Malerba
|
||||||
|
- petebacondarwin # Pete Bacon Darwin
|
||||||
|
- pkozlowski-opensource # Pawel Kozlowski
|
||||||
|
- Splaktar # Michael Prentice
|
||||||
|
- StephenFluin # Stephen Fluin
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Framework: Animations
|
# Framework: Animations
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-animations:
|
fw-animations:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -185,6 +213,7 @@ groups:
|
|||||||
# Framework: Compiler
|
# Framework: Compiler
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-compiler:
|
fw-compiler:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -209,6 +238,7 @@ groups:
|
|||||||
# Framework: Compiler / ngcc
|
# Framework: Compiler / ngcc
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-ngcc:
|
fw-ngcc:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -225,6 +255,7 @@ groups:
|
|||||||
# Framework: Migrations
|
# Framework: Migrations
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-migrations:
|
fw-migrations:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -240,6 +271,7 @@ groups:
|
|||||||
# Framework: Core
|
# Framework: Core
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-core:
|
fw-core:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -283,6 +315,7 @@ groups:
|
|||||||
'aio/content/images/guide/dependency-injection-in-action/**',
|
'aio/content/images/guide/dependency-injection-in-action/**',
|
||||||
'aio/content/guide/dependency-injection-navtree.md',
|
'aio/content/guide/dependency-injection-navtree.md',
|
||||||
'aio/content/guide/dependency-injection-providers.md',
|
'aio/content/guide/dependency-injection-providers.md',
|
||||||
|
'aio/content/guide/lightweight-injection-tokens.md',
|
||||||
'aio/content/guide/displaying-data.md',
|
'aio/content/guide/displaying-data.md',
|
||||||
'aio/content/examples/displaying-data/**',
|
'aio/content/examples/displaying-data/**',
|
||||||
'aio/content/images/guide/displaying-data/**',
|
'aio/content/images/guide/displaying-data/**',
|
||||||
@ -359,6 +392,7 @@ groups:
|
|||||||
# Framework: Http
|
# Framework: Http
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-http:
|
fw-http:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -380,6 +414,7 @@ groups:
|
|||||||
# Framework: Elements
|
# Framework: Elements
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-elements:
|
fw-elements:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -400,6 +435,7 @@ groups:
|
|||||||
# Framework: Forms
|
# Framework: Forms
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-forms:
|
fw-forms:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -432,6 +468,7 @@ groups:
|
|||||||
# Framework: i18n
|
# Framework: i18n
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-i18n:
|
fw-i18n:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -465,6 +502,7 @@ groups:
|
|||||||
# Framework: Platform Server
|
# Framework: Platform Server
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-platform-server:
|
fw-platform-server:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -484,6 +522,7 @@ groups:
|
|||||||
# Framework: Router
|
# Framework: Router
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-router:
|
fw-router:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -506,6 +545,7 @@ groups:
|
|||||||
# Framework: Service Worker
|
# Framework: Service Worker
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-service-worker:
|
fw-service-worker:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -533,6 +573,7 @@ groups:
|
|||||||
# Framework: Upgrade
|
# Framework: Upgrade
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-upgrade:
|
fw-upgrade:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -563,6 +604,7 @@ groups:
|
|||||||
# Framework: Testing
|
# Framework: Testing
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-testing:
|
fw-testing:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -584,6 +626,7 @@ groups:
|
|||||||
# Framework: Benchmarks
|
# Framework: Benchmarks
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-benchmarks:
|
fw-benchmarks:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -600,6 +643,7 @@ groups:
|
|||||||
# Framework: Playground
|
# Framework: Playground
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-playground:
|
fw-playground:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -617,6 +661,7 @@ groups:
|
|||||||
# Framework: Security
|
# Framework: Security
|
||||||
# =========================================================
|
# =========================================================
|
||||||
fw-security:
|
fw-security:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -646,6 +691,7 @@ groups:
|
|||||||
# Bazel
|
# Bazel
|
||||||
# =========================================================
|
# =========================================================
|
||||||
bazel:
|
bazel:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -664,6 +710,7 @@ groups:
|
|||||||
# Language Service
|
# Language Service
|
||||||
# =========================================================
|
# =========================================================
|
||||||
language-service:
|
language-service:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -683,6 +730,7 @@ groups:
|
|||||||
# zone.js
|
# zone.js
|
||||||
# =========================================================
|
# =========================================================
|
||||||
zone-js:
|
zone-js:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -696,11 +744,27 @@ groups:
|
|||||||
- JiaLiPassion
|
- JiaLiPassion
|
||||||
- mhevery
|
- mhevery
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# in-memory-web-api
|
||||||
|
# =========================================================
|
||||||
|
in-memory-web-api:
|
||||||
|
conditions:
|
||||||
|
- *can-be-global-approved
|
||||||
|
- *can-be-global-docs-approved
|
||||||
|
- >
|
||||||
|
contains_any_globs(files, [
|
||||||
|
'packages/misc/angular-in-memory-web-api/**',
|
||||||
|
])
|
||||||
|
reviewers:
|
||||||
|
users:
|
||||||
|
- IgorMinar
|
||||||
|
- crisbeto
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Benchpress
|
# Benchpress
|
||||||
# =========================================================
|
# =========================================================
|
||||||
benchpress:
|
benchpress:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -718,6 +782,7 @@ groups:
|
|||||||
# Integration Tests
|
# Integration Tests
|
||||||
# =========================================================
|
# =========================================================
|
||||||
integration-tests:
|
integration-tests:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -735,6 +800,7 @@ groups:
|
|||||||
# Docs: Gettings Started & Tutorial
|
# Docs: Gettings Started & Tutorial
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-getting-started-and-tutorial:
|
docs-getting-started-and-tutorial:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -767,6 +833,7 @@ groups:
|
|||||||
# Docs: Marketing
|
# Docs: Marketing
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-marketing:
|
docs-marketing:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -789,6 +856,7 @@ groups:
|
|||||||
# Docs: Observables
|
# Docs: Observables
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-observables:
|
docs-observables:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -814,6 +882,7 @@ groups:
|
|||||||
# Docs: Packaging, Tooling, Releasing
|
# Docs: Packaging, Tooling, Releasing
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-packaging-and-releasing:
|
docs-packaging-and-releasing:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -833,7 +902,7 @@ groups:
|
|||||||
'aio/content/guide/migration-localize.md',
|
'aio/content/guide/migration-localize.md',
|
||||||
'aio/content/guide/migration-module-with-providers.md',
|
'aio/content/guide/migration-module-with-providers.md',
|
||||||
'aio/content/guide/static-query-migration.md',
|
'aio/content/guide/static-query-migration.md',
|
||||||
'aio/content/guide/updating-to-version-9.md',
|
'aio/content/guide/updating-to-version-10.md',
|
||||||
'aio/content/guide/ivy-compatibility.md',
|
'aio/content/guide/ivy-compatibility.md',
|
||||||
'aio/content/guide/ivy-compatibility-examples.md'
|
'aio/content/guide/ivy-compatibility-examples.md'
|
||||||
])
|
])
|
||||||
@ -873,6 +942,7 @@ groups:
|
|||||||
# Docs: CLI
|
# Docs: CLI
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-cli:
|
docs-cli:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -889,8 +959,12 @@ groups:
|
|||||||
'aio/content/images/guide/deployment/**',
|
'aio/content/images/guide/deployment/**',
|
||||||
'aio/content/guide/file-structure.md',
|
'aio/content/guide/file-structure.md',
|
||||||
'aio/content/guide/ivy.md',
|
'aio/content/guide/ivy.md',
|
||||||
|
'aio/content/guide/strict-mode.md',
|
||||||
'aio/content/guide/web-worker.md',
|
'aio/content/guide/web-worker.md',
|
||||||
'aio/content/guide/workspace-config.md',
|
'aio/content/guide/workspace-config.md',
|
||||||
|
'aio/content/guide/migration-solution-style-tsconfig.md',
|
||||||
|
'aio/content/guide/migration-update-module-and-target-compiler-options.md',
|
||||||
|
'aio/content/guide/migration-update-libraries-tslib.md',
|
||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
@ -903,6 +977,7 @@ groups:
|
|||||||
# Docs: CLI Libraries
|
# Docs: CLI Libraries
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-libraries:
|
docs-libraries:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -923,6 +998,7 @@ groups:
|
|||||||
# Docs: Schematics
|
# Docs: Schematics
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-schematics:
|
docs-schematics:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -945,6 +1021,7 @@ groups:
|
|||||||
# Docs-infra
|
# Docs-infra
|
||||||
# =========================================================
|
# =========================================================
|
||||||
docs-infra:
|
docs-infra:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
@ -974,10 +1051,11 @@ groups:
|
|||||||
# Dev-infra
|
# Dev-infra
|
||||||
# =========================================================
|
# =========================================================
|
||||||
dev-infra:
|
dev-infra:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
contains_any_globs(files.exclude("CHANGELOG.md"), [
|
contains_any_globs(files.exclude("CHANGELOG.md").exclude("packages/compiler-cli/**/BUILD.bazel"), [
|
||||||
'*',
|
'*',
|
||||||
'.circleci/**',
|
'.circleci/**',
|
||||||
'.devcontainer/**',
|
'.devcontainer/**',
|
||||||
@ -1038,6 +1116,7 @@ groups:
|
|||||||
# Public API
|
# Public API
|
||||||
# =========================================================
|
# =========================================================
|
||||||
public-api:
|
public-api:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -1066,6 +1145,7 @@ groups:
|
|||||||
# Size tracking
|
# Size tracking
|
||||||
# ================================================
|
# ================================================
|
||||||
size-tracking:
|
size-tracking:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -1088,6 +1168,7 @@ groups:
|
|||||||
# Circular dependencies
|
# Circular dependencies
|
||||||
# ================================================
|
# ================================================
|
||||||
circular-dependencies:
|
circular-dependencies:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -1110,6 +1191,7 @@ groups:
|
|||||||
# Code Ownership
|
# Code Ownership
|
||||||
# =========================================================
|
# =========================================================
|
||||||
code-ownership:
|
code-ownership:
|
||||||
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
@ -1125,6 +1207,7 @@ groups:
|
|||||||
# Catch all for if no groups match the code change
|
# Catch all for if no groups match the code change
|
||||||
# ====================================================
|
# ====================================================
|
||||||
fallback:
|
fallback:
|
||||||
|
<<: *defaults
|
||||||
# A group is considered to be `active` for a PR if at least one of group's
|
# A group is considered to be `active` for a PR if at least one of group's
|
||||||
# conditions matches the PR.
|
# conditions matches the PR.
|
||||||
#
|
#
|
||||||
@ -1144,13 +1227,17 @@ groups:
|
|||||||
# `global-approvers` can still approve PRs that match this `fallback` rule,
|
# `global-approvers` can still approve PRs that match this `fallback` rule,
|
||||||
# but that should be an exception and not an expectation.
|
# but that should be an exception and not an expectation.
|
||||||
conditions:
|
conditions:
|
||||||
- *can-be-global-approved
|
# The following groups have no file based conditions and will be initially `active` on all PRs
|
||||||
# The following groups have no conditions and will be `active` on all PRs
|
|
||||||
# - `global-approvers`
|
# - `global-approvers`
|
||||||
# - `global-docs-approvers`
|
# - `global-docs-approvers`
|
||||||
|
# - `required-minimum-review`
|
||||||
#
|
#
|
||||||
# Since this means the minimum number of active groups a PR can have is 2, this
|
# By checking the number of active groups when these are excluded, we can determine
|
||||||
# `fallback` group should be matched anytime the number of active groups is at or
|
# if any other groups are matched.
|
||||||
# below this minimum. This work as a protection to ensure that pullapprove does
|
- len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
||||||
# not incidently mark a PR as passing without meeting the review criteria.
|
# When any of the `global-*` groups is approved, they cause other groups to deactivate.
|
||||||
- len(groups.active) <= 2
|
# In those cases, the condition above would evaluate to `true` while in reality, only a global
|
||||||
|
# approval has been provided. To ensure we don't activate the fallback group in such cases,
|
||||||
|
# ensure that no explicit global approval has been provided.
|
||||||
|
- *can-be-global-approved
|
||||||
|
- *can-be-global-docs-approved
|
||||||
|
@ -20,11 +20,11 @@ filegroup(
|
|||||||
# do not sort
|
# do not sort
|
||||||
srcs = [
|
srcs = [
|
||||||
"@npm//:node_modules/core-js/client/core.js",
|
"@npm//:node_modules/core-js/client/core.js",
|
||||||
"//packages/zone.js/dist:zone.js",
|
"//packages/zone.js/bundles:zone.umd.js",
|
||||||
"//packages/zone.js/dist:zone-testing.js",
|
"//packages/zone.js/bundles:zone-testing.umd.js",
|
||||||
"//packages/zone.js/dist:task-tracking.js",
|
"//packages/zone.js/bundles:task-tracking.umd.js",
|
||||||
"//:test-events.js",
|
"//:test-events.js",
|
||||||
"//:shims_for_IE.js",
|
"//:third_party/shims_for_IE.js",
|
||||||
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||||
"@npm//:node_modules/systemjs/dist/system.src.js",
|
"@npm//:node_modules/systemjs/dist/system.src.js",
|
||||||
"@npm//:node_modules/reflect-metadata/Reflect.js",
|
"@npm//:node_modules/reflect-metadata/Reflect.js",
|
||||||
|
1011
CHANGELOG.md
1011
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ Do not open issues for general support questions as we want to keep GitHub issue
|
|||||||
Stack Overflow is a much better place to ask questions since:
|
Stack Overflow is a much better place to ask questions since:
|
||||||
|
|
||||||
- there are thousands of people willing to help on Stack Overflow
|
- there are thousands of people willing to help on Stack Overflow
|
||||||
- questions and answers stay available for public viewing so your question / answer might help someone else
|
- questions and answers stay available for public viewing so your question/answer might help someone else
|
||||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||||
|
|
||||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||||
@ -57,7 +57,7 @@ We want to fix all the issues as soon as possible, but before fixing a bug we ne
|
|||||||
|
|
||||||
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
||||||
|
|
||||||
We will be insisting on a minimal reproduction scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
We will be insisting on a minimal reproduction scenario in order to save maintainers' time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||||
|
|
||||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
||||||
that relates to your submission. You don't want to duplicate effort.
|
that relates to your submission. You don't want to duplicate effort.
|
||||||
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||||
Discussing the design up front helps to ensure that we're ready to accept your work.
|
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
||||||
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||||
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
|
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
|
||||||
1. Fork the angular/angular repo.
|
1. Fork the angular/angular repo.
|
||||||
@ -85,8 +85,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||||
and ensure that all tests pass.
|
and ensure that all tests pass.
|
||||||
1. Commit your changes using a descriptive commit message that follows our
|
1. Commit your changes using a descriptive commit message that follows our
|
||||||
[commit message conventions](#commit). Adherence to these conventions
|
[commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||||
is necessary because release notes are automatically generated from these messages.
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git commit -a
|
git commit -a
|
||||||
@ -181,13 +180,13 @@ Samples: (even more [samples](https://github.com/angular/angular/commits/master)
|
|||||||
docs(changelog): update changelog to beta.5
|
docs(changelog): update changelog to beta.5
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
fix(release): need to depend on latest rxjs and zone.js
|
fix(release): need to depend on the latest rxjs and zone.js
|
||||||
|
|
||||||
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Revert
|
### Revert
|
||||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||||
|
|
||||||
### Type
|
### Type
|
||||||
Must be one of the following:
|
Must be one of the following:
|
||||||
@ -282,7 +281,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
|||||||
* https://help.github.com/articles/about-commit-email-addresses/
|
* https://help.github.com/articles/about-commit-email-addresses/
|
||||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||||
|
|
||||||
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
|
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA before you commit changes. If not, your PR will fail the CLA check.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
10
aio/content/examples/i18n/stackblitz.json
Normal file
10
aio/content/examples/i18n/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "i18n",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[0-9].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Angular", "i18n", "internationalization"]
|
||||||
|
}
|
@ -6,5 +6,5 @@ import { Component } from '@angular/core';
|
|||||||
templateUrl: './app.component.html'
|
templateUrl: './app.component.html'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ import { Component } from '@angular/core';
|
|||||||
// #enddocregion hero-birthday-template
|
// #enddocregion hero-birthday-template
|
||||||
})
|
})
|
||||||
export class HeroBirthdayComponent {
|
export class HeroBirthdayComponent {
|
||||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { Component } from '@angular/core';
|
|||||||
})
|
})
|
||||||
// #docregion class
|
// #docregion class
|
||||||
export class HeroBirthday2Component {
|
export class HeroBirthday2Component {
|
||||||
birthday = new Date(1988, 3, 15); // April 15, 1988
|
birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based
|
||||||
toggle = true; // start with true == shortDate
|
toggle = true; // start with true == shortDate
|
||||||
|
|
||||||
get format() { return this.toggle ? 'shortDate' : 'fullDate'; }
|
get format() { return this.toggle ? 'shortDate' : 'fullDate'; }
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
@ -33,7 +33,7 @@ export class HeroesComponent implements OnInit {
|
|||||||
|
|
||||||
onSelect(hero: Hero): void {
|
onSelect(hero: Hero): void {
|
||||||
this.selectedHero = hero;
|
this.selectedHero = hero;
|
||||||
this.messageService.add(`HeroService: Selected hero id=${hero.id}`);
|
this.messageService.add(`HeroesComponent: Selected hero id=${hero.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion getHeroes
|
// #docregion getHeroes
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<script src="phone-detail/phone-detail.module.js"></script>
|
<script src="phone-detail/phone-detail.module.js"></script>
|
||||||
|
|
||||||
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
||||||
<script src="/node_modules/zone.js/dist/zone.min.js"></script>
|
<script src="/node_modules/zone.js/bundles/zone.umd.min.js"></script>
|
||||||
|
|
||||||
<script>window.module = 'aot';</script>
|
<script>window.module = 'aot';</script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -3,7 +3,7 @@ var fsExtra = require('fs-extra');
|
|||||||
var resources = [
|
var resources = [
|
||||||
// polyfills
|
// polyfills
|
||||||
'node_modules/core-js/client/shim.min.js',
|
'node_modules/core-js/client/shim.min.js',
|
||||||
'node_modules/zone.js/dist/zone.min.js',
|
'node_modules/zone.js/bundles/zone.umd.min.js',
|
||||||
// css
|
// css
|
||||||
'app/app.css',
|
'app/app.css',
|
||||||
'app/app.animations.css',
|
'app/app.animations.css',
|
||||||
@ -20,6 +20,7 @@ var resources = [
|
|||||||
'app/phone-detail/phone-detail.module.js'
|
'app/phone-detail/phone-detail.module.js'
|
||||||
];
|
];
|
||||||
resources.map(function(sourcePath) {
|
resources.map(function(sourcePath) {
|
||||||
var destPath = `aot/${sourcePath}`;
|
// Need to rename zone.umd.min.js to zone.min.js
|
||||||
|
var destPath = `aot/${sourcePath}`.replace('.umd.min.js', '.min.js');
|
||||||
fsExtra.copySync(sourcePath, destPath);
|
fsExtra.copySync(sourcePath, destPath);
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<!-- #docregion angular -->
|
<!-- #docregion angular -->
|
||||||
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
||||||
<!-- #enddocregion angular -->
|
<!-- #enddocregion angular -->
|
||||||
<script src="/systemjs.config.1.js"></script>
|
<script src="/systemjs.config.1.js"></script>
|
||||||
|
@ -21,8 +21,8 @@ module.exports = function(config) {
|
|||||||
'node_modules/core-js/client/shim.js',
|
'node_modules/core-js/client/shim.js',
|
||||||
|
|
||||||
// zone.js
|
// zone.js
|
||||||
'node_modules/zone.js/dist/zone.js',
|
'node_modules/zone.js/bundles/zone.umd.js',
|
||||||
'node_modules/zone.js/dist/zone-testing.js',
|
'node_modules/zone.js/bundles/zone-testing.umd.js',
|
||||||
|
|
||||||
// RxJs.
|
// RxJs.
|
||||||
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
||||||
|
@ -31,8 +31,8 @@ module.exports = function(config) {
|
|||||||
'node_modules/core-js/client/shim.js',
|
'node_modules/core-js/client/shim.js',
|
||||||
|
|
||||||
// zone.js
|
// zone.js
|
||||||
'node_modules/zone.js/dist/zone.js',
|
'node_modules/zone.js/bundles/zone.umd.js',
|
||||||
'node_modules/zone.js/dist/zone-testing.js',
|
'node_modules/zone.js/bundles/zone-testing.umd.js',
|
||||||
|
|
||||||
// RxJs
|
// RxJs
|
||||||
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<link rel="stylesheet" href="app.css" />
|
<link rel="stylesheet" href="app.css" />
|
||||||
|
|
||||||
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/bundles/zone.umd.js"></script>
|
||||||
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
<script src="/node_modules/systemjs/dist/system.src.js"></script>
|
||||||
<!-- #enddocregion full -->
|
<!-- #enddocregion full -->
|
||||||
<script src="/systemjs.config.1.js"></script>
|
<script src="/systemjs.config.1.js"></script>
|
||||||
|
@ -31,8 +31,8 @@ module.exports = function(config) {
|
|||||||
'node_modules/core-js/client/shim.js',
|
'node_modules/core-js/client/shim.js',
|
||||||
|
|
||||||
// zone.js
|
// zone.js
|
||||||
'node_modules/zone.js/dist/zone.js',
|
'node_modules/zone.js/bundles/zone.umd.js',
|
||||||
'node_modules/zone.js/dist/zone-testing.js',
|
'node_modules/zone.js/bundles/zone-testing.umd.js',
|
||||||
|
|
||||||
// RxJs
|
// RxJs
|
||||||
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
||||||
|
@ -526,7 +526,7 @@ For example:
|
|||||||
// __Zone_enable_cross_context_check = true;
|
// __Zone_enable_cross_context_check = true;
|
||||||
</script>
|
</script>
|
||||||
<!-- zone.js required by Angular -->
|
<!-- zone.js required by Angular -->
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
||||||
|
|
||||||
<!-- application polyfills -->
|
<!-- application polyfills -->
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
# Creating libraries
|
# Creating libraries
|
||||||
|
|
||||||
You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.
|
||||||
|
|
||||||
|
If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
||||||
A simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
A simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
<p>For more details on how a library project is structured you can refer the <a href="guide/file-structure#library-project-files">Library Project Files</a></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
Use the Angular CLI to generate a new library skeleton with the following command:
|
Use the Angular CLI to generate a new library skeleton in a new workspace with the following commands.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng new my-workspace --create-application=false
|
ng new my-workspace --create-application=false
|
||||||
@ -18,12 +15,18 @@ Use the Angular CLI to generate a new library skeleton with the following comman
|
|||||||
ng generate library my-lib
|
ng generate library my-lib
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
The `ng generate` command creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
<p>You can use the monorepo model to use the same workspace for multiple projects. See <a href="guide/file-structure#multiple-projects">Setting up for a multi-project workspace</a>.</p>
|
|
||||||
|
For more details on how a library project is structured, refer to the [Library project files](guide/file-structure#library-project-files) section of the [Project File Structure guide](guide/file-structure).
|
||||||
|
|
||||||
|
You can use the monorepo model to use the same workspace for multiple projects.
|
||||||
|
See [Setting up for a multi-project workspace](guide/file-structure#multiple-projects).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
This creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
||||||
The workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
|
||||||
|
|
||||||
<code-example format="json">
|
<code-example format="json">
|
||||||
"projects": {
|
"projects": {
|
||||||
@ -69,35 +72,30 @@ Here are some things to consider in migrating application functionality to a lib
|
|||||||
|
|
||||||
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
||||||
|
|
||||||
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
|
||||||
|
|
||||||
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
|
||||||
|
|
||||||
* Check all internal dependencies.
|
* Check all internal dependencies.
|
||||||
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
||||||
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
||||||
* If your library code or its templates depend on other libraries (such a Angular Material, for instance), you must configure your library with those dependencies.
|
* If your library code or its templates depend on other libraries (such as Angular Material, for instance), you must configure your library with those dependencies.
|
||||||
|
|
||||||
## Reusable code and schematics
|
* Consider how you provide services to client applications.
|
||||||
|
|
||||||
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||||
A library is packaged into an npm package for publishing and sharing, and this package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic skeleton app with `ng generate component`.
|
|
||||||
A schematic that is combined with a library can, for example, provide the Angular CLI with the information it needs to generate a particular component defined in that library.
|
|
||||||
|
|
||||||
What you include in your library is determined by the kind of task you are trying to accomplish.
|
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` design patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
||||||
For example, if you want a dropdown with some canned data to show how to add it to your app, your library could define a schematic to create it.
|
|
||||||
For a component like a dropdown that would contain different passed-in values each time, you could provide it as a component in a shared library.
|
|
||||||
|
|
||||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
* If your library provides optional services that might not be used by all client applications, support proper tree-shaking for that case by using the [lightweight token design pattern](guide/lightweight-injection-tokens).
|
||||||
If that form will need additional customization by the user, it might work best as a schematic.
|
|
||||||
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
|
||||||
In general, the more complex the customization, the more useful the schematic approach.
|
|
||||||
|
|
||||||
{@a integrating-with-the-cli}
|
{@a integrating-with-the-cli}
|
||||||
|
|
||||||
## Integrating with the CLI
|
## Integrating with the CLI using code-generation schematics
|
||||||
|
|
||||||
A library can include [schematics](guide/glossary#schematic) that allow it to integrate with the Angular CLI.
|
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
||||||
|
A library is packaged into an npm package for publishing and sharing.
|
||||||
|
This package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic new component with `ng generate component`.
|
||||||
|
A schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.
|
||||||
|
One example of this is Angular Material's navigation schematic which configures the CDK's `BreakpointObserver` and uses it with Material's `MatSideNav` and `MatToolbar` components.
|
||||||
|
|
||||||
|
You can create and include the following kinds of schematics.
|
||||||
|
|
||||||
* Include an installation schematic so that `ng add` can add your library to a project.
|
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||||
|
|
||||||
@ -105,6 +103,15 @@ A library can include [schematics](guide/glossary#schematic) that allow it to in
|
|||||||
|
|
||||||
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||||
|
|
||||||
|
What you include in your library depends on your task.
|
||||||
|
For example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an app.
|
||||||
|
If you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use `ng generate` to configure an instance for their own app.
|
||||||
|
|
||||||
|
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||||
|
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
||||||
|
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||||
|
In general, the more complex the customization, the more useful the schematic approach.
|
||||||
|
|
||||||
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries).
|
||||||
|
|
||||||
## Publishing your library
|
## Publishing your library
|
||||||
|
@ -197,11 +197,11 @@ Like `EvenBetterLogger`, `HeroService` needs to know if the user is authorized
|
|||||||
That authorization can change during the course of a single application session,
|
That authorization can change during the course of a single application session,
|
||||||
as when you log in a different user.
|
as when you log in a different user.
|
||||||
|
|
||||||
Let's say you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
|
Imagine that you don't want to inject `UserService` directly into `HeroService`, because you don't want to complicate that service with security-sensitive information.
|
||||||
`HeroService` won't have direct access to the user information to decide
|
`HeroService` won't have direct access to the user information to decide
|
||||||
who is authorized and who isn't.
|
who is authorized and who isn't.
|
||||||
|
|
||||||
To resolve this, we give the `HeroService` constructor a boolean flag to control display of secret heroes.
|
To resolve this, give the `HeroService` constructor a boolean flag to control display of secret heroes.
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" header="src/app/heroes/hero.service.ts (excerpt)"></code-example>
|
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" header="src/app/heroes/hero.service.ts (excerpt)"></code-example>
|
||||||
|
|
||||||
|
@ -448,13 +448,13 @@ When targeting older browsers, [polyfills](guide/browser-support#polyfills) can
|
|||||||
|
|
||||||
To maximize compatibility, you could ship a single bundle that includes all your compiled code, plus any polyfills that may be needed.
|
To maximize compatibility, you could ship a single bundle that includes all your compiled code, plus any polyfills that may be needed.
|
||||||
Users with modern browsers, however, shouldn't have to pay the price of increased bundle size that comes with polyfills they don't need.
|
Users with modern browsers, however, shouldn't have to pay the price of increased bundle size that comes with polyfills they don't need.
|
||||||
Differential loading, which is supported by default in Angular CLI version 8 and higher, solves this problem.
|
Differential loading, which is supported in Angular CLI version 8 and higher, can help solve this problem.
|
||||||
|
|
||||||
Differential loading is a strategy that allows your web application to support multiple browsers, but only load the necessary code that the browser needs. When differential loading is enabled (which is the default) the CLI builds two separate bundles as part of your deployed application.
|
Differential loading is a strategy that allows your web application to support multiple browsers, but only load the necessary code that the browser needs. When differential loading is enabled the CLI builds two separate bundles as part of your deployed application.
|
||||||
|
|
||||||
* The first bundle contains modern ES2015 syntax, takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller bundle size.
|
* The first bundle contains modern ES2015 syntax. This bundle takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller bundle size.
|
||||||
|
|
||||||
* The second bundle contains code in the old ES5 syntax, along with all necessary polyfills. This results in a larger bundle size, but supports older browsers.
|
* The second bundle contains code in the old ES5 syntax, along with all necessary polyfills. This second bundle is larger, but supports older browsers.
|
||||||
|
|
||||||
### Differential builds
|
### Differential builds
|
||||||
|
|
||||||
@ -463,9 +463,9 @@ The [`ng build` CLI command](cli/build) queries the browser configuration and th
|
|||||||
|
|
||||||
The following configurations determine your requirements.
|
The following configurations determine your requirements.
|
||||||
|
|
||||||
* Browsers list
|
* Browserslist
|
||||||
|
|
||||||
The `browserslist` configuration file is included in your application [project structure](guide/file-structure#application-configuration-files) and provides the minimum browsers your application supports. See the [Browserslist spec](https://github.com/browserslist/browserslist) for complete configuration options.
|
The Browserslist configuration file is included in your application [project structure](guide/file-structure#application-configuration-files) and provides the minimum browsers your application supports. See the [Browserslist spec](https://github.com/browserslist/browserslist) for complete configuration options.
|
||||||
|
|
||||||
* TypeScript configuration
|
* TypeScript configuration
|
||||||
|
|
||||||
@ -509,16 +509,27 @@ Each script tag has a `type="module"` or `nomodule` attribute. Browsers with nat
|
|||||||
|
|
||||||
### Configuring differential loading
|
### Configuring differential loading
|
||||||
|
|
||||||
Differential loading is supported by default with version 8 and later of the Angular CLI.
|
To include differential loading in your application builds, you must configure the Browserslist and TypeScript configuration files in your application project.
|
||||||
For each application project in your workspace, you can configure how builds are produced based on the `browserslist` and `tsconfig.json` configuration files in your application project.
|
|
||||||
|
|
||||||
For a newly created Angular application, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
The following examples show a `browserlistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
|
||||||
|
|
||||||
<code-example language="none" header="browserslist">
|
<code-example language="none" header="browserslistrc">
|
||||||
> 0.5%
|
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||||
last 2 versions
|
# For additional information regarding the format and rule options, please see:
|
||||||
|
# https://github.com/browserslist/browserslist#queries
|
||||||
|
|
||||||
|
# For the full list of supported browsers by the Angular framework, please see:
|
||||||
|
# https://angular.io/guide/browser-support
|
||||||
|
|
||||||
|
# You can see what browsers were selected by your queries by running:
|
||||||
|
# npx browserslist
|
||||||
|
|
||||||
|
last 1 Chrome version
|
||||||
|
last 1 Firefox version
|
||||||
|
last 2 Edge major versions
|
||||||
|
last 2 Safari major version
|
||||||
|
last 2 iOS major versions
|
||||||
Firefox ESR
|
Firefox ESR
|
||||||
not dead
|
|
||||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
@ -549,36 +560,24 @@ not IE 9-11 # For IE 9-11 support, remove 'not'.
|
|||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The default configuration creates two builds, with differential loading enabled.
|
|
||||||
|
|
||||||
<div class="alert is-important">
|
<div class="alert is-important">
|
||||||
|
|
||||||
To see which browsers are supported with the default configuration and determine which settings meet to your browser support requirements, see the [Browserslist compatibility page](https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+not+dead%2C+not+IE+9-11).
|
To see which browsers are supported and determine which settings meet to your browser support requirements, see the [Browserslist compatibility page](https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+not+dead%2C+not+IE+9-11).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
The `browserslist` configuration allows you to ignore browsers without ES2015 support. In this case, a single build is produced.
|
The Browserslist configuration allows you to ignore browsers without ES2015 support. In this case, a single build is produced.
|
||||||
|
|
||||||
If your `browserslist` configuration includes support for any legacy browsers, the build target in the TypeScript configuration determines whether the build will support differential loading.
|
If your Browserslist configuration includes support for any legacy browsers, the build target in the TypeScript configuration determines whether the build will support differential loading.
|
||||||
|
|
||||||
{@a configuration-table }
|
{@a configuration-table }
|
||||||
|
|
||||||
| browserslist | ES target | Build result |
|
| Browserslist | ES target | Build result |
|
||||||
| -------- | -------- | -------- |
|
| -------- | -------- | -------- |
|
||||||
| ES5 support disabled | es2015 | Single build, ES5 not required |
|
| ES5 support disabled | es2015 | Single build, ES5 not required |
|
||||||
| ES5 support enabled | es5 | Single build w/conditional polyfills for ES5 only |
|
| ES5 support enabled | es5 | Single build w/conditional polyfills for ES5 only |
|
||||||
| ES5 support enabled | es2015 | Differential loading (two builds w/conditional polyfills) |
|
| ES5 support enabled | es2015 | Differential loading (two builds w/conditional polyfills) |
|
||||||
|
|
||||||
|
|
||||||
### Opting out of differential loading
|
|
||||||
|
|
||||||
Differential loading can be explicitly disabled if it causes unexpected issues, or if you need to target ES5 specifically for legacy browser support.
|
|
||||||
|
|
||||||
To explicitly disable differential loading and create an ES5 build:
|
|
||||||
|
|
||||||
- Enable the `dead` or `IE` browsers in the `browserslist` configuration file by removing the `not` keyword in front of them.
|
|
||||||
- To create a single ES5 build, set the target in the `compilerOptions` to `es5`.
|
|
||||||
|
|
||||||
{@a test-and-serve}
|
{@a test-and-serve}
|
||||||
|
|
||||||
## Local development in older browsers
|
## Local development in older browsers
|
||||||
|
@ -62,8 +62,7 @@ v9 - v12
|
|||||||
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> unspecified |
|
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> unspecified |
|
||||||
| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | <!--v10--> v11 |
|
| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | <!--v10--> v11 |
|
||||||
|
|
||||||
|
For information about Angular CDK and Angular Material deprecations, see the [changelog](https://github.com/angular/components/blob/master/CHANGELOG.md).
|
||||||
|
|
||||||
|
|
||||||
## Deprecated APIs
|
## Deprecated APIs
|
||||||
|
|
||||||
@ -490,6 +489,56 @@ If you rely on the behavior that the same object instance should cause change de
|
|||||||
- Clone the resulting value so that it has a new identity.
|
- Clone the resulting value so that it has a new identity.
|
||||||
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
||||||
|
|
||||||
|
{@a deprecated-cli-flags}
|
||||||
|
## Deprecated CLI APIs and Options
|
||||||
|
|
||||||
|
This section contains a complete list all of the currently deprecated CLI flags.
|
||||||
|
|
||||||
|
### @angular-devkit/build-angular
|
||||||
|
|
||||||
|
| API/Option | May be removed in | Notes |
|
||||||
|
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||||
|
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||||
|
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||||
|
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||||
|
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||||
|
| `rebaseRootRelativeCssUrls` | <!--v8--> v11 | Intended only to assist with specific migration issues. |
|
||||||
|
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||||
|
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||||
|
| `i18nFormat` | <!--v9--> v11 | Renamed to `format` to simplify the user experience. |
|
||||||
|
| `i18nLocale` | <!--v9--> v11 | Redundant with project’s source locale. |
|
||||||
|
| `scripts[].lazy` | <!--v8--> v11 | Renamed to `scripts[].inject`. |
|
||||||
|
| `styles[].lazy` | <!--v8--> v11 | Renamed to `styles[].inject`. |
|
||||||
|
| `i18nFile` | <!--v9--> v11 | Specified in the project locale configuration in version 9 and later. |
|
||||||
|
| `i18nFormat` | <!--v9--> v11 | Format is now automatically detected. |
|
||||||
|
| `i18nLocale` | <!--v9--> v11 | New [localization option](/guide/i18n#localize-config) in version 9 and later. |
|
||||||
|
| `lazyModules` | <!--v9--> v11 | Used with deprecated SystemJsNgModuleLoader. |
|
||||||
|
|
||||||
|
### @angular-devkit/core
|
||||||
|
|
||||||
|
| API/Option | May be removed in | Notes |
|
||||||
|
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||||
|
| `ModuleNotFoundException` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||||
|
| `resolve` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||||
|
| `setResolveHook` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||||
|
| `ResolveOptions` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Not Yarn PnP compatible and not used in the Angular CLI. Use Node.js [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options).|
|
||||||
|
| `terminal` | <!--v8--> v10 | Unused implementation of terminal codes (color). |
|
||||||
|
| `isObservable` | <!--v8--> v10 | Not used within projects. Used with Tooling API only. Use `isObservable` function from the `rxjs` package.|
|
||||||
|
|
||||||
|
### @ngtools/webpack
|
||||||
|
|
||||||
|
| API/Option | May be removed in | Notes |
|
||||||
|
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||||
|
| `discoverLazyRoutes` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||||
|
| `additionalLazyModules` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||||
|
| `additionalLazyModuleResources` | <!--v9--> TBD | Used with deprecated SystemJsNgModuleLoader. |
|
||||||
|
|
||||||
|
### @schematics/angular
|
||||||
|
|
||||||
|
| API/Option | May be removed in | Notes |
|
||||||
|
| ------------------------------- | ----------------- |-------------------------------------------------------------------------------- |
|
||||||
|
| `entryComponent` | <!--v9--> TBD | No longer needed with Ivy. |
|
||||||
|
|
||||||
{@a removed}
|
{@a removed}
|
||||||
## Removed APIs
|
## Removed APIs
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc
|
|||||||
|
|
||||||
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code.
|
||||||
|
|
||||||
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --name=*your_project_name*`.
|
Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`.
|
||||||
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
- For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills).
|
||||||
|
|
||||||
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
- For more information about Angular browser support, see [Browser Support](guide/browser-support).
|
||||||
|
@ -78,6 +78,12 @@ Files at the top level of `src/` support testing and running your application. S
|
|||||||
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
|
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
|
||||||
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
|
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
If you create an application using Angular's strict mode, you will also have an additional `package.json` file in the `src/app` directory. For more information, see [Strict mode](/guide/strict-mode).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{@a app-src}
|
{@a app-src}
|
||||||
|
|
||||||
Inside the `src/` folder, the `app/` folder contains your project's logic and data.
|
Inside the `src/` folder, the `app/` folder contains your project's logic and data.
|
||||||
@ -90,6 +96,7 @@ Angular components, templates, and styles go here.
|
|||||||
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
||||||
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
||||||
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
|
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
|
||||||
|
| `app/package.json` | This file is generated only in applications created using `--strict` mode. This file is not used by package managers. It is used to tell the tools and bundlers whether the code under this directory is free of non-local [side-effects](guide/strict-mode#side-effect). |
|
||||||
|
|
||||||
### Application configuration files
|
### Application configuration files
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
The Angular team has worked hard to ensure Ivy is as backwards-compatible with the previous rendering engine ("View Engine") as possible.
|
The Angular team has worked hard to ensure Ivy is as backwards-compatible with the previous rendering engine ("View Engine") as possible.
|
||||||
However, in rare cases, minor changes were necessary to ensure that the Angular's behavior was predictable and consistent, correcting issues in the View Engine implementation.
|
However, in rare cases, minor changes were necessary to ensure that the Angular's behavior was predictable and consistent, correcting issues in the View Engine implementation.
|
||||||
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-9#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
|
In order to smooth the transition, we have provided [automated migrations](guide/updating-to-version-10#migrations) wherever possible so your application and library code is migrated automatically by the CLI.
|
||||||
That said, some applications will likely need to apply some manual updates.
|
That said, some applications will likely need to apply some manual updates.
|
||||||
|
|
||||||
{@a debugging}
|
{@a debugging}
|
||||||
## How to debug errors with Ivy
|
## How to debug errors with Ivy
|
||||||
|
|
||||||
In version 9, [a few deprecated APIs have been removed](guide/updating-to-version-9#removals) and there are a [few breaking changes](guide/updating-to-version-9#breaking-changes) unrelated to Ivy.
|
In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy.
|
||||||
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
If you're seeing errors after updating to version 9, you'll first want to rule those changes out.
|
||||||
|
|
||||||
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app.
|
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app.
|
||||||
|
|
||||||
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 9 guide](guide/updating-to-version-9). If you've opted into any of the stricter type-checking settings that are new with v9, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck).
|
||||||
|
|
||||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below.
|
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below.
|
||||||
|
|
||||||
|
@ -495,7 +495,7 @@ for one turn of the browser's JavaScript cycle, which triggers a new change-dete
|
|||||||
|
|
||||||
#### Write lean hook methods to avoid performance problems
|
#### Write lean hook methods to avoid performance problems
|
||||||
|
|
||||||
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`$emdash;often when there are no changes of interest.
|
When you run the *AfterView* sample, notice how frequently Angular calls `AfterViewChecked()`-often when there are no changes of interest.
|
||||||
Be very careful about how much logic or computation you put into one of these methods.
|
Be very careful about how much logic or computation you put into one of these methods.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
187
aio/content/guide/lightweight-injection-tokens.md
Normal file
187
aio/content/guide/lightweight-injection-tokens.md
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
# Optimizing client app size with lightweight injection tokens
|
||||||
|
|
||||||
|
This page provides a conceptual overview of a dependency injection technique that is recommended for library developers.
|
||||||
|
Designing your library with *lightweight injection tokens* helps optimize the bundle size of client applications that use your library.
|
||||||
|
|
||||||
|
You can manage the dependency structure among your components and injectable services to optimize bundle size by using [tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||||
|
This normally ensures that if a provided component or service is never actually used by the app, the compiler can eliminate its code from the bundle.
|
||||||
|
|
||||||
|
However, due to the way Angular stores injection tokens, it is possible that such an unused component or service can end up in the bundle anyway.
|
||||||
|
This page describes a dependency-injection design pattern that supports proper tree-shaking by using lightweight injection tokens.
|
||||||
|
|
||||||
|
The lightweight injection token design pattern is especially important for library developers. It ensures that when an application uses only some of your library's capabilities, the unused code can be eliminated from the client's app bundle.
|
||||||
|
|
||||||
|
When an application uses your library, there might be some services that your library supplies which the client app doesn't use.
|
||||||
|
In this case, the app developer should expect that service to be tree-shaken, and not contribute to the size of the compiled app.
|
||||||
|
Because the application developer cannot know about or remedy a tree-shaking problem in the library, it is the responsibility of the library developer to do so.
|
||||||
|
To prevent the retention of unused components, your library should use the lightweight injection token design pattern.
|
||||||
|
|
||||||
|
## When tokens are retained
|
||||||
|
|
||||||
|
To better explain the condition under which token retention occurs, consider a library that provides a library-card component, which contains a body and can contain an optional header.
|
||||||
|
|
||||||
|
```
|
||||||
|
<lib-card>
|
||||||
|
<lib-header>...</lib-header>
|
||||||
|
</lib-card>
|
||||||
|
```
|
||||||
|
|
||||||
|
In a likely implementation, the `<lib-card>` component uses `@ContentChild()` or `@ContentChildren()` to obtain `<lib-header>` and `<lib-body>`, as in the following.
|
||||||
|
|
||||||
|
```
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-header',
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibHeaderComponent {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-card',
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibCardComponent {
|
||||||
|
@ContentChild(LibHeaderComponent)
|
||||||
|
header: LibHeaderComponent|null = null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Because `<lib-header>` is optional, the element can appear in the template in its minimal form,
|
||||||
|
`<lib-card></lib-card>`.
|
||||||
|
In this case, `<lib-header>` is not used and you would expect it to be tree-shaken, but that is not what happens.
|
||||||
|
This is because `LibCardComponent` actually contains two references to the `LibHeaderComponent`.
|
||||||
|
|
||||||
|
`@ContentChild(LibHeaderComponent) header: LibHeaderComponent;`
|
||||||
|
|
||||||
|
* One of these reference is in the *type position*-- that is, it specifies `LibHeaderComponent` as a type: `header: LibHeaderComponent;`.
|
||||||
|
|
||||||
|
* The other reference is in the *value position*-- that is, LibHeaderComponent is the value of the `@ContentChild()` parameter decorator: `@ContentChild(LibHeaderComponent)`.
|
||||||
|
|
||||||
|
The compiler handles token references in these positions differently.
|
||||||
|
|
||||||
|
* The compiler erases *type position* references after conversion from TypeScript, so they have no impact on tree-shaking.
|
||||||
|
|
||||||
|
* The compiler must retain *value position* references at runtime, which prevents the component from being tree-shaken.
|
||||||
|
|
||||||
|
In the example, the compiler retains the `LibHeaderComponent` token that occurs in the value position, which prevents the referenced component from being tree-shaken, even if the application developer does not actually use `<lib-header>` anywhere.
|
||||||
|
If `LibHeaderComponent` is large (code, template, and styles), including it unnecessarily can significantly increase the size of the client application.
|
||||||
|
|
||||||
|
## When to use the lightweight injection token pattern
|
||||||
|
|
||||||
|
The tree-shaking problem arises when a component is used as an injection token.
|
||||||
|
There are two cases when that can happen.
|
||||||
|
|
||||||
|
* The token is used in the value position of a [content query](guide/lifecycle-hooks#using-aftercontent-hooks "See more about using content queries.").
|
||||||
|
* The token is used as a type specifier for constructor injection.
|
||||||
|
|
||||||
|
In the following example, both uses of the `OtherComponent` token cause retention of `OtherComponent` (that is, prevent it from being tree-shaken when it is not used).
|
||||||
|
|
||||||
|
```
|
||||||
|
class MyComponent {
|
||||||
|
constructor(@Optional() other: OtherComponent) {}
|
||||||
|
|
||||||
|
@ContentChild(OtherComponent)
|
||||||
|
other: OtherComponent|null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Although tokens used only as type specifiers are removed when converted to JavaScript, all tokens used for dependency injection are needed at runtime.
|
||||||
|
These effectively change `constructor(@Optional() other: OtherComponent)` to `constructor(@Optional() @Inject(OtherComponent) other)`. The token is now in a value position, and causes the tree shaker to retain the reference.
|
||||||
|
|
||||||
|
<div class="alert is helpful">
|
||||||
|
|
||||||
|
For all services, a library should use [tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers), providing dependencies at the root level rather than in component constructors.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Using lightweight injection tokens
|
||||||
|
|
||||||
|
The lightweight injection token design pattern consists of using a small abstract class as an injection token, and providing the actual implementation at a later stage.
|
||||||
|
The abstract class is retained (not tree-shaken), but it is small and has no material impact on the application size.
|
||||||
|
|
||||||
|
The following example shows how this works for the `LibHeaderComponent`.
|
||||||
|
|
||||||
|
```
|
||||||
|
abstract class LibHeaderToken {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-header',
|
||||||
|
providers: [
|
||||||
|
{provide: LibHeaderToken, useExisting: LibHeaderComponent}
|
||||||
|
]
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibHeaderComponent extends LibHeaderToken {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-card',
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibCardComponent {
|
||||||
|
@ContentChild(LibHeaderToken) header: LibHeaderToken|null = null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the `LibCardComponent` implementation no longer refers to `LibHeaderComponent` in either the type position or the value position.
|
||||||
|
This allows full tree shaking of `LibHeaderComponent` to take place.
|
||||||
|
The `LibHeaderToken` is retained, but it is only a class declaration, with no concrete implementation. It is small and does not materially impact the application size when retained after compilation.
|
||||||
|
|
||||||
|
Instead, `LibHeaderComponent` itself implements the abstract `LibHeaderToken` class. You can safely use that token as the provider in the component definition, allowing Angular to correctly inject the concrete type.
|
||||||
|
|
||||||
|
To summarize, the lightweight injection token pattern consists of the following.
|
||||||
|
|
||||||
|
1. A lightweight injection token that is represented as an abstract class.
|
||||||
|
2. A component definition that implements the abstract class.
|
||||||
|
3. Injection of the lightweight pattern, using ` @ContentChild()` or `@ContentChildren()`.
|
||||||
|
4. A provider in the implementation of the lightweight injection token which associates the lightweight injection token with the implementation.
|
||||||
|
|
||||||
|
### Use the lightweight injection token for API definition
|
||||||
|
|
||||||
|
A component that injects a lightweight injection token might need to invoke a method in the injected class.
|
||||||
|
Because the token is now an abstract class, and the injectable component implements that class, you must also declare an abstract method in the abstract lightweight injection token class.
|
||||||
|
The implementation of the method (with all of its code overhead) resides in the injectable component that can be tree-shaken.
|
||||||
|
This allows the parent to communicate with the child (if it is present) in a type-safe manner.
|
||||||
|
|
||||||
|
For example, the `LibCardComponent` now queries`LibHeaderToken` rather than `LibHeaderComponent`.
|
||||||
|
The following example shows how the pattern allows `LibCardComponent` to communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`.
|
||||||
|
|
||||||
|
```
|
||||||
|
abstract class LibHeaderToken {
|
||||||
|
abstract doSomething(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-header',
|
||||||
|
providers: [
|
||||||
|
{provide: LibHeaderToken, useExisting: LibHeader}
|
||||||
|
]
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibHeaderComponent extends LibHeaderToken {
|
||||||
|
doSomething(): void {
|
||||||
|
// Concrete implementation of `doSomething`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-card',
|
||||||
|
...,
|
||||||
|
})
|
||||||
|
class LibCardComponent implement AfterContentInit {
|
||||||
|
@ContentChild(LibHeaderToken)
|
||||||
|
header: LibHeaderToken|null = null;
|
||||||
|
|
||||||
|
ngAfterContentInit(): void {
|
||||||
|
this.header && this.header.doSomething();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example the parent queries the token to obtain the child component, and stores the resulting component reference if it is present.
|
||||||
|
Before calling a method in the child, the parent component checks to see if the child component is present.
|
||||||
|
If the child component has been tree-shaken, there is no runtime reference to it, and no call to its method.
|
||||||
|
|
||||||
|
### Naming your lightweight injection token
|
||||||
|
|
||||||
|
Lightweight injection tokens are only useful with components. The Angular style guide suggests that you name components using the "Component" suffix. The example "LibHeaderComponent" follows this convention.
|
||||||
|
|
||||||
|
To maintain the relationship between the component and its token while still distinguishing between them, the recommended style is to use the component base name with the suffix "Token" to name your lightweight injection tokens: "LibHeaderToken".
|
55
aio/content/guide/migration-solution-style-tsconfig.md
Normal file
55
aio/content/guide/migration-solution-style-tsconfig.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Solution-style `tsconfig.json` migration
|
||||||
|
|
||||||
|
## What does this migration do?
|
||||||
|
|
||||||
|
This migration adds support to existing projects for TypeScript's new ["solution-style" tsconfig feature](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig).
|
||||||
|
|
||||||
|
Support is added by making two changes:
|
||||||
|
|
||||||
|
1. Renaming the workspace-level `tsconfig.json` to `tsconfig.base.json`.
|
||||||
|
All project [TypeScript configuration files](guide/typescript-configuration) will extend from this base which contains the common options used throughout the workspace.
|
||||||
|
|
||||||
|
2. Adding the solution `tsconfig.json` file at the root of the workspace.
|
||||||
|
This `tsconfig.json` file will only contain references to project-level TypeScript configuration files and is only used by editors/IDEs.
|
||||||
|
|
||||||
|
As an example, the solution `tsconfig.json` for a new project is as follows:
|
||||||
|
```json
|
||||||
|
// This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
|
||||||
|
// It is not intended to be used to perform a compilation.
|
||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./e2e/tsconfig.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why is this migration necessary?
|
||||||
|
|
||||||
|
Solution-style `tsconfig.json` files provide an improved editing experience and fix several long-standing defects when editing files in an IDE.
|
||||||
|
IDEs that leverage the TypeScript language service (for example, [Visual Studio Code](https://code.visualstudio.com)), will only use TypeScript configuration files that are named `tsconfig.json`.
|
||||||
|
In complex projects, there may be more than one compilation unit and each of these units may have different settings and options.
|
||||||
|
|
||||||
|
With the Angular CLI, a project will have application code that will target a browser.
|
||||||
|
It will also have unit tests that should not be included within the built application and that also need additional type information present (`jasmine` in this case).
|
||||||
|
Both parts of the project also share some but not all of the code within the project.
|
||||||
|
As a result, two separate TypeScript configuration files (`tsconfig.app.json` and `tsconfig.spec.json`) are needed to ensure that each part of the application is configured properly and that the right types are used for each part.
|
||||||
|
Also if web workers are used within a project, an additional tsconfig (`tsconfig.worker.json`) is needed.
|
||||||
|
Web workers use similar but incompatible types to the main browser application.
|
||||||
|
This requires the additional configuration file to ensure that the web worker files use the appropriate types and will build successfully.
|
||||||
|
|
||||||
|
While the Angular build system knows about all of these TypeScript configuration files, an IDE using TypeScript's language service does not.
|
||||||
|
Because of this, an IDE will not be able to properly analyze the code from each part of the project and may generate false errors or make suggestions that are incorrect for certain files.
|
||||||
|
By leveraging the new solution-style tsconfig, the IDE can now be aware of the configuration of each part of a project.
|
||||||
|
This allows each file to be treated appropriately based on its tsconfig.
|
||||||
|
IDE features such as error/warning reporting and auto-suggestion will operate more effectively as well.
|
||||||
|
|
||||||
|
The TypeScript 3.9 release [blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig) also contains some additional information regarding this new feature.
|
52
aio/content/guide/migration-update-libraries-tslib.md
Normal file
52
aio/content/guide/migration-update-libraries-tslib.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# `tslib` direct dependency migration
|
||||||
|
|
||||||
|
## What does this migration do?
|
||||||
|
|
||||||
|
If you have any libraries within your workspace, this migration will convert `tslib` peer dependencies to direct dependencies for the libraries.
|
||||||
|
TypeScript uses the `tslib` package to provide common helper functions used in compiled TypeScript code.
|
||||||
|
The `tslib` version is also updated to `2.0.0` to support TypeScript 3.9.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "my-lib",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^9.0.0",
|
||||||
|
"@angular/core": "^9.0.0",
|
||||||
|
"tslib": "^1.12.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "my-lib",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^9.0.0",
|
||||||
|
"@angular/core": "^9.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why is this migration necessary?
|
||||||
|
|
||||||
|
The [`tslib`](https://github.com/Microsoft/tslib) is a runtime library for Typescript.
|
||||||
|
The version of this library is bound to the version of the TypeScript compiler used to compile a library.
|
||||||
|
Peer dependencies do not accurately represent this relationship between the runtime and the compiler.
|
||||||
|
If `tslib` remained declared as a library peer dependency, it would be possible for some Angular workspaces to get into a state where the workspace could not satisfy `tslib` peer dependency requirements for multiple libraries, resulting in build-time or run-time errors.
|
||||||
|
|
||||||
|
As of TypeScript 3.9 (used by Angular v10), `tslib` version of 2.x is required to build new applications.
|
||||||
|
However, older libraries built with previous version of TypeScript and already published to npm might need `tslib` 1.x.
|
||||||
|
This migration makes it possible for code depending on incompatible versions of the `tslib` runtime library to remain interoperable.
|
||||||
|
|
||||||
|
|
||||||
|
## Do I still need `tslib` as a dependency in my workspace `package.json`?
|
||||||
|
|
||||||
|
Yes.
|
||||||
|
The `tslib` dependency declared in the `package.json` file of the workspace is used to build applications within this workspace, as well as run unit tests for workspace libraries, and is required.
|
@ -0,0 +1,33 @@
|
|||||||
|
# Update `module` and `target` compiler options migration
|
||||||
|
|
||||||
|
## What does this migration do?
|
||||||
|
|
||||||
|
This migration adjusts the [`target`](https://www.typescriptlang.org/v2/en/tsconfig#target) and [`module`](https://www.typescriptlang.org/v2/en/tsconfig#module) settings within the [TypeScript configuration files](guide/typescript-configuration) for the workspace.
|
||||||
|
The changes to each option vary based on the builder or command that uses the TypeScript configuration file.
|
||||||
|
Unless otherwise noted, changes are only made if the existing value was not changed since the project was created.
|
||||||
|
This process helps ensure that intentional changes to the options are kept in place.
|
||||||
|
|
||||||
|
TypeScript Configuration File(s) | Changed Property | Existing Value | New Value
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
`<workspace base>/tsconfig.base.json` | `"module"` | `"esnext"` | `"es2020"`
|
||||||
|
Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
|
Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
|
Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"`
|
||||||
|
Used in `server` builder options (universal) | `"module"` | `"commonjs"` | _removed_
|
||||||
|
Used in `server` builder options (universal) | `"target"` | _any_ | `"es2016"`
|
||||||
|
Used in `protractor` builder options (`ng e2e` for applications) | `"target"` | `"es5"` | `"es2018"`
|
||||||
|
|
||||||
|
## Why is this migration necessary?
|
||||||
|
|
||||||
|
This migration provides improvements to the long-term supportability of projects by updating the projects to use recommended best practice compilation options.
|
||||||
|
|
||||||
|
For the functionality that executes on Node.js, such as Universal and Protractor, the new settings provide performance and troubleshooting benefits as well.
|
||||||
|
The minimum Node.js version for the Angular CLI (v10.13) supports features in ES2018 and earlier.
|
||||||
|
By targeting later ES versions, the compiler transforms less code and can use newer features directly.
|
||||||
|
Since zone.js does not support native `async` and `await`, the universal builds still target ES2016.
|
||||||
|
|
||||||
|
## Why `"es2020"` instead of `"esnext"`?
|
||||||
|
|
||||||
|
In TypeScript 3.9, the behavior of the TypeScript compiler controlled by `module` is the same with both `"esnext"` and `"es2020"` values.
|
||||||
|
This behavior can change in the future, because the `"esnext"` option could evolve in a backwards incompatible ways, resulting in build-time or run-time errors during a TypeScript update.
|
||||||
|
As a result, code can become unstable. Using the `"es2020"` option mitigates this risk.
|
@ -118,7 +118,6 @@ Package name | Description
|
|||||||
[**@angular‑devkit/<br />build‑angular**](https://github.com/angular/angular-cli/) | The Angular build tools.
|
[**@angular‑devkit/<br />build‑angular**](https://github.com/angular/angular-cli/) | The Angular build tools.
|
||||||
[**@angular/cli**](https://github.com/angular/angular-cli/) | The Angular CLI tools.
|
[**@angular/cli**](https://github.com/angular/angular-cli/) | The Angular CLI tools.
|
||||||
**@angular/<br />compiler‑cli** | The Angular compiler, which is invoked by the Angular CLI's `ng build` and `ng serve` commands.
|
**@angular/<br />compiler‑cli** | The Angular compiler, which is invoked by the Angular CLI's `ng build` and `ng serve` commands.
|
||||||
**@angular/<br />language‑service** | The [Angular language service](guide/language-service) analyzes component templates and provides type and error information that TypeScript-aware editors can use to improve the developer's experience. For example, see the [Angular language service extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Angular.ng-template).
|
|
||||||
**@types/... ** | TypeScript definition files for 3rd party libraries such as Jasmine and Node.js.
|
**@types/... ** | TypeScript definition files for 3rd party libraries such as Jasmine and Node.js.
|
||||||
[**codelyzer**](https://www.npmjs.com/package/codelyzer) | A linter for Angular apps whose rules conform to the Angular [style guide](guide/styleguide).
|
[**codelyzer**](https://www.npmjs.com/package/codelyzer) | A linter for Angular apps whose rules conform to the Angular [style guide](guide/styleguide).
|
||||||
**jasmine/... ** | Packages to support the [Jasmine](https://jasmine.github.io/) test library.
|
**jasmine/... ** | Packages to support the [Jasmine](https://jasmine.github.io/) test library.
|
||||||
@ -135,3 +134,4 @@ Package name | Description
|
|||||||
|
|
||||||
* [Building and serving](guide/build) describes how packages come together to create a development build.
|
* [Building and serving](guide/build) describes how packages come together to create a development build.
|
||||||
* [Deployment](guide/deployment) describes how packages come together to create a production build.
|
* [Deployment](guide/deployment) describes how packages come together to create a production build.
|
||||||
|
|
@ -112,7 +112,7 @@ Because observables produce values asynchronously, try/catch will not effectivel
|
|||||||
<code-example>
|
<code-example>
|
||||||
myObservable.subscribe({
|
myObservable.subscribe({
|
||||||
next(num) { console.log('Next num: ' + num)},
|
next(num) { console.log('Next num: ' + num)},
|
||||||
error(err) { console.log('Received an errror: ' + err)}
|
error(err) { console.log('Received an error: ' + err)}
|
||||||
});
|
});
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ The following table provides the status for Angular versions under support.
|
|||||||
|
|
||||||
Version | Status | Released | Active Ends | LTS Ends
|
Version | Status | Released | Active Ends | LTS Ends
|
||||||
------- | ------ | ------------ | ------------ | ------------
|
------- | ------ | ------------ | ------------ | ------------
|
||||||
|
^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021
|
||||||
^9.0.0 | Active | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
|
^9.0.0 | Active | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021
|
||||||
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Schematics for libraries
|
# Schematics for libraries
|
||||||
|
|
||||||
When you create an Angular library, you can provide and package it with schematics that integrate it with the Angular CLI.
|
When you create an Angular library, you can provide and package it with schematics that integrate it with the Angular CLI.
|
||||||
With your schematics, your users can use `ng add` to install an initial version of your library,
|
With your schematics, your users can use `ng add` to install an initial version of your library,
|
||||||
`ng generate` to create artifacts defined in your library, and `ng update` to adjust their project for a new version of your library that introduces breaking changes.
|
`ng generate` to create artifacts defined in your library, and `ng update` to adjust their project for a new version of your library that introduces breaking changes.
|
||||||
|
|
||||||
All three types of schematics can be part of a collection that you package with your library.
|
All three types of schematics can be part of a collection that you package with your library.
|
||||||
@ -115,10 +115,10 @@ When you add a schematic to the collection, you have to point to it in the colle
|
|||||||
<code-example header="projects/my-lib/schematics/my-service/schema.json (Schematic JSON Schema)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json">
|
<code-example header="projects/my-lib/schematics/my-service/schema.json (Schematic JSON Schema)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
* *id* : A unique id for the schema in the collection.
|
* *id*: A unique id for the schema in the collection.
|
||||||
* *title* : A human-readable description of the schema.
|
* *title*: A human-readable description of the schema.
|
||||||
* *type* : A descriptor for the type provided by the properties.
|
* *type*: A descriptor for the type provided by the properties.
|
||||||
* *properties* : An object that defines the available options for the schematic.
|
* *properties*: An object that defines the available options for the schematic.
|
||||||
|
|
||||||
Each option associates key with a type, description, and optional alias.
|
Each option associates key with a type, description, and optional alias.
|
||||||
The type defines the shape of the value you expect, and the description is displayed when the user requests usage help for your schematic.
|
The type defines the shape of the value you expect, and the description is displayed when the user requests usage help for your schematic.
|
||||||
@ -130,9 +130,9 @@ When you add a schematic to the collection, you have to point to it in the colle
|
|||||||
<code-example header="projects/my-lib/schematics/my-service/schema.ts (Schematic Interface)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts">
|
<code-example header="projects/my-lib/schematics/my-service/schema.ts (Schematic Interface)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
* *name* : The name you want to provide for the created service.
|
* *name*: The name you want to provide for the created service.
|
||||||
* *path* : Overrides the path provided to the schematic. The default path value is based on the current working directory.
|
* *path*: Overrides the path provided to the schematic. The default path value is based on the current working directory.
|
||||||
* *project* : Provides a specific project to run the schematic on. In the schematic, you can provide a default if the option is not provided by the user.
|
* *project*: Provides a specific project to run the schematic on. In the schematic, you can provide a default if the option is not provided by the user.
|
||||||
|
|
||||||
### Add template files
|
### Add template files
|
||||||
|
|
||||||
@ -169,10 +169,9 @@ The Schematics framework provides a file templating system, which supports both
|
|||||||
The system operates on placeholders defined inside files or paths that loaded in the input `Tree`.
|
The system operates on placeholders defined inside files or paths that loaded in the input `Tree`.
|
||||||
It fills these in using values passed into the `Rule`.
|
It fills these in using values passed into the `Rule`.
|
||||||
|
|
||||||
For details of these data structure and syntax, see the [Schematics README](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/README.md).
|
For details of these data structures and syntax, see the [Schematics README](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/README.md).
|
||||||
|
|
||||||
|
1. Create the main file `index.ts` and add the source code for your schematic factory function.
|
||||||
1. Create the main file, `index.ts` and add the source code for your schematic factory function.
|
|
||||||
|
|
||||||
1. First, import the schematics definitions you will need. The Schematics framework offers many utility functions to create and use rules when running a schematic.
|
1. First, import the schematics definitions you will need. The Schematics framework offers many utility functions to create and use rules when running a schematic.
|
||||||
|
|
||||||
@ -271,7 +270,6 @@ For more information about rules and utility methods, see [Provided Rules](https
|
|||||||
|
|
||||||
After you build your library and schematics, you can install the schematics collection to run against your project. The steps below show you how to generate a service using the schematic you created above.
|
After you build your library and schematics, you can install the schematics collection to run against your project. The steps below show you how to generate a service using the schematic you created above.
|
||||||
|
|
||||||
|
|
||||||
### Build your library and schematics
|
### Build your library and schematics
|
||||||
|
|
||||||
From the root of your workspace, run the `ng build` command for your library.
|
From the root of your workspace, run the `ng build` command for your library.
|
||||||
|
@ -25,49 +25,48 @@ To use the Angular framework, you should be familiar with the following:
|
|||||||
|
|
||||||
Knowledge of [TypeScript](https://www.typescriptlang.org/) is helpful, but not required.
|
Knowledge of [TypeScript](https://www.typescriptlang.org/) is helpful, but not required.
|
||||||
|
|
||||||
|
To install Angular on your local system, you need the following:
|
||||||
|
|
||||||
{@a nodejs}
|
{@a nodejs}
|
||||||
### Node.js
|
|
||||||
|
|
||||||
Make sure your development environment includes `Node.js®` and an npm package manager.
|
* **Node.js**
|
||||||
|
|
||||||
Angular requires a [current, active LTS, or maintenance LTS](https://nodejs.org/about/releases/) version of `Node.js`. See the `engines` key for the specific version requirements in our [package.json](https://unpkg.com/@angular/cli/package.json).
|
Angular requires a [current, active LTS, or maintenance LTS](https://nodejs.org/about/releases) version of Node.js.
|
||||||
|
|
||||||
* To check your version, run `node -v` in a terminal/console window.
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
* To get `Node.js`, go to [nodejs.org](https://nodejs.org "Nodejs.org").
|
For information about specific version requirements, see the `engines` key in the [package.json](https://unpkg.com/@angular/cli/package.json) file.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
For more information on installing Node.js, see [nodejs.org](http://nodejs.org "Nodejs.org").
|
||||||
|
If you are unsure what version of Node.js runs on your system, run `node -v` in a terminal window.
|
||||||
|
|
||||||
{@a npm}
|
{@a npm}
|
||||||
### npm package manager
|
|
||||||
|
|
||||||
Angular, the Angular CLI, and Angular apps depend on features and functionality provided by libraries that are available as [npm packages](https://docs.npmjs.com/getting-started/what-is-npm). To download and install npm packages, you must have an npm package manager.
|
* **npm package manager**
|
||||||
|
|
||||||
This setup guide uses the [npm client](https://docs.npmjs.com/cli/install) command line interface, which is installed with `Node.js` by default.
|
Angular, the Angular CLI, and Angular applications depend on [npm packages](https://docs.npmjs.com/getting-started/what-is-npm) for many features and functions.
|
||||||
|
To download and install npm packages, you need an npm package manager.
|
||||||
To check that you have the npm client installed, run `npm -v` in a terminal/console window.
|
This guide uses the [npm client](https://docs.npmjs.com/cli/install) command line interface, which is installed with `Node.js` by default.
|
||||||
|
To check that you have the npm client installed, run `npm -v` in a terminal window.
|
||||||
|
|
||||||
|
|
||||||
{@a install-cli}
|
{@a install-cli}
|
||||||
|
|
||||||
## Step 1: Install the Angular CLI
|
## Install the Angular CLI
|
||||||
|
|
||||||
You use the Angular CLI
|
You use the Angular CLI to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
|
||||||
to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
|
|
||||||
|
|
||||||
Install the Angular CLI globally.
|
|
||||||
|
|
||||||
To install the CLI using `npm`, open a terminal/console window and enter the following command:
|
|
||||||
|
|
||||||
|
To install the Angular CLI, open a terminal window and run the following command:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm install -g @angular/cli
|
npm install -g @angular/cli
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a create-proj}
|
{@a create-proj}
|
||||||
|
|
||||||
## Step 2: Create a workspace and initial application
|
## Create a workspace and initial application
|
||||||
|
|
||||||
You develop apps in the context of an Angular [**workspace**](guide/glossary#workspace).
|
You develop apps in the context of an Angular [**workspace**](guide/glossary#workspace).
|
||||||
|
|
||||||
@ -86,16 +85,22 @@ The Angular CLI installs the necessary Angular npm packages and other dependenci
|
|||||||
|
|
||||||
The CLI creates a new workspace and a simple Welcome app, ready to run.
|
The CLI creates a new workspace and a simple Welcome app, ready to run.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
You also have the option to use Angular's strict mode, which can help you write better, more maintainable code.
|
||||||
|
For more information, see [Strict mode](/guide/strict-mode).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{@a serve}
|
{@a serve}
|
||||||
|
|
||||||
## Step 3: Run the application
|
## Run the application
|
||||||
|
|
||||||
The Angular CLI includes a server, so that you can easily build and serve your app locally.
|
The Angular CLI includes a server, so that you can build and serve your app locally.
|
||||||
|
|
||||||
1. Go to the workspace folder (`my-app`).
|
1. Navigate to the workspace folder, such as `my-app`.
|
||||||
|
|
||||||
1. Launch the server by using the CLI command `ng serve`, with the `--open` option.
|
1. Run the following command:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
cd my-app
|
cd my-app
|
||||||
@ -108,7 +113,7 @@ and rebuilds the app as you make changes to those files.
|
|||||||
The `--open` (or just `-o`) option automatically opens your browser
|
The `--open` (or just `-o`) option automatically opens your browser
|
||||||
to `http://localhost:4200/`.
|
to `http://localhost:4200/`.
|
||||||
|
|
||||||
You will see:
|
If your installation and setup was successful, you should see a page similar to the following.
|
||||||
|
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
46
aio/content/guide/strict-mode.md
Normal file
46
aio/content/guide/strict-mode.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Strict mode
|
||||||
|
|
||||||
|
When you create a new workspace or a project you have an option to create them in a strict mode using the `--strict` flag.
|
||||||
|
|
||||||
|
Enabling this flag initializes your new workspace or project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your application.
|
||||||
|
Additionally, applications that use these stricter settings are easier to statically analyze, which can help the `ng update` command refactor code more safely and precisely when you are updating to future versions of Angular.
|
||||||
|
|
||||||
|
Specifically, the `strict` flag does the following:
|
||||||
|
|
||||||
|
* Enables [`strict` mode in TypeScript](https://www.staging-typescript.org/tsconfig#strict), as well as other strictness flags recommended by the TypeScript team. Specifically, `forceConsistentCasingInFileNames`, `noImplicitReturns`, `noFallthroughCasesInSwitch`.
|
||||||
|
* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates) and [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters)
|
||||||
|
* [Bundle size budgets](guide/build#configuring-size-budgets) have been reduced by ~75%
|
||||||
|
* Turns on [`no-any` tslint rule](https://palantir.github.io/tslint/rules/no-any/) to prevent declarations of type `any`
|
||||||
|
* [Marks your application as side-effect free](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) to enable more advanced tree-shaking
|
||||||
|
|
||||||
|
You can apply these settings at the workspace and project level.
|
||||||
|
|
||||||
|
To create a new workspace and application using the strict mode, run the following command:
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
|
||||||
|
ng new [project-name] --strict
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
To create a new application in the strict mode within an existing non-strict workspace, run the following command:
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
|
||||||
|
ng generate application [project-name] --strict
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
{@a side-effect}
|
||||||
|
|
||||||
|
### Non-local side effects in applications
|
||||||
|
|
||||||
|
When you create projects and workspaces using the `strict` mode, you'll notice an additional `package.json` file, located in `src/app/` directory.
|
||||||
|
This file informs tools and bundlers that the code under this directory is free of non-local side effects. Non-local side effects in the application code are not common and using them is not considered a good coding pattern.
|
||||||
|
More importantly, code with these types of side effects cannot be optimized, resulting in increased bundle sizes and applications that load more slowly.
|
||||||
|
|
||||||
|
If you need more information, the following links may be helpful.
|
||||||
|
|
||||||
|
* [Tree-shaking](https://webpack.js.org/guides/tree-shaking/)
|
||||||
|
* [Dealing with side effects and pure functions in JavaScript](https://dev.to/vonheikemen/dealing-with-side-effects-and-pure-functions-in-javascript-16mg)
|
||||||
|
* [How to deal with dirty side effects in your pure function JavaScript](https://jrsinclair.com/articles/2018/how-to-deal-with-dirty-side-effects-in-your-pure-functional-javascript/)
|
@ -359,10 +359,11 @@ Then inject it inside a test by calling `TestBed.inject()` with the service clas
|
|||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
**Note:** We used to have `TestBed.get()` instead of `TestBed.inject()`.
|
**Note:** `TestBed.get()` was deprecated as of Angular version 9.
|
||||||
The `get` method wasn't type safe, it always returned `any`, and this is error prone.
|
To help minimize breaking changes, Angular introduces a
|
||||||
We decided to migrate to a new function instead of updating the existing one given
|
new function called `TestBed.inject()`, which you should use instead.
|
||||||
the large scale use that would have an immense amount of breaking changes.
|
For information on the removal of `TestBed.get()`,
|
||||||
|
see its entry in the [Deprecations index](guide/deprecations#index).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -79,6 +79,10 @@ The initial `tsconfig.base.json` for an Angular workspace typically looks like t
|
|||||||
}
|
}
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
### Strict mode
|
||||||
|
|
||||||
|
When you create new workspaces and projects, you have the option to use Angular's strict mode, which can help you write better, more maintainable code.
|
||||||
|
For more information, see [Strict mode](/guide/strict-mode).
|
||||||
|
|
||||||
{@a noImplicitAny}
|
{@a noImplicitAny}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ as a navigation URL intended for the router.
|
|||||||
|
|
||||||
Fortunately, application routes have something in common: their URLs lack file extensions.
|
Fortunately, application routes have something in common: their URLs lack file extensions.
|
||||||
(Data requests also lack extensions but they're easy to recognize because they always begin with `/api`.)
|
(Data requests also lack extensions but they're easy to recognize because they always begin with `/api`.)
|
||||||
All static asset requests have a file extension (such as `main.js` or `/node_modules/zone.js/dist/zone.js`).
|
All static asset requests have a file extension (such as `main.js` or `/node_modules/zone.js/bundles/zone.umd.js`).
|
||||||
|
|
||||||
Because we use routing, we can easily recognize the three types of requests and handle them differently.
|
Because we use routing, we can easily recognize the three types of requests and handle them differently.
|
||||||
|
|
||||||
|
82
aio/content/guide/updating-to-version-10.md
Normal file
82
aio/content/guide/updating-to-version-10.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Updating to Angular version 10
|
||||||
|
|
||||||
|
This guide contains information related to updating to version 10 of Angular.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
For information on upgrading to Angular version 9, see [Updating to Angular version 9](https://v9.angular.io/guide/updating-to-version-9).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Updating CLI Apps
|
||||||
|
|
||||||
|
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
|
||||||
|
|
||||||
|
If you're curious about the specific migrations being run by the CLI, see the [automated migrations section](#migrations) for details on what code is changing and why.
|
||||||
|
|
||||||
|
## Changes and Deprecations in Version 10
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{@a breaking-changes}
|
||||||
|
### New Breaking Changes
|
||||||
|
|
||||||
|
* Typescript 3.6, 3.7, and 3.8 are no longer supported. Please update to Typescript 3.9.
|
||||||
|
* Input fields of type `number` fire the `valueChanges` event only once per value change (as opposed to twice in some cases). See [PR 36087](https://github.com/angular/angular/pull/36087).
|
||||||
|
* The `minLength` and `maxLength` validators only validate values that have a numeric `length` property. See [PR 36157](https://github.com/angular/angular/pull/36157).
|
||||||
|
* Templates with unknown property bindings or unknown element names now log errors instead of warnings. See [PR 36399](https://github.com/angular/angular/pull/36399).
|
||||||
|
* `UrlMatcher` can now return `null` values. See [PR 36402](https://github.com/angular/angular/pull/36402).
|
||||||
|
* Transplanted views now refresh at insertion point only. See [PR 35968](https://github.com/angular/angular/pull/35968).
|
||||||
|
* Formatting times with the `b` or `B` format codes now supports time periods that cross midnight. See [PR 36611](https://github.com/angular/angular/pull/36611).
|
||||||
|
* Navigation is canceled for routes with at least one empty resolver. See [PR 24621](https://github.com/angular/angular/pull/24621).
|
||||||
|
|
||||||
|
{@a deprecations}
|
||||||
|
### New Deprecations
|
||||||
|
|
||||||
|
| Area | API or Feature | May be removed in |
|
||||||
|
| ----------------------------- | --------------------------------------------------------------------------- | ----------------- |
|
||||||
|
| `@angular/core` | [`WrappedValue`](guide/deprecations#wrapped-value) | <!--v10--> v12 |
|
||||||
|
| browser support | [`IE 9, 10, and IE Mobile`](guide/deprecations#ie-9-10-and-ie-mobile-support) | <!--v10--> v11 |
|
||||||
|
|
||||||
|
|
||||||
|
{@a removals}
|
||||||
|
### New Removals of Deprecated APIs
|
||||||
|
|
||||||
|
The following APIs have been removed starting with version 10.0.0*:
|
||||||
|
|
||||||
|
| Package | API | Replacement | Notes |
|
||||||
|
| ---------------- | -------------- | ----------- | ----- |
|
||||||
|
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||||
|
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||||
|
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](/guide/deprecations#style-sanitization) for more info
|
||||||
|
| `@angular/bazel` | [`Bazel builder and schematics`](guide/deprecations#bazelbuilder) | `bazelbuild/rules_nodejs` | [More info](https://github.com/angular/angular/tree/10.0.x/packages/bazel/src/schematics) |
|
||||||
|
|
||||||
|
|
||||||
|
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||||
|
|
||||||
|
{@a ivy}
|
||||||
|
|
||||||
|
## Ivy features and compatibility
|
||||||
|
|
||||||
|
Since version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
|
||||||
|
|
||||||
|
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
|
||||||
|
|
||||||
|
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
|
||||||
|
|
||||||
|
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
|
||||||
|
|
||||||
|
{@a migrations}
|
||||||
|
## Automated Migrations for Version 10
|
||||||
|
|
||||||
|
Read about the migrations the CLI handles for you automatically:
|
||||||
|
|
||||||
|
* [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
|
||||||
|
* [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
|
||||||
|
* [Solution-style `tsconfig.json` migration](guide/migration-solution-style-tsconfig)
|
||||||
|
* [`tslib` direct dependency migration](guide/migration-update-libraries-tslib)
|
||||||
|
* [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options)
|
@ -1,90 +0,0 @@
|
|||||||
# Updating to Angular version 9
|
|
||||||
|
|
||||||
This guide contains information related to updating to version 9 of Angular.
|
|
||||||
|
|
||||||
## Updating CLI Apps
|
|
||||||
|
|
||||||
For step-by-step instructions on how to update to the latest Angular release (and leverage our automated migration tools to do so), use the interactive update guide at [update.angular.io](https://update.angular.io).
|
|
||||||
|
|
||||||
If you're curious about the specific migrations being run by the CLI, see the [automated migrations section](#migrations) for details on what code is changing and why.
|
|
||||||
|
|
||||||
## Changes and Deprecations in Version 9
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
For information about Angular's deprecation and removal practices, see [Angular Release Practices](guide/releases#deprecation-practices "Angular Release Practices: Deprecation practices").
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a breaking-changes}
|
|
||||||
### New Breaking Changes
|
|
||||||
|
|
||||||
- Angular now compiles with Ivy by default. See the [Ivy compatibility section](#ivy).
|
|
||||||
|
|
||||||
- CLI apps compile in [AOT mode](/guide/aot-compiler) by default (which includes template type-checking).
|
|
||||||
Users who only built with JIT before may see new type errors.
|
|
||||||
See our [template type-checking guide](guide/template-typecheck) for more information and debugging tips.
|
|
||||||
|
|
||||||
- Typescript 3.4 and 3.5 are no longer supported. Please update to Typescript 3.7.
|
|
||||||
|
|
||||||
- `tslib` is now listed as a peer dependency rather than a direct dependency. If you are not using the CLI, you must manually install `tslib`, using `yarn add tslib` or `npm install tslib --save`.
|
|
||||||
|
|
||||||
{@a deprecations}
|
|
||||||
### New Deprecations
|
|
||||||
|
|
||||||
| API | Replacement | Notes |
|
|
||||||
| ------------------------------------------------------------------------| ------------------------------------ | ----- |
|
|
||||||
| [`entryComponents`](api/core/NgModule#entryComponents) | none | See [`entryComponents`](guide/deprecations#entryComponents) |
|
|
||||||
| [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation)| `{provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}` | From v11 the default code will be extracted from the locale data given by `LOCAL_ID`, rather than `USD`. |
|
|
||||||
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](guide/deprecations#entryComponents) |
|
|
||||||
| `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | |
|
|
||||||
| Undecorated base classes that use Angular features | Base classes with `@Directive()` decorator that use Angular features | |
|
|
||||||
| `esm5` and `fesm5` distribution in `@angular/*` npm packages | `esm2015` and `fesm2015` entrypoints | See [`esm5` and `fesm5`](guide/deprecations#esm5-fesm5) |
|
|
||||||
| [`TestBed.get`](api/core/testing/TestBed#get) | [`TestBed.inject`](api/core/testing/TestBed#inject) | Same behavior, but type safe. |
|
|
||||||
|
|
||||||
|
|
||||||
{@a removals}
|
|
||||||
### New Removals of Deprecated APIs
|
|
||||||
|
|
||||||
| Package | API | Replacement | Notes |
|
|
||||||
| ------- | -------------- | ----------- | ----- |
|
|
||||||
| `@angular/core` | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](api/core/Renderer2) | [Migration guide.](guide/migration-renderer) |
|
|
||||||
| `@angular/core` | [`RootRenderer`](https://v8.angular.io/api/core/RootRenderer) | [`RendererFactory2`](api/core/RendererFactory2) | none |
|
|
||||||
| `@angular/core` | [`RenderComponentType`](https://v8.angular.io/api/core/RenderComponentType) | [`RendererType2`](api/core/RendererType2) | none |
|
|
||||||
| `@angular/core` | [`WtfScopeFn`](https://v8.angular.io/api/core/WtfScopeFn) | none | v8 | See [Web Tracing Framework](#wtf) |
|
|
||||||
| `@angular/core` | [`wtfCreateScope`](https://v8.angular.io/api/core/wtfCreateScope) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
|
|
||||||
| `@angular/core` | [`wtfStartTimeRange`](https://v8.angular.io/api/core/wtfStartTimeRange) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
|
|
||||||
| `@angular/core` | [`wtfEndTimeRange`](https://v8.angular.io/api/core/wtfEndTimeRange) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
|
|
||||||
| `@angular/core` | [`wtfLeave`](https://v8.angular.io/api/core/wtfLeave) | none | v8 | See [Web Tracing Framework](guide/deprecations#wtf) |
|
|
||||||
| `@angular/common` | `DeprecatedI18NPipesModule` | [`CommonModule`](api/common/CommonModule#pipes) | none |
|
|
||||||
| `@angular/common` | `DeprecatedCurrencyPipe` | [`CurrencyPipe`](api/common/CurrencyPipe) | none |
|
|
||||||
| `@angular/common` | `DeprecatedDatePipe` | [`DatePipe`](api/common/DatePipe) | none |
|
|
||||||
| `@angular/common` | `DeprecatedDecimalPipe` | [`DecimalPipe`](api/common/DecimalPipe) | none |
|
|
||||||
| `@angular/common` | `DeprecatedPercentPipe` | [`PercentPipe`](api/common/PercentPipe) | none |
|
|
||||||
| `@angular/forms` | [`NgFormSelectorWarning`](https://v8.angular.io/api/forms/NgFormSelectorWarning) | none |
|
|
||||||
| `@angular/forms` | `ngForm` element selector | `ng-form` element selector | none |
|
|
||||||
| `@angular/service-worker` | `versionedFiles` | `files` | In the service worker configuration file `ngsw-config.json`, replace `versionedFiles` with `files`. See [Service Worker Configuration](guide/service-worker-config#assetgroups). |
|
|
||||||
|
|
||||||
{@a ivy}
|
|
||||||
|
|
||||||
## Ivy features and compatibility
|
|
||||||
|
|
||||||
In Version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
|
|
||||||
|
|
||||||
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
|
|
||||||
|
|
||||||
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
|
|
||||||
|
|
||||||
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
|
|
||||||
|
|
||||||
{@a migrations}
|
|
||||||
## Automated Migrations for Version 9
|
|
||||||
|
|
||||||
Read about the migrations the CLI handles for you automatically:
|
|
||||||
|
|
||||||
- [Migrating from `Renderer` to `Renderer2`](guide/migration-renderer)
|
|
||||||
- [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes)
|
|
||||||
- [Migrating missing `@Injectable()` decorators and incomplete provider definitions](guide/migration-injectable)
|
|
||||||
- [Migrating dynamic queries](guide/migration-dynamic-flag)
|
|
||||||
- [Migrating to the new `$localize` i18n support](guide/migration-localize)
|
|
||||||
- [Migrating `ModuleWithProviders`](guide/migration-module-with-providers)
|
|
@ -41,6 +41,11 @@ When you create a library project with `ng generate library`, the library projec
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Strict mode
|
||||||
|
|
||||||
|
When you create new workspaces and projects, you have the option to use Angular's strict mode, which can help you write better, more maintainable code.
|
||||||
|
For more information, see [Strict mode](/guide/strict-mode).
|
||||||
|
|
||||||
## Project configuration options
|
## Project configuration options
|
||||||
|
|
||||||
The following top-level configuration properties are available for each project, under `projects:<project_name>`.
|
The following top-level configuration properties are available for each project, under `projects:<project_name>`.
|
||||||
|
BIN
aio/content/images/bios/ahasall.jpg
Normal file
BIN
aio/content/images/bios/ahasall.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
aio/content/images/bios/sonukapoor.jpg
Normal file
BIN
aio/content/images/bios/sonukapoor.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
@ -596,6 +596,13 @@
|
|||||||
"twitter": "devjoost",
|
"twitter": "devjoost",
|
||||||
"bio": "Joost is a Software Engineer from the Netherlands with an interest in open source software who likes to learn something new every day. He works at Blueriq during the day and contributes to Angular in his spare time, by working on the Angular compiler and runtime. He may review your PR even if you never asked for it ;)"
|
"bio": "Joost is a Software Engineer from the Netherlands with an interest in open source software who likes to learn something new every day. He works at Blueriq during the day and contributes to Angular in his spare time, by working on the Angular compiler and runtime. He may review your PR even if you never asked for it ;)"
|
||||||
},
|
},
|
||||||
|
"sonukapoor": {
|
||||||
|
"name": "Sonu Kapoor",
|
||||||
|
"groups": ["Collaborators"],
|
||||||
|
"picture": "sonukapoor.jpg",
|
||||||
|
"website": "https://www.linkedin.com/in/sonu-kapoor/",
|
||||||
|
"bio": "Sonu is a Software Engineer from Toronto, with a high interest in front-end technologies and algorithms."
|
||||||
|
},
|
||||||
"jschwarty": {
|
"jschwarty": {
|
||||||
"name": "Justin Schwartzenberger",
|
"name": "Justin Schwartzenberger",
|
||||||
"picture": "justinschwartzenberger.jpg",
|
"picture": "justinschwartzenberger.jpg",
|
||||||
@ -815,5 +822,13 @@
|
|||||||
"website": "https://wellwind.idv.tw/blog/",
|
"website": "https://wellwind.idv.tw/blog/",
|
||||||
"bio": "Mike is a full-stack developer, consultant, blogger, instructor, and conference speaker. He has over 10 years of web development experience and passion to share his knowledge.",
|
"bio": "Mike is a full-stack developer, consultant, blogger, instructor, and conference speaker. He has over 10 years of web development experience and passion to share his knowledge.",
|
||||||
"groups": ["GDE"]
|
"groups": ["GDE"]
|
||||||
|
},
|
||||||
|
"ahasall": {
|
||||||
|
"name": "Amadou Sall",
|
||||||
|
"picture": "ahasall.jpg",
|
||||||
|
"groups": ["GDE"],
|
||||||
|
"twitter": "ahasall",
|
||||||
|
"website": "https://www.amadousall.com",
|
||||||
|
"bio": "Amadou is a Frontend Software Engineer from Senegal based in France. He currently works at Air France where he helps developers build better Angular applications. Passionate about web technologies, Amadou is an international speaker, a technical writer, and a Google Developer Expert in Angular."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
|
|
||||||
<td>Oslo, Norway</td>
|
|
||||||
<td>May 25-26 conference, 27 workshops, 2020</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -31,6 +26,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<!-- ng-vikings 2020 -->
|
||||||
|
<tr>
|
||||||
|
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
|
||||||
|
<td>Oslo, Norway</td>
|
||||||
|
<td>May 25-26 conference, 27 workshops, 2020</td>
|
||||||
|
</tr>
|
||||||
<!-- ng-conf 2020 -->
|
<!-- ng-conf 2020 -->
|
||||||
<tr>
|
<tr>
|
||||||
<th><a href="https://ng-conf.org/" title="ng-conf">ng-conf</a></th>
|
<th><a href="https://ng-conf.org/" title="ng-conf">ng-conf</a></th>
|
||||||
|
@ -506,80 +506,6 @@
|
|||||||
"url": "guide/universal",
|
"url": "guide/universal",
|
||||||
"title": "Server-side Rendering",
|
"title": "Server-side Rendering",
|
||||||
"tooltip": "Render HTML server-side with Angular Universal."
|
"tooltip": "Render HTML server-side with Angular Universal."
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Upgrading from AngularJS",
|
|
||||||
"tooltip": "Incrementally upgrade an AngularJS application to Angular.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/upgrade-setup",
|
|
||||||
"title": "Setup for Upgrading from AngularJS",
|
|
||||||
"tooltip": "Use code from the Angular QuickStart seed as part of upgrading from AngularJS.",
|
|
||||||
"hidden": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/upgrade",
|
|
||||||
"title": "Upgrading Instructions",
|
|
||||||
"tooltip": "Incrementally upgrade an AngularJS application to Angular."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/upgrade-performance",
|
|
||||||
"title": "Upgrading for Performance",
|
|
||||||
"tooltip": "Upgrade from AngularJS to Angular in a more flexible way."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/ajs-quick-reference",
|
|
||||||
"title": "AngularJS-Angular Concepts",
|
|
||||||
"tooltip": "Learn how AngularJS concepts and techniques map to Angular."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Angular Libraries",
|
|
||||||
"tooltip": "Extending Angular with shared libraries.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/libraries",
|
|
||||||
"title": "Libraries Overview",
|
|
||||||
"tooltip": "Understand how and when to use or create libraries."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/using-libraries",
|
|
||||||
"title": "Using Published Libraries",
|
|
||||||
"tooltip": "Integrate published libraries into an app."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/creating-libraries",
|
|
||||||
"title": "Creating Libraries",
|
|
||||||
"tooltip": "Extend Angular by creating, publishing, and using your own libraries."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Schematics",
|
|
||||||
"tooltip": "Using CLI schematics for code generation.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/schematics",
|
|
||||||
"title": "Schematics Overview",
|
|
||||||
"tooltip": "How the CLI uses schematics to generate code."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/schematics-authoring",
|
|
||||||
"title": "Authoring Schematics",
|
|
||||||
"tooltip": "Understand the structure of a schematic."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/schematics-for-libraries",
|
|
||||||
"title": "Schematics for Libraries",
|
|
||||||
"tooltip": "Use schematics to integrate your library with the Angular CLI."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/cli-builder",
|
|
||||||
"title": "CLI Builders",
|
|
||||||
"tooltip": "Using builders to customize Angular CLI."
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -675,6 +601,11 @@
|
|||||||
"url": "guide/browser-support",
|
"url": "guide/browser-support",
|
||||||
"title": "Browser Support",
|
"title": "Browser Support",
|
||||||
"tooltip": "Browser support and polyfills guide."
|
"tooltip": "Browser support and polyfills guide."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/strict-mode",
|
||||||
|
"title": "Strict mode",
|
||||||
|
"tooltip": "Reference documentation for Angular's strict mode."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -700,6 +631,11 @@
|
|||||||
"url": "guide/creating-libraries",
|
"url": "guide/creating-libraries",
|
||||||
"title": "Creating Libraries",
|
"title": "Creating Libraries",
|
||||||
"tooltip": "Extend Angular by creating, publishing, and using your own libraries."
|
"tooltip": "Extend Angular by creating, publishing, and using your own libraries."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/lightweight-injection-tokens",
|
||||||
|
"title": "Lightweight Injection Tokens for Libraries",
|
||||||
|
"tooltip": "Optimize client app size by designing library services with lightweight injection tokens."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -762,13 +698,13 @@
|
|||||||
"tooltip": "Angular versioning, release, support, and deprecation policies and practices."
|
"tooltip": "Angular versioning, release, support, and deprecation policies and practices."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Updating to Version 9",
|
"title": "Updating to Version 10",
|
||||||
"tooltip": "Support for updating your application from version 8 to 9.",
|
"tooltip": "Support for updating your application from version 9 to 10.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"url": "guide/updating-to-version-9",
|
"url": "guide/updating-to-version-10",
|
||||||
"title": "Overview",
|
"title": "Overview",
|
||||||
"tooltip": "Everything you need to know for updating your application from version 8 to 9."
|
"tooltip": "Everything you need to know for updating your application from version 9 to 10."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/ivy-compatibility",
|
"url": "guide/ivy-compatibility",
|
||||||
@ -776,29 +712,9 @@
|
|||||||
"tooltip": "Details to help you make sure your application is compatible with Ivy."
|
"tooltip": "Details to help you make sure your application is compatible with Ivy."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Optional Migrations",
|
"title": "Migrations",
|
||||||
"tooltip": "Optional migration details regarding updating to version 9.",
|
"tooltip": "Migration details regarding updating to version 10.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
|
||||||
"url": "guide/migration-renderer",
|
|
||||||
"title": "Renderer to Renderer2",
|
|
||||||
"tooltip": "Migration from the deprecated Renderer API to the newer Renderer2 API."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/migration-dynamic-flag",
|
|
||||||
"title": "Dynamic Queries Flag",
|
|
||||||
"tooltip": "Migration to remove unnecessary `static: false` flag from @ViewChild and @ContentChild queries."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/migration-injectable",
|
|
||||||
"title": "Missing @Injectable() Decorators",
|
|
||||||
"tooltip": "Migration to add missing @Injectable() decorators and incomplete provider definitions."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/migration-localize",
|
|
||||||
"title": "$localize Global Import",
|
|
||||||
"tooltip": "Migration to add an import statement for @angular/localize to polyfills.ts."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "guide/migration-module-with-providers",
|
"url": "guide/migration-module-with-providers",
|
||||||
"title": "Missing ModuleWithProviders Generic",
|
"title": "Missing ModuleWithProviders Generic",
|
||||||
@ -808,6 +724,26 @@
|
|||||||
"url": "guide/migration-undecorated-classes",
|
"url": "guide/migration-undecorated-classes",
|
||||||
"title": "Missing @Directive() Decorators",
|
"title": "Missing @Directive() Decorators",
|
||||||
"tooltip": "Migration to add missing @Directive()/@Component() decorators."
|
"tooltip": "Migration to add missing @Directive()/@Component() decorators."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/migration-injectable",
|
||||||
|
"title": "Missing @Injectable() Decorators",
|
||||||
|
"tooltip": "Migration to add missing @Injectable() decorators and incomplete provider definitions."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/migration-solution-style-tsconfig",
|
||||||
|
"title": "Solution-style `tsconfig.json`",
|
||||||
|
"tooltip": "Migration to create a solution-style `tsconfig.json`."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/migration-update-libraries-tslib",
|
||||||
|
"title": "`tslib` direct dependency",
|
||||||
|
"tooltip": "Migration to a direct dependency on the `tslib` npm package."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/migration-update-module-and-target-compiler-options",
|
||||||
|
"title": "`module` and `target` compiler options",
|
||||||
|
"tooltip": "Migration to update `module` and `target` compiler options."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1003,6 +939,10 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docVersions": [
|
"docVersions": [
|
||||||
|
{
|
||||||
|
"title": "v9",
|
||||||
|
"url": "https://v9.angular.io/"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "v8",
|
"title": "v8",
|
||||||
"url": "https://v8.angular.io/"
|
"url": "https://v8.angular.io/"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
In this tutorial, you build your own app from the ground up, providing experience with the typical development process, as well as an introduction to basic app-design concepts, tools, and terminology.
|
In this tutorial, you build your own app from the ground up, providing experience with the typical development process, as well as an introduction to basic app-design concepts, tools, and terminology.
|
||||||
|
|
||||||
If you're completely new to Angular, you might want to try the [**Try it now**](start) quick-start app first.
|
If you're completely new to Angular, you might want to try the [**Try it now**](start) quick-start app first.
|
||||||
It is based on a ready-made partially-completed project, which you can examine and modify in the StacBlitz interactive development environment, where you can see the results in real time.
|
It is based on a ready-made partially-completed project, which you can examine and modify in the StackBlitz interactive development environment, where you can see the results in real time.
|
||||||
|
|
||||||
The "Try it" tutorial covers the same major topics—components, template syntax, routing, services, and accessing data via HTTP—in a condensed format, following the most current best practices.
|
The "Try it" tutorial covers the same major topics—components, template syntax, routing, services, and accessing data via HTTP—in a condensed format, following the most current best practices.
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"hosting": {
|
"hosting": {
|
||||||
|
"target": "aio",
|
||||||
"public": "dist",
|
"public": "dist",
|
||||||
"cleanUrls": true,
|
"cleanUrls": true,
|
||||||
"redirects": [
|
"redirects": [
|
||||||
@ -127,7 +128,7 @@
|
|||||||
// The below paths are referenced in users projects generated by the CLI
|
// The below paths are referenced in users projects generated by the CLI
|
||||||
{"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"},
|
{"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"},
|
||||||
{"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"},
|
{"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"},
|
||||||
{"type": 301, "source": "/config/app-package-json", "destination": "https://webpack.js.org/configuration/optimization/#optimizationsideeffects"}
|
{"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"}
|
||||||
],
|
],
|
||||||
"rewrites": [
|
"rewrites": [
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"build-local-with-viewengine": "yarn ~~build",
|
"build-local-with-viewengine": "yarn ~~build",
|
||||||
"prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci",
|
"prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci",
|
||||||
"build-local-with-viewengine-ci": "yarn ~~build --progress=false",
|
"build-local-with-viewengine-ci": "yarn ~~build --progress=false",
|
||||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 14af4e07c",
|
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js b76099083",
|
||||||
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
||||||
"test": "yarn check-env && ng test",
|
"test": "yarn check-env && ng test",
|
||||||
"pree2e": "yarn check-env && yarn update-webdriver",
|
"pree2e": "yarn check-env && yarn update-webdriver",
|
||||||
@ -123,7 +123,7 @@
|
|||||||
"cross-spawn": "^5.1.0",
|
"cross-spawn": "^5.1.0",
|
||||||
"css-selector-parser": "^1.3.0",
|
"css-selector-parser": "^1.3.0",
|
||||||
"dgeni": "^0.4.11",
|
"dgeni": "^0.4.11",
|
||||||
"dgeni-packages": "^0.28.3",
|
"dgeni-packages": "^0.28.4",
|
||||||
"entities": "^1.1.1",
|
"entities": "^1.1.1",
|
||||||
"eslint": "^3.19.0",
|
"eslint": "^3.19.0",
|
||||||
"eslint-plugin-jasmine": "^2.2.0",
|
"eslint-plugin-jasmine": "^2.2.0",
|
||||||
|
@ -33,7 +33,7 @@ else
|
|||||||
readonly majorVersionStable=${CI_STABLE_BRANCH%%.*}
|
readonly majorVersionStable=${CI_STABLE_BRANCH%%.*}
|
||||||
|
|
||||||
# Do not deploy if the major version is not less than the stable branch major version
|
# Do not deploy if the major version is not less than the stable branch major version
|
||||||
if [[ !( "$majorVersion" -lt "$majorVersionStable" ) ]]; then
|
if (( $majorVersion >= $majorVersionStable )); then
|
||||||
echo "Skipping deploy of branch \"$CI_BRANCH\" to firebase."
|
echo "Skipping deploy of branch \"$CI_BRANCH\" to firebase."
|
||||||
echo "We only deploy archive branches with the major version less than the stable branch: \"$CI_STABLE_BRANCH\""
|
echo "We only deploy archive branches with the major version less than the stable branch: \"$CI_STABLE_BRANCH\""
|
||||||
exit 0
|
exit 0
|
||||||
@ -64,16 +64,27 @@ fi
|
|||||||
case $deployEnv in
|
case $deployEnv in
|
||||||
next)
|
next)
|
||||||
readonly projectId=aio-staging
|
readonly projectId=aio-staging
|
||||||
|
readonly siteId=$projectId
|
||||||
readonly deployedUrl=https://next.angular.io/
|
readonly deployedUrl=https://next.angular.io/
|
||||||
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
||||||
;;
|
;;
|
||||||
stable)
|
stable)
|
||||||
readonly projectId=angular-io
|
readonly projectId=angular-io
|
||||||
|
readonly siteId=$projectId
|
||||||
readonly deployedUrl=https://angular.io/
|
readonly deployedUrl=https://angular.io/
|
||||||
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
||||||
;;
|
;;
|
||||||
archive)
|
archive)
|
||||||
readonly projectId=v${majorVersion}-angular-io
|
# Special case v9-angular-io because its piloting the firebase hosting "multisites" setup
|
||||||
|
# See https://angular-team.atlassian.net/browse/DEV-125 for more info.
|
||||||
|
if [[ "$majorVersion" == "9" ]]; then
|
||||||
|
readonly projectId=aio-staging
|
||||||
|
readonly siteId=v9-angular-io
|
||||||
|
else
|
||||||
|
readonly projectId=v${majorVersion}-angular-io
|
||||||
|
readonly siteId=$projectId
|
||||||
|
fi
|
||||||
|
|
||||||
readonly deployedUrl=https://v${majorVersion}.angular.io/
|
readonly deployedUrl=https://v${majorVersion}.angular.io/
|
||||||
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
readonly firebaseToken=$CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN
|
||||||
;;
|
;;
|
||||||
@ -82,6 +93,7 @@ esac
|
|||||||
echo "Git branch : $CI_BRANCH"
|
echo "Git branch : $CI_BRANCH"
|
||||||
echo "Build/deploy mode : $deployEnv"
|
echo "Build/deploy mode : $deployEnv"
|
||||||
echo "Firebase project : $projectId"
|
echo "Firebase project : $projectId"
|
||||||
|
echo "Firebase site : $siteId"
|
||||||
echo "Deployment URL : $deployedUrl"
|
echo "Deployment URL : $deployedUrl"
|
||||||
|
|
||||||
if [[ ${1:-} == "--dry-run" ]]; then
|
if [[ ${1:-} == "--dry-run" ]]; then
|
||||||
@ -92,23 +104,29 @@ fi
|
|||||||
(
|
(
|
||||||
cd "`dirname $0`/.."
|
cd "`dirname $0`/.."
|
||||||
|
|
||||||
# Build the app
|
echo "\n\n\n==== Build the aio app ====\n"
|
||||||
yarn build --configuration=$deployEnv --progress=false
|
yarn build --configuration=$deployEnv --progress=false
|
||||||
|
|
||||||
# Include any mode-specific files
|
|
||||||
|
echo "\n\n\n==== Add any mode-specific files into the aio distribution ====\n"
|
||||||
cp -rf src/extra-files/$deployEnv/. dist/
|
cp -rf src/extra-files/$deployEnv/. dist/
|
||||||
|
|
||||||
# Set deployedUrl as parameter in the opensearch description
|
|
||||||
|
echo "\n\n\n==== Update opensearch descriptor for aio with the deployedUrl ====\n"
|
||||||
# deployedUrl must end with /
|
# deployedUrl must end with /
|
||||||
yarn set-opensearch-url $deployedUrl
|
yarn set-opensearch-url $deployedUrl
|
||||||
|
|
||||||
# Check payload size
|
echo "\n\n\n==== Check payload size and upload the numbers to firebase db ====\n"
|
||||||
yarn payload-size
|
yarn payload-size
|
||||||
|
|
||||||
# Deploy to Firebase
|
|
||||||
yarn firebase use "$projectId" --token "$firebaseToken"
|
|
||||||
yarn firebase deploy --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
|
|
||||||
|
|
||||||
# Run PWA-score tests
|
echo "\n\n\n==== Deploy aio to firebase hosting ====\n"
|
||||||
|
|
||||||
|
yarn firebase use "${projectId}" --token "$firebaseToken"
|
||||||
|
yarn firebase target:apply hosting aio $siteId --token "$firebaseToken"
|
||||||
|
yarn firebase deploy --only hosting:aio --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
|
||||||
|
|
||||||
|
|
||||||
|
echo "\n\n\n==== Run PWA-score tests ====\n"
|
||||||
yarn test-pwa-score "$deployedUrl" "$CI_AIO_MIN_PWA_SCORE"
|
yarn test-pwa-score "$deployedUrl" "$CI_AIO_MIN_PWA_SCORE"
|
||||||
)
|
)
|
||||||
|
@ -68,6 +68,7 @@ function check {
|
|||||||
expected="Git branch : master
|
expected="Git branch : master
|
||||||
Build/deploy mode : next
|
Build/deploy mode : next
|
||||||
Firebase project : aio-staging
|
Firebase project : aio-staging
|
||||||
|
Firebase site : aio-staging
|
||||||
Deployment URL : https://next.angular.io/"
|
Deployment URL : https://next.angular.io/"
|
||||||
check "$actual" "$expected"
|
check "$actual" "$expected"
|
||||||
)
|
)
|
||||||
@ -103,6 +104,7 @@ Deployment URL : https://next.angular.io/"
|
|||||||
expected="Git branch : 4.3.x
|
expected="Git branch : 4.3.x
|
||||||
Build/deploy mode : stable
|
Build/deploy mode : stable
|
||||||
Firebase project : angular-io
|
Firebase project : angular-io
|
||||||
|
Firebase site : angular-io
|
||||||
Deployment URL : https://angular.io/"
|
Deployment URL : https://angular.io/"
|
||||||
check "$actual" "$expected"
|
check "$actual" "$expected"
|
||||||
)
|
)
|
||||||
@ -139,10 +141,37 @@ Deployment URL : https://angular.io/"
|
|||||||
expected="Git branch : 2.4.x
|
expected="Git branch : 2.4.x
|
||||||
Build/deploy mode : archive
|
Build/deploy mode : archive
|
||||||
Firebase project : v2-angular-io
|
Firebase project : v2-angular-io
|
||||||
|
Firebase site : v2-angular-io
|
||||||
Deployment URL : https://v2.angular.io/"
|
Deployment URL : https://v2.angular.io/"
|
||||||
check "$actual" "$expected"
|
check "$actual" "$expected"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
echo ===== archive - v9-angular-io multisite special case - deploy success
|
||||||
|
actual=$(
|
||||||
|
export BASH_ENV=/dev/null
|
||||||
|
export CI_REPO_OWNER=angular
|
||||||
|
export CI_REPO_NAME=angular
|
||||||
|
export CI_PULL_REQUEST=false
|
||||||
|
export CI_BRANCH=9.1.x
|
||||||
|
export CI_STABLE_BRANCH=10.0.x
|
||||||
|
export CI_COMMIT=$(git ls-remote origin 9.1.x | cut -c1-40)
|
||||||
|
export CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN=XXXXX
|
||||||
|
$deployToFirebaseDryRun
|
||||||
|
)
|
||||||
|
expected="Git branch : 9.1.x
|
||||||
|
Build/deploy mode : archive
|
||||||
|
Firebase project : aio-staging
|
||||||
|
Firebase site : v9-angular-io
|
||||||
|
Deployment URL : https://v9.angular.io/"
|
||||||
|
# TODO: This test incorrectly expects the Firebase project to be v9-angular-io.
|
||||||
|
# v9-angular-io is a "multisites" project currently within the aio-staging project
|
||||||
|
# This setup is temporary and was created in order to deploy v9.angular.io without
|
||||||
|
# disruptions.
|
||||||
|
# See https://angular-team.atlassian.net/browse/DEV-125 for more info.
|
||||||
|
check "$actual" "$expected"
|
||||||
|
)
|
||||||
|
|
||||||
(
|
(
|
||||||
echo ===== archive - skip deploy - commit not HEAD
|
echo ===== archive - skip deploy - commit not HEAD
|
||||||
actual=$(
|
actual=$(
|
||||||
|
24
aio/scripts/prepare-size-debug-artifacts.js
Normal file
24
aio/scripts/prepare-size-debug-artifacts.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const {cp, ls, mkdir, set} = require('shelljs');
|
||||||
|
const {join, resolve} = require('path');
|
||||||
|
set('-e');
|
||||||
|
|
||||||
|
// Read input arguments.
|
||||||
|
const [sizesTarget, artifactsRelativeDir] = process.argv.slice(2);
|
||||||
|
|
||||||
|
// Compute paths.
|
||||||
|
const projectDir = resolve(__dirname, '../..');
|
||||||
|
const sizesFilePath = join(projectDir, 'goldens/size-tracking/aio-payloads.json');
|
||||||
|
const distDir = join(projectDir, 'aio/dist');
|
||||||
|
const artifactsDir = resolve(projectDir, artifactsRelativeDir);
|
||||||
|
|
||||||
|
// Determine which files need to be copied.
|
||||||
|
const fileNamePrefixes = Object.keys(require(sizesFilePath)[sizesTarget].master.uncompressed);
|
||||||
|
const filesToCopyRe = new RegExp(`^(?:${fileNamePrefixes.join('|')})\\..+\\.js$`);
|
||||||
|
const filesToCopy = ls(distDir)
|
||||||
|
.filter(file => filesToCopyRe.test(file))
|
||||||
|
.map(file => join(distDir, file));
|
||||||
|
|
||||||
|
// Copy files to the specified directory.
|
||||||
|
mkdir('-p', artifactsDir);
|
||||||
|
cp(filesToCopy, artifactsDir);
|
@ -5,20 +5,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-toolbar color="primary" class="app-toolbar no-print" [class.transitioning]="isTransitioning">
|
<mat-toolbar color="primary" class="app-toolbar no-print" [class.transitioning]="isTransitioning">
|
||||||
<mat-toolbar-row class="notification-container blm-message">
|
<mat-toolbar-row class="notification-container">
|
||||||
<aio-notification notificationId="blm-2020" expirationDate="2022-04-15" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
|
<aio-notification notificationId="survey-march-2020" expirationDate="2020-04-15" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
|
||||||
#BlackLivesMatter
|
<a href="https://goo.gle/angular-survey-2020">
|
||||||
|
<mat-icon class="icon" svgIcon="insert_comment" aria-label="Announcement"></mat-icon>
|
||||||
|
<span class="message">Help Angular by taking a <b>1 minute survey</b>!</span>
|
||||||
|
<span class="action-button">Go to survey</span>
|
||||||
|
</a>
|
||||||
</aio-notification>
|
</aio-notification>
|
||||||
</mat-toolbar-row>
|
</mat-toolbar-row>
|
||||||
<mat-toolbar-row>
|
<mat-toolbar-row>
|
||||||
<button mat-button class="hamburger" [class.starting]="isStarting" (click)="sidenav.toggle()" title="Docs menu">
|
<button mat-button class="hamburger" [class.starting]="isStarting" (click)="sidenav.toggle()" title="Docs menu">
|
||||||
<mat-icon svgIcon="menu"></mat-icon>
|
<mat-icon svgIcon="menu"></mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<a class="nav-link home" href="/" [ngSwitch]="isSideBySide">
|
<a class="nav-link home" href="/" [ngSwitch]="showTopMenu">
|
||||||
<img *ngSwitchCase="true" src="assets/images/logos/angular/logo-nav@2x.png" width="150" height="40" title="Home" alt="Home">
|
<img *ngSwitchCase="true" src="assets/images/logos/angular/logo-nav@2x.png" width="150" height="40" title="Home" alt="Home">
|
||||||
<img *ngSwitchDefault src="assets/images/logos/angular/shield-large.svg" width="37" height="40" title="Home" alt="Home">
|
<img *ngSwitchDefault src="assets/images/logos/angular/shield-large.svg" width="37" height="40" title="Home" alt="Home">
|
||||||
</a>
|
</a>
|
||||||
<aio-top-menu *ngIf="isSideBySide" [nodes]="topMenuNodes" [currentNode]="currentNodes?.TopBar"></aio-top-menu>
|
<aio-top-menu *ngIf="showTopMenu" [nodes]="topMenuNodes" [currentNode]="currentNodes?.TopBar"></aio-top-menu>
|
||||||
<aio-search-box class="search-container" #searchBox (onSearch)="doSearch($event)" (onFocus)="doSearch($event)"></aio-search-box>
|
<aio-search-box class="search-container" #searchBox (onSearch)="doSearch($event)" (onFocus)="doSearch($event)"></aio-search-box>
|
||||||
<div class="toolbar-external-icons-container">
|
<div class="toolbar-external-icons-container">
|
||||||
<a href="https://twitter.com/angular" title="Twitter" aria-label="Angular on twitter">
|
<a href="https://twitter.com/angular" title="Twitter" aria-label="Angular on twitter">
|
||||||
@ -35,9 +39,9 @@
|
|||||||
|
|
||||||
<mat-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
|
<mat-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
|
||||||
|
|
||||||
<mat-sidenav [ngClass]="{'collapsed': !isSideBySide}" #sidenav class="sidenav" [mode]="mode" [opened]="isOpened" (openedChange)="updateHostClasses()">
|
<mat-sidenav [ngClass]="{'collapsed': !dockSideNav}" #sidenav class="sidenav" [mode]="mode" [opened]="isOpened" (openedChange)="updateHostClasses()">
|
||||||
<aio-nav-menu *ngIf="!isSideBySide" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
|
<aio-nav-menu *ngIf="!showTopMenu" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
|
||||||
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="isSideBySide"></aio-nav-menu>
|
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="dockSideNav"></aio-nav-menu>
|
||||||
|
|
||||||
<div class="doc-version">
|
<div class="doc-version">
|
||||||
<aio-select (change)="onDocVersionChange($event.index)" [options]="docVersions" [selected]="currentDocVersion"></aio-select>
|
<aio-select (change)="onDocVersionChange($event.index)" [options]="docVersions" [selected]="currentDocVersion"></aio-select>
|
||||||
|
@ -25,11 +25,9 @@ import { first, mapTo } from 'rxjs/operators';
|
|||||||
import { MockLocationService } from 'testing/location.service';
|
import { MockLocationService } from 'testing/location.service';
|
||||||
import { MockLogger } from 'testing/logger.service';
|
import { MockLogger } from 'testing/logger.service';
|
||||||
import { MockSearchService } from 'testing/search.service';
|
import { MockSearchService } from 'testing/search.service';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent, dockSideNavWidth, showFloatingTocWidth, showTopMenuWidth } from './app.component';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
const sideBySideBreakPoint = 992;
|
|
||||||
const hideToCBreakPoint = 800;
|
|
||||||
const startedDelay = 100;
|
const startedDelay = 100;
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
@ -58,7 +56,7 @@ describe('AppComponent', () => {
|
|||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.onResize(sideBySideBreakPoint + 1); // wide by default
|
component.onResize(showTopMenuWidth + 1); // wide by default
|
||||||
|
|
||||||
const de = fixture.debugElement;
|
const de = fixture.debugElement;
|
||||||
const docViewerDe = de.query(By.css('aio-doc-viewer'));
|
const docViewerDe = de.query(By.css('aio-doc-viewer'));
|
||||||
@ -99,7 +97,7 @@ describe('AppComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be false on narrow screens', () => {
|
it('should be false on narrow screens', () => {
|
||||||
component.onResize(hideToCBreakPoint - 1);
|
component.onResize(showFloatingTocWidth - 1);
|
||||||
|
|
||||||
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
expect(component.hasFloatingToc).toBe(false);
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
@ -112,7 +110,7 @@ describe('AppComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be true on wide screens unless the toc is empty', () => {
|
it('should be true on wide screens unless the toc is empty', () => {
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
component.onResize(showFloatingTocWidth + 1);
|
||||||
|
|
||||||
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
expect(component.hasFloatingToc).toBe(true);
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
@ -127,37 +125,47 @@ describe('AppComponent', () => {
|
|||||||
it('should be false when toc is empty', () => {
|
it('should be false when toc is empty', () => {
|
||||||
tocService.tocList.next([]);
|
tocService.tocList.next([]);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
component.onResize(showFloatingTocWidth + 1);
|
||||||
expect(component.hasFloatingToc).toBe(false);
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint - 1);
|
component.onResize(showFloatingTocWidth - 1);
|
||||||
expect(component.hasFloatingToc).toBe(false);
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
component.onResize(showFloatingTocWidth + 1);
|
||||||
expect(component.hasFloatingToc).toBe(false);
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be true when toc is not empty unless the screen is narrow', () => {
|
it('should be true when toc is not empty unless the screen is narrow', () => {
|
||||||
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
component.onResize(showFloatingTocWidth + 1);
|
||||||
expect(component.hasFloatingToc).toBe(true);
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint - 1);
|
component.onResize(showFloatingTocWidth - 1);
|
||||||
expect(component.hasFloatingToc).toBe(false);
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
component.onResize(showFloatingTocWidth + 1);
|
||||||
expect(component.hasFloatingToc).toBe(true);
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isSideBySide', () => {
|
describe('showTopMenu', () => {
|
||||||
it('should be updated on resize', () => {
|
it('should be updated on resize', () => {
|
||||||
component.onResize(sideBySideBreakPoint - 1);
|
component.onResize(showTopMenuWidth - 1);
|
||||||
expect(component.isSideBySide).toBe(false);
|
expect(component.showTopMenu).toBe(false);
|
||||||
|
|
||||||
component.onResize(sideBySideBreakPoint + 1);
|
component.onResize(showTopMenuWidth + 1);
|
||||||
expect(component.isSideBySide).toBe(true);
|
expect(component.showTopMenu).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('dockSideNav', () => {
|
||||||
|
it('should be updated on resize', () => {
|
||||||
|
component.onResize(dockSideNavWidth - 1);
|
||||||
|
expect(component.dockSideNav).toBe(false);
|
||||||
|
|
||||||
|
component.onResize(dockSideNavWidth + 1);
|
||||||
|
expect(component.dockSideNav).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -185,8 +193,8 @@ describe('AppComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('when side-by-side (wide)', () => {
|
describe('when view is wide', () => {
|
||||||
beforeEach(() => resizeTo(sideBySideBreakPoint + 1)); // side-by-side
|
beforeEach(() => resizeTo(dockSideNavWidth + 1)); // wide view
|
||||||
|
|
||||||
it('should open when navigating to a guide page (guide/pipes)', () => {
|
it('should open when navigating to a guide page (guide/pipes)', () => {
|
||||||
navigateTo('guide/pipes');
|
navigateTo('guide/pipes');
|
||||||
@ -232,8 +240,8 @@ describe('AppComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when NOT side-by-side (narrow)', () => {
|
describe('when view is narrow', () => {
|
||||||
beforeEach(() => resizeTo(sideBySideBreakPoint - 1)); // NOT side-by-side
|
beforeEach(() => resizeTo(dockSideNavWidth - 1)); // narrow view
|
||||||
|
|
||||||
it('should be closed when navigating to a guide page (guide/pipes)', () => {
|
it('should be closed when navigating to a guide page (guide/pipes)', () => {
|
||||||
navigateTo('guide/pipes');
|
navigateTo('guide/pipes');
|
||||||
@ -286,30 +294,30 @@ describe('AppComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when changing side-by-side (narrow --> wide)', () => {
|
describe('when changing from narrow to wide view', () => {
|
||||||
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
|
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
|
||||||
const nonSidenavDocs = ['features', 'about'];
|
const nonSidenavDocs = ['features', 'about'];
|
||||||
|
|
||||||
sidenavDocs.forEach(doc => {
|
sidenavDocs.forEach(doc => {
|
||||||
it(`should open when on a sidenav doc (${doc})`, () => {
|
it(`should open when on a sidenav doc (${doc})`, () => {
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
|
|
||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint + 1);
|
resizeTo(dockSideNavWidth + 1);
|
||||||
expect(sidenav.opened).toBe(true);
|
expect(sidenav.opened).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
nonSidenavDocs.forEach(doc => {
|
nonSidenavDocs.forEach(doc => {
|
||||||
it(`should remain closed when on a non-sidenav doc (${doc})`, () => {
|
it(`should remain closed when on a non-sidenav doc (${doc})`, () => {
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
|
|
||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint + 1);
|
resizeTo(dockSideNavWidth + 1);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -317,33 +325,33 @@ describe('AppComponent', () => {
|
|||||||
describe('when manually opened', () => {
|
describe('when manually opened', () => {
|
||||||
sidenavDocs.forEach(doc => {
|
sidenavDocs.forEach(doc => {
|
||||||
it(`should remain opened when on a sidenav doc (${doc})`, () => {
|
it(`should remain opened when on a sidenav doc (${doc})`, () => {
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
|
|
||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
toggleSidenav();
|
toggleSidenav();
|
||||||
expect(sidenav.opened).toBe(true);
|
expect(sidenav.opened).toBe(true);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint + 1);
|
resizeTo(dockSideNavWidth + 1);
|
||||||
expect(sidenav.opened).toBe(true);
|
expect(sidenav.opened).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
nonSidenavDocs.forEach(doc => {
|
nonSidenavDocs.forEach(doc => {
|
||||||
it(`should close when on a non-sidenav doc (${doc})`, () => {
|
it(`should close when on a non-sidenav doc (${doc})`, () => {
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
|
|
||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
toggleSidenav();
|
toggleSidenav();
|
||||||
expect(sidenav.opened).toBe(true);
|
expect(sidenav.opened).toBe(true);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint + 1);
|
resizeTo(showTopMenuWidth + 1);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when changing side-by-side (wide --> narrow)', () => {
|
describe('when changing from wide to narrow view', () => {
|
||||||
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
|
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
|
||||||
const nonSidenavDocs = ['features', 'about'];
|
const nonSidenavDocs = ['features', 'about'];
|
||||||
|
|
||||||
@ -352,7 +360,7 @@ describe('AppComponent', () => {
|
|||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
expect(sidenav.opened).toBe(true);
|
expect(sidenav.opened).toBe(true);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -362,7 +370,7 @@ describe('AppComponent', () => {
|
|||||||
navigateTo(doc);
|
navigateTo(doc);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
|
|
||||||
resizeTo(sideBySideBreakPoint - 1);
|
resizeTo(dockSideNavWidth - 1);
|
||||||
expect(sidenav.opened).toBe(false);
|
expect(sidenav.opened).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -376,7 +384,7 @@ describe('AppComponent', () => {
|
|||||||
async function setupSelectorForTesting(mode?: string) {
|
async function setupSelectorForTesting(mode?: string) {
|
||||||
createTestingModule('a/b', mode);
|
createTestingModule('a/b', mode);
|
||||||
await initializeTest();
|
await initializeTest();
|
||||||
component.onResize(sideBySideBreakPoint + 1); // side-by-side
|
component.onResize(dockSideNavWidth + 1); // wide view
|
||||||
selectElement = fixture.debugElement.query(By.directive(SelectComponent));
|
selectElement = fixture.debugElement.query(By.directive(SelectComponent));
|
||||||
selectComponent = selectElement.componentInstance;
|
selectComponent = selectElement.componentInstance;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,9 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
|||||||
import { first, map } from 'rxjs/operators';
|
import { first, map } from 'rxjs/operators';
|
||||||
|
|
||||||
const sideNavView = 'SideNav';
|
const sideNavView = 'SideNav';
|
||||||
|
export const showTopMenuWidth = 1048;
|
||||||
|
export const dockSideNavWidth = 992;
|
||||||
|
export const showFloatingTocWidth = 800;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'aio-shell',
|
selector: 'aio-shell',
|
||||||
@ -57,18 +60,17 @@ export class AppComponent implements OnInit {
|
|||||||
isStarting = true;
|
isStarting = true;
|
||||||
isTransitioning = true;
|
isTransitioning = true;
|
||||||
isFetching = false;
|
isFetching = false;
|
||||||
isSideBySide = false;
|
showTopMenu = false;
|
||||||
|
dockSideNav = false;
|
||||||
private isFetchingTimeout: any;
|
private isFetchingTimeout: any;
|
||||||
private isSideNavDoc = false;
|
private isSideNavDoc = false;
|
||||||
|
|
||||||
private sideBySideWidth = 992;
|
|
||||||
sideNavNodes: NavigationNode[];
|
sideNavNodes: NavigationNode[];
|
||||||
topMenuNodes: NavigationNode[];
|
topMenuNodes: NavigationNode[];
|
||||||
topMenuNarrowNodes: NavigationNode[];
|
topMenuNarrowNodes: NavigationNode[];
|
||||||
|
|
||||||
hasFloatingToc = false;
|
hasFloatingToc = false;
|
||||||
private showFloatingToc = new BehaviorSubject(false);
|
private showFloatingToc = new BehaviorSubject(false);
|
||||||
private showFloatingTocWidth = 800;
|
|
||||||
tocMaxHeight: string;
|
tocMaxHeight: string;
|
||||||
private tocMaxHeightOffset = 0;
|
private tocMaxHeightOffset = 0;
|
||||||
|
|
||||||
@ -76,8 +78,8 @@ export class AppComponent implements OnInit {
|
|||||||
|
|
||||||
private currentUrl: string;
|
private currentUrl: string;
|
||||||
|
|
||||||
get isOpened() { return this.isSideBySide && this.isSideNavDoc; }
|
get isOpened() { return this.dockSideNav && this.isSideNavDoc; }
|
||||||
get mode() { return this.isSideBySide ? 'side' : 'over'; }
|
get mode() { return this.dockSideNav && (this.isSideNavDoc || this.showTopMenu) ? 'side' : 'over'; }
|
||||||
|
|
||||||
// Search related properties
|
// Search related properties
|
||||||
showSearchResults = false;
|
showSearchResults = false;
|
||||||
@ -239,13 +241,14 @@ export class AppComponent implements OnInit {
|
|||||||
|
|
||||||
@HostListener('window:resize', ['$event.target.innerWidth'])
|
@HostListener('window:resize', ['$event.target.innerWidth'])
|
||||||
onResize(width: number) {
|
onResize(width: number) {
|
||||||
this.isSideBySide = width >= this.sideBySideWidth;
|
this.showTopMenu = width >= showTopMenuWidth;
|
||||||
this.showFloatingToc.next(width > this.showFloatingTocWidth);
|
this.dockSideNav = width >= dockSideNavWidth;
|
||||||
|
this.showFloatingToc.next(width > showFloatingTocWidth);
|
||||||
|
|
||||||
if (this.isSideBySide && !this.isSideNavDoc) {
|
if (this.showTopMenu && !this.isSideNavDoc) {
|
||||||
// If this is a non-sidenav doc and the screen is wide enough so that we can display menu
|
// If this is a non-sidenav doc and the screen is wide enough so that we can display menu
|
||||||
// items in the top-bar, ensure the sidenav is closed.
|
// items in the top-bar, ensure the sidenav is closed.
|
||||||
// (This condition can only be met when the resize event changes the value of `isSideBySide`
|
// (This condition can only be met when the resize event changes the value of `showTopMenu`
|
||||||
// from `false` to `true` while on a non-sidenav doc.)
|
// from `false` to `true` while on a non-sidenav doc.)
|
||||||
this.sidenav.toggle(false);
|
this.sidenav.toggle(false);
|
||||||
}
|
}
|
||||||
@ -338,7 +341,7 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// May be open or closed when wide; always closed when narrow.
|
// May be open or closed when wide; always closed when narrow.
|
||||||
this.sidenav.toggle(this.isSideBySide && openSideNav);
|
this.sidenav.toggle(this.dockSideNav && openSideNav);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically change height of table of contents container
|
// Dynamically change height of table of contents container
|
||||||
|
@ -401,7 +401,10 @@ describe('DocViewerComponent', () => {
|
|||||||
expect(loadElementsSpy.calls.argsFor(1)).toEqual([docViewer.nextViewContainer]);
|
expect(loadElementsSpy.calls.argsFor(1)).toEqual([docViewer.nextViewContainer]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should unsubscribe from the previous "embed" observable when unsubscribed from', () => {
|
// This test sometimes incorrectly fails on CI.
|
||||||
|
// Reported in https://github.com/angular/angular/issues/37629.
|
||||||
|
// Investigated in https://github.com/angular/angular/pull/37637.
|
||||||
|
xit('should unsubscribe from the previous "embed" observable when unsubscribed from', () => {
|
||||||
const obs = new ObservableWithSubscriptionSpies();
|
const obs = new ObservableWithSubscriptionSpies();
|
||||||
loadElementsSpy.and.returnValue(obs);
|
loadElementsSpy.and.returnValue(obs);
|
||||||
|
|
||||||
@ -436,7 +439,10 @@ describe('DocViewerComponent', () => {
|
|||||||
expect(swapViewsSpy).toHaveBeenCalledWith(addTitleAndTocSpy);
|
expect(swapViewsSpy).toHaveBeenCalledWith(addTitleAndTocSpy);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should unsubscribe from the previous "swap" observable when unsubscribed from', () => {
|
// This test sometimes incorrectly fails on CI.
|
||||||
|
// Reported in https://github.com/angular/angular/issues/37629.
|
||||||
|
// Investigated in https://github.com/angular/angular/pull/37637.
|
||||||
|
xit('should unsubscribe from the previous "swap" observable when unsubscribed from', () => {
|
||||||
const obs = new ObservableWithSubscriptionSpies();
|
const obs = new ObservableWithSubscriptionSpies();
|
||||||
swapViewsSpy.and.returnValue(obs);
|
swapViewsSpy.and.returnValue(obs);
|
||||||
|
|
||||||
|
@ -8,6 +8,11 @@
|
|||||||
Join the community of millions of developers who build compelling user interfaces with Angular.">
|
Join the community of millions of developers who build compelling user interfaces with Angular.">
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://www.google-analytics.com">
|
||||||
|
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||||
|
<link rel="preconnect" href="https://stats.g.doubleclick.net">
|
||||||
|
<link rel="dns-prefetch" href="https://stats.g.doubleclick.net">
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<link rel="search" type="application/opensearchdescription+xml" href="assets/opensearch.xml">
|
<link rel="search" type="application/opensearchdescription+xml" href="assets/opensearch.xml">
|
||||||
|
@ -183,8 +183,8 @@ section#intro {
|
|||||||
|
|
||||||
// ANGULAR LINE
|
// ANGULAR LINE
|
||||||
.background-sky {
|
.background-sky {
|
||||||
background-color: $black;
|
background-color: $blue;
|
||||||
background: $black;
|
background: $bluegradient;
|
||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
// VARIABLES
|
// VARIABLES
|
||||||
|
$showTopMenuWidth: 1048px;
|
||||||
|
$hideTopMenuWidth: $showTopMenuWidth - 1;
|
||||||
$hamburgerShownMargin: 0 8px 0 0;
|
$hamburgerShownMargin: 0 8px 0 0;
|
||||||
$hamburgerHiddenMargin: 0 16px 0 -64px;
|
$hamburgerHiddenMargin: 0 16px 0 -64px;
|
||||||
|
|
||||||
@ -20,16 +22,9 @@ mat-toolbar.mat-toolbar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.blm-message {
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: #2d2d2d;
|
|
||||||
font-size: 0.75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HOME PAGE OVERRIDE: TOPNAV TOOLBAR
|
// HOME PAGE OVERRIDE: TOPNAV TOOLBAR
|
||||||
aio-shell.page-home mat-toolbar.mat-toolbar {
|
aio-shell.page-home mat-toolbar.mat-toolbar {
|
||||||
background-color: $black;
|
background-color: $blue;
|
||||||
|
|
||||||
@media (min-width: 481px) {
|
@media (min-width: 481px) {
|
||||||
&:not(.transitioning) {
|
&:not(.transitioning) {
|
||||||
@ -59,9 +54,9 @@ aio-shell.folder-docs mat-toolbar.mat-toolbar,
|
|||||||
aio-shell.folder-guide mat-toolbar.mat-toolbar,
|
aio-shell.folder-guide mat-toolbar.mat-toolbar,
|
||||||
aio-shell.folder-start mat-toolbar.mat-toolbar,
|
aio-shell.folder-start mat-toolbar.mat-toolbar,
|
||||||
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
||||||
@media (min-width: 992px) {
|
@media (min-width: $showTopMenuWidth) {
|
||||||
.hamburger.mat-button {
|
.hamburger.mat-button {
|
||||||
// Hamburger shown on non-marketing pages on large screens.
|
// Hamburger shown on non-marketing pages even on large screens.
|
||||||
margin: $hamburgerShownMargin;
|
margin: $hamburgerShownMargin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +68,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
|||||||
margin: $hamburgerShownMargin;
|
margin: $hamburgerShownMargin;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: $showTopMenuWidth) {
|
||||||
// Hamburger hidden by default on large screens.
|
// Hamburger hidden by default on large screens.
|
||||||
// (Will be shown per doc.)
|
// (Will be shown per doc.)
|
||||||
margin: $hamburgerHiddenMargin;
|
margin: $hamburgerHiddenMargin;
|
||||||
@ -111,7 +106,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
|||||||
outline-offset: 4px;
|
outline-offset: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 991px) {
|
@media screen and (max-width: $hideTopMenuWidth) {
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +120,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
|||||||
top: 12px;
|
top: 12px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
||||||
@media (max-width: 991px) {
|
@media (max-width: $hideTopMenuWidth) {
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
@ -237,6 +232,7 @@ aio-search-box.search-container {
|
|||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
52
aio/tests/e2e/src/api-list.e2e-spec.ts
Normal file
52
aio/tests/e2e/src/api-list.e2e-spec.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { by, element } from 'protractor';
|
||||||
|
import { SitePage } from './app.po';
|
||||||
|
|
||||||
|
describe('api-list', () => {
|
||||||
|
const apiSearchInput = element(by.css('aio-api-list .form-search input'));
|
||||||
|
const apiStatusDropdown = element(by.css('aio-api-list aio-select[label="Status:"]'));
|
||||||
|
const apiTypeDropdown = element(by.css('aio-api-list aio-select[label="Type:"]'));
|
||||||
|
let page: SitePage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new SitePage();
|
||||||
|
page.navigateTo('api');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find AnimationSequenceMetadata when searching by partial word anima', () => {
|
||||||
|
expect(page.getApiSearchResults()).toContain('HttpEventType');
|
||||||
|
|
||||||
|
apiSearchInput.clear();
|
||||||
|
apiSearchInput.sendKeys('anima');
|
||||||
|
|
||||||
|
expect(page.getApiSearchResults()).not.toContain('HttpEventType');
|
||||||
|
expect(page.getApiSearchResults()).toContain('AnimationSequenceMetadata');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find getLocaleDateTimeFormat when searching by partial word date', () => {
|
||||||
|
expect(page.getApiSearchResults()).toContain('formatCurrency');
|
||||||
|
|
||||||
|
apiSearchInput.clear();
|
||||||
|
apiSearchInput.sendKeys('date');
|
||||||
|
|
||||||
|
expect(page.getApiSearchResults()).not.toContain('formatCurrency');
|
||||||
|
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find LowerCasePipe when searching for type pipe', () => {
|
||||||
|
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
|
||||||
|
|
||||||
|
page.clickDropdownItem(apiTypeDropdown, 'Pipe');
|
||||||
|
|
||||||
|
expect(page.getApiSearchResults()).not.toContain('getLocaleDateTimeFormat');
|
||||||
|
expect(page.getApiSearchResults()).toContain('LowerCasePipe');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find ElementRef when searching for status Security Risk', () => {
|
||||||
|
expect(page.getApiSearchResults()).toContain('getLocaleDateTimeFormat');
|
||||||
|
|
||||||
|
page.clickDropdownItem(apiStatusDropdown, 'Security Risk');
|
||||||
|
|
||||||
|
expect(page.getApiSearchResults()).not.toContain('getLocaleDateTimeFormat');
|
||||||
|
expect(page.getApiSearchResults()).toContain('ElementRef');
|
||||||
|
});
|
||||||
|
});
|
@ -83,4 +83,16 @@ export class SitePage {
|
|||||||
browser.wait(ExpectedConditions.presenceOf(results.first()), 8000);
|
browser.wait(ExpectedConditions.presenceOf(results.first()), 8000);
|
||||||
return results.map(link => link && link.getText());
|
return results.map(link => link && link.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getApiSearchResults() {
|
||||||
|
const results = element.all(by.css('aio-api-list .api-item'));
|
||||||
|
browser.wait(ExpectedConditions.presenceOf(results.first()), 2000);
|
||||||
|
return results.map(elem => elem && elem.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
clickDropdownItem(dropdown: ElementFinder, itemName: string){
|
||||||
|
dropdown.element(by.css('.form-select-button')).click();
|
||||||
|
const menuItem = dropdown.element(by.cssContainingText('.form-select-dropdown li', itemName));
|
||||||
|
menuItem.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const sh = require('shelljs');
|
const sh = require('shelljs');
|
||||||
|
|
||||||
const PATCH_LOCK = 'node_modules/@angular/cli/.patched';
|
const PATCH_LOCK = 'node_modules/@angular/cli/.patched';
|
||||||
|
|
||||||
if (!fs.existsSync(PATCH_LOCK)) {
|
sh.set('-e');
|
||||||
|
sh.cd(`${__dirname}/../../`);
|
||||||
|
|
||||||
|
if (!sh.test('-f', PATCH_LOCK)) {
|
||||||
|
sh.ls('-l', __dirname)
|
||||||
|
.filter(stat => stat.isFile() && /\.patch$/i.test(stat.name))
|
||||||
|
.forEach(stat => sh.exec(`patch -p0 -i "${__dirname}/${stat.name}"`));
|
||||||
|
|
||||||
sh.touch(PATCH_LOCK);
|
sh.touch(PATCH_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,7 @@ const DEFAULT_CLI_EXAMPLE_PORT = 4200;
|
|||||||
const DEFAULT_CLI_SPECS_CONCURRENCY = 1;
|
const DEFAULT_CLI_SPECS_CONCURRENCY = 1;
|
||||||
const IGNORED_EXAMPLES = [];
|
const IGNORED_EXAMPLES = [];
|
||||||
|
|
||||||
const fixmeIvyExamples = [
|
const fixmeIvyExamples = [];
|
||||||
// fixmeIvy('unknown') app fails at runtime due to missing external service (goog is undefined)
|
|
||||||
'i18n',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!argv.viewengine) {
|
if (!argv.viewengine) {
|
||||||
IGNORED_EXAMPLES.push(...fixmeIvyExamples);
|
IGNORED_EXAMPLES.push(...fixmeIvyExamples);
|
||||||
@ -72,8 +69,10 @@ function runE2e() {
|
|||||||
const outputFile = path.join(AIO_PATH, './protractor-results.txt');
|
const outputFile = path.join(AIO_PATH, './protractor-results.txt');
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => findAndRunE2eTests(argv.filter, outputFile, argv.shard,
|
.then(
|
||||||
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
|
() => findAndRunE2eTests(
|
||||||
|
argv.filter, outputFile, argv.shard,
|
||||||
|
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
|
||||||
.then((status) => {
|
.then((status) => {
|
||||||
reportStatus(status, outputFile);
|
reportStatus(status, outputFile);
|
||||||
if (status.failed.length > 0) {
|
if (status.failed.length > 0) {
|
||||||
@ -226,8 +225,12 @@ function runProtractorSystemJS(prepPromise, appDir, appRunSpawnInfo, outputFile)
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
function() { return finish(appRunSpawnInfo.proc.pid, true); },
|
function() {
|
||||||
function() { return finish(appRunSpawnInfo.proc.pid, false); });
|
return finish(appRunSpawnInfo.proc.pid, true);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
return finish(appRunSpawnInfo.proc.pid, false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function finish(spawnProcId, ok) {
|
function finish(spawnProcId, ok) {
|
||||||
@ -263,15 +266,15 @@ function runE2eTestsCLI(appDir, outputFile, bufferOutput, port) {
|
|||||||
// `--no-webdriver-update` is needed to preserve the ChromeDriver version already installed.
|
// `--no-webdriver-update` is needed to preserve the ChromeDriver version already installed.
|
||||||
const config = loadExampleConfig(appDir);
|
const config = loadExampleConfig(appDir);
|
||||||
const testCommands = config.tests || [{
|
const testCommands = config.tests || [{
|
||||||
cmd: 'yarn',
|
cmd: 'yarn',
|
||||||
args: [
|
args: [
|
||||||
'e2e',
|
'e2e',
|
||||||
'--prod',
|
'--prod',
|
||||||
'--protractor-config=e2e/protractor-puppeteer.conf.js',
|
'--protractor-config=e2e/protractor-puppeteer.conf.js',
|
||||||
'--no-webdriver-update',
|
'--no-webdriver-update',
|
||||||
'--port={PORT}',
|
'--port={PORT}',
|
||||||
],
|
],
|
||||||
}];
|
}];
|
||||||
let bufferedOutput = `\n\n============== AIO example output for: ${appDir}\n\n`;
|
let bufferedOutput = `\n\n============== AIO example output for: ${appDir}\n\n`;
|
||||||
|
|
||||||
const e2eSpawnPromise = testCommands.reduce((prevSpawnPromise, {cmd, args}) => {
|
const e2eSpawnPromise = testCommands.reduce((prevSpawnPromise, {cmd, args}) => {
|
||||||
@ -281,26 +284,30 @@ function runE2eTestsCLI(appDir, outputFile, bufferOutput, port) {
|
|||||||
args = args.map(a => a.replace('{PORT}', port || DEFAULT_CLI_EXAMPLE_PORT));
|
args = args.map(a => a.replace('{PORT}', port || DEFAULT_CLI_EXAMPLE_PORT));
|
||||||
|
|
||||||
return prevSpawnPromise.then(() => {
|
return prevSpawnPromise.then(() => {
|
||||||
const currSpawn = spawnExt(cmd, args, {cwd: appDir}, false,
|
const currSpawn = spawnExt(
|
||||||
bufferOutput ? msg => bufferedOutput += msg : undefined);
|
cmd, args, {cwd: appDir}, false, bufferOutput ? msg => bufferedOutput += msg : undefined);
|
||||||
return currSpawn.promise.then(
|
return currSpawn.promise.then(
|
||||||
() => Promise.resolve(finish(currSpawn.proc.pid, true)),
|
() => Promise.resolve(finish(currSpawn.proc.pid, true)),
|
||||||
() => Promise.reject(finish(currSpawn.proc.pid, false)));
|
() => Promise.reject(finish(currSpawn.proc.pid, false)));
|
||||||
});
|
});
|
||||||
}, Promise.resolve());
|
}, Promise.resolve());
|
||||||
|
|
||||||
return e2eSpawnPromise.then(() => {
|
return e2eSpawnPromise
|
||||||
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
|
.then(
|
||||||
return true;
|
() => {
|
||||||
}, () => {
|
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
|
||||||
fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`);
|
return true;
|
||||||
return false;
|
},
|
||||||
}).then(passed => {
|
() => {
|
||||||
if (bufferOutput) {
|
fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`);
|
||||||
process.stdout.write(bufferedOutput);
|
return false;
|
||||||
}
|
})
|
||||||
return passed;
|
.then(passed => {
|
||||||
});
|
if (bufferOutput) {
|
||||||
|
process.stdout.write(bufferedOutput);
|
||||||
|
}
|
||||||
|
return passed;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report final status.
|
// Report final status.
|
||||||
@ -309,23 +316,31 @@ function reportStatus(status, outputFile) {
|
|||||||
|
|
||||||
log.push('Suites ignored due to legacy guides:');
|
log.push('Suites ignored due to legacy guides:');
|
||||||
IGNORED_EXAMPLES.filter(example => !fixmeIvyExamples.find(ex => ex.startsWith(example)))
|
IGNORED_EXAMPLES.filter(example => !fixmeIvyExamples.find(ex => ex.startsWith(example)))
|
||||||
.forEach(function(val) { log.push(' ' + val); });
|
.forEach(function(val) {
|
||||||
|
log.push(' ' + val);
|
||||||
|
});
|
||||||
|
|
||||||
if (!argv.viewengine) {
|
if (!argv.viewengine) {
|
||||||
log.push('');
|
log.push('');
|
||||||
log.push('Suites ignored due to breakage with Ivy:');
|
log.push('Suites ignored due to breakage with Ivy:');
|
||||||
fixmeIvyExamples.forEach(function(val) { log.push(' ' + val); });
|
fixmeIvyExamples.forEach(function(val) {
|
||||||
|
log.push(' ' + val);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
log.push('');
|
log.push('');
|
||||||
log.push('Suites passed:');
|
log.push('Suites passed:');
|
||||||
status.passed.forEach(function(val) { log.push(' ' + val); });
|
status.passed.forEach(function(val) {
|
||||||
|
log.push(' ' + val);
|
||||||
|
});
|
||||||
|
|
||||||
if (status.failed.length == 0) {
|
if (status.failed.length == 0) {
|
||||||
log.push('All tests passed');
|
log.push('All tests passed');
|
||||||
} else {
|
} else {
|
||||||
log.push('Suites failed:');
|
log.push('Suites failed:');
|
||||||
status.failed.forEach(function(val) { log.push(' ' + val); });
|
status.failed.forEach(function(val) {
|
||||||
|
log.push(' ' + val);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
log.push('\nElapsed time: ' + status.elapsedTime + ' seconds');
|
log.push('\nElapsed time: ' + status.elapsedTime + ' seconds');
|
||||||
log = log.join('\n');
|
log = log.join('\n');
|
||||||
@ -334,8 +349,8 @@ function reportStatus(status, outputFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns both a promise and the spawned process so that it can be killed if needed.
|
// Returns both a promise and the spawned process so that it can be killed if needed.
|
||||||
function spawnExt(command, args, options, ignoreClose = false,
|
function spawnExt(
|
||||||
printMessage = msg => process.stdout.write(msg)) {
|
command, args, options, ignoreClose = false, printMessage = msg => process.stdout.write(msg)) {
|
||||||
let proc;
|
let proc;
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
let descr = command + ' ' + args.join(' ');
|
let descr = command + ' ' + args.join(' ');
|
||||||
@ -370,13 +385,19 @@ function getE2eSpecs(basePath, filter) {
|
|||||||
let specs = {};
|
let specs = {};
|
||||||
|
|
||||||
return getE2eSpecsFor(basePath, SJS_SPEC_FILENAME, filter)
|
return getE2eSpecsFor(basePath, SJS_SPEC_FILENAME, filter)
|
||||||
.then(sjsPaths => { specs.systemjs = sjsPaths; })
|
.then(sjsPaths => {
|
||||||
|
specs.systemjs = sjsPaths;
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return getE2eSpecsFor(basePath, CLI_SPEC_FILENAME, filter).then(cliPaths => {
|
return getE2eSpecsFor(basePath, CLI_SPEC_FILENAME, filter).then(cliPaths => {
|
||||||
return cliPaths.map(p => { return p.replace(`${CLI_SPEC_FILENAME}`, ''); });
|
return cliPaths.map(p => {
|
||||||
|
return p.replace(`${CLI_SPEC_FILENAME}`, '');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(cliPaths => { specs.cli = cliPaths; })
|
.then(cliPaths => {
|
||||||
|
specs.cli = cliPaths;
|
||||||
|
})
|
||||||
.then(() => specs);
|
.then(() => specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +9,18 @@
|
|||||||
"root": "",
|
"root": "",
|
||||||
"sourceRoot": "src",
|
"sourceRoot": "src",
|
||||||
"prefix": "app",
|
"prefix": "app",
|
||||||
|
"i18n": {
|
||||||
|
"sourceLocale": "en-US",
|
||||||
|
"locales": {
|
||||||
|
"fr": "src/locale/messages.fr.xlf"
|
||||||
|
}
|
||||||
|
},
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
"options": {
|
"options": {
|
||||||
|
"localize": true,
|
||||||
|
"aot": true,
|
||||||
"outputPath": "dist",
|
"outputPath": "dist",
|
||||||
"index": "src/index.html",
|
"index": "src/index.html",
|
||||||
"main": "src/main.ts",
|
"main": "src/main.ts",
|
||||||
@ -57,35 +65,10 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"production-fr": {
|
|
||||||
"fileReplacements": [
|
|
||||||
{
|
|
||||||
"replace": "src/environments/environment.ts",
|
|
||||||
"with": "src/environments/environment.prod.ts"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"optimization": true,
|
|
||||||
"outputHashing": "all",
|
|
||||||
"sourceMap": false,
|
|
||||||
"extractCss": true,
|
|
||||||
"namedChunks": false,
|
|
||||||
"aot": true,
|
|
||||||
"extractLicenses": true,
|
|
||||||
"vendorChunk": false,
|
|
||||||
"buildOptimizer": true,
|
|
||||||
"outputPath": "dist/my-project-fr/",
|
|
||||||
"i18nFile": "src/locale/messages.fr.xlf",
|
|
||||||
"i18nFormat": "xlf",
|
|
||||||
"i18nLocale": "fr",
|
|
||||||
"i18nMissingTranslation": "error"
|
|
||||||
},
|
|
||||||
"fr": {
|
"fr": {
|
||||||
"aot": true,
|
"localize": [
|
||||||
"outputPath": "dist/my-project-fr/",
|
"fr"
|
||||||
"i18nFile": "src/locale/messages.fr.xlf",
|
]
|
||||||
"i18nFormat": "xlf",
|
|
||||||
"i18nLocale": "fr",
|
|
||||||
"i18nMissingTranslation": "error"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"@angular/compiler": "~9.1.4",
|
"@angular/compiler": "~9.1.4",
|
||||||
"@angular/core": "~9.1.4",
|
"@angular/core": "~9.1.4",
|
||||||
"@angular/forms": "~9.1.4",
|
"@angular/forms": "~9.1.4",
|
||||||
|
"@angular/localize": "^9.1.4",
|
||||||
"@angular/platform-browser": "~9.1.4",
|
"@angular/platform-browser": "~9.1.4",
|
||||||
"@angular/platform-browser-dynamic": "~9.1.4",
|
"@angular/platform-browser-dynamic": "~9.1.4",
|
||||||
"@angular/router": "~9.1.4",
|
"@angular/router": "~9.1.4",
|
||||||
|
68
aio/tools/examples/shared/boilerplate/i18n/polyfills.ts
Normal file
68
aio/tools/examples/shared/boilerplate/i18n/polyfills.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
|
||||||
|
*/
|
||||||
|
import '@angular/localize/init';
|
||||||
|
/**
|
||||||
|
* 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/guide/browser-support
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* BROWSER POLYFILLS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||||
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Animations `@angular/platform-browser/animations`
|
||||||
|
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||||
|
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||||
|
*/
|
||||||
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||||
|
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||||
|
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||||
|
* will put import in the top of bundle, so user need to create a separate file
|
||||||
|
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||||
|
* into that file, and then add the following code before importing zone.js.
|
||||||
|
* import './zone-flags';
|
||||||
|
*
|
||||||
|
* The flags allowed in zone-flags.ts are listed here.
|
||||||
|
*
|
||||||
|
* The following flags will work for all browsers.
|
||||||
|
*
|
||||||
|
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch
|
||||||
|
* requestAnimationFrame
|
||||||
|
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||||
|
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch
|
||||||
|
* specified eventNames
|
||||||
|
*
|
||||||
|
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||||
|
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||||
|
*
|
||||||
|
* (window as any).__Zone_enable_cross_context_check = true;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Zone JS is required by default for Angular itself.
|
||||||
|
*/
|
||||||
|
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* APPLICATION IMPORTS
|
||||||
|
*/
|
@ -26,6 +26,7 @@
|
|||||||
"@angular/core": "~9.1.4",
|
"@angular/core": "~9.1.4",
|
||||||
"@angular/elements": "~9.1.4",
|
"@angular/elements": "~9.1.4",
|
||||||
"@angular/forms": "~9.1.4",
|
"@angular/forms": "~9.1.4",
|
||||||
|
"@angular/localize": "~9.1.4",
|
||||||
"@angular/platform-browser": "~9.1.4",
|
"@angular/platform-browser": "~9.1.4",
|
||||||
"@angular/platform-browser-dynamic": "~9.1.4",
|
"@angular/platform-browser-dynamic": "~9.1.4",
|
||||||
"@angular/platform-server": "~9.1.4",
|
"@angular/platform-server": "~9.1.4",
|
||||||
|
@ -215,6 +215,15 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.4.tgz#2fa2c444e5a5a6036d5ca43d2887826df17d0553"
|
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.4.tgz#2fa2c444e5a5a6036d5ca43d2887826df17d0553"
|
||||||
integrity sha512-eyVxxiegdb4ESdFGfkuDN+YfUbOVHRQLjIl6ACFJQDNHzVXzbmuqpyr5hIJANIVady103/7+dqRxxJo1DdIdTQ==
|
integrity sha512-eyVxxiegdb4ESdFGfkuDN+YfUbOVHRQLjIl6ACFJQDNHzVXzbmuqpyr5hIJANIVady103/7+dqRxxJo1DdIdTQ==
|
||||||
|
|
||||||
|
"@angular/localize@~9.1.4":
|
||||||
|
version "9.1.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.1.11.tgz#25921d794836fb7a07d284c1ac0ed06c10e77d50"
|
||||||
|
integrity sha512-CrR7RniwJIK3+QKH8nHl35KDAHZn1mp1QAd5vujTWKw6YRLfio7SjM9qIfzw5y4WZuUitTsqKlQT/m/NK146Ag==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "7.8.3"
|
||||||
|
glob "7.1.2"
|
||||||
|
yargs "15.3.0"
|
||||||
|
|
||||||
"@angular/platform-browser-dynamic@~9.1.4":
|
"@angular/platform-browser-dynamic@~9.1.4":
|
||||||
version "9.1.4"
|
version "9.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.4.tgz#bf1cde9156bd29eeeef932b683b0c993614f75d5"
|
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.4.tgz#bf1cde9156bd29eeeef932b683b0c993614f75d5"
|
||||||
@ -254,6 +263,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.0.0"
|
"@babel/highlight" "^7.0.0"
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff"
|
||||||
|
integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.10.1"
|
||||||
|
|
||||||
"@babel/code-frame@^7.5.5":
|
"@babel/code-frame@^7.5.5":
|
||||||
version "7.5.5"
|
version "7.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
|
||||||
@ -277,6 +293,27 @@
|
|||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
semver "^5.5.0"
|
semver "^5.5.0"
|
||||||
|
|
||||||
|
"@babel/core@7.8.3":
|
||||||
|
version "7.8.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
|
||||||
|
integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.8.3"
|
||||||
|
"@babel/generator" "^7.8.3"
|
||||||
|
"@babel/helpers" "^7.8.3"
|
||||||
|
"@babel/parser" "^7.8.3"
|
||||||
|
"@babel/template" "^7.8.3"
|
||||||
|
"@babel/traverse" "^7.8.3"
|
||||||
|
"@babel/types" "^7.8.3"
|
||||||
|
convert-source-map "^1.7.0"
|
||||||
|
debug "^4.1.0"
|
||||||
|
gensync "^1.0.0-beta.1"
|
||||||
|
json5 "^2.1.0"
|
||||||
|
lodash "^4.17.13"
|
||||||
|
resolve "^1.3.2"
|
||||||
|
semver "^5.4.1"
|
||||||
|
source-map "^0.5.0"
|
||||||
|
|
||||||
"@babel/core@7.9.0":
|
"@babel/core@7.9.0":
|
||||||
version "7.9.0"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
|
||||||
@ -330,6 +367,16 @@
|
|||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
source-map "^0.5.0"
|
source-map "^0.5.0"
|
||||||
|
|
||||||
|
"@babel/generator@^7.10.1", "@babel/generator@^7.8.3":
|
||||||
|
version "7.10.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.2.tgz#0fa5b5b2389db8bfdfcc3492b551ee20f5dd69a9"
|
||||||
|
integrity sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.10.2"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
lodash "^4.17.13"
|
||||||
|
source-map "^0.5.0"
|
||||||
|
|
||||||
"@babel/generator@^7.4.0", "@babel/generator@^7.7.4":
|
"@babel/generator@^7.4.0", "@babel/generator@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
|
||||||
@ -420,6 +467,15 @@
|
|||||||
"@babel/traverse" "^7.8.3"
|
"@babel/traverse" "^7.8.3"
|
||||||
"@babel/types" "^7.8.3"
|
"@babel/types" "^7.8.3"
|
||||||
|
|
||||||
|
"@babel/helper-function-name@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4"
|
||||||
|
integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-get-function-arity" "^7.10.1"
|
||||||
|
"@babel/template" "^7.10.1"
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
|
||||||
"@babel/helper-function-name@^7.7.4":
|
"@babel/helper-function-name@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
|
||||||
@ -447,6 +503,13 @@
|
|||||||
"@babel/template" "^7.8.3"
|
"@babel/template" "^7.8.3"
|
||||||
"@babel/types" "^7.9.5"
|
"@babel/types" "^7.9.5"
|
||||||
|
|
||||||
|
"@babel/helper-get-function-arity@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d"
|
||||||
|
integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
|
||||||
"@babel/helper-get-function-arity@^7.7.4":
|
"@babel/helper-get-function-arity@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
|
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
|
||||||
@ -558,6 +621,13 @@
|
|||||||
"@babel/template" "^7.8.3"
|
"@babel/template" "^7.8.3"
|
||||||
"@babel/types" "^7.8.3"
|
"@babel/types" "^7.8.3"
|
||||||
|
|
||||||
|
"@babel/helper-split-export-declaration@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f"
|
||||||
|
integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
|
||||||
"@babel/helper-split-export-declaration@^7.7.4":
|
"@babel/helper-split-export-declaration@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
|
||||||
@ -572,6 +642,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.8.3"
|
"@babel/types" "^7.8.3"
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5"
|
||||||
|
integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.9.5":
|
"@babel/helper-validator-identifier@^7.9.5":
|
||||||
version "7.9.5"
|
version "7.9.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
|
||||||
@ -587,6 +662,15 @@
|
|||||||
"@babel/traverse" "^7.8.3"
|
"@babel/traverse" "^7.8.3"
|
||||||
"@babel/types" "^7.8.3"
|
"@babel/types" "^7.8.3"
|
||||||
|
|
||||||
|
"@babel/helpers@^7.8.3":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973"
|
||||||
|
integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.10.1"
|
||||||
|
"@babel/traverse" "^7.10.1"
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
|
||||||
"@babel/helpers@^7.8.4":
|
"@babel/helpers@^7.8.4":
|
||||||
version "7.8.4"
|
version "7.8.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
|
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
|
||||||
@ -613,6 +697,15 @@
|
|||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/highlight@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0"
|
||||||
|
integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.10.1"
|
||||||
|
chalk "^2.0.0"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/highlight@^7.8.3":
|
"@babel/highlight@^7.8.3":
|
||||||
version "7.8.3"
|
version "7.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
|
||||||
@ -622,6 +715,11 @@
|
|||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/parser@^7.10.1":
|
||||||
|
version "7.10.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0"
|
||||||
|
integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==
|
||||||
|
|
||||||
"@babel/parser@^7.4.3", "@babel/parser@^7.7.4":
|
"@babel/parser@^7.4.3", "@babel/parser@^7.7.4":
|
||||||
version "7.7.5"
|
version "7.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
|
||||||
@ -1126,6 +1224,15 @@
|
|||||||
"@babel/parser" "^7.8.6"
|
"@babel/parser" "^7.8.6"
|
||||||
"@babel/types" "^7.8.6"
|
"@babel/types" "^7.8.6"
|
||||||
|
|
||||||
|
"@babel/template@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
||||||
|
integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.10.1"
|
||||||
|
"@babel/parser" "^7.10.1"
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
|
||||||
"@babel/template@^7.4.0", "@babel/template@^7.7.4":
|
"@babel/template@^7.4.0", "@babel/template@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
|
||||||
@ -1144,6 +1251,21 @@
|
|||||||
"@babel/parser" "^7.8.3"
|
"@babel/parser" "^7.8.3"
|
||||||
"@babel/types" "^7.8.3"
|
"@babel/types" "^7.8.3"
|
||||||
|
|
||||||
|
"@babel/traverse@^7.10.1":
|
||||||
|
version "7.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27"
|
||||||
|
integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.10.1"
|
||||||
|
"@babel/generator" "^7.10.1"
|
||||||
|
"@babel/helper-function-name" "^7.10.1"
|
||||||
|
"@babel/helper-split-export-declaration" "^7.10.1"
|
||||||
|
"@babel/parser" "^7.10.1"
|
||||||
|
"@babel/types" "^7.10.1"
|
||||||
|
debug "^4.1.0"
|
||||||
|
globals "^11.1.0"
|
||||||
|
lodash "^4.17.13"
|
||||||
|
|
||||||
"@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4":
|
"@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
|
||||||
@ -1189,6 +1311,15 @@
|
|||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
|
|
||||||
|
"@babel/types@^7.10.1", "@babel/types@^7.10.2":
|
||||||
|
version "7.10.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d"
|
||||||
|
integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.10.1"
|
||||||
|
lodash "^4.17.13"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@babel/types@^7.4.0", "@babel/types@^7.7.4":
|
"@babel/types@^7.4.0", "@babel/types@^7.7.4":
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
|
||||||
@ -5265,10 +5396,10 @@ glob-parent@~5.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob "^4.0.1"
|
is-glob "^4.0.1"
|
||||||
|
|
||||||
glob@7.1.6, glob@^7.1.4:
|
glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
|
||||||
version "7.1.6"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
fs.realpath "^1.0.0"
|
fs.realpath "^1.0.0"
|
||||||
inflight "^1.0.4"
|
inflight "^1.0.4"
|
||||||
@ -5277,9 +5408,10 @@ glob@7.1.6, glob@^7.1.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
|
glob@7.1.6, glob@^7.1.4:
|
||||||
version "7.1.2"
|
version "7.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||||
|
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||||
dependencies:
|
dependencies:
|
||||||
fs.realpath "^1.0.0"
|
fs.realpath "^1.0.0"
|
||||||
inflight "^1.0.4"
|
inflight "^1.0.4"
|
||||||
|
@ -4467,10 +4467,10 @@ dezalgo@^1.0.0:
|
|||||||
asap "^2.0.0"
|
asap "^2.0.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
dgeni-packages@^0.28.3:
|
dgeni-packages@^0.28.4:
|
||||||
version "0.28.3"
|
version "0.28.4"
|
||||||
resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.28.3.tgz#2e1e55f341c389b67ebb28933ce1e7e9ad05c49b"
|
resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.28.4.tgz#53a3e6700b8d8f6be168cadcc9fdb36e1d7011d3"
|
||||||
integrity sha512-WyVzY3Q4ylfnc2677le5G7a7WqkF88rBSjU9IrAofqro71yzZeWLoEdr/gJY+lJZ0PrDyuRW05pFvIbvX8N0PQ==
|
integrity sha512-7AUG3pKpWtn69c3v2Mzgh+i5gd+L0AxFfYGWGzBdlJqMlQfaQPQjaS54iYCvnOlK9rXBn9j39yO6EU70gDZuFw==
|
||||||
dependencies:
|
dependencies:
|
||||||
canonical-path "^1.0.0"
|
canonical-path "^1.0.0"
|
||||||
catharsis "^0.8.1"
|
catharsis "^0.8.1"
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
var CIconfiguration = {
|
var CIconfiguration = {
|
||||||
'Chrome': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
'Chrome': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
'Firefox': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
'Firefox': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
'FirefoxESR': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
// Set ESR as a not required browser as it fails for Ivy acceptance tests.
|
||||||
|
'FirefoxESR': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
// Disabled because using the "beta" channel of Chrome can cause non-deterministic CI results.
|
// Disabled because using the "beta" channel of Chrome can cause non-deterministic CI results.
|
||||||
// e.g. a new chrome beta version has been released, but the Saucelabs selenium server does
|
// e.g. a new chrome beta version has been released, but the Saucelabs selenium server does
|
||||||
// not provide a chromedriver version that is compatible with the new beta.
|
// not provide a chromedriver version that is compatible with the new beta.
|
||||||
|
1
dev-infra/bazel/BUILD.bazel
Normal file
1
dev-infra/bazel/BUILD.bazel
Normal file
@ -0,0 +1 @@
|
|||||||
|
package(default_visibility = ["//visibility:public"])
|
45
dev-infra/bazel/expand_template.bzl
Normal file
45
dev-infra/bazel/expand_template.bzl
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""Implementation of the expand_template rule """
|
||||||
|
|
||||||
|
def expand_template_impl(ctx):
|
||||||
|
substitutions = dict()
|
||||||
|
|
||||||
|
for k in ctx.attr.configuration_env_vars:
|
||||||
|
if k in ctx.var.keys():
|
||||||
|
substitutions["TMPL_%s" % k] = ctx.var[k]
|
||||||
|
|
||||||
|
for k in ctx.attr.substitutions:
|
||||||
|
substitutions[k] = ctx.expand_location(ctx.attr.substitutions[k], targets = ctx.attr.data)
|
||||||
|
|
||||||
|
ctx.actions.expand_template(
|
||||||
|
template = ctx.file.template,
|
||||||
|
output = ctx.outputs.output_name,
|
||||||
|
substitutions = substitutions,
|
||||||
|
)
|
||||||
|
|
||||||
|
"""Rule that can be used to substitute variables in a given template file."""
|
||||||
|
expand_template = rule(
|
||||||
|
implementation = expand_template_impl,
|
||||||
|
attrs = {
|
||||||
|
"configuration_env_vars": attr.string_list(
|
||||||
|
default = [],
|
||||||
|
doc = "Bazel configuration variables which should be exposed to the template.",
|
||||||
|
),
|
||||||
|
"output_name": attr.output(
|
||||||
|
mandatory = True,
|
||||||
|
doc = "File where the substituted template is written to.",
|
||||||
|
),
|
||||||
|
"substitutions": attr.string_dict(
|
||||||
|
mandatory = True,
|
||||||
|
doc = "Dictionary of substitutions that should be available to the template. Dictionary key represents the placeholder in the template.",
|
||||||
|
),
|
||||||
|
"data": attr.label_list(
|
||||||
|
doc = """Data dependencies for location expansion.""",
|
||||||
|
allow_files = True,
|
||||||
|
),
|
||||||
|
"template": attr.label(
|
||||||
|
mandatory = True,
|
||||||
|
allow_single_file = True,
|
||||||
|
doc = "File used as template.",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
@ -25,6 +25,7 @@ def component_benchmark(
|
|||||||
driver_deps,
|
driver_deps,
|
||||||
ng_srcs,
|
ng_srcs,
|
||||||
ng_deps,
|
ng_deps,
|
||||||
|
ng_assets = [],
|
||||||
assets = None,
|
assets = None,
|
||||||
styles = None,
|
styles = None,
|
||||||
entry_point = None,
|
entry_point = None,
|
||||||
@ -65,6 +66,7 @@ def component_benchmark(
|
|||||||
driver_deps: Driver's dependencies
|
driver_deps: Driver's dependencies
|
||||||
ng_srcs: All of the ts srcs for the angular app
|
ng_srcs: All of the ts srcs for the angular app
|
||||||
ng_deps: Dependencies for the angular app
|
ng_deps: Dependencies for the angular app
|
||||||
|
ng_assets: The static assets for the angular app
|
||||||
assets: Static files
|
assets: Static files
|
||||||
styles: Stylesheets
|
styles: Stylesheets
|
||||||
entry_point: Main entry point for the angular app
|
entry_point: Main entry point for the angular app
|
||||||
@ -104,6 +106,7 @@ def component_benchmark(
|
|||||||
ng_module(
|
ng_module(
|
||||||
name = app_lib,
|
name = app_lib,
|
||||||
srcs = ng_srcs,
|
srcs = ng_srcs,
|
||||||
|
assets = ng_assets,
|
||||||
# Creates ngFactory and ngSummary to be imported by the app's entry point.
|
# Creates ngFactory and ngSummary to be imported by the app's entry point.
|
||||||
generate_ve_shims = True,
|
generate_ve_shims = True,
|
||||||
deps = ng_deps,
|
deps = ng_deps,
|
||||||
@ -129,10 +132,10 @@ def component_benchmark(
|
|||||||
# The server for our application.
|
# The server for our application.
|
||||||
ts_devserver(
|
ts_devserver(
|
||||||
name = server,
|
name = server,
|
||||||
bootstrap = ["//packages/zone.js/dist:zone.js"],
|
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
|
||||||
port = 4200,
|
port = 4200,
|
||||||
static_files = assets + styles,
|
static_files = assets + styles,
|
||||||
deps = [":" + app_main + ".min_debug.es2015.js"],
|
deps = [":" + app_main + ".min_debug.js"],
|
||||||
additional_root_paths = ["//dev-infra/benchmark/component_benchmark/defaults"],
|
additional_root_paths = ["//dev-infra/benchmark/component_benchmark/defaults"],
|
||||||
serving_path = "/app_bundle.js",
|
serving_path = "/app_bundle.js",
|
||||||
)
|
)
|
||||||
|
@ -9,12 +9,12 @@ ts_library(
|
|||||||
tsconfig = "//dev-infra/benchmark/component_benchmark:tsconfig-e2e.json",
|
tsconfig = "//dev-infra/benchmark/component_benchmark:tsconfig-e2e.json",
|
||||||
deps = [
|
deps = [
|
||||||
"//packages/benchpress",
|
"//packages/benchpress",
|
||||||
"@npm//@types/fs-extra",
|
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/selenium-webdriver",
|
"@npm//@types/selenium-webdriver",
|
||||||
"@npm//fs-extra",
|
"@npm//@types/shelljs",
|
||||||
"@npm//node-uuid",
|
"@npm//node-uuid",
|
||||||
"@npm//protractor",
|
"@npm//protractor",
|
||||||
"@npm//selenium-webdriver",
|
"@npm//selenium-webdriver",
|
||||||
|
"@npm//shelljs",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
import {mkdir} from 'shelljs';
|
||||||
|
|
||||||
export {verifyNoBrowserErrors} from './e2e_util';
|
export {verifyNoBrowserErrors} from './e2e_util';
|
||||||
|
|
||||||
const nodeUuid = require('node-uuid');
|
const nodeUuid = require('node-uuid');
|
||||||
import * as fs from 'fs-extra';
|
|
||||||
|
|
||||||
import {SeleniumWebDriverAdapter, Options, JsonFileReporter, Validator, RegressionSlopeValidator, ConsoleReporter, SizeValidator, MultiReporter, MultiMetric, Runner, StaticProvider} from '@angular/benchpress';
|
import {SeleniumWebDriverAdapter, Options, JsonFileReporter, Validator, RegressionSlopeValidator, ConsoleReporter, SizeValidator, MultiReporter, MultiMetric, Runner, StaticProvider} from '@angular/benchpress';
|
||||||
import {openBrowser} from './e2e_util';
|
import {openBrowser} from './e2e_util';
|
||||||
@ -53,7 +54,7 @@ function createBenchpressRunner(): Runner {
|
|||||||
runId = process.env.GIT_SHA + ' ' + runId;
|
runId = process.env.GIT_SHA + ' ' + runId;
|
||||||
}
|
}
|
||||||
const resultsFolder = './dist/benchmark_results';
|
const resultsFolder = './dist/benchmark_results';
|
||||||
fs.ensureDirSync(resultsFolder);
|
mkdir('-p', resultsFolder);
|
||||||
const providers: StaticProvider[] = [
|
const providers: StaticProvider[] = [
|
||||||
SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
|
SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
|
||||||
{provide: Options.FORCE_GC, useValue: globalOptions.forceGc},
|
{provide: Options.FORCE_GC, useValue: globalOptions.forceGc},
|
||||||
|
@ -3,7 +3,7 @@ package(default_visibility = ["//visibility:public"])
|
|||||||
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
|
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
|
||||||
|
|
||||||
exports_files([
|
exports_files([
|
||||||
"rollup.config.js",
|
"rollup.config-tmpl.js",
|
||||||
"terser_config.json",
|
"terser_config.json",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -3,414 +3,90 @@
|
|||||||
# Use of this source code is governed by an MIT-style license that can be
|
# 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
|
# found in the LICENSE file at https://angular.io/license
|
||||||
|
|
||||||
"""Rollup with Build Optimizer
|
|
||||||
|
|
||||||
This provides a variant of the [rollup_bundle] rule that works better for Angular apps.
|
|
||||||
|
|
||||||
It registers `@angular-devkit/build-optimizer` as a rollup plugin, to get
|
|
||||||
better optimization. It also uses ESM5 format inputs, as this is what
|
|
||||||
build-optimizer is hard-coded to look for and transform.
|
|
||||||
|
|
||||||
[rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html
|
|
||||||
"""
|
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
|
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
|
||||||
load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "NpmPackageInfo", "node_modules_aspect")
|
|
||||||
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5")
|
|
||||||
load("@npm_bazel_terser//:index.bzl", "terser_minified")
|
load("@npm_bazel_terser//:index.bzl", "terser_minified")
|
||||||
|
load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
|
||||||
|
load("//dev-infra/bazel:expand_template.bzl", "expand_template")
|
||||||
|
|
||||||
_NG_ROLLUP_BUNDLE_OUTPUTS = {
|
def ng_rollup_bundle(
|
||||||
"bundle": "%{name}.js",
|
name,
|
||||||
"sourcemap": "%{name}.js.map",
|
entry_point,
|
||||||
}
|
deps = [],
|
||||||
|
license_banner = None,
|
||||||
|
build_optimizer = True,
|
||||||
|
visibility = None,
|
||||||
|
format = "iife",
|
||||||
|
globals = {},
|
||||||
|
**kwargs):
|
||||||
|
"""Rollup with Build Optimizer on target prodmode output (ESM2015).
|
||||||
|
|
||||||
_NG_ROLLUP_MODULE_MAPPINGS_ATTR = "ng_rollup_module_mappings"
|
This provides an extension of the [rollup_bundle] rule that works better for Angular apps.
|
||||||
|
|
||||||
def _ng_rollup_module_mappings_aspect_impl(target, ctx):
|
|
||||||
mappings = dict()
|
|
||||||
for dep in ctx.rule.attr.deps:
|
|
||||||
if hasattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR):
|
|
||||||
for k, v in getattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR).items():
|
|
||||||
if k in mappings and mappings[k] != v:
|
|
||||||
fail(("duplicate module mapping at %s: %s maps to both %s and %s" %
|
|
||||||
(target.label, k, mappings[k], v)), "deps")
|
|
||||||
mappings[k] = v
|
|
||||||
if ((hasattr(ctx.rule.attr, "module_name") and ctx.rule.attr.module_name) or
|
|
||||||
(hasattr(ctx.rule.attr, "module_root") and ctx.rule.attr.module_root)):
|
|
||||||
mn = ctx.rule.attr.module_name
|
|
||||||
if not mn:
|
|
||||||
mn = target.label.name
|
|
||||||
mr = target.label.package
|
|
||||||
if target.label.workspace_root:
|
|
||||||
mr = "%s/%s" % (target.label.workspace_root, mr)
|
|
||||||
if ctx.rule.attr.module_root and ctx.rule.attr.module_root != ".":
|
|
||||||
if ctx.rule.attr.module_root.endswith(".ts"):
|
|
||||||
# This is the type-checking module mapping. Strip the trailing .d.ts
|
|
||||||
# as it doesn't belong in TypeScript's path mapping.
|
|
||||||
mr = "%s/%s" % (mr, ctx.rule.attr.module_root.replace(".d.ts", ""))
|
|
||||||
else:
|
|
||||||
mr = "%s/%s" % (mr, ctx.rule.attr.module_root)
|
|
||||||
if mn in mappings and mappings[mn] != mr:
|
|
||||||
fail(("duplicate module mapping at %s: %s maps to both %s and %s" %
|
|
||||||
(target.label, mn, mappings[mn], mr)), "deps")
|
|
||||||
mappings[mn] = mr
|
|
||||||
return struct(ng_rollup_module_mappings = mappings)
|
|
||||||
|
|
||||||
ng_rollup_module_mappings_aspect = aspect(
|
|
||||||
_ng_rollup_module_mappings_aspect_impl,
|
|
||||||
attr_aspects = ["deps"],
|
|
||||||
)
|
|
||||||
|
|
||||||
_NG_ROLLUP_BUNDLE_DEPS_ASPECTS = [esm5_outputs_aspect, ng_rollup_module_mappings_aspect, node_modules_aspect]
|
|
||||||
|
|
||||||
_NG_ROLLUP_BUNDLE_ATTRS = {
|
|
||||||
"build_optimizer": attr.bool(
|
|
||||||
doc = """Use build optimizer plugin
|
|
||||||
|
|
||||||
Only used if sources are esm5 which depends on value of esm5_sources.""",
|
|
||||||
default = True,
|
|
||||||
),
|
|
||||||
"esm5_sources": attr.bool(
|
|
||||||
doc = """Use esm5 input sources""",
|
|
||||||
default = True,
|
|
||||||
),
|
|
||||||
"srcs": attr.label_list(
|
|
||||||
doc = """JavaScript source files from the workspace.
|
|
||||||
These can use ES2015 syntax and ES Modules (import/export)""",
|
|
||||||
allow_files = True,
|
|
||||||
),
|
|
||||||
"entry_point": attr.label(
|
|
||||||
doc = """The starting point of the application, passed as the `--input` flag to rollup.
|
|
||||||
|
|
||||||
If the entry JavaScript file belongs to the same package (as the BUILD file),
|
|
||||||
you can simply reference it by its relative name to the package directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
ng_rollup_bundle(
|
|
||||||
name = "bundle",
|
|
||||||
entry_point = ":main.js",
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
You can specify the entry point as a typescript file so long as you also include
|
|
||||||
the ts_library target in deps:
|
|
||||||
|
|
||||||
```
|
|
||||||
ts_library(
|
|
||||||
name = "main",
|
|
||||||
srcs = ["main.ts"],
|
|
||||||
)
|
|
||||||
|
|
||||||
ng_rollup_bundle(
|
|
||||||
name = "bundle",
|
|
||||||
deps = [":main"]
|
|
||||||
entry_point = ":main.ts",
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
The rule will use the corresponding `.js` output of the ts_library rule as the entry point.
|
|
||||||
|
|
||||||
If the entry point target is a rule, it should produce a single JavaScript entry file that will be passed to the nodejs_binary rule.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
filegroup(
|
|
||||||
name = "entry_file",
|
|
||||||
srcs = ["main.js"],
|
|
||||||
)
|
|
||||||
|
|
||||||
ng_rollup_bundle(
|
|
||||||
name = "bundle",
|
|
||||||
entry_point = ":entry_file",
|
|
||||||
)
|
|
||||||
```
|
|
||||||
""",
|
|
||||||
mandatory = True,
|
|
||||||
allow_single_file = True,
|
|
||||||
),
|
|
||||||
"deps": attr.label_list(
|
|
||||||
doc = """Other targets that provide JavaScript files.
|
|
||||||
Typically this will be `ts_library` or `ng_module` targets.""",
|
|
||||||
aspects = _NG_ROLLUP_BUNDLE_DEPS_ASPECTS,
|
|
||||||
),
|
|
||||||
"format": attr.string(
|
|
||||||
doc = """"Specifies the format of the generated bundle. One of the following:
|
|
||||||
|
|
||||||
- `amd`: Asynchronous Module Definition, used with module loaders like RequireJS
|
|
||||||
- `cjs`: CommonJS, suitable for Node and other bundlers
|
|
||||||
- `esm`: Keep the bundle as an ES module file, suitable for other bundlers and inclusion as a `<script type=module>` tag in modern browsers
|
|
||||||
- `iife`: A self-executing function, suitable for inclusion as a `<script>` tag. (If you want to create a bundle for your application, you probably want to use this.)
|
|
||||||
- `umd`: Universal Module Definition, works as amd, cjs and iife all in one
|
|
||||||
- `system`: Native format of the SystemJS loader
|
|
||||||
""",
|
|
||||||
values = ["amd", "cjs", "esm", "iife", "umd", "system"],
|
|
||||||
default = "esm",
|
|
||||||
),
|
|
||||||
"global_name": attr.string(
|
|
||||||
doc = """A name given to this package when referenced as a global variable.
|
|
||||||
This name appears in the bundle module incantation at the beginning of the file,
|
|
||||||
and governs the global symbol added to the global context (e.g. `window`) as a side-
|
|
||||||
effect of loading the UMD/IIFE JS bundle.
|
|
||||||
|
|
||||||
Rollup doc: "The variable name, representing your iife/umd bundle, by which other scripts on the same page can access it."
|
|
||||||
|
|
||||||
This is passed to the `output.name` setting in Rollup.""",
|
|
||||||
),
|
|
||||||
"globals": attr.string_dict(
|
|
||||||
doc = """A dict of symbols that reference external scripts.
|
|
||||||
The keys are variable names that appear in the program,
|
|
||||||
and the values are the symbol to reference at runtime in a global context (UMD bundles).
|
|
||||||
For example, a program referencing @angular/core should use ng.core
|
|
||||||
as the global reference, so Angular users should include the mapping
|
|
||||||
`"@angular/core":"ng.core"` in the globals.""",
|
|
||||||
default = {},
|
|
||||||
),
|
|
||||||
"license_banner": attr.label(
|
|
||||||
doc = """A .txt file passed to the `banner` config option of rollup.
|
|
||||||
The contents of the file will be copied to the top of the resulting bundles.
|
|
||||||
Note that you can replace a version placeholder in the license file, by using
|
|
||||||
the special version `0.0.0-PLACEHOLDER`. See the section on stamping in the README.""",
|
|
||||||
allow_single_file = [".txt"],
|
|
||||||
),
|
|
||||||
"_rollup": attr.label(
|
|
||||||
executable = True,
|
|
||||||
cfg = "host",
|
|
||||||
default = Label("//dev-infra/benchmark/ng_rollup_bundle:rollup_with_build_optimizer"),
|
|
||||||
),
|
|
||||||
"_rollup_config_tmpl": attr.label(
|
|
||||||
default = Label("//dev-infra/benchmark/ng_rollup_bundle:rollup.config.js"),
|
|
||||||
allow_single_file = True,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
def _compute_node_modules_root(ctx):
|
|
||||||
"""Computes the node_modules root from the node_modules and deps attributes.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ctx: the skylark execution context
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The node_modules root as a string
|
|
||||||
"""
|
|
||||||
node_modules_root = None
|
|
||||||
for d in ctx.attr.deps:
|
|
||||||
if NpmPackageInfo in d:
|
|
||||||
possible_root = "/".join(["external", d[NpmPackageInfo].workspace, "node_modules"])
|
|
||||||
if not node_modules_root:
|
|
||||||
node_modules_root = possible_root
|
|
||||||
elif node_modules_root != possible_root:
|
|
||||||
fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (node_modules_root, possible_root))
|
|
||||||
if not node_modules_root:
|
|
||||||
# there are no fine grained deps but we still need a node_modules_root even if its empty
|
|
||||||
node_modules_root = "external/npm/node_modules"
|
|
||||||
return node_modules_root
|
|
||||||
|
|
||||||
# Avoid using non-normalized paths (workspace/../other_workspace/path)
|
|
||||||
def _to_manifest_path(ctx, file):
|
|
||||||
if file.short_path.startswith("../"):
|
|
||||||
return file.short_path[3:]
|
|
||||||
else:
|
|
||||||
return ctx.workspace_name + "/" + file.short_path
|
|
||||||
|
|
||||||
# Expand entry_point into runfiles and strip the file extension
|
|
||||||
def _esm5_entry_point_path(ctx):
|
|
||||||
return _to_manifest_path(ctx, ctx.file.entry_point)[:-(len(ctx.file.entry_point.extension) + 1)]
|
|
||||||
|
|
||||||
def _no_ext(f):
|
|
||||||
return f.short_path[:-len(f.extension) - 1]
|
|
||||||
|
|
||||||
def _resolve_js_input(f, inputs):
|
|
||||||
if f.extension == "js" or f.extension == "mjs":
|
|
||||||
return f
|
|
||||||
|
|
||||||
# look for corresponding js file in inputs
|
|
||||||
no_ext = _no_ext(f)
|
|
||||||
for i in inputs:
|
|
||||||
if i.extension == "js" or i.extension == "mjs":
|
|
||||||
if _no_ext(i) == no_ext:
|
|
||||||
return i
|
|
||||||
fail("Could not find corresponding javascript entry point for %s. Add the %s.js to your deps." % (f.path, no_ext))
|
|
||||||
|
|
||||||
def _write_rollup_config(ctx, root_dir, build_optimizer, filename = "_%s.rollup.conf.js"):
|
|
||||||
"""Generate a rollup config file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ctx: Bazel rule execution context
|
|
||||||
root_dir: root directory for module resolution
|
|
||||||
build_optimizer: whether to enable Build Optimizer plugin
|
|
||||||
filename: output filename pattern (defaults to `_%s.rollup.conf.js`)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The rollup config file. See https://rollupjs.org/guide/en#configuration-files
|
|
||||||
"""
|
|
||||||
config = ctx.actions.declare_file(filename % ctx.label.name)
|
|
||||||
|
|
||||||
mappings = dict()
|
|
||||||
all_deps = ctx.attr.deps + ctx.attr.srcs
|
|
||||||
for dep in all_deps:
|
|
||||||
if hasattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR):
|
|
||||||
for k, v in getattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR).items():
|
|
||||||
if k in mappings and mappings[k] != v:
|
|
||||||
fail(("duplicate module mapping at %s: %s maps to both %s and %s" %
|
|
||||||
(dep.label, k, mappings[k], v)), "deps")
|
|
||||||
mappings[k] = v
|
|
||||||
|
|
||||||
globals = {}
|
|
||||||
external = []
|
|
||||||
if ctx.attr.globals:
|
|
||||||
globals = ctx.attr.globals.items()
|
|
||||||
external = ctx.attr.globals.keys()
|
|
||||||
|
|
||||||
ctx.actions.expand_template(
|
|
||||||
output = config,
|
|
||||||
template = ctx.file._rollup_config_tmpl,
|
|
||||||
substitutions = {
|
|
||||||
"TMPL_banner_file": "\"%s\"" % ctx.file.license_banner.path if ctx.file.license_banner else "undefined",
|
|
||||||
"TMPL_build_optimizer": "true" if build_optimizer else "false",
|
|
||||||
"TMPL_module_mappings": str(mappings),
|
|
||||||
"TMPL_node_modules_root": _compute_node_modules_root(ctx),
|
|
||||||
"TMPL_root_dir": root_dir,
|
|
||||||
"TMPL_stamp_data": "\"%s\"" % ctx.version_file.path if ctx.version_file else "undefined",
|
|
||||||
"TMPL_workspace_name": ctx.workspace_name,
|
|
||||||
"TMPL_external": ", ".join(["'%s'" % e for e in external]),
|
|
||||||
"TMPL_globals": ", ".join(["'%s': '%s'" % g for g in globals]),
|
|
||||||
"TMPL_ivy_enabled": "true" if ctx.var.get("angular_ivy_enabled", None) == "True" else "false",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
def _filter_js_inputs(all_inputs):
|
|
||||||
all_inputs_list = all_inputs.to_list() if type(all_inputs) == type(depset()) else all_inputs
|
|
||||||
return [
|
|
||||||
f
|
|
||||||
for f in all_inputs_list
|
|
||||||
if f.path.endswith(".js") or f.path.endswith(".mjs") or f.path.endswith(".json")
|
|
||||||
]
|
|
||||||
|
|
||||||
def _run_rollup(ctx, entry_point_path, sources, config):
|
|
||||||
args = ctx.actions.args()
|
|
||||||
args.add("--config", config.path)
|
|
||||||
args.add("--input", entry_point_path)
|
|
||||||
args.add("--output.file", ctx.outputs.bundle)
|
|
||||||
args.add("--output.name", ctx.attr.global_name if ctx.attr.global_name else ctx.label.name)
|
|
||||||
args.add("--output.format", ctx.attr.format)
|
|
||||||
args.add("--output.sourcemap")
|
|
||||||
args.add("--output.sourcemapFile", ctx.outputs.sourcemap)
|
|
||||||
|
|
||||||
# We will produce errors as needed. Anything else is spammy: a well-behaved
|
|
||||||
# bazel rule prints nothing on success.
|
|
||||||
args.add("--silent")
|
|
||||||
|
|
||||||
args.add("--preserveSymlinks")
|
|
||||||
|
|
||||||
direct_inputs = [config]
|
|
||||||
|
|
||||||
# Also include files from npm fine grained deps as inputs.
|
|
||||||
# These deps are identified by the NpmPackageInfo provider.
|
|
||||||
for d in ctx.attr.deps:
|
|
||||||
if NpmPackageInfo in d:
|
|
||||||
# Note: we can't avoid calling .to_list() on sources
|
|
||||||
direct_inputs.extend(_filter_js_inputs(d[NpmPackageInfo].sources.to_list()))
|
|
||||||
|
|
||||||
if ctx.file.license_banner:
|
|
||||||
direct_inputs.append(ctx.file.license_banner)
|
|
||||||
if ctx.version_file:
|
|
||||||
direct_inputs.append(ctx.version_file)
|
|
||||||
|
|
||||||
ctx.actions.run(
|
|
||||||
progress_message = "Bundling JavaScript %s [rollup]" % ctx.outputs.bundle.short_path,
|
|
||||||
executable = ctx.executable._rollup,
|
|
||||||
inputs = depset(direct_inputs, transitive = [sources]),
|
|
||||||
outputs = [ctx.outputs.bundle, ctx.outputs.sourcemap],
|
|
||||||
arguments = [args],
|
|
||||||
)
|
|
||||||
|
|
||||||
def _ng_rollup_bundle_impl(ctx):
|
|
||||||
if ctx.attr.esm5_sources:
|
|
||||||
# Use esm5 sources and build optimzier if ctx.attr.build_optimizer is set
|
|
||||||
rollup_config = _write_rollup_config(ctx, build_optimizer = ctx.attr.build_optimizer, root_dir = "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]))
|
|
||||||
_run_rollup(ctx, _esm5_entry_point_path(ctx), flatten_esm5(ctx), rollup_config)
|
|
||||||
else:
|
|
||||||
# Use esm2015 sources and no build optimzier
|
|
||||||
rollup_config = _write_rollup_config(ctx, build_optimizer = False, root_dir = ctx.bin_dir.path)
|
|
||||||
esm2015_files_depsets = []
|
|
||||||
for dep in ctx.attr.deps:
|
|
||||||
if JSEcmaScriptModuleInfo in dep:
|
|
||||||
esm2015_files_depsets.append(dep[JSEcmaScriptModuleInfo].sources)
|
|
||||||
esm2015_files = depset(transitive = esm2015_files_depsets)
|
|
||||||
entry_point_path = _to_manifest_path(ctx, _resolve_js_input(ctx.file.entry_point, esm2015_files.to_list()))
|
|
||||||
_run_rollup(ctx, entry_point_path, esm2015_files, rollup_config)
|
|
||||||
|
|
||||||
return DefaultInfo(files = depset([ctx.outputs.bundle, ctx.outputs.sourcemap]))
|
|
||||||
|
|
||||||
_ng_rollup_bundle = rule(
|
|
||||||
implementation = _ng_rollup_bundle_impl,
|
|
||||||
attrs = _NG_ROLLUP_BUNDLE_ATTRS,
|
|
||||||
outputs = _NG_ROLLUP_BUNDLE_OUTPUTS,
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
Run [Rollup] with the [Build Optimizer] plugin and use esm5 inputs.
|
|
||||||
|
|
||||||
[Rollup]: https://rollupjs.org/
|
|
||||||
[Build Optimizer]: https://www.npmjs.com/package/@angular-devkit/build-optimizer
|
|
||||||
"""
|
|
||||||
|
|
||||||
def ng_rollup_bundle(name, **kwargs):
|
|
||||||
"""Rollup with Build Optimizer on esm5 inputs.
|
|
||||||
|
|
||||||
This provides a variant of the [legacy rollup_bundle] rule that works better for Angular apps.
|
|
||||||
|
|
||||||
Runs [rollup], [terser_minified] and [brotli] to produce a number of output bundles.
|
Runs [rollup], [terser_minified] and [brotli] to produce a number of output bundles.
|
||||||
|
|
||||||
es5 : "%{name}.js"
|
es2015 : "%{name}.js"
|
||||||
es5 minified : "%{name}.min.js"
|
es2015 minified : "%{name}.min.js"
|
||||||
es5 minified (compressed) : "%{name}.min.js.br",
|
es2015 minified (compressed) : "%{name}.min.js.br",
|
||||||
es5 minified (debug) : "%{name}.min_debug.js"
|
es2015 minified (debug) : "%{name}.min_debug.js"
|
||||||
es2015 : "%{name}.es2015.js"
|
|
||||||
es2015 minified : "%{name}.min.es2015.js"
|
|
||||||
es2015 minified (compressed) : "%{name}.min.js.es2015.br",
|
|
||||||
es2015 minified (debug) : "%{name}.min_debug.es2015.js"
|
|
||||||
|
|
||||||
It registers `@angular-devkit/build-optimizer` as a rollup plugin, to get
|
It registers `@angular-devkit/build-optimizer` as a rollup plugin by default. This helps
|
||||||
better optimization. It also uses ESM5 format inputs, as this is what
|
with further optimization. See https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_optimizer.
|
||||||
build-optimizer is hard-coded to look for and transform.
|
|
||||||
|
|
||||||
[legacy rollup_bundle]: https://github.com/bazelbuild/rules_nodejs/blob/0.38.3/internal/rollup/rollup_bundle.bzl
|
[rollup_bundle]: https://github.com/bazelbuild/rules_nodejs/blob/1.x/packages/rollup/src/rollup_bundle.bzl
|
||||||
[rollup]: https://rollupjs.org/guide/en/
|
[rollup]: https://rollupjs.org/guide/en/
|
||||||
[terser_minified]: https://bazelbuild.github.io/rules_nodejs/Terser.html
|
[terser_minified]: https://bazelbuild.github.io/rules_nodejs/Terser.html
|
||||||
[brotli]: https://brotli.org/
|
[brotli]: https://brotli.org/
|
||||||
"""
|
"""
|
||||||
format = kwargs.pop("format", "iife")
|
|
||||||
build_optimizer = kwargs.pop("build_optimizer", True)
|
|
||||||
visibility = kwargs.pop("visibility", None)
|
|
||||||
|
|
||||||
# Common arguments for all terser_minified targets
|
config_data = [license_banner] if license_banner else []
|
||||||
common_terser_args = {
|
|
||||||
# As of terser 4.3.4 license comments are preserved by default. See
|
expand_template(
|
||||||
# https://github.com/terser/terser/blob/master/CHANGELOG.md. We want to
|
name = "%s_rollup_config" % name,
|
||||||
# maintain the comments off behavior. We pass the --comments flag with
|
template = "//dev-infra/benchmark/ng_rollup_bundle:rollup.config-tmpl.js",
|
||||||
# a regex that always evaluates to false to do this.
|
output_name = "%s_rollup_config.js" % name,
|
||||||
"args": ["--comments", "/bogus_string_to_suppress_all_comments^/"],
|
configuration_env_vars = ["angular_ivy_enabled"],
|
||||||
|
data = config_data,
|
||||||
|
substitutions = {
|
||||||
|
"TMPL_build_optimizer": "true" if build_optimizer else "false",
|
||||||
|
"TMPL_banner_file": "\"$(execpath %s)\"" % license_banner if license_banner else "undefined",
|
||||||
|
"TMPL_external": ", ".join(["'%s'" % e for e in globals.keys()]),
|
||||||
|
"TMPL_globals": ", ".join(["'%s': '%s'" % (g, g) for g in globals]),
|
||||||
|
},
|
||||||
|
visibility = visibility,
|
||||||
|
)
|
||||||
|
|
||||||
|
rollup_bundle(
|
||||||
|
name = name,
|
||||||
|
config_file = "%s_rollup_config" % name,
|
||||||
|
entry_points = {
|
||||||
|
(entry_point): name,
|
||||||
|
},
|
||||||
|
visibility = visibility,
|
||||||
|
deps = config_data + deps + [
|
||||||
|
"@npm//rollup-plugin-node-resolve",
|
||||||
|
"@npm//rollup-plugin-sourcemaps",
|
||||||
|
"@npm//rollup-plugin-commonjs",
|
||||||
|
"@npm//@angular-devkit/build-optimizer",
|
||||||
|
],
|
||||||
|
silent = True,
|
||||||
|
format = format,
|
||||||
|
sourcemap = "true",
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
common_terser_options = {
|
||||||
|
"visibility": visibility,
|
||||||
"config_file": "//dev-infra/benchmark/ng_rollup_bundle:terser_config.json",
|
"config_file": "//dev-infra/benchmark/ng_rollup_bundle:terser_config.json",
|
||||||
|
# TODO: Enable source maps for better debugging when `@bazel/terser` pre-declares
|
||||||
|
# JS and map outputs. Tracked with: DEV-120
|
||||||
"sourcemap": False,
|
"sourcemap": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO(gregmagolan): reduce this macro to just use the new @bazel/rollup rollup_bundle
|
terser_minified(name = name + ".min", src = name + ".js", **common_terser_options)
|
||||||
# once esm5 inputs are no longer needed. _ng_rollup_bundle is just here for esm5 support
|
|
||||||
# and once that requirement is removed for Angular 10 then there is nothing that rule is doing
|
|
||||||
# that the new @bazel/rollup rollup_bundle rule can't do.
|
|
||||||
_ng_rollup_bundle(
|
|
||||||
name = name,
|
|
||||||
build_optimizer = build_optimizer,
|
|
||||||
format = format,
|
|
||||||
visibility = visibility,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
terser_minified(name = name + ".min", src = name, visibility = visibility, **common_terser_args)
|
|
||||||
native.filegroup(name = name + ".min.js", srcs = [name + ".min"], visibility = visibility)
|
native.filegroup(name = name + ".min.js", srcs = [name + ".min"], visibility = visibility)
|
||||||
terser_minified(name = name + ".min_debug", src = name, debug = True, visibility = visibility, **common_terser_args)
|
terser_minified(name = name + ".min_debug", src = name + ".js", debug = True, **common_terser_options)
|
||||||
native.filegroup(name = name + ".min_debug.js", srcs = [name + ".min_debug"], visibility = visibility)
|
native.filegroup(name = name + ".min_debug.js", srcs = [name + ".min_debug"], visibility = visibility)
|
||||||
|
|
||||||
npm_package_bin(
|
npm_package_bin(
|
||||||
name = "_%s_brotli" % name,
|
name = "_%s_brotli" % name,
|
||||||
tool = "//dev-infra/benchmark/brotli-cli",
|
tool = "//dev-infra/benchmark/brotli-cli",
|
||||||
@ -422,50 +98,3 @@ def ng_rollup_bundle(name, **kwargs):
|
|||||||
],
|
],
|
||||||
visibility = visibility,
|
visibility = visibility,
|
||||||
)
|
)
|
||||||
|
|
||||||
_ng_rollup_bundle(
|
|
||||||
name = name + ".es2015",
|
|
||||||
esm5_sources = False,
|
|
||||||
format = format,
|
|
||||||
visibility = visibility,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
terser_minified(name = name + ".min.es2015", src = name + ".es2015", visibility = visibility, **common_terser_args)
|
|
||||||
native.filegroup(name = name + ".min.es2015.js", srcs = [name + ".min.es2015"], visibility = visibility)
|
|
||||||
terser_minified(name = name + ".min_debug.es2015", src = name + ".es2015", debug = True, visibility = visibility, **common_terser_args)
|
|
||||||
native.filegroup(name = name + ".min_debug.es2015.js", srcs = [name + ".min_debug.es2015"], visibility = visibility)
|
|
||||||
npm_package_bin(
|
|
||||||
name = "_%s_es2015_brotli" % name,
|
|
||||||
tool = "//dev-infra/benchmark/brotli-cli",
|
|
||||||
data = [name + ".min.es2015.js"],
|
|
||||||
outs = [name + ".min.es2015.js.br"],
|
|
||||||
args = [
|
|
||||||
"--output=$(execpath %s.min.es2015.js.br)" % name,
|
|
||||||
"$(execpath %s.min.es2015.js)" % name,
|
|
||||||
],
|
|
||||||
visibility = visibility,
|
|
||||||
)
|
|
||||||
|
|
||||||
def ls_rollup_bundle(name, **kwargs):
|
|
||||||
"""A variant of ng_rollup_bundle for the language-service bundle
|
|
||||||
|
|
||||||
ls_rollup_bundle uses esm5 inputs, outputs AMD and does not use the build optimizer.
|
|
||||||
"""
|
|
||||||
visibility = kwargs.pop("visibility", None)
|
|
||||||
|
|
||||||
# Note: the output file is called "umd.js" because of historical reasons.
|
|
||||||
# The format is actually AMD and not UMD, but we are afraid to rename
|
|
||||||
# the file because that would likely break the IDE and other integrations that
|
|
||||||
# have the path hardcoded in them.
|
|
||||||
ng_rollup_bundle(
|
|
||||||
name = name + ".umd",
|
|
||||||
build_optimizer = False,
|
|
||||||
format = "amd",
|
|
||||||
visibility = visibility,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
native.alias(
|
|
||||||
name = name,
|
|
||||||
actual = name + ".umd",
|
|
||||||
visibility = visibility,
|
|
||||||
)
|
|
||||||
|
89
dev-infra/benchmark/ng_rollup_bundle/rollup.config-tmpl.js
Normal file
89
dev-infra/benchmark/ng_rollup_bundle/rollup.config-tmpl.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Rollup configuration
|
||||||
|
// GENERATED BY Bazel
|
||||||
|
|
||||||
|
const buildOptimizer =
|
||||||
|
require('@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js');
|
||||||
|
const nodeResolve = require('rollup-plugin-node-resolve');
|
||||||
|
const sourcemaps = require('rollup-plugin-sourcemaps');
|
||||||
|
const commonjs = require('rollup-plugin-commonjs');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
function log_verbose(...m) {
|
||||||
|
// This is a template file so we use __filename to output the actual filename
|
||||||
|
if (!!process.env['VERBOSE_LOGS']) console.error(`[${path.basename(__filename)}]`, ...m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substitutions from the `ng_rollup_bundle` macro. We want to conditionally toggle
|
||||||
|
// build optimizer, support optional banner files, and generally respect the current
|
||||||
|
// compilation mode (i.e. Ivy or View Engine) as that affects module resolution.
|
||||||
|
const useBuildOptimizer = TMPL_build_optimizer;
|
||||||
|
const bannerFile = TMPL_banner_file;
|
||||||
|
const ivyEnabled = 'TMPL_angular_ivy_enabled' === 'True';
|
||||||
|
// `bazel_stamp_file` is a substitution that is applied by `@bazel/rollup`.
|
||||||
|
const stampDataFile = bazel_stamp_file;
|
||||||
|
|
||||||
|
log_verbose(`running with
|
||||||
|
cwd: ${process.cwd()}
|
||||||
|
useBuildOptimizer: ${useBuildOptimizer}
|
||||||
|
bannerFile: ${bannerFile}
|
||||||
|
stampDataFile: ${stampDataFile}
|
||||||
|
ivyEnabled: ${ivyEnabled}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
nodeResolve({
|
||||||
|
// If Ivy is enabled, we need to make sure that the module resolution prioritizes ngcc
|
||||||
|
// processed entry-point fields. Ngcc adds special fields to `package.json` files of
|
||||||
|
// modules that have been processed. Prioritizing these fields matches the Angular CLIs
|
||||||
|
// behavior for supporting Ivy. We need to support ngcc because `ng_rollup_bundle` rule is
|
||||||
|
// shared with other repositories that consume Angular from NPM (w/ ngcc).
|
||||||
|
// https://github.com/angular/angular-cli/blob/1a1ceb609b9a87c4021cce3a6f0fc6d167cd09d2/packages/ngtools/webpack/src/angular_compiler_plugin.ts#L918-L920
|
||||||
|
mainFields: ivyEnabled ? ['module_ivy_ngcc', 'main_ivy_ngcc', 'module', 'main'] :
|
||||||
|
['module', 'main'],
|
||||||
|
}),
|
||||||
|
commonjs({ignoreGlobal: true}),
|
||||||
|
sourcemaps(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (useBuildOptimizer) {
|
||||||
|
plugins.unshift(buildOptimizer.default({
|
||||||
|
sideEffectFreeModules: [],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
plugins,
|
||||||
|
external: [TMPL_external],
|
||||||
|
output: {
|
||||||
|
globals: {TMPL_globals},
|
||||||
|
banner: extractBannerIfConfigured(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Extracts the top-level bundle banner if specified. */
|
||||||
|
function extractBannerIfConfigured() {
|
||||||
|
if (!bannerFile) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
let banner = fs.readFileSync(bannerFile, 'utf8');
|
||||||
|
if (stampDataFile) {
|
||||||
|
const versionTag = fs.readFileSync(stampDataFile, 'utf8')
|
||||||
|
.split('\n')
|
||||||
|
.find(s => s.startsWith('BUILD_SCM_VERSION'));
|
||||||
|
// Don't assume BUILD_SCM_VERSION exists
|
||||||
|
if (versionTag) {
|
||||||
|
const version = versionTag.split(' ')[1].trim();
|
||||||
|
banner = banner.replace(/0.0.0-PLACEHOLDER/, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return banner;
|
||||||
|
}
|
@ -1,212 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Rollup configuration
|
|
||||||
// GENERATED BY Bazel
|
|
||||||
|
|
||||||
const buildOptimizer = require(
|
|
||||||
'npm/node_modules/@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js');
|
|
||||||
const nodeResolve = require('rollup-plugin-node-resolve');
|
|
||||||
const sourcemaps = require('rollup-plugin-sourcemaps');
|
|
||||||
const commonjs = require('rollup-plugin-commonjs');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
function log_verbose(...m) {
|
|
||||||
// This is a template file so we use __filename to output the actual filename
|
|
||||||
if (!!process.env['VERBOSE_LOGS']) console.error(`[${path.basename(__filename)}]`, ...m);
|
|
||||||
}
|
|
||||||
|
|
||||||
const workspaceName = 'TMPL_workspace_name';
|
|
||||||
const useBuildOptimzier = TMPL_build_optimizer;
|
|
||||||
const rootDir = 'TMPL_root_dir';
|
|
||||||
const bannerFile = TMPL_banner_file;
|
|
||||||
const stampData = TMPL_stamp_data;
|
|
||||||
const moduleMappings = TMPL_module_mappings;
|
|
||||||
const nodeModulesRoot = 'TMPL_node_modules_root';
|
|
||||||
const ivyEnabled = TMPL_ivy_enabled;
|
|
||||||
|
|
||||||
log_verbose(`running with
|
|
||||||
cwd: ${process.cwd()}
|
|
||||||
workspaceName: ${workspaceName}
|
|
||||||
useBuildOptimzier: ${useBuildOptimzier}
|
|
||||||
rootDir: ${rootDir}
|
|
||||||
bannerFile: ${bannerFile}
|
|
||||||
stampData: ${stampData}
|
|
||||||
moduleMappings: ${JSON.stringify(moduleMappings)}
|
|
||||||
nodeModulesRoot: ${nodeModulesRoot}
|
|
||||||
ivyEnabled: ${ivyEnabled}
|
|
||||||
`);
|
|
||||||
|
|
||||||
function fileExists(filePath) {
|
|
||||||
try {
|
|
||||||
return fs.statSync(filePath).isFile();
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This resolver mimics the TypeScript Path Mapping feature, which lets us resolve
|
|
||||||
// modules based on a mapping of short names to paths.
|
|
||||||
function resolveBazel(
|
|
||||||
importee, importer, baseDir = process.cwd(), resolve = require.resolve, root = rootDir) {
|
|
||||||
log_verbose(`resolving '${importee}' from ${importer}`);
|
|
||||||
|
|
||||||
function resolveInRootDir(importee) {
|
|
||||||
function tryImportee(importee) {
|
|
||||||
var candidate = path.join(baseDir, root, importee);
|
|
||||||
log_verbose(`try to resolve '${importee}' at '${candidate}'`);
|
|
||||||
try {
|
|
||||||
var result = resolve(candidate);
|
|
||||||
return result;
|
|
||||||
} catch (e) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Attempt in the following order {importee}.mjs, {importee}/index.mjs,
|
|
||||||
// {importee}, {importee}.js, {importee}/index.js. If an .mjs file is
|
|
||||||
// available it should be resolved as rollup cannot handle the .js files
|
|
||||||
// generated by ts_library as they are not esm. When rolling up esm5 files
|
|
||||||
// these are re-rooted so it is not an issue.
|
|
||||||
// TODO(gregmagolan): clean this up in the future as the .mjs es2015 outputs
|
|
||||||
// along side the .js es5 outputs from ts_library creates this unusual situation for
|
|
||||||
// which we can't rely on standard node module resolution to do the right thing.
|
|
||||||
// In the future ts_library (or equivalent) should only produce a single flavor of
|
|
||||||
// output and ng_rollup_bundle should also just use the use the vanilla rollup_bundle
|
|
||||||
// rule without the need for a custom bazel resolver.
|
|
||||||
return tryImportee(`${importee}.mjs`) || tryImportee(`${importee}/index.mjs`) ||
|
|
||||||
tryImportee(importee) || tryImportee(`${importee}.js`) ||
|
|
||||||
tryImportee(`${importee}/index.js`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since mappings are always in POSIX paths, when comparing the importee to mappings
|
|
||||||
// we should normalize the importee.
|
|
||||||
// Having it normalized is also useful to determine relative paths.
|
|
||||||
const normalizedImportee = importee.replace(/\\/g, '/');
|
|
||||||
|
|
||||||
// If import is fully qualified then resolve it directly
|
|
||||||
if (fileExists(importee)) {
|
|
||||||
log_verbose(`resolved fully qualified '${importee}'`);
|
|
||||||
return importee;
|
|
||||||
}
|
|
||||||
|
|
||||||
var resolved;
|
|
||||||
if (normalizedImportee.startsWith('./') || normalizedImportee.startsWith('../')) {
|
|
||||||
// relative import
|
|
||||||
if (importer) {
|
|
||||||
let importerRootRelative = path.dirname(importer);
|
|
||||||
const relative = path.relative(path.join(baseDir, root), importerRootRelative);
|
|
||||||
if (!relative.startsWith('.')) {
|
|
||||||
importerRootRelative = relative;
|
|
||||||
}
|
|
||||||
resolved = path.join(importerRootRelative, importee);
|
|
||||||
} else {
|
|
||||||
throw new Error('cannot resolve relative paths without an importer');
|
|
||||||
}
|
|
||||||
if (resolved) resolved = resolveInRootDir(resolved);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resolved) {
|
|
||||||
// possible workspace import or external import if importee matches a module
|
|
||||||
// mapping
|
|
||||||
for (const k in moduleMappings) {
|
|
||||||
if (normalizedImportee == k || normalizedImportee.startsWith(k + '/')) {
|
|
||||||
// replace the root module name on a mappings match
|
|
||||||
// note that the module_root attribute is intended to be used for type-checking
|
|
||||||
// so it uses eg. "index.d.ts". At runtime, we have only index.js, so we strip the
|
|
||||||
// .d.ts suffix and let node require.resolve do its thing.
|
|
||||||
var v = moduleMappings[k].replace(/\.d\.ts$/, '');
|
|
||||||
const mappedImportee = path.join(v, normalizedImportee.slice(k.length + 1));
|
|
||||||
log_verbose(`module mapped '${importee}' to '${mappedImportee}'`);
|
|
||||||
resolved = resolveInRootDir(mappedImportee);
|
|
||||||
if (resolved) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resolved) {
|
|
||||||
// workspace import
|
|
||||||
const userWorkspacePath = path.relative(workspaceName, importee);
|
|
||||||
resolved = resolveInRootDir(userWorkspacePath.startsWith('..') ? importee : userWorkspacePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolved) {
|
|
||||||
log_verbose(`resolved to ${resolved}`);
|
|
||||||
} else {
|
|
||||||
log_verbose(`allowing rollup to resolve '${importee}' with node module resolution`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolved;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We make mainFields match what was the default for plugin-node-resolve <4.2.0
|
|
||||||
// when mainFields was introduced. Resolving to 'browser' or 'es2015' first breaks
|
|
||||||
// some of the benchmarks such as `//modules/benchmarks/src/expanding_rows:perf_chromium-local`.
|
|
||||||
// See https://app.circleci.com/jobs/github/angular/angular/507444 &&
|
|
||||||
// https://app.circleci.com/jobs/github/angular/angular/507442 for affected tests.
|
|
||||||
const mainFields = ['module', 'main'];
|
|
||||||
const ngccMainFields = mainFields.map(f => `${f}_ivy_ngcc`);
|
|
||||||
|
|
||||||
let plugins = [
|
|
||||||
{
|
|
||||||
name: 'resolveBazel',
|
|
||||||
resolveId: resolveBazel,
|
|
||||||
},
|
|
||||||
nodeResolve({
|
|
||||||
// If Ivy is enabled, we need to make sure that the module resolution prioritizes ngcc
|
|
||||||
// processed entry-point fields. Ngcc adds special fields to `package.json` files of
|
|
||||||
// modules that have been processed. Prioritizing these fields matches the Angular CLIs
|
|
||||||
// behavior for supporting Ivy. We need to support ngcc because `ng_rollup_bundle` rule is
|
|
||||||
// shared with other repositories that consume Angular from NPM (w/ ngcc).
|
|
||||||
// https://github.com/angular/angular-cli/blob/1a1ceb609b9a87c4021cce3a6f0fc6d167cd09d2/packages/ngtools/webpack/src/angular_compiler_plugin.ts#L918-L920
|
|
||||||
mainFields: ivyEnabled ? [...ngccMainFields, ...mainFields] : mainFields,
|
|
||||||
jail: process.cwd(),
|
|
||||||
customResolveOptions: {moduleDirectory: nodeModulesRoot}
|
|
||||||
}),
|
|
||||||
commonjs({ignoreGlobal: true}),
|
|
||||||
sourcemaps(),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (useBuildOptimzier) {
|
|
||||||
plugins = [
|
|
||||||
buildOptimizer.default({
|
|
||||||
sideEffectFreeModules: [
|
|
||||||
'.esm5/packages/core/src',
|
|
||||||
'.esm5/packages/common/src',
|
|
||||||
'.esm5/packages/compiler/src',
|
|
||||||
'.esm5/packages/platform-browser/src',
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
].concat(plugins);
|
|
||||||
}
|
|
||||||
|
|
||||||
let banner = '';
|
|
||||||
if (bannerFile) {
|
|
||||||
banner = fs.readFileSync(bannerFile, {encoding: 'utf-8'});
|
|
||||||
if (stampData) {
|
|
||||||
const versionTag = fs.readFileSync(stampData, {encoding: 'utf-8'})
|
|
||||||
.split('\n')
|
|
||||||
.find(s => s.startsWith('BUILD_SCM_VERSION'));
|
|
||||||
// Don't assume BUILD_SCM_VERSION exists
|
|
||||||
if (versionTag) {
|
|
||||||
const version = versionTag.split(' ')[1].trim();
|
|
||||||
banner = banner.replace(/0.0.0-PLACEHOLDER/, version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
plugins,
|
|
||||||
external: [TMPL_external],
|
|
||||||
output: {
|
|
||||||
globals: {TMPL_globals},
|
|
||||||
banner,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = config;
|
|
@ -1,12 +1,18 @@
|
|||||||
{
|
{
|
||||||
"compress": {
|
"output": {
|
||||||
"global_defs": {"ngDevMode": false, "ngI18nClosureMode": false, "ngJitMode": false},
|
"ecma": "es2015",
|
||||||
"keep_fnames": "bazel_no_debug",
|
"comments": false,
|
||||||
"passes": 3,
|
"beautify": "bazel_debug"
|
||||||
"pure_getters": true,
|
|
||||||
"reduce_funcs": "bazel_no_debug",
|
|
||||||
"reduce_vars": "bazel_no_debug",
|
|
||||||
"sequences": "bazel_no_debug"
|
|
||||||
},
|
},
|
||||||
|
"compress": {
|
||||||
|
"global_defs": {
|
||||||
|
"ngDevMode": false,
|
||||||
|
"ngI18nClosureMode": false,
|
||||||
|
"ngJitMode": false
|
||||||
|
},
|
||||||
|
"passes": 3,
|
||||||
|
"pure_getters": true
|
||||||
|
},
|
||||||
|
"toplevel": true,
|
||||||
"mangle": "bazel_no_debug"
|
"mangle": "bazel_no_debug"
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ import {assertNoErrors, getConfig, NgDevConfig} from '../utils/config';
|
|||||||
export interface CommitMessageConfig {
|
export interface CommitMessageConfig {
|
||||||
maxLineLength: number;
|
maxLineLength: number;
|
||||||
minBodyLength: number;
|
minBodyLength: number;
|
||||||
|
minBodyLengthTypeExcludes?: string[];
|
||||||
types: string[];
|
types: string[];
|
||||||
scopes: string[];
|
scopes: string[];
|
||||||
}
|
}
|
||||||
@ -19,7 +20,7 @@ export interface CommitMessageConfig {
|
|||||||
export function getCommitMessageConfig() {
|
export function getCommitMessageConfig() {
|
||||||
// List of errors encountered validating the config.
|
// List of errors encountered validating the config.
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
// The unvalidated config object.
|
// The non-validated config object.
|
||||||
const config: Partial<NgDevConfig<{commitMessage: CommitMessageConfig}>> = getConfig();
|
const config: Partial<NgDevConfig<{commitMessage: CommitMessageConfig}>> = getConfig();
|
||||||
|
|
||||||
if (config.commitMessage === undefined) {
|
if (config.commitMessage === undefined) {
|
||||||
|
@ -10,19 +10,22 @@
|
|||||||
import * as validateConfig from './config';
|
import * as validateConfig from './config';
|
||||||
import {validateCommitMessage} from './validate';
|
import {validateCommitMessage} from './validate';
|
||||||
|
|
||||||
|
type CommitMessageConfig = validateConfig.CommitMessageConfig;
|
||||||
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const config = {
|
const config: {commitMessage: CommitMessageConfig} = {
|
||||||
'commitMessage': {
|
commitMessage: {
|
||||||
'maxLineLength': 120,
|
maxLineLength: 120,
|
||||||
'minBodyLength': 0,
|
minBodyLength: 0,
|
||||||
'types': [
|
types: [
|
||||||
'feat',
|
'feat',
|
||||||
'fix',
|
'fix',
|
||||||
'refactor',
|
'refactor',
|
||||||
'release',
|
'release',
|
||||||
'style',
|
'style',
|
||||||
],
|
],
|
||||||
'scopes': [
|
scopes: [
|
||||||
'common',
|
'common',
|
||||||
'compiler',
|
'compiler',
|
||||||
'core',
|
'core',
|
||||||
@ -224,5 +227,42 @@ describe('validate-commit-message.js', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('minBodyLength', () => {
|
||||||
|
const minBodyLengthConfig: {commitMessage: CommitMessageConfig} = {
|
||||||
|
commitMessage: {
|
||||||
|
maxLineLength: 120,
|
||||||
|
minBodyLength: 30,
|
||||||
|
minBodyLengthTypeExcludes: ['docs'],
|
||||||
|
types: ['fix', 'docs'],
|
||||||
|
scopes: ['core']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
(validateConfig.getCommitMessageConfig as jasmine.Spy).and.returnValue(minBodyLengthConfig);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail validation if the body is shorter than `minBodyLength`', () => {
|
||||||
|
expect(validateCommitMessage(
|
||||||
|
'fix(core): something\n\n Explanation of the motivation behind this change'))
|
||||||
|
.toBe(VALID);
|
||||||
|
expect(validateCommitMessage('fix(core): something\n\n too short')).toBe(INVALID);
|
||||||
|
expect(lastError).toContain(
|
||||||
|
'The commit message body does not meet the minimum length of 30 characters');
|
||||||
|
expect(validateCommitMessage('fix(core): something')).toBe(INVALID);
|
||||||
|
expect(lastError).toContain(
|
||||||
|
'The commit message body does not meet the minimum length of 30 characters');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pass validation if the body is shorter than `minBodyLength` but the commit type is in the `minBodyLengthTypeExclusions` list',
|
||||||
|
() => {
|
||||||
|
expect(validateCommitMessage('docs: just fixing a typo')).toBe(VALID);
|
||||||
|
expect(validateCommitMessage('docs(core): just fixing a typo')).toBe(VALID);
|
||||||
|
expect(validateCommitMessage(
|
||||||
|
'docs(core): just fixing a typo\n\nThis was just a silly typo.'))
|
||||||
|
.toBe(VALID);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -148,7 +148,8 @@ export function validateCommitMessage(
|
|||||||
// Checking commit body //
|
// Checking commit body //
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
||||||
if (commit.bodyWithoutLinking.trim().length < config.minBodyLength) {
|
if (!config.minBodyLengthTypeExcludes?.includes(commit.type) &&
|
||||||
|
commit.bodyWithoutLinking.trim().length < config.minBodyLength) {
|
||||||
printError(`The commit message body does not meet the minimum length of ${
|
printError(`The commit message body does not meet the minimum length of ${
|
||||||
config.minBodyLength} characters`);
|
config.minBodyLength} characters`);
|
||||||
return false;
|
return false;
|
||||||
@ -157,7 +158,7 @@ export function validateCommitMessage(
|
|||||||
const bodyByLine = commit.body.split('\n');
|
const bodyByLine = commit.body.split('\n');
|
||||||
if (bodyByLine.some(line => line.length > config.maxLineLength)) {
|
if (bodyByLine.some(line => line.length > config.maxLineLength)) {
|
||||||
printError(
|
printError(
|
||||||
`The commit messsage body contains lines greater than ${config.maxLineLength} characters`);
|
`The commit message body contains lines greater than ${config.maxLineLength} characters`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ export async function discoverNewConflictsForPr(
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The active github branch when the run began. */
|
/** The active github branch or revision before we performed any Git commands. */
|
||||||
const originalBranch = git.getCurrentBranch();
|
const previousBranchOrRevision = git.getCurrentBranchOrRevision();
|
||||||
/* Progress bar to indicate progress. */
|
/* Progress bar to indicate progress. */
|
||||||
const progressBar = new Bar({format: `[{bar}] ETA: {eta}s | {value}/{total}`});
|
const progressBar = new Bar({format: `[{bar}] ETA: {eta}s | {value}/{total}`});
|
||||||
/* PRs which were found to be conflicting. */
|
/* PRs which were found to be conflicting. */
|
||||||
@ -103,7 +103,7 @@ export async function discoverNewConflictsForPr(
|
|||||||
const result = exec(`git rebase FETCH_HEAD`);
|
const result = exec(`git rebase FETCH_HEAD`);
|
||||||
if (result.code) {
|
if (result.code) {
|
||||||
error('The requested PR currently has conflicts');
|
error('The requested PR currently has conflicts');
|
||||||
cleanUpGitState(originalBranch);
|
cleanUpGitState(previousBranchOrRevision);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ export async function discoverNewConflictsForPr(
|
|||||||
info();
|
info();
|
||||||
info(`Result:`);
|
info(`Result:`);
|
||||||
|
|
||||||
cleanUpGitState(originalBranch);
|
cleanUpGitState(previousBranchOrRevision);
|
||||||
|
|
||||||
// If no conflicts are found, exit successfully.
|
// If no conflicts are found, exit successfully.
|
||||||
if (conflicts.length === 0) {
|
if (conflicts.length === 0) {
|
||||||
@ -147,14 +147,14 @@ export async function discoverNewConflictsForPr(
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reset git back to the provided branch. */
|
/** Reset git back to the provided branch or revision. */
|
||||||
export function cleanUpGitState(branch: string) {
|
export function cleanUpGitState(previousBranchOrRevision: string) {
|
||||||
// Ensure that any outstanding rebases are aborted.
|
// Ensure that any outstanding rebases are aborted.
|
||||||
exec(`git rebase --abort`);
|
exec(`git rebase --abort`);
|
||||||
// Ensure that any changes in the current repo state are cleared.
|
// Ensure that any changes in the current repo state are cleared.
|
||||||
exec(`git reset --hard`);
|
exec(`git reset --hard`);
|
||||||
// Checkout the original branch from before the run began.
|
// Checkout the original branch from before the run began.
|
||||||
exec(`git checkout ${branch}`);
|
exec(`git checkout ${previousBranchOrRevision}`);
|
||||||
// Delete the generated branch.
|
// Delete the generated branch.
|
||||||
exec(`git branch -D ${tempWorkingBranch}`);
|
exec(`git branch -D ${tempWorkingBranch}`);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,8 @@ export interface MergeConfig {
|
|||||||
claSignedLabel: string|RegExp;
|
claSignedLabel: string|RegExp;
|
||||||
/** Pattern that matches labels which imply a merge ready pull request. */
|
/** Pattern that matches labels which imply a merge ready pull request. */
|
||||||
mergeReadyLabel: string|RegExp;
|
mergeReadyLabel: string|RegExp;
|
||||||
|
/** Label that is applied when special attention from the caretaker is required. */
|
||||||
|
caretakerNoteLabel?: string|RegExp;
|
||||||
/** Label which can be applied to fixup commit messages in the merge script. */
|
/** Label which can be applied to fixup commit messages in the merge script. */
|
||||||
commitMessageFixupLabel: string|RegExp;
|
commitMessageFixupLabel: string|RegExp;
|
||||||
/**
|
/**
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user