Compare commits
235 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
80073944a1 | ||
![]() |
a2aa45d3c7 | ||
![]() |
0731c7f634 | ||
![]() |
cf2d40e359 | ||
![]() |
0c47b7184c | ||
![]() |
752100487b | ||
![]() |
7a183c9920 | ||
![]() |
eac35a64e1 | ||
![]() |
0348f47f62 | ||
![]() |
79da3e8cd2 | ||
![]() |
67b431603a | ||
![]() |
604bd6e1cb | ||
![]() |
fdf572b3c5 | ||
![]() |
f6936406ca | ||
![]() |
a4909d6aa0 | ||
![]() |
600af0a5f6 | ||
![]() |
a0fcc0b839 | ||
![]() |
cf6efd91ae | ||
![]() |
ee02855bd5 | ||
![]() |
53fd049d12 | ||
![]() |
a025e98ede | ||
![]() |
768f81627e | ||
![]() |
c2924a10e7 | ||
![]() |
5af3281103 | ||
![]() |
0496e59a10 | ||
![]() |
6f07ef5236 | ||
![]() |
0f9ed1d7d6 | ||
![]() |
3aa0ca984c | ||
![]() |
77832458c9 | ||
![]() |
e10a578603 | ||
![]() |
b142d33bbe | ||
![]() |
bcabf710d0 | ||
![]() |
a725fe261a | ||
![]() |
ebee38994f | ||
![]() |
6ebb0246ab | ||
![]() |
c7a054fa31 | ||
![]() |
6ff6acbb21 | ||
![]() |
8a09cb9794 | ||
![]() |
eeb59b4f4d | ||
![]() |
7afbc3a1c1 | ||
![]() |
3da8ebf27e | ||
![]() |
7e33d531ae | ||
![]() |
32577820f4 | ||
![]() |
3686c640d6 | ||
![]() |
cbe53247fa | ||
![]() |
bbbae1065a | ||
![]() |
b5c3bb998d | ||
![]() |
4ff7aeadbb | ||
![]() |
86eaf57d53 | ||
![]() |
ff7b7a9c2f | ||
![]() |
dea267e5c8 | ||
![]() |
07200be358 | ||
![]() |
45e6bb4a74 | ||
![]() |
b44f7b1a5c | ||
![]() |
3c9c40c4b7 | ||
![]() |
15bb08eea6 | ||
![]() |
10953bddcb | ||
![]() |
7b87a797ed | ||
![]() |
4ea5a19a10 | ||
![]() |
ee263f3b97 | ||
![]() |
f73846cd6b | ||
![]() |
b2fd28d2b0 | ||
![]() |
05535d985b | ||
![]() |
4dc8aa2a27 | ||
![]() |
3d084ac910 | ||
![]() |
f8678d7513 | ||
![]() |
c50136e2cb | ||
![]() |
c3b4e0f37e | ||
![]() |
4d33c41e92 | ||
![]() |
eff4e3e3c2 | ||
![]() |
e6c7536d62 | ||
![]() |
5f4a06039e | ||
![]() |
05b9bb71b1 | ||
![]() |
c7cae616e0 | ||
![]() |
14daffecc5 | ||
![]() |
f6ae7d4f49 | ||
![]() |
316d9d5c34 | ||
![]() |
ba99c7792a | ||
![]() |
66a2af0c77 | ||
![]() |
ab87527e1d | ||
![]() |
a0486577a8 | ||
![]() |
6f4c65c029 | ||
![]() |
295f3796c6 | ||
![]() |
6362ec46d5 | ||
![]() |
de2b1c4bb4 | ||
![]() |
6aad16e11f | ||
![]() |
78b657e8f3 | ||
![]() |
ee9e65ecb1 | ||
![]() |
5341121fde | ||
![]() |
265581e525 | ||
![]() |
06da025393 | ||
![]() |
317bbd8f46 | ||
![]() |
9cb99bbaa8 | ||
![]() |
8a70ac0950 | ||
![]() |
9956446ad7 | ||
![]() |
f0865de125 | ||
![]() |
5cb6779305 | ||
![]() |
1e2e9201b2 | ||
![]() |
6062e658db | ||
![]() |
eca92ea193 | ||
![]() |
3177ce1f35 | ||
![]() |
faa17f8959 | ||
![]() |
d42a09e9b6 | ||
![]() |
408d38b223 | ||
![]() |
333a1266cc | ||
![]() |
a4912ff297 | ||
![]() |
a9920d6776 | ||
![]() |
71b1f1ad88 | ||
![]() |
a198e2984c | ||
![]() |
e160d8466c | ||
![]() |
575479a6a1 | ||
![]() |
8b97de61f5 | ||
![]() |
d870e5c309 | ||
![]() |
2da56a70a2 | ||
![]() |
0b2f134680 | ||
![]() |
5d32a199a9 | ||
![]() |
f677c22fba | ||
![]() |
97ae2d3b9b | ||
![]() |
a3fe2de883 | ||
![]() |
7f6c3b3fc1 | ||
![]() |
ab4ab682e5 | ||
![]() |
a69cb738a8 | ||
![]() |
e9eeee5608 | ||
![]() |
d89ab70036 | ||
![]() |
fa82a82a07 | ||
![]() |
39f92d985b | ||
![]() |
da0129b83e | ||
![]() |
c980caecac | ||
![]() |
b88abd81c8 | ||
![]() |
201c38e407 | ||
![]() |
31c53670e7 | ||
![]() |
e169f00193 | ||
![]() |
e1ee231993 | ||
![]() |
7d4aebd603 | ||
![]() |
2cde8da71c | ||
![]() |
6f54c28c87 | ||
![]() |
17841959f5 | ||
![]() |
cfe5fadb3a | ||
![]() |
3cd4a5ded5 | ||
![]() |
36156244a1 | ||
![]() |
a66a804082 | ||
![]() |
d2524eef7f | ||
![]() |
f6d2af17fc | ||
![]() |
a86754b4c4 | ||
![]() |
2968435f81 | ||
![]() |
4096bbfeee | ||
![]() |
0314fd4b6e | ||
![]() |
3f2257f209 | ||
![]() |
271e0f9896 | ||
![]() |
79b5e1891d | ||
![]() |
b4b453d6de | ||
![]() |
06f085560c | ||
![]() |
38fb735551 | ||
![]() |
b0ecee8155 | ||
![]() |
ba46a0c05b | ||
![]() |
0112164c34 | ||
![]() |
f60fafbb2e | ||
![]() |
004079b07a | ||
![]() |
523a1a71d7 | ||
![]() |
d3999d904a | ||
![]() |
63894062d4 | ||
![]() |
5c60a65eaf | ||
![]() |
c387933d3c | ||
![]() |
882336e0e6 | ||
![]() |
e91aa6db32 | ||
![]() |
325b3fd0db | ||
![]() |
84348299b3 | ||
![]() |
e934864a90 | ||
![]() |
920205bc61 | ||
![]() |
0dcc34837e | ||
![]() |
57d8d7fcd4 | ||
![]() |
f26f014ffc | ||
![]() |
134aa72467 | ||
![]() |
a7a8938291 | ||
![]() |
9338556872 | ||
![]() |
28ef4bc441 | ||
![]() |
686f9ae4b2 | ||
![]() |
a57119761b | ||
![]() |
6881149540 | ||
![]() |
4f842e23df | ||
![]() |
47873a339a | ||
![]() |
03e02185d9 | ||
![]() |
e565d97bc8 | ||
![]() |
6bf8d2b356 | ||
![]() |
2981656ebe | ||
![]() |
5ec0ba72cd | ||
![]() |
f020941629 | ||
![]() |
f1a92872a4 | ||
![]() |
9e7ce2c916 | ||
![]() |
788532dc99 | ||
![]() |
54679ea9cc | ||
![]() |
cb0aeaf708 | ||
![]() |
8de04115ec | ||
![]() |
e65e5ea9d0 | ||
![]() |
19b577bf66 | ||
![]() |
ccb0b42ffb | ||
![]() |
1d46ef38d2 | ||
![]() |
06356d806a | ||
![]() |
45847c62ce | ||
![]() |
9cb6bb8535 | ||
![]() |
e9b25a1e98 | ||
![]() |
ad51b996a2 | ||
![]() |
8a05f311b9 | ||
![]() |
e72267bc00 | ||
![]() |
2e0973a814 | ||
![]() |
27092a822a | ||
![]() |
0cd8e48c36 | ||
![]() |
2b95289ee2 | ||
![]() |
5df5ce6463 | ||
![]() |
04ad0077f4 | ||
![]() |
1bf2f118c7 | ||
![]() |
2119abf954 | ||
![]() |
fc728d0cfb | ||
![]() |
dd01edd168 | ||
![]() |
7c3edad3d4 | ||
![]() |
c4d76a65da | ||
![]() |
db394e2b81 | ||
![]() |
92c7145139 | ||
![]() |
d133525502 | ||
![]() |
cd1817bf6d | ||
![]() |
0d1491b1a6 | ||
![]() |
f67774d84b | ||
![]() |
37668d159e | ||
![]() |
38554288f5 | ||
![]() |
04dcc3bceb | ||
![]() |
0910a2fc0d | ||
![]() |
3325cb2f86 | ||
![]() |
a1e8443bfb | ||
![]() |
599d34b41e | ||
![]() |
7fd1733882 | ||
![]() |
2e42123870 | ||
![]() |
4cbb90daf7 | ||
![]() |
cf2663b034 | ||
![]() |
95681b16bd | ||
![]() |
e620827fa8 |
4
.bazelrc
4
.bazelrc
@ -74,8 +74,8 @@ test --test_output=errors
|
|||||||
# Trick bazel into treating BUILD files under integration/bazel as being regular files
|
# Trick bazel into treating BUILD files under integration/bazel as being regular files
|
||||||
# This lets us glob() up all the files inside this integration test to make them inputs to tests
|
# This lets us glob() up all the files inside this integration test to make them inputs to tests
|
||||||
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
|
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
|
||||||
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e
|
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||||
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e
|
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Temporary Settings for Ivy #
|
# Temporary Settings for Ivy #
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
3.5.1
|
3.2.0
|
||||||
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
||||||
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
||||||
|
@ -14,8 +14,8 @@ build --repository_cache=/home/circleci/bazel_repository_cache
|
|||||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||||
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
||||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||||
build --local_cpu_resources=20
|
build --local_cpu_resources=8
|
||||||
build --local_ram_resources=32768
|
build --local_ram_resources=14336
|
||||||
|
|
||||||
# All build executed remotely should be done using our RBE configuration.
|
# All build executed remotely should be done using our RBE configuration.
|
||||||
build:remote --google_default_credentials
|
build:remote --google_default_credentials
|
||||||
|
@ -11,8 +11,8 @@ try-import %workspace%/.circleci/bazel.common.rc
|
|||||||
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
||||||
|
|
||||||
# Manually set the local resources used in windows CI runs
|
# Manually set the local resources used in windows CI runs
|
||||||
build --local_ram_resources=120000
|
build --local_ram_resources=13500
|
||||||
build --local_cpu_resources=32
|
build --local_cpu_resources=4
|
||||||
|
|
||||||
# All windows jobs run on master and should use http caching
|
# All windows jobs run on master and should use http caching
|
||||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||||
|
@ -30,11 +30,6 @@ var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
|||||||
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||||
|
|
||||||
# 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.
|
|
||||||
var_5: &components_repo_unit_tests_cache_key v9-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
|
|
||||||
var_6: &components_repo_unit_tests_cache_key_fallback v9-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
|
||||||
# `build-ivy-npm-packages`.
|
# `build-ivy-npm-packages`.
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
@ -80,7 +75,7 @@ executors:
|
|||||||
|
|
||||||
windows-executor:
|
windows-executor:
|
||||||
working_directory: ~/ng
|
working_directory: ~/ng
|
||||||
resource_class: windows.2xlarge
|
resource_class: windows.medium
|
||||||
# CircleCI windows VMs do have the GitBash shell available:
|
# CircleCI windows VMs do have the GitBash shell available:
|
||||||
# https://github.com/CircleCI-Public/windows-preview-docs#shells
|
# https://github.com/CircleCI-Public/windows-preview-docs#shells
|
||||||
# But in this specific case we really should not use it because Bazel must not be ran from
|
# But in this specific case we really should not use it because Bazel must not be ran from
|
||||||
@ -156,27 +151,6 @@ commands:
|
|||||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||||
git config --global gc.auto 0 || true
|
git config --global gc.auto 0 || true
|
||||||
|
|
||||||
init_saucelabs_environment:
|
|
||||||
description: Sets up a domain that resolves to the local host.
|
|
||||||
steps:
|
|
||||||
- run:
|
|
||||||
name: Preparing environment for running tests on Sauce Labs.
|
|
||||||
command: |
|
|
||||||
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
|
||||||
# the tunnel. We do this because devices are sometimes not able to properly resolve
|
|
||||||
# `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
|
|
||||||
# resolve to anything on SauceLabs VMs ensures that such requests are always resolved
|
|
||||||
# through the tunnel, and resolve to the actual tunnel host machine (i.e. the CircleCI VM).
|
|
||||||
# More context can be found in: https://github.com/angular/angular/pull/35171.
|
|
||||||
setPublicVar SAUCE_LOCALHOST_ALIAS_DOMAIN "angular-ci.local"
|
|
||||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
|
||||||
- run:
|
|
||||||
# Sets up a local domain in the machine's host file that resolves to the local
|
|
||||||
# host. This domain is helpful in Sauce Labs tests where devices are not able to
|
|
||||||
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
|
|
||||||
name: Setting up alias domain for local host.
|
|
||||||
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
|
|
||||||
|
|
||||||
# Normally this would be an individual job instead of a command.
|
# Normally this would be an individual job instead of a command.
|
||||||
# But startup and setup time for each individual windows job are high enough to discourage
|
# But startup and setup time for each individual windows job are high enough to discourage
|
||||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||||
@ -272,110 +246,8 @@ jobs:
|
|||||||
- run: yarn -s tslint
|
- run: yarn -s tslint
|
||||||
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
||||||
- run: yarn -s ts-circular-deps:check
|
- run: yarn -s ts-circular-deps:check
|
||||||
- run: yarn -s ng-dev pullapprove verify
|
|
||||||
- run: yarn -s ng-dev ngbot verify
|
|
||||||
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
||||||
|
|
||||||
test:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
# Now that large integration tests are running locally in parallel (they can't run on RBE yet
|
|
||||||
# as they require network access for yarn install), this test is running out of memory
|
|
||||||
# consistently with the xlarge machine.
|
|
||||||
# TODO: switch back to xlarge once integration tests are running on remote-exec
|
|
||||||
resource_class: 2xlarge+
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- install_chrome_libs
|
|
||||||
- install_java
|
|
||||||
- run:
|
|
||||||
command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
|
||||||
no_output_timeout: 20m
|
|
||||||
|
|
||||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
|
||||||
test_ivy_aot:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- install_chrome_libs
|
|
||||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
|
||||||
# not be able to easily find the output bin directory when uploading artifacts for size
|
|
||||||
# measurements.
|
|
||||||
- run:
|
|
||||||
command: yarn test-ivy-aot //... --symlink_prefix=dist/
|
|
||||||
no_output_timeout: 20m
|
|
||||||
|
|
||||||
# Publish bundle artifacts which will be used to calculate the size change. **Note**: Make
|
|
||||||
# sure that the size plugin from the Angular robot fetches the artifacts from this CircleCI
|
|
||||||
# job (see .github/angular-robot.yml). Additionally any artifacts need to be stored with the
|
|
||||||
# following path format: "{projectName}/{context}/{fileName}". This format is necessary
|
|
||||||
# because otherwise the bot is not able to pick up the artifacts from CircleCI. See:
|
|
||||||
# https://github.com/angular/github-robot/blob/master/functions/src/plugins/size.ts#L392-L394
|
|
||||||
- store_artifacts:
|
|
||||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
|
||||||
destination: core/hello_world/bundle
|
|
||||||
- store_artifacts:
|
|
||||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js
|
|
||||||
destination: core/todo/bundle
|
|
||||||
- store_artifacts:
|
|
||||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.br
|
|
||||||
destination: core/hello_world/bundle.br
|
|
||||||
- store_artifacts:
|
|
||||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
|
||||||
destination: core/todo/bundle.br
|
|
||||||
|
|
||||||
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
|
||||||
saucelabs_view_engine:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- init_saucelabs_environment
|
|
||||||
- run:
|
|
||||||
name: Run Bazel tests on Saucelabs with ViewEngine
|
|
||||||
# See /tools/saucelabs/README.md for more info
|
|
||||||
command: |
|
|
||||||
yarn bazel run //tools/saucelabs:sauce_service_setup
|
|
||||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "ivy-only", ...) except attr("tags", "fixme-saucelabs-ve", ...)')
|
|
||||||
yarn bazel test --config=saucelabs ${TESTS}
|
|
||||||
yarn bazel run //tools/saucelabs:sauce_service_stop
|
|
||||||
no_output_timeout: 40m
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
|
||||||
|
|
||||||
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
|
||||||
saucelabs_ivy:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- init_saucelabs_environment
|
|
||||||
- run:
|
|
||||||
name: Run Bazel tests on Saucelabs with Ivy
|
|
||||||
# See /tools/saucelabs/README.md for more info
|
|
||||||
command: |
|
|
||||||
yarn bazel run //tools/saucelabs:sauce_service_setup
|
|
||||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "no-ivy-aot", ...) except attr("tags", "fixme-saucelabs-ivy", ...)')
|
|
||||||
yarn bazel test --config=saucelabs --config=ivy ${TESTS}
|
|
||||||
yarn bazel run //tools/saucelabs:sauce_service_stop
|
|
||||||
no_output_timeout: 40m
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
@ -394,10 +266,6 @@ 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
|
||||||
# Run accessibility tests
|
# Run accessibility tests
|
||||||
- run: yarn --cwd aio test-a11y-score-localhost
|
- run: yarn --cwd aio test-a11y-score-localhost
|
||||||
# Check the bundle sizes.
|
|
||||||
- run: yarn --cwd aio payload-size
|
|
||||||
# Run unit tests for Firebase redirects
|
|
||||||
- run: yarn --cwd aio redirects-test
|
|
||||||
|
|
||||||
deploy_aio:
|
deploy_aio:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -427,8 +295,6 @@ jobs:
|
|||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run PWA-score tests
|
# Run PWA-score tests
|
||||||
- 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.
|
|
||||||
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -442,26 +308,6 @@ jobs:
|
|||||||
- run: yarn --cwd aio tools-test
|
- run: yarn --cwd aio tools-test
|
||||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||||
|
|
||||||
test_docs_examples:
|
|
||||||
parameters:
|
|
||||||
viewengine:
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
resource_class: xlarge
|
|
||||||
parallelism: 5
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- install_chrome_libs
|
|
||||||
# Install aio
|
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
|
||||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
|
||||||
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
|
|
||||||
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
|
|
||||||
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.viewengine >>--viewengine<</ parameters.viewengine >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
|
||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -490,7 +336,6 @@ jobs:
|
|||||||
name: Wait for preview and run tests
|
name: Wait for preview and run tests
|
||||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||||
|
|
||||||
|
|
||||||
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||||
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||||
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||||
@ -502,7 +347,7 @@ jobs:
|
|||||||
build-npm-packages:
|
build-npm-packages:
|
||||||
executor:
|
executor:
|
||||||
name: default-executor
|
name: default-executor
|
||||||
resource_class: xlarge
|
resource_class: medium
|
||||||
steps:
|
steps:
|
||||||
- custom_attach_workspace
|
- custom_attach_workspace
|
||||||
- init_environment
|
- init_environment
|
||||||
@ -524,258 +369,6 @@ jobs:
|
|||||||
- "~/bazel_repository_cache"
|
- "~/bazel_repository_cache"
|
||||||
- "~/.cache/bazelisk"
|
- "~/.cache/bazelisk"
|
||||||
|
|
||||||
# Build the ivy npm packages.
|
|
||||||
build-ivy-npm-packages:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- run: node scripts/build/build-ivy-npm-packages.js
|
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
|
||||||
- persist_to_workspace:
|
|
||||||
root: *workspace_location
|
|
||||||
paths:
|
|
||||||
- ng/dist/packages-dist-ivy-aot
|
|
||||||
- ng/dist/zone.js-dist-ivy-aot
|
|
||||||
|
|
||||||
# This job creates compressed tarballs (`.tgz` files) for all Angular packages and stores them as
|
|
||||||
# build artifacts. This makes it easy to try out changes from a PR build for testing purposes.
|
|
||||||
# More info CircleCI build artifacts: https://circleci.com/docs/2.0/artifacts
|
|
||||||
#
|
|
||||||
# NOTE: Currently, this job only runs for PR builds. See `publish_snapshot` for non-PR builds.
|
|
||||||
publish_packages_as_artifacts:
|
|
||||||
executor: default-executor
|
|
||||||
environment:
|
|
||||||
NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist'
|
|
||||||
NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives'
|
|
||||||
ZONEJS_PACKAGES_DIR: &zonejs_packages_dir 'dist/zone.js-dist'
|
|
||||||
ZONEJS_PACKAGES_ARCHIVES_DIR: &zonejs_packages_archives_dir 'dist/zone.js-dist-archives'
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
# Publish `@angular/*` packages.
|
|
||||||
- run:
|
|
||||||
name: Create artifacts for @angular/* packages
|
|
||||||
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR
|
|
||||||
- store_artifacts:
|
|
||||||
path: *ng_packages_archives_dir
|
|
||||||
destination: angular
|
|
||||||
# Publish `zone.js` package.
|
|
||||||
- run:
|
|
||||||
name: Create artifacts for zone.js package
|
|
||||||
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $ZONEJS_PACKAGES_DIR $ZONEJS_PACKAGES_ARCHIVES_DIR
|
|
||||||
- store_artifacts:
|
|
||||||
path: *zonejs_packages_archives_dir
|
|
||||||
destination: zone.js
|
|
||||||
|
|
||||||
# This job updates the content of repos like github.com/angular/core-builds
|
|
||||||
# for every green build on angular/angular.
|
|
||||||
publish_snapshot:
|
|
||||||
executor: default-executor
|
|
||||||
steps:
|
|
||||||
# See below - ideally this job should not trigger for non-upstream builds.
|
|
||||||
# But since it does, we have to check this condition.
|
|
||||||
- run:
|
|
||||||
name: Skip this job for Pull Requests and Fork builds
|
|
||||||
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
|
|
||||||
# step can be run before `init_environment`.
|
|
||||||
command: >
|
|
||||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]] ||
|
|
||||||
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
|
|
||||||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
|
||||||
circleci step halt
|
|
||||||
fi
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
# CircleCI has a config setting to force SSH for all github connections
|
|
||||||
# This is not compatible with our mechanism of using a Personal Access Token
|
|
||||||
# Clear the global setting
|
|
||||||
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
|
||||||
- run:
|
|
||||||
name: Decrypt github credentials
|
|
||||||
# We need ensure that the same default digest is used for encoding and decoding with
|
|
||||||
# OpenSSL. OpenSSL versions might have different default digests which can cause
|
|
||||||
# decryption failures based on the installed OpenSSL version. https://stackoverflow.com/a/39641378/4317734
|
|
||||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
|
||||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
|
||||||
|
|
||||||
aio_monitoring_stable:
|
|
||||||
executor: default-executor
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- install_chrome_libs
|
|
||||||
- run: setPublicVar_CI_STABLE_BRANCH
|
|
||||||
- run:
|
|
||||||
name: Check out `aio/` and yarn from the stable branch
|
|
||||||
command: |
|
|
||||||
git fetch origin $CI_STABLE_BRANCH
|
|
||||||
git checkout --force origin/$CI_STABLE_BRANCH -- aio/ .yarn/ .yarnrc
|
|
||||||
# Ignore yarn's engines check, because we checked out `aio/package.json` from the stable
|
|
||||||
# branch and there could be a node version skew, which is acceptable in this monitoring job.
|
|
||||||
- run: yarn config set ignore-engines true
|
|
||||||
- run:
|
|
||||||
name: Run tests against https://angular.io/
|
|
||||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
|
||||||
|
|
||||||
aio_monitoring_next:
|
|
||||||
executor: default-executor
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- install_chrome_libs
|
|
||||||
- run:
|
|
||||||
name: Run tests against https://next.angular.io/
|
|
||||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
|
||||||
- notify_webhook_on_fail:
|
|
||||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
|
||||||
|
|
||||||
legacy-unit-tests-saucelabs:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
- init_saucelabs_environment
|
|
||||||
- run:
|
|
||||||
name: Starting Saucelabs tunnel service
|
|
||||||
command: ./tools/saucelabs/sauce-service.sh run
|
|
||||||
background: true
|
|
||||||
- run: yarn tsc -p packages
|
|
||||||
- run: yarn tsc -p modules
|
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package
|
|
||||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
|
||||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
|
||||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
|
||||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
|
||||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
|
||||||
- run:
|
|
||||||
name: Preparing Bazel-generated fixtures required in legacy tests
|
|
||||||
command: |
|
|
||||||
yarn bazel build //packages/core/test:downleveled_es5_fixture
|
|
||||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
|
||||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
|
||||||
dist/all/@angular/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
|
||||||
- run:
|
|
||||||
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
|
||||||
name: Waiting for Saucelabs tunnel to connect
|
|
||||||
command: ./tools/saucelabs/sauce-service.sh ready-wait
|
|
||||||
- run:
|
|
||||||
name: Running tests on Saucelabs.
|
|
||||||
command: |
|
|
||||||
browsers=$(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
|
||||||
yarn karma start ./karma-js.conf.js --single-run --browsers=${browsers}
|
|
||||||
- run:
|
|
||||||
name: Stop Saucelabs tunnel service
|
|
||||||
command: ./tools/saucelabs/sauce-service.sh stop
|
|
||||||
|
|
||||||
# Job that runs all unit tests of the `angular/components` repository.
|
|
||||||
components-repo-unit-tests:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
# Restore the cache before cloning the repository because the clone script re-uses
|
|
||||||
# the restored repository if present. This reduces the amount of times the components
|
|
||||||
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
|
||||||
- restore_cache:
|
|
||||||
keys:
|
|
||||||
- *components_repo_unit_tests_cache_key
|
|
||||||
# Whenever the `angular/components` SHA is updated, the cache key will no longer
|
|
||||||
# match. The fallback cache will still match, and CircleCI will restore the most
|
|
||||||
# recently cached repository folder. Without the fallback cache, we'd need to download
|
|
||||||
# the repository from scratch and it would slow down the job. This is because we can't
|
|
||||||
# clone the repository with reduced `--depth`, but rather need to clone the whole
|
|
||||||
# repository to be able to support arbitrary SHAs.
|
|
||||||
- *components_repo_unit_tests_cache_key_fallback
|
|
||||||
- run:
|
|
||||||
name: "Fetching angular/components repository"
|
|
||||||
command: ./scripts/ci/clone_angular_components_repo.sh
|
|
||||||
- run:
|
|
||||||
# Run yarn install to fetch the Bazel binaries as used in the components repo.
|
|
||||||
name: Installing dependencies.
|
|
||||||
# TODO: remove this once the repo has been updated to use NodeJS v12 and Yarn 1.19.1.
|
|
||||||
# We temporarily ignore the "engines" because the Angular components repository has
|
|
||||||
# minimum dependency on NodeJS v12 and Yarn 1.19.1, but the framework repository uses
|
|
||||||
# older versions.
|
|
||||||
command: yarn --ignore-engines --cwd ${COMPONENTS_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
|
||||||
- save_cache:
|
|
||||||
key: *components_repo_unit_tests_cache_key
|
|
||||||
paths:
|
|
||||||
# Temporary directory must be kept in sync with the `$COMPONENTS_REPO_TMP_DIR` env
|
|
||||||
# variable. It needs to be hardcoded here, because env variables interpolation is
|
|
||||||
# not supported.
|
|
||||||
- "/tmp/angular-components-repo"
|
|
||||||
- run:
|
|
||||||
# Updates the `angular/components` `package.json` file to refer to the release output
|
|
||||||
# inside the `packages-dist` directory. Note that it's not necessary to perform a yarn
|
|
||||||
# install as Bazel runs Yarn automatically when needed.
|
|
||||||
name: Setting up release packages.
|
|
||||||
command: node scripts/ci/update-deps-to-dist-packages.js ${COMPONENTS_REPO_TMP_DIR}/package.json dist/packages-dist/
|
|
||||||
- run:
|
|
||||||
name: "Running `angular/components` unit tests"
|
|
||||||
command: ./scripts/ci/run_angular_components_unit_tests.sh
|
|
||||||
|
|
||||||
test_zonejs:
|
|
||||||
executor:
|
|
||||||
name: default-executor
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- custom_attach_workspace
|
|
||||||
- init_environment
|
|
||||||
# Install
|
|
||||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
|
||||||
# Run zone.js tools tests
|
|
||||||
- run: yarn --cwd packages/zone.js promisetest
|
|
||||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package &&
|
|
||||||
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/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
|
||||||
yarn --cwd packages/zone.js electrontest
|
|
||||||
- run: yarn --cwd packages/zone.js jesttest
|
|
||||||
|
|
||||||
# Windows jobs
|
|
||||||
# Docs: https://circleci.com/docs/2.0/hello-world-windows/
|
|
||||||
test_win:
|
|
||||||
executor: windows-executor
|
|
||||||
steps:
|
|
||||||
- setup_win
|
|
||||||
- run:
|
|
||||||
# Ran into a command parsing problem where `-browser:chromium-local` was converted to
|
|
||||||
# `-browser: chromium-local` (a space was added) in https://circleci.com/gh/angular/angular/357511.
|
|
||||||
# Probably a powershell command parsing thing. There's no problem using a yarn script though.
|
|
||||||
command: yarn circleci-win-ve
|
|
||||||
no_output_timeout: 45m
|
|
||||||
# Save bazel repository cache to use on subsequent runs.
|
|
||||||
# We don't save node_modules because it's faster to use the linux workspace and reinstall.
|
|
||||||
- save_cache:
|
|
||||||
key: *cache_key_win
|
|
||||||
paths:
|
|
||||||
- "C:/Users/circleci/bazel_repository_cache"
|
|
||||||
|
|
||||||
test_ivy_aot_win:
|
|
||||||
executor: windows-executor
|
|
||||||
steps:
|
|
||||||
- setup_win
|
|
||||||
- run:
|
|
||||||
command: yarn circleci-win-ivy
|
|
||||||
no_output_timeout: 45m
|
|
||||||
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
@ -788,21 +381,9 @@ workflows:
|
|||||||
- lint:
|
- lint:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- test:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- test_ivy_aot:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- build-npm-packages:
|
- build-npm-packages:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
- build-ivy-npm-packages:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- legacy-unit-tests-saucelabs:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- test_aio:
|
- test_aio:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
@ -812,22 +393,9 @@ workflows:
|
|||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_local:
|
|
||||||
name: test_aio_local_viewengine
|
|
||||||
viewengine: true
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_docs_examples:
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- test_docs_examples:
|
|
||||||
name: test_docs_examples_viewengine
|
|
||||||
viewengine: true
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- aio_preview:
|
- aio_preview:
|
||||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||||
<<: *only_on_pull_requests
|
<<: *only_on_pull_requests
|
||||||
@ -836,85 +404,3 @@ workflows:
|
|||||||
- test_aio_preview:
|
- test_aio_preview:
|
||||||
requires:
|
requires:
|
||||||
- aio_preview
|
- aio_preview
|
||||||
- publish_packages_as_artifacts:
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- publish_snapshot:
|
|
||||||
# Note: no filters on this job because we want it to run for all upstream branches
|
|
||||||
# We'd really like to filter out pull requests here, but not yet available:
|
|
||||||
# https://discuss.circleci.com/t/workflows-pull-request-filter/14396/4
|
|
||||||
# Instead, the job just exits immediately at the first step.
|
|
||||||
requires:
|
|
||||||
# Only publish if tests and integration tests pass
|
|
||||||
- test
|
|
||||||
- test_ivy_aot
|
|
||||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
|
||||||
- test_aio_local
|
|
||||||
- test_aio_local_viewengine
|
|
||||||
- test_docs_examples
|
|
||||||
- test_docs_examples_viewengine
|
|
||||||
# Get the artifacts to publish from the build-packages-dist job
|
|
||||||
# since the publishing script expects the legacy outputs layout.
|
|
||||||
- build-npm-packages
|
|
||||||
- build-ivy-npm-packages
|
|
||||||
- legacy-unit-tests-saucelabs
|
|
||||||
# Temporarily disabled components-repo-unit-tests to update rules_nodejs to 2.0.0. Breaking changes in
|
|
||||||
# rules_nodejs create a dependency sandwich between angular/angular & angular/components that are very
|
|
||||||
# difficult and time consuming to resolve and involve patching @angular/bazel in components repo such
|
|
||||||
# as https://github.com/angular/components/commit/9e7ba251207df77164d73d66620e619bcbc4d2ad. It is simpler to
|
|
||||||
# 1) land angular/angular upgrade to rule_nodejs 2.0.0 which has breaking changes
|
|
||||||
# 2) land angular/components upgrade to rules_nodejs 2.0.0 using the @angular/bazel builds snapshot
|
|
||||||
# 3) update angular/angular to the landed components commit and re-enable these tests
|
|
||||||
# - components-repo-unit-tests:
|
|
||||||
# requires:
|
|
||||||
# - build-npm-packages
|
|
||||||
- test_zonejs:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
# Windows Jobs
|
|
||||||
# These are very slow so we run them on non-PRs only for now.
|
|
||||||
# TODO: remove the filter when CircleCI makes Windows FS faster.
|
|
||||||
# The Windows jobs are only run after their non-windows counterparts finish successfully.
|
|
||||||
# This isn't strictly necessary as there is no artifact dependency, but helps economize
|
|
||||||
# CI resources by not attempting to build when we know should fail.
|
|
||||||
- test_win:
|
|
||||||
<<: *skip_on_pull_requests
|
|
||||||
requires:
|
|
||||||
- test
|
|
||||||
- test_ivy_aot_win:
|
|
||||||
<<: *skip_on_pull_requests
|
|
||||||
requires:
|
|
||||||
- test_ivy_aot
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
jobs:
|
|
||||||
- setup
|
|
||||||
- aio_monitoring_stable:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- aio_monitoring_next:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- saucelabs_ivy:
|
|
||||||
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
|
||||||
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
|
||||||
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
|
||||||
# slowing down CI for PRs.
|
|
||||||
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
|
||||||
# share provisioned browsers and we can remove the legacy saucelabs job.
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- saucelabs_view_engine:
|
|
||||||
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
|
||||||
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
|
||||||
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
|
||||||
# slowing down CI for PRs.
|
|
||||||
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
|
||||||
# share provisioned browsers and we can remove the legacy saucelabs job.
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
triggers:
|
|
||||||
- schedule:
|
|
||||||
<<: *only_on_master
|
|
||||||
# Runs monitoring jobs at 10:00AM every day.
|
|
||||||
cron: "0 10 * * *"
|
|
||||||
|
@ -17,7 +17,7 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
setPublicVar CI "$CI"
|
setPublicVar CI "$CI"
|
||||||
setPublicVar PROJECT_ROOT "$projectDir";
|
setPublicVar PROJECT_ROOT "$projectDir";
|
||||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
setPublicVar CI_AIO_MIN_PWA_SCORE "62";
|
||||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||||
|
@ -41,8 +41,7 @@ copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Install specific version of node.
|
# Install specific version of node.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
nvm install 12.14.1
|
choco install nodejs --version 12.14.1 --no-progress
|
||||||
nvm use 12.14.1
|
|
||||||
|
|
||||||
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
|
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
|
||||||
# choco install yarn --version 1.16.0 --no-progress
|
# choco install yarn --version 1.16.0 --no-progress
|
||||||
|
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -1,69 +0,0 @@
|
|||||||
---
|
|
||||||
name: "\U0001F41EBug report"
|
|
||||||
about: Report a bug in the Angular Framework
|
|
||||||
---
|
|
||||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
|
||||||
|
|
||||||
Oh hi there! 😄
|
|
||||||
|
|
||||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
|
||||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
|
||||||
|
|
||||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
|
||||||
|
|
||||||
|
|
||||||
# 🐞 bug report
|
|
||||||
|
|
||||||
### Affected Package
|
|
||||||
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
|
|
||||||
<!-- ✍️edit: --> The issue is caused by package @angular/....
|
|
||||||
|
|
||||||
|
|
||||||
### Is this a regression?
|
|
||||||
|
|
||||||
<!-- Did this behavior use to work in the previous version? -->
|
|
||||||
<!-- ✍️--> Yes, the previous version in which this bug was not present was: ....
|
|
||||||
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!-- ✍️--> A clear and concise description of the problem...
|
|
||||||
|
|
||||||
|
|
||||||
## 🔬 Minimal Reproduction
|
|
||||||
<!--
|
|
||||||
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
|
|
||||||
-->
|
|
||||||
<!-- ✍️--> https://stackblitz.com/...
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
|
||||||
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
|
||||||
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
|
||||||
|
|
||||||
Issues that don't have enough info and can't be reproduced will be closed.
|
|
||||||
|
|
||||||
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue
|
|
||||||
-->
|
|
||||||
|
|
||||||
## 🔥 Exception or Error
|
|
||||||
<pre><code>
|
|
||||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
|
||||||
<!-- ✍️-->
|
|
||||||
|
|
||||||
</code></pre>
|
|
||||||
|
|
||||||
|
|
||||||
## 🌍 Your Environment
|
|
||||||
|
|
||||||
**Angular Version:**
|
|
||||||
<pre><code>
|
|
||||||
<!-- run `ng version` and paste output below -->
|
|
||||||
<!-- ✍️-->
|
|
||||||
|
|
||||||
</code></pre>
|
|
||||||
|
|
||||||
**Anything else relevant?**
|
|
||||||
<!-- ✍️Is this a browser specific issue? If so, please specify the browser and version. -->
|
|
||||||
|
|
||||||
<!-- ✍️Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->
|
|
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: "\U0001F680Feature request"
|
|
||||||
about: Suggest a feature for Angular Framework
|
|
||||||
|
|
||||||
---
|
|
||||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
|
||||||
|
|
||||||
Oh hi there! 😄
|
|
||||||
|
|
||||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
|
||||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
|
||||||
|
|
||||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
|
||||||
|
|
||||||
|
|
||||||
# 🚀 feature request
|
|
||||||
|
|
||||||
### Relevant Package
|
|
||||||
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
|
|
||||||
<!-- ✍️edit: --> This feature request is for @angular/....
|
|
||||||
|
|
||||||
|
|
||||||
### Description
|
|
||||||
<!-- ✍️--> A clear and concise description of the problem or missing capability...
|
|
||||||
|
|
||||||
|
|
||||||
### Describe the solution you'd like
|
|
||||||
<!-- ✍️--> If you have a solution in mind, please describe it.
|
|
||||||
|
|
||||||
|
|
||||||
### Describe alternatives you've considered
|
|
||||||
<!-- ✍️--> Have you considered any alternative solutions or workarounds?
|
|
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
@ -1,55 +0,0 @@
|
|||||||
---
|
|
||||||
name: "📚 Docs or angular.io issue report"
|
|
||||||
about: Report an issue in Angular's documentation or angular.io application
|
|
||||||
|
|
||||||
---
|
|
||||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
|
||||||
|
|
||||||
Oh hi there! 😄
|
|
||||||
|
|
||||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
|
||||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
|
||||||
|
|
||||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
|
||||||
|
|
||||||
# 📚 Docs or angular.io bug report
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
<!-- ✍️edit:--> A clear and concise description of the problem...
|
|
||||||
|
|
||||||
|
|
||||||
## 🔬 Minimal Reproduction
|
|
||||||
|
|
||||||
### What's the affected URL?**
|
|
||||||
<!-- ✍️edit:--> https://angular.io/...
|
|
||||||
|
|
||||||
### Reproduction Steps**
|
|
||||||
<!-- If applicable please list the steps to take to reproduce the issue -->
|
|
||||||
<!-- ✍️edit:-->
|
|
||||||
|
|
||||||
### Expected vs Actual Behavior**
|
|
||||||
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
|
|
||||||
<!-- ✍️edit:-->
|
|
||||||
|
|
||||||
|
|
||||||
## 📷Screenshot
|
|
||||||
<!-- Often a screenshot can help to capture the issue better than a long description. -->
|
|
||||||
<!-- ✍️upload a screenshot:-->
|
|
||||||
|
|
||||||
|
|
||||||
## 🔥 Exception or Error
|
|
||||||
<pre><code>
|
|
||||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
|
||||||
<!-- ✍️-->
|
|
||||||
|
|
||||||
</code></pre>
|
|
||||||
|
|
||||||
|
|
||||||
## 🌍 Your Environment
|
|
||||||
|
|
||||||
### Browser info
|
|
||||||
<!-- ✍️Is this a browser specific issue? If so, please specify the device, browser, and version. -->
|
|
||||||
|
|
||||||
### Anything else relevant?
|
|
||||||
<!-- ✍️Please provide additional info if necessary. -->
|
|
@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
name: ⚠️ Security issue disclosure
|
|
||||||
about: Report a security issue in Angular Framework, Material, or CLI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
||||||
|
|
||||||
Please read https://angular.io/guide/security#report-issues on how to disclose security related issues.
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
name: "❓Support request"
|
|
||||||
about: Questions and requests for support
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
||||||
|
|
||||||
Please do not file questions or support requests on the GitHub issues tracker.
|
|
||||||
|
|
||||||
You can get your questions answered using other communication channels. Please see:
|
|
||||||
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
|
||||||
|
|
||||||
Thank you!
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: "\U0001F6E0️Angular CLI"
|
|
||||||
about: Issues and feature requests for Angular CLI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
||||||
|
|
||||||
Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new
|
|
||||||
|
|
||||||
For the time being, we keep Angular CLI issues in a separate repository.
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: "\U0001F48EAngular Components"
|
|
||||||
about: Issues and feature requests for Angular Components
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
||||||
|
|
||||||
Please file any Angular Components issues at: https://github.com/angular/components/issues/new
|
|
||||||
|
|
||||||
For the time being, we keep Angular Components issues in a separate repository.
|
|
||||||
|
|
||||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
|
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: "📚Traducir doc al español"
|
||||||
|
about: Solicitud para traducir ciertos docs al español
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
📚Traducir: <!-- ✍️ editar: --> creating-libraries.md
|
||||||
|
|
||||||
|
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||||
|
|
||||||
|
Traducción de la documentación oficial de Angular a español
|
||||||
|
|
||||||
|
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||||
|
|
||||||
|
|
||||||
|
## Nombre del archivo:
|
||||||
|
<!-- ✍️ editar: --> creating-libraries.md
|
||||||
|
|
||||||
|
|
||||||
|
## Ruta donde se encuentra el archivo dentro del proyecto de Angular
|
||||||
|
|
||||||
|
<!-- ✍️ editar: --> https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md
|
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,43 +1,35 @@
|
|||||||
## PR Checklist
|
## Lista de Verificación del PR
|
||||||
Please check if your PR fulfills the following requirements:
|
Comprueba si tu PR cumple los siguientes requisitos:
|
||||||
|
|
||||||
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
- [ ] El mensaje de commit esta conforme con [nuestras reglas](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md#-formato-para-el-mensaje-de-los-commits)
|
||||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
- [ ] Probe los cambios que agregué (arreglo de bugs / funcionalidades)
|
||||||
- [ ] Docs have been added / updated (for bug fixes / features)
|
- [ ] Revisé previamente las traducciones o cambios de contenido
|
||||||
|
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/blob/master/aio/diccionario-de-términos.md) en español
|
||||||
|
- [ ] He creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
|
||||||
|
- [ ] He enlazado el commit con el issue correspondiente <!-- ejemplo Fixes #X -->
|
||||||
|
|
||||||
|
|
||||||
## PR Type
|
## Tipo de PR
|
||||||
What kind of change does this PR introduce?
|
¿Qué tipo de cambio introduce este PR?
|
||||||
|
|
||||||
<!-- Please check the one that applies to this PR using "x". -->
|
<!-- Marca con una "x" las opciones que aplican. -->
|
||||||
|
|
||||||
- [ ] Bugfix
|
- [ ] Bugfix
|
||||||
- [ ] Feature
|
- [ ] Funcionalidad
|
||||||
- [ ] Code style update (formatting, local variables)
|
- [ ] Actualización de el estilo del código (formato, variables locales)
|
||||||
- [ ] Refactoring (no functional changes, no api changes)
|
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
|
||||||
- [ ] Build related changes
|
- [ ] Cambios relacionados al build
|
||||||
- [ ] CI related changes
|
- [ ] Cambios relacionados al CI (Integración continua)
|
||||||
- [ ] Documentation content changes
|
- [ ] Cambios en el contenido de la documentación
|
||||||
- [ ] angular.io application / infrastructure changes
|
- [ ] Cambios en la aplicación / infraestructura de angular.io
|
||||||
- [ ] Other... Please describe:
|
- [ ] Otro... Por favor describe la:
|
||||||
|
|
||||||
|
## ¿Cuál es el comportamiento actual?
|
||||||
|
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
## What is the current behavior?
|
## ¿Cuál es el nuevo comportamiento?
|
||||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
<!--
|
||||||
|
Ejemplo: Archivo en inglés traducido al español
|
||||||
Issue Number: N/A
|
-->
|
||||||
|
|
||||||
|
|
||||||
## What is the new behavior?
|
|
||||||
|
|
||||||
|
|
||||||
## Does this PR introduce a breaking change?
|
|
||||||
|
|
||||||
- [ ] Yes
|
|
||||||
- [ ] No
|
|
||||||
|
|
||||||
|
|
||||||
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
|
|
||||||
|
|
||||||
|
|
||||||
## Other information
|
|
||||||
|
55
.github/angular-robot.yml
vendored
55
.github/angular-robot.yml
vendored
@ -38,7 +38,6 @@ merge:
|
|||||||
- "modules/benchmarks/**"
|
- "modules/benchmarks/**"
|
||||||
- "modules/system.d.ts"
|
- "modules/system.d.ts"
|
||||||
- "packages/**"
|
- "packages/**"
|
||||||
- "dev-infra/benchmark/driver-utilities/**"
|
|
||||||
# list of patterns to ignore for the files changed by the PR
|
# list of patterns to ignore for the files changed by the PR
|
||||||
exclude:
|
exclude:
|
||||||
- "packages/*"
|
- "packages/*"
|
||||||
@ -48,10 +47,7 @@ merge:
|
|||||||
- "packages/bazel/src/ng_package/**"
|
- "packages/bazel/src/ng_package/**"
|
||||||
- "packages/bazel/src/protractor/**"
|
- "packages/bazel/src/protractor/**"
|
||||||
- "packages/bazel/src/schematics/**"
|
- "packages/bazel/src/schematics/**"
|
||||||
- "packages/compiler-cli/src/ngcc/**"
|
|
||||||
- "packages/compiler-cli/linker/**"
|
|
||||||
- "packages/compiler-cli/ngcc/**"
|
- "packages/compiler-cli/ngcc/**"
|
||||||
- "packages/compiler-cli/src/ngtsc/sourcemaps/**"
|
|
||||||
- "packages/docs/**"
|
- "packages/docs/**"
|
||||||
- "packages/elements/schematics/**"
|
- "packages/elements/schematics/**"
|
||||||
- "packages/examples/**"
|
- "packages/examples/**"
|
||||||
@ -59,8 +55,6 @@ merge:
|
|||||||
- "packages/localize/**"
|
- "packages/localize/**"
|
||||||
- "packages/private/**"
|
- "packages/private/**"
|
||||||
- "packages/service-worker/**"
|
- "packages/service-worker/**"
|
||||||
- "packages/common/locales/**"
|
|
||||||
- "packages/http/**"
|
|
||||||
- "**/.gitignore"
|
- "**/.gitignore"
|
||||||
- "**/.gitkeep"
|
- "**/.gitkeep"
|
||||||
- "**/yarn.lock"
|
- "**/yarn.lock"
|
||||||
@ -74,20 +68,20 @@ merge:
|
|||||||
- "packages/**/integrationtest/**"
|
- "packages/**/integrationtest/**"
|
||||||
- "packages/**/test/**"
|
- "packages/**/test/**"
|
||||||
- "packages/zone.js/*"
|
- "packages/zone.js/*"
|
||||||
- "packages/zone.js/dist/**"
|
|
||||||
- "packages/zone.js/doc/**"
|
- "packages/zone.js/doc/**"
|
||||||
- "packages/zone.js/example/**"
|
- "packages/zone.js/example/**"
|
||||||
- "packages/zone.js/scripts/**"
|
- "packages/zone.js/scripts/**"
|
||||||
|
|
||||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
||||||
|
\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||||
|
|
||||||
# label to monitor
|
# label to monitor
|
||||||
mergeLabel: "action: merge"
|
mergeLabel: "PR action: merge"
|
||||||
|
|
||||||
# adding any of these labels will also add the merge label
|
# adding any of these labels will also add the merge label
|
||||||
mergeLinkedLabels:
|
mergeLinkedLabels:
|
||||||
- "action: merge-assistance"
|
- "PR action: merge-assistance"
|
||||||
|
|
||||||
# list of checks that will determine if the merge label can be added
|
# list of checks that will determine if the merge label can be added
|
||||||
checks:
|
checks:
|
||||||
@ -100,17 +94,17 @@ merge:
|
|||||||
|
|
||||||
# whether the PR shouldn't have a conflict with the base branch
|
# whether the PR shouldn't have a conflict with the base branch
|
||||||
noConflict: true
|
noConflict: true
|
||||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
|
||||||
requiredLabels:
|
requiredLabels:
|
||||||
- "target: *"
|
- "PR target: *"
|
||||||
- "cla: yes"
|
- "cla: yes"
|
||||||
|
|
||||||
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
||||||
forbiddenLabels:
|
forbiddenLabels:
|
||||||
- "target: TBD"
|
- "PR target: TBD"
|
||||||
- "action: cleanup"
|
- "PR action: cleanup"
|
||||||
- "action: review"
|
- "PR action: review"
|
||||||
- "state: blocked"
|
- "PR state: blocked"
|
||||||
- "cla: no"
|
- "cla: no"
|
||||||
|
|
||||||
# list of PR statuses that need to be successful
|
# list of PR statuses that need to be successful
|
||||||
@ -127,7 +121,12 @@ merge:
|
|||||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
|
||||||
|
\n{{PLACEHOLDER}}
|
||||||
|
\n
|
||||||
|
\n**If you want your PR to be merged, it has to pass all the CI checks.**
|
||||||
|
\n
|
||||||
|
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||||
|
|
||||||
# options for the triage plugin
|
# options for the triage plugin
|
||||||
triage:
|
triage:
|
||||||
@ -142,28 +141,24 @@ triage:
|
|||||||
# arrays of labels that determine if an issue has been fully triaged
|
# arrays of labels that determine if an issue has been fully triaged
|
||||||
l2TriageLabels:
|
l2TriageLabels:
|
||||||
-
|
-
|
||||||
- "P0"
|
- "type: bug/fix"
|
||||||
|
- "severity*"
|
||||||
|
- "freq*"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P1"
|
- "type: feature"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P2"
|
- "type: refactor"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P3"
|
- "type: RFC / Discussion / question"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P4"
|
- "type: confusing"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P5"
|
- "type: use-case"
|
||||||
- "comp: *"
|
|
||||||
-
|
|
||||||
- "feature"
|
|
||||||
- "comp: *"
|
|
||||||
-
|
|
||||||
- "discussion"
|
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
|
|
||||||
# options for the triage PR plugin
|
# options for the triage PR plugin
|
||||||
@ -191,4 +186,4 @@ rerunCircleCI:
|
|||||||
# set to true to disable
|
# set to true to disable
|
||||||
disabled: false
|
disabled: false
|
||||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||||
triggerRerunLabel: "action: rerun CI at HEAD"
|
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -40,9 +40,6 @@ yarn-error.log
|
|||||||
# User specific bazel settings
|
# User specific bazel settings
|
||||||
.bazelrc.user
|
.bazelrc.user
|
||||||
|
|
||||||
# User specific ng-dev settings
|
|
||||||
.ng-dev.user*
|
|
||||||
|
|
||||||
.notes.md
|
.notes.md
|
||||||
baseline.json
|
baseline.json
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import {CaretakerConfig} from '../dev-infra/caretaker/config';
|
|
||||||
|
|
||||||
/** The configuration for `ng-dev caretaker` commands. */
|
|
||||||
export const caretaker: CaretakerConfig = {
|
|
||||||
githubQueries: [
|
|
||||||
{
|
|
||||||
name: 'Merge Queue',
|
|
||||||
query: `is:pr is:open status:success label:"action: merge"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Merge Assistance Queue',
|
|
||||||
query: `is:pr is:open label:"action: merge-assistance"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Initial Triage Queue',
|
|
||||||
query: `is:open no:milestone`,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
@ -6,7 +6,20 @@ import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
|||||||
export const commitMessage: CommitMessageConfig = {
|
export const commitMessage: CommitMessageConfig = {
|
||||||
maxLineLength: 120,
|
maxLineLength: 120,
|
||||||
minBodyLength: 20,
|
minBodyLength: 20,
|
||||||
minBodyLengthTypeExcludes: ['docs'],
|
minBodyLengthTypeExcludes: ['docs', 'upstream'],
|
||||||
|
types: [
|
||||||
|
'build',
|
||||||
|
'ci',
|
||||||
|
'docs',
|
||||||
|
'feat',
|
||||||
|
'fix',
|
||||||
|
'perf',
|
||||||
|
'refactor',
|
||||||
|
'release',
|
||||||
|
'style',
|
||||||
|
'test',
|
||||||
|
'upstream',
|
||||||
|
],
|
||||||
scopes: [
|
scopes: [
|
||||||
'animations',
|
'animations',
|
||||||
'bazel',
|
'bazel',
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import {caretaker} from './caretaker';
|
|
||||||
import {commitMessage} from './commit-message';
|
import {commitMessage} from './commit-message';
|
||||||
import {format} from './format';
|
import {format} from './format';
|
||||||
import {github} from './github';
|
import {github} from './github';
|
||||||
import {merge} from './merge';
|
import {merge} from './merge';
|
||||||
import {release} from './release';
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
commitMessage,
|
commitMessage,
|
||||||
format,
|
format,
|
||||||
github,
|
github,
|
||||||
merge,
|
merge,
|
||||||
caretaker,
|
|
||||||
release,
|
|
||||||
};
|
};
|
||||||
|
@ -1,28 +1,38 @@
|
|||||||
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
|
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||||
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
|
|
||||||
import {github} from './github';
|
|
||||||
import {release} from './release';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||||
* are respected by the merge script (e.g. the target labels).
|
* are respected by the merge script (e.g. the target labels).
|
||||||
*/
|
*/
|
||||||
export const merge: DevInfraMergeConfig['merge'] = async api => {
|
export const merge = (): MergeConfig => {
|
||||||
|
// TODO: resume dynamically determining patch branch
|
||||||
|
const patch = '10.0.x';
|
||||||
return {
|
return {
|
||||||
githubApiMerge: false,
|
githubApiMerge: false,
|
||||||
claSignedLabel: 'cla: yes',
|
claSignedLabel: 'cla: yes',
|
||||||
mergeReadyLabel: /^action: merge(-assistance)?/,
|
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||||
caretakerNoteLabel: 'action: merge-assistance',
|
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||||
commitMessageFixupLabel: 'commit message fixup',
|
commitMessageFixupLabel: 'commit message fixup',
|
||||||
// We can pick any of the NPM packages as we are in a monorepo where all packages are
|
labels: [
|
||||||
// published together with the same version and branching.
|
{
|
||||||
labels: await getDefaultTargetLabelConfiguration(api, github, release),
|
pattern: 'PR target: master-only',
|
||||||
|
branches: ['master'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: 'PR target: patch-only',
|
||||||
|
branches: [patch],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: 'PR target: master & patch',
|
||||||
|
branches: ['master', patch],
|
||||||
|
},
|
||||||
|
],
|
||||||
requiredBaseCommits: {
|
requiredBaseCommits: {
|
||||||
// PRs that target either `master` or the patch branch, need to be rebased
|
// PRs that target either `master` or the patch branch, need to be rebased
|
||||||
// on top of the latest commit message validation fix.
|
// on top of the latest commit message validation fix.
|
||||||
// These SHAs are the commits that update the required license text in the header.
|
// These SHAs are the commits that update the required license text in the header.
|
||||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||||
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
|
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import {join} from 'path';
|
|
||||||
import {exec} from 'shelljs';
|
|
||||||
import {ReleaseConfig} from '../dev-infra/release/config';
|
|
||||||
|
|
||||||
/** Configuration for the `ng-dev release` command. */
|
|
||||||
export const release: ReleaseConfig = {
|
|
||||||
npmPackages: [
|
|
||||||
'@angular/animations',
|
|
||||||
'@angular/bazel',
|
|
||||||
'@angular/common',
|
|
||||||
'@angular/compiler',
|
|
||||||
'@angular/compiler-cli',
|
|
||||||
'@angular/core',
|
|
||||||
'@angular/elements',
|
|
||||||
'@angular/forms',
|
|
||||||
'@angular/language-service',
|
|
||||||
'@angular/localize',
|
|
||||||
'@angular/platform-browser',
|
|
||||||
'@angular/platform-browser-dynamic',
|
|
||||||
'@angular/platform-server',
|
|
||||||
'@angular/platform-webworker',
|
|
||||||
'@angular/platform-webworker-dynamic',
|
|
||||||
'@angular/router',
|
|
||||||
'@angular/service-worker',
|
|
||||||
'@angular/upgrade',
|
|
||||||
],
|
|
||||||
// TODO: Implement release package building here.
|
|
||||||
buildPackages: async () => [],
|
|
||||||
// TODO: This can be removed once there is an org-wide tool for changelog generation.
|
|
||||||
generateReleaseNotesForHead: async () => {
|
|
||||||
exec('yarn -s gulp changelog', {cwd: join(__dirname, '../')});
|
|
||||||
},
|
|
||||||
};
|
|
@ -284,7 +284,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- alxhub
|
- alxhub
|
||||||
- crisbeto
|
- crisbeto
|
||||||
# OOO as of 2020-09-28 - devversion
|
- devversion
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -326,7 +326,6 @@ groups:
|
|||||||
'aio/content/examples/component-interaction/**',
|
'aio/content/examples/component-interaction/**',
|
||||||
'aio/content/images/guide/component-interaction/**',
|
'aio/content/images/guide/component-interaction/**',
|
||||||
'aio/content/guide/component-styles.md',
|
'aio/content/guide/component-styles.md',
|
||||||
'aio/content/guide/view-encapsulation.md',
|
|
||||||
'aio/content/examples/component-styles/**',
|
'aio/content/examples/component-styles/**',
|
||||||
'aio/content/guide/dependency-injection.md',
|
'aio/content/guide/dependency-injection.md',
|
||||||
'aio/content/examples/dependency-injection/**',
|
'aio/content/examples/dependency-injection/**',
|
||||||
@ -420,7 +419,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
||||||
- mhevery
|
- mhevery
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -510,8 +509,8 @@ groups:
|
|||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
'packages/core/src/i18n/**',
|
'packages/core/src/i18n/**',
|
||||||
'packages/core/src/render3/i18n/**',
|
'packages/core/src/render3/i18n.ts',
|
||||||
'packages/core/src/render3/instructions/i18n.ts',
|
'packages/core/src/render3/i18n.md',
|
||||||
'packages/core/src/render3/interfaces/i18n.ts',
|
'packages/core/src/render3/interfaces/i18n.ts',
|
||||||
'packages/common/locales/**',
|
'packages/common/locales/**',
|
||||||
'packages/common/src/i18n/**',
|
'packages/common/src/i18n/**',
|
||||||
@ -663,7 +662,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
- AndrewKushnir
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -680,7 +679,7 @@ groups:
|
|||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -698,7 +697,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- jelbourn
|
- jelbourn
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -724,7 +723,7 @@ groups:
|
|||||||
- IgorMinar
|
- IgorMinar
|
||||||
- mhevery
|
- mhevery
|
||||||
- jelbourn
|
- jelbourn
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: -1 # request reviews from everyone
|
request: -1 # request reviews from everyone
|
||||||
required: 2 # require at least 2 approvals
|
required: 2 # require at least 2 approvals
|
||||||
@ -1116,7 +1115,6 @@ groups:
|
|||||||
'docs/DEBUG.md',
|
'docs/DEBUG.md',
|
||||||
'docs/DEBUG_COMPONENTS_REPO_IVY.md',
|
'docs/DEBUG_COMPONENTS_REPO_IVY.md',
|
||||||
'docs/DEVELOPER.md',
|
'docs/DEVELOPER.md',
|
||||||
'docs/FIXUP_COMMITS.md',
|
|
||||||
'docs/GITHUB_PROCESS.md',
|
'docs/GITHUB_PROCESS.md',
|
||||||
'docs/PR_REVIEW.md',
|
'docs/PR_REVIEW.md',
|
||||||
'docs/SAVED_REPLIES.md',
|
'docs/SAVED_REPLIES.md',
|
||||||
@ -1152,7 +1150,7 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
# OOO as of 2020-09-28 - devversion
|
- devversion
|
||||||
- filipesilva
|
- filipesilva
|
||||||
- gkalpak
|
- gkalpak
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
@ -1186,7 +1184,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: 4 # Request reviews from four people
|
||||||
required: 3 # Require that three people approve
|
required: 3 # Require that three people approve
|
||||||
@ -1214,7 +1212,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: 4 # Request reviews from four people
|
||||||
required: 2 # Require that two people approve
|
required: 2 # Require that two people approve
|
||||||
@ -1242,7 +1240,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
####################################################################################
|
####################################################################################
|
||||||
|
@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [
|
|||||||
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
||||||
|
|
||||||
// ignore cruft
|
// ignore cruft
|
||||||
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']);
|
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']);
|
||||||
|
|
||||||
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
||||||
// never ignore these files
|
// never ignore these files
|
||||||
@ -44663,7 +44663,6 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
|||||||
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
||||||
return tar.pack(cwd, {
|
return tar.pack(cwd, {
|
||||||
ignore: ignoreFunction,
|
ignore: ignoreFunction,
|
||||||
sort: true,
|
|
||||||
map: header => {
|
map: header => {
|
||||||
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
||||||
header.name = `package${suffix}`;
|
header.name = `package${suffix}`;
|
||||||
@ -46679,7 +46678,7 @@ function mkdirfix (name, opts, cb) {
|
|||||||
/* 194 */
|
/* 194 */
|
||||||
/***/ (function(module, exports) {
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
/* 195 */
|
/* 195 */
|
||||||
@ -98339,7 +98338,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
|
|||||||
|
|
||||||
const bundle = yield fetchBundle(config, bundleUrl);
|
const bundle = yield fetchBundle(config, bundleUrl);
|
||||||
|
|
||||||
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`);
|
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`);
|
||||||
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
||||||
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
||||||
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
||||||
@ -100191,7 +100190,7 @@ let main = exports.main = (() => {
|
|||||||
|
|
||||||
const config = new (_config || _load_config()).default(reporter);
|
const config = new (_config || _load_config()).default(reporter);
|
||||||
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
||||||
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]);
|
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args);
|
||||||
|
|
||||||
if (shouldWrapOutput) {
|
if (shouldWrapOutput) {
|
||||||
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
||||||
@ -100605,7 +100604,7 @@ let start = (() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (/\.[cm]?js$/.test(yarnPath)) {
|
if (yarnPath.endsWith(`.js`)) {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
||||||
} else {
|
} else {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
2
.yarnrc
2
.yarnrc
@ -2,4 +2,4 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
yarn-path ".yarn/releases/yarn-1.22.5.js"
|
yarn-path ".yarn/releases/yarn-1.22.4.js"
|
||||||
|
@ -34,7 +34,7 @@ filegroup(
|
|||||||
filegroup(
|
filegroup(
|
||||||
name = "angularjs_scripts",
|
name = "angularjs_scripts",
|
||||||
srcs = [
|
srcs = [
|
||||||
# We also declare the unminified AngularJS files since these can be used for
|
# We also declare the unminfied AngularJS files since these can be used for
|
||||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||||
"@npm//:node_modules/angular/angular.js",
|
"@npm//:node_modules/angular/angular.js",
|
||||||
"@npm//:node_modules/angular/angular.min.js",
|
"@npm//:node_modules/angular/angular.min.js",
|
||||||
@ -47,9 +47,3 @@ filegroup(
|
|||||||
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Detect if the build is running under --stamp
|
|
||||||
config_setting(
|
|
||||||
name = "stamp",
|
|
||||||
values = {"stamp": "true"},
|
|
||||||
)
|
|
||||||
|
335
CHANGELOG.md
335
CHANGELOG.md
@ -1,251 +1,19 @@
|
|||||||
<a name="10.1.6"></a>
|
<a name="10.1.0-next.4"></a>
|
||||||
## 10.1.6 (2020-10-14)
|
# 10.1.0-next.4 (2020-08-04)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **compiler:** incorrectly encapsulating [@import](https://github.com/import) containing colons and semicolons ([#38716](https://github.com/angular/angular/issues/38716)) ([52a0c6b](https://github.com/angular/angular/commit/52a0c6b)), closes [#38587](https://github.com/angular/angular/issues/38587)
|
|
||||||
* **compiler-cli:** support namespaced query types in directives ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([f752ab9](https://github.com/angular/angular/commit/f752ab9))
|
|
||||||
* **elements:** detect matchesSelector prototype without IIFE ([#37799](https://github.com/angular/angular/issues/37799)) ([952fd86](https://github.com/angular/angular/commit/952fd86)), closes [#24551](https://github.com/angular/angular/issues/24551)
|
|
||||||
* **ngcc:** ensure that "inline exports" can be interpreted correctly ([#39272](https://github.com/angular/angular/issues/39272)) ([e08d021](https://github.com/angular/angular/commit/e08d021))
|
|
||||||
* **ngcc:** handle aliases in UMD export declarations ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9963c5d](https://github.com/angular/angular/commit/9963c5d)), closes [#38947](https://github.com/angular/angular/issues/38947)
|
|
||||||
* **ngcc:** map `exports` to the current module in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([13c4a7b](https://github.com/angular/angular/commit/13c4a7b))
|
|
||||||
* **ngcc:** support inline export declarations in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9c875b3](https://github.com/angular/angular/commit/9c875b3)), closes [#38947](https://github.com/angular/angular/issues/38947)
|
|
||||||
|
|
||||||
|
|
||||||
### build
|
|
||||||
|
|
||||||
* upgrade angular build, integration/bazel and [@angular](https://github.com/angular)/bazel package to rule_nodejs 2.2.0 ([#39182](https://github.com/angular/angular/issues/39182)) ([7628c36](https://github.com/angular/angular/commit/7628c36))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **ngcc:** do not rescan program source files when referenced from multiple root files ([#39254](https://github.com/angular/angular/issues/39254)) ([5221df8](https://github.com/angular/angular/commit/5221df8)), closes [#39240](https://github.com/angular/angular/issues/39240)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.5"></a>
|
|
||||||
## 10.1.5 (2020-10-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **router:** update getRouteGuards to check if the context outlet is activated ([#39049](https://github.com/angular/angular/issues/39049)) ([771f731](https://github.com/angular/angular/commit/771f731)), closes [#39030](https://github.com/angular/angular/issues/39030)
|
|
||||||
* **compiler:** Recover on malformed keyed reads and keyed writes ([#39004](https://github.com/angular/angular/issues/39004)) ([f50313f](https://github.com/angular/angular/commit/f50313f)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.4"></a>
|
|
||||||
## 10.1.4 (2020-09-30)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler-cli:** enable [@types](https://github.com/types) discovery in incremental rebuilds ([#39011](https://github.com/angular/angular/issues/39011)) ([6e99427](https://github.com/angular/angular/commit/6e99427)), closes [#38979](https://github.com/angular/angular/issues/38979)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.3"></a>
|
|
||||||
## 10.1.3 (2020-09-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0))
|
|
||||||
* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883)
|
|
||||||
|
|
||||||
|
|
||||||
### Reverts
|
|
||||||
|
|
||||||
* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.2"></a>
|
|
||||||
## 10.1.2 (2020-09-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539)
|
|
||||||
* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619)
|
|
||||||
* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d))
|
|
||||||
* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691)
|
|
||||||
* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405))
|
|
||||||
* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67))
|
|
||||||
* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7))
|
|
||||||
* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.1"></a>
|
|
||||||
## 10.1.1 (2020-09-09)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6))
|
|
||||||
* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
|
||||||
* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670)
|
|
||||||
* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600)
|
|
||||||
* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692)
|
|
||||||
* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679)
|
|
||||||
* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329)
|
|
||||||
* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377)
|
|
||||||
* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705)
|
|
||||||
* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238)
|
|
||||||
* **router:** If users are using the Alt key when clicking the router links, prioritize browser’s default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0"></a>
|
|
||||||
# 10.1.0 (2020-09-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
|
||||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
|
||||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
|
||||||
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
|
||||||
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
|
||||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
|
||||||
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
|
||||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
|
||||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
|
||||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
|
||||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
|
||||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
|
||||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
|
||||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
|
||||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
|
||||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
|
||||||
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
|
|
||||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
|
||||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
|
||||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
|
||||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
|
||||||
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
|
||||||
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
|
|
||||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
|
||||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
|
||||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
|
||||||
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
|
||||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
|
||||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
|
||||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
|
||||||
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
|
|
||||||
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
|
||||||
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
|
||||||
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
|
|
||||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
|
||||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
|
||||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
|
||||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
|
||||||
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
|
||||||
|
|
||||||
### Code Refactoring
|
|
||||||
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
|
||||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
|
||||||
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
|
||||||
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
|
||||||
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
|
||||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
|
||||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
|
||||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.14"></a>
|
|
||||||
## 10.0.14 (2020-08-26)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.12"></a>
|
|
||||||
## 10.0.12 (2020-08-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
|
|
||||||
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
|
|
||||||
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
|
|
||||||
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
|
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||||
|
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.11"></a>
|
|
||||||
## 10.0.11 (2020-08-19)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.10"></a>
|
|
||||||
## 10.0.10 (2020-08-17)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630)
|
|
||||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292)
|
|
||||||
* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201)
|
|
||||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.9"></a>
|
|
||||||
## 10.0.9 (2020-08-12)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629)
|
|
||||||
* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194)
|
|
||||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912)
|
|
||||||
* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568)
|
|
||||||
* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147)
|
|
||||||
* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82))
|
|
||||||
* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311)
|
|
||||||
* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105)
|
|
||||||
* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315)
|
|
||||||
* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f))
|
|
||||||
* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149))
|
|
||||||
* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314))
|
|
||||||
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.8"></a>
|
<a name="10.0.8"></a>
|
||||||
## 10.0.8 (2020-08-04)
|
## 10.0.8 (2020-08-04)
|
||||||
@ -268,6 +36,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.0-next.3"></a>
|
||||||
|
# 10.1.0-next.3 (2020-07-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.6"></a>
|
<a name="10.0.6"></a>
|
||||||
## 10.0.6 (2020-07-28)
|
## 10.0.6 (2020-07-28)
|
||||||
|
|
||||||
@ -281,6 +59,23 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.0-next.2"></a>
|
||||||
|
# 10.1.0-next.2 (2020-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||||
|
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||||
|
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.5"></a>
|
<a name="10.0.5"></a>
|
||||||
## 10.0.5 (2020-07-22)
|
## 10.0.5 (2020-07-22)
|
||||||
|
|
||||||
@ -315,6 +110,62 @@
|
|||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.0-next.1"></a>
|
||||||
|
# 10.1.0-next.1 (2020-07-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663))
|
||||||
|
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
||||||
|
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
||||||
|
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15))
|
||||||
|
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
||||||
|
* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710)
|
||||||
|
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
||||||
|
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="10.1.0-next.0"></a>
|
||||||
|
# 10.1.0-next.0 (2020-07-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||||
|
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||||
|
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||||
|
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||||
|
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||||
|
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||||
|
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||||
|
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||||
|
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||||
|
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||||
|
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||||
|
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||||
|
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||||
|
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||||
|
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||||
|
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||||
|
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||||
|
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||||
|
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||||
|
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.3"></a>
|
<a name="10.0.3"></a>
|
||||||
## 10.0.3 (2020-07-08)
|
## 10.0.3 (2020-07-08)
|
||||||
|
|
||||||
@ -596,12 +447,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more
|
|||||||
information and updates.
|
information and updates.
|
||||||
|
|
||||||
If you used Closure Compiler with Angular in the past, you will likely
|
If you used Closure Compiler with Angular in the past, you will likely
|
||||||
be better off consuming Angular packages built from sources directly
|
be better off consuming Angular packages built from sources directly
|
||||||
rather than consuming the version we publish on npm,
|
rather than consuming the version we publish on npm,
|
||||||
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
||||||
|
|
||||||
As a temporary workaround, you might consider using your current build
|
As a temporary workaround, you might consider using your current build
|
||||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||||
will ensure that your build pipeline produces buildable and
|
will ensure that your build pipeline produces buildable and
|
||||||
runnable artifacts, at the cost of increased payload size due to
|
runnable artifacts, at the cost of increased payload size due to
|
||||||
advanced optimizations being disabled.
|
advanced optimizations being disabled.
|
||||||
@ -609,17 +460,17 @@ advanced optimizations being disabled.
|
|||||||
If you were affected by this change, please help us understand your
|
If you were affected by this change, please help us understand your
|
||||||
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
||||||
|
|
||||||
* **core:** make generic mandatory for ModuleWithProviders
|
* **core:** make generic mandatory for ModuleWithProviders
|
||||||
|
|
||||||
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
||||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||||
|
|
||||||
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
||||||
|
|
||||||
```
|
```
|
||||||
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
||||||
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
||||||
|
|
||||||
@ -1947,7 +1798,7 @@ API surface going forward.
|
|||||||
* **core:** Injector.get now accepts abstract classes to return
|
* **core:** Injector.get now accepts abstract classes to return
|
||||||
type-safe values. Previous implementation returned `any` through the
|
type-safe values. Previous implementation returned `any` through the
|
||||||
deprecated implementation.
|
deprecated implementation.
|
||||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||||
|
|
||||||
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
||||||
|
|
||||||
|
@ -1,12 +1,72 @@
|
|||||||
# Contributor Code of Conduct
|
# Código de Conducta
|
||||||
## Version 0.3b-angular
|
|
||||||
|
|
||||||
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
## 1. Propósito
|
||||||
|
|
||||||
Communication through any of Angular's channels (GitHub, Discord, Gitter, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
“Prometemos brindar cortesía y respeto a cualquier persona involucrada en esta comunidad, sin importar el género con el que se identifique, su orientación sexual, limitación física, edad, raza, etnia, religión o nivel de conocimiento. Esperamos que cualquiera que desee contribuir en este proyecto brinde el mismo comportamiento”
|
||||||
|
|
||||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
Bajo ese principio queremos enfocar esta comunidad, una comunidad de respeto por el otro, donde cualquiera que sienta pasión por Angular y desee involucrarse con cualquier tipo de actividad deberá ayudar a mantener una atmósfera de cortesía por el otro, respetando los pensamientos, acciones, ideales y propuestas del otro.
|
||||||
|
|
||||||
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
## 2. Comportamiento esperado
|
||||||
|
|
||||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).
|
- Evitar usar expresiones o gestos insultantes, humillantes o intimidatorios para referirnos a otros.
|
||||||
|
- Ejercita la consideración y el respeto en tus comunicaciones y acciones.
|
||||||
|
- Absténte de adoptar una conducta y un lenguaje degradantes, discriminatorios, abusivos o acosadores.
|
||||||
|
- Evitar comportamientos que agredan las expresiones de identidad, género, creencias religiosas, acciones que lastimen o los aíslen a otros.
|
||||||
|
- Evitar comentarios sobre ideas políticas.
|
||||||
|
- No se toleran conductas físicas y actitudes dirigidas al descrédito personal, físico o emocional de cualquier persona.
|
||||||
|
- No se toleran chistes y comentarios excluyentes, sexistas y racistas.
|
||||||
|
- Se rechaza actitudes de hostigamiento.
|
||||||
|
- Se rechaza el acoso: este se entiende como cualquier tipo de comentario verbal que refuerce discriminación por género, identidad y expresión de género, orientación sexual, discapacidad, apariencia física, tamaño corporal, raza, edad o religión en contextos laborales o sociales.
|
||||||
|
- No se tolera el contacto físico y/o la atención sexual no deseada.
|
||||||
|
- Promover la igualdad de oportunidades de formación, educación, intercambio y retroalimentación antes, durante y después de los eventos.
|
||||||
|
- Intenta colaborar en lugar de generar conflicto.
|
||||||
|
- Sé consciente de tu entorno y de tus compañeros participantes. Alerta a líderes de la comunidad si notas una situación peligrosa, alguien en apuros, o violaciones de este Código de Conducta, incluso si parecen intrascendentes.
|
||||||
|
|
||||||
|
## 3. Comportamiento inaceptable
|
||||||
|
Comportamientos inaceptables incluyen: intimidación, acoso, abuso, discriminación, comunicación despectiva o degradante o acciones por cualquier participante en nuestra comunidad ya sea virtual, o en las comunicaciones uno-a-uno que se realizan en el contexto de la comunidad. Por favor ser respetuoso con todos.
|
||||||
|
|
||||||
|
El acoso incluye: comentarios nocivos o perjudiciales, verbales o escritos relacionados con el género, la orientación sexual, raza, religión, discapacidad; uso inadecuado de desnudos y / o imágenes sexuales en espacios públicos (incluyendo la presentación diapositivas); intimidación deliberada, acecho o seguimiento; fotografías o grabaciones acosadoras; interrupción sostenida de charlas y otros eventos; contacto físico inapropiado, y atención sexual no deseada.
|
||||||
|
|
||||||
|
## 4. Consecuencias de comportamiento inaceptable
|
||||||
|
Se espera que personas a quienes se les solicite que detengan su comportamiento inaceptable lo hagan de manera inmediata esto será válido para cualquier miembro de la comunidad.
|
||||||
|
|
||||||
|
En caso de presentarse una violación al código de conducta de manera repetida se tendrá cero tolerancia a este comportamiento por parte de los organizadores.
|
||||||
|
|
||||||
|
Si un miembro de la comunidad participa en una conducta inaceptable, los organizadores pueden tomar cualquier acción que consideren apropiada, hasta e incluyendo una prohibición temporal o expulsión permanente de la comunidad, sin previo aviso.
|
||||||
|
|
||||||
|
Priorizamos la seguridad de las personas marginadas sobre la comodidad de las personas privilegiadas. Nos reservamos el derecho de no actuar sobre las quejas relacionadas con:
|
||||||
|
|
||||||
|
- El "racismo inverso", "sexismo inverso" y "cisfobia".
|
||||||
|
- Comunicación razonable de límites, como "déjame en paz", "vete" o "no estoy discutiendo esto contigo".
|
||||||
|
- Al comunicarse en un "tono", no se encuentra agradable.
|
||||||
|
- Identificando comportamientos o suposiciones racistas, sexistas, cissexistas u opresivas.
|
||||||
|
|
||||||
|
## 5. ¿Qué hacer si se incumple el código de conducta?
|
||||||
|
Si eres víctima o testigo de una conducta inaceptable, o tienes cualquier inquietud, por favor comunícate con el equipo organizador lo antes posible:
|
||||||
|
|
||||||
|
- Mensaje directo: Michael Prentice (@splaktar)
|
||||||
|
- Mensaje directo: Jorge Cano (@jorgeucano)
|
||||||
|
- Mensaje directo: Andrés Villanueva (@villanuevand)
|
||||||
|
- Email: [soporte@angular.lat](mailto:soporte@angular.lat)
|
||||||
|
|
||||||
|
### ¿Qué pasa después?
|
||||||
|
- Una vez haya sido notificada el no cumplimiento de la norma, el equipo de liderazgo se reunirán y analizarán el caso.
|
||||||
|
- Los incidentes presentados se manejarán con discreción.
|
||||||
|
- Los organizadores se comunicarán con la persona que incumplió la norma y tomarán las medidas respectivas.
|
||||||
|
- Se realizará un acompañamiento a la persona agredida y se apoyará.
|
||||||
|
- Si el incidente se hace público, Angular Hispano no se hace responsable de los perjuicios que esto pueda ocasionar en el agresor o el agredido.
|
||||||
|
|
||||||
|
## 6. Alcance
|
||||||
|
Esperamos que todos los participantes de la comunidad (organizadores, voluntarios, contribuyentes pagados o de otro modo; patrocinadores; y otros invitados) se atengan a este Código de Conducta en todos los espacios virtuales y presenciales, así como en todas las comunicaciones de uno-a-uno pertinentes la comunidad.
|
||||||
|
|
||||||
|
### Colaboradores
|
||||||
|
|
||||||
|
- Alejandra Giraldo
|
||||||
|
- Vanessa Marely
|
||||||
|
- Mariano Alvarez
|
||||||
|
- Andrés Villanueva
|
||||||
|
- Michael Prentice
|
||||||
|
- javascript&friends
|
||||||
|
- Angular
|
||||||
|
- She Codes Angular
|
||||||
|
- Colombia dev
|
359
CONTRIBUTING.en.md
Normal file
359
CONTRIBUTING.en.md
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
# Contributing to Angular
|
||||||
|
|
||||||
|
We would love for you to contribute to Angular and help make it even better than it is today!
|
||||||
|
As a contributor, here are the guidelines we would like you to follow:
|
||||||
|
|
||||||
|
- [Code of Conduct](#coc)
|
||||||
|
- [Question or Problem?](#question)
|
||||||
|
- [Issues and Bugs](#issue)
|
||||||
|
- [Feature Requests](#feature)
|
||||||
|
- [Submission Guidelines](#submit)
|
||||||
|
- [Coding Rules](#rules)
|
||||||
|
- [Commit Message Guidelines](#commit)
|
||||||
|
- [Signing the CLA](#cla)
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="coc"></a> Code of Conduct
|
||||||
|
|
||||||
|
Help us keep Angular open and inclusive.
|
||||||
|
Please read and follow our [Code of Conduct][coc].
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="question"></a> Got a Question or Problem?
|
||||||
|
|
||||||
|
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
||||||
|
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
||||||
|
|
||||||
|
Stack Overflow is a much better place to ask questions since:
|
||||||
|
|
||||||
|
- 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
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="issue"></a> Found a Bug?
|
||||||
|
|
||||||
|
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
||||||
|
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="feature"></a> Missing a Feature?
|
||||||
|
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
||||||
|
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
||||||
|
|
||||||
|
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
||||||
|
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
||||||
|
|
||||||
|
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
||||||
|
|
||||||
|
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="submit"></a> Submission Guidelines
|
||||||
|
|
||||||
|
|
||||||
|
### <a name="submit-issue"></a> Submitting an Issue
|
||||||
|
|
||||||
|
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||||
|
|
||||||
|
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
|
||||||
|
In order to reproduce bugs, we require that you provide a minimal reproduction.
|
||||||
|
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
||||||
|
|
||||||
|
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 require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
||||||
|
Often, developers 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.
|
||||||
|
|
||||||
|
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
||||||
|
|
||||||
|
|
||||||
|
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||||
|
|
||||||
|
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 that relates to your submission.
|
||||||
|
You don't want to duplicate existing efforts.
|
||||||
|
|
||||||
|
2. 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 upfront helps to ensure that we're ready to accept your work.
|
||||||
|
|
||||||
|
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||||
|
We cannot accept code without a signed CLA.
|
||||||
|
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||||
|
|
||||||
|
4. Fork the angular/angular repo.
|
||||||
|
|
||||||
|
5. Make your changes in a new git branch:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git checkout -b my-fix-branch master
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Create your patch, **including appropriate test cases**.
|
||||||
|
|
||||||
|
7. Follow our [Coding Rules](#rules).
|
||||||
|
|
||||||
|
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||||
|
|
||||||
|
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
||||||
|
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git commit -a
|
||||||
|
```
|
||||||
|
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||||
|
|
||||||
|
10. Push your branch to GitHub:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git push origin my-fix-branch
|
||||||
|
```
|
||||||
|
|
||||||
|
11. In GitHub, send a pull request to `angular:master`.
|
||||||
|
|
||||||
|
If we ask for changes via code reviews then:
|
||||||
|
|
||||||
|
* Make the required updates.
|
||||||
|
* Re-run the Angular test suites to ensure tests are still passing.
|
||||||
|
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git rebase master -i
|
||||||
|
git push -f
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! Thank you for your contribution!
|
||||||
|
|
||||||
|
|
||||||
|
#### After your pull request is merged
|
||||||
|
|
||||||
|
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||||
|
|
||||||
|
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git push origin --delete my-fix-branch
|
||||||
|
```
|
||||||
|
|
||||||
|
* Check out the master branch:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git checkout master -f
|
||||||
|
```
|
||||||
|
|
||||||
|
* Delete the local branch:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git branch -D my-fix-branch
|
||||||
|
```
|
||||||
|
|
||||||
|
* Update your master with the latest upstream version:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git pull --ff upstream master
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="rules"></a> Coding Rules
|
||||||
|
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||||
|
|
||||||
|
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||||
|
* All public API methods **must be documented**.
|
||||||
|
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||||
|
|
||||||
|
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="commit"></a> Commit Message Format
|
||||||
|
|
||||||
|
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||||
|
|
||||||
|
We have very precise rules over how our Git commit messages must be formatted.
|
||||||
|
This format leads to **easier to read commit history**.
|
||||||
|
|
||||||
|
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
<header>
|
||||||
|
<BLANK LINE>
|
||||||
|
<body>
|
||||||
|
<BLANK LINE>
|
||||||
|
<footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||||
|
|
||||||
|
The `body` is mandatory for all commits except for those of scope "docs".
|
||||||
|
When the body is required it must be at least 20 characters long.
|
||||||
|
|
||||||
|
The `footer` is optional.
|
||||||
|
|
||||||
|
Any line of the commit message cannot be longer than 100 characters.
|
||||||
|
|
||||||
|
|
||||||
|
#### <a href="commit-header"></a>Commit Message Header
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <short summary>
|
||||||
|
│ │ │
|
||||||
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
|
│ │
|
||||||
|
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||||
|
│ elements|forms|http|language-service|localize|platform-browser|
|
||||||
|
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||||
|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||||
|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||||
|
│
|
||||||
|
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||||
|
```
|
||||||
|
|
||||||
|
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||||
|
|
||||||
|
|
||||||
|
##### Type
|
||||||
|
|
||||||
|
Must be one of the following:
|
||||||
|
|
||||||
|
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||||
|
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||||
|
* **docs**: Documentation only changes
|
||||||
|
* **feat**: A new feature
|
||||||
|
* **fix**: A bug fix
|
||||||
|
* **perf**: A code change that improves performance
|
||||||
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
|
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||||
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
|
|
||||||
|
##### Scope
|
||||||
|
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||||
|
|
||||||
|
The following is the list of supported scopes:
|
||||||
|
|
||||||
|
* `animations`
|
||||||
|
* `bazel`
|
||||||
|
* `benchpress`
|
||||||
|
* `common`
|
||||||
|
* `compiler`
|
||||||
|
* `compiler-cli`
|
||||||
|
* `core`
|
||||||
|
* `elements`
|
||||||
|
* `forms`
|
||||||
|
* `http`
|
||||||
|
* `language-service`
|
||||||
|
* `localize`
|
||||||
|
* `platform-browser`
|
||||||
|
* `platform-browser-dynamic`
|
||||||
|
* `platform-server`
|
||||||
|
* `platform-webworker`
|
||||||
|
* `platform-webworker-dynamic`
|
||||||
|
* `router`
|
||||||
|
* `service-worker`
|
||||||
|
* `upgrade`
|
||||||
|
* `zone.js`
|
||||||
|
|
||||||
|
There are currently a few exceptions to the "use package name" rule:
|
||||||
|
|
||||||
|
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||||
|
|
||||||
|
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||||
|
|
||||||
|
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||||
|
|
||||||
|
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||||
|
|
||||||
|
* `migrations`: used for changes to the `ng update` migrations.
|
||||||
|
|
||||||
|
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||||
|
|
||||||
|
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||||
|
|
||||||
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
||||||
|
|
||||||
|
|
||||||
|
##### Summary
|
||||||
|
|
||||||
|
Use the summary field to provide a succinct description of the change:
|
||||||
|
|
||||||
|
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
|
* don't capitalize the first letter
|
||||||
|
* no dot (.) at the end
|
||||||
|
|
||||||
|
|
||||||
|
#### Commit Message Body
|
||||||
|
|
||||||
|
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||||
|
|
||||||
|
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
||||||
|
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
||||||
|
|
||||||
|
|
||||||
|
#### Commit Message Footer
|
||||||
|
|
||||||
|
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||||
|
|
||||||
|
```
|
||||||
|
BREAKING CHANGE: <breaking change summary>
|
||||||
|
<BLANK LINE>
|
||||||
|
<breaking change description + migration instructions>
|
||||||
|
<BLANK LINE>
|
||||||
|
<BLANK LINE>
|
||||||
|
Fixes #<issue number>
|
||||||
|
```
|
||||||
|
|
||||||
|
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||||
|
|
||||||
|
|
||||||
|
### Revert commits
|
||||||
|
|
||||||
|
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||||
|
|
||||||
|
The content of the commit message body should contain:
|
||||||
|
|
||||||
|
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||||
|
- a clear description of the reason for reverting the commit message.
|
||||||
|
|
||||||
|
|
||||||
|
## <a name="cla"></a> Signing the CLA
|
||||||
|
|
||||||
|
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||||
|
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||||
|
|
||||||
|
* For individuals, we have a [simple click-through form][individual-cla].
|
||||||
|
* For corporations, we'll need you to
|
||||||
|
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||||
|
|
||||||
|
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
||||||
|
|
||||||
|
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
||||||
|
|
||||||
|
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||||
|
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||||
|
* https://help.github.com/articles/about-commit-email-addresses/
|
||||||
|
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||||
|
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||||
|
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||||
|
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||||
|
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||||
|
[github]: https://github.com/angular/angular
|
||||||
|
[gitter]: https://gitter.im/angular/angular
|
||||||
|
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||||
|
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||||
|
[jsfiddle]: http://jsfiddle.net
|
||||||
|
[plunker]: http://plnkr.co/edit
|
||||||
|
[runnable]: http://runnable.com
|
||||||
|
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
357
CONTRIBUTING.md
357
CONTRIBUTING.md
@ -1,277 +1,243 @@
|
|||||||
# Contributing to Angular
|
# Contribuye a Angular
|
||||||
|
|
||||||
We would love for you to contribute to Angular and help make it even better than it is today!
|
¡Nos encantaría que contribuyeras a Angular y que ayudaras a hacerlo aún mejor de lo que es hoy!
|
||||||
As a contributor, here are the guidelines we would like you to follow:
|
Como colaborador, estos son los lineamientos que nos gustaría que siguieras:
|
||||||
|
|
||||||
- [Code of Conduct](#coc)
|
- [Código de conducta](#coc)
|
||||||
- [Question or Problem?](#question)
|
- [¿Preguntas o problemas?](#question)
|
||||||
- [Issues and Bugs](#issue)
|
- [_Issues_ y _bugs_](#issue)
|
||||||
- [Feature Requests](#feature)
|
- [Solicitud de funcionalidades](#feature)
|
||||||
- [Submission Guidelines](#submit)
|
- [Guía para la creación de issues y PRs](#submit)
|
||||||
- [Coding Rules](#rules)
|
- [Reglas del código](#rules)
|
||||||
- [Commit Message Guidelines](#commit)
|
- [Convención para el mensaje de los _commits_](#commit)
|
||||||
- [Signing the CLA](#cla)
|
- [Firma del Acuerdo de Licencia de Colaborador (CLA)](#cla)
|
||||||
|
|
||||||
|
|
||||||
## <a name="coc"></a> Code of Conduct
|
## <a name="coc"></a> Código de conducta
|
||||||
|
|
||||||
Help us keep Angular open and inclusive.
|
Ayúdanos a mantener Angular abierto e inclusivo.
|
||||||
Please read and follow our [Code of Conduct][coc].
|
Por favor lee y sigue nuestro [Código de conducta][coc].
|
||||||
|
|
||||||
|
|
||||||
## <a name="question"></a> Got a Question or Problem?
|
## <a name="question"></a> ¿Tienes alguna pregunta o problema?
|
||||||
|
|
||||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
No abras *issues* para preguntas de soporte general ya que queremos mantener los *issues* de GitHub para reporte de *bugs* y solicitud de funcionalidades.
|
||||||
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
En su lugar, recomendamos utilizar [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) para hacer preguntas relacionadas con soporte. Al crear una nueva pregunta en Stack Overflow, asegúrate de agregar el etiqueta (tag) de `angular`.
|
||||||
|
|
||||||
Stack Overflow is a much better place to ask questions since:
|
Stack Overflow es mucho mejor para hacer preguntas ya que:
|
||||||
|
|
||||||
- there are thousands of people willing to help on Stack Overflow
|
- Hay miles de personas dispuestas a ayudar en preguntas y respuestas de Stack Overflow
|
||||||
- questions and answers stay available for public viewing so your question/answer might help someone else
|
que permanecen disponibles para el público, por lo que tu pregunta o respuesta podría ayudar a otra persona.
|
||||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
- El sistema de votación de Stack Overflow asegura que las mejores respuestas sobresalgan y sean visibles.
|
||||||
|
|
||||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
Para ahorrar tu tiempo y el nuestro, cerraremos sistemáticamente todos los *issues* que sean solicitudes de soporte general y redirigiremos a las personas a Stack Overflow.
|
||||||
|
|
||||||
If you would like to chat about the question in real-time, you can reach out via [our Discord server][discord].
|
Si deseas chatear sobre alguna pregunta en tiempo real, puedes hacerlo a través de nuestro [canal de Gitter][gitter].
|
||||||
|
|
||||||
|
|
||||||
## <a name="issue"></a> Found a Bug?
|
## <a name="issue"></a> ¿Encontraste un Bug?
|
||||||
|
|
||||||
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
Si encontraste un error en el código fuente, puedes ayudarnos [creando un *issue*](#submit-issue) en nuestro [repositorio de GitHub][github].
|
||||||
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
O incluso mejor, puedes [crear un *Pull Request*](#submit-pr) con la solución.
|
||||||
|
|
||||||
|
|
||||||
## <a name="feature"></a> Missing a Feature?
|
## <a name="feature"></a> ¿Falta alguna funcionalidad?
|
||||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
Puedes solicitar una nueva funcionalidad [creando un *issue*](#submit-issue) en nuestro repositorio de GitHub.
|
||||||
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
Si deseas implementar una nueva funcionalidad, por favor considera el tamaño del cambio para determinar los pasos correctos para continuar:
|
||||||
|
|
||||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
* Para un **cambio significativo**, primero abre un *issue* y describe tu propuesta para que pueda ser discutida.
|
||||||
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
Este proceso nos permite coordinar mejor nuestros esfuerzos, evitar trabajo duplicado y ayudarte a diseñar el cambio para que sea aceptado con éxito en el proyecto.
|
||||||
|
|
||||||
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
**Nota**: Agregar un nuevo tema a la documentación o reescribir significativamente un tema, también cuenta como *cambio significativo*.
|
||||||
|
|
||||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
* **Cambios pequeños** pueden ser elaborados y directamente [creados como un _pull request_](#submit-pr).
|
||||||
|
|
||||||
|
|
||||||
## <a name="submit"></a> Submission Guidelines
|
## <a name="submit"></a> Guía para la creación de issues y PRs
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-issue"></a> Submitting an Issue
|
### <a name="submit-issue"></a> Creación de _issues_
|
||||||
|
|
||||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
Antes de crear un *issue*, por favor busca en el el *issue tracker*, quizá un *issue* para tu problema ya existe y la discusión puede informarte sobre soluciones alternativas disponibles.
|
||||||
|
|
||||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
|
Queremos solucionar todos los problemas lo antes posible, pero antes de corregir un bug necesitamos reproducirlo y confirmarlo.
|
||||||
In order to reproduce bugs, we require that you provide a minimal reproduction.
|
Para reproducir errores, requerimos que proporciones una reproducción mínima.
|
||||||
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
Tener un escenario reproducible mínimo nos brinda una gran cantidad de información importante sin tener que ir y venir con preguntas adicionales.
|
||||||
|
|
||||||
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.
|
Una reproducción mínima nos permite confirmar rápidamente un bug (o señalar un problema de código), así también confirmar que estamos solucionando el problema correcto.
|
||||||
|
|
||||||
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
Requerimos una reproducción mínima para ahorrar tiempo a los encargados del mantenimiento y en última instancia, poder corregir más bugs.
|
||||||
Often, developers find coding problems themselves while preparing a minimal reproduction.
|
A menudo los desarrolladores encuentran problemas de código mientras preparan una reproducción mínima.
|
||||||
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.
|
Entendemos que a veces puede ser difícil extraer porciones esenciales de código de un código más grande, pero realmente necesitamos aislar el problema antes de poder solucionarlo.
|
||||||
|
|
||||||
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.
|
Desafortunadamente no podemos investigar/corregir errores sin una reproducción mínima, por lo que si no tenemos tu retroalimentación del bug, vamos a cerrar el *issue* ya que no tiene suficiente información para reproducirse.
|
||||||
|
|
||||||
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
Puedes presentar nuevos *issues* seleccionando nuestra [plantilla de _issues_](https://github.com/angular/angular/issues/new/choose) y complentando la plantilla.
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
### <a name="submit-pr"></a> Creación de un Pull Requests (PR)
|
||||||
|
|
||||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
Antes de crear tu Pull Request (PR) considera los siguientes lineamientos:
|
||||||
|
|
||||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
|
1. Busca en [GitHub](https://github.com/angular/angular/pulls) PRs que estén abiertos o cerrados y que estén relacionados con el que vas a crear.
|
||||||
You don't want to duplicate existing efforts.
|
No deseas duplicar los esfuerzos existentes.
|
||||||
|
|
||||||
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
2. Asegúrate de que el PR describa el problema que estás solucionando o que documente el diseño de la funcionalidad que deseas agregar.
|
||||||
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
Discutir el diseño por adelantado ayuda a garantizar que estemos listos para aceptar tu trabajo.
|
||||||
|
|
||||||
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
3. Por favor firma nuestro [Acuerdo de Licencia de Colaborador (CLA)](#cla) antes de crear PRs.
|
||||||
We cannot accept code without a signed CLA.
|
No podemos aceptar el código sin el Acuerdo de Licencia de Colaborador (CLA) firmado.
|
||||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
Asegúrate de crear todas las contribuciones de Git con la dirección de correo electrónico asociada con tu firma del Acuerdo de Licencia de Colaborador (CLA).
|
||||||
|
|
||||||
4. Fork the angular/angular repo.
|
4. Haz *fork* del repositorio angular/angular.
|
||||||
|
|
||||||
5. Make your changes in a new git branch:
|
5. Haz tus cambios en una nueva rama de Git:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git checkout -b my-fix-branch master
|
git checkout -b my-fix-branch master
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Create your patch, **including appropriate test cases**.
|
6. Crea tu correción, **incluyendo casos de prueba apropiados**.
|
||||||
|
|
||||||
7. Follow our [Coding Rules](#rules).
|
7. Sigue nuestras [Reglas de código](#rules).
|
||||||
|
|
||||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
8. Ejecuta todo el conjunto de pruebas de Angular, tal como está descrito en la [documentación del desarrollador][dev-doc], y asegúrate de que todas las pruebas pasen.
|
||||||
|
|
||||||
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
9. Crea un commit de tus cambios utilizando un mensaje de commit descriptivo que siga nuestra [convención para el mensaje de los commits](#commit).
|
||||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
Es necesario cumplir con estas convenciones porque las notas de las versiones se generan automáticamente a partir de estos mensajes.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git commit --all
|
git commit -a
|
||||||
```
|
```
|
||||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
Nota: la opción de la línea de comandos de Git `-a` automaticamente hará "add" y "rm" a los archivos editados.
|
||||||
|
|
||||||
10. Push your branch to GitHub:
|
10. Haz push de tu rama a GitHub:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git push origin my-fix-branch
|
git push origin my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
11. In GitHub, send a pull request to `angular:master`.
|
11. En GitHub, crea un pull request a `angular:master`.
|
||||||
|
|
||||||
|
Si solicitamos cambios a través de revisiones de código, sigue las siguientes indicaciones:
|
||||||
|
|
||||||
|
* Haz los cambios requeridos.
|
||||||
|
* Ejecuta nuevamente el conjunto de pruebas de Angular para asegurar que todas las pruebas aún están pasando.
|
||||||
|
* Haz rebase de tu rama a la rama master y haz push con la opción `-f` a tu repositorio de Github (esto actualizará tu Pull Request):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git rebase master -i
|
||||||
|
git push -f
|
||||||
|
```
|
||||||
|
|
||||||
|
¡Es todo! ¡Muchas gracias por tu contribución!
|
||||||
|
|
||||||
|
|
||||||
#### Addressing review feedback
|
#### Después del merge de tu pull request
|
||||||
|
|
||||||
If we ask for changes via code reviews then:
|
Después de que se hizo merge de tu pull request, puedes eliminar de forma segura tu rama y hacer pull de los cambios del repositorio principal (upstream):
|
||||||
|
|
||||||
1. Make the required updates to the code.
|
* Elimina la rama remota en GitHub a través de la interfaz de usuario web de GitHub o en tu línea de comandos de la siguiente manera:
|
||||||
|
|
||||||
2. Re-run the Angular test suites to ensure tests are still passing.
|
|
||||||
|
|
||||||
3. Create a fixup commit and push to your GitHub repository (this will update your Pull Request):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git commit --all --fixup HEAD
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
For more info on working with fixup commits see [here](docs/FIXUP_COMMITS.md).
|
|
||||||
|
|
||||||
That's it! Thank you for your contribution!
|
|
||||||
|
|
||||||
|
|
||||||
##### Updating the commit message
|
|
||||||
|
|
||||||
A reviewer might often suggest changes to a commit message (for example, to add more context for a change or adhere to our [commit message guidelines](#commit)).
|
|
||||||
In order to update the commit message of the last commit on your branch:
|
|
||||||
|
|
||||||
1. Check out your branch:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git checkout my-fix-branch
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Amend the last commit and modify the commit message:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git commit --amend
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Push to your GitHub repository:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git push --force-with-lease
|
|
||||||
```
|
|
||||||
|
|
||||||
> NOTE:<br />
|
|
||||||
> If you need to update the commit message of an earlier commit, you can use `git rebase` in interactive mode.
|
|
||||||
> See the [git docs](https://git-scm.com/docs/git-rebase#_interactive_mode) for more details.
|
|
||||||
|
|
||||||
|
|
||||||
#### After your pull request is merged
|
|
||||||
|
|
||||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
|
||||||
|
|
||||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git push origin --delete my-fix-branch
|
git push origin --delete my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
* Check out the master branch:
|
* Muévete a la rama master:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git checkout master -f
|
git checkout master -f
|
||||||
```
|
```
|
||||||
|
|
||||||
* Delete the local branch:
|
* Elimina tu rama local:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git branch -D my-fix-branch
|
git branch -D my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
* Update your master with the latest upstream version:
|
* Actualiza tu rama master con la última versión del fork (upstream):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git pull --ff upstream master
|
git pull --ff upstream master
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a name="rules"></a> Coding Rules
|
## <a name="rules"></a> Reglas del código
|
||||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
Para garantizar la coherencia en todo el código fuente, ten en cuenta estas reglas mientras trabajas:
|
||||||
|
|
||||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
* Todas las funcionalidades o solución de bugs **deben ser probadas** por una o más pruebas (pruebas unitarias).
|
||||||
* All public API methods **must be documented**.
|
* Todos los métodos públicos del API **deben ser documentados**.
|
||||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
* Seguimos la [guía de estilo JavaScript de Google][js-style-guide], pero cada línea no debe exceder **100 caracteres**.
|
||||||
|
|
||||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
Un formateador automatizado está disponible, revisar [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||||
|
|
||||||
|
|
||||||
## <a name="commit"></a> Commit Message Format
|
## <a name="commit"></a> Formato para el mensaje de los commits
|
||||||
|
|
||||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
*Esta especificación está inspirada y reemplaza el [Formato de mensaje de commits de AngularJS][commit-message-format].*
|
||||||
|
|
||||||
We have very precise rules over how our Git commit messages must be formatted.
|
Tenemos reglas muy precisas sobre cómo deben formatearse nuestros mensajes de los commits de Git.
|
||||||
This format leads to **easier to read commit history**.
|
Este formato permite tener **un historial de commits más facil de leer**.
|
||||||
|
|
||||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
Cada mensaje de un commit consta del **header**, el **body**, y el **footer**.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
<header>
|
<header>
|
||||||
<BLANK LINE>
|
<LINEA VACIA>
|
||||||
<body>
|
<body>
|
||||||
<BLANK LINE>
|
<LINEA VACIA>
|
||||||
<footer>
|
<footer>
|
||||||
```
|
```
|
||||||
|
|
||||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
El `header` es obligatorio y debe ajustarse al formato del [mensaje del header del commit](#commit-header).
|
||||||
|
|
||||||
The `body` is mandatory for all commits except for those of scope "docs".
|
El `body` es obligatorio para todos los commits excepto los que tenga scope "docs".
|
||||||
When the body is required it must be at least 20 characters long.
|
Cuando el body es requerido debe tener al menos 20 caracteres.
|
||||||
|
|
||||||
The `footer` is optional.
|
El `footer` es opcional.
|
||||||
|
|
||||||
Any line of the commit message cannot be longer than 100 characters.
|
Cualquier línea del mensaje del commit no puede tener más de 100 caracteres.
|
||||||
|
|
||||||
|
|
||||||
#### <a href="commit-header"></a>Commit Message Header
|
#### <a href="commit-header"></a>Mensaje del header del commit
|
||||||
|
|
||||||
```
|
```
|
||||||
<type>(<scope>): <short summary>
|
<tipo>(<alcance>): <resumen>
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
│ │ └─⫸ Resumen corto escrito en modo imperativo, tiempo presente. Sin mayúsculas. Sin punto final.
|
||||||
│ │
|
│ │
|
||||||
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
│ └─⫸ Alcance del commit: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||||
│ elements|forms|http|language-service|localize|platform-browser|
|
│ elements|forms|http|language-service|localize|platform-browser|
|
||||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||||
│
|
│
|
||||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
└─⫸ Tipo de commit: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||||
```
|
```
|
||||||
|
|
||||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
El `<tipo>` y `<resumen>` son obligatorios, el `(<alcance>)` es opcional.
|
||||||
|
|
||||||
|
|
||||||
##### Type
|
##### Tipo
|
||||||
|
|
||||||
Must be one of the following:
|
El tipo debe ser uno de los siguientes:
|
||||||
|
|
||||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
* **build**: cambios que afectan el sistema de compilación o dependencias externas (ejemplos de scopes: gulp, broccoli, npm)
|
||||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
* **ci**: cambios en nuestros archivos y scripts de configuración de CI (ejemplos de scopes: Circle, BrowserStack, SauceLabs)
|
||||||
* **docs**: Documentation only changes
|
* **docs**: cambios en la documentación
|
||||||
* **feat**: A new feature
|
* **feat**: una nueva funcionalidad
|
||||||
* **fix**: A bug fix
|
* **fix**: una solución de un bug
|
||||||
* **perf**: A code change that improves performance
|
* **perf**: un cambio de código que mejora el rendimiento.
|
||||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
* **refactor**: un cambio de código que no corrige ningún error ni agrega ninguna funcionalidad
|
||||||
* **test**: Adding missing tests or correcting existing tests
|
* **style**: cambios que no afectan el significado del código (espacios en blanco, formato, falta de punto y coma, etc.)
|
||||||
|
* **test**: se agregan pruebas faltantes o se corrigen pruebas existentes
|
||||||
|
|
||||||
|
|
||||||
##### Scope
|
##### Alcance
|
||||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
El alcance debe ser el nombre del paquete npm afectado (tal como lo percibe la persona que lee el registro de cambios generado a partir de los mensajes de commit).
|
||||||
|
|
||||||
The following is the list of supported scopes:
|
La siguiente es la lista de alcances permitidos:
|
||||||
|
|
||||||
* `animations`
|
* `animations`
|
||||||
* `bazel`
|
* `bazel`
|
||||||
@ -295,80 +261,73 @@ The following is the list of supported scopes:
|
|||||||
* `upgrade`
|
* `upgrade`
|
||||||
* `zone.js`
|
* `zone.js`
|
||||||
|
|
||||||
There are currently a few exceptions to the "use package name" rule:
|
Actualmente hay algunas excepciones a la regla "usar el nombre de paquete":
|
||||||
|
|
||||||
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
* `packaging`: usado para cambios que cambian el diseño de los paquetes de npm en todos nuestros paquetes. Ejemplos: cambios de la ruta públic, package.json cambios hechos a todos los paquetes, cambios a archivos o formatos d.ts, cambios a bundles, etc.
|
||||||
|
|
||||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
* `changelog`: utilizado para actualizar las notas de la versión en CHANGELOG.md
|
||||||
|
|
||||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
* `dev-infra`: utilizado para cambios relacionados con dev-infra dentro de los directorios /scripts, /tools y /dev-infra
|
||||||
|
|
||||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
* `docs-infra`: utilizado para cambios relacionados con la documentación (angular.io) dentro del directorio /aio del repositorio
|
||||||
|
|
||||||
* `migrations`: used for changes to the `ng update` migrations.
|
* `migrations`: utilizado para los cambios en las migraciones `ng update`.
|
||||||
|
|
||||||
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
* `ngcc`: usado para los cambios del [Compilador de compatibilidad de Angular](./packages/compiler-cli/ngcc/README.md)
|
||||||
|
|
||||||
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
* `ve`: utilizado para cambios específicos de ViewEngine (legacy compiler/renderer).
|
||||||
|
|
||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
* alcance vacío: útil para cambios de `style`, `test` y `refactor` que se realizan en todos los paquetes (ejemplo: `style: add missing semicolons`) y para cambios de la documentación que no están relacionados a un paquete en específico(ejemplo: `docs: corrige error gramatical en el tutorial`).
|
||||||
|
|
||||||
|
|
||||||
##### Summary
|
##### Resumen
|
||||||
|
|
||||||
Use the summary field to provide a succinct description of the change:
|
Usa el campo resumen para proporcionar una descripción breve del cambio:
|
||||||
|
|
||||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
* usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios"
|
||||||
* don't capitalize the first letter
|
* no debe de contener ninguna letra mayúscula
|
||||||
* no dot (.) at the end
|
* no debe de conter punto (.) al final
|
||||||
|
|
||||||
|
|
||||||
#### Commit Message Body
|
#### Mensaje del cuerpo del commit
|
||||||
|
|
||||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
Tal como en el resumen, usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios".
|
||||||
|
|
||||||
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
Explica la razón del cambio en el el mensaje del cuerpo del commit. Este mensaje de confirmación debe explicar _por qué_ está realizando el cambio.
|
||||||
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
Puedes incluir una comparación del comportamiento anterior con el nuevo comportamiento para ilustrar el impacto del cambio.
|
||||||
|
|
||||||
|
|
||||||
#### Commit Message Footer
|
#### Mensaje del footer del commit
|
||||||
|
|
||||||
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
El footer puede contener información sobre cambios significativos y también es el lugar para hacer referencia a issues de GitHub, tickets de Jira y otros PRs que están relacionados con el commit.
|
||||||
|
|
||||||
```
|
```
|
||||||
BREAKING CHANGE: <breaking change summary>
|
CAMBIO SIGNIFICATIVO: <resumen del cambio significativo>
|
||||||
<BLANK LINE>
|
<LINEA VACIA>
|
||||||
<breaking change description + migration instructions>
|
<descripción del cambio significativo + instrucciones para la migración>
|
||||||
<BLANK LINE>
|
<LINEA VACIA>
|
||||||
<BLANK LINE>
|
<LINEA VACIA>
|
||||||
Fixes #<issue number>
|
Fix #<issue número>
|
||||||
```
|
```
|
||||||
|
|
||||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
La sección de cambios significativos debería comenzar con la frase "CAMBIO SIGNIFICATIVO: " seguido de un resumen del cambio significativo, una línea en blanco y una descripción detallada del cambio significativo que también incluya instrucciones de migración.
|
||||||
|
|
||||||
|
|
||||||
### Revert commits
|
### Revirtiendo commits
|
||||||
|
|
||||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
Si el commit revierte un commit previo, el commit debería comenzar con `revert: `, seguido por el header del commit revertido.
|
||||||
|
|
||||||
The content of the commit message body should contain:
|
El contenido del mensaje del commit debería contener:
|
||||||
|
|
||||||
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
- Información sobre el SHA del commit que se revierte en el siguiente formato: `Esto revierte el commit <SHA>`,
|
||||||
- a clear description of the reason for reverting the commit message.
|
- Una descripción clara de la razón para revertir el mensaje del _commit_.
|
||||||
|
|
||||||
|
|
||||||
## <a name="cla"></a> Signing the CLA
|
## <a name="cla"></a> Firma del Acuerdo de Licencia de Colaborador (CLA)
|
||||||
|
|
||||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
Por favor firma nuestro Acuerdo de Licencia de Colaborador (CLA) cuando creas tu primer pull request. Para que cualquier cambio de código sea aceptado, el Acuerdo de Licencia de Colaborador (CLA) debe ser firmado. Es un proceso rápido con nuestro CLA assistant que está integrado con nuestro CI.
|
||||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
|
||||||
|
|
||||||
* For individuals, we have a [simple click-through form][individual-cla].
|
Los siguientes documentos pueden ayudarte a resolver problemas con cuentas de GitHub y múltiples direcciones de correo electrónico:
|
||||||
* For corporations, we'll need you to
|
|
||||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
|
||||||
|
|
||||||
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
|
||||||
|
|
||||||
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
|
||||||
|
|
||||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||||
@ -384,7 +343,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
|||||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||||
[github]: https://github.com/angular/angular
|
[github]: https://github.com/angular/angular
|
||||||
[discord]: https://discord.gg/angular
|
[gitter]: https://gitter.im/angular/angular
|
||||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||||
[jsfiddle]: http://jsfiddle.net
|
[jsfiddle]: http://jsfiddle.net
|
||||||
|
26
README.en.md
Normal file
26
README.en.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||||
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[](https://www.npmjs.com/@angular/core)
|
||||||
|
|
||||||
|
|
||||||
|
# Angular
|
||||||
|
|
||||||
|
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
[Get started in 5 minutes][quickstart].
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
[Learn about the latest improvements][changelog].
|
||||||
|
|
||||||
|
## Want to help?
|
||||||
|
|
||||||
|
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||||
|
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||||
|
|
||||||
|
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||||
|
[quickstart]: https://angular.io/start
|
||||||
|
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||||
|
[ng]: https://angular.io
|
32
README.md
32
README.md
@ -1,27 +1,25 @@
|
|||||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
# Angular en español
|
||||||
[](https://discord.gg/angular)
|
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[](https://www.npmjs.com/@angular/core)
|
|
||||||
|
|
||||||
|
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa
|
||||||
|
TypeScript/JavaScript y otros lenguajes de programación.
|
||||||
|
|
||||||
# Angular
|
## ¿Quieres ayudar?
|
||||||
|
|
||||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
### Documentación en español
|
||||||
|
|
||||||
## Quickstart
|
¿Quieres mejorar la documentación? ¡Excelente! Lee nuestras pautas para
|
||||||
|
[colaborar](CONTRIBUTING.md) y luego revisa algunos de nuestras
|
||||||
|
[issues](https://github.com/angular-hispano/angular/issues).
|
||||||
|
|
||||||
[Get started in 5 minutes][quickstart].
|
### El framework
|
||||||
|
|
||||||
## Changelog
|
La colaboración para corregir errores y agregar funciones en el framework debe realizarse en inglés a través
|
||||||
|
del repositorio [angular/angular](https://github.com/angular/angular) upstream.
|
||||||
|
|
||||||
[Learn about the latest improvements][changelog].
|
## Guía rápida
|
||||||
|
|
||||||
## Want to help?
|
[Comienza a usarlo en 5 minutos](https://docs.angular.lat/start).
|
||||||
|
|
||||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
## Registro de cambios (Changelog)
|
||||||
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
|
||||||
|
|
||||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
[Últimas mejoras realizadas](CHANGELOG.md).
|
||||||
[quickstart]: https://angular.io/start
|
|
||||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
|
||||||
[ng]: https://angular.io
|
|
||||||
|
24
WORKSPACE
24
WORKSPACE
@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef",
|
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.0/rules_nodejs-2.2.0.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the rules_nodejs version and download npm dependencies
|
# Check the rules_nodejs version and download npm dependencies
|
||||||
@ -17,7 +17,7 @@ http_archive(
|
|||||||
# assert on that.
|
# assert on that.
|
||||||
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
||||||
|
|
||||||
check_rules_nodejs_version(minimum_version_string = "2.2.0")
|
check_rules_nodejs_version(minimum_version_string = "1.7.0")
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
@ -39,18 +39,23 @@ yarn_install(
|
|||||||
yarn_lock = "//:yarn.lock",
|
yarn_lock = "//:yarn.lock",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Install all bazel dependencies of the @npm npm packages
|
||||||
|
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||||
|
|
||||||
|
install_bazel_dependencies()
|
||||||
|
|
||||||
# Load angular dependencies
|
# Load angular dependencies
|
||||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||||
|
|
||||||
rules_angular_dev_dependencies()
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
# Load protractor dependencies
|
# Load protractor dependencies
|
||||||
load("@npm//@bazel/protractor:package.bzl", "npm_bazel_protractor_dependencies")
|
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||||
|
|
||||||
npm_bazel_protractor_dependencies()
|
npm_bazel_protractor_dependencies()
|
||||||
|
|
||||||
# Load karma dependencies
|
# Load karma dependencies
|
||||||
load("@npm//@bazel/karma:package.bzl", "npm_bazel_karma_dependencies")
|
load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies")
|
||||||
|
|
||||||
npm_bazel_karma_dependencies()
|
npm_bazel_karma_dependencies()
|
||||||
|
|
||||||
@ -63,6 +68,11 @@ load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
|
|||||||
|
|
||||||
browser_repositories()
|
browser_repositories()
|
||||||
|
|
||||||
|
# Setup the rules_typescript tooolchain
|
||||||
|
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
||||||
|
|
||||||
|
ts_setup_workspace()
|
||||||
|
|
||||||
# Setup the rules_sass toolchain
|
# Setup the rules_sass toolchain
|
||||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||||
|
|
||||||
@ -81,8 +91,8 @@ rbe_autoconfig(
|
|||||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||||
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||||
# need to pull the image and run it in order determine the toolchain configuration. See:
|
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.5.1/configs/ubuntu16_04_clang/versions.bzl
|
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
|
||||||
base_container_digest = "sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1",
|
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
|
||||||
# Note that if you change the `digest`, you might also need to update the
|
# Note that if you change the `digest`, you might also need to update the
|
||||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||||
|
168
aio/README.md
168
aio/README.md
@ -1,141 +1,131 @@
|
|||||||
# Angular documentation project (https://angular.io)
|
# Proyecto de documentación Angular (https://docs.angular.lat)
|
||||||
|
|
||||||
Everything in this folder is part of the documentation project. This includes
|
Todo en esta carpeta es parte del proyecto de documentación. Esto incluye:
|
||||||
|
|
||||||
* the web site for displaying the documentation
|
* El sitio web para mostrar la documentación
|
||||||
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
* La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web.
|
||||||
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
* Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos.
|
||||||
|
|
||||||
<a name="developer-tasks"></a>
|
## Tareas de desarrollador
|
||||||
## Developer tasks
|
|
||||||
|
|
||||||
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación.
|
||||||
You should run all these tasks from the `angular/aio` folder.
|
Debes ejecutar todas estas tareas desde la carpeta `angular/aio`.
|
||||||
Here are the most important tasks you might need to use:
|
Aquí están las tareas más importantes que podrías necesitar usar:
|
||||||
|
|
||||||
* `yarn` - install all the dependencies.
|
* `yarn` - instalar todas las dependencias.
|
||||||
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
* `yarn setup` - instalar todas las dependencias, boilerplate, stackblitz, zips y ejecuta dgeni en los documentos.
|
||||||
* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate.
|
* `yarn setup-local` - igual que `setup`, pero crea los paquetes de Angular a partir del código y usa estas versiones construidas localmente (en lugar de las recuperadas desde npm) para aio y ejemplos de documentos boilerplate.
|
||||||
|
|
||||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
* `yarn build` - crear una compilación de producción de la aplicación (después de instalar dependencias, boilerplate, etc).
|
||||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
* `yarn build-local` - igual que `build`, pero usa `setup-local` en lugar de `setup`.
|
||||||
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` (pre-Ivy) mode in aio.
|
* `yarn build-local-with-viewengine` - igual que `build-local`, pero además también enciende el modo `ViewEngine` (pre-Ivy) en aio.
|
||||||
(Note: To turn on `ViewEngine` mode in docs examples, see `yarn boilerplate:add:viewengine` below.)
|
(Nota: Encender el modo `ViewEngine` en ejemplos de documentos, ver `yarn boilerplate:add:viewengine` abajo.)
|
||||||
|
|
||||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
* `yarn start` - ejecutar un servidor web de desarrollo que observa los archivos; luego crea el doc-viewer y vuelve a cargar la página, según sea necesario.
|
||||||
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
* `yarn serve-and-sync` - ejecutar ambos, el `docs-watch` y `start` en la misma consola.
|
||||||
* `yarn lint` - check that the doc-viewer code follows our style rules.
|
* `yarn lint` - comprobar que el código del doc-viewer sigue nuestras reglas de estilo.
|
||||||
* `yarn test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.
|
* `yarn test` - observar todos los archivos de origen, para el doc-viewer, y ejecuta todas las pruebas unitarias cuando haya algún cambio.
|
||||||
* `yarn test --watch=false` - run all the unit tests once.
|
* `yarn test --watch=false` -ejecutar todas las pruebas unitarias una sola vez.
|
||||||
* `yarn e2e` - run all the e2e tests for the doc-viewer.
|
* `yarn e2e` - ejecutar todas las pruebas de e2e para el doc-viewer.
|
||||||
|
|
||||||
* `yarn docs` - generate all the docs from the source files.
|
* `yarn docs` - generar toda la documentación desde los archivos fuente.
|
||||||
* `yarn docs-watch` - watch the Angular source and the docs files and run a short-circuited doc-gen for the docs that changed.
|
* `yarn docs-watch` - observar el código Angular, los archivos de documentación y ejecutar un 'doc-gen' en corto circuito para los documentos que fueron cambiados.
|
||||||
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
* `yarn docs-lint` - comprobar que el código del documento generado sigue nuestras reglas de estilo.
|
||||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
* `yarn docs-test` - ejecutar las pruebas unitarias para el código de generación de doc.
|
||||||
|
|
||||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
* `yarn boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente.
|
||||||
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
|
* `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy).
|
||||||
|
|
||||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
* `yarn boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`.
|
||||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
* `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos.
|
||||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
* `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos.
|
||||||
|
|
||||||
* `yarn example-e2e` - run all e2e tests for examples. Available options:
|
* `yarn example-e2e` - ejecutar todas las pruebas e2e para ejemplos. Opciones disponibles:
|
||||||
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
|
- `--setup`: generar boilerplate, forzar la actualización del controlador web y otras configuraciones, luego ejecutar las pruebas.
|
||||||
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
|
- `--local`: ejecutar pruebas e2e con la versión local de Angular contenida en la carpeta "dist".
|
||||||
_Requires `--setup` in order to take effect._
|
_Requiere `--setup` para que surta efecto._
|
||||||
- `--viewengine`: run e2e tests in `ViewEngine` (pre-Ivy) mode.
|
- `--viewengine`: ejecutar pruebas e2e en modo `ViewEngine` (pre-Ivy).
|
||||||
- `--filter=foo`: limit e2e tests to those containing the word "foo".
|
- `--filter=foo`: limitar pruebas e2e a las que contienen la palabra "foo".
|
||||||
|
|
||||||
> **Note for Windows users**
|
> **Nota para usuarios Windows**
|
||||||
>
|
>
|
||||||
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
> Configurar los ejemplos implica crear algunos [enlaces simbólicos](https://es.wikipedia.org/wiki/Enlace_simb%C3%B3lico) (ver [Aquí](./tools/examples/README.md#symlinked-node_modules) para más detalles). En Windows, esto requiere tener [Habilitado el Modo de desarrollador ](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (compatible con Windows 10 o más reciente) o ejecutar los comandos de configuración cómo administrador.
|
||||||
>
|
>
|
||||||
> The affected commands are:
|
> Los comandos afectados son:
|
||||||
> - `yarn setup` / `yarn setup-*`
|
> - `yarn setup` / `yarn setup-*`
|
||||||
> - `yarn build` / `yarn build-*`
|
> - `yarn build` / `yarn build-*`
|
||||||
> - `yarn boilerplate:add`
|
> - `yarn boilerplate:add`
|
||||||
> - `yarn example-e2e --setup`
|
> - `yarn example-e2e --setup`
|
||||||
|
|
||||||
## Using ServiceWorker locally
|
## Usando ServiceWorker localmente
|
||||||
|
|
||||||
Running `yarn start` (even when explicitly targeting production mode) does not set up the
|
Ejecutando `yarn start` (incluso cuando se apunta explícitamente al modo de producción) no configura el
|
||||||
ServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then
|
ServiceWorker. Si quieres probar el ServiceWorker localmente, puedes usar `yarn build` y luego
|
||||||
serve the files in `dist/` with `yarn http-server dist -p 4200`.
|
ejecutar los archivos en `dist/` con `yarn http-server dist -p 4200`.
|
||||||
|
|
||||||
|
|
||||||
## Guide to authoring
|
## Guía de autoría
|
||||||
|
Existen dos tipos de contenido en la documentación:
|
||||||
|
|
||||||
There are two types of content in the documentation:
|
* **Documentación de API**: descripciones de los módulos, clases, interfaces, decoradores, etc que son parte de la plataforma Angular.
|
||||||
|
La documentacion de API está generada directamente desde el código fuente.
|
||||||
|
El código fuente está contenido en archivos TypeScript , almacenados en la carpeta `angular/packages`.
|
||||||
|
Cada elemento de la API puede tener un comentario anterior, el cual contiene etiquetas y contenido de estilos JSDoc.
|
||||||
|
El contenido está escrito en markdown.
|
||||||
|
|
||||||
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
* **Otro contenido**: guias, tutoriales, y otro material de marketing.
|
||||||
API docs are generated directly from the source code.
|
Todos los demás contenidos se escriben utilizando markdown en archivos de texto, ubicados en la carpeta `angular/aio/content`.
|
||||||
The source code is contained in TypeScript files, located in the `angular/packages` folder.
|
Más específicamente, hay subcarpetas que contienen tipos particulares de contenido: guías, tutoriales y marketing.
|
||||||
Each API item may have a preceding comment, which contains JSDoc style tags and content.
|
|
||||||
The content is written in markdown.
|
|
||||||
|
|
||||||
* **Other content**: guides, tutorials, and other marketing material.
|
* **Ejempos de código**: los ejemplos de código deben ser comprobables para garantizar su precisión.
|
||||||
All other content is written using markdown in text files, located in the `angular/aio/content` folder.
|
Además, nuestros ejemplos tienen un aspecto específico y permiten al usuario copiar el código fuente. Para mayor
|
||||||
More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.
|
ejemplos se representan en una interfaz con pestañas (e.g. template, HTML, y TypeScript en pestañas separadas). Adicionalmente, algunos son ejemplos en acción, que proporcionan enlaces donde se puede editar el código, ejecutar, y/o descargar. Para obtener más detalles sobre cómo trabajar con ejemplos de código, lea los [fragmentos de código](https://docs.angular.lat/guide/docs-style-guide#code-snippets), [código fuente de marcado ](https://docs.angular.lat/guide/docs-style-guide#source-code-markup), y [ ejemplos en acción ](https://docs.angular.lat/guide/docs-style-guide#live-examples) paginas de los [ autores de guías de estilo ](https://docs.angular.lat/guide/docs-style-guide).
|
||||||
|
|
||||||
* **Code examples**: code examples need to be testable to ensure their accuracy.
|
Usamos la herramienta [dgeni](https://github.com/angular/dgeni) para convertir estos archivos en docs que se pueden ver en el doc-viewer.
|
||||||
Also, our examples have a specific look and feel and allow the user to copy the source code. For larger
|
Las [guías de estilo para Autores](https://docs.angular.lat/guide/docs-style-guide) prescriben pautas para
|
||||||
examples they are rendered in a tabbed interface (e.g. template, HTML, and TypeScript on separate
|
escribir páginas de guía, explica cómo usar la documentación de clases y componentes, y cómo marcar el código fuente para producir fragmentos de código.
|
||||||
tabs). Additionally, some are live examples, which provide links where the code can be edited, executed, and/or downloaded. For details on working with code examples, please read the [Code snippets](https://angular.io/guide/docs-style-guide#code-snippets), [Source code markup](https://angular.io/guide/docs-style-guide#source-code-markup), and [Live examples](https://angular.io/guide/docs-style-guide#live-examples) pages of the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
|
||||||
|
|
||||||
We use the [dgeni](https://github.com/angular/dgeni) tool to convert these files into docs that can be viewed in the doc-viewer.
|
### Generando documentos completos
|
||||||
|
|
||||||
The [Authors Style Guide](https://angular.io/guide/docs-style-guide) prescribes guidelines for
|
La principal tarea para generar los documentos es `yarn docs`. Esto procesará todos los archivos fuente (API y otros), extrayendo la documentación y generando archivos JSON que pueden ser consumidos por el doc-viewer.
|
||||||
writing guide pages, explains how to use the documentation classes and components, and how to markup sample source code to produce code snippets.
|
|
||||||
|
|
||||||
### Generating the complete docs
|
### Generación parcial de doc para editores
|
||||||
|
|
||||||
The main task for generating the docs is `yarn docs`. This will process all the source files (API and other),
|
La generación completa de documentos puede llevar hasta un minuto. Eso es demasiado lento para la creación y edición eficiente de documentos.
|
||||||
extracting the documentation and generating JSON files that can be consumed by the doc-viewer.
|
|
||||||
|
|
||||||
### Partial doc generation for editors
|
Puedes ealizar pequeños cambios en un editor inteligente que muestre un markdown con formato:
|
||||||
|
>En VS Code, _Cmd-K, V_ abre la vista previa de markdown en el panel lateral; _Cmd-B_ alterna la barra izquierda
|
||||||
|
|
||||||
Full doc generation can take up to one minute. That's too slow for efficient document creation and editing.
|
Puedes también mirar los cambios que se muestran correctamente en el doc-viewer
|
||||||
|
con un tiempo de ciclo rápido de edición / visualización.
|
||||||
|
|
||||||
You can make small changes in a smart editor that displays formatted markdown:
|
Para este propósito, usa la tarea `yarn docs-watch`, que observa los cambios en los archivos de origen y solo vuelve a procesar los archivos necesarios para generar los documentos relacionados con el archivo que ha cambiado.
|
||||||
>In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar
|
Dado que esta tarea tiene accesos directos, es mucho más rápido (a menudo menos de 1 segundo) pero no producirá contenido de fidelidad completa. Por ejemplo, los enlaces a otros documentoss y ejemplos de código pueden no mostrarse correctamente. Esto se nota especialmente en los enlaces a otros documentos y en los ejemplos incrustados, que no siempre se representan correctamente.
|
||||||
|
|
||||||
You also want to see those changes displayed properly in the doc viewer
|
La configuración general es la siguiente:
|
||||||
with a quick, edit/view cycle time.
|
|
||||||
|
|
||||||
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
* Abrir una terminal, estar seguro que las dependencias están instaladas; ejecutar una generación inicial del doc; luego iniciar el doc-viewer:
|
||||||
re-processes the files necessary to generate the docs that are related to the file that has changed.
|
|
||||||
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
|
||||||
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
|
||||||
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
|
||||||
correctly.
|
|
||||||
|
|
||||||
The general setup is as follows:
|
|
||||||
|
|
||||||
* Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn setup
|
yarn setup
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
* Open a second terminal and start watching the docs
|
* Abrir una segunda terminal e iniciar el observador de documentos.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn docs-watch
|
yarn docs-watch
|
||||||
```
|
```
|
||||||
|
|
||||||
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
|
>Alternativamente, prueba el comando fusionado `serve-and-sync` que crea, observa y ejecuta en la misma ventana de la terminal
|
||||||
```bash
|
```bash
|
||||||
yarn serve-and-sync
|
yarn serve-and-sync
|
||||||
```
|
```
|
||||||
|
|
||||||
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
* Abre un navegador con la siguiente dirección https://localhost:4200/ y navega hasta el documento en el que quieras trabajar.
|
||||||
You can automatically open the browser by using `yarn start -o` in the first terminal.
|
Puedes automáticamente abrir el navegador utilizando `yarn start -o` en la primera terminal.
|
||||||
|
|
||||||
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
* Realiza cambios en la página de documentación asociada o en los archivos de ejemplo. Cada vez que un archivo es guardado, la documentación se regenerará, la aplicación se reconstruirá y la página se volverá a cargar.
|
||||||
be regenerated, the app will rebuild and the page will reload.
|
|
||||||
|
|
||||||
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
|
*Si recibes un error de compilación acerca de los ejemplos o cualquier otro error, asegúrate de consultar las
|
||||||
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
[guías de estilo para Autores](https://angular.io/guide/docs-style-guide) para más información.
|
||||||
|
@ -16,6 +16,13 @@ import {BuildNums, PrNums, SHA} from './constants';
|
|||||||
|
|
||||||
const logger = new Logger('mock-external-apis');
|
const logger = new Logger('mock-external-apis');
|
||||||
|
|
||||||
|
const log = (...args: any[]) => {
|
||||||
|
// Filter out non-matching URL checks
|
||||||
|
if (!/^matching.+: false$/.test(args[0])) {
|
||||||
|
logger.log(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
||||||
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
||||||
|
|
||||||
@ -84,8 +91,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create request scopes
|
// Create request scopes
|
||||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
|
const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist();
|
||||||
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
|
@ -27,28 +27,28 @@
|
|||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"delete-empty": "^3.0.0",
|
"delete-empty": "^3.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"jasmine": "^3.6.1",
|
"jasmine": "^3.5.0",
|
||||||
"nock": "^13.0.4",
|
"nock": "^12.0.3",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.0",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"tar-stream": "^2.1.3",
|
"tar-stream": "^2.1.2",
|
||||||
"tslib": "^2.0.1"
|
"tslib": "^1.11.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.19.0",
|
"@types/body-parser": "^1.19.0",
|
||||||
"@types/express": "^4.17.8",
|
"@types/express": "^4.17.6",
|
||||||
"@types/jasmine": "^3.5.14",
|
"@types/jasmine": "^3.5.10",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^14.6.4",
|
"@types/node": "^13.13.2",
|
||||||
"@types/node-fetch": "^2.5.7",
|
"@types/node-fetch": "^2.5.7",
|
||||||
"@types/shelljs": "^0.8.8",
|
"@types/shelljs": "^0.8.7",
|
||||||
"@types/supertest": "^2.0.10",
|
"@types/supertest": "^2.0.8",
|
||||||
"nodemon": "^2.0.4",
|
"nodemon": "^2.0.3",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"supertest": "^4.0.2",
|
"supertest": "^4.0.2",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.1",
|
||||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||||
"typescript": "^4.0.2"
|
"typescript": "^3.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,24 +214,23 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should call \'https.request()\' with the correct options', async () => {
|
it('should call \'https.request()\' with the correct options', () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method')
|
.intercept('/path', 'method')
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
|
||||||
await (api as any).request('method', '/path');
|
(api as any).request('method', '/path');
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should add the \'Authorization\' header containing the \'githubToken\'', async () => {
|
it('should add the \'Authorization\' header containing the \'githubToken\'', () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', undefined, {
|
.intercept('/path', 'method', undefined, {
|
||||||
reqheaders: {Authorization: 'token 12345'},
|
reqheaders: {Authorization: 'token 12345'},
|
||||||
})
|
})
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
(api as any).request('method', '/path');
|
||||||
await (api as any).request('method', '/path');
|
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,13 +244,12 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should \'JSON.stringify\' and send the data along with the request', async () => {
|
it('should \'JSON.stringify\' and send the data along with the request', () => {
|
||||||
const data = {key: 'value'};
|
const data = {key: 'value'};
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', JSON.stringify(data))
|
.intercept('/path', 'method', JSON.stringify(data))
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
(api as any).request('method', '/path', data);
|
||||||
await (api as any).request('method', '/path', data);
|
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ you don't need to specify values for those.
|
|||||||
The domain name of the server.
|
The domain name of the server.
|
||||||
|
|
||||||
- `AIO_GITHUB_ORGANIZATION`:
|
- `AIO_GITHUB_ORGANIZATION`:
|
||||||
The GitHub organization whose teams are trusted for accepting build artifacts.
|
The GitHub organization whose teams are whitelisted for accepting build artifacts.
|
||||||
See also `AIO_GITHUB_TEAM_SLUGS`.
|
See also `AIO_GITHUB_TEAM_SLUGS`.
|
||||||
|
|
||||||
- `AIO_GITHUB_REPO`:
|
- `AIO_GITHUB_REPO`:
|
||||||
|
@ -98,7 +98,7 @@ This section describes how each of the aforementioned sub-tasks is accomplished:
|
|||||||
Such a label can only have been added by a maintainer (with the necessary rights) and
|
Such a label can only have been added by a maintainer (with the necessary rights) and
|
||||||
designates that they have manually verified the PR contents.
|
designates that they have manually verified the PR contents.
|
||||||
2. We can verify (again using the GitHub API) the author's membership in one of the
|
2. We can verify (again using the GitHub API) the author's membership in one of the
|
||||||
trusted GitHub teams. For this operation, we need a Personal Access Token with the
|
whitelisted/trusted GitHub teams. For this operation, we need a Personal Access Token with the
|
||||||
`read:org` scope issued by a user that can "see" the specified GitHub organization.
|
`read:org` scope issued by a user that can "see" the specified GitHub organization.
|
||||||
Here too, we use the token by @mary-poppins.
|
Here too, we use the token by @mary-poppins.
|
||||||
|
|
||||||
|
2
aio/content/examples/.gitignore
vendored
2
aio/content/examples/.gitignore
vendored
@ -17,7 +17,6 @@
|
|||||||
**/e2e/tsconfig.e2e.json
|
**/e2e/tsconfig.e2e.json
|
||||||
**/src/karma.conf.js
|
**/src/karma.conf.js
|
||||||
**/.angular-cli.json
|
**/.angular-cli.json
|
||||||
**/.browserslistrc
|
|
||||||
**/.editorconfig
|
**/.editorconfig
|
||||||
**/.gitignore
|
**/.gitignore
|
||||||
**/angular.json
|
**/angular.json
|
||||||
@ -31,6 +30,7 @@
|
|||||||
**/tslint.json
|
**/tslint.json
|
||||||
**/karma-test-shim.js
|
**/karma-test-shim.js
|
||||||
**/browser-test-shim.js
|
**/browser-test-shim.js
|
||||||
|
**/browserslist
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
|
||||||
# built files
|
# built files
|
||||||
|
@ -21,13 +21,11 @@ import { ItemDirective } from './item.directive';
|
|||||||
ItemDirective
|
ItemDirective
|
||||||
],
|
],
|
||||||
// #enddocregion declarations
|
// #enddocregion declarations
|
||||||
// #docregion imports
|
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpClientModule
|
HttpClientModule
|
||||||
],
|
],
|
||||||
// #enddocregion imports
|
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Component Communication Cookbook Tests', () => {
|
describe('Component Communication Cookbook Tests', () => {
|
||||||
|
|
||||||
beforeEach(() => browser.get(browser.baseUrl));
|
// Note: '?e2e' which app can read to know it is running in protractor
|
||||||
|
// e.g. `if (!/e2e/.test(location.search)) { ...`
|
||||||
|
beforeAll(() => {
|
||||||
|
browser.get('?e2e');
|
||||||
|
});
|
||||||
|
|
||||||
describe('Parent-to-child communication', () => {
|
describe('Parent-to-child communication', () => {
|
||||||
// #docregion parent-to-child
|
// #docregion parent-to-child
|
||||||
@ -11,7 +15,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
const masterName = 'Master';
|
const masterName = 'Master';
|
||||||
|
|
||||||
it('should pass properties to children properly', () => {
|
it('should pass properties to children properly', () => {
|
||||||
const parent = element(by.tagName('app-hero-parent'));
|
const parent = element.all(by.tagName('app-hero-parent')).get(0);
|
||||||
const heroes = parent.all(by.tagName('app-hero-child'));
|
const heroes = parent.all(by.tagName('app-hero-child'));
|
||||||
|
|
||||||
for (let i = 0; i < heroNames.length; i++) {
|
for (let i = 0; i < heroNames.length; i++) {
|
||||||
@ -31,7 +35,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
it('should display trimmed, non-empty names', () => {
|
it('should display trimmed, non-empty names', () => {
|
||||||
const nonEmptyNameIndex = 0;
|
const nonEmptyNameIndex = 0;
|
||||||
const nonEmptyName = '"Dr IQ"';
|
const nonEmptyName = '"Dr IQ"';
|
||||||
const parent = element(by.tagName('app-name-parent'));
|
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
|
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
const displayName = hero.element(by.tagName('h3')).getText();
|
||||||
@ -41,7 +45,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
it('should replace empty name with default name', () => {
|
it('should replace empty name with default name', () => {
|
||||||
const emptyNameIndex = 1;
|
const emptyNameIndex = 1;
|
||||||
const defaultName = '"<no name set>"';
|
const defaultName = '"<no name set>"';
|
||||||
const parent = element(by.tagName('app-name-parent'));
|
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
|
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
const displayName = hero.element(by.tagName('h3')).getText();
|
||||||
@ -66,36 +70,38 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
expect(actual.logs.get(0).getText()).toBe(initialLog);
|
expect(actual.logs.get(0).getText()).toBe(initialLog);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set expected values after clicking \'Minor\' twice', async () => {
|
it('should set expected values after clicking \'Minor\' twice', () => {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
const repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
||||||
|
|
||||||
await newMinorButton.click();
|
newMinorButton.click().then(() => {
|
||||||
await newMinorButton.click();
|
newMinorButton.click().then(() => {
|
||||||
|
const actual = getActual();
|
||||||
|
|
||||||
const actual = getActual();
|
const labelAfter2Minor = 'Version 1.25';
|
||||||
|
const logAfter2Minor = 'minor changed from 24 to 25';
|
||||||
|
|
||||||
const labelAfter2Minor = 'Version 1.25';
|
expect(actual.label).toBe(labelAfter2Minor);
|
||||||
const logAfter2Minor = 'minor changed from 24 to 25';
|
expect(actual.count).toBe(3);
|
||||||
|
expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
|
||||||
expect(actual.label).toBe(labelAfter2Minor);
|
});
|
||||||
expect(actual.count).toBe(3);
|
});
|
||||||
expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set expected values after clicking \'Major\' once', async () => {
|
it('should set expected values after clicking \'Major\' once', () => {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
const repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
||||||
|
|
||||||
await newMajorButton.click();
|
newMajorButton.click().then(() => {
|
||||||
const actual = getActual();
|
const actual = getActual();
|
||||||
|
|
||||||
const labelAfterMajor = 'Version 2.0';
|
const labelAfterMajor = 'Version 2.0';
|
||||||
const logAfterMajor = 'major changed from 1 to 2, minor changed from 23 to 0';
|
const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
|
||||||
|
|
||||||
expect(actual.label).toBe(labelAfterMajor);
|
expect(actual.label).toBe(labelAfterMajor);
|
||||||
expect(actual.count).toBe(2);
|
expect(actual.count).toBe(4);
|
||||||
expect(actual.logs.get(1).getText()).toBe(logAfterMajor);
|
expect(actual.logs.get(3).getText()).toBe(logAfterMajor);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getActual() {
|
function getActual() {
|
||||||
@ -112,125 +118,110 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion parent-to-child-onchanges
|
// #enddocregion parent-to-child-onchanges
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Child-to-parent communication', () => {
|
describe('Child-to-parent communication', () => {
|
||||||
// #docregion child-to-parent
|
// #docregion child-to-parent
|
||||||
// ...
|
// ...
|
||||||
it('should not emit the event initially', () => {
|
it('should not emit the event initially', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 0');
|
.element(by.tagName('h3')).getText();
|
||||||
|
expect(voteLabel).toBe('Agree: 0, Disagree: 0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Agree vote', async () => {
|
it('should process Agree vote', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
||||||
.all(by.tagName('button')).get(0);
|
.all(by.tagName('button')).get(0);
|
||||||
|
agreeButton1.click().then(() => {
|
||||||
await agreeButton1.click();
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel.getText()).toBe('Agree: 1, Disagree: 0');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 0');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Disagree vote', async () => {
|
it('should process Disagree vote', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
||||||
.all(by.tagName('button')).get(1);
|
.all(by.tagName('button')).get(1);
|
||||||
|
agreeButton1.click().then(() => {
|
||||||
await agreeButton1.click();
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 1');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion child-to-parent
|
// #enddocregion child-to-parent
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent calls child via local var', () => {
|
// Can't run timer tests in protractor because
|
||||||
countDownTimerTests('app-countdown-parent-lv');
|
// interaction w/ zones causes all tests to freeze & timeout.
|
||||||
|
xdescribe('Parent calls child via local var', () => {
|
||||||
|
countDownTimerTests('countdown-parent-lv');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent calls ViewChild', () => {
|
xdescribe('Parent calls ViewChild', () => {
|
||||||
countDownTimerTests('app-countdown-parent-vc');
|
countDownTimerTests('countdown-parent-vc');
|
||||||
});
|
});
|
||||||
|
|
||||||
function countDownTimerTests(parentTag: string) {
|
function countDownTimerTests(parentTag: string) {
|
||||||
// #docregion countdown-timer-tests
|
// #docregion countdown-timer-tests
|
||||||
// ...
|
// ...
|
||||||
// The tests trigger periodic asynchronous operations (via `setInterval()`), which will prevent
|
it('timer and parent seconds should match', () => {
|
||||||
// the app from stabilizing. See https://angular.io/api/core/ApplicationRef#is-stable-examples
|
|
||||||
// for more details.
|
|
||||||
// To allow the tests to complete, we will disable automatically waiting for the Angular app to
|
|
||||||
// stabilize.
|
|
||||||
beforeEach(() => browser.waitForAngularEnabled(false));
|
|
||||||
afterEach(() => browser.waitForAngularEnabled(true));
|
|
||||||
|
|
||||||
it('timer and parent seconds should match', async () => {
|
|
||||||
const parent = element(by.tagName(parentTag));
|
const parent = element(by.tagName(parentTag));
|
||||||
const startButton = parent.element(by.buttonText('Start'));
|
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
const seconds = parent.element(by.className('seconds'));
|
browser.sleep(10); // give `seconds` a chance to catchup with `message`
|
||||||
const timer = parent.element(by.tagName('app-countdown-timer'));
|
const seconds = parent.element(by.className('seconds')).getText();
|
||||||
|
expect(message).toContain(seconds);
|
||||||
await startButton.click();
|
|
||||||
|
|
||||||
// Wait for `<app-countdown-timer>` to be populated with any text.
|
|
||||||
await browser.wait(() => timer.getText(), 2000);
|
|
||||||
|
|
||||||
expect(await timer.getText()).toContain(await seconds.getText());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should stop the countdown', async () => {
|
it('should stop the countdown', () => {
|
||||||
const parent = element(by.tagName(parentTag));
|
const parent = element(by.tagName(parentTag));
|
||||||
const startButton = parent.element(by.buttonText('Start'));
|
const stopButton = parent.all(by.tagName('button')).get(1);
|
||||||
const stopButton = parent.element(by.buttonText('Stop'));
|
|
||||||
const timer = parent.element(by.tagName('app-countdown-timer'));
|
|
||||||
|
|
||||||
await startButton.click();
|
stopButton.click().then(() => {
|
||||||
expect(await timer.getText()).not.toContain('Holding');
|
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
|
expect(message).toContain('Holding');
|
||||||
await stopButton.click();
|
});
|
||||||
expect(await timer.getText()).toContain('Holding');
|
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion countdown-timer-tests
|
// #enddocregion countdown-timer-tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe('Parent and children communicate via a service', () => {
|
describe('Parent and children communicate via a service', () => {
|
||||||
// #docregion bidirectional-service
|
// #docregion bidirectional-service
|
||||||
// ...
|
// ...
|
||||||
it('should announce a mission', async () => {
|
it('should announce a mission', () => {
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
const missionControl = element(by.tagName('app-mission-control'));
|
||||||
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
||||||
const history = missionControl.all(by.tagName('li'));
|
announceButton.click().then(() => {
|
||||||
|
const history = missionControl.all(by.tagName('li'));
|
||||||
await announceButton.click();
|
expect(history.count()).toBe(1);
|
||||||
|
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
||||||
expect(history.count()).toBe(1);
|
});
|
||||||
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Lovell', async () => {
|
it('should confirm the mission by Lovell', () => {
|
||||||
await testConfirmMission(1, 'Lovell');
|
testConfirmMission(1, 2, 'Lovell');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Haise', async () => {
|
it('should confirm the mission by Haise', () => {
|
||||||
await testConfirmMission(3, 'Haise');
|
testConfirmMission(3, 3, 'Haise');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Swigert', async () => {
|
it('should confirm the mission by Swigert', () => {
|
||||||
await testConfirmMission(2, 'Swigert');
|
testConfirmMission(2, 4, 'Swigert');
|
||||||
});
|
});
|
||||||
|
|
||||||
async function testConfirmMission(buttonIndex: number, astronaut: string) {
|
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
|
||||||
|
const confirmedLog = ' confirmed the mission';
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
const missionControl = element(by.tagName('app-mission-control'));
|
||||||
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
|
||||||
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
||||||
const history = missionControl.all(by.tagName('li'));
|
confirmButton.click().then(() => {
|
||||||
|
const history = missionControl.all(by.tagName('li'));
|
||||||
await announceButton.click();
|
expect(history.count()).toBe(expectedLogCount);
|
||||||
await confirmButton.click();
|
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog);
|
||||||
|
});
|
||||||
expect(history.count()).toBe(2);
|
|
||||||
expect(history.get(1).getText()).toBe(`${astronaut} confirmed the mission`);
|
|
||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion bidirectional-service
|
// #enddocregion bidirectional-service
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": [
|
||||||
|
"e2e",
|
||||||
|
"--protractor-config=e2e/protractor-puppeteer.conf.js",
|
||||||
|
"--no-webdriver-update",
|
||||||
|
"--port={PORT}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -30,21 +30,22 @@
|
|||||||
<app-vote-taker></app-vote-taker>
|
<app-vote-taker></app-vote-taker>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="parent-to-child-local-var">
|
<div id="parent-to-child-local-var">
|
||||||
<app-countdown-parent-lv></app-countdown-parent-lv>
|
<app-countdown-parent-lv></app-countdown-parent-lv>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="parent-to-view-child">
|
<div id="parent-to-view-child">
|
||||||
<app-countdown-parent-vc></app-countdown-parent-vc>
|
<app-countdown-parent-vc></app-countdown-parent-vc>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="bidirectional-service">
|
<div id="bidirectional-service">
|
||||||
<app-mission-control></app-mission-control>
|
<app-mission-control></app-mission-control>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
<hr>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
@ -15,17 +15,10 @@ import { VersionParentComponent } from './version-parent.component';
|
|||||||
import { VoterComponent } from './voter.component';
|
import { VoterComponent } from './voter.component';
|
||||||
import { VoteTakerComponent } from './votetaker.component';
|
import { VoteTakerComponent } from './votetaker.component';
|
||||||
|
|
||||||
|
const directives: any[] = [
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
AppComponent,
|
||||||
AstronautComponent,
|
AstronautComponent,
|
||||||
CountdownLocalVarParentComponent,
|
|
||||||
CountdownTimerComponent,
|
CountdownTimerComponent,
|
||||||
CountdownViewChildParentComponent,
|
|
||||||
HeroChildComponent,
|
HeroChildComponent,
|
||||||
HeroParentComponent,
|
HeroParentComponent,
|
||||||
MissionControlComponent,
|
MissionControlComponent,
|
||||||
@ -34,8 +27,28 @@ import { VoteTakerComponent } from './votetaker.component';
|
|||||||
VersionChildComponent,
|
VersionChildComponent,
|
||||||
VersionParentComponent,
|
VersionParentComponent,
|
||||||
VoterComponent,
|
VoterComponent,
|
||||||
VoteTakerComponent,
|
VoteTakerComponent
|
||||||
|
];
|
||||||
|
|
||||||
|
const schemas: any[] = [];
|
||||||
|
|
||||||
|
// Include Countdown examples
|
||||||
|
// unless in e2e tests which they break.
|
||||||
|
if (!/e2e/.test(location.search)) {
|
||||||
|
console.log('adding countdown timer examples');
|
||||||
|
directives.push(CountdownLocalVarParentComponent);
|
||||||
|
directives.push(CountdownViewChildParentComponent);
|
||||||
|
} else {
|
||||||
|
// In e2e test use CUSTOM_ELEMENTS_SCHEMA to suppress unknown element errors
|
||||||
|
schemas.push(CUSTOM_ELEMENTS_SCHEMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
],
|
],
|
||||||
|
declarations: directives,
|
||||||
bootstrap: [ AppComponent ],
|
bootstrap: [ AppComponent ],
|
||||||
|
schemas
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnDestroy } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-countdown-timer',
|
selector: 'app-countdown-timer',
|
||||||
template: '<p>{{message}}</p>'
|
template: '<p>{{message}}</p>'
|
||||||
})
|
})
|
||||||
export class CountdownTimerComponent implements OnDestroy {
|
export class CountdownTimerComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
intervalId = 0;
|
intervalId = 0;
|
||||||
message = '';
|
message = '';
|
||||||
seconds = 11;
|
seconds = 11;
|
||||||
|
|
||||||
|
clearTimer() { clearInterval(this.intervalId); }
|
||||||
|
|
||||||
|
ngOnInit() { this.start(); }
|
||||||
ngOnDestroy() { this.clearTimer(); }
|
ngOnDestroy() { this.clearTimer(); }
|
||||||
|
|
||||||
start() { this.countDown(); }
|
start() { this.countDown(); }
|
||||||
@ -19,8 +22,6 @@ export class CountdownTimerComponent implements OnDestroy {
|
|||||||
this.message = `Holding at T-${this.seconds} seconds`;
|
this.message = `Holding at T-${this.seconds} seconds`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearTimer() { clearInterval(this.intervalId); }
|
|
||||||
|
|
||||||
private countDown() {
|
private countDown() {
|
||||||
this.clearTimer();
|
this.clearTimer();
|
||||||
this.intervalId = window.setInterval(() => {
|
this.intervalId = window.setInterval(() => {
|
||||||
|
@ -24,7 +24,7 @@ export class UploaderService {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
upload(file: File) {
|
upload(file: File) {
|
||||||
if (!file) { return of<string>(); }
|
if (!file) { return; }
|
||||||
|
|
||||||
// COULD HAVE WRITTEN:
|
// COULD HAVE WRITTEN:
|
||||||
// return this.http.post('/upload/file', file, {
|
// return this.http.post('/upload/file', file, {
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<!-- #enddocregion translated-plural -->
|
<!-- #enddocregion translated-plural -->
|
||||||
<!-- #docregion translated-select -->
|
<!-- #docregion translated-select -->
|
||||||
<!-- #docregion translate-select-1 -->
|
<!-- #docregion translate-select-1 -->
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
||||||
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
||||||
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// TODO: Add unit tests for this file.
|
|
||||||
// tslint:disable: no-output-native
|
// tslint:disable: no-output-native
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
import { docRegionFromEvent, docRegionSubscriber } from './creating';
|
|
||||||
|
|
||||||
describe('observables', () => {
|
|
||||||
it('should create an observable using the constructor', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionSubscriber(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(4);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[2],
|
|
||||||
[3],
|
|
||||||
['Finished sequence'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should listen to input changes', () => {
|
|
||||||
let triggerInputChange;
|
|
||||||
const input = {
|
|
||||||
value: 'Test',
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'keydown') {
|
|
||||||
triggerInputChange = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEventListener'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const document = { getElementById: () => input };
|
|
||||||
docRegionFromEvent(document);
|
|
||||||
triggerInputChange({keyCode: 65});
|
|
||||||
expect(input.value).toBe('Test');
|
|
||||||
|
|
||||||
triggerInputChange({keyCode: 27});
|
|
||||||
expect(input.value).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call removeEventListener when unsubscribing', (doneFn: DoneFn) => {
|
|
||||||
const input = {
|
|
||||||
addEventListener: jasmine.createSpy('addEvent'),
|
|
||||||
removeEventListener: jasmine
|
|
||||||
.createSpy('removeEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'keydown') {
|
|
||||||
doneFn();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const document = { getElementById: () => input };
|
|
||||||
const subscription = docRegionFromEvent(document);
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,39 +1,38 @@
|
|||||||
// #docplaster
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export function docRegionSubscriber(console) {
|
// #docregion subscriber
|
||||||
// #docregion subscriber
|
|
||||||
// This function runs when subscribe() is called
|
|
||||||
function sequenceSubscriber(observer) {
|
|
||||||
// synchronously deliver 1, 2, and 3, then complete
|
|
||||||
observer.next(1);
|
|
||||||
observer.next(2);
|
|
||||||
observer.next(3);
|
|
||||||
observer.complete();
|
|
||||||
|
|
||||||
// unsubscribe function doesn't need to do anything in this
|
// This function runs when subscribe() is called
|
||||||
// because values are delivered synchronously
|
function sequenceSubscriber(observer) {
|
||||||
return {unsubscribe() {}};
|
// synchronously deliver 1, 2, and 3, then complete
|
||||||
}
|
observer.next(1);
|
||||||
|
observer.next(2);
|
||||||
|
observer.next(3);
|
||||||
|
observer.complete();
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
// unsubscribe function doesn't need to do anything in this
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
// because values are delivered synchronously
|
||||||
|
return {unsubscribe() {}};
|
||||||
// execute the Observable and print the result of each notification
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// 1
|
|
||||||
// 2
|
|
||||||
// 3
|
|
||||||
// Finished sequence
|
|
||||||
// #enddocregion subscriber
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
|
|
||||||
|
// execute the Observable and print the result of each notification
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// Finished sequence
|
||||||
|
|
||||||
|
// #enddocregion subscriber
|
||||||
|
|
||||||
// #docregion fromevent
|
// #docregion fromevent
|
||||||
|
|
||||||
function fromEvent(target, eventName) {
|
function fromEvent(target, eventName) {
|
||||||
@ -52,18 +51,16 @@ function fromEvent(target, eventName) {
|
|||||||
|
|
||||||
// #enddocregion fromevent
|
// #enddocregion fromevent
|
||||||
|
|
||||||
export function docRegionFromEvent(document) {
|
// #docregion fromevent_use
|
||||||
// #docregion fromevent_use
|
|
||||||
|
|
||||||
const ESC_KEY = 27;
|
const ESC_KEY = 27;
|
||||||
const nameInput = document.getElementById('name') as HTMLInputElement;
|
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||||
|
|
||||||
const subscription = fromEvent(nameInput, 'keydown').subscribe((e: KeyboardEvent) => {
|
const subscription = fromEvent(nameInput, 'keydown')
|
||||||
|
.subscribe((e: KeyboardEvent) => {
|
||||||
if (e.keyCode === ESC_KEY) {
|
if (e.keyCode === ESC_KEY) {
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// #enddocregion fromevent_use
|
|
||||||
return subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// #enddocregion fromevent_use
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// TODO: Add unit tests for this file.
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
// Create an Observable that will start listening to geolocation updates
|
// Create an Observable that will start listening to geolocation updates
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
import { docRegionDelaySequence, docRegionMulticastSequence } from './multicasting';
|
|
||||||
|
|
||||||
describe('multicasting', () => {
|
|
||||||
let console;
|
|
||||||
beforeEach(() => {
|
|
||||||
jasmine.clock().install();
|
|
||||||
console = {log: jasmine.createSpy('log')};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jasmine.clock().uninstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create an observable and emit in sequence', () => {
|
|
||||||
docRegionDelaySequence(console);
|
|
||||||
jasmine.clock().tick(10000);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(12);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
['1st subscribe: 1'],
|
|
||||||
['2nd subscribe: 1'],
|
|
||||||
[2],
|
|
||||||
['1st subscribe: 2'],
|
|
||||||
['2nd subscribe: 2'],
|
|
||||||
[3],
|
|
||||||
['Finished sequence'],
|
|
||||||
['1st subscribe: 3'],
|
|
||||||
['1st sequence finished.'],
|
|
||||||
['2nd subscribe: 3'],
|
|
||||||
['2nd sequence finished.']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create an observable and multicast the emissions', () => {
|
|
||||||
docRegionMulticastSequence(console);
|
|
||||||
jasmine.clock().tick(10000);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(7);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
['1st subscribe: 1'],
|
|
||||||
['1st subscribe: 2'],
|
|
||||||
['2nd subscribe: 2'],
|
|
||||||
['1st subscribe: 3'],
|
|
||||||
['2nd subscribe: 3'],
|
|
||||||
['1st sequence finished.'],
|
|
||||||
['2nd sequence finished.']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,160 +1,155 @@
|
|||||||
// #docplaster
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export function docRegionDelaySequence(console) {
|
// #docregion delay_sequence
|
||||||
// #docregion delay_sequence
|
|
||||||
function sequenceSubscriber(observer) {
|
|
||||||
const seq = [1, 2, 3];
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
// Will run through an array of numbers, emitting one value
|
function sequenceSubscriber(observer) {
|
||||||
// per second until it gets to the end of the array.
|
const seq = [1, 2, 3];
|
||||||
function doInSequence(arr, idx) {
|
let timeoutId;
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
observer.next(arr[idx]);
|
|
||||||
if (idx === arr.length - 1) {
|
|
||||||
observer.complete();
|
|
||||||
} else {
|
|
||||||
doInSequence(arr, ++idx);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
doInSequence(seq, 0);
|
// Will run through an array of numbers, emitting one value
|
||||||
|
|
||||||
// Unsubscribe should clear the timeout to stop execution
|
|
||||||
return {
|
|
||||||
unsubscribe() {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
|
||||||
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1
|
|
||||||
// (at 2 seconds): 2
|
|
||||||
// (at 3 seconds): 3
|
|
||||||
// (at 3 seconds): Finished sequence
|
|
||||||
|
|
||||||
// #enddocregion delay_sequence
|
|
||||||
|
|
||||||
// #docregion subscribe_twice
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and will emit after 1 second
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
|
||||||
complete() { console.log('1st sequence finished.'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// After 1/2 second, subscribe again.
|
|
||||||
setTimeout(() => {
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1st subscribe: 1
|
|
||||||
// (at 1.5 seconds): 2nd subscribe: 1
|
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
|
||||||
// (at 2.5 seconds): 2nd subscribe: 2
|
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
|
||||||
// (at 3 seconds): 1st sequence finished
|
|
||||||
// (at 3.5 seconds): 2nd subscribe: 3
|
|
||||||
// (at 3.5 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion subscribe_twice
|
|
||||||
}
|
|
||||||
|
|
||||||
export function docRegionMulticastSequence(console) {
|
|
||||||
// #docregion multicast_sequence
|
|
||||||
function multicastSequenceSubscriber() {
|
|
||||||
const seq = [1, 2, 3];
|
|
||||||
// Keep track of each observer (one for every active subscription)
|
|
||||||
const observers = [];
|
|
||||||
// Still a single timeoutId because there will only ever be one
|
|
||||||
// set of values being generated, multicasted to each subscriber
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
// Return the subscriber function (runs when subscribe()
|
|
||||||
// function is invoked)
|
|
||||||
return observer => {
|
|
||||||
observers.push(observer);
|
|
||||||
// When this is the first subscription, start the sequence
|
|
||||||
if (observers.length === 1) {
|
|
||||||
timeoutId = doSequence({
|
|
||||||
next(val) {
|
|
||||||
// Iterate through observers and notify all subscriptions
|
|
||||||
observers.forEach(obs => obs.next(val));
|
|
||||||
},
|
|
||||||
complete() {
|
|
||||||
// Notify all complete callbacks
|
|
||||||
observers.slice(0).forEach(obs => obs.complete());
|
|
||||||
}
|
|
||||||
}, seq, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
unsubscribe() {
|
|
||||||
// Remove from the observers array so it's no longer notified
|
|
||||||
observers.splice(observers.indexOf(observer), 1);
|
|
||||||
// If there's no more listeners, do cleanup
|
|
||||||
if (observers.length === 0) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run through an array of numbers, emitting one value
|
|
||||||
// per second until it gets to the end of the array.
|
// per second until it gets to the end of the array.
|
||||||
function doSequence(observer, arr, idx) {
|
function doInSequence(arr, idx) {
|
||||||
return setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
observer.next(arr[idx]);
|
observer.next(arr[idx]);
|
||||||
if (idx === arr.length - 1) {
|
if (idx === arr.length - 1) {
|
||||||
observer.complete();
|
observer.complete();
|
||||||
} else {
|
} else {
|
||||||
doSequence(observer, arr, ++idx);
|
doInSequence(arr, ++idx);
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
doInSequence(seq, 0);
|
||||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and begins to emit after 1 second
|
// Unsubscribe should clear the timeout to stop execution
|
||||||
multicastSequence.subscribe({
|
return {unsubscribe() {
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
clearTimeout(timeoutId);
|
||||||
complete() { console.log('1st sequence finished.'); }
|
}};
|
||||||
});
|
|
||||||
|
|
||||||
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
|
||||||
setTimeout(() => {
|
|
||||||
multicastSequence.subscribe({
|
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1st subscribe: 1
|
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
|
||||||
// (at 2 seconds): 2nd subscribe: 2
|
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
|
||||||
// (at 3 seconds): 1st sequence finished
|
|
||||||
// (at 3 seconds): 2nd subscribe: 3
|
|
||||||
// (at 3 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion multicast_sequence
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
|
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1
|
||||||
|
// (at 2 seconds): 2
|
||||||
|
// (at 3 seconds): 3
|
||||||
|
// (at 3 seconds): Finished sequence
|
||||||
|
|
||||||
|
// #enddocregion delay_sequence
|
||||||
|
|
||||||
|
// #docregion subscribe_twice
|
||||||
|
|
||||||
|
// Subscribe starts the clock, and will emit after 1 second
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
|
complete() { console.log('1st sequence finished.'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// After 1/2 second, subscribe again.
|
||||||
|
setTimeout(() => {
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 1.5 seconds): 2nd subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2.5 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3.5 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3.5 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion subscribe_twice
|
||||||
|
|
||||||
|
// #docregion multicast_sequence
|
||||||
|
|
||||||
|
function multicastSequenceSubscriber() {
|
||||||
|
const seq = [1, 2, 3];
|
||||||
|
// Keep track of each observer (one for every active subscription)
|
||||||
|
const observers = [];
|
||||||
|
// Still a single timeoutId because there will only ever be one
|
||||||
|
// set of values being generated, multicasted to each subscriber
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
// Return the subscriber function (runs when subscribe()
|
||||||
|
// function is invoked)
|
||||||
|
return (observer) => {
|
||||||
|
observers.push(observer);
|
||||||
|
// When this is the first subscription, start the sequence
|
||||||
|
if (observers.length === 1) {
|
||||||
|
timeoutId = doSequence({
|
||||||
|
next(val) {
|
||||||
|
// Iterate through observers and notify all subscriptions
|
||||||
|
observers.forEach(obs => obs.next(val));
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
// Notify all complete callbacks
|
||||||
|
observers.slice(0).forEach(obs => obs.complete());
|
||||||
|
}
|
||||||
|
}, seq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
unsubscribe() {
|
||||||
|
// Remove from the observers array so it's no longer notified
|
||||||
|
observers.splice(observers.indexOf(observer), 1);
|
||||||
|
// If there's no more listeners, do cleanup
|
||||||
|
if (observers.length === 0) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run through an array of numbers, emitting one value
|
||||||
|
// per second until it gets to the end of the array.
|
||||||
|
function doSequence(observer, arr, idx) {
|
||||||
|
return setTimeout(() => {
|
||||||
|
observer.next(arr[idx]);
|
||||||
|
if (idx === arr.length - 1) {
|
||||||
|
observer.complete();
|
||||||
|
} else {
|
||||||
|
doSequence(observer, arr, ++idx);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||||
|
|
||||||
|
// Subscribe starts the clock, and begins to emit after 1 second
|
||||||
|
multicastSequence.subscribe({
|
||||||
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
|
complete() { console.log('1st sequence finished.'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
||||||
|
setTimeout(() => {
|
||||||
|
multicastSequence.subscribe({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion multicast_sequence
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import { docRegionObserver } from './subscribing';
|
|
||||||
|
|
||||||
describe('subscribing', () => {
|
|
||||||
it('should subscribe and emit', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionObserver(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(8);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
['Observer got a next value: 1'],
|
|
||||||
['Observer got a next value: 2'],
|
|
||||||
['Observer got a next value: 3'],
|
|
||||||
['Observer got a complete notification'],
|
|
||||||
['Observer got a next value: 1'],
|
|
||||||
['Observer got a next value: 2'],
|
|
||||||
['Observer got a next value: 3'],
|
|
||||||
['Observer got a complete notification'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +1,32 @@
|
|||||||
// #docplaster
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
export function docRegionObserver(console) {
|
import { Observable, of } from 'rxjs';
|
||||||
// #docregion observer
|
|
||||||
|
|
||||||
// Create simple observable that emits three values
|
// #docregion observer
|
||||||
const myObservable = of(1, 2, 3);
|
|
||||||
|
|
||||||
// Create observer object
|
// Create simple observable that emits three values
|
||||||
const myObserver = {
|
const myObservable = of(1, 2, 3);
|
||||||
next: x => console.log('Observer got a next value: ' + x),
|
|
||||||
error: err => console.error('Observer got an error: ' + err),
|
|
||||||
complete: () => console.log('Observer got a complete notification'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Execute with the observer object
|
// Create observer object
|
||||||
myObservable.subscribe(myObserver);
|
const myObserver = {
|
||||||
|
next: x => console.log('Observer got a next value: ' + x),
|
||||||
|
error: err => console.error('Observer got an error: ' + err),
|
||||||
|
complete: () => console.log('Observer got a complete notification'),
|
||||||
|
};
|
||||||
|
|
||||||
// Logs:
|
// Execute with the observer object
|
||||||
// Observer got a next value: 1
|
myObservable.subscribe(myObserver);
|
||||||
// Observer got a next value: 2
|
// Logs:
|
||||||
// Observer got a next value: 3
|
// Observer got a next value: 1
|
||||||
// Observer got a complete notification
|
// Observer got a next value: 2
|
||||||
|
// Observer got a next value: 3
|
||||||
|
// Observer got a complete notification
|
||||||
|
|
||||||
// #enddocregion observer
|
// #enddocregion observer
|
||||||
|
|
||||||
// #docregion sub_fn
|
// #docregion sub_fn
|
||||||
myObservable.subscribe(
|
myObservable.subscribe(
|
||||||
x => console.log('Observer got a next value: ' + x),
|
x => console.log('Observer got a next value: ' + x),
|
||||||
err => console.error('Observer got an error: ' + err),
|
err => console.error('Observer got an error: ' + err),
|
||||||
() => console.log('Observer got a complete notification')
|
() => console.log('Observer got a complete notification')
|
||||||
);
|
);
|
||||||
// #enddocregion sub_fn
|
// #enddocregion sub_fn
|
||||||
}
|
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
import { interval } from 'rxjs';
|
|
||||||
import { tap } from 'rxjs/operators';
|
|
||||||
import { backoff } from './backoff';
|
|
||||||
|
|
||||||
describe('backoff()', () => {
|
|
||||||
beforeEach(() => jasmine.clock().install());
|
|
||||||
afterEach(() => jasmine.clock().uninstall());
|
|
||||||
|
|
||||||
it('should retry in case of error', () => {
|
|
||||||
const mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
const source = interval(10).pipe(
|
|
||||||
tap(i => {
|
|
||||||
if (i > 0) {
|
|
||||||
throw new Error('Test error');
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
backoff(3, 100),
|
|
||||||
);
|
|
||||||
source.subscribe({
|
|
||||||
next: v => mockConsole.log(`Emitted: ${v}`),
|
|
||||||
error: e => mockConsole.log(`Errored: ${e.message || e}`),
|
|
||||||
complete: () => mockConsole.log('Completed'),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial try:
|
|
||||||
// Errors on second emission and schedules retrying (with delay).
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// First re-attempt after 100ms:
|
|
||||||
// Errors again on second emission and schedules retrying (with larger delay).
|
|
||||||
jasmine.clock().tick(100);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// Second re-attempt after 400ms:
|
|
||||||
// Errors again on second emission and schedules retrying (with even larger delay).
|
|
||||||
jasmine.clock().tick(400);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// Third re-attempt after 900ms:
|
|
||||||
// Errors again on second emission and gives up (no retrying).
|
|
||||||
jasmine.clock().tick(900);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Errored: Test error']]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +1,23 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { of, pipe, range, throwError, timer, zip } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
import { map, mergeMap, retryWhen } from 'rxjs/operators';
|
|
||||||
|
|
||||||
export function backoff(maxTries, delay) {
|
import { pipe, range, timer, zip } from 'rxjs';
|
||||||
return pipe(
|
import { ajax } from 'rxjs/ajax';
|
||||||
retryWhen(attempts =>
|
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||||
zip(range(1, maxTries + 1), attempts).pipe(
|
|
||||||
mergeMap(([i, err]) => (i > maxTries) ? throwError(err) : of(i)),
|
function backoff(maxTries, ms) {
|
||||||
map(i => i * i),
|
return pipe(
|
||||||
mergeMap(v => timer(v * delay)),
|
retryWhen(attempts => zip(range(1, maxTries), attempts)
|
||||||
),
|
.pipe(
|
||||||
),
|
map(([i]) => i * i),
|
||||||
);
|
mergeMap(i => timer(i * ms))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
/*
|
|
||||||
This function declaration is necessary to ensure that it does not get called
|
|
||||||
when running the unit tests. It will not get rendered into the docs.
|
|
||||||
The indentation needs to start in the leftmost level position as well because of how
|
|
||||||
the docplaster combines the different regions together.
|
|
||||||
*/
|
|
||||||
function docRegionAjaxCall() {
|
|
||||||
// #docregion
|
|
||||||
ajax('/api/endpoint')
|
ajax('/api/endpoint')
|
||||||
.pipe(backoff(3, 250))
|
.pipe(backoff(3, 250))
|
||||||
.subscribe(function handleData(data) { /* ... */ });
|
.subscribe(data => handleData(data));
|
||||||
// #enddocregion
|
|
||||||
|
function handleData(data) {
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionTypeahead } from './typeahead';
|
|
||||||
|
|
||||||
describe('typeahead', () => {
|
|
||||||
let document;
|
|
||||||
let ajax;
|
|
||||||
let triggertInputChange;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jasmine.clock().install();
|
|
||||||
const input = {
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'input') {
|
|
||||||
triggertInputChange = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEvent'),
|
|
||||||
};
|
|
||||||
|
|
||||||
document = { getElementById: (id: string) => input };
|
|
||||||
ajax = jasmine.createSpy('ajax').and.callFake((url: string) => of('foo bar'));
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jasmine.clock().uninstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make an ajax call to the corrent endpoint', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call, when the input length < 3', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: '' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
triggertInputChange({ target: { value: 'fo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call for intermediate values when debouncing', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'bar' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'baz' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'qux' } });
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(ajax).toHaveBeenCalledTimes(1);
|
|
||||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=qux');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call, when the input value has not changed', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).toHaveBeenCalled();
|
|
||||||
ajax.calls.reset();
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +1,18 @@
|
|||||||
/*
|
import { fromEvent } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
import { ajax } from 'rxjs/ajax';
|
||||||
we need to indent the imports with the function below.
|
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
||||||
*/
|
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { fromEvent } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
export function docRegionTypeahead(document, ajax) {
|
|
||||||
// #docregion
|
|
||||||
const searchBox = document.getElementById('search-box');
|
|
||||||
|
|
||||||
const typeahead = fromEvent(searchBox, 'input').pipe(
|
const searchBox = document.getElementById('search-box');
|
||||||
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
|
||||||
filter(text => text.length > 2),
|
|
||||||
debounceTime(10),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`))
|
|
||||||
);
|
|
||||||
|
|
||||||
typeahead.subscribe(data => {
|
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||||
// Handle the data from the API
|
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
||||||
});
|
filter(text => text.length > 2),
|
||||||
|
debounceTime(10),
|
||||||
|
distinctUntilChanged(),
|
||||||
|
switchMap(() => ajax('/api/endpoint'))
|
||||||
|
);
|
||||||
|
|
||||||
// #enddocregion
|
typeahead.subscribe(data => {
|
||||||
return typeahead;
|
// Handle the data from the API
|
||||||
}
|
});
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
import { Subject, throwError } from 'rxjs';
|
|
||||||
import { docRegionDefault } from './error-handling';
|
|
||||||
|
|
||||||
describe('error-handling', () => {
|
|
||||||
let mockConsole;
|
|
||||||
let ajaxSubject;
|
|
||||||
let ajax;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
ajaxSubject = new Subject();
|
|
||||||
ajax = jasmine
|
|
||||||
.createSpy('ajax')
|
|
||||||
.and.callFake((url: string) => ajaxSubject);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => ajaxSubject.unsubscribe());
|
|
||||||
|
|
||||||
it('should return the response object', () => {
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
ajaxSubject.next({response: {foo: 'bar'}});
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', {foo: 'bar'}]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when using an object without a `response` property', () => {
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
ajaxSubject.next({foo: 'bar'});
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when the ajax observable errors', () => {
|
|
||||||
ajax.and.returnValue(throwError('Test Error'));
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,36 +1,25 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
import { ajax } from 'rxjs/ajax';
|
||||||
import { map, catchError } from 'rxjs/operators';
|
import { map, catchError } from 'rxjs/operators';
|
||||||
|
// Return "response" from the API. If an error happens,
|
||||||
|
// return an empty array.
|
||||||
|
const apiData = ajax('/api/data').pipe(
|
||||||
|
map(res => {
|
||||||
|
if (!res.response) {
|
||||||
|
throw new Error('Value expected!');
|
||||||
|
}
|
||||||
|
return res.response;
|
||||||
|
}),
|
||||||
|
catchError(err => of([]))
|
||||||
|
);
|
||||||
|
|
||||||
|
apiData.subscribe({
|
||||||
|
next(x) { console.log('data: ', x); },
|
||||||
|
error(err) { console.log('errors already caught... will not run'); }
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console, ajax) {
|
|
||||||
// #docregion
|
|
||||||
// Return "response" from the API. If an error happens,
|
|
||||||
// return an empty array.
|
|
||||||
const apiData = ajax('/api/data').pipe(
|
|
||||||
map((res: any) => {
|
|
||||||
if (!res.response) {
|
|
||||||
throw new Error('Value expected!');
|
|
||||||
}
|
|
||||||
return res.response;
|
|
||||||
}),
|
|
||||||
catchError(err => of([]))
|
|
||||||
);
|
|
||||||
|
|
||||||
apiData.subscribe({
|
|
||||||
next(x) { console.log('data: ', x); },
|
|
||||||
error(err) { console.log('errors already caught... will not run'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
return apiData;
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators.1';
|
|
||||||
|
|
||||||
describe('squareOdd - operators.1.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[9],
|
|
||||||
[25],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,30 +1,23 @@
|
|||||||
// #docplaster
|
import { of, pipe } from 'rxjs';
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of, pipe } from 'rxjs';
|
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const nums = of(1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
// Create a function that accepts an Observable.
|
||||||
|
const squareOddVals = pipe(
|
||||||
|
filter((n: number) => n % 2 !== 0),
|
||||||
|
map(n => n * n)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create an Observable that will run the filter and map functions
|
||||||
|
const squareOdd = squareOddVals(nums);
|
||||||
|
|
||||||
|
// Subscribe to run the combined functions
|
||||||
|
squareOdd.subscribe(x => console.log(x));
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const nums = of(1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
// Create a function that accepts an Observable.
|
|
||||||
const squareOddVals = pipe(
|
|
||||||
filter((n: number) => n % 2 !== 0),
|
|
||||||
map(n => n * n)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create an Observable that will run the filter and map functions
|
|
||||||
const squareOdd = squareOddVals(nums);
|
|
||||||
|
|
||||||
// Subscribe to run the combined functions
|
|
||||||
squareOdd.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators.2';
|
|
||||||
|
|
||||||
describe('squareOdd - operators.2.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[9],
|
|
||||||
[25],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,25 +1,16 @@
|
|||||||
// #docplaster
|
import { Observable, of } from 'rxjs';
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const squareOdd = of(1, 2, 3, 4, 5)
|
||||||
|
.pipe(
|
||||||
|
filter(n => n % 2 !== 0),
|
||||||
|
map(n => n * n)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Subscribe to get values
|
||||||
|
squareOdd.subscribe(x => console.log(x));
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const squareOdd = of(1, 2, 3, 4, 5)
|
|
||||||
.pipe(
|
|
||||||
filter(n => n % 2 !== 0),
|
|
||||||
map(n => n * n)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Subscribe to get values
|
|
||||||
squareOdd.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators';
|
|
||||||
|
|
||||||
describe('squaredNums - operators.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[4],
|
|
||||||
[9],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +1,20 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { Observable, of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const nums = of(1, 2, 3);
|
||||||
|
|
||||||
|
const squareValues = map((val: number) => val * val);
|
||||||
|
const squaredNums = squareValues(nums);
|
||||||
|
|
||||||
|
squaredNums.subscribe(x => console.log(x));
|
||||||
|
|
||||||
|
// Logs
|
||||||
|
// 1
|
||||||
|
// 4
|
||||||
|
// 9
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const nums = of(1, 2, 3);
|
|
||||||
|
|
||||||
const squareValues = map((val: number) => val * val);
|
|
||||||
const squaredNums = squareValues(nums);
|
|
||||||
|
|
||||||
squaredNums.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// Logs
|
|
||||||
// 1
|
|
||||||
// 4
|
|
||||||
// 9
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
import { of, throwError } from 'rxjs';
|
|
||||||
import { mergeMap, tap } from 'rxjs/operators';
|
|
||||||
import { docRegionDefault } from './retry-on-error';
|
|
||||||
|
|
||||||
describe('retry-on-error', () => {
|
|
||||||
let mockConsole;
|
|
||||||
beforeEach(() => mockConsole = { log: jasmine.createSpy('log') });
|
|
||||||
|
|
||||||
it('should return the response object', () => {
|
|
||||||
const ajax = () => of({ response: { foo: 'bar' } });
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', { foo: 'bar' }],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array after 3 retries + 1 initial request', () => {
|
|
||||||
const ajax = () => {
|
|
||||||
return of({ noresponse: true }).pipe(tap(() => mockConsole.log('Subscribed to AJAX')));
|
|
||||||
};
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['data: ', []],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the response if the request succeeds upon retrying', () => {
|
|
||||||
// Fail on the first two requests, but succeed from the 3rd onwards.
|
|
||||||
let failCount = 2;
|
|
||||||
const ajax = () => of(null).pipe(
|
|
||||||
tap(() => mockConsole.log('Subscribed to AJAX')),
|
|
||||||
// Fail on the first 2 requests, but succeed from the 3rd onwards.
|
|
||||||
mergeMap(() => {
|
|
||||||
if (failCount > 0) {
|
|
||||||
failCount--;
|
|
||||||
return throwError('Test error');
|
|
||||||
}
|
|
||||||
return of({ response: { foo: 'bar' } });
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Subscribed to AJAX'], // Initial request | 1st attempt overall
|
|
||||||
['Subscribed to AJAX'], // 1st retry attempt | 2nd attempt overall
|
|
||||||
['Subscribed to AJAX'], // 2nd retry attempt | 3rd attempt overall
|
|
||||||
['data: ', { foo: 'bar' }],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when the ajax observable throws an error', () => {
|
|
||||||
const ajax = () => throwError('Test Error');
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +1,26 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { Observable, of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
import { ajax } from 'rxjs/ajax';
|
||||||
import { map, retry, catchError } from 'rxjs/operators';
|
import { map, retry, catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const apiData = ajax('/api/data').pipe(
|
||||||
|
retry(3), // Retry up to 3 times before failing
|
||||||
|
map(res => {
|
||||||
|
if (!res.response) {
|
||||||
|
throw new Error('Value expected!');
|
||||||
|
}
|
||||||
|
return res.response;
|
||||||
|
}),
|
||||||
|
catchError(err => of([]))
|
||||||
|
);
|
||||||
|
|
||||||
|
apiData.subscribe({
|
||||||
|
next(x) { console.log('data: ', x); },
|
||||||
|
error(err) { console.log('errors already caught... will not run'); }
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console, ajax) {
|
|
||||||
// #docregion
|
|
||||||
const apiData = ajax('/api/data').pipe(
|
|
||||||
map((res: any) => {
|
|
||||||
if (!res.response) {
|
|
||||||
console.log('Error occured.');
|
|
||||||
throw new Error('Value expected!');
|
|
||||||
}
|
|
||||||
return res.response;
|
|
||||||
}),
|
|
||||||
retry(3), // Retry up to 3 times before failing
|
|
||||||
catchError(err => of([]))
|
|
||||||
);
|
|
||||||
|
|
||||||
apiData.subscribe({
|
|
||||||
next(x) { console.log('data: ', x); },
|
|
||||||
error(err) { console.log('errors already caught... will not run'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionPromise } from './simple-creation.1';
|
|
||||||
|
|
||||||
describe('simple-creation.1', () => {
|
|
||||||
it('should create a promise from an observable and return an empty object', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const fetch = () => of({foo: 42});
|
|
||||||
docRegionPromise(console, fetch);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[{foo: 42}],
|
|
||||||
['Completed'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,24 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion promise
|
|
||||||
import { from } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion promise
|
|
||||||
|
|
||||||
export function docRegionPromise(console, fetch) {
|
|
||||||
// #docregion promise
|
|
||||||
// Create an Observable out of a promise
|
|
||||||
const data = from(fetch('/api/endpoint'));
|
|
||||||
// Subscribe to begin listening for async result
|
|
||||||
data.subscribe({
|
|
||||||
next(response) { console.log(response); },
|
|
||||||
error(err) { console.error('Error: ' + err); },
|
|
||||||
complete() { console.log('Completed'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion promise
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { docRegionInterval } from './simple-creation.2';
|
|
||||||
|
|
||||||
describe('simple-creation.2', () => {
|
|
||||||
beforeEach(() => jasmine.clock().install());
|
|
||||||
afterEach(() => jasmine.clock().uninstall());
|
|
||||||
|
|
||||||
it('should create an Observable that will publish a value on an interval', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const subscription = docRegionInterval(console);
|
|
||||||
jasmine.clock().tick(1000);
|
|
||||||
expect(console.log).toHaveBeenCalledWith('It\'s been 1 seconds since subscribing!');
|
|
||||||
console.log.calls.reset();
|
|
||||||
|
|
||||||
jasmine.clock().tick(999);
|
|
||||||
expect(console.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(1);
|
|
||||||
expect(console.log).toHaveBeenCalledWith('It\'s been 2 seconds since subscribing!');
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,22 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion interval
|
|
||||||
import { interval } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion interval
|
|
||||||
|
|
||||||
export function docRegionInterval(console) {
|
|
||||||
// #docregion interval
|
|
||||||
// Create an Observable that will publish a value on an interval
|
|
||||||
const secondsCounter = interval(1000);
|
|
||||||
// Subscribe to begin publishing values
|
|
||||||
const subscription = secondsCounter.subscribe(n =>
|
|
||||||
console.log(`It's been ${n + 1} seconds since subscribing!`));
|
|
||||||
|
|
||||||
// #enddocregion interval
|
|
||||||
return subscription;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
import { docRegionEvent } from './simple-creation.3';
|
|
||||||
|
|
||||||
describe('simple-creation.3', () => {
|
|
||||||
let triggerMousemove;
|
|
||||||
let mockConsole;
|
|
||||||
let input;
|
|
||||||
let mockDocument;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
input = {
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEventListener')
|
|
||||||
.and.callFake((eventName, cb) => {
|
|
||||||
if (eventName === 'mousemove') {
|
|
||||||
triggerMousemove = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEventListener'),
|
|
||||||
};
|
|
||||||
mockDocument = { getElementById: () => input };
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log coords when subscribing', () => {
|
|
||||||
docRegionEvent(mockConsole, mockDocument);
|
|
||||||
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 50 });
|
|
||||||
triggerMousemove({ clientX: 30, clientY: 50 });
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 30 });
|
|
||||||
expect(mockConsole.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Coords: 50 X 50'],
|
|
||||||
['Coords: 30 X 50'],
|
|
||||||
['Coords: 50 X 30']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call unsubscribe when clientX and clientY are below < 40 ', () => {
|
|
||||||
docRegionEvent(mockConsole, mockDocument);
|
|
||||||
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
// Ensure that we have unsubscribed.
|
|
||||||
triggerMousemove({ clientX: 30, clientY: 30 });
|
|
||||||
expect(input.removeEventListener).toHaveBeenCalledWith('mousemove', triggerMousemove, undefined);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 50 });
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion event
|
|
||||||
import { fromEvent } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion event
|
|
||||||
|
|
||||||
export function docRegionEvent(console, document) {
|
|
||||||
// #docregion event
|
|
||||||
const el = document.getElementById('my-element');
|
|
||||||
|
|
||||||
// Create an Observable that will publish mouse movements
|
|
||||||
const mouseMoves = fromEvent(el, 'mousemove');
|
|
||||||
|
|
||||||
// Subscribe to start listening for mouse-move events
|
|
||||||
const subscription = mouseMoves.subscribe((evt: MouseEvent) => {
|
|
||||||
// Log coords of mouse movements
|
|
||||||
console.log(`Coords: ${evt.clientX} X ${evt.clientY}`);
|
|
||||||
|
|
||||||
// When the mouse is over the upper-left of the screen,
|
|
||||||
// unsubscribe to stop listening for mouse movements
|
|
||||||
if (evt.clientX < 40 && evt.clientY < 40) {
|
|
||||||
subscription.unsubscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion event
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionAjax } from './simple-creation';
|
|
||||||
|
|
||||||
describe('ajax', () => {
|
|
||||||
it('should make a request and console log the status and response', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const ajax = jasmine.createSpy('ajax').and.callFake((url: string) => {
|
|
||||||
return of({status: 200, response: 'foo bar'});
|
|
||||||
});
|
|
||||||
|
|
||||||
docRegionAjax(console, ajax);
|
|
||||||
expect(console.log).toHaveBeenCalledWith(200, 'foo bar');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,19 +1,65 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
// #docregion promise
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
import { from } from 'rxjs';
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
// Create an Observable out of a promise
|
||||||
/* tslint:disable:align */
|
const data = from(fetch('/api/endpoint'));
|
||||||
|
// Subscribe to begin listening for async result
|
||||||
|
data.subscribe({
|
||||||
|
next(response) { console.log(response); },
|
||||||
|
error(err) { console.error('Error: ' + err); },
|
||||||
|
complete() { console.log('Completed'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion promise
|
||||||
|
|
||||||
|
// #docregion interval
|
||||||
|
|
||||||
|
import { interval } from 'rxjs';
|
||||||
|
|
||||||
|
// Create an Observable that will publish a value on an interval
|
||||||
|
const secondsCounter = interval(1000);
|
||||||
|
// Subscribe to begin publishing values
|
||||||
|
secondsCounter.subscribe(n =>
|
||||||
|
console.log(`It's been ${n} seconds since subscribing!`));
|
||||||
|
|
||||||
|
// #enddocregion interval
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion event
|
||||||
|
|
||||||
|
import { fromEvent } from 'rxjs';
|
||||||
|
|
||||||
|
const el = document.getElementById('my-element');
|
||||||
|
|
||||||
|
// Create an Observable that will publish mouse movements
|
||||||
|
const mouseMoves = fromEvent(el, 'mousemove');
|
||||||
|
|
||||||
|
// Subscribe to start listening for mouse-move events
|
||||||
|
const subscription = mouseMoves.subscribe((evt: MouseEvent) => {
|
||||||
|
// Log coords of mouse movements
|
||||||
|
console.log(`Coords: ${evt.clientX} X ${evt.clientY}`);
|
||||||
|
|
||||||
|
// When the mouse is over the upper-left of the screen,
|
||||||
|
// unsubscribe to stop listening for mouse movements
|
||||||
|
if (evt.clientX < 40 && evt.clientY < 40) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion event
|
||||||
|
|
||||||
|
|
||||||
// #docregion ajax
|
// #docregion ajax
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
|
import { ajax } from 'rxjs/ajax';
|
||||||
|
|
||||||
// Create an Observable that will create an AJAX request
|
// Create an Observable that will create an AJAX request
|
||||||
|
const apiData = ajax('/api/data');
|
||||||
|
// Subscribe to create the request
|
||||||
|
apiData.subscribe(res => console.log(res.status, res.response));
|
||||||
|
|
||||||
// #enddocregion ajax
|
// #enddocregion ajax
|
||||||
export function docRegionAjax(console, ajax) {
|
|
||||||
// #docregion ajax
|
|
||||||
const apiData = ajax('/api/data');
|
|
||||||
// Subscribe to create the request
|
|
||||||
apiData.subscribe(res => console.log(res.status, res.response));
|
|
||||||
// #enddocregion ajax
|
|
||||||
}
|
|
||||||
|
@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model';
|
|||||||
template: `
|
template: `
|
||||||
<section>
|
<section>
|
||||||
Our list of heroes:
|
Our list of heroes:
|
||||||
<toh-hero *ngFor="let hero of heroes" [hero]="hero">
|
<hero-profile *ngFor="let hero of heroes" [hero]="hero">
|
||||||
</toh-hero>
|
</hero-profile>
|
||||||
Total powers: {{totalPowers}}<br>
|
Total powers: {{totalPowers}}<br>
|
||||||
Average power: {{totalPowers / heroes.length}}
|
Average power: {{totalPowers / heroes.length}}
|
||||||
</section>
|
</section>
|
||||||
|
@ -28,7 +28,7 @@ import {
|
|||||||
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { addMatchers, click } from '../../testing';
|
import { addMatchers, newEvent, click } from '../../testing';
|
||||||
|
|
||||||
export class NotProvided extends ValueService { /* example below */ }
|
export class NotProvided extends ValueService { /* example below */ }
|
||||||
beforeEach(addMatchers);
|
beforeEach(addMatchers);
|
||||||
@ -274,11 +274,9 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait while ngModel pushes input.box value to comp.name
|
// then wait while ngModel pushes input.box value to comp.name
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
return fixture.whenStable();
|
return fixture.whenStable();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -314,11 +312,9 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.name
|
// then wait a tick while ngModel pushes input.box value to comp.name
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
tick();
|
tick();
|
||||||
expect(comp.name).toBe(expectedNewName,
|
expect(comp.name).toBe(expectedNewName,
|
||||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||||
@ -339,12 +335,10 @@ describe('demo (with TestBed):', () => {
|
|||||||
// simulate user entering new name in input
|
// simulate user entering new name in input
|
||||||
input.value = inputText;
|
input.value = inputText;
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.text
|
// then wait a tick while ngModel pushes input.box value to comp.text
|
||||||
// and Angular updates the output span
|
// and Angular updates the output span
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(span.textContent).toBe(expectedText, 'output span');
|
expect(span.textContent).toBe(expectedText, 'output span');
|
||||||
|
@ -3,7 +3,7 @@ import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActivatedRoute, ActivatedRouteStub, asyncData, click
|
ActivatedRoute, ActivatedRouteStub, asyncData, click, newEvent
|
||||||
} from '../../testing';
|
} from '../../testing';
|
||||||
|
|
||||||
import { Hero } from '../model/hero';
|
import { Hero } from '../model/hero';
|
||||||
@ -99,10 +99,7 @@ function overrideSetup() {
|
|||||||
const newName = 'New Name';
|
const newName = 'New Name';
|
||||||
|
|
||||||
page.nameInput.value = newName;
|
page.nameInput.value = newName;
|
||||||
|
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
page.nameInput.dispatchEvent(new Event('input')); // tell Angular
|
|
||||||
|
|
||||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||||
@ -200,10 +197,9 @@ function heroModuleSetup() {
|
|||||||
// simulate user entering a new name into the input box
|
// simulate user entering a new name into the input box
|
||||||
nameInput.value = 'quick BROWN fOx';
|
nameInput.value = 'quick BROWN fOx';
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
nameInput.dispatchEvent(newEvent('input'));
|
||||||
nameInput.dispatchEvent(new Event('input'));
|
|
||||||
|
|
||||||
// Tell Angular to update the display binding through the title pipe
|
// Tell Angular to update the display binding through the title pipe
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@ -6,7 +6,7 @@ import { DebugElement } from '@angular/core';
|
|||||||
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { addMatchers } from '../../testing';
|
import { addMatchers, newEvent } from '../../testing';
|
||||||
import { HeroService } from '../model/hero.service';
|
import { HeroService } from '../model/hero.service';
|
||||||
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
||||||
|
|
||||||
@ -53,10 +53,7 @@ describe('HeroListComponent', () => {
|
|||||||
it('should select hero on click', fakeAsync(() => {
|
it('should select hero on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
|
li.dispatchEvent(newEvent('click'));
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
li.dispatchEvent(new Event('click'));
|
|
||||||
tick();
|
tick();
|
||||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||||
expect(comp.selectedHero).toEqual(expectedHero);
|
expect(comp.selectedHero).toEqual(expectedHero);
|
||||||
@ -65,10 +62,7 @@ describe('HeroListComponent', () => {
|
|||||||
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
|
li.dispatchEvent(newEvent('click'));
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
li.dispatchEvent(new Event('click'));
|
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
// should have navigated
|
// should have navigated
|
||||||
|
@ -3,6 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { HighlightDirective } from './highlight.directive';
|
import { HighlightDirective } from './highlight.directive';
|
||||||
|
import { newEvent } from '../../testing';
|
||||||
|
|
||||||
// #docregion test-component
|
// #docregion test-component
|
||||||
@Component({
|
@Component({
|
||||||
@ -58,12 +59,9 @@ describe('HighlightDirective', () => {
|
|||||||
const input = des[2].nativeElement as HTMLInputElement;
|
const input = des[2].nativeElement as HTMLInputElement;
|
||||||
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
||||||
|
|
||||||
|
// dispatch a DOM event so that Angular responds to the input value change.
|
||||||
input.value = 'green';
|
input.value = 'green';
|
||||||
|
input.dispatchEvent(newEvent('input'));
|
||||||
// Dispatch a DOM event so that Angular responds to the input value change.
|
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
||||||
|
@ -14,6 +14,18 @@ export function advance(f: ComponentFixture<any>): void {
|
|||||||
f.detectChanges();
|
f.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create custom DOM event the old fashioned way
|
||||||
|
*
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
|
||||||
|
* Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)"
|
||||||
|
*/
|
||||||
|
export function newEvent(eventName: string, bubbles = false, cancelable = false) {
|
||||||
|
const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
|
||||||
|
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
||||||
// #docregion click-event
|
// #docregion click-event
|
||||||
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ import { HeroService } from '../hero.service';
|
|||||||
styleUrls: [ './hero-detail.component.css' ]
|
styleUrls: [ './hero-detail.component.css' ]
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnInit {
|
||||||
hero: Hero;
|
@Input() hero: Hero;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "tslint:recommended",
|
"extends": "tslint:recommended",
|
||||||
"rulesDirectory": [
|
|
||||||
"codelyzer"
|
|
||||||
],
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"align": {
|
"align": {
|
||||||
"options": [
|
"options": [
|
||||||
@ -16,6 +13,22 @@
|
|||||||
"deprecation": {
|
"deprecation": {
|
||||||
"severity": "warning"
|
"severity": "warning"
|
||||||
},
|
},
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
// TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense).
|
||||||
|
"",
|
||||||
|
"kebab-case"
|
||||||
|
],
|
||||||
|
"contextual-lifecycle": true,
|
||||||
|
"directive-class-suffix": true,
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
["app", "toh"],
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
"eofline": true,
|
"eofline": true,
|
||||||
"import-blacklist": [
|
"import-blacklist": [
|
||||||
true,
|
true,
|
||||||
@ -43,8 +56,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// TODO(gkalpak): Fix the code and enable this.
|
|
||||||
// "no-any": true,
|
|
||||||
"no-console": [
|
"no-console": [
|
||||||
true,
|
true,
|
||||||
"debug",
|
"debug",
|
||||||
@ -84,11 +95,6 @@
|
|||||||
"named": "never"
|
"named": "never"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO(gkalpak): Fix the code and enable this.
|
|
||||||
// "typedef": [
|
|
||||||
// true,
|
|
||||||
// "call-signature"
|
|
||||||
// ],
|
|
||||||
"typedef-whitespace": {
|
"typedef-whitespace": {
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
@ -124,9 +130,6 @@
|
|||||||
"check-typecast"
|
"check-typecast"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"component-class-suffix": true,
|
|
||||||
"contextual-lifecycle": true,
|
|
||||||
"directive-class-suffix": true,
|
|
||||||
"no-conflicting-lifecycle": true,
|
"no-conflicting-lifecycle": true,
|
||||||
"no-host-metadata-property": true,
|
"no-host-metadata-property": true,
|
||||||
"no-input-rename": true,
|
"no-input-rename": true,
|
||||||
@ -138,19 +141,9 @@
|
|||||||
"template-banana-in-box": true,
|
"template-banana-in-box": true,
|
||||||
"template-no-negated-async": true,
|
"template-no-negated-async": true,
|
||||||
"use-lifecycle-interface": true,
|
"use-lifecycle-interface": true,
|
||||||
"use-pipe-transform-interface": true,
|
"use-pipe-transform-interface": true
|
||||||
"directive-selector": [
|
},
|
||||||
true,
|
"rulesDirectory": [
|
||||||
"attribute",
|
"codelyzer"
|
||||||
["app", "toh"],
|
]
|
||||||
"camelCase"
|
|
||||||
],
|
|
||||||
"component-selector": [
|
|
||||||
true,
|
|
||||||
"element",
|
|
||||||
// TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense).
|
|
||||||
"",
|
|
||||||
"kebab-case"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import * as angular from 'angular';
|
import * as angular from 'angular';
|
||||||
import 'angular-route';
|
import 'angular-route';
|
||||||
|
|
||||||
const appModule = angular.module('myApp', [
|
const appName = 'myApp';
|
||||||
|
|
||||||
|
angular.module(appName, [
|
||||||
'ngRoute'
|
'ngRoute'
|
||||||
])
|
])
|
||||||
.config(['$routeProvider', '$locationProvider',
|
.config(['$routeProvider', '$locationProvider',
|
||||||
@ -23,5 +25,5 @@ const appModule = angular.module('myApp', [
|
|||||||
);
|
);
|
||||||
|
|
||||||
export function bootstrap(el: HTMLElement) {
|
export function bootstrap(el: HTMLElement) {
|
||||||
return angular.bootstrap(el, [appModule.name]);
|
return angular.bootstrap(el, [appName]);
|
||||||
}
|
}
|
||||||
|
@ -1,111 +1,112 @@
|
|||||||
# Accessibility in Angular
|
# Accesibilidad en Angular
|
||||||
|
|
||||||
The web is used by a wide variety of people, including those who have visual or motor impairments.
|
Hay una amplia variedad de personas que utilizan la web, algunas de ellas con discapacidad visual o motora.
|
||||||
A variety of assistive technologies are available that make it much easier for these groups to
|
Existen diferentes tecnologías de apoyo que hacen que sea mucho más fácil para estos grupos
|
||||||
interact with web-based software applications.
|
interactuar con aplicaciones de software basadas en la web.
|
||||||
In addition, designing an application to be more accessible generally improves the user experience for all users.
|
Además, diseñar una aplicación para que sea más accesible, normalmente mejora la experiencia de usuario en general.
|
||||||
|
|
||||||
For an in-depth introduction to issues and techniques for designing accessible applications, see the [Accessibility](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) section of the Google's [Web Fundamentals](https://developers.google.com/web/fundamentals/).
|
Para una introducción en profundidad a los problemas y técnicas sobre el diseño de aplicaciones accesibles, puede consultar la sección de [Accesibilidad](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) de Google [Fundamentos Web](https://developers.google.com/web/fundamentals/).
|
||||||
|
|
||||||
This page discusses best practices for designing Angular applications that
|
Esta página habla de las mejores prácticas para diseñar aplicaciones en Angular que funcionan
|
||||||
work well for all users, including those who rely on assistive technologies.
|
bien para todos los usuarios, incluyendo aquéllos que necesitan tecnologías de apoyo.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
For the sample app that this page describes, see the <live-example></live-example>.
|
Para ver la aplicación de ejemplo que describe esta página, ir a <live-example></live-example>.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Accessibility attributes
|
## Atributos de accesibilidad
|
||||||
|
|
||||||
Building accessible web experience often involves setting [ARIA attributes](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
Crear una web accesible a menudo implica establecer los [atributos ARIA](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
||||||
to provide semantic meaning where it might otherwise be missing.
|
para proporcionar la semántica que, de otro modo, podría no estar presente.
|
||||||
Use [attribute binding](guide/attribute-binding) template syntax to control the values of accessibility-related attributes.
|
Usa la plantilla de sintaxis del [enlace de atributos](attribute binding) (guide/attribute-binding) para controlar los valores de los atributos relacionados con la accesibilidad.
|
||||||
|
|
||||||
When binding to ARIA attributes in Angular, you must use the `attr.` prefix, as the ARIA
|
Para enlazar los atributos ARIA en Angular, debes usar el prefijo `attr.`, ya que la especificación ARIA
|
||||||
specification depends specifically on HTML attributes rather than properties of DOM elements.
|
depende de los atributos HTML y no de las propiedades de los elementos del DOM.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!-- Use attr. when binding to an ARIA attribute -->
|
<!-- Use attr. when binding to an ARIA attribute -->
|
||||||
<button [attr.aria-label]="myActionLabel">...</button>
|
<button [attr.aria-label]="myActionLabel">...</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this syntax is only necessary for attribute _bindings_.
|
Observa que esta sintaxis solo es necesaria para los _enlaces_ de atributos.
|
||||||
Static ARIA attributes require no extra syntax.
|
Los atributos ARIA estáticos no requieren de ninguna sintaxis adicional.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!-- Static ARIA attributes require no extra syntax -->
|
<!-- Static ARIA attributes require no extra syntax -->
|
||||||
<button aria-label="Save document">...</button>
|
<button aria-label="Save document">...</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE:
|
NOTA:
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`).
|
Por convenio, los atributos HTML se escriben en minúscula (`tabindex`), mientras que para las propiedades se usa *camelCase* (`tabIndex`).
|
||||||
|
|
||||||
See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
Consulta la guía [Sintaxis del enlace](guide/binding-syntax#html-attribute-vs-dom-property) para saber más sobre las diferencias entre atributos y propiedades.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Angular UI components
|
## Componentes del interfaz de usuario de Angular
|
||||||
|
|
||||||
The [Angular Material](https://material.angular.io/) library, which is maintained by the Angular team, is a suite of reusable UI components that aims to be fully accessible.
|
La librería [Angular Material](https://material.angular.io/), que es mantenida por el equipo Angular, es un conjunto de componentes reutilizables para la interfaz de usuario que pretende ser totalmente accesible.
|
||||||
The [Component Development Kit (CDK)](https://material.angular.io/cdk/categories) includes the `a11y` package that provides tools to support various areas of accessibility.
|
El [Kit de Desarrollo de Componentes (CDK)](https://material.angular.io/cdk/categories) (Component Development Kit) incluye el paquete `a11y` que proporciona herramientas para dar soporte a distintos aspectos de la accesibilidad.
|
||||||
For example:
|
Por ejemplo:
|
||||||
|
|
||||||
* `LiveAnnouncer` is used to announce messages for screen-reader users using an `aria-live` region. See the W3C documentation for more information on [aria-live regions](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live).
|
* `LiveAnnouncer` se utiliza para comunicar mensajes a los usuarios de lectores de pantalla que usan la region `aria-live`. Se puede consultar la documentación de la W3C para obtener más información sobre [regiones aria-live](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live).
|
||||||
|
|
||||||
* The `cdkTrapFocus` directive traps Tab-key focus within an element. Use it to create accessible experience for components like modal dialogs, where focus must be constrained.
|
* La directiva `cdkTrapFocus` limita el foco de la tecla de tabulación para que se quede dentro de un elemento. Úsala para crear una experiencia accesible en componentes como las ventanas modales, donde el foco debe estar limitado.
|
||||||
|
|
||||||
For full details of these and other tools, see the [Angular CDK accessibility overview](https://material.angular.io/cdk/a11y/overview).
|
Para obtener más detalles sobre esta y otras herramientas, consulta el [resumen de accesibilidad del Angular CDK](https://material.angular.io/cdk/a11y/overview).
|
||||||
|
|
||||||
|
|
||||||
### Augmenting native elements
|
### Aumento de elementos nativos
|
||||||
|
|
||||||
Native HTML elements capture a number of standard interaction patterns that are important to accessibility.
|
Los elementos HTML nativos capturan una serie de patrones de interacción estándar que son importantes para la accesibilidad.
|
||||||
When authoring Angular components, you should re-use these native elements directly when possible, rather than re-implementing well-supported behaviors.
|
Al crear componentes de Angular, deberías reutilizar estos elementos nativos directamente cuando sea posible, en lugar de volver a implementar comportamientos bien soportados.
|
||||||
|
|
||||||
For example, instead of creating a custom element for a new variety of button, you can create a component that uses an attribute selector with a native `<button>` element.
|
Por ejemplo, en lugar de crear un elemento personalizado para un nuevo tipo de botón, puedes crear un componente que use un selector de atributos con un elemento nativo `<button>`.
|
||||||
This most commonly applies to `<button>` and `<a>`, but can be used with many other types of element.
|
Esto se aplica sobre todo a `<button>` y `<a>`, pero se puede usar con muchos otros tipos de elementos.
|
||||||
|
|
||||||
You can see examples of this pattern in Angular Material: [`MatButton`](https://github.com/angular/components/blob/master/src/material/button/button.ts#L66-L68), [`MatTabNav`](https://github.com/angular/components/blob/master/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L67), [`MatTable`](https://github.com/angular/components/blob/master/src/material/table/table.ts#L17).
|
You can see examples of this pattern in Angular Material: [`MatButton`](https://github.com/angular/components/blob/master/src/material/button/button.ts#L66-L68), [`MatTabNav`](https://github.com/angular/components/blob/master/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L67), [`MatTable`](https://github.com/angular/components/blob/master/src/material/table/table.ts#L17).
|
||||||
|
|
||||||
### Using containers for native elements
|
### Uso de contenedores para elementos nativos
|
||||||
|
|
||||||
Sometimes using the appropriate native element requires a container element.
|
A veces, para usar el elemento nativo apropiado hace falta un contenedor.
|
||||||
For example, the native `<input>` element cannot have children, so any custom text entry components need
|
Por ejemplo, el elemento nativo `<input>` no puede tener hijos, por lo que cualquier componente de entrada de texto personalizado necesita envolver un `<input>` con elementos adicionales.
|
||||||
to wrap an `<input>` with additional elements.
|
|
||||||
While you might just include the `<input>` in your custom component's template,
|
|
||||||
this makes it impossible for users of the component to set arbitrary properties and attributes to the input element.
|
|
||||||
Instead, you can create a container component that uses content projection to include the native control in the
|
|
||||||
component's API.
|
|
||||||
|
|
||||||
You can see [`MatFormField`](https://material.angular.io/components/form-field/overview) as an example of this pattern.
|
Si bien puedes incluir el `<input>` en la plantilla de tu componente personalizado,
|
||||||
|
esto hace que sea imposible para los usuarios de dicho componente establecer propiedades y atributos arbitrarios para el elemento de entrada.
|
||||||
|
En su lugar, puedes crear un componente contenedor que utilice la proyección de contenido para incluir el control nativo en el
|
||||||
|
API del componente.
|
||||||
|
|
||||||
## Case study: Building a custom progress bar
|
Puedes consultar [`MatFormField`](https://material.angular.io/components/form-field/overview) para ver un ejemplo de este patrón.
|
||||||
|
|
||||||
The following example shows how to make a simple progress bar accessible by using host binding to control accessibility-related attributes.
|
## Caso práctico: creación de una barra de progreso personalizada
|
||||||
|
|
||||||
* The component defines an accessibility-enabled element with both the standard HTML attribute `role`, and ARIA attributes. The ARIA attribute `aria-valuenow` is bound to the user's input.
|
El siguiente ejemplo muestra cómo hacer que una barra de progreso simple sea accesible utilizando el *host binding* para controlar los atributos relacionados con la accesibilidad.
|
||||||
|
|
||||||
|
* El componente define un elemento habilitado para accesibilidad con el atributo HTML estándar `role` y los atributos ARIA. El atributo ARIA `aria-valuenow` está vinculado a la entrada del usuario.
|
||||||
|
|
||||||
<code-example path="accessibility/src/app/progress-bar.component.ts" header="src/app/progress-bar.component.ts" region="progressbar-component"></code-example>
|
<code-example path="accessibility/src/app/progress-bar.component.ts" header="src/app/progress-bar.component.ts" region="progressbar-component"></code-example>
|
||||||
|
|
||||||
|
|
||||||
* In the template, the `aria-label` attribute ensures that the control is accessible to screen readers.
|
* En la plantilla, el atributo `aria-label` asegura que el control sea accesible para los lectores de pantalla.
|
||||||
|
|
||||||
<code-example path="accessibility/src/app/app.component.html" header="src/app/app.component.html" region="template"></code-example>
|
<code-example path="accessibility/src/app/app.component.html" header="src/app/app.component.html" region="template"></code-example>
|
||||||
|
|
||||||
|
|
||||||
## Routing and focus management
|
## Enrutamiento y gestión del foco
|
||||||
|
|
||||||
Tracking and controlling [focus](https://developers.google.com/web/fundamentals/accessibility/focus/) in a UI is an important consideration in designing for accessibility.
|
El seguimiento y el control del [foco](https://developers.google.com/web/fundamentals/accessibility/focus/) en una interfaz de usuario son aspectos muy importantes en el diseño si queremos tener en cuenta la accesibilidad.
|
||||||
When using Angular routing, you should decide where page focus goes upon navigation.
|
Al usar el enrutamiento de Angular, debes decidir dónde va el foco de la página al navegar.
|
||||||
|
|
||||||
To avoid relying solely on visual cues, you need to make sure your routing code updates focus after page navigation.
|
Para evitar depender únicamente de señales visuales, te debes asegurar de que el código de enrutamiento actualiza el foco después de la navegación de la página.
|
||||||
Use the `NavigationEnd` event from the `Router` service to know when to update
|
Usa el evento `NavigationEnd` del servicio` Router` para saber cuándo actualizar el foco.
|
||||||
focus.
|
|
||||||
|
El siguiente ejemplo muestra cómo encontrar y poner el foco en el contenido principal de la cabecera (el elemento `#main-content-header`) dentro del DOM después de la navegación.
|
||||||
|
|
||||||
The following example shows how to find and focus the main content header in the DOM after navigation.
|
The following example shows how to find and focus the main content header in the DOM after navigation.
|
||||||
|
|
||||||
@ -119,13 +120,12 @@ router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
In a real application, the element that receives focus will depend on your specific
|
En una aplicación real, el elemento que recibe el foco dependerá de la estructura específica y del diseño que tenga tu aplicación.
|
||||||
application structure and layout.
|
El elemento enfocado debe colocar a los usuarios en una posición en la que pasen inmediatamente al contenido principal que acaba de ser visualizado.
|
||||||
The focused element should put users in a position to immediately move into the main content that has just been routed into view.
|
Debe evitar situaciones en las que el foco vuelva al elemento `body` después de un cambio de ruta.
|
||||||
You should avoid situations where focus returns to the `body` element after a route change.
|
|
||||||
|
|
||||||
|
|
||||||
## Additional resources
|
## Recursos adicionales
|
||||||
|
|
||||||
* [Accessibility - Google Web Fundamentals](https://developers.google.com/web/fundamentals/accessibility)
|
* [Accessibility - Google Web Fundamentals](https://developers.google.com/web/fundamentals/accessibility)
|
||||||
|
|
||||||
@ -145,13 +145,13 @@ You should avoid situations where focus returns to the `body` element after a ro
|
|||||||
|
|
||||||
* [Codelyzer](http://codelyzer.com/rules/) provides linting rules that can help you make sure your code meets accessibility standards.
|
* [Codelyzer](http://codelyzer.com/rules/) provides linting rules that can help you make sure your code meets accessibility standards.
|
||||||
|
|
||||||
Books
|
Libros
|
||||||
|
|
||||||
* "A Web for Everyone: Designing Accessible User Experiences", Sarah Horton and Whitney Quesenbery
|
* "A Web for Everyone: Designing Accessible User Experiences", Sarah Horton and Whitney Quesenbery
|
||||||
|
|
||||||
* "Inclusive Design Patterns", Heydon Pickering
|
* "Inclusive Design Patterns", Heydon Pickering
|
||||||
|
|
||||||
## More on accessibility
|
## Más sobre accesibilidad
|
||||||
|
|
||||||
You may also be interested in the following:
|
Podrías estar interesado en lo siguiente:
|
||||||
* [Audit your Angular app's accessibility with codelyzer](https://web.dev/accessible-angular-with-codelyzer/).
|
* [Audit your Angular app's accessibility with codelyzer](https://web.dev/accessible-angular-with-codelyzer/).
|
||||||
|
@ -341,7 +341,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
In Angular, the template no longer specifies its associated controller.
|
In Angular, the template no longer specifies its associated controller.
|
||||||
Rather, the component specifies its associated template as part of the component class decorator.
|
Rather, the component specifies its associated template as part of the component class decorator.
|
||||||
|
|
||||||
For more information, see [Architecture Overview](guide/architecture#components).
|
For more information, see [Architecture Overview](guide/architecture#componentes).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -1035,7 +1035,7 @@ The Angular code is shown using TypeScript.
|
|||||||
This is a nonissue in Angular because ES 2015 modules
|
This is a nonissue in Angular because ES 2015 modules
|
||||||
handle the namespacing for you.
|
handle the namespacing for you.
|
||||||
|
|
||||||
For more information on modules, see the [Modules](guide/architecture#modules) section of the
|
For more information on modules, see the [Modules](guide/architecture#módulos) section of the
|
||||||
[Architecture Overview](guide/architecture).
|
[Architecture Overview](guide/architecture).
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -1112,7 +1112,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
This is how you associate a template with logic, which is defined in the component class.
|
This is how you associate a template with logic, which is defined in the component class.
|
||||||
|
|
||||||
For more information, see the [Components](guide/architecture#components)
|
For more information, see the [Components](guide/architecture#componentes)
|
||||||
section of the [Architecture Overview](guide/architecture) page.
|
section of the [Architecture Overview](guide/architecture) page.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -1144,7 +1144,7 @@ The Angular code is shown using TypeScript.
|
|||||||
|
|
||||||
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the functionality can be imported into NgModules.
|
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the functionality can be imported into NgModules.
|
||||||
|
|
||||||
For more information, see the [Components](guide/architecture#components)
|
For more information, see the [Components](guide/architecture#componentes)
|
||||||
section of the [Architecture Overview](guide/architecture) page.
|
section of the [Architecture Overview](guide/architecture) page.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ For example:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
...
|
...
|
||||||
|
665
aio/content/guide/aot-compile.en.md
Normal file
665
aio/content/guide/aot-compile.en.md
Normal file
@ -0,0 +1,665 @@
|
|||||||
|
# Ahead-of-time (AOT) compilation
|
||||||
|
|
||||||
|
An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
|
||||||
|
|
||||||
|
The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
|
||||||
|
|
||||||
|
This guide explains how to specify metadata and apply available compiler options to compile your applications efficiently using the AOT compiler.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Watch Alex Rickabaugh explain the Angular compiler</a> at AngularConnect 2019.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{@a why-aot}
|
||||||
|
|
||||||
|
Here are some reasons you might want to use AOT.
|
||||||
|
|
||||||
|
* *Faster rendering*
|
||||||
|
With AOT, the browser downloads a pre-compiled version of the application.
|
||||||
|
The browser loads executable code so it can render the application immediately, without waiting to compile the app first.
|
||||||
|
|
||||||
|
* *Fewer asynchronous requests*
|
||||||
|
The compiler _inlines_ external HTML templates and CSS style sheets within the application JavaScript,
|
||||||
|
eliminating separate ajax requests for those source files.
|
||||||
|
|
||||||
|
* *Smaller Angular framework download size*
|
||||||
|
There's no need to download the Angular compiler if the app is already compiled.
|
||||||
|
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
||||||
|
|
||||||
|
* *Detect template errors earlier*
|
||||||
|
The AOT compiler detects and reports template binding errors during the build step
|
||||||
|
before users can see them.
|
||||||
|
|
||||||
|
* *Better security*
|
||||||
|
AOT compiles HTML templates and components into JavaScript files long before they are served to the client.
|
||||||
|
With no templates to read and no risky client-side HTML or JavaScript evaluation,
|
||||||
|
there are fewer opportunities for injection attacks.
|
||||||
|
|
||||||
|
{@a overview}
|
||||||
|
|
||||||
|
## Choosing a compiler
|
||||||
|
|
||||||
|
Angular offers two ways to compile your application:
|
||||||
|
|
||||||
|
* **_Just-in-Time_ (JIT)**, which compiles your app in the browser at runtime. This was the default until Angular 8.
|
||||||
|
* **_Ahead-of-Time_ (AOT)**, which compiles your app and libraries at build time. This is the default since Angular 9.
|
||||||
|
|
||||||
|
When you run the [`ng build`](cli/build) (build only) or [`ng serve`](cli/serve) (build and serve locally) CLI commands, the type of compilation (JIT or AOT) depends on the value of the `aot` property in your build configuration specified in `angular.json`. By default, `aot` is set to `true` for new CLI apps.
|
||||||
|
|
||||||
|
See the [CLI command reference](cli) and [Building and serving Angular apps](guide/build) for more information.
|
||||||
|
|
||||||
|
## How AOT works
|
||||||
|
|
||||||
|
The Angular AOT compiler extracts **metadata** to interpret the parts of the application that Angular is supposed to manage.
|
||||||
|
You can specify the metadata explicitly in **decorators** such as `@Component()` and `@Input()`, or implicitly in the constructor declarations of the decorated classes.
|
||||||
|
The metadata tells Angular how to construct instances of your application classes and interact with them at runtime.
|
||||||
|
|
||||||
|
In the following example, the `@Component()` metadata object and the class constructor tell Angular how to create and display an instance of `TypicalComponent`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'app-typical',
|
||||||
|
template: '<div>A typical component for {{data.name}}</div>'
|
||||||
|
)}
|
||||||
|
export class TypicalComponent {
|
||||||
|
@Input() data: TypicalData;
|
||||||
|
constructor(private someService: SomeService) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`.
|
||||||
|
When it needs to create a `TypicalComponent` instance, Angular calls the factory, which produces a new visual element, bound to a new instance of the component class with its injected dependency.
|
||||||
|
|
||||||
|
### Compilation phases
|
||||||
|
|
||||||
|
There are three phases of AOT compilation.
|
||||||
|
* Phase 1 is *code analysis*.
|
||||||
|
In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||||
|
|
||||||
|
* Phase 2 is *code generation*.
|
||||||
|
In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation.
|
||||||
|
|
||||||
|
* Phase 3 is *template type checking*.
|
||||||
|
In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options).
|
||||||
|
|
||||||
|
|
||||||
|
### Metadata restrictions
|
||||||
|
|
||||||
|
You write metadata in a _subset_ of TypeScript that must conform to the following general constraints:
|
||||||
|
|
||||||
|
* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript.
|
||||||
|
* Only reference exported symbols after [code folding](#code-folding).
|
||||||
|
* Only call [functions supported](#supported-functions) by the compiler.
|
||||||
|
* Decorated and data-bound class members must be public.
|
||||||
|
|
||||||
|
For additional guidelines and instructions on preparing an application for AOT compilation, see [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements (as described more fully below).
|
||||||
|
For help in understanding and resolving these problems, see [AOT Metadata Errors](guide/aot-metadata-errors).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### Configuring AOT compilation
|
||||||
|
|
||||||
|
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
||||||
|
|
||||||
|
## Phase 1: Code analysis
|
||||||
|
|
||||||
|
The TypeScript compiler does some of the analytic work of the first phase. It emits the `.d.ts` _type definition files_ with type information that the AOT compiler needs to generate application code.
|
||||||
|
At the same time, the AOT **collector** analyzes the metadata recorded in the Angular decorators and outputs metadata information in **`.metadata.json`** files, one per `.d.ts` file.
|
||||||
|
|
||||||
|
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
|
||||||
|
describes the JSON format as a collection of TypeScript interfaces.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{@a expression-syntax}
|
||||||
|
### Expression syntax limitations
|
||||||
|
|
||||||
|
The AOT collector only understands a subset of JavaScript.
|
||||||
|
Define metadata objects with the following limited syntax:
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td, th {vertical-align: top}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Syntax</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal object </td>
|
||||||
|
<td><code>{cherry: true, apple: true, mincemeat: false}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal array </td>
|
||||||
|
<td><code>['cherries', 'flour', 'sugar']</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Spread in literal array</td>
|
||||||
|
<td><code>['apples', 'flour', ...the_rest]</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Calls</td>
|
||||||
|
<td><code>bake(ingredients)</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New</td>
|
||||||
|
<td><code>new Oven()</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Property access</td>
|
||||||
|
<td><code>pie.slice</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Array index</td>
|
||||||
|
<td><code>ingredients[0]</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Identity reference</td>
|
||||||
|
<td><code>Component</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>A template string</td>
|
||||||
|
<td><code>`pie is ${multiplier} times better than cake`</code></td>
|
||||||
|
<tr>
|
||||||
|
<td>Literal string</td>
|
||||||
|
<td><code>pi</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal number</td>
|
||||||
|
<td><code>3.14153265</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal boolean</td>
|
||||||
|
<td><code>true</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal null</td>
|
||||||
|
<td><code>null</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Supported prefix operator </td>
|
||||||
|
<td><code>!cake</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Supported binary operator </td>
|
||||||
|
<td><code>a+b</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Conditional operator</td>
|
||||||
|
<td><code>a ? b : c</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parentheses</td>
|
||||||
|
<td><code>(a+b)</code></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
If an expression uses unsupported syntax, the collector writes an error node to the `.metadata.json` file.
|
||||||
|
The compiler later reports the error if it needs that piece of metadata to generate the application code.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
|
||||||
|
|
||||||
|
```
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
...
|
||||||
|
"strictMetadataEmit" : true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{@a function-expression}
|
||||||
|
{@a arrow-functions}
|
||||||
|
### No arrow functions
|
||||||
|
|
||||||
|
The AOT compiler does not support [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)
|
||||||
|
and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called _lambda_ functions.
|
||||||
|
|
||||||
|
Consider the following component decorator:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
...
|
||||||
|
providers: [{provide: server, useFactory: () => new Server()}]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The AOT collector does not support the arrow function, `() => new Server()`, in a metadata expression.
|
||||||
|
It generates an error node in place of the function.
|
||||||
|
When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an _exported function_.
|
||||||
|
|
||||||
|
You can fix the error by converting to this:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export function serverFactory() {
|
||||||
|
return new Server();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
...
|
||||||
|
providers: [{provide: server, useFactory: serverFactory}]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
In version 5 and later, the compiler automatically performs this rewriting while emitting the `.js` file.
|
||||||
|
|
||||||
|
{@a exported-symbols}
|
||||||
|
{@a code-folding}
|
||||||
|
### Code folding
|
||||||
|
|
||||||
|
The compiler can only resolve references to **_exported_** symbols.
|
||||||
|
The collector, however, can evaluate an expression during collection and record the result in the `.metadata.json`, rather than the original expression.
|
||||||
|
This allows you to make limited use of non-exported symbols within expressions.
|
||||||
|
|
||||||
|
For example, the collector can evaluate the expression `1 + 2 + 3 + 4` and replace it with the result, `10`.
|
||||||
|
This process is called _folding_. An expression that can be reduced in this manner is _foldable_.
|
||||||
|
|
||||||
|
{@a var-declaration}
|
||||||
|
The collector can evaluate references to module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file.
|
||||||
|
|
||||||
|
Consider the following component definition:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const template = '<div>{{hero.name}}</div>';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-hero',
|
||||||
|
template: template
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
@Input() hero: Hero;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler could not refer to the `template` constant because it isn't exported.
|
||||||
|
The collector, however, can fold the `template` constant into the metadata definition by in-lining its contents.
|
||||||
|
The effect is the same as if you had written:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'app-hero',
|
||||||
|
template: '<div>{{hero.name}}</div>'
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
@Input() hero: Hero;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`.
|
||||||
|
|
||||||
|
You can take this example a step further by including the `template` constant in another expression:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const template = '<div>{{hero.name}}</div>';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-hero',
|
||||||
|
template: template + '<div>{{hero.title}}</div>'
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
@Input() hero: Hero;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The collector reduces this expression to its equivalent _folded_ string:
|
||||||
|
|
||||||
|
```
|
||||||
|
'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Foldable syntax
|
||||||
|
|
||||||
|
The following table describes which expressions the collector can and cannot fold:
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td, th {vertical-align: top}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Syntax</th>
|
||||||
|
<th>Foldable</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal object </td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal array </td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Spread in literal array</td>
|
||||||
|
<td>no</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Calls</td>
|
||||||
|
<td>no</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New</td>
|
||||||
|
<td>no</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Property access</td>
|
||||||
|
<td>yes, if target is foldable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Array index</td>
|
||||||
|
<td> yes, if target and index are foldable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Identity reference</td>
|
||||||
|
<td>yes, if it is a reference to a local</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>A template with no substitutions</td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>A template with substitutions</td>
|
||||||
|
<td>yes, if the substitutions are foldable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal string</td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal number</td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal boolean</td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Literal null</td>
|
||||||
|
<td>yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Supported prefix operator </td>
|
||||||
|
<td>yes, if operand is foldable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Supported binary operator </td>
|
||||||
|
<td>yes, if both left and right are foldable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Conditional operator</td>
|
||||||
|
<td>yes, if condition is foldable </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parentheses</td>
|
||||||
|
<td>yes, if the expression is foldable</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the compiler to resolve.
|
||||||
|
|
||||||
|
|
||||||
|
## Phase 2: code generation
|
||||||
|
|
||||||
|
The collector makes no attempt to understand the metadata that it collects and outputs to `.metadata.json`.
|
||||||
|
It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
||||||
|
It's the compiler's job to interpret the `.metadata.json` in the code generation phase.
|
||||||
|
|
||||||
|
The compiler understands all syntax forms that the collector supports, but it may reject _syntactically_ correct metadata if the _semantics_ violate compiler rules.
|
||||||
|
|
||||||
|
### Public symbols
|
||||||
|
|
||||||
|
The compiler can only reference _exported symbols_.
|
||||||
|
|
||||||
|
* Decorated component class members must be public. You cannot make an `@Input()` property private or protected.
|
||||||
|
* Data bound properties must also be public.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// BAD CODE - title is private
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
template: '<h1>{{title}}</h1>'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
private title = 'My App'; // Bad
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{@a supported-functions}
|
||||||
|
|
||||||
|
### Supported classes and functions
|
||||||
|
|
||||||
|
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
|
||||||
|
The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
|
||||||
|
|
||||||
|
The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
||||||
|
* New instances
|
||||||
|
|
||||||
|
The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
|
||||||
|
|
||||||
|
* Supported decorators
|
||||||
|
|
||||||
|
The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators).
|
||||||
|
|
||||||
|
* Function calls
|
||||||
|
|
||||||
|
Factory functions must be exported, named functions.
|
||||||
|
The AOT compiler does not support lambda expressions ("arrow functions") for factory functions.
|
||||||
|
|
||||||
|
{@a function-calls}
|
||||||
|
### Functions and static method calls
|
||||||
|
|
||||||
|
The collector accepts any function or static method that contains a single `return` statement.
|
||||||
|
The compiler, however, only supports macros in the form of functions or static methods that return an *expression*.
|
||||||
|
|
||||||
|
For example, consider the following function:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export function wrapInArray<T>(value: T): T[] {
|
||||||
|
return [value];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset.
|
||||||
|
|
||||||
|
You might use `wrapInArray()` like this:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@NgModule({
|
||||||
|
declarations: wrapInArray(TypicalComponent)
|
||||||
|
})
|
||||||
|
export class TypicalModule {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler treats this usage as if you had written:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@NgModule({
|
||||||
|
declarations: [TypicalComponent]
|
||||||
|
})
|
||||||
|
export class TypicalModule {}
|
||||||
|
```
|
||||||
|
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
||||||
|
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
||||||
|
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
|
||||||
|
|
||||||
|
{@a metadata-rewriting}
|
||||||
|
|
||||||
|
### Metadata rewriting
|
||||||
|
|
||||||
|
The compiler treats object literals containing the fields `useClass`, `useValue`, `useFactory`, and `data` specially, converting the expression initializing one of these fields into an exported variable that replaces the expression.
|
||||||
|
This process of rewriting these expressions removes all the restrictions on what can be in them because
|
||||||
|
the compiler doesn't need to know the expression's value—it just needs to be able to generate a reference to the value.
|
||||||
|
|
||||||
|
You might write something like:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class TypicalServer {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
providers: [{provide: SERVER, useFactory: () => TypicalServer}]
|
||||||
|
})
|
||||||
|
export class TypicalModule {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported.
|
||||||
|
To allow this, the compiler automatically rewrites this to something like:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class TypicalServer {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ɵ0 = () => new TypicalServer();
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
providers: [{provide: SERVER, useFactory: ɵ0}]
|
||||||
|
})
|
||||||
|
export class TypicalModule {}
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows the compiler to generate a reference to `ɵ0` in the factory without having to know what the value of `ɵ0` contains.
|
||||||
|
|
||||||
|
The compiler does the rewriting during the emit of the `.js` file.
|
||||||
|
It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export. and it does not interfere with the ES module's exported API.
|
||||||
|
|
||||||
|
|
||||||
|
{@a binding-expression-validation}
|
||||||
|
|
||||||
|
## Phase 3: Template type checking
|
||||||
|
|
||||||
|
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
|
||||||
|
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
|
||||||
|
|
||||||
|
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
|
||||||
|
(see [Angular Compiler Options](guide/angular-compiler-options)).
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
In [Angular Ivy](guide/ivy), the template type checker has been completely rewritten to be more capable as well as stricter, meaning it can catch a variety of new errors that the previous type checker would not detect.
|
||||||
|
|
||||||
|
As a result, templates that previously compiled under View Engine can fail type checking under Ivy. This can happen because Ivy's stricter checking catches genuine errors, or because application code is not typed correctly, or because the application uses libraries in which typings are inaccurate or not specific enough.
|
||||||
|
|
||||||
|
This stricter type checking is not enabled by default in version 9, but can be enabled by setting the `strictTemplates` configuration option.
|
||||||
|
We do expect to make strict type checking the default in the future.
|
||||||
|
|
||||||
|
For more information about type-checking options, and about improvements to template type checking in version 9 and above, see [Template type checking](guide/template-typecheck).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Template validation produces error messages when a type error is detected in a template binding
|
||||||
|
expression, similar to how type errors are reported by the TypeScript compiler against code in a `.ts`
|
||||||
|
file.
|
||||||
|
|
||||||
|
For example, consider the following component:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: '{{person.addresss.street}}'
|
||||||
|
})
|
||||||
|
class MyComponent {
|
||||||
|
person?: Person;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the following error:
|
||||||
|
|
||||||
|
```
|
||||||
|
my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
|
||||||
|
```
|
||||||
|
|
||||||
|
The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file
|
||||||
|
generated by the template compiler that holds contents of the `MyComponent` class template.
|
||||||
|
The compiler never writes this file to disk.
|
||||||
|
The line and column numbers are relative to the template string in the `@Component` annotation of the class, `MyComponent` in this case.
|
||||||
|
If a component uses `templateUrl` instead of `template`, the errors are reported in the HTML file referenced by the `templateUrl` instead of a synthetic file.
|
||||||
|
|
||||||
|
The error location is the beginning of the text node that contains the interpolation expression with the error.
|
||||||
|
If the error is in an attribute binding such as `[value]="person.address.street"`, the error
|
||||||
|
location is the location of the attribute that contains the error.
|
||||||
|
|
||||||
|
The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is.
|
||||||
|
For example, if the `strictTypeChecks` is specified, the error
|
||||||
|
```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'```
|
||||||
|
is reported as well as the above error message.
|
||||||
|
|
||||||
|
### Type narrowing
|
||||||
|
|
||||||
|
The expression used in an `ngIf` directive is used to narrow type unions in the Angular
|
||||||
|
template compiler, the same way the `if` expression does in TypeScript.
|
||||||
|
For example, to avoid `Object is possibly 'undefined'` error in the template above, modify it to only emit the interpolation if the value of `person` is initialized as shown below:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: '<span *ngIf="person"> {{person.addresss.street}} </span>'
|
||||||
|
})
|
||||||
|
class MyComponent {
|
||||||
|
person?: Person;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the binding expression will never be `undefined`.
|
||||||
|
|
||||||
|
For more information about input type narrowing, see [Input setter coercion](guide/template-typecheck#input-setter-coercion) and [Improving template type checking for custom directives](guide/structural-directives#directive-type-checks).
|
||||||
|
|
||||||
|
### Non-null type assertion operator
|
||||||
|
|
||||||
|
Use the [non-null type assertion operator](guide/template-expression-operators#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||||
|
|
||||||
|
In the following example, the `person` and `address` properties are always set together, implying that `address` is always non-null if `person` is non-null.
|
||||||
|
There is no convenient way to describe this constraint to TypeScript and the template compiler, but the error is suppressed in the example by using `address!.street`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>'
|
||||||
|
})
|
||||||
|
class MyComponent {
|
||||||
|
person?: Person;
|
||||||
|
address?: Address;
|
||||||
|
|
||||||
|
setData(person: Person, address: Address) {
|
||||||
|
this.person = person;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The non-null assertion operator should be used sparingly as refactoring of the component might break this constraint.
|
||||||
|
|
||||||
|
In this example it is recommended to include the checking of `address` in the `*ngIf` as shown below:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
selector: 'my-component',
|
||||||
|
template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>'
|
||||||
|
})
|
||||||
|
class MyComponent {
|
||||||
|
person?: Person;
|
||||||
|
address?: Address;
|
||||||
|
|
||||||
|
setData(person: Person, address: Address) {
|
||||||
|
this.person = person;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -1,131 +1,128 @@
|
|||||||
# Ahead-of-time (AOT) compilation
|
# Compilación anticipada (AOT)
|
||||||
|
|
||||||
An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
|
Una aplicación Angular consta principalmente de componentes y sus plantillas HTML. Los componentes y plantillas proporcionados por Angular no pueden ser entendidos por el navegador directamente, las aplicaciones en Angular requieren un proceso de compilación antes de que puedan correr en un navegador.
|
||||||
|
|
||||||
The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
|
La [compilación anticipada de Angular (AOT)](guide/glossary#aot) convierte plantillas y código de TypeScript en eficiente código JavaScript durante la fase de construcción _antes_ de que el navegador descargue y corra el código. Compilando tu aplicación durante el proceso de construcción se proporciona una renderización más rápida en el navegador.
|
||||||
|
|
||||||
This guide explains how to specify metadata and apply available compiler options to compile your applications efficiently using the AOT compiler.
|
Esta guía explica como especificar metadatos y aplicar las opciones del compilador disponibles para compilar aplicaciones eficientemente usando la compilación anticipada (AOT).
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Watch Alex Rickabaugh explain the Angular compiler</a> at AngularConnect 2019.
|
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Mira a Alex Rickabaugh explicando el compilador de Angular en AngularConnect 2019.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a why-aot}
|
{@a why-aot}
|
||||||
|
|
||||||
Here are some reasons you might want to use AOT.
|
Aquí algunas razones por las qué podrías querer usar AOT.
|
||||||
|
|
||||||
* *Faster rendering*
|
* *Renderizado más rápido*
|
||||||
With AOT, the browser downloads a pre-compiled version of the application.
|
Con AOT, el navegador descarga una versión pre compilada de una aplicación.
|
||||||
The browser loads executable code so it can render the application immediately, without waiting to compile the app first.
|
El navegador carga el código ejecutable para que pueda renderizar la aplicación inmediatamente, sin esperar a compilar la aplicación primero.
|
||||||
|
|
||||||
* *Fewer asynchronous requests*
|
* *Menos solicitudes asincrónicas*
|
||||||
The compiler _inlines_ external HTML templates and CSS style sheets within the application JavaScript,
|
El compilador _inserta_ plantillas HTML y hojas de estilo CSS externas dentro de la aplicación JavaScript, eliminando solicitudes ajax separadas para esos archivos fuente.
|
||||||
eliminating separate ajax requests for those source files.
|
|
||||||
|
|
||||||
* *Smaller Angular framework download size*
|
* *Angular pesa menos*
|
||||||
There's no need to download the Angular compiler if the app is already compiled.
|
No existe necesidad de incluir el compilador de Angular si la aplicación ya esta compilada.
|
||||||
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
El compilador es aproximadamente la mitad de Angular en si mismo, así que omitíendolo se reduce drásticamente el peso de la aplicación.
|
||||||
|
|
||||||
* *Detect template errors earlier*
|
* *Detecte errores en platillas antes*
|
||||||
The AOT compiler detects and reports template binding errors during the build step
|
El compilador AOT detecta y reporta errores de enlace de datos en plantillas durante el paso de construcción antes que los usuarios puedan verlos.
|
||||||
before users can see them.
|
|
||||||
|
|
||||||
* *Better security*
|
* *Mejor seguridad*
|
||||||
AOT compiles HTML templates and components into JavaScript files long before they are served to the client.
|
AOT compila las plantillas HTML y componentes en archivos JavaScript mucho antes de que se sirvan a el cliente.
|
||||||
With no templates to read and no risky client-side HTML or JavaScript evaluation,
|
Sin plantillas para leer y sin evaluaciones de JavaScript o HTML del lado del cliente riesgosas, existen pocas oportunidades para ataques de inyección.
|
||||||
there are fewer opportunities for injection attacks.
|
|
||||||
|
|
||||||
{@a overview}
|
{@a overview}
|
||||||
|
|
||||||
## Choosing a compiler
|
## Eligiendo un compilador.
|
||||||
|
|
||||||
Angular offers two ways to compile your application:
|
Angular ofrece dos formas para compilar tu aplicación:
|
||||||
|
|
||||||
* **_Just-in-Time_ (JIT)**, which compiles your app in the browser at runtime. This was the default until Angular 8.
|
* **_Just-in-Time_ (JIT)**, cuando compila tu aplicación en el navegador en tiempo de ejecución. Este fué el modo de compilación por defecto hasta Angular 8.
|
||||||
* **_Ahead-of-Time_ (AOT)**, which compiles your app and libraries at build time. This is the default since Angular 9.
|
* **_Ahead-of-Time_ (AOT)**, cuando compila tu aplicación y librerías en el tiempo de construcción. Este es el modo de compilación por defecto desde Angular 9.
|
||||||
|
|
||||||
When you run the [`ng build`](cli/build) (build only) or [`ng serve`](cli/serve) (build and serve locally) CLI commands, the type of compilation (JIT or AOT) depends on the value of the `aot` property in your build configuration specified in `angular.json`. By default, `aot` is set to `true` for new CLI apps.
|
Cuando ejecutas los comandos del CLI [`ng build`](cli/build) (solo construcción) o [`ng serve`](cli/serve) (construye y sirve localmente), el tipo de compilación (JIT o AOT) depende del valor de la propiedad `aot` en tu configuración de construcción especificada en el archivo `angular.json`. Por defecto, `aot` esta establecido en `true` para nuevas aplicaciones.
|
||||||
|
|
||||||
See the [CLI command reference](cli) and [Building and serving Angular apps](guide/build) for more information.
|
Mira la [referencia de comandos del CLI](cli) y [Construyendo y sirviendo Angular apps](guide/build) para más información.
|
||||||
|
|
||||||
## How AOT works
|
## Como funciona AOT
|
||||||
|
|
||||||
The Angular AOT compiler extracts **metadata** to interpret the parts of the application that Angular is supposed to manage.
|
El compilador de Angular AOT extrae **metadatos** para interpretar las partes de la aplicación que se supone que Angular maneja.
|
||||||
You can specify the metadata explicitly in **decorators** such as `@Component()` and `@Input()`, or implicitly in the constructor declarations of the decorated classes.
|
Puedes especificar los metadatos explícitamente en **decoradores** como `@Component()` y `@Input()`, o implícitamente en las declaraciones del constructor de las clases decoradas.
|
||||||
The metadata tells Angular how to construct instances of your application classes and interact with them at runtime.
|
Los metadatos le dicen a Angular como construir instancias de clases e interactuar con ellas en tiempo de ejecución.
|
||||||
|
|
||||||
In the following example, the `@Component()` metadata object and the class constructor tell Angular how to create and display an instance of `TypicalComponent`.
|
En el siguiente ejemplo, los metadatos de `@Component()` y el constructor le dicen a Angular como crear y mostrar una instancia de `TypicalComponent`.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-typical',
|
selector: 'app-typical',
|
||||||
template: '<div>A typical component for {{data.name}}</div>'
|
template: '<div>A typical component for {{data.name}}</div>'
|
||||||
})
|
)}
|
||||||
export class TypicalComponent {
|
export class TypicalComponent {
|
||||||
@Input() data: TypicalData;
|
@Input() data: TypicalData;
|
||||||
constructor(private someService: SomeService) { ... }
|
constructor(private someService: SomeService) { ... }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`.
|
El compilador de Angular extrae los metadatos _una_ vez y genera una _fabrica_ para `TypicalComponent`.
|
||||||
When it needs to create a `TypicalComponent` instance, Angular calls the factory, which produces a new visual element, bound to a new instance of the component class with its injected dependency.
|
Cuando este necesita crear una instancia de `TypicalComponent`, Angular llama a la fabrica, el cuál produce un nuevo elemento visual, vinculado a una nueva instancia la clase del componente con su dependencia inyectada.
|
||||||
|
|
||||||
### Compilation phases
|
### Fases de compilación
|
||||||
|
|
||||||
There are three phases of AOT compilation.
|
Existen tres fases de compilación en AOT.
|
||||||
* Phase 1 is *code analysis*.
|
|
||||||
In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
|
||||||
|
|
||||||
* Phase 2 is *code generation*.
|
* Fase 1: *análisis de código*
|
||||||
In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation.
|
En esta fase, el compilador de TypeScript y el *recolector AOT* crea una representación de la fuente. El recolector no intenta interpretar los metadatos recopilados. Estos representan los metadatos lo mejor que pueden y registra errores cuando este detecta un violación de sintaxis en los metadatos.
|
||||||
|
|
||||||
* Phase 3 is *template type checking*.
|
* Fase 2: *generación de código*
|
||||||
In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options).
|
En esta fase, el `StaticReflector` del compilador interpreta los metadatos recolectados en la fase 1, realiza validaciones adicionales de los metadatos y lanza un error si este detecta una violación de la restricción de metadatos.
|
||||||
|
|
||||||
|
* Fase 3: *verificación de tipos en plantillas*
|
||||||
|
Esta fase es opcional, el *compilador de plantillas* de Angular usa el compilador de Typescript para validar las expresiones de enlaces de datos en las plantillas. Puedes habilitar esta fase explícitamente configurando la opción `fullTemplateTypeCheck`; revisa [Opciones del Compilador Angular](guide/angular-compiler-options).
|
||||||
|
|
||||||
|
|
||||||
### Metadata restrictions
|
### Restricciones de los metadatos
|
||||||
|
|
||||||
You write metadata in a _subset_ of TypeScript that must conform to the following general constraints:
|
Escribe metadatos en un _subconjunto_ de TypeScript que debe cumplir las siguientes restricciones generales:
|
||||||
|
|
||||||
* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript.
|
* Limita la [sintaxis de expresiones](#expression-syntax) al subconjunto soportado de JavaScript.
|
||||||
* Only reference exported symbols after [code folding](#code-folding).
|
* Solo haz referencia a los símbolos exportados después del [plegado de código](#code-folding).
|
||||||
* Only call [functions supported](#supported-functions) by the compiler.
|
* Solo llame [funciones compátibles](#supported-functions) por el compilador.
|
||||||
* Decorated and data-bound class members must be public.
|
* Miembros de clase decorados y con enlaces de datos deben ser públicos.
|
||||||
|
|
||||||
For additional guidelines and instructions on preparing an application for AOT compilation, see [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
Para guías e instrucciones adicionales al preparar una aplicación para compilación anticipada (AOT), revise [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements (as described more fully below).
|
Los errores en compilación anticipada (AOT) comúnmente ocurren debido a que los metadatos no se ajustan a los requisitos del compilador (como se describen con más detalle a continuación).
|
||||||
For help in understanding and resolving these problems, see [AOT Metadata Errors](guide/aot-metadata-errors).
|
Para ayudar a entender y resolver estos problemas, revisa [Errores de metadatos en AOT](guide/aot-metadata-errors).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Configuring AOT compilation
|
### Configurando la compilación anticipada (AOT).
|
||||||
|
|
||||||
You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
|
Puedes proporcionar opciones en el [archivo de configuración de TypeScript](guide/typescript-configuration) que controlan el proceso de compilación. Revisa [las opciones de compilación de Angular](guide/angular-compiler-options) para una lista completa de opciones disponibles.
|
||||||
|
|
||||||
## Phase 1: Code analysis
|
## Fase 1: Análisis de código.
|
||||||
|
|
||||||
The TypeScript compiler does some of the analytic work of the first phase. It emits the `.d.ts` _type definition files_ with type information that the AOT compiler needs to generate application code.
|
El compilador de TypeScript realiza parte del trabajo analítico en la primer fase. Este emite los _archivos de definición de tipos_ `.d.ts` con el tipo de información que el compilador AOT necesita para generar el código de la aplicación.
|
||||||
At the same time, the AOT **collector** analyzes the metadata recorded in the Angular decorators and outputs metadata information in **`.metadata.json`** files, one per `.d.ts` file.
|
Al mismo tiempo, el **recolector** AOT analiza los metadatos registrados en los decoradores de Angular y genera información de metadatos en archivos **`.metadata.json`**, uno por archivo `.d.ts`.
|
||||||
|
|
||||||
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
Puedes pensar en `.metadata.json` como un diagrama de la estructura general de los metadatos de un decorador, representados como un [árbol de sintaxis abstracta (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
|
El [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) de Angular describe el formato JSON como una colección de interfaces de TypeScript.
|
||||||
describes the JSON format as a collection of TypeScript interfaces.
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a expression-syntax}
|
{@a expression-syntax}
|
||||||
### Expression syntax limitations
|
### Limitaciones del sintaxis de expresión.
|
||||||
|
|
||||||
The AOT collector only understands a subset of JavaScript.
|
El recolector de AOT solo entiende un subconjunto de JavaScript.
|
||||||
Define metadata objects with the following limited syntax:
|
Defina objetos de metadatos con la siguiente sintaxis limitada:
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
@ -133,85 +130,84 @@ Define metadata objects with the following limited syntax:
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Syntax</th>
|
<th>Sintaxis</th>
|
||||||
<th>Example</th>
|
<th>Ejemplo</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal object </td>
|
<td>Objeto literal </td>
|
||||||
<td><code>{cherry: true, apple: true, mincemeat: false}</code></td>
|
<td><code>{cherry: true, apple: true, mincemeat: false}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal array </td>
|
<td>Colección literal </td>
|
||||||
<td><code>['cherries', 'flour', 'sugar']</code></td>
|
<td><code>['cherries', 'flour', 'sugar']</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Spread in literal array</td>
|
<td>Operador spread en colección literal</td>
|
||||||
<td><code>['apples', 'flour', ...the_rest]</code></td>
|
<td><code>['apples', 'flour', ...the_rest]</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Calls</td>
|
<td>Llamadas</td>
|
||||||
<td><code>bake(ingredients)</code></td>
|
<td><code>bake(ingredients)</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>New</td>
|
<td>Nuevo</td>
|
||||||
<td><code>new Oven()</code></td>
|
<td><code>new Oven()</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Property access</td>
|
<td>Acceso a propiedades</td>
|
||||||
<td><code>pie.slice</code></td>
|
<td><code>pie.slice</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Array index</td>
|
<td>Indices de colección</td>
|
||||||
<td><code>ingredients[0]</code></td>
|
<td><code>ingredients[0]</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Identity reference</td>
|
<td>Referencia de identidad</td>
|
||||||
<td><code>Component</code></td>
|
<td><code>Component</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>A template string</td>
|
<td>Una plantilla de cadena</td>
|
||||||
<td><code>`pie is ${multiplier} times better than cake`</code></td>
|
<td><code>`pie is ${multiplier} times better than cake`</code></td>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal string</td>
|
<td>Cadena literal</td>
|
||||||
<td><code>pi</code></td>
|
<td><code>pi</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal number</td>
|
<td>Numero literal</td>
|
||||||
<td><code>3.14153265</code></td>
|
<td><code>3.14153265</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal boolean</td>
|
<td>Booleano literal</td>
|
||||||
<td><code>true</code></td>
|
<td><code>true</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal null</td>
|
<td>Nulo literal</td>
|
||||||
<td><code>null</code></td>
|
<td><code>null</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Supported prefix operator </td>
|
<td>Soporte a operador prefijo</td>
|
||||||
<td><code>!cake</code></td>
|
<td><code>!cake</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Supported binary operator </td>
|
<td>Soporte a operaciones binarias</td>
|
||||||
<td><code>a+b</code></td>
|
<td><code>a+b</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Conditional operator</td>
|
<td>Operador condicional</td>
|
||||||
<td><code>a ? b : c</code></td>
|
<td><code>a ? b : c</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Parentheses</td>
|
<td>Paréntesis</td>
|
||||||
<td><code>(a+b)</code></td>
|
<td><code>(a+b)</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
Si una expresión usa sintaxis no compatible, el recolector escribe un error de nodo en el archivo `.metadata.json`.
|
||||||
If an expression uses unsupported syntax, the collector writes an error node to the `.metadata.json` file.
|
El compilador luego reporta el error si necesita esa pieza de metadatos para generar el código de la aplicación.
|
||||||
The compiler later reports the error if it needs that piece of metadata to generate the application code.
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
|
Si quieres que `ngc` reporte errores de sintaxis inmediatamente en lugar de producir un archivo `.metadata.json` con errores, configurá la opción `strictMetadataEmit` en el archivo de configuración de TypeScript.
|
||||||
|
|
||||||
```
|
```
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
@ -220,18 +216,17 @@ The compiler later reports the error if it needs that piece of metadata to gener
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries.
|
Las librerías de Angular tienen esta opción para asegurar que todo los archivos `.metadata.json` están limpios y es una buena practica hacer lo mismo cuando construimos nuestras propias librerías.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a function-expression}
|
{@a function-expression}
|
||||||
{@a arrow-functions}
|
{@a arrow-functions}
|
||||||
### No arrow functions
|
### Sin funciones flecha
|
||||||
|
|
||||||
The AOT compiler does not support [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)
|
El compilador AOT no soporta [expresiones de función](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function) y [funciones flecha](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function), tampoco las funciones llamadas _lambda_.
|
||||||
and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called _lambda_ functions.
|
|
||||||
|
|
||||||
Consider the following component decorator:
|
Considere el siguiente decorador del componente:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
@ -240,11 +235,11 @@ Consider the following component decorator:
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
The AOT collector does not support the arrow function, `() => new Server()`, in a metadata expression.
|
El recolector de AOT no soporta la función tipo flecha, `() => new Server()`, en una expression de los metadatos.
|
||||||
It generates an error node in place of the function.
|
Esto genera un error de nodo en lugar de la función.
|
||||||
When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an _exported function_.
|
Cuando el compilador posteriormente interpreta este nodo, este reporta un error que invita a convertir la función flecha en una _función exportada_.
|
||||||
|
|
||||||
You can fix the error by converting to this:
|
Puedes arreglar este error convirtiendo a esto:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export function serverFactory() {
|
export function serverFactory() {
|
||||||
@ -257,23 +252,23 @@ export function serverFactory() {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
In version 5 and later, the compiler automatically performs this rewriting while emitting the `.js` file.
|
En la version 5 y posterior, el compilador realiza automáticamente esta re escritura mientras emite el archivo `.js`.
|
||||||
|
|
||||||
{@a exported-symbols}
|
{@a exported-symbols}
|
||||||
{@a code-folding}
|
{@a code-folding}
|
||||||
### Code folding
|
### Plegado de código (code folding)
|
||||||
|
|
||||||
The compiler can only resolve references to **_exported_** symbols.
|
El compilador puede solo resolver referencias a símbolos **_exportados_**.
|
||||||
The collector, however, can evaluate an expression during collection and record the result in the `.metadata.json`, rather than the original expression.
|
El recolector sin embargo, puede evaluar una expresión durante la recolección y registrar el resultado en el `.metadata.json`, en vez de la expresión original.
|
||||||
This allows you to make limited use of non-exported symbols within expressions.
|
Esto permite hacer un uso limitado de símbolos no exportados dentro de expresiones.
|
||||||
|
|
||||||
For example, the collector can evaluate the expression `1 + 2 + 3 + 4` and replace it with the result, `10`.
|
Por ejemplo, el recolector puede evaluar la expresión `1 + 2 + 3 + 4` y remplazarlo con el resultado, `10`.
|
||||||
This process is called _folding_. An expression that can be reduced in this manner is _foldable_.
|
El proceso es llamado _plegado_. Una expresión que puede se reducida de esta manera es _plegable_.
|
||||||
|
|
||||||
{@a var-declaration}
|
{@a var-declaration}
|
||||||
The collector can evaluate references to module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file.
|
El recolector puede evaluar referencias hacia el modulo local, declaraciones `const` e inicializadas en `var` y `let` efectivamente son removidas del archivo `.metadata.json`.
|
||||||
|
|
||||||
Consider the following component definition:
|
Considere la siguiente definición del componente:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const template = '<div>{{hero.name}}</div>';
|
const template = '<div>{{hero.name}}</div>';
|
||||||
@ -287,9 +282,9 @@ export class HeroComponent {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The compiler could not refer to the `template` constant because it isn't exported.
|
El compilador no podría referirse hacia la constante `template` por que esta no ha sido exportada.
|
||||||
The collector, however, can fold the `template` constant into the metadata definition by in-lining its contents.
|
El recolector sim embargo, puede encontrar la constante `template` dentro de la definición de metadatos insertando su contenido.
|
||||||
The effect is the same as if you had written:
|
El efecto es el mismo como si hubieras escrito:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
@ -301,9 +296,9 @@ export class HeroComponent {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`.
|
No hay una referencia a `template` y por lo tanto nada que moleste al compilador cuando posteriormente interprete las salidas del recolector en el archivo `.metadata.json`.
|
||||||
|
|
||||||
You can take this example a step further by including the `template` constant in another expression:
|
Puedes tomar este ejemplo un paso más allá para incluir la constante `template` en otra expresión:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const template = '<div>{{hero.name}}</div>';
|
const template = '<div>{{hero.name}}</div>';
|
||||||
@ -317,15 +312,15 @@ export class HeroComponent {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The collector reduces this expression to its equivalent _folded_ string:
|
El recolector reduce esta expresión a su equivalente cadena _plegada_:
|
||||||
|
|
||||||
```
|
```
|
||||||
'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
|
'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Foldable syntax
|
#### Sintaxis plegable
|
||||||
|
|
||||||
The following table describes which expressions the collector can and cannot fold:
|
La siguiente tabla describe cuales expresiones el recolector puede y no puede encontrar:
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
@ -333,101 +328,101 @@ The following table describes which expressions the collector can and cannot fol
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Syntax</th>
|
<th>Sintaxis</th>
|
||||||
<th>Foldable</th>
|
<th>Plegable</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal object </td>
|
<td>Objeto literal </td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal array </td>
|
<td>Colección literal </td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Spread in literal array</td>
|
<td>Operador spread en colección literal</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Calls</td>
|
<td>Llamadas</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>New</td>
|
<td>Nuevo</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Property access</td>
|
<td>Acceso a propiedades<</td>
|
||||||
<td>yes, if target is foldable</td>
|
<td>si, si el objetivo es plegable</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Array index</td>
|
<td>Indices de colección</td>
|
||||||
<td> yes, if target and index are foldable</td>
|
<td>si, si el objetivo y el indice es plegable</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Identity reference</td>
|
<td>Referencia de identidad</td>
|
||||||
<td>yes, if it is a reference to a local</td>
|
<td>si, si es una referencia a una local</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>A template with no substitutions</td>
|
<td>Una plantilla sin sustituciones</td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>A template with substitutions</td>
|
<td>Una plantilla con sustituciones</td>
|
||||||
<td>yes, if the substitutions are foldable</td>
|
<td>si, si las sustituciones son plegables</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal string</td>
|
<td>Cadena literal</td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal number</td>
|
<td>Numero literal</td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal boolean</td>
|
<td>Booleano literal</td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Literal null</td>
|
<td>Nulo literal</td>
|
||||||
<td>yes</td>
|
<td>si</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Supported prefix operator </td>
|
<td>Soporte a operador prefijo </td>
|
||||||
<td>yes, if operand is foldable</td>
|
<td>si, si el operador es plegable</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Supported binary operator </td>
|
<td>Soporte a operador binario </td>
|
||||||
<td>yes, if both left and right are foldable</td>
|
<td>si, si ambos tanto el izquierda y derecha con plegables</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Conditional operator</td>
|
<td>Operador condicional</td>
|
||||||
<td>yes, if condition is foldable </td>
|
<td>si, si la condición es plegable </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Parentheses</td>
|
<td>Paréntesis</td>
|
||||||
<td>yes, if the expression is foldable</td>
|
<td>si, si la expresión es plegable</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the compiler to resolve.
|
Si es una expresión no plegable, el recolector lo escribe a `.metadata.json` como un [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) para que el compilador lo resuelva.
|
||||||
|
|
||||||
|
|
||||||
## Phase 2: code generation
|
## Fase 2: generación de código
|
||||||
|
|
||||||
The collector makes no attempt to understand the metadata that it collects and outputs to `.metadata.json`.
|
El recolector no hace ningún intento para entender los metadatos que se recolectarón y las envía a `.metadata.json`.
|
||||||
It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
|
Esto representa los metadatos lo mejor que puede y registra errores cuando detecta una violación de sintaxis en los metadatos.
|
||||||
It's the compiler's job to interpret the `.metadata.json` in the code generation phase.
|
Es el trabajo del compilador interpretar el `.metadata.json` en la fase de generación de código.
|
||||||
|
|
||||||
The compiler understands all syntax forms that the collector supports, but it may reject _syntactically_ correct metadata if the _semantics_ violate compiler rules.
|
El compilador entiende toda las formas de sintaxis que el recolector soporta pero puede rechazar metadatos _sintácticamente_ correctos si la _semántica_ viola reglas del compilador.
|
||||||
|
|
||||||
### Public symbols
|
### Símbolos públicos
|
||||||
|
|
||||||
The compiler can only reference _exported symbols_.
|
El compilador puede solo referirse a _símbolos exportados_.
|
||||||
|
|
||||||
* Decorated component class members must be public. You cannot make an `@Input()` property private or protected.
|
* Los atributos de la clase que tienen un decorador deben ser públicos. No puedes hacer que una propiedad `@Input()` sea privada o protegida.
|
||||||
* Data bound properties must also be public.
|
* Las propiedades enlazadas a datos también deben ser publicas.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// BAD CODE - title is private
|
// BAD CODE - title is private
|
||||||
@ -442,32 +437,32 @@ export class AppComponent {
|
|||||||
|
|
||||||
{@a supported-functions}
|
{@a supported-functions}
|
||||||
|
|
||||||
### Supported classes and functions
|
### Clases y funciones compatibles
|
||||||
|
|
||||||
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
|
El recolector puede representar una función o la creación de un objeto con `new` mientras la sintaxis sea valida.
|
||||||
The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
|
El compilador, sin embargo, puede posteriormente rechazar a generar una llamada hacia una función _particular_ o la creación de un objeto _particular_.
|
||||||
|
|
||||||
The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
El compilador puede solo crea instancias de ciertas clases, compatibles solo con decoradores centrales y solo compatibles con llamadas a macros (funciones o métodos estáticos) que retornan expresiones.
|
||||||
* New instances
|
|
||||||
|
|
||||||
The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
|
* Nuevas instancias
|
||||||
|
El compilador solo permite metadatos que crean instancias de las clases `InjectionToken` de `@angular/core`.
|
||||||
|
|
||||||
* Supported decorators
|
* Decoradores soportados
|
||||||
|
El compilador solo soporta metadatos del [Modulo de decoradores de Angular en `@angular/core`](api/core#decorators).
|
||||||
|
|
||||||
The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators).
|
* Llamadas a funciones
|
||||||
|
|
||||||
* Function calls
|
Las funciones de fabrica deben ser exportadas.
|
||||||
|
El compilador AOT no soporta expresiones lambda ("funciones flecha") para las funciones de fabrica.
|
||||||
Factory functions must be exported, named functions.
|
|
||||||
The AOT compiler does not support lambda expressions ("arrow functions") for factory functions.
|
|
||||||
|
|
||||||
{@a function-calls}
|
{@a function-calls}
|
||||||
### Functions and static method calls
|
|
||||||
|
|
||||||
The collector accepts any function or static method that contains a single `return` statement.
|
### Llamadas a funciones y métodos estáticos.
|
||||||
The compiler, however, only supports macros in the form of functions or static methods that return an *expression*.
|
|
||||||
|
|
||||||
For example, consider the following function:
|
El recolector acepta cualquier función o método estático que contenga una sola declaración de `return`.
|
||||||
|
El compilador sin embargo, solo soporta macros (funciones o métodos estáticos) en la forma de funciones y métodos estáticos que retornan una *expression*.
|
||||||
|
|
||||||
|
Por ejemplo, considere la siguiente función:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export function wrapInArray<T>(value: T): T[] {
|
export function wrapInArray<T>(value: T): T[] {
|
||||||
@ -475,9 +470,9 @@ export function wrapInArray<T>(value: T): T[] {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset.
|
Puedes llamar a `wrapInArray` en una definición de metadatos porque este retorna el valor de una expresiones qué se ajusta al subconjunto de Javascript restringido del compilador.
|
||||||
|
|
||||||
You might use `wrapInArray()` like this:
|
Puede usar `wrapInArray()` así:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -486,7 +481,7 @@ You might use `wrapInArray()` like this:
|
|||||||
export class TypicalModule {}
|
export class TypicalModule {}
|
||||||
```
|
```
|
||||||
|
|
||||||
The compiler treats this usage as if you had written:
|
El compilador trata este uso como si hubieras escrito:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -494,19 +489,19 @@ The compiler treats this usage as if you had written:
|
|||||||
})
|
})
|
||||||
export class TypicalModule {}
|
export class TypicalModule {}
|
||||||
```
|
```
|
||||||
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
|
|
||||||
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
|
El [`RouterModule`](api/router/RouterModule) de Angular exporta dos métodos estáticos, `forRoot` y `forChild` para ayudar a declarar rutas raíz e hijas.
|
||||||
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
|
Revisa el [código fuente](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code") para estos métodos para ver como los macros puede simplificar la configuración de complejos [NgModules](guide/ngmodules).
|
||||||
|
|
||||||
{@a metadata-rewriting}
|
{@a metadata-rewriting}
|
||||||
|
|
||||||
### Metadata rewriting
|
### Re escribiendo metadatos
|
||||||
|
|
||||||
The compiler treats object literals containing the fields `useClass`, `useValue`, `useFactory`, and `data` specially, converting the expression initializing one of these fields into an exported variable that replaces the expression.
|
El compilador trata a los objetos literales que contengan los campos `useClass`, `useValue`, `useFactory` y `data` específicamente, convirtiendo la expresión inicializando uno de estos campos en una variable exportada que reemplaza la expresión
|
||||||
This process of rewriting these expressions removes all the restrictions on what can be in them because
|
|
||||||
the compiler doesn't need to know the expression's value—it just needs to be able to generate a reference to the value.
|
|
||||||
|
|
||||||
You might write something like:
|
Este proceso de rescribir estas expresiones remueve todo las restricciones que pueden estar en el, porque el compilador no necesita conocer el valor de las expresiones solo necesita poder generar una referencia al valor.
|
||||||
|
|
||||||
|
Puedes escribir algo como:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class TypicalServer {
|
class TypicalServer {
|
||||||
@ -519,8 +514,8 @@ class TypicalServer {
|
|||||||
export class TypicalModule {}
|
export class TypicalModule {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported.
|
Sin la reescritura, esto sería invalido por que las lambdas no son soportadas y `TypicalServer` no esta exportada.
|
||||||
To allow this, the compiler automatically rewrites this to something like:
|
Para permitirlo, el compilador automáticamente re escribe esto a algo como:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class TypicalServer {
|
class TypicalServer {
|
||||||
@ -535,40 +530,38 @@ export const ɵ0 = () => new TypicalServer();
|
|||||||
export class TypicalModule {}
|
export class TypicalModule {}
|
||||||
```
|
```
|
||||||
|
|
||||||
This allows the compiler to generate a reference to `ɵ0` in the factory without having to know what the value of `ɵ0` contains.
|
Esto permite que el compilador genere una referencia hacia `ɵ0` en la fabrica sin tener que conocer cual es el valor de `ɵ0`.
|
||||||
|
|
||||||
The compiler does the rewriting during the emit of the `.js` file.
|
El compilador hace la reescritura durante la emisión de el archivo `.js`.
|
||||||
It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export. and it does not interfere with the ES module's exported API.
|
Sin embargo, no reescribe el archivo `.d.ts`, entonces TypeScript no lo reconoce como una exportación y esto no interfiere con la API exportada de los módulos ES.
|
||||||
|
|
||||||
|
|
||||||
{@a binding-expression-validation}
|
{@a binding-expression-validation}
|
||||||
|
|
||||||
## Phase 3: Template type checking
|
## Fase 3: Verificación de tipos en las plantillas
|
||||||
|
|
||||||
One of the Angular compiler's most helpful features is the ability to type-check expressions within templates, and catch any errors before they cause crashes at runtime.
|
Una de las características más útiles del compilador de Angular es la habilidad de comprobar el tipado de las expresiones dentro de las plantillas y capturar cualquier error antes de que ellos causen fallas en tiempo de ejecución.
|
||||||
In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
|
|
||||||
|
|
||||||
Enable this phase explicitly by adding the compiler option `"fullTemplateTypeCheck"` in the `"angularCompilerOptions"` of the project's TypeScript configuration file
|
En la fase de verificación de tipos en las plantillas, el compilador de plantillas de Angular usa a el compilador de TypeScript para validar las expresiones con enlazadas a datos en las plantillas.
|
||||||
(see [Angular Compiler Options](guide/angular-compiler-options)).
|
|
||||||
|
Habilite esta fase explícitamente agregando la opción del compilador `"fullTemplateTypeCheck"` en las `"angularCompilerOptions"` del archivo de configuración del proyecto TypeScript (mira [Opciones del compilador de Angular](guide/angular-compiler-options)).
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
In [Angular Ivy](guide/ivy), the template type checker has been completely rewritten to be more capable as well as stricter, meaning it can catch a variety of new errors that the previous type checker would not detect.
|
En [Angular Ivy](guide/ivy), la verificación de tipos para las plantillas a sido completamente reescrita para ser más capaz así como más estricto, esto significa poder capturar una variedad de nuevos errores que antes el verificador de tipos no podia detectar.
|
||||||
|
|
||||||
As a result, templates that previously compiled under View Engine can fail type checking under Ivy. This can happen because Ivy's stricter checking catches genuine errors, or because application code is not typed correctly, or because the application uses libraries in which typings are inaccurate or not specific enough.
|
Como resultado, las plantillas que previamente se compilarón bajo `View Engine` pueden fallar con el verificador de tipos bajo `Ivy`. Esto puede pasar por que el verificador de Ivy captura errores genuinos o porque el código de la aplicación no esta tipado correctamente o porque la aplicación usa librerías en las cuales el tipado es incorrecto o no es lo suficientemente especifico.
|
||||||
|
|
||||||
This stricter type checking is not enabled by default in version 9, but can be enabled by setting the `strictTemplates` configuration option.
|
Este verificador de tipos estricto no esta habilitado por defecto el la version 9 pero puedes habilitarlo configurando la opción `strictTemplates`.
|
||||||
We do expect to make strict type checking the default in the future.
|
Nosotros esperamos hacer que el verificador de tipos estricto este habilitado por defecto en el futuro.
|
||||||
|
|
||||||
For more information about type-checking options, and about improvements to template type checking in version 9 and above, see [Template type checking](guide/template-typecheck).
|
Para más información acerca de las opciones del verificador de tipos y más acerca de mejoras hacia la verificación de tipos en plantillas en la version 9 en adelante, mira [Verificando tipos en plantillas](guide/template-typecheck).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Template validation produces error messages when a type error is detected in a template binding
|
La validación de templates produce mensajes de error cuando un error de tipo es detectado en una plantilla con una expresión con enlace de datos, similar a como los errores de tipado son reportados por el compilador de TypeScript contra el código en un archivo `.ts`.
|
||||||
expression, similar to how type errors are reported by the TypeScript compiler against code in a `.ts`
|
|
||||||
file.
|
|
||||||
|
|
||||||
For example, consider the following component:
|
Por ejemplo, considere el siguiente componente:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
@ -580,32 +573,29 @@ For example, consider the following component:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This produces the following error:
|
Esto produce el siguiente error:
|
||||||
|
|
||||||
```
|
```
|
||||||
my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
|
my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
|
||||||
```
|
```
|
||||||
|
|
||||||
The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file
|
El archivo reporta el mensaje de error, `my.component.ts.MyComponent.html`, es un archivo sintético generado por el compilador de plantillas que espera que tenga contenido de la clase `MyComponent`.
|
||||||
generated by the template compiler that holds contents of the `MyComponent` class template.
|
El compilador nunca escribe un archivo en el disco.
|
||||||
The compiler never writes this file to disk.
|
Los números de línea y columna son relativos a la plantilla de cadena en el anotación `@Component` de la clase, `MyComponent` en este caso.
|
||||||
The line and column numbers are relative to the template string in the `@Component` annotation of the class, `MyComponent` in this case.
|
Si un componente usa `templateUrl` en vez de `template`, los errores son reportados en el archivo HTML referenciado por el `templateUrl` en vez de un archivo sintético.
|
||||||
If a component uses `templateUrl` instead of `template`, the errors are reported in the HTML file referenced by the `templateUrl` instead of a synthetic file.
|
|
||||||
|
|
||||||
The error location is the beginning of the text node that contains the interpolation expression with the error.
|
La ubicación del error esta en el inicio del nodo de texto que contiene la expresión interpolada con el error.
|
||||||
If the error is in an attribute binding such as `[value]="person.address.street"`, the error
|
Si el error esta en un atributo con enlace de datos como `[value]="person.address.street"`, la ubicación del error es la ubicación del atributo que contiene el error.
|
||||||
location is the location of the attribute that contains the error.
|
|
||||||
|
La validación usa el verificador de tipos de TypeScript y las opciones suministradas hacia el compilador de TypeScript para controlar qué tan detallada es la validación de tipos.
|
||||||
|
Por ejemplo, si el `strictTypeChecks` es especificado, el error ```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'``` es reportado así como el mensaje de error anterior.
|
||||||
|
|
||||||
The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is.
|
|
||||||
For example, if the `strictTypeChecks` is specified, the error
|
|
||||||
```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'```
|
|
||||||
is reported as well as the above error message.
|
|
||||||
|
|
||||||
### Type narrowing
|
### Type narrowing
|
||||||
|
|
||||||
The expression used in an `ngIf` directive is used to narrow type unions in the Angular
|
La expresión usada en un directiva `ngIf` es usada para estrechar uniones de tipo en el compilador de plantillas de Angular, de la misma manera que la expresión `if` lo hace en TypeScript.
|
||||||
template compiler, the same way the `if` expression does in TypeScript.
|
Por ejemplo, para evitar el error `Object is possibly 'undefined'` en la plantilla de arriba, modifícalo para que solo emita la interpolación si el valor de `person` esta inicializado como se muestra en seguida:
|
||||||
For example, to avoid `Object is possibly 'undefined'` error in the template above, modify it to only emit the interpolation if the value of `person` is initialized as shown below:
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
@ -617,16 +607,17 @@ For example, to avoid `Object is possibly 'undefined'` error in the template abo
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the binding expression will never be `undefined`.
|
Usando `*ngIf` permite que el compilador de TypeScript infiera que el atributo `person` usado en la expresión enlanzada nunca séra `undefined`.
|
||||||
|
|
||||||
For more information about input type narrowing, see [Input setter coercion](guide/template-typecheck#input-setter-coercion) and [Improving template type checking for custom directives](guide/structural-directives#directive-type-checks).
|
Para más información acerca del estrechamiento de tipos de entrada, mira [Coerción del establecedor de entrada](guide/template-typecheck#input-setter-coercion) y [Mejorando el verificar de tipos para directivas personalizadas](guide/structural-directives#directive-type-checks).
|
||||||
|
|
||||||
### Non-null type assertion operator
|
### Operador de aserción de tipo nulo
|
||||||
|
|
||||||
Use the [non-null type assertion operator](guide/template-expression-operators#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
Use el [operador de aserción de tipo nulo](guide/template-expression-operators#non-null-assertion-operator) para reprimir el error `Object is possibly 'undefined'` cuando es inconveniente usar `*ngIf` o cuando alguna restricción en el componente asegura que la expresión siempre es no nula cuando la expresión con enlace de datos es interpolada.
|
||||||
|
|
||||||
|
En el siguiente ejemplo, las propiedades `person` y `address` son siempre configuradas juntas, implicando que `address` siempre es no nula si `person` es no nula.
|
||||||
|
No existe una forma conveniente de describir esta restricción a TypeScript y a el compilador de plantillas pero el error es suprimido en el ejemplo por usar `address!.street`.
|
||||||
|
|
||||||
In the following example, the `person` and `address` properties are always set together, implying that `address` is always non-null if `person` is non-null.
|
|
||||||
There is no convenient way to describe this constraint to TypeScript and the template compiler, but the error is suppressed in the example by using `address!.street`.
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
@ -644,9 +635,9 @@ There is no convenient way to describe this constraint to TypeScript and the tem
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The non-null assertion operator should be used sparingly as refactoring of the component might break this constraint.
|
El operador de aserción de tipo nulo debería usarse con moderación ya que la refactorización del componente podría romper esta restricción.
|
||||||
|
|
||||||
In this example it is recommended to include the checking of `address` in the `*ngIf` as shown below:
|
En este ejemplo es recomendable incluir la verificación de `address` en el `*ngIf` como se muestra a continuación:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
# App shell
|
# App shell
|
||||||
|
|
||||||
App shell is a way to render a portion of your application via a route at build time.
|
App shell es una manera de renderizar una porción de tu aplicación a través de una ruta en tiempo de compilación (build time).
|
||||||
It can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads.
|
Puede mejorar la experiencia de usuario lanzando rápidamente una página estática renderizada (un esqueleto común a todas las páginas) mientras el navegador descarga la versión completa del cliente y la muestra automáticamente al finalizar su carga.
|
||||||
|
|
||||||
This gives users a meaningful first paint of your application that appears quickly because the browser can simply render the HTML and CSS without the need to initialize any JavaScript.
|
Esto da a los usuarios una primera visualización significativa de su aplicación que aparece rápidamente porque el navegador simplemente puede renderizar HTML y CSS sin la necesidad de inicializar JavaScript.
|
||||||
|
|
||||||
Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
Obténga más información en [El modelo de aplicación Shell](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||||
|
|
||||||
## Step 1: Prepare the application
|
## Paso 1: Prepara la aplicación
|
||||||
|
|
||||||
You can do this with the following CLI command:
|
Puedes hacer esto con el siguiente comando CLI:
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng new my-app --routing
|
ng new my-app --routing
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
For an existing application, you have to manually add the `RouterModule` and defining a `<router-outlet>` within your application.
|
Para una aplicación existente, debes agregar manualmente el `RouterModule` y definir un` <router-outlet> `dentro de tu aplicación.
|
||||||
|
|
||||||
## Step 2: Create the app shell
|
## Paso 2: Crea el shell de la aplicación
|
||||||
|
|
||||||
Use the CLI to automatically create the app shell.
|
Usa la CLI para crear automáticamente el shell de la aplicación.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng generate app-shell
|
ng generate app-shell
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
* `client-project` takes the name of your client application.
|
* `client-project` toma el nombre de tu aplicación cliente.
|
||||||
|
|
||||||
After running this command you will notice that the `angular.json` configuration file has been updated to add two new targets, with a few other changes.
|
Después de ejecutar este comando, notará que el archivo de configuración `angular.json` se ha actualizado para agregar dos nuevos targets, con algunos otros cambios.
|
||||||
|
|
||||||
<code-example language="json">
|
<code-example language="json">
|
||||||
"server": {
|
"server": {
|
||||||
@ -53,20 +53,18 @@ After running this command you will notice that the `angular.json` configuration
|
|||||||
}
|
}
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
## Step 3: Verify the app is built with the shell content
|
## Paso 3: Verifica que la aplicación está construida con el contenido del shell
|
||||||
|
|
||||||
Use the CLI to build the `app-shell` target.
|
Usa la CLI para construir el `app-shell` target.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng run my-app:app-shell
|
ng run my-app:app-shell
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Or to use the production configuration.
|
O usa la configuración de producción.
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng run my-app:app-shell:production
|
ng run my-app:app-shell:production
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output.
|
Para verificar el resultado de la compilación, abre `dist/my-app/index.html`. Busca el texto por defecto `app-shell works!` para mostrar que la ruta del shell de la aplicación se ha renderizado como parte de la carpeta de distribución.
|
||||||
|
|
||||||
|
|
||||||
|
104
aio/content/guide/architecture-modules.en.md
Normal file
104
aio/content/guide/architecture-modules.en.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# Introduction to modules
|
||||||
|
|
||||||
|
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
||||||
|
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
||||||
|
|
||||||
|
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
||||||
|
|
||||||
|
While a small application might have only one NgModule, most apps have many more *feature modules*. The *root* NgModule for an app is so named because it can include child NgModules in a hierarchy of any depth.
|
||||||
|
|
||||||
|
## NgModule metadata
|
||||||
|
|
||||||
|
An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
|
||||||
|
|
||||||
|
* `declarations`: The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule.
|
||||||
|
|
||||||
|
* `exports`: The subset of declarations that should be visible and usable in the *component templates* of other NgModules.
|
||||||
|
|
||||||
|
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
||||||
|
|
||||||
|
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level, which is often preferred.)
|
||||||
|
|
||||||
|
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
||||||
|
|
||||||
|
Here's a simple root NgModule definition.
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/mini-app.ts" region="module" header="src/app/app.module.ts"></code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## NgModules and components
|
||||||
|
|
||||||
|
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
|
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
||||||
|
|
||||||
|
<div class="lightbox">
|
||||||
|
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
When you create a component, it's associated directly with a single view, called the *host view*. The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
**Note:** The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## NgModules and JavaScript modules
|
||||||
|
|
||||||
|
The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are *complementary* module systems that you can use together to write your apps.
|
||||||
|
|
||||||
|
In JavaScript each *file* is a module and all objects defined in the file belong to that module.
|
||||||
|
The module declares some objects to be public by marking them with the `export` key word.
|
||||||
|
Other JavaScript modules use *import statements* to access public objects from other modules.
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Angular libraries
|
||||||
|
|
||||||
|
<img src="generated/images/guide/architecture/library-module.png" alt="Component" class="left">
|
||||||
|
|
||||||
|
Angular loads as a collection of JavaScript modules. You can think of them as library modules. Each Angular library name begins with the `@angular` prefix. Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
For example, import Angular's `Component` decorator from the `@angular/core` library like this.
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/app.component.ts" region="import"></code-example>
|
||||||
|
|
||||||
|
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
||||||
|
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module"></code-example>
|
||||||
|
|
||||||
|
In the example of the simple root module above, the application module needs material from within
|
||||||
|
`BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports"></code-example>
|
||||||
|
|
||||||
|
In this way you're using the Angular and JavaScript module systems *together*. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
Learn more from the [NgModules](guide/ngmodules) guide.
|
||||||
|
|
||||||
|
</div>
|
@ -1,39 +1,39 @@
|
|||||||
# Introduction to modules
|
# Introducción a módulos
|
||||||
|
|
||||||
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
Las aplicaciones Angular son modulares y Angular tiene su propio sistema de modularidad llamado *NgModules*.
|
||||||
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
Los NgModules son contenedores para un bloque cohesivo de código dedicado a un dominio de aplicación, un flujo de trabajo o un conjunto de capacidades estrechamente relacionadas. Pueden contener componentes, proveedores de servicios y otros archivos de código cuyo alcance está definido por el NgModule que los contiene. Pueden importar la funcionalidad que se exporta desde otros NgModules y exportar la funcionalidad seleccionada para que la utilicen otros NgModules.
|
||||||
|
|
||||||
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
Cada aplicación Angular tiene al menos una clase NgModule, [el *módulo raíz*](guide/bootstrapping), que se llama convencionalmente `AppModule` y reside en un archivo llamado `app.module.ts`. Inicia tu aplicación *cargando* el NgModule raíz.
|
||||||
|
|
||||||
While a small application might have only one NgModule, most apps have many more *feature modules*. The *root* NgModule for an app is so named because it can include child NgModules in a hierarchy of any depth.
|
Si bien una aplicación pequeña puede tener sólo un NgModule, la mayoría de las aplicaciones tienen muchos más *módulos de funcionalidad*. El NgModule *raíz* para una aplicación se llama así porque puede incluir NgModules secundarios en una jerarquía de cualquier profundidad.
|
||||||
|
|
||||||
## NgModule metadata
|
## Metadatos de NgModule
|
||||||
|
|
||||||
An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
|
Un NgModule está definido por una clase decorada con `@NgModule()`. El decorador `@NgModule()` es una función que toma un único objeto de metadatos, cuyas propiedades describen el módulo. Las propiedades más importantes son las siguientes.
|
||||||
|
|
||||||
* `declarations`: The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule.
|
* `declarations`: Los [componentes](guide/architecture-components), *directivas*, y *pipes* que pertenecen a este NgModule.
|
||||||
|
|
||||||
* `exports`: The subset of declarations that should be visible and usable in the *component templates* of other NgModules.
|
* `exports`: El subconjunto de declaraciones que deberían ser visibles y utilizables en las *plantillas de componentes* de otros NgModules.
|
||||||
|
|
||||||
* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
|
* `imports`: Otros módulos cuyas clases exportadas son necesarias para las plantillas de componentes declaradas en *este* NgModule.
|
||||||
|
|
||||||
* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level.)
|
* `providers`: Creadores de [servicios](guide/architecture-services) que este NgModule aporta a la colección global de servicios; se vuelven accesibles en todas las partes de la aplicación. (También puedes especificar proveedores a nivel de componente, que a menudo es preferido).
|
||||||
|
|
||||||
* `bootstrap`: The main application view, called the *root component*, which hosts all other app views. Only the *root NgModule* should set the `bootstrap` property.
|
* `bootstrap`: La vista principal de la aplicación, llamado el *componente raíz*, que aloja todas las demás vistas de la aplicación. Sólo el *NgModule raíz* debe establecer la propiedad `bootstrap`.
|
||||||
|
|
||||||
Here's a simple root NgModule definition.
|
Aquí hay una definición simple del NgModule raíz.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/mini-app.ts" region="module" header="src/app/app.module.ts"></code-example>
|
<code-example path="architecture/src/app/mini-app.ts" region="module" header="src/app/app.module.ts"></code-example>
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
Aquí se incluye `AppComponent` en la lista de `exports` como ilustración; en realidad no es necesario en este ejemplo. Un NgModule raíz no tiene ninguna razón para *exportar* nada porque otros módulos no necesitan *importar* el NgModule raíz.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## NgModules and components
|
## NgModules y componentes
|
||||||
|
|
||||||
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
|
NgModules proporciona un *contexto de compilación* para sus componentes. Un NgModule raíz siempre tiene un componente raíz que se crea durante el arranque, pero cualquier NgModule puede incluir cualquier cantidad de componentes adicionales, que se pueden cargar a través del enrutador o crear a través de la plantilla. Los componentes que pertenecen a un NgModule comparten un contexto de compilación.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
|
||||||
@ -41,7 +41,7 @@ NgModules provide a *compilation context* for their components. A root NgModule
|
|||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
|
Juntos, un componente y su plantilla definen una *vista*. Un componente puede contener una *jerarquía de vista*, que te permiten definir áreas arbitrariamente complejas de la pantalla que se pueden crear, modificar y destruir como una unidad. Una jerarquía de vistas puede mezclar vistas definidas en componentes que pertenecen a diferentes NgModules. Este suele ser el caso, especialmente para las bibliotecas de interfaz de usuario.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
|
||||||
@ -49,56 +49,56 @@ A component and its template together define a *view*. A component can contain a
|
|||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
When you create a component, it's associated directly with a single view, called the *host view*. The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
|
Cuando creas un componente, se asocia directamente con una sola vista, llamada *vista host*. La vista host puede ser la raíz de una jerarquía de vistas, que puede contener *vistas incrustadas*, que a su vez son las vistas de host de otros componentes. Esos componentes pueden estar en el mismo NgModule o pueden importarse desde otros NgModules. Las vistas en el árbol se pueden anidar a cualquier profundidad.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
**Note:** The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and app data.
|
**Nota:** La estructura jerárquica de las vistas es un factor clave en la forma en que Angular detecta y responde a los cambios en el DOM y los datos de la aplicación.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## NgModules and JavaScript modules
|
## NgModules y módulos JavaScript
|
||||||
|
|
||||||
The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are *complementary* module systems that you can use together to write your apps.
|
El sistema NgModule es diferente y no está relacionado con el sistema de módulos JavaScript (ES2015) para administrar colecciones de objetos JavaScript. Estos son sistemas de módulos *complementarios* que puedes usar juntos para escribir tus aplicaciones.
|
||||||
|
|
||||||
In JavaScript each *file* is a module and all objects defined in the file belong to that module.
|
En JavaScript, cada *archivo* es un módulo y todos los objetos definidos en el archivo pertenecen a ese módulo.
|
||||||
The module declares some objects to be public by marking them with the `export` key word.
|
El módulo declara que algunos objetos son públicos marcándolos con la palabra clave `export`.
|
||||||
Other JavaScript modules use *import statements* to access public objects from other modules.
|
Otros módulos de JavaScript usan *declaraciones de importación* para acceder a objetos públicos de otros módulos.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
||||||
|
|
||||||
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
<a href="http://exploringjs.com/es6/ch_modules.html">Learn more about the JavaScript module system on the web.</a>
|
<a href="http://exploringjs.com/es6/ch_modules.html">Obtén más información sobre el sistema de módulos de JavaScript en la web.</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Angular libraries
|
## Bibliotecas Angular
|
||||||
|
|
||||||
<img src="generated/images/guide/architecture/library-module.png" alt="Component" class="left">
|
<img src="generated/images/guide/architecture/library-module.png" alt="Component" class="left">
|
||||||
|
|
||||||
Angular loads as a collection of JavaScript modules. You can think of them as library modules. Each Angular library name begins with the `@angular` prefix. Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
|
Angular se carga como una colección de módulos JavaScript. Puedes pensar en ellos como módulos de biblioteca. Cada nombre de biblioteca de Angular comienza con el prefijo `@angular`. Instálalos con el gestor de paquetes `npm` e importa partes de ellos con declaraciones `import` de JavaScript.
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
For example, import Angular's `Component` decorator from the `@angular/core` library like this.
|
Por ejemplo, importa el decorador `Component` de Angular de la biblioteca `@angular/core` como esta.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/app.component.ts" region="import"></code-example>
|
<code-example path="architecture/src/app/app.component.ts" region="import"></code-example>
|
||||||
|
|
||||||
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
También importa NgModules desde las *bibliotecas* Angular usando declaraciones de importación de JavaScript.
|
||||||
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
Por ejemplo, el siguiente código importa el NgModule `BrowserModule` de la biblioteca `platform-browser`.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module"></code-example>
|
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module"></code-example>
|
||||||
|
|
||||||
In the example of the simple root module above, the application module needs material from within
|
En el ejemplo del módulo raíz simple anterior, el módulo de la aplicación necesita material de
|
||||||
`BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
|
`BrowserModule`. Para acceder a ese material, agrégalo a los metadatos `imports` de `@NgModule` de esta manera.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports"></code-example>
|
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports"></code-example>
|
||||||
|
|
||||||
In this way you're using the Angular and JavaScript module systems *together*. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
|
De esta manera, estás utilizando los sistemas de módulos Angular y JavaScript *juntos*. Aunque es fácil confundir los dos sistemas, que comparten el vocabulario común de "importaciones" y "exportaciones", te familiarizarás con los diferentes contextos en los que se utilizan.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Learn more from the [NgModules](guide/ngmodules) guide.
|
Obtén más información en la guía [NgModules](guide/ngmodules).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user