Compare commits
80 Commits
Author | SHA1 | Date | |
---|---|---|---|
5db7b4c354 | |||
e08d02145e | |||
dae3a77c43 | |||
02e75df3e7 | |||
f752ab9367 | |||
9c875b30dc | |||
8fa78d10ab | |||
26988f0d62 | |||
6acf117386 | |||
8b731e374d | |||
5378f78e79 | |||
495c40e31c | |||
9963c5d8f7 | |||
13c4a7b1da | |||
70e85d226c | |||
dfb129dbfa | |||
1a1407aef6 | |||
da71f76a6a | |||
0c9b76e9e7 | |||
db34b23ab5 | |||
df0941554b | |||
5221df8e92 | |||
bc35c6a8ed | |||
23fc2b43ac | |||
c16995eb59 | |||
3487d5a13a | |||
1efc75cd72 | |||
c4190e3142 | |||
5d98834585 | |||
529ff73200 | |||
791205005c | |||
2d37e47e95 | |||
27c8066641 | |||
952fd8662c | |||
42be9047d8 | |||
52a0c6b36e | |||
8913aee527 | |||
7628c36f49 | |||
b417dd7b9c | |||
8cf16b4815 | |||
806aed63f4 | |||
eb34037cd7 | |||
ba0df5250f | |||
c4553bbed9 | |||
cc13b37446 | |||
166df5d2ca | |||
a5b474580c | |||
9f132d0d93 | |||
8dee378b3e | |||
0845d1148f | |||
7cfa57a5f7 | |||
f80c22002b | |||
7aa12412f3 | |||
072b707b38 | |||
223b80cb7d | |||
416403fc63 | |||
878e2f0deb | |||
4c30f5135b | |||
6791cd79af | |||
f50313f54d | |||
30433a0710 | |||
86ab9f92b4 | |||
42f9679376 | |||
bee10574d8 | |||
afce0f5038 | |||
bb19e61848 | |||
50e83e2566 | |||
d80c4890be | |||
4f8b716c13 | |||
cb85d69450 | |||
4a446878fa | |||
cb80f46c64 | |||
5199d55d45 | |||
bb11fd9058 | |||
771f7318f0 | |||
5d584b7728 | |||
1b5f6ee7a6 | |||
669e07580c | |||
965249d1da | |||
3a01856e7c |
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/test/e2e
|
build --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
|
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Temporary Settings for Ivy #
|
# Temporary Settings for Ivy #
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
3.2.0
|
3.5.1
|
||||||
# [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=8
|
build --local_cpu_resources=20
|
||||||
build --local_ram_resources=14336
|
build --local_ram_resources=32768
|
||||||
|
|
||||||
# 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=13500
|
build --local_ram_resources=120000
|
||||||
build --local_cpu_resources=4
|
build --local_cpu_resources=32
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -80,7 +80,7 @@ executors:
|
|||||||
|
|
||||||
windows-executor:
|
windows-executor:
|
||||||
working_directory: ~/ng
|
working_directory: ~/ng
|
||||||
resource_class: windows.medium
|
resource_class: windows.2xlarge
|
||||||
# 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
|
||||||
@ -273,6 +273,7 @@ jobs:
|
|||||||
- 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 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:
|
test:
|
||||||
@ -857,9 +858,16 @@ workflows:
|
|||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- build-ivy-npm-packages
|
- build-ivy-npm-packages
|
||||||
- legacy-unit-tests-saucelabs
|
- legacy-unit-tests-saucelabs
|
||||||
- components-repo-unit-tests:
|
# Temporarily disabled components-repo-unit-tests to update rules_nodejs to 2.0.0. Breaking changes in
|
||||||
requires:
|
# rules_nodejs create a dependency sandwich between angular/angular & angular/components that are very
|
||||||
- build-npm-packages
|
# 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:
|
- test_zonejs:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
@ -41,7 +41,8 @@ copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Install specific version of node.
|
# Install specific version of node.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
choco install nodejs --version 12.14.1 --no-progress
|
nvm install 12.14.1
|
||||||
|
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
|
||||||
|
27
.github/angular-robot.yml
vendored
27
.github/angular-robot.yml
vendored
@ -38,6 +38,7 @@ 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/*"
|
||||||
@ -47,8 +48,10 @@ 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/compiler-cli/src/ngtsc/sourcemaps/**"
|
||||||
- "packages/docs/**"
|
- "packages/docs/**"
|
||||||
- "packages/elements/schematics/**"
|
- "packages/elements/schematics/**"
|
||||||
- "packages/examples/**"
|
- "packages/examples/**"
|
||||||
@ -56,6 +59,8 @@ 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"
|
||||||
@ -137,24 +142,28 @@ 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:
|
||||||
-
|
-
|
||||||
- "type: bug/fix"
|
- "P0"
|
||||||
- "severity*"
|
|
||||||
- "freq*"
|
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: feature"
|
- "P1"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: refactor"
|
- "P2"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: RFC / Discussion / question"
|
- "P3"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: confusing"
|
- "P4"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "type: use-case"
|
- "P5"
|
||||||
|
- "comp: *"
|
||||||
|
-
|
||||||
|
- "feature"
|
||||||
|
- "comp: *"
|
||||||
|
-
|
||||||
|
- "discussion"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
|
|
||||||
# options for the triage PR plugin
|
# options for the triage PR plugin
|
||||||
|
@ -9,11 +9,11 @@ export const caretaker: CaretakerConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Merge Assistance Queue',
|
name: 'Merge Assistance Queue',
|
||||||
query: `is:pr is:open status:success label:"action: merge-assistance"`,
|
query: `is:pr is:open label:"action: merge-assistance"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Primary Triage Queue',
|
name: 'Initial Triage Queue',
|
||||||
query: `is:open is:issue no:milestone`,
|
query: `is:open no:milestone`,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ export const release: ReleaseConfig = {
|
|||||||
],
|
],
|
||||||
// TODO: Implement release package building here.
|
// TODO: Implement release package building here.
|
||||||
buildPackages: async () => [],
|
buildPackages: async () => [],
|
||||||
// TODO: This can be removed once there is a org-wide tool for changelog generation.
|
// TODO: This can be removed once there is an org-wide tool for changelog generation.
|
||||||
generateReleaseNotesForHead: async () => {
|
generateReleaseNotesForHead: async () => {
|
||||||
exec('yarn -s gulp changelog', {cwd: join(__dirname, '../')});
|
exec('yarn -s gulp changelog', {cwd: join(__dirname, '../')});
|
||||||
},
|
},
|
||||||
|
@ -326,6 +326,7 @@ 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/**',
|
||||||
@ -1115,6 +1116,7 @@ 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',
|
||||||
|
@ -47,3 +47,9 @@ 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"},
|
||||||
|
)
|
||||||
|
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,3 +1,39 @@
|
|||||||
|
<a name="10.1.6"></a>
|
||||||
|
## 10.1.6 (2020-10-14)
|
||||||
|
|
||||||
|
|
||||||
|
### 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>
|
<a name="10.1.4"></a>
|
||||||
## 10.1.4 (2020-09-30)
|
## 10.1.4 (2020-09-30)
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ Stack Overflow is a much better place to ask questions since:
|
|||||||
|
|
||||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||||
|
|
||||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
If you would like to chat about the question in real-time, you can reach out via [our Discord server][discord].
|
||||||
|
|
||||||
|
|
||||||
## <a name="issue"></a> Found a Bug?
|
## <a name="issue"></a> Found a Bug?
|
||||||
@ -107,7 +107,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git commit -a
|
git commit --all
|
||||||
```
|
```
|
||||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||||
|
|
||||||
@ -119,20 +119,55 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
|
|
||||||
11. In GitHub, send a pull request to `angular:master`.
|
11. In GitHub, send a pull request to `angular:master`.
|
||||||
|
|
||||||
If we ask for changes via code reviews then:
|
|
||||||
|
|
||||||
* Make the required updates.
|
#### Addressing review feedback
|
||||||
* 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
|
If we ask for changes via code reviews then:
|
||||||
git rebase master -i
|
|
||||||
git push -f
|
1. Make the required updates to the code.
|
||||||
```
|
|
||||||
|
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!
|
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
|
||||||
|
|
||||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||||
@ -349,7 +384,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
|
||||||
[gitter]: https://gitter.im/angular/angular
|
[discord]: https://discord.gg/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
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||||
|
[](https://discord.gg/angular)
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://www.npmjs.com/@angular/core)
|
[](https://www.npmjs.com/@angular/core)
|
||||||
|
|
||||||
|
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 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
|
sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.0/rules_nodejs-2.2.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 = "1.7.0")
|
check_rules_nodejs_version(minimum_version_string = "2.2.0")
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
@ -39,23 +39,18 @@ 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()
|
||||||
|
|
||||||
@ -68,11 +63,6 @@ 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")
|
||||||
|
|
||||||
@ -91,8 +81,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.2.0/configs/ubuntu16_04_clang/versions.bzl
|
# https://github.com/bazelbuild/bazel-toolchains/blob/3.5.1/configs/ubuntu16_04_clang/versions.bzl
|
||||||
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
|
base_container_digest = "sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1",
|
||||||
# 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
|
||||||
|
@ -119,7 +119,7 @@ The `/deep/` combinator also has the aliases `>>>`, and `::ng-deep`.
|
|||||||
|
|
||||||
Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation.
|
Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation.
|
||||||
Emulated is the default and most commonly used view encapsulation. For more information, see the
|
Emulated is the default and most commonly used view encapsulation. For more information, see the
|
||||||
[Controlling view encapsulation](guide/component-styles#view-encapsulation) section.
|
[View Encapsulation](guide/view-encapsulation) section.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -267,89 +267,3 @@ as explained in the [CLI wiki](https://github.com/angular/angular-cli/wiki/stori
|
|||||||
Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles.
|
Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{@a view-encapsulation}
|
|
||||||
|
|
||||||
## View encapsulation
|
|
||||||
|
|
||||||
As discussed earlier, component CSS styles are encapsulated into the component's view and don't
|
|
||||||
affect the rest of the application.
|
|
||||||
|
|
||||||
To control how this encapsulation happens on a *per
|
|
||||||
component* basis, you can set the *view encapsulation mode* in the component metadata.
|
|
||||||
Choose from the following modes:
|
|
||||||
|
|
||||||
* `ShadowDom` view encapsulation uses the browser's native shadow DOM implementation (see
|
|
||||||
[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
|
||||||
on the [MDN](https://developer.mozilla.org) site)
|
|
||||||
to attach a shadow DOM to the component's host element, and then puts the component
|
|
||||||
view inside that shadow DOM. The component's styles are included within the shadow DOM.
|
|
||||||
|
|
||||||
* `Native` view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - [learn about the changes](https://hayato.io/2016/shadowdomv1/).
|
|
||||||
|
|
||||||
* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing
|
|
||||||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
|
||||||
For details, see [Inspecting generated CSS](guide/component-styles#inspect-generated-css) below.
|
|
||||||
|
|
||||||
* `None` means that Angular does no view encapsulation.
|
|
||||||
Angular adds the CSS to the global styles.
|
|
||||||
The scoping rules, isolations, and protections discussed earlier don't apply.
|
|
||||||
This is essentially the same as pasting the component's styles into the HTML.
|
|
||||||
|
|
||||||
To set the components encapsulation mode, use the `encapsulation` property in the component metadata:
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" header="src/app/quest-summary.component.ts"></code-example>
|
|
||||||
|
|
||||||
`ShadowDom` view encapsulation only works on browsers that have native support
|
|
||||||
for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the
|
|
||||||
[Can I use](http://caniuse.com) site). The support is still limited,
|
|
||||||
which is why `Emulated` view encapsulation is the default mode and recommended
|
|
||||||
in most cases.
|
|
||||||
|
|
||||||
{@a inspect-generated-css}
|
|
||||||
|
|
||||||
## Inspecting generated CSS
|
|
||||||
|
|
||||||
When using emulated view encapsulation, Angular preprocesses
|
|
||||||
all component styles so that they approximate the standard shadow CSS scoping rules.
|
|
||||||
|
|
||||||
In the DOM of a running Angular application with emulated view
|
|
||||||
encapsulation enabled, each DOM element has some extra attributes
|
|
||||||
attached to it:
|
|
||||||
|
|
||||||
<code-example format="">
|
|
||||||
<hero-details _nghost-pmm-5>
|
|
||||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
|
||||||
<hero-team _ngcontent-pmm-5 _nghost-pmm-6>
|
|
||||||
<h3 _ngcontent-pmm-6>Team</h3>
|
|
||||||
</hero-team>
|
|
||||||
</hero-detail>
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
There are two kinds of generated attributes:
|
|
||||||
|
|
||||||
* An element that would be a shadow DOM host in native encapsulation has a
|
|
||||||
generated `_nghost` attribute. This is typically the case for component host elements.
|
|
||||||
* An element within a component's view has a `_ngcontent` attribute
|
|
||||||
that identifies to which host's emulated shadow DOM this element belongs.
|
|
||||||
|
|
||||||
The exact values of these attributes aren't important. They are automatically
|
|
||||||
generated and you never refer to them in application code. But they are targeted
|
|
||||||
by the generated component styles, which are in the `<head>` section of the DOM:
|
|
||||||
|
|
||||||
<code-example format="">
|
|
||||||
[_nghost-pmm-5] {
|
|
||||||
display: block;
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3[_ngcontent-pmm-6] {
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid #777;
|
|
||||||
}
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
These styles are post-processed so that each selector is augmented
|
|
||||||
with `_nghost` or `_ngcontent` attribute selectors.
|
|
||||||
These extra selectors enable the scoping rules described in this page.
|
|
||||||
|
@ -156,7 +156,7 @@ The library must be rebuilt on every change.
|
|||||||
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
||||||
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
||||||
|
|
||||||
## Use TypeScript path mapping for peer dependencies
|
### Use TypeScript path mapping for peer dependencies
|
||||||
|
|
||||||
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
||||||
This ensures that when modules ask for Angular, they all get the exact same module.
|
This ensures that when modules ask for Angular, they all get the exact same module.
|
||||||
|
@ -397,7 +397,7 @@ The following code example binds an observable of message strings
|
|||||||
## Caching HTTP requests
|
## Caching HTTP requests
|
||||||
|
|
||||||
To [communicate with backend services using HTTP](/guide/http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HTTPClient.get()` method to fetch data from a server.
|
To [communicate with backend services using HTTP](/guide/http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HTTPClient.get()` method to fetch data from a server.
|
||||||
The aynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response.
|
The asynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response.
|
||||||
|
|
||||||
As shown in the previous section, you can use the impure `AsyncPipe` to accept an observable as input and subscribe to the input automatically.
|
As shown in the previous section, you can use the impure `AsyncPipe` to accept an observable as input and subscribe to the input automatically.
|
||||||
You can also create an impure pipe to make and cache an HTTP request.
|
You can also create an impure pipe to make and cache an HTTP request.
|
||||||
|
@ -180,7 +180,7 @@ A form group tracks the status and changes for each of its controls, so if one o
|
|||||||
|
|
||||||
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.1.html" region="formgroup" header="src/app/profile-editor/profile-editor.component.html (template form group)"></code-example>
|
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.1.html" region="formgroup" header="src/app/profile-editor/profile-editor.component.html (template form group)"></code-example>
|
||||||
|
|
||||||
Note that just as a form group contains a group of controls, the *profile form* `FormGroup` is bound to the `form` element with the `FormGroup` directive, creating a communication layer between the model and the form containing the inputs. The `formControlName` input provided by the `FormControlName` directive binds each individual input to the form control defined in `FormGroup`. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value.
|
Note that just as a form group contains a group of controls, the *profileForm* `FormGroup` is bound to the `form` element with the `FormGroup` directive, creating a communication layer between the model and the form containing the inputs. The `formControlName` input provided by the `FormControlName` directive binds each individual input to the form control defined in `FormGroup`. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value.
|
||||||
|
|
||||||
**Save form data**
|
**Save form data**
|
||||||
|
|
||||||
|
@ -479,6 +479,15 @@ using the `downgradeComponent()` method. The result is an AngularJS
|
|||||||
<code-example path="upgrade-module/src/app/downgrade-static/app.module.ts" region="downgradecomponent" header="app.module.ts">
|
<code-example path="upgrade-module/src/app/downgrade-static/app.module.ts" region="downgradecomponent" header="app.module.ts">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
By default, Angular change detection will also run on the component for every
|
||||||
|
AngularJS `$digest` cycle. If you wish to only have change detection run when
|
||||||
|
the inputs change, you can set `propagateDigest` to `false` when calling
|
||||||
|
`downgradeComponent()`.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
Because `HeroDetailComponent` is an Angular component, you must also add it to the
|
Because `HeroDetailComponent` is an Angular component, you must also add it to the
|
||||||
`declarations` in the `AppModule`.
|
`declarations` in the `AppModule`.
|
||||||
|
|
||||||
|
83
aio/content/guide/view-encapsulation.md
Normal file
83
aio/content/guide/view-encapsulation.md
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# View encapsulation
|
||||||
|
|
||||||
|
In Angular, component CSS styles are encapsulated into the component's view and don't
|
||||||
|
affect the rest of the application.
|
||||||
|
|
||||||
|
To control how this encapsulation happens on a *per
|
||||||
|
component* basis, you can set the *view encapsulation mode* in the component metadata.
|
||||||
|
Choose from the following modes:
|
||||||
|
|
||||||
|
* `ShadowDom` view encapsulation uses the browser's native shadow DOM implementation (see
|
||||||
|
[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||||
|
on the [MDN](https://developer.mozilla.org) site)
|
||||||
|
to attach a shadow DOM to the component's host element, and then puts the component
|
||||||
|
view inside that shadow DOM. The component's styles are included within the shadow DOM.
|
||||||
|
|
||||||
|
* `Native` view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - [learn about the changes](https://hayato.io/2016/shadowdomv1/).
|
||||||
|
|
||||||
|
* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing
|
||||||
|
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||||
|
For details, see [Inspecting generated CSS](guide/view-encapsulation#inspect-generated-css) below.
|
||||||
|
|
||||||
|
* `None` means that Angular does no view encapsulation.
|
||||||
|
Angular adds the CSS to the global styles.
|
||||||
|
The scoping rules, isolations, and protections discussed earlier don't apply.
|
||||||
|
This is essentially the same as pasting the component's styles into the HTML.
|
||||||
|
|
||||||
|
To set the components encapsulation mode, use the `encapsulation` property in the component metadata:
|
||||||
|
|
||||||
|
<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" header="src/app/quest-summary.component.ts"></code-example>
|
||||||
|
|
||||||
|
`ShadowDom` view encapsulation only works on browsers that have native support
|
||||||
|
for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the
|
||||||
|
[Can I use](http://caniuse.com) site). The support is still limited,
|
||||||
|
which is why `Emulated` view encapsulation is the default mode and recommended
|
||||||
|
in most cases.
|
||||||
|
|
||||||
|
{@a inspect-generated-css}
|
||||||
|
|
||||||
|
## Inspecting generated CSS
|
||||||
|
|
||||||
|
When using emulated view encapsulation, Angular preprocesses
|
||||||
|
all component styles so that they approximate the standard shadow CSS scoping rules.
|
||||||
|
|
||||||
|
In the DOM of a running Angular application with emulated view
|
||||||
|
encapsulation enabled, each DOM element has some extra attributes
|
||||||
|
attached to it:
|
||||||
|
|
||||||
|
<code-example format="">
|
||||||
|
<hero-details _nghost-pmm-5>
|
||||||
|
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||||
|
<hero-team _ngcontent-pmm-5 _nghost-pmm-6>
|
||||||
|
<h3 _ngcontent-pmm-6>Team</h3>
|
||||||
|
</hero-team>
|
||||||
|
</hero-detail>
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
There are two kinds of generated attributes:
|
||||||
|
|
||||||
|
* An element that would be a shadow DOM host in native encapsulation has a
|
||||||
|
generated `_nghost` attribute. This is typically the case for component host elements.
|
||||||
|
* An element within a component's view has a `_ngcontent` attribute
|
||||||
|
that identifies to which host's emulated shadow DOM this element belongs.
|
||||||
|
|
||||||
|
The exact values of these attributes aren't important. They are automatically
|
||||||
|
generated and you never refer to them in application code. But they are targeted
|
||||||
|
by the generated component styles, which are in the `<head>` section of the DOM:
|
||||||
|
|
||||||
|
<code-example format="">
|
||||||
|
[_nghost-pmm-5] {
|
||||||
|
display: block;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3[_ngcontent-pmm-6] {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #777;
|
||||||
|
}
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
These styles are post-processed so that each selector is augmented
|
||||||
|
with `_nghost` or `_ngcontent` attribute selectors.
|
||||||
|
These extra selectors enable the scoping rules described in this page.
|
Binary file not shown.
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 56 KiB |
@ -458,8 +458,8 @@
|
|||||||
"name": "Sajeetharan Sinnathurai",
|
"name": "Sajeetharan Sinnathurai",
|
||||||
"picture": "sajee.jpg",
|
"picture": "sajee.jpg",
|
||||||
"twitter": "kokkisajee",
|
"twitter": "kokkisajee",
|
||||||
"website": "https://sajeetharan.herokuapp.com/",
|
"website": "https://sajeetharan.com/",
|
||||||
"bio": "Sajeetharan is a Developer, Top contributor on stackoverflow for #Angular, ng-SriLanka organizer. He makes use of his extensive knowledge over the past years to contribute to community to make the world a better place.",
|
"bio": "Sajeetharan is a Cloud Architect, Top contributor on stackoverflow for #Angular, ng-SriLanka organizer. He makes use of his extensive knowledge over the past years to contribute to community to make the world a better place.",
|
||||||
"groups": ["GDE"]
|
"groups": ["GDE"]
|
||||||
},
|
},
|
||||||
"lacolaco": {
|
"lacolaco": {
|
||||||
|
@ -46,7 +46,7 @@ Most Angular code can be written with just the latest JavaScript, using [types](
|
|||||||
|
|
||||||
<h3>You can sit with us!</h3>
|
<h3>You can sit with us!</h3>
|
||||||
|
|
||||||
We want to hear from you. [Report problems or submit suggestions for future docs.](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form")
|
We want to hear from you. [Report problems or submit suggestions for future docs](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form").
|
||||||
|
|
||||||
Contribute to Angular docs by creating
|
Contribute to Angular docs by creating
|
||||||
[pull requests](https://github.com/angular/angular/pulls "Angular Github pull requests")
|
[pull requests](https://github.com/angular/angular/pulls "Angular Github pull requests")
|
||||||
|
@ -116,6 +116,11 @@
|
|||||||
"title": "Component Lifecycle",
|
"title": "Component Lifecycle",
|
||||||
"tooltip": "Angular calls lifecycle hook methods on directives and components as it creates, changes, and destroys them."
|
"tooltip": "Angular calls lifecycle hook methods on directives and components as it creates, changes, and destroys them."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/view-encapsulation",
|
||||||
|
"title": "View Encapsulation",
|
||||||
|
"tooltip": "Describes how component CSS styles are encapsulated into a component's view."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/component-interaction",
|
"url": "guide/component-interaction",
|
||||||
"title": "Component Interaction",
|
"title": "Component Interaction",
|
||||||
@ -126,6 +131,11 @@
|
|||||||
"title": "Component Styles",
|
"title": "Component Styles",
|
||||||
"tooltip": "Add CSS styles that are specific to a component."
|
"tooltip": "Add CSS styles that are specific to a component."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/inputs-outputs",
|
||||||
|
"title": "Inputs and Outputs",
|
||||||
|
"tooltip": "Introductory guide to sharing data between parent and child directives or components."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/dynamic-component-loader",
|
"url": "guide/dynamic-component-loader",
|
||||||
"title": "Dynamic Components",
|
"title": "Dynamic Components",
|
||||||
@ -187,11 +197,6 @@
|
|||||||
"title": "Template reference variables",
|
"title": "Template reference variables",
|
||||||
"tooltip": "Introductory guide to referring to DOM elements within a template."
|
"tooltip": "Introductory guide to referring to DOM elements within a template."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"url": "guide/inputs-outputs",
|
|
||||||
"title": "Inputs and Outputs",
|
|
||||||
"tooltip": "Introductory guide to sharing data between parent and child directives or components."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "guide/template-expression-operators",
|
"url": "guide/template-expression-operators",
|
||||||
"title": "Template expression operators",
|
"title": "Template expression operators",
|
||||||
@ -1004,6 +1009,11 @@
|
|||||||
"title": "Stack Overflow",
|
"title": "Stack Overflow",
|
||||||
"tooltip": "Stack Overflow: where the community answers your technical Angular questions."
|
"tooltip": "Stack Overflow: where the community answers your technical Angular questions."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "https://discord.gg/angular",
|
||||||
|
"title": "Join Discord",
|
||||||
|
"tooltip": "Join the discussions at Angular Community Discord server."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "https://gitter.im/angular/angular",
|
"url": "https://gitter.im/angular/angular",
|
||||||
"title": "Gitter",
|
"title": "Gitter",
|
||||||
|
@ -128,7 +128,8 @@
|
|||||||
// The below paths are referenced in users projects generated by the CLI
|
// The below paths are referenced in users projects generated by the CLI
|
||||||
{"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"},
|
{"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"},
|
||||||
{"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"},
|
{"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"},
|
||||||
{"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"}
|
{"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"},
|
||||||
|
{"type": 301, "source": "/strict", "destination": "/guide/strict-mode"}
|
||||||
],
|
],
|
||||||
"rewrites": [
|
"rewrites": [
|
||||||
{
|
{
|
||||||
|
@ -148,6 +148,7 @@
|
|||||||
"!/styleguide/**",
|
"!/styleguide/**",
|
||||||
"!/testing",
|
"!/testing",
|
||||||
"!/testing/**",
|
"!/testing/**",
|
||||||
"!/config/**"
|
"!/config/**",
|
||||||
|
"!/strict"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
"tools-lint": "tslint --config \"tools/tslint.json\" --project \"tools/firebase-test-utils\"",
|
"tools-lint": "tslint --config \"tools/tslint.json\" --project \"tools/firebase-test-utils\"",
|
||||||
"tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js && yarn firebase-utils-test",
|
"tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js && yarn firebase-utils-test",
|
||||||
"preserve-and-sync": "yarn docs",
|
"preserve-and-sync": "yarn docs",
|
||||||
"serve-and-sync": "run-p \"start\" \"docs-watch --watch-only\"",
|
"serve-and-sync": "run-p \"docs-watch --watch-only\" \"start {@}\" --",
|
||||||
"boilerplate:add": "node ./tools/examples/example-boilerplate add",
|
"boilerplate:add": "node ./tools/examples/example-boilerplate add",
|
||||||
"boilerplate:add:viewengine": "yarn boilerplate:add --viewengine",
|
"boilerplate:add:viewengine": "yarn boilerplate:add --viewengine",
|
||||||
"boilerplate:remove": "node ./tools/examples/example-boilerplate remove",
|
"boilerplate:remove": "node ./tools/examples/example-boilerplate remove",
|
||||||
@ -153,7 +153,7 @@
|
|||||||
"lunr": "^2.1.0",
|
"lunr": "^2.1.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"protractor": "~5.4.4",
|
"protractor": "~5.4.4",
|
||||||
"puppeteer": "3.3.0",
|
"puppeteer": "5.1.0",
|
||||||
"rehype": "^6.0.0",
|
"rehype": "^6.0.0",
|
||||||
"rehype-slug": "^2.0.0",
|
"rehype-slug": "^2.0.0",
|
||||||
"remark": "^9.0.0",
|
"remark": "^9.0.0",
|
||||||
|
@ -782,7 +782,7 @@ describe('AppComponent', () => {
|
|||||||
it('should grab focus when the / key is pressed', () => {
|
it('should grab focus when the / key is pressed', () => {
|
||||||
const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance;
|
const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance;
|
||||||
spyOn(searchBox, 'focus');
|
spyOn(searchBox, 'focus');
|
||||||
window.document.dispatchEvent(new KeyboardEvent('keyup', { 'key': '/' }));
|
window.document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(searchBox.focus).toHaveBeenCalled();
|
expect(searchBox.focus).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -791,7 +791,7 @@ describe('AppComponent', () => {
|
|||||||
const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance;
|
const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance;
|
||||||
spyOn(searchBox, 'focus');
|
spyOn(searchBox, 'focus');
|
||||||
component.showSearchResults = true;
|
component.showSearchResults = true;
|
||||||
window.document.dispatchEvent(new KeyboardEvent('keyup', { 'key': 'Escape' }));
|
window.document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' }));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(searchBox.focus).toHaveBeenCalled();
|
expect(searchBox.focus).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -968,23 +968,23 @@ describe('AppComponent', () => {
|
|||||||
|
|
||||||
// Initially, `isTransitoning` is true.
|
// Initially, `isTransitoning` is true.
|
||||||
expect(component.isTransitioning).toBe(true);
|
expect(component.isTransitioning).toBe(true);
|
||||||
expect(toolbar.classes['transitioning']).toBe(true);
|
expect(toolbar.classes.transitioning).toBe(true);
|
||||||
|
|
||||||
triggerDocViewerEvent('docRendered');
|
triggerDocViewerEvent('docRendered');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.isTransitioning).toBe(false);
|
expect(component.isTransitioning).toBe(false);
|
||||||
expect(toolbar.classes['transitioning']).toBeFalsy();
|
expect(toolbar.classes.transitioning).toBeFalsy();
|
||||||
|
|
||||||
// While a document is being rendered, `isTransitoning` is set to true.
|
// While a document is being rendered, `isTransitoning` is set to true.
|
||||||
triggerDocViewerEvent('docReady');
|
triggerDocViewerEvent('docReady');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.isTransitioning).toBe(true);
|
expect(component.isTransitioning).toBe(true);
|
||||||
expect(toolbar.classes['transitioning']).toBe(true);
|
expect(toolbar.classes.transitioning).toBe(true);
|
||||||
|
|
||||||
triggerDocViewerEvent('docRendered');
|
triggerDocViewerEvent('docRendered');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.isTransitioning).toBe(false);
|
expect(component.isTransitioning).toBe(false);
|
||||||
expect(toolbar.classes['transitioning']).toBeFalsy();
|
expect(toolbar.classes.transitioning).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the sidenav state as soon as a new document is inserted (but not before)', () => {
|
it('should update the sidenav state as soon as a new document is inserted (but not before)', () => {
|
||||||
@ -1031,15 +1031,15 @@ describe('AppComponent', () => {
|
|||||||
|
|
||||||
navigateTo('guide/pipes');
|
navigateTo('guide/pipes');
|
||||||
expect(component.pageId).toEqual('guide-pipes');
|
expect(component.pageId).toEqual('guide-pipes');
|
||||||
expect(container.properties['id']).toEqual('guide-pipes');
|
expect(container.properties.id).toEqual('guide-pipes');
|
||||||
|
|
||||||
navigateTo('news');
|
navigateTo('news');
|
||||||
expect(component.pageId).toEqual('news');
|
expect(component.pageId).toEqual('news');
|
||||||
expect(container.properties['id']).toEqual('news');
|
expect(container.properties.id).toEqual('news');
|
||||||
|
|
||||||
navigateTo('');
|
navigateTo('');
|
||||||
expect(component.pageId).toEqual('home');
|
expect(component.pageId).toEqual('home');
|
||||||
expect(container.properties['id']).toEqual('home');
|
expect(container.properties.id).toEqual('home');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be affected by changes to the query', () => {
|
it('should not be affected by changes to the query', () => {
|
||||||
@ -1050,7 +1050,7 @@ describe('AppComponent', () => {
|
|||||||
navigateTo('guide/other?search=http');
|
navigateTo('guide/other?search=http');
|
||||||
|
|
||||||
expect(component.pageId).toEqual('guide-other');
|
expect(component.pageId).toEqual('guide-other');
|
||||||
expect(container.properties['id']).toEqual('guide-other');
|
expect(container.properties.id).toEqual('guide-other');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1125,7 +1125,7 @@ describe('AppComponent', () => {
|
|||||||
|
|
||||||
function checkHostClass(type: string, value: string) {
|
function checkHostClass(type: string, value: string) {
|
||||||
const host = fixture.debugElement;
|
const host = fixture.debugElement;
|
||||||
const classes: string = host.properties['className'];
|
const classes: string = host.properties.className;
|
||||||
const classArray = classes.split(' ').filter(c => c.indexOf(`${type}-`) === 0);
|
const classArray = classes.split(' ').filter(c => c.indexOf(`${type}-`) === 0);
|
||||||
expect(classArray.length).toBeLessThanOrEqual(1, `"${classes}" should have only one class matching ${type}-*`);
|
expect(classArray.length).toBeLessThanOrEqual(1, `"${classes}" should have only one class matching ${type}-*`);
|
||||||
expect(classArray).toEqual([`${type}-${value}`], `"${classes}" should contain ${type}-${value}`);
|
expect(classArray).toEqual([`${type}-${value}`], `"${classes}" should contain ${type}-${value}`);
|
||||||
@ -1311,42 +1311,42 @@ class TestHttpClient {
|
|||||||
|
|
||||||
// tslint:disable:quotemark
|
// tslint:disable:quotemark
|
||||||
navJson = {
|
navJson = {
|
||||||
"TopBar": [
|
TopBar: [
|
||||||
{
|
{
|
||||||
"url": "features",
|
url: 'features',
|
||||||
"title": "Features"
|
title: 'Features',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "no-title",
|
url: 'no-title',
|
||||||
"title": "No Title"
|
title: 'No Title',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"SideNav": [
|
SideNav: [
|
||||||
{
|
{
|
||||||
"title": "Core",
|
title: 'Core',
|
||||||
"tooltip": "Learn the core capabilities of Angular",
|
tooltip: 'Learn the core capabilities of Angular',
|
||||||
"children": [
|
children: [
|
||||||
{
|
{
|
||||||
"url": "guide/pipes",
|
url: 'guide/pipes',
|
||||||
"title": "Pipes",
|
title: 'Pipes',
|
||||||
"tooltip": "Pipes transform displayed values within a template."
|
tooltip: 'Pipes transform displayed values within a template.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/bags",
|
url: 'guide/bags',
|
||||||
"title": "Bags",
|
title: 'Bags',
|
||||||
"tooltip": "Pack your bags for a code adventure."
|
tooltip: 'Pack your bags for a code adventure.',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "api",
|
url: 'api',
|
||||||
"title": "API",
|
title: 'API',
|
||||||
"tooltip": "Details of the Angular classes and values."
|
tooltip: 'Details of the Angular classes and values.',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"docVersions": TestHttpClient.docVersions,
|
docVersions: TestHttpClient.docVersions,
|
||||||
|
|
||||||
"__versionInfo": TestHttpClient.versionInfo,
|
__versionInfo: TestHttpClient.versionInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
get(url: string) {
|
get(url: string) {
|
||||||
|
@ -147,7 +147,7 @@ export class AppComponent implements OnInit {
|
|||||||
// Compute the version picker list from the current version and the versions in the navigation map
|
// Compute the version picker list from the current version and the versions in the navigation map
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.navigationService.versionInfo,
|
this.navigationService.versionInfo,
|
||||||
this.navigationService.navigationViews.pipe(map(views => views['docVersions'])),
|
this.navigationService.navigationViews.pipe(map(views => views.docVersions)),
|
||||||
]).subscribe(([versionInfo, versions]) => {
|
]).subscribe(([versionInfo, versions]) => {
|
||||||
// TODO(pbd): consider whether we can lookup the stable and next versions from the internet
|
// TODO(pbd): consider whether we can lookup the stable and next versions from the internet
|
||||||
const computedVersions: NavigationNode[] = [
|
const computedVersions: NavigationNode[] = [
|
||||||
@ -167,10 +167,10 @@ export class AppComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.navigationService.navigationViews.subscribe(views => {
|
this.navigationService.navigationViews.subscribe(views => {
|
||||||
this.footerNodes = views['Footer'] || [];
|
this.footerNodes = views.Footer || [];
|
||||||
this.sideNavNodes = views['SideNav'] || [];
|
this.sideNavNodes = views.SideNav || [];
|
||||||
this.topMenuNodes = views['TopBar'] || [];
|
this.topMenuNodes = views.TopBar || [];
|
||||||
this.topMenuNarrowNodes = views['TopBarNarrow'] || this.topMenuNodes;
|
this.topMenuNarrowNodes = views.TopBarNarrow || this.topMenuNodes;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.navigationService.versionInfo.subscribe(vi => this.versionInfo = vi);
|
this.navigationService.versionInfo.subscribe(vi => this.versionInfo = vi);
|
||||||
|
@ -223,77 +223,77 @@ class TestApiService {
|
|||||||
// tslint:disable:quotemark
|
// tslint:disable:quotemark
|
||||||
const apiSections: ApiSection[] = [
|
const apiSections: ApiSection[] = [
|
||||||
{
|
{
|
||||||
"name": "common",
|
name: 'common',
|
||||||
"title": "common",
|
title: 'common',
|
||||||
"path": "api/common",
|
path: 'api/common',
|
||||||
"deprecated": false,
|
deprecated: false,
|
||||||
"items": [
|
items: [
|
||||||
{
|
{
|
||||||
"name": "class_1",
|
name: 'class_1',
|
||||||
"title": "Class 1",
|
title: 'Class 1',
|
||||||
"path": "api/common/class_1",
|
path: 'api/common/class_1',
|
||||||
"docType": "class",
|
docType: 'class',
|
||||||
"stability": "experimental",
|
stability: 'experimental',
|
||||||
"securityRisk": false,
|
securityRisk: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "class_2",
|
name: 'class_2',
|
||||||
"title": "Class 2",
|
title: 'Class 2',
|
||||||
"path": "api/common/class_2",
|
path: 'api/common/class_2',
|
||||||
"docType": "class",
|
docType: 'class',
|
||||||
"stability": "stable",
|
stability: 'stable',
|
||||||
"securityRisk": false,
|
securityRisk: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "directive_1",
|
name: 'directive_1',
|
||||||
"title": "Directive 1",
|
title: 'Directive 1',
|
||||||
"path": "api/common/directive_1",
|
path: 'api/common/directive_1',
|
||||||
"docType": "directive",
|
docType: 'directive',
|
||||||
"stability": "stable",
|
stability: 'stable',
|
||||||
"securityRisk": true,
|
securityRisk: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pipe_1",
|
name: 'pipe_1',
|
||||||
"title": "Pipe 1",
|
title: 'Pipe 1',
|
||||||
"path": "api/common/pipe_1",
|
path: 'api/common/pipe_1',
|
||||||
"docType": "pipe",
|
docType: 'pipe',
|
||||||
"stability": "stable",
|
stability: 'stable',
|
||||||
"securityRisk": true,
|
securityRisk: true,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "core",
|
name: 'core',
|
||||||
"title": "core",
|
title: 'core',
|
||||||
"path": "api/core",
|
path: 'api/core',
|
||||||
"deprecated": false,
|
deprecated: false,
|
||||||
"items": [
|
items: [
|
||||||
{
|
{
|
||||||
"name": "class_3",
|
name: 'class_3',
|
||||||
"title": "Class 3",
|
title: 'Class 3',
|
||||||
"path": "api/core/class_3",
|
path: 'api/core/class_3',
|
||||||
"docType": "class",
|
docType: 'class',
|
||||||
"stability": "experimental",
|
stability: 'experimental',
|
||||||
"securityRisk": false,
|
securityRisk: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "function_1",
|
name: 'function_1',
|
||||||
"title": "Function 1",
|
title: 'Function 1',
|
||||||
"path": "api/core/function 1",
|
path: 'api/core/function 1',
|
||||||
"docType": "function",
|
docType: 'function',
|
||||||
"stability": "deprecated",
|
stability: 'deprecated',
|
||||||
"securityRisk": true,
|
securityRisk: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "const_1",
|
name: 'const_1',
|
||||||
"title": "Const 1",
|
title: 'Const 1',
|
||||||
"path": "api/core/const_1",
|
path: 'api/core/const_1',
|
||||||
"docType": "const",
|
docType: 'const',
|
||||||
"stability": "stable",
|
stability: 'stable',
|
||||||
"securityRisk": false,
|
securityRisk: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function getApiSections() { return apiSections; }
|
function getApiSections() { return apiSections; }
|
||||||
|
@ -67,7 +67,7 @@ export class ApiService implements OnDestroy {
|
|||||||
* API sections is an array of Angular top modules and metadata about their API documents (items).
|
* API sections is an array of Angular top modules and metadata about their API documents (items).
|
||||||
* Updates `sections` observable
|
* Updates `sections` observable
|
||||||
*
|
*
|
||||||
* @param {string} [src] - Name of the api list JSON file
|
* @param [src] - Name of the api list JSON file
|
||||||
*/
|
*/
|
||||||
fetchSections(src?: string) {
|
fetchSections(src?: string) {
|
||||||
// TODO: get URL by configuration?
|
// TODO: get URL by configuration?
|
||||||
|
@ -20,13 +20,13 @@ export class PrettyPrinter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getPrettyPrintOne(): Promise<PrettyPrintOne> {
|
private getPrettyPrintOne(): Promise<PrettyPrintOne> {
|
||||||
const ppo = (window as any)['prettyPrintOne'];
|
const ppo = (window as any).prettyPrintOne;
|
||||||
return ppo ? Promise.resolve(ppo) :
|
return ppo ? Promise.resolve(ppo) :
|
||||||
// `prettyPrintOne` is not on `window`, which means `prettify.js` has not been loaded yet.
|
// `prettyPrintOne` is not on `window`, which means `prettify.js` has not been loaded yet.
|
||||||
// Import it; ad a side-effect it will add `prettyPrintOne` on `window`.
|
// Import it; ad a side-effect it will add `prettyPrintOne` on `window`.
|
||||||
import('assets/js/prettify.js' as any)
|
import('assets/js/prettify.js' as any)
|
||||||
.then(
|
.then(
|
||||||
() => (window as any)['prettyPrintOne'],
|
() => (window as any).prettyPrintOne,
|
||||||
err => {
|
err => {
|
||||||
const msg = `Cannot get prettify.js from server: ${err.message}`;
|
const msg = `Cannot get prettify.js from server: ${err.message}`;
|
||||||
this.logger.error(new Error(msg));
|
this.logger.error(new Error(msg));
|
||||||
@ -37,9 +37,9 @@ export class PrettyPrinter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Format code snippet as HTML
|
* Format code snippet as HTML
|
||||||
* @param {string} code - the code snippet to format; should already be HTML encoded
|
* @param code - the code snippet to format; should already be HTML encoded
|
||||||
* @param {string} [language] - The language of the code to render (could be javascript, html, typescript, etc)
|
* @param [language] - The language of the code to render (could be javascript, html, typescript, etc)
|
||||||
* @param {string|number} [linenums] - Whether to display line numbers:
|
* @param [linenums] - Whether to display line numbers:
|
||||||
* - false: don't display
|
* - false: don't display
|
||||||
* - true: do display
|
* - true: do display
|
||||||
* - number: do display but start at the given number
|
* - number: do display but start at the given number
|
||||||
|
@ -63,7 +63,7 @@ describe('ContributorListComponent', () => {
|
|||||||
it('should set the query to the "GDE" group when user selects "GDE"', () => {
|
it('should set the query to the "GDE" group when user selects "GDE"', () => {
|
||||||
component = getComponent();
|
component = getComponent();
|
||||||
component.selectGroup('GDE');
|
component.selectGroup('GDE');
|
||||||
expect(locationService.searchResult['group']).toBe('GDE');
|
expect(locationService.searchResult.group).toBe('GDE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the query to the first group when user selects unknown name', () => {
|
it('should set the query to the first group when user selects unknown name', () => {
|
||||||
@ -71,7 +71,7 @@ describe('ContributorListComponent', () => {
|
|||||||
component.selectGroup('GDE'); // a legit group that isn't the first
|
component.selectGroup('GDE'); // a legit group that isn't the first
|
||||||
|
|
||||||
component.selectGroup('foo'); // not a legit group name
|
component.selectGroup('foo'); // not a legit group name
|
||||||
expect(locationService.searchResult['group']).toBe('Angular');
|
expect(locationService.searchResult.group).toBe('Angular');
|
||||||
});
|
});
|
||||||
|
|
||||||
//// Test Helpers ////
|
//// Test Helpers ////
|
||||||
|
@ -29,7 +29,7 @@ export class ContributorListComponent implements OnInit {
|
|||||||
private locationService: LocationService) { }
|
private locationService: LocationService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
const groupName = this.locationService.search()['group'] || '';
|
const groupName = this.locationService.search().group || '';
|
||||||
// no need to unsubscribe because `contributors` completes
|
// no need to unsubscribe because `contributors` completes
|
||||||
this.contributorService.contributors
|
this.contributorService.contributors
|
||||||
.subscribe(grps => {
|
.subscribe(grps => {
|
||||||
|
@ -63,7 +63,7 @@ describe('ResourceListComponent', () => {
|
|||||||
it('should set the query to the "education" category when user selects "education"', () => {
|
it('should set the query to the "education" category when user selects "education"', () => {
|
||||||
component = getComponent();
|
component = getComponent();
|
||||||
component.selectCategory('education');
|
component.selectCategory('education');
|
||||||
expect(locationService.searchResult['category']).toBe('education');
|
expect(locationService.searchResult.category).toBe('education');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the query to the first category when user selects unknown name', () => {
|
it('should set the query to the first category when user selects unknown name', () => {
|
||||||
@ -71,7 +71,7 @@ describe('ResourceListComponent', () => {
|
|||||||
component.selectCategory('education'); // a legit group that isn't the first
|
component.selectCategory('education'); // a legit group that isn't the first
|
||||||
|
|
||||||
component.selectCategory('foo'); // not a legit group name
|
component.selectCategory('foo'); // not a legit group name
|
||||||
expect(locationService.searchResult['category']).toBe('development');
|
expect(locationService.searchResult.category).toBe('development');
|
||||||
});
|
});
|
||||||
|
|
||||||
//// Test Helpers ////
|
//// Test Helpers ////
|
||||||
|
@ -20,7 +20,7 @@ export class ResourceListComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
const category = this.locationService.search()['category'] || '';
|
const category = this.locationService.search().category || '';
|
||||||
// Not using async pipe because cats appear twice in template
|
// Not using async pipe because cats appear twice in template
|
||||||
// No need to unsubscribe because categories observable completes.
|
// No need to unsubscribe because categories observable completes.
|
||||||
this.resourceService.categories.subscribe(cats => {
|
this.resourceService.categories.subscribe(cats => {
|
||||||
|
@ -86,62 +86,61 @@ describe('ResourceService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function getTestResources() {
|
function getTestResources() {
|
||||||
// tslint:disable:quotemark
|
|
||||||
return {
|
return {
|
||||||
"Cat 3": {
|
'Cat 3': {
|
||||||
"order": 3,
|
order: 3,
|
||||||
"subCategories": {
|
subCategories: {
|
||||||
"Cat3 SubCat1": {
|
'Cat3 SubCat1': {
|
||||||
"order": 2,
|
order: 2,
|
||||||
"resources": {
|
resources: {
|
||||||
"Cat3 SubCat1 Res1": {
|
'Cat3 SubCat1 Res1': {
|
||||||
"desc": "Meetup in Barcelona, Spain. ",
|
desc: 'Meetup in Barcelona, Spain. ',
|
||||||
"title": "Angular Beers",
|
title: 'Angular Beers',
|
||||||
"url": "http://www.meetup.com/AngularJS-Beers/"
|
url: 'http://www.meetup.com/AngularJS-Beers/',
|
||||||
},
|
},
|
||||||
"Cat3 SubCat1 Res2": {
|
'Cat3 SubCat1 Res2': {
|
||||||
"desc": "Angular Camps in Barcelona, Spain.",
|
desc: 'Angular Camps in Barcelona, Spain.',
|
||||||
"title": "Angular Camp",
|
title: 'Angular Camp',
|
||||||
"url": "http://angularcamp.org/"
|
url: 'http://angularcamp.org/',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"Cat3 SubCat2": {
|
'Cat3 SubCat2': {
|
||||||
"order": 1,
|
order: 1,
|
||||||
"resources": {
|
resources: {
|
||||||
"Cat3 SubCat2 Res1": {
|
'Cat3 SubCat2 Res1': {
|
||||||
"desc": "A community index of components and libraries",
|
desc: 'A community index of components and libraries',
|
||||||
"title": "Catalog of Angular Components & Libraries",
|
title: 'Catalog of Angular Components & Libraries',
|
||||||
"url": "https://a/b/c"
|
url: 'https://a/b/c',
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Cat 1": {
|
|
||||||
"order": 1,
|
|
||||||
"subCategories": {
|
|
||||||
"Cat1 SubCat1": {
|
|
||||||
"order": 1,
|
|
||||||
"resources": {
|
|
||||||
"S S S": {
|
|
||||||
"desc": "SSS",
|
|
||||||
"title": "Sssss",
|
|
||||||
"url": "http://s/s/s"
|
|
||||||
},
|
},
|
||||||
"A A A": {
|
},
|
||||||
"desc": "AAA",
|
|
||||||
"title": "Aaaa",
|
|
||||||
"url": "http://a/a/a"
|
|
||||||
},
|
|
||||||
"Z Z Z": {
|
|
||||||
"desc": "ZZZ",
|
|
||||||
"title": "Zzzzz",
|
|
||||||
"url": "http://z/z/z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
'Cat 1': {
|
||||||
|
order: 1,
|
||||||
|
subCategories: {
|
||||||
|
'Cat1 SubCat1': {
|
||||||
|
order: 1,
|
||||||
|
resources: {
|
||||||
|
'S S S': {
|
||||||
|
desc: 'SSS',
|
||||||
|
title: 'Sssss',
|
||||||
|
url: 'http://s/s/s',
|
||||||
|
},
|
||||||
|
'A A A': {
|
||||||
|
desc: 'AAA',
|
||||||
|
title: 'Aaaa',
|
||||||
|
url: 'http://a/a/a',
|
||||||
|
},
|
||||||
|
'Z Z Z': {
|
||||||
|
desc: 'ZZZ',
|
||||||
|
title: 'Zzzzz',
|
||||||
|
url: 'http://z/z/z',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ describe('NavigationService', () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
navService.navigationViews.subscribe(views => view = views['sideNav']);
|
navService.navigationViews.subscribe(views => view = views.sideNav);
|
||||||
httpMock.expectOne({}).flush({sideNav});
|
httpMock.expectOne({}).flush({sideNav});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ describe('NavigationService', () => {
|
|||||||
{...v, ...{ tooltip: v.title + '.'}})
|
{...v, ...{ tooltip: v.title + '.'}})
|
||||||
);
|
);
|
||||||
|
|
||||||
navService.navigationViews.subscribe(views => actualDocVersions = views['docVersions']);
|
navService.navigationViews.subscribe(views => actualDocVersions = views.docVersions);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extract the docVersions', () => {
|
it('should extract the docVersions', () => {
|
||||||
|
@ -41,7 +41,7 @@ export class SearchBoxComponent implements AfterViewInit {
|
|||||||
* When we first show this search box we trigger a search if there is a search query in the URL
|
* When we first show this search box we trigger a search if there is a search query in the URL
|
||||||
*/
|
*/
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
const query = this.locationService.search()['search'];
|
const query = this.locationService.search().search;
|
||||||
if (query) {
|
if (query) {
|
||||||
this.query = this.decodeQuery(query);
|
this.query = this.decodeQuery(query);
|
||||||
this.doSearch();
|
this.doSearch();
|
||||||
|
@ -26,7 +26,7 @@ function createIndex(loadIndexFn: IndexLoader): lunr.Index {
|
|||||||
// The lunr typings are missing QueryLexer so we have to add them here manually.
|
// The lunr typings are missing QueryLexer so we have to add them here manually.
|
||||||
const queryLexer = (lunr as any as { QueryLexer: { termSeparator: RegExp } }).QueryLexer;
|
const queryLexer = (lunr as any as { QueryLexer: { termSeparator: RegExp } }).QueryLexer;
|
||||||
queryLexer.termSeparator = lunr.tokenizer.separator = /\s+/;
|
queryLexer.termSeparator = lunr.tokenizer.separator = /\s+/;
|
||||||
return lunr(/** @this */function() {
|
return lunr(function() {
|
||||||
this.ref('path');
|
this.ref('path');
|
||||||
this.field('topics', { boost: 15 });
|
this.field('topics', { boost: 15 });
|
||||||
this.field('titleWords', { boost: 10 });
|
this.field('titleWords', { boost: 10 });
|
||||||
@ -44,7 +44,7 @@ function handleMessage(message: { data: WebWorkerMessage }): void {
|
|||||||
const payload = message.data.payload;
|
const payload = message.data.payload;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'load-index':
|
case 'load-index':
|
||||||
makeRequest(SEARCH_TERMS_URL, function(searchInfo: PageInfo[]) {
|
makeRequest(SEARCH_TERMS_URL, (searchInfo: PageInfo[]) => {
|
||||||
index = createIndex(loadIndex(searchInfo));
|
index = createIndex(loadIndex(searchInfo));
|
||||||
postMessage({ type, id, payload: true });
|
postMessage({ type, id, payload: true });
|
||||||
});
|
});
|
||||||
@ -94,7 +94,7 @@ function queryIndex(query: string): PageInfo[] {
|
|||||||
results = index.search(query + ' ' + titleQuery);
|
results = index.search(query + ' ' + titleQuery);
|
||||||
}
|
}
|
||||||
// Map the hits into info about each page to be returned as results
|
// Map the hits into info about each page to be returned as results
|
||||||
return results.map(function(hit) { return pages[hit.ref]; });
|
return results.map(hit => pages[hit.ref]);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If the search query cannot be parsed the index throws an error
|
// If the search query cannot be parsed the index throws an error
|
||||||
|
@ -11,7 +11,7 @@ export class Deployment {
|
|||||||
* The deployment mode set from the environment provided at build time;
|
* The deployment mode set from the environment provided at build time;
|
||||||
* or overridden by the `mode` query parameter: e.g. `...?mode=archive`
|
* or overridden by the `mode` query parameter: e.g. `...?mode=archive`
|
||||||
*/
|
*/
|
||||||
mode: string = this.location.search()['mode'] || environment.mode;
|
mode: string = this.location.search().mode || environment.mode;
|
||||||
|
|
||||||
constructor(private location: LocationService) {}
|
constructor(private location: LocationService) {}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export class GaService {
|
|||||||
private previousUrl: string;
|
private previousUrl: string;
|
||||||
|
|
||||||
constructor(@Inject(WindowToken) private window: Window) {
|
constructor(@Inject(WindowToken) private window: Window) {
|
||||||
this.ga('create', environment['gaId'] , 'auto');
|
this.ga('create', environment.gaId , 'auto');
|
||||||
}
|
}
|
||||||
|
|
||||||
locationChanged(url: string) {
|
locationChanged(url: string) {
|
||||||
@ -34,7 +34,7 @@ export class GaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ga(...args: any[]) {
|
ga(...args: any[]) {
|
||||||
const gaFn = (this.window as any)['ga'];
|
const gaFn = (this.window as any).ga;
|
||||||
if (gaFn) {
|
if (gaFn) {
|
||||||
gaFn(...args);
|
gaFn(...args);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ export class LocationService {
|
|||||||
/**
|
/**
|
||||||
* Handle user's anchor click
|
* Handle user's anchor click
|
||||||
*
|
*
|
||||||
* @param anchor {HTMLAnchorElement} - the anchor element clicked
|
* @param anchor The anchor element clicked
|
||||||
* @param button Number of the mouse button held down. 0 means left or none
|
* @param button Number of the mouse button held down. 0 means left or none
|
||||||
* @param ctrlKey True if control key held down
|
* @param ctrlKey True if control key held down
|
||||||
* @param metaKey True if command or window key held down
|
* @param metaKey True if command or window key held down
|
||||||
|
@ -13,14 +13,13 @@ import { Logger } from 'app/shared/logger.service';
|
|||||||
* 1. Checks for available ServiceWorker updates once instantiated.
|
* 1. Checks for available ServiceWorker updates once instantiated.
|
||||||
* 2. Re-checks every 6 hours.
|
* 2. Re-checks every 6 hours.
|
||||||
* 3. Whenever an update is available, it activates the update.
|
* 3. Whenever an update is available, it activates the update.
|
||||||
*
|
|
||||||
* @property
|
|
||||||
* `updateActivated` {Observable<string>} - Emit the version hash whenever an update is activated.
|
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SwUpdatesService implements OnDestroy {
|
export class SwUpdatesService implements OnDestroy {
|
||||||
private checkInterval = 1000 * 60 * 60 * 6; // 6 hours
|
private checkInterval = 1000 * 60 * 60 * 6; // 6 hours
|
||||||
private onDestroy = new Subject<void>();
|
private onDestroy = new Subject<void>();
|
||||||
|
|
||||||
|
/** Emit the version hash whenever an update is activated. */
|
||||||
updateActivated: Observable<string>;
|
updateActivated: Observable<string>;
|
||||||
|
|
||||||
constructor(appRef: ApplicationRef, private logger: Logger, private swu: SwUpdate) {
|
constructor(appRef: ApplicationRef, private logger: Logger, private swu: SwUpdate) {
|
||||||
|
@ -38,7 +38,11 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
clear: left;
|
clear: left;
|
||||||
}
|
}
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
color: $blue;
|
||||||
|
@include font-size(14);
|
||||||
|
}
|
||||||
.show-all {
|
.show-all {
|
||||||
display: initial;
|
display: initial;
|
||||||
}
|
}
|
||||||
|
@ -105,9 +105,7 @@
|
|||||||
|
|
||||||
li {
|
li {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@include font-size(12);
|
padding: 7px 0 7px 12px;
|
||||||
@include line-height(16);
|
|
||||||
padding: 3px 0 3px 12px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
|
|
||||||
@ -129,6 +127,7 @@
|
|||||||
color: lighten($darkgray, 10);
|
color: lighten($darkgray, 10);
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
@include font-size(12);
|
@include font-size(12);
|
||||||
|
@include line-height(16);
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,11 +167,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:first-child:before {
|
&:first-child:before {
|
||||||
top: 13px;
|
top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child:before {
|
&:last-child:before {
|
||||||
bottom: calc(100% - 14px);
|
bottom: calc(100% - 15px);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.active):hover a:before {
|
&:not(.active):hover a:before {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ApiPage } from './api.po';
|
import { ApiPage } from './api.po';
|
||||||
|
|
||||||
describe('Api pages', function() {
|
describe('Api pages', () => {
|
||||||
it('should show direct subclasses of a class', () => {
|
it('should show direct subclasses of a class', () => {
|
||||||
const page = new ApiPage('api/forms/AbstractControlDirective');
|
const page = new ApiPage('api/forms/AbstractControlDirective');
|
||||||
expect(page.getDescendants('class', true)).toEqual(['ControlContainer', 'NgControl']);
|
expect(page.getDescendants('class', true)).toEqual(['ControlContainer', 'NgControl']);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { browser, by, element, ElementFinder } from 'protractor';
|
import { browser, by, element, ElementFinder } from 'protractor';
|
||||||
import { SitePage } from './app.po';
|
import { SitePage } from './app.po';
|
||||||
|
|
||||||
describe('site App', function() {
|
describe('site App', () => {
|
||||||
let page: SitePage;
|
let page: SitePage;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -3,7 +3,7 @@ import { SitePage } from './app.po';
|
|||||||
|
|
||||||
/* tslint:disable:max-line-length */
|
/* tslint:disable:max-line-length */
|
||||||
|
|
||||||
describe('onerror handler', function() {
|
describe('onerror handler', () => {
|
||||||
let page: SitePage;
|
let page: SitePage;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@ -186,7 +186,7 @@ createViewNodes@???`);
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function callOnError(message: string, url?: string, line?: number, column?: number, error?: Error) {
|
async function callOnError(message: string, url?: string, line?: number, column?: number, error?: Error) {
|
||||||
await browser.executeScript(function() {
|
await browser.executeScript(() => {
|
||||||
// reset the ga queue
|
// reset the ga queue
|
||||||
(window as any).ga.q.length = 0;
|
(window as any).ga.q.length = 0;
|
||||||
// post the error to the handler
|
// post the error to the handler
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
"lite-server": "^2.2.2",
|
"lite-server": "^2.2.2",
|
||||||
"lodash": "^4.16.2",
|
"lodash": "^4.16.2",
|
||||||
"protractor": "~7.0.0",
|
"protractor": "~7.0.0",
|
||||||
"puppeteer": "3.3.0",
|
"puppeteer": "5.1.0",
|
||||||
"rimraf": "^2.5.4",
|
"rimraf": "^2.5.4",
|
||||||
"rollup": "^1.1.0",
|
"rollup": "^1.1.0",
|
||||||
"rollup-plugin-commonjs": "^9.2.1",
|
"rollup-plugin-commonjs": "^9.2.1",
|
||||||
|
@ -4336,6 +4336,11 @@ dev-ip@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0"
|
resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0"
|
||||||
|
|
||||||
|
devtools-protocol@0.0.767361:
|
||||||
|
version "0.0.767361"
|
||||||
|
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b"
|
||||||
|
integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA==
|
||||||
|
|
||||||
dezalgo@^1.0.0:
|
dezalgo@^1.0.0:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
|
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
|
||||||
@ -7704,6 +7709,11 @@ mitt@^1.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d"
|
resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d"
|
||||||
integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==
|
integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==
|
||||||
|
|
||||||
|
mitt@^2.0.1:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
|
||||||
|
integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
|
||||||
|
|
||||||
mixin-deep@^1.2.0:
|
mixin-deep@^1.2.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a"
|
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a"
|
||||||
@ -8759,7 +8769,7 @@ pkg-dir@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up "^3.0.0"
|
find-up "^3.0.0"
|
||||||
|
|
||||||
pkg-dir@^4.1.0:
|
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||||
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
|
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
|
||||||
@ -9363,15 +9373,18 @@ punycode@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
puppeteer@3.3.0:
|
puppeteer@5.1.0:
|
||||||
version "3.3.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.3.0.tgz#95839af9fdc0aa4de7e5ee073a4c0adeb9e2d3d7"
|
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.1.0.tgz#e7bae2caa6e3a13a622755e4c27689d9812c38ca"
|
||||||
integrity sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw==
|
integrity sha512-IZBFG8XcA+oHxYo5rEpJI/HQignUis2XPijPoFpNxla2O+WufonGsUsSqrhRXgBKOME5zNfhRdUY2LvxAiKlhw==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
|
devtools-protocol "0.0.767361"
|
||||||
extract-zip "^2.0.0"
|
extract-zip "^2.0.0"
|
||||||
https-proxy-agent "^4.0.0"
|
https-proxy-agent "^4.0.0"
|
||||||
mime "^2.0.3"
|
mime "^2.0.3"
|
||||||
|
mitt "^2.0.1"
|
||||||
|
pkg-dir "^4.2.0"
|
||||||
progress "^2.0.1"
|
progress "^2.0.1"
|
||||||
proxy-from-env "^1.0.0"
|
proxy-from-env "^1.0.0"
|
||||||
rimraf "^3.0.2"
|
rimraf "^3.0.2"
|
||||||
|
@ -12,12 +12,16 @@
|
|||||||
{% for option in doc.members %}
|
{% for option in doc.members %}
|
||||||
<a id="{$ option.anchor $}"></a>
|
<a id="{$ option.anchor $}"></a>
|
||||||
<table class="is-full-width option-table">
|
<table class="is-full-width option-table">
|
||||||
<thead><tr><th>
|
<thead>
|
||||||
<div class="with-github-links">
|
<tr>
|
||||||
<h3>{$ option.name $}</h3>
|
<th>
|
||||||
{$ github.githubLinks(option, versionInfo) $}
|
<div class="with-github-links">
|
||||||
</div>
|
<h3>{$ option.name $}</h3>
|
||||||
</th></tr></thead>
|
{$ github.githubLinks(option, versionInfo) $}
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -26,8 +30,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code-example language="ts" hideCopy="true" class="no-box api-heading{% if option.deprecated %} deprecated-api-item{% endif %}">
|
<code-example language="ts" hideCopy="true"
|
||||||
{$ option.name $}: {$ option.type | escape $}
|
class="no-box api-heading{% if option.deprecated %} deprecated-api-item{% endif %}">
|
||||||
|
{$ option.name $}{%- if option.isOptional %}?{% endif -%}: {$ option.type | escape $}
|
||||||
</code-example>
|
</code-example>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<tr class="option">
|
<tr class="option">
|
||||||
<td>
|
<td>
|
||||||
<a class="code-anchor" href="{$ doc.path $}#{$ option.anchor | urlencode $}">
|
<a class="code-anchor" href="{$ doc.path $}#{$ option.anchor | urlencode $}">
|
||||||
<code>{$ option.name $}</code>
|
<code>{$ option.name $}{%- if option.isOptional %}?{% endif -%}</code>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{$ option.shortDescription | marked $}</td>
|
<td>{$ option.shortDescription | marked $}</td>
|
||||||
|
@ -132,11 +132,11 @@
|
|||||||
<summary>
|
<summary>
|
||||||
<div class="icon-action-header">
|
<div class="icon-action-header">
|
||||||
<h4 class="no-anchor">{$ method.overloads.length $} overloads...</h4>
|
<h4 class="no-anchor">{$ method.overloads.length $} overloads...</h4>
|
||||||
<a>
|
<span class="actions">
|
||||||
<span class="show-all">Show All</span>
|
<span class="show-all">Show All</span>
|
||||||
<span class="collapse-all">Hide All</span>
|
<span class="collapse-all">Hide All</span>
|
||||||
<i class="material-icons expand">expand_more</i>
|
<i class="material-icons expand">expand_more</i>
|
||||||
</a>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="detail-contents">
|
<div class="detail-contents">
|
||||||
|
120
aio/tslint.json
120
aio/tslint.json
@ -11,32 +11,16 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"array-type": false,
|
"array-type": false,
|
||||||
"arrow-parens": false,
|
|
||||||
"arrow-return-shorthand": true,
|
"arrow-return-shorthand": true,
|
||||||
"ban": [
|
"ban": [
|
||||||
true,
|
true,
|
||||||
{"name": "fdescribe", "message": "Don't keep jasmine focus methods."},
|
{"name": "fdescribe", "message": "Don't keep jasmine focus methods."},
|
||||||
{"name": "fit", "message": "Don't keep jasmine focus methods."}
|
{"name": "fit", "message": "Don't keep jasmine focus methods."}
|
||||||
],
|
],
|
||||||
"component-class-suffix": true,
|
|
||||||
"component-selector": [
|
|
||||||
true,
|
|
||||||
"element",
|
|
||||||
"aio",
|
|
||||||
"kebab-case"
|
|
||||||
],
|
|
||||||
"contextual-lifecycle": true,
|
|
||||||
"curly": true,
|
"curly": true,
|
||||||
"deprecation": {
|
"deprecation": {
|
||||||
"severity": "warn"
|
"severity": "warning"
|
||||||
},
|
},
|
||||||
"directive-class-suffix": true,
|
|
||||||
"directive-selector": [
|
|
||||||
true,
|
|
||||||
"attribute",
|
|
||||||
"aio",
|
|
||||||
"camelCase"
|
|
||||||
],
|
|
||||||
"eofline": true,
|
"eofline": true,
|
||||||
"import-blacklist": [
|
"import-blacklist": [
|
||||||
true,
|
true,
|
||||||
@ -48,13 +32,11 @@
|
|||||||
"spaces"
|
"spaces"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"interface-name": false,
|
|
||||||
"max-classes-per-file": false,
|
"max-classes-per-file": false,
|
||||||
"max-line-length": [
|
"max-line-length": [
|
||||||
true,
|
true,
|
||||||
140
|
140
|
||||||
],
|
],
|
||||||
"member-access": false,
|
|
||||||
"member-ordering": [
|
"member-ordering": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
@ -66,8 +48,8 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"no-conflicting-lifecycle": true,
|
// TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 114)
|
||||||
"no-consecutive-blank-lines": false,
|
// "no-any": true,
|
||||||
"no-console": [
|
"no-console": [
|
||||||
true,
|
true,
|
||||||
"debug",
|
"debug",
|
||||||
@ -77,24 +59,20 @@
|
|||||||
"trace"
|
"trace"
|
||||||
],
|
],
|
||||||
"no-empty": false,
|
"no-empty": false,
|
||||||
"no-host-metadata-property": true,
|
|
||||||
"no-inferrable-types": [
|
"no-inferrable-types": [
|
||||||
true,
|
true,
|
||||||
"ignore-params"
|
"ignore-params"
|
||||||
],
|
],
|
||||||
"no-input-rename": true,
|
// TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 59)
|
||||||
"no-inputs-metadata-property": true,
|
// "no-non-null-assertion": true,
|
||||||
"no-output-native": true,
|
"no-redundant-jsdoc": true,
|
||||||
"no-output-on-prefix": true,
|
// TODO(gkalpak): Fix the code and remove this to align with CLI.
|
||||||
"no-output-rename": true,
|
|
||||||
"no-outputs-metadata-property": true,
|
|
||||||
"no-string-literal": false,
|
|
||||||
"no-switch-case-fall-through": true,
|
"no-switch-case-fall-through": true,
|
||||||
"no-var-requires": false,
|
"no-var-requires": false,
|
||||||
"object-literal-key-quotes": false,
|
"object-literal-key-quotes": [
|
||||||
"object-literal-sort-keys": false,
|
true,
|
||||||
"only-arrow-functions": false,
|
"as-needed"
|
||||||
"ordered-imports": false,
|
],
|
||||||
"quotemark": [
|
"quotemark": [
|
||||||
true,
|
true,
|
||||||
"single"
|
"single"
|
||||||
@ -113,9 +91,11 @@
|
|||||||
"named": "never"
|
"named": "never"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"template-banana-in-box": true,
|
// TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 243)
|
||||||
"template-no-negated-async": true,
|
// "typedef": [
|
||||||
"trailing-comma": false,
|
// true,
|
||||||
|
// "call-signature"
|
||||||
|
// ],
|
||||||
"typedef-whitespace": {
|
"typedef-whitespace": {
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
@ -134,26 +114,15 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"use-lifecycle-interface": true,
|
"variable-name": {
|
||||||
"use-pipe-transform-interface": true,
|
"options": [
|
||||||
"variable-name": [
|
"ban-keywords",
|
||||||
true,
|
"check-format",
|
||||||
"allow-leading-underscore",
|
"allow-leading-underscore",
|
||||||
"allow-pascal-case",
|
"allow-pascal-case",
|
||||||
"ban-keywords",
|
"require-const-for-all-caps"
|
||||||
"check-format",
|
]
|
||||||
"require-const-for-all-caps"
|
},
|
||||||
],
|
|
||||||
"template-accessibility-alt-text": true,
|
|
||||||
"template-accessibility-elements-content": true,
|
|
||||||
"template-accessibility-label-for": true,
|
|
||||||
"template-accessibility-tabindex-no-positive": true,
|
|
||||||
"template-accessibility-table-scope": true,
|
|
||||||
"template-accessibility-valid-aria": true,
|
|
||||||
"template-click-events-have-key-events": true,
|
|
||||||
"template-mouse-events-have-key-events": true,
|
|
||||||
"template-no-autofocus": true,
|
|
||||||
"template-no-distracting-elements": true,
|
|
||||||
"whitespace": {
|
"whitespace": {
|
||||||
"options": [
|
"options": [
|
||||||
"check-branch",
|
"check-branch",
|
||||||
@ -163,6 +132,43 @@
|
|||||||
"check-type",
|
"check-type",
|
||||||
"check-typecast"
|
"check-typecast"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"contextual-lifecycle": true,
|
||||||
|
"directive-class-suffix": true,
|
||||||
|
"no-conflicting-lifecycle": true,
|
||||||
|
"no-host-metadata-property": true,
|
||||||
|
"no-input-rename": true,
|
||||||
|
"no-inputs-metadata-property": true,
|
||||||
|
"no-output-native": true,
|
||||||
|
"no-output-on-prefix": true,
|
||||||
|
"no-output-rename": true,
|
||||||
|
"no-outputs-metadata-property": true,
|
||||||
|
"template-accessibility-alt-text": true,
|
||||||
|
"template-accessibility-elements-content": true,
|
||||||
|
"template-accessibility-label-for": true,
|
||||||
|
"template-accessibility-tabindex-no-positive": true,
|
||||||
|
"template-accessibility-table-scope": true,
|
||||||
|
"template-accessibility-valid-aria": true,
|
||||||
|
"template-banana-in-box": true,
|
||||||
|
"template-click-events-have-key-events": true,
|
||||||
|
"template-mouse-events-have-key-events": true,
|
||||||
|
"template-no-autofocus": true,
|
||||||
|
"template-no-distracting-elements": true,
|
||||||
|
"template-no-negated-async": true,
|
||||||
|
"use-lifecycle-interface": true,
|
||||||
|
"use-pipe-transform-interface": true,
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"aio",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"aio",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4509,6 +4509,11 @@ detect-node@^2.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||||
|
|
||||||
|
devtools-protocol@0.0.767361:
|
||||||
|
version "0.0.767361"
|
||||||
|
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b"
|
||||||
|
integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA==
|
||||||
|
|
||||||
dezalgo@^1.0.0:
|
dezalgo@^1.0.0:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
|
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
|
||||||
@ -8926,6 +8931,11 @@ mississippi@^3.0.0:
|
|||||||
stream-each "^1.1.0"
|
stream-each "^1.1.0"
|
||||||
through2 "^2.0.0"
|
through2 "^2.0.0"
|
||||||
|
|
||||||
|
mitt@^2.0.1:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
|
||||||
|
integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
|
||||||
|
|
||||||
mixin-deep@^1.2.0:
|
mixin-deep@^1.2.0:
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
|
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
|
||||||
@ -10040,7 +10050,7 @@ pkg-dir@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up "^3.0.0"
|
find-up "^3.0.0"
|
||||||
|
|
||||||
pkg-dir@^4.1.0:
|
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||||
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
|
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
|
||||||
@ -10695,15 +10705,18 @@ punycode@^2.1.0, punycode@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
puppeteer@3.3.0:
|
puppeteer@5.1.0:
|
||||||
version "3.3.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.3.0.tgz#95839af9fdc0aa4de7e5ee073a4c0adeb9e2d3d7"
|
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.1.0.tgz#e7bae2caa6e3a13a622755e4c27689d9812c38ca"
|
||||||
integrity sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw==
|
integrity sha512-IZBFG8XcA+oHxYo5rEpJI/HQignUis2XPijPoFpNxla2O+WufonGsUsSqrhRXgBKOME5zNfhRdUY2LvxAiKlhw==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
|
devtools-protocol "0.0.767361"
|
||||||
extract-zip "^2.0.0"
|
extract-zip "^2.0.0"
|
||||||
https-proxy-agent "^4.0.0"
|
https-proxy-agent "^4.0.0"
|
||||||
mime "^2.0.3"
|
mime "^2.0.3"
|
||||||
|
mitt "^2.0.1"
|
||||||
|
pkg-dir "^4.2.0"
|
||||||
progress "^2.0.1"
|
progress "^2.0.1"
|
||||||
proxy-from-env "^1.0.0"
|
proxy-from-env "^1.0.0"
|
||||||
rimraf "^3.0.2"
|
rimraf "^3.0.2"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm")
|
load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm")
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "cli",
|
name = "cli",
|
||||||
@ -11,6 +11,7 @@ ts_library(
|
|||||||
"//dev-infra/caretaker",
|
"//dev-infra/caretaker",
|
||||||
"//dev-infra/commit-message",
|
"//dev-infra/commit-message",
|
||||||
"//dev-infra/format",
|
"//dev-infra/format",
|
||||||
|
"//dev-infra/ngbot",
|
||||||
"//dev-infra/pr",
|
"//dev-infra/pr",
|
||||||
"//dev-infra/pullapprove",
|
"//dev-infra/pullapprove",
|
||||||
"//dev-infra/release",
|
"//dev-infra/release",
|
||||||
@ -48,7 +49,7 @@ pkg_npm(
|
|||||||
# substitutions to replace these in the published version of dev-infra.
|
# substitutions to replace these in the published version of dev-infra.
|
||||||
"//dev-infra/": "@npm_angular_dev_infra_private//",
|
"//dev-infra/": "@npm_angular_dev_infra_private//",
|
||||||
"//packages/benchpress": "@npm//@angular/benchpress",
|
"//packages/benchpress": "@npm//@angular/benchpress",
|
||||||
"//packages/bazel/": "@npm_angular_bazel//",
|
"//packages/bazel": "@npm//@angular/bazel",
|
||||||
"//packages/zone.js/bundles:zone.umd.js": "@npm//:node_modules/zone.js/dist/zone.js",
|
"//packages/zone.js/bundles:zone.umd.js": "@npm//:node_modules/zone.js/dist/zone.js",
|
||||||
"//packages/core": "@npm//@angular/core",
|
"//packages/core": "@npm//@angular/core",
|
||||||
"//packages/platform-browser": "@npm//@angular/platform-browser",
|
"//packages/platform-browser": "@npm//@angular/platform-browser",
|
||||||
@ -56,7 +57,7 @@ pkg_npm(
|
|||||||
# This substitution is particularly verbose because we need to make sure
|
# This substitution is particularly verbose because we need to make sure
|
||||||
# that only things available via Angular Bazel are imported from
|
# that only things available via Angular Bazel are imported from
|
||||||
# tools/defaults.bzl.
|
# tools/defaults.bzl.
|
||||||
"load\(\"//tools:defaults.bzl\", \"ng_module\"\)": "load(\"@npm_angular_bazel//:index.bzl\", \"ng_module\")",
|
"load\(\"//tools:defaults.bzl\", \"ng_module\"\)": "load(\"@npm//@angular/bazel:index.bzl\", \"ng_module\")",
|
||||||
},
|
},
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
load("@npm//@bazel/protractor:index.bzl", "protractor_web_test_suite")
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Macro that can be used to define a benchmark test. This differentiates from
|
Macro that can be used to define a benchmark test. This differentiates from
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
load("//dev-infra/benchmark/ng_rollup_bundle:ng_rollup_bundle.bzl", "ng_rollup_bundle")
|
load("//dev-infra/benchmark/ng_rollup_bundle:ng_rollup_bundle.bzl", "ng_rollup_bundle")
|
||||||
load("//tools:defaults.bzl", "ng_module")
|
load("//tools:defaults.bzl", "ng_module")
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_devserver", "ts_library")
|
||||||
load(":benchmark_test.bzl", "benchmark_test")
|
load(":benchmark_test.bzl", "benchmark_test")
|
||||||
|
|
||||||
def copy_default_file(origin, destination):
|
def copy_default_file(origin, destination):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "driver-utilities",
|
name = "driver-utilities",
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
# found in the LICENSE file at https://angular.io/license
|
# found in the LICENSE file at https://angular.io/license
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
|
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
|
||||||
load("@npm_bazel_terser//:index.bzl", "terser_minified")
|
load("@npm//@bazel/terser:index.bzl", "terser_minified")
|
||||||
load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
|
load("@npm//@bazel/rollup:index.bzl", "rollup_bundle")
|
||||||
load("//dev-infra/bazel:expand_template.bzl", "expand_template")
|
load("//dev-infra/bazel:expand_template.bzl", "expand_template")
|
||||||
|
|
||||||
def ng_rollup_bundle(
|
def ng_rollup_bundle(
|
||||||
|
@ -12,47 +12,47 @@ def define_chromium_repositories():
|
|||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromium_amd64",
|
name = "org_chromium_chromium_amd64",
|
||||||
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
||||||
sha256 = "2cfd74ee58c79d8b7aada05c899a930967e2fd8bb0186582cde02c7340863f64",
|
sha256 = "0e303931d9c3e065a160f5d31f1178c647f0748fb0b58b1945b84b04fe1c1165",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/756066/chrome-linux.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/768968/chrome-linux.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromium_macos",
|
name = "org_chromium_chromium_macos",
|
||||||
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
||||||
sha256 = "b841ec5ad03b08422d97593fc719f1c5b038703388ad65e6cd8cc8272d58958c",
|
sha256 = "39118c96db1b3fdb0129f434912a329c5ca07d3a1c6c6cda673d3383d83e2f9a",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/756053/chrome-mac.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/768968/chrome-mac.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromium_windows",
|
name = "org_chromium_chromium_windows",
|
||||||
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
licenses = ["notice"], # BSD 3-clause (maybe more?)
|
||||||
sha256 = "4683d7ac88dfec4b98d1da3012ecc8e42cc8c1a560a7b95589ad4cc96bf90fcb",
|
sha256 = "3429746fa80c917c6f4d5d96aba4e58894b905a2b8392e43ddb470c5ba612d60",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/756065/chrome-win.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/768975/chrome-win.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromedriver_amd64",
|
name = "org_chromium_chromedriver_amd64",
|
||||||
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
||||||
sha256 = "95dded16000b82e31445361da7d251ed707e027a4b61e9a3ec5fbd1cc2f62bb1",
|
sha256 = "f6b9852031d185739a2c1816508fe8158eb92782d13e831b8345957ef2506fe8",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/756066/chromedriver_linux64.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/768968/chromedriver_linux64.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromedriver_macos",
|
name = "org_chromium_chromedriver_macos",
|
||||||
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
||||||
sha256 = "17260e9b2222b0c905a1861285210192baef830f4281778903e7cebb8db683cc",
|
sha256 = "aa0124085146556d5d32ad172670e5dcef79b7429380112ad02898047ba7a8b7",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/756053/chromedriver_mac64.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/768968/chromedriver_mac64.zip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
platform_http_file(
|
platform_http_file(
|
||||||
name = "org_chromium_chromedriver_windows",
|
name = "org_chromium_chromedriver_windows",
|
||||||
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
|
||||||
sha256 = "de1423b2d69f96e451e902d686e8d471610d786c345a8de59dd1a5a436e45fc2",
|
sha256 = "c4b04fd263e757d3aa99c596832f2c414f9f00e80d2769590e2b9044072b140e",
|
||||||
# 83.0.4103
|
# 84.0.4147
|
||||||
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/756065/chromedriver_win32.zip"],
|
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/768975/chromedriver_win32.zip"],
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "caretaker",
|
name = "caretaker",
|
||||||
@ -8,6 +8,7 @@ ts_library(
|
|||||||
module_name = "@angular/dev-infra-private/caretaker",
|
module_name = "@angular/dev-infra-private/caretaker",
|
||||||
visibility = ["//dev-infra:__subpackages__"],
|
visibility = ["//dev-infra:__subpackages__"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//dev-infra/release/versioning",
|
||||||
"//dev-infra/utils",
|
"//dev-infra/utils",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/node-fetch",
|
"@npm//@types/node-fetch",
|
||||||
|
@ -7,52 +7,55 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
import {fetchActiveReleaseTrains} from '../../release/versioning/index';
|
||||||
|
|
||||||
import {bold, green, info, red} from '../../utils/console';
|
import {bold, debug, info} from '../../utils/console';
|
||||||
import {GitClient} from '../../utils/git';
|
import {GitClient} from '../../utils/git';
|
||||||
|
|
||||||
|
|
||||||
/** The results of checking the status of CI. */
|
/** The results of checking the status of CI. */
|
||||||
interface StatusCheckResult {
|
interface StatusCheckResult {
|
||||||
status: 'success'|'failed'|'canceled'|'infrastructure_fail'|'timedout'|'failed'|'no_tests';
|
status: 'success'|'failed';
|
||||||
timestamp: Date;
|
|
||||||
buildUrl: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve and log status of CI for the project. */
|
/** Retrieve and log status of CI for the project. */
|
||||||
export async function printCiStatus(git: GitClient) {
|
export async function printCiStatus(git: GitClient) {
|
||||||
|
const releaseTrains = await fetchActiveReleaseTrains({api: git.github, ...git.remoteConfig});
|
||||||
|
|
||||||
info.group(bold(`CI`));
|
info.group(bold(`CI`));
|
||||||
// TODO(josephperrott): Expand list of branches checked to all active branches.
|
for (const [trainName, train] of Object.entries(releaseTrains)) {
|
||||||
await printStatus(git, 'master');
|
if (train === null) {
|
||||||
|
debug(`No active release train for ${trainName}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const status = await getStatusOfBranch(git, train.branchName);
|
||||||
|
await printStatus(`${trainName.padEnd(6)} (${train.branchName})`, status);
|
||||||
|
}
|
||||||
info.groupEnd();
|
info.groupEnd();
|
||||||
info();
|
info();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Log the status of CI for a given branch to the console. */
|
/** Log the status of CI for a given branch to the console. */
|
||||||
async function printStatus(git: GitClient, branch: string) {
|
async function printStatus(label: string, status: StatusCheckResult|null) {
|
||||||
const result = await getStatusOfBranch(git, branch);
|
const branchName = label.padEnd(16);
|
||||||
const branchName = branch.padEnd(10);
|
if (status === null) {
|
||||||
if (result === null) {
|
|
||||||
info(`${branchName} was not found on CircleCI`);
|
info(`${branchName} was not found on CircleCI`);
|
||||||
} else if (result.status === 'success') {
|
} else if (status.status === 'success') {
|
||||||
info(`${branchName} ✅`);
|
info(`${branchName} ✅`);
|
||||||
} else {
|
} else {
|
||||||
info(`${branchName} ❌ (Ran at: ${result.timestamp.toLocaleString()})`);
|
info(`${branchName} ❌`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the CI status of a given branch from CircleCI. */
|
/** Get the CI status of a given branch from CircleCI. */
|
||||||
async function getStatusOfBranch(git: GitClient, branch: string): Promise<StatusCheckResult|null> {
|
async function getStatusOfBranch(git: GitClient, branch: string): Promise<StatusCheckResult|null> {
|
||||||
const {owner, name} = git.remoteConfig;
|
const {owner, name} = git.remoteConfig;
|
||||||
const url = `https://circleci.com/api/v1.1/project/gh/${owner}/${name}/tree/${
|
const url = `https://circleci.com/gh/${owner}/${name}/tree/${branch}.svg?style=shield`;
|
||||||
branch}?limit=1&filter=completed&shallow=true`;
|
const result = await fetch(url).then(result => result.text());
|
||||||
const result = (await fetch(url).then(result => result.json()))?.[0];
|
|
||||||
|
|
||||||
if (result) {
|
if (result && !result.includes('no builds')) {
|
||||||
return {
|
return {
|
||||||
status: result.outcome,
|
status: result.includes('passing') ? 'success' : 'failed',
|
||||||
timestamp: new Date(result.stop_time),
|
|
||||||
buildUrl: result.build_url
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -44,7 +44,8 @@ export async function printG3Comparison(git: GitClient) {
|
|||||||
/** Url of the ref for fetching master and g3 branches. */
|
/** Url of the ref for fetching master and g3 branches. */
|
||||||
const refUrl = `https://github.com/${git.remoteConfig.owner}/${git.remoteConfig.name}.git`;
|
const refUrl = `https://github.com/${git.remoteConfig.owner}/${git.remoteConfig.name}.git`;
|
||||||
/** The result fo the fetch command. */
|
/** The result fo the fetch command. */
|
||||||
const fetchResult = git.runGraceful(['fetch', refUrl, `master:${masterRef}`, `g3:${g3Ref}`]);
|
const fetchResult =
|
||||||
|
git.runGraceful(['fetch', '-q', refUrl, `master:${masterRef}`, `g3:${g3Ref}`]);
|
||||||
|
|
||||||
// If the upstream repository does not have a g3 branch to compare to, skip the comparison.
|
// If the upstream repository does not have a g3 branch to compare to, skip the comparison.
|
||||||
if (fetchResult.status !== 0) {
|
if (fetchResult.status !== 0) {
|
||||||
@ -118,6 +119,6 @@ export async function printG3Comparison(git: GitClient) {
|
|||||||
/** Determine whether the file name passes both include and exclude checks. */
|
/** Determine whether the file name passes both include and exclude checks. */
|
||||||
function checkMatchAgainstIncludeAndExclude(
|
function checkMatchAgainstIncludeAndExclude(
|
||||||
file: string, includes: string[], excludes: string[]) {
|
file: string, includes: string[], excludes: string[]) {
|
||||||
return multimatch(multimatch(file, includes), excludes, {flipNegate: true}).length !== 0;
|
return multimatch(file, includes).length >= 1 && multimatch(file, excludes).length === 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,17 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {alias, params, types} from 'typed-graphqlify';
|
import {alias, onUnion, params, types} from 'typed-graphqlify';
|
||||||
|
|
||||||
import {bold, debug, info} from '../../utils/console';
|
import {bold, debug, info} from '../../utils/console';
|
||||||
import {GitClient} from '../../utils/git';
|
import {GitClient} from '../../utils/git';
|
||||||
import {CaretakerConfig} from '../config';
|
import {CaretakerConfig} from '../config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cap the returned issues in the queries to an arbitrary 100. At that point, caretaker has a lot
|
||||||
|
* of work to do and showing more than that isn't really useful.
|
||||||
|
*/
|
||||||
|
const MAX_RETURNED_ISSUES = 20;
|
||||||
|
|
||||||
/** Retrieve the number of matching issues for each github query. */
|
/** Retrieve the number of matching issues for each github query. */
|
||||||
export async function printGithubTasks(git: GitClient, config?: CaretakerConfig) {
|
export async function printGithubTasks(git: GitClient, config?: CaretakerConfig) {
|
||||||
@ -19,7 +24,7 @@ export async function printGithubTasks(git: GitClient, config?: CaretakerConfig)
|
|||||||
debug('No github queries defined in the configuration, skipping.');
|
debug('No github queries defined in the configuration, skipping.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info.group(bold('Github Tasks'));
|
info.group(bold(`Github Tasks`));
|
||||||
await getGithubInfo(git, config);
|
await getGithubInfo(git, config);
|
||||||
info.groupEnd();
|
info.groupEnd();
|
||||||
info();
|
info();
|
||||||
@ -28,7 +33,12 @@ export async function printGithubTasks(git: GitClient, config?: CaretakerConfig)
|
|||||||
/** Retrieve query match counts and log discovered counts to the console. */
|
/** Retrieve query match counts and log discovered counts to the console. */
|
||||||
async function getGithubInfo(git: GitClient, {githubQueries: queries = []}: CaretakerConfig) {
|
async function getGithubInfo(git: GitClient, {githubQueries: queries = []}: CaretakerConfig) {
|
||||||
/** The query object for graphql. */
|
/** The query object for graphql. */
|
||||||
const graphQlQuery: {[key: string]: {issueCount: number}} = {};
|
const graphQlQuery: {
|
||||||
|
[key: string]: {
|
||||||
|
issueCount: number,
|
||||||
|
nodes: Array<{url: string}>,
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
/** The Github search filter for the configured repository. */
|
/** The Github search filter for the configured repository. */
|
||||||
const repoFilter = `repo:${git.remoteConfig.owner}/${git.remoteConfig.name}`;
|
const repoFilter = `repo:${git.remoteConfig.owner}/${git.remoteConfig.name}`;
|
||||||
queries.forEach(({name, query}) => {
|
queries.forEach(({name, query}) => {
|
||||||
@ -37,14 +47,37 @@ async function getGithubInfo(git: GitClient, {githubQueries: queries = []}: Care
|
|||||||
graphQlQuery[queryKey] = params(
|
graphQlQuery[queryKey] = params(
|
||||||
{
|
{
|
||||||
type: 'ISSUE',
|
type: 'ISSUE',
|
||||||
|
first: MAX_RETURNED_ISSUES,
|
||||||
query: `"${repoFilter} ${query.replace(/"/g, '\\"')}"`,
|
query: `"${repoFilter} ${query.replace(/"/g, '\\"')}"`,
|
||||||
},
|
},
|
||||||
{issueCount: types.number},
|
{
|
||||||
|
issueCount: types.number,
|
||||||
|
nodes: [{...onUnion({
|
||||||
|
PullRequest: {
|
||||||
|
url: types.string,
|
||||||
|
},
|
||||||
|
Issue: {
|
||||||
|
url: types.string,
|
||||||
|
},
|
||||||
|
})}],
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
/** The results of the generated github query. */
|
/** The results of the generated github query. */
|
||||||
const results = await git.github.graphql.query(graphQlQuery);
|
const results = await git.github.graphql.query(graphQlQuery);
|
||||||
Object.values(results).forEach((result, i) => {
|
Object.values(results).forEach((result, i) => {
|
||||||
info(`${queries[i]?.name.padEnd(25)} ${result.issueCount}`);
|
info(`${queries[i]?.name.padEnd(25)} ${result.issueCount}`);
|
||||||
|
if (result.issueCount > 0) {
|
||||||
|
const {owner, name: repo} = git.remoteConfig;
|
||||||
|
const url = encodeURI(`https://github.com/${owner}/${repo}/issues?q=${queries[i]?.query}`);
|
||||||
|
info.group(`${url}`);
|
||||||
|
if (result.nodes.length === MAX_RETURNED_ISSUES && result.nodes.length < result.issueCount) {
|
||||||
|
info(`(first ${MAX_RETURNED_ISSUES})`);
|
||||||
|
}
|
||||||
|
for (const node of result.nodes) {
|
||||||
|
info(`- ${node.url}`);
|
||||||
|
}
|
||||||
|
info.groupEnd();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import {buildReleaseParser} from './release/cli';
|
|||||||
import {buildPrParser} from './pr/cli';
|
import {buildPrParser} from './pr/cli';
|
||||||
import {captureLogOutputForCommand} from './utils/console';
|
import {captureLogOutputForCommand} from './utils/console';
|
||||||
import {buildCaretakerParser} from './caretaker/cli';
|
import {buildCaretakerParser} from './caretaker/cli';
|
||||||
|
import {buildNgbotParser} from './ngbot/cli';
|
||||||
|
|
||||||
yargs.scriptName('ng-dev')
|
yargs.scriptName('ng-dev')
|
||||||
.middleware(captureLogOutputForCommand)
|
.middleware(captureLogOutputForCommand)
|
||||||
@ -27,6 +28,7 @@ yargs.scriptName('ng-dev')
|
|||||||
.command('release <command>', '', buildReleaseParser)
|
.command('release <command>', '', buildReleaseParser)
|
||||||
.command('ts-circular-deps <command>', '', tsCircularDependenciesBuilder)
|
.command('ts-circular-deps <command>', '', tsCircularDependenciesBuilder)
|
||||||
.command('caretaker <command>', '', buildCaretakerParser)
|
.command('caretaker <command>', '', buildCaretakerParser)
|
||||||
|
.command('ngbot <command>', false, buildNgbotParser)
|
||||||
.wrap(120)
|
.wrap(120)
|
||||||
.strict()
|
.strict()
|
||||||
.parse();
|
.parse();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "commit-message",
|
name = "commit-message",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "format",
|
name = "format",
|
||||||
|
19
dev-infra/ngbot/BUILD.bazel
Normal file
19
dev-infra/ngbot/BUILD.bazel
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
|
ts_library(
|
||||||
|
name = "ngbot",
|
||||||
|
srcs = [
|
||||||
|
"cli.ts",
|
||||||
|
"verify.ts",
|
||||||
|
],
|
||||||
|
module_name = "@angular/dev-infra-private/ngbot",
|
||||||
|
visibility = ["//dev-infra:__subpackages__"],
|
||||||
|
deps = [
|
||||||
|
"//dev-infra/utils",
|
||||||
|
"@npm//@types/node",
|
||||||
|
"@npm//@types/yaml",
|
||||||
|
"@npm//@types/yargs",
|
||||||
|
"@npm//yaml",
|
||||||
|
"@npm//yargs",
|
||||||
|
],
|
||||||
|
)
|
19
dev-infra/ngbot/cli.ts
Normal file
19
dev-infra/ngbot/cli.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
import * as yargs from 'yargs';
|
||||||
|
import {verify} from './verify';
|
||||||
|
|
||||||
|
/** Build the parser for the NgBot commands. */
|
||||||
|
export function buildNgbotParser(localYargs: yargs.Argv) {
|
||||||
|
return localYargs.help().strict().demandCommand().command(
|
||||||
|
'verify', 'Verify the NgBot config', {}, () => verify());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
buildNgbotParser(yargs).parse();
|
||||||
|
}
|
31
dev-infra/ngbot/verify.ts
Normal file
31
dev-infra/ngbot/verify.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
import {readFileSync} from 'fs';
|
||||||
|
import {resolve} from 'path';
|
||||||
|
import {parse as parseYaml} from 'yaml';
|
||||||
|
|
||||||
|
import {getRepoBaseDir} from '../utils/config';
|
||||||
|
import {error, green, info, red} from '../utils/console';
|
||||||
|
|
||||||
|
export function verify() {
|
||||||
|
/** Full path to NgBot config file */
|
||||||
|
const NGBOT_CONFIG_YAML_PATH = resolve(getRepoBaseDir(), '.github/angular-robot.yml');
|
||||||
|
|
||||||
|
/** The NgBot config file */
|
||||||
|
const ngBotYaml = readFileSync(NGBOT_CONFIG_YAML_PATH, 'utf8');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try parsing the config file to verify that the syntax is correct.
|
||||||
|
parseYaml(ngBotYaml);
|
||||||
|
info(`${green('√')} Valid NgBot YAML config`);
|
||||||
|
} catch (e) {
|
||||||
|
error(`${red('!')} Invalid NgBot YAML config`);
|
||||||
|
error(e);
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "pr",
|
name = "pr",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "checkout",
|
name = "checkout",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "common",
|
name = "common",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "discover-new-conflicts",
|
name = "discover-new-conflicts",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
|
@ -41,8 +41,8 @@ export async function getDefaultTargetLabelConfiguration(
|
|||||||
// allow merging of PRs with `target: major`.
|
// allow merging of PRs with `target: major`.
|
||||||
if (!next.isMajor) {
|
if (!next.isMajor) {
|
||||||
throw new InvalidTargetLabelError(
|
throw new InvalidTargetLabelError(
|
||||||
`Unable to merge pull request. The "${nextBranchName}" branch will be ` +
|
`Unable to merge pull request. The "${nextBranchName}" branch will be released as ` +
|
||||||
`released as a minor version.`);
|
'a minor version.');
|
||||||
}
|
}
|
||||||
return [nextBranchName];
|
return [nextBranchName];
|
||||||
},
|
},
|
||||||
|
@ -30,8 +30,8 @@ export async function assertActiveLtsBranch(
|
|||||||
const ltsNpmTag = getLtsNpmDistTagOfMajor(version.major);
|
const ltsNpmTag = getLtsNpmDistTagOfMajor(version.major);
|
||||||
const ltsVersion = semver.parse(distTags[ltsNpmTag]);
|
const ltsVersion = semver.parse(distTags[ltsNpmTag]);
|
||||||
|
|
||||||
// Ensure that there is a LTS version tagged for the given version-branch major. e.g.
|
// Ensure that there is an LTS version tagged for the given version-branch major. e.g.
|
||||||
// if the version branch is `9.2.x` then we want to make sure that there is a LTS
|
// if the version branch is `9.2.x` then we want to make sure that there is an LTS
|
||||||
// version tagged in NPM for `v9`, following the `v{major}-lts` tag convention.
|
// version tagged in NPM for `v9`, following the `v{major}-lts` tag convention.
|
||||||
if (ltsVersion === null) {
|
if (ltsVersion === null) {
|
||||||
throw new InvalidTargetBranchError(`No LTS version tagged for v${version.major} in NPM.`);
|
throw new InvalidTargetBranchError(`No LTS version tagged for v${version.major} in NPM.`);
|
||||||
|
@ -33,7 +33,7 @@ export async function mergePullRequest(
|
|||||||
prNumber: number, githubToken: string, projectRoot: string = getRepoBaseDir(),
|
prNumber: number, githubToken: string, projectRoot: string = getRepoBaseDir(),
|
||||||
config?: MergeConfigWithRemote) {
|
config?: MergeConfigWithRemote) {
|
||||||
// Set the environment variable to skip all git commit hooks triggered by husky. We are unable to
|
// Set the environment variable to skip all git commit hooks triggered by husky. We are unable to
|
||||||
// rely on `---no-verify` as some hooks still run, notably the `prepare-commit-msg` hook.
|
// rely on `--no-verify` as some hooks still run, notably the `prepare-commit-msg` hook.
|
||||||
process.env['HUSKY_SKIP_HOOKS'] = '1';
|
process.env['HUSKY_SKIP_HOOKS'] = '1';
|
||||||
|
|
||||||
const api = await createPullRequestMergeTask(githubToken, projectRoot, config);
|
const api = await createPullRequestMergeTask(githubToken, projectRoot, config);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "rebase",
|
name = "rebase",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "release",
|
name = "release",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
|
@ -60,7 +60,7 @@ describe('ng-dev release build', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should error if package has not been built', async () => {
|
it('should error if package has not been built', async () => {
|
||||||
// Set up a NPM package that is not built.
|
// Set up an NPM package that is not built.
|
||||||
npmPackages.push('@angular/non-existent');
|
npmPackages.push('@angular/non-existent');
|
||||||
|
|
||||||
spyOn(console, 'error');
|
spyOn(console, 'error');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "config",
|
name = "config",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "publish",
|
name = "publish",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {promises as fs} from 'fs';
|
import {promises as fs} from 'fs';
|
||||||
import * as Ora from 'ora';
|
import * as ora from 'ora';
|
||||||
import {join} from 'path';
|
import {join} from 'path';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export interface PullRequest {
|
|||||||
forkBranch: string;
|
forkBranch: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor type for a instantiating a release action */
|
/** Constructor type for instantiating a release action */
|
||||||
export interface ReleaseActionConstructor<T extends ReleaseAction = ReleaseAction> {
|
export interface ReleaseActionConstructor<T extends ReleaseAction = ReleaseAction> {
|
||||||
/** Whether the release action is currently active. */
|
/** Whether the release action is currently active. */
|
||||||
isActive(active: ActiveReleaseTrains): Promise<boolean>;
|
isActive(active: ActiveReleaseTrains): Promise<boolean>;
|
||||||
@ -107,25 +107,22 @@ export abstract class ReleaseAction {
|
|||||||
if (state === 'failure') {
|
if (state === 'failure') {
|
||||||
error(
|
error(
|
||||||
red(` ✘ Cannot stage release. Commit "${commitSha}" does not pass all github ` +
|
red(` ✘ Cannot stage release. Commit "${commitSha}" does not pass all github ` +
|
||||||
`status checks. Please make sure this commit passes all checks before re-running.`));
|
'status checks. Please make sure this commit passes all checks before re-running.'));
|
||||||
error(` Please have a look at: ${branchCommitsUrl}`);
|
error(` Please have a look at: ${branchCommitsUrl}`);
|
||||||
|
|
||||||
if (await promptConfirm('Do you want to ignore the Github status and proceed?')) {
|
if (await promptConfirm('Do you want to ignore the Github status and proceed?')) {
|
||||||
info(yellow(
|
info(yellow(
|
||||||
` ⚠ Upstream commit is failing CI checks, but status has been ` +
|
' ⚠ Upstream commit is failing CI checks, but status has been forcibly ignored.'));
|
||||||
`forcibly ignored.`));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UserAbortedReleaseActionError();
|
throw new UserAbortedReleaseActionError();
|
||||||
} else if (state === 'pending') {
|
} else if (state === 'pending') {
|
||||||
error(
|
error(
|
||||||
red(` ✘ Commit "${commitSha}" still has pending github statuses that ` +
|
red(` ✘ Commit "${commitSha}" still has pending github statuses that ` +
|
||||||
`need to succeed before staging a release.`));
|
'need to succeed before staging a release.'));
|
||||||
error(red(` Please have a look at: ${branchCommitsUrl}`));
|
error(red(` Please have a look at: ${branchCommitsUrl}`));
|
||||||
if (await promptConfirm('Do you want to ignore the Github status and proceed?')) {
|
if (await promptConfirm('Do you want to ignore the Github status and proceed?')) {
|
||||||
info(yellow(
|
info(yellow(' ⚠ Upstream commit is pending CI, but status has been forcibly ignored.'));
|
||||||
` ⚠ Upstream commit is pending CI, but status has been ` +
|
|
||||||
`forcibly ignored.`));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UserAbortedReleaseActionError();
|
throw new UserAbortedReleaseActionError();
|
||||||
@ -157,9 +154,9 @@ export abstract class ReleaseAction {
|
|||||||
*/
|
*/
|
||||||
protected async waitForEditsAndCreateReleaseCommit(newVersion: semver.SemVer) {
|
protected async waitForEditsAndCreateReleaseCommit(newVersion: semver.SemVer) {
|
||||||
info(yellow(
|
info(yellow(
|
||||||
` ⚠ Please review the changelog and ensure that the log contains only changes ` +
|
' ⚠ Please review the changelog and ensure that the log contains only changes ' +
|
||||||
`that apply to the public API surface. Manual changes can be made. When done, please ` +
|
'that apply to the public API surface. Manual changes can be made. When done, please ' +
|
||||||
`proceed with the prompt below.`));
|
'proceed with the prompt below.'));
|
||||||
|
|
||||||
if (!await promptConfirm('Do you want to proceed and commit the changes?')) {
|
if (!await promptConfirm('Do you want to proceed and commit the changes?')) {
|
||||||
throw new UserAbortedReleaseActionError();
|
throw new UserAbortedReleaseActionError();
|
||||||
@ -188,7 +185,7 @@ export abstract class ReleaseAction {
|
|||||||
const forks = result.repository.forks.nodes;
|
const forks = result.repository.forks.nodes;
|
||||||
|
|
||||||
if (forks.length === 0) {
|
if (forks.length === 0) {
|
||||||
error(red(` ✘ Unable to find fork for currently authenticated user.`));
|
error(red(' ✘ Unable to find fork for currently authenticated user.'));
|
||||||
error(red(` Please ensure you created a fork of: ${owner}/${name}.`));
|
error(red(` Please ensure you created a fork of: ${owner}/${name}.`));
|
||||||
throw new FatalReleaseActionError();
|
throw new FatalReleaseActionError();
|
||||||
}
|
}
|
||||||
@ -304,7 +301,7 @@ export abstract class ReleaseAction {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
debug(`Waiting for pull request #${id} to be merged.`);
|
debug(`Waiting for pull request #${id} to be merged.`);
|
||||||
|
|
||||||
const spinner = Ora().start(`Waiting for pull request #${id} to be merged.`);
|
const spinner = ora().start(`Waiting for pull request #${id} to be merged.`);
|
||||||
const intervalId = setInterval(async () => {
|
const intervalId = setInterval(async () => {
|
||||||
const prState = await getPullRequestState(this.git, id);
|
const prState = await getPullRequestState(this.git, id);
|
||||||
if (prState === 'merged') {
|
if (prState === 'merged') {
|
||||||
@ -451,7 +448,7 @@ export abstract class ReleaseAction {
|
|||||||
|
|
||||||
info(green(
|
info(green(
|
||||||
` ✓ Pull request for cherry-picking the changelog into "${nextBranch}" ` +
|
` ✓ Pull request for cherry-picking the changelog into "${nextBranch}" ` +
|
||||||
`has been created.`));
|
'has been created.'));
|
||||||
info(yellow(` Please ask team members to review: ${url}.`));
|
info(yellow(` Please ask team members to review: ${url}.`));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -490,7 +487,7 @@ export abstract class ReleaseAction {
|
|||||||
|
|
||||||
if (!await this._isCommitForVersionStaging(newVersion, versionBumpCommitSha)) {
|
if (!await this._isCommitForVersionStaging(newVersion, versionBumpCommitSha)) {
|
||||||
error(red(` ✘ Latest commit in "${publishBranch}" branch is not a staging commit.`));
|
error(red(` ✘ Latest commit in "${publishBranch}" branch is not a staging commit.`));
|
||||||
error(red(` Please make sure the staging pull request has been merged.`));
|
error(red(' Please make sure the staging pull request has been merged.'));
|
||||||
throw new FatalReleaseActionError();
|
throw new FatalReleaseActionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,13 +511,13 @@ export abstract class ReleaseAction {
|
|||||||
await this._publishBuiltPackageToNpm(builtPackage, npmDistTag);
|
await this._publishBuiltPackageToNpm(builtPackage, npmDistTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
info(green(` ✓ Published all packages successfully`));
|
info(green(' ✓ Published all packages successfully'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Publishes the given built package to NPM with the specified NPM dist tag. */
|
/** Publishes the given built package to NPM with the specified NPM dist tag. */
|
||||||
private async _publishBuiltPackageToNpm(pkg: BuiltPackage, npmDistTag: string) {
|
private async _publishBuiltPackageToNpm(pkg: BuiltPackage, npmDistTag: string) {
|
||||||
debug(`Starting publish of "${pkg.name}".`);
|
debug(`Starting publish of "${pkg.name}".`);
|
||||||
const spinner = Ora().start(`Publishing "${pkg.name}"`);
|
const spinner = ora().start(`Publishing "${pkg.name}"`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await runNpmPublish(pkg.outputPath, npmDistTag, this.config.publishRegistry);
|
await runNpmPublish(pkg.outputPath, npmDistTag, this.config.publishRegistry);
|
||||||
|
@ -65,14 +65,14 @@ export class CutLongTermSupportPatchAction extends ReleaseAction {
|
|||||||
{
|
{
|
||||||
name: 'activeLtsBranch',
|
name: 'activeLtsBranch',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
message: 'Please select a version for which you want to cut a LTS patch',
|
message: 'Please select a version for which you want to cut an LTS patch',
|
||||||
choices: activeBranchChoices,
|
choices: activeBranchChoices,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'inactiveLtsBranch',
|
name: 'inactiveLtsBranch',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
when: o => o.activeLtsBranch === null,
|
when: o => o.activeLtsBranch === null,
|
||||||
message: 'Please select an inactive LTS version for which you want to cut a LTS patch',
|
message: 'Please select an inactive LTS version for which you want to cut an LTS patch',
|
||||||
choices: inactive.map(branch => this._getChoiceForLtsBranch(branch)),
|
choices: inactive.map(branch => this._getChoiceForLtsBranch(branch)),
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Ora from 'ora';
|
import * as ora from 'ora';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
|
|
||||||
import {spawnWithDebugOutput} from '../../utils/child-process';
|
import {spawnWithDebugOutput} from '../../utils/child-process';
|
||||||
@ -19,11 +19,11 @@ import {FatalReleaseActionError} from './actions-error';
|
|||||||
* ###############################################################
|
* ###############################################################
|
||||||
*
|
*
|
||||||
* This file contains helpers for invoking external `ng-dev` commands. A subset of actions,
|
* This file contains helpers for invoking external `ng-dev` commands. A subset of actions,
|
||||||
* like building release output or setting a NPM dist tag for release packages, cannot be
|
* like building release output or setting aν NPM dist tag for release packages, cannot be
|
||||||
* performed directly as part of the release tool and need to be delegated to external `ng-dev`
|
* performed directly as part of the release tool and need to be delegated to external `ng-dev`
|
||||||
* commands that exist across arbitrary version branches.
|
* commands that exist across arbitrary version branches.
|
||||||
*
|
*
|
||||||
* In an concrete example: Consider a new patch version is released and that a new release
|
* In a concrete example: Consider a new patch version is released and that a new release
|
||||||
* package has been added to the `next` branch. The patch branch will not contain the new
|
* package has been added to the `next` branch. The patch branch will not contain the new
|
||||||
* release package, so we could not build the release output for it. To work around this, we
|
* release package, so we could not build the release output for it. To work around this, we
|
||||||
* call the ng-dev build command for the patch version branch and expect it to return a list
|
* call the ng-dev build command for the patch version branch and expect it to return a list
|
||||||
@ -44,7 +44,7 @@ export async function invokeSetNpmDistCommand(npmDistTag: string, version: semve
|
|||||||
info(green(` ✓ Set "${npmDistTag}" NPM dist tag for all packages to v${version}.`));
|
info(green(` ✓ Set "${npmDistTag}" NPM dist tag for all packages to v${version}.`));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error(e);
|
error(e);
|
||||||
error(red(` ✘ An error occurred while setting the NPM dist tag for ${npmDistTag}.`));
|
error(red(` ✘ An error occurred while setting the NPM dist tag for "${npmDistTag}".`));
|
||||||
throw new FatalReleaseActionError();
|
throw new FatalReleaseActionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,21 +54,21 @@ export async function invokeSetNpmDistCommand(npmDistTag: string, version: semve
|
|||||||
* packages for the currently checked out branch.
|
* packages for the currently checked out branch.
|
||||||
*/
|
*/
|
||||||
export async function invokeReleaseBuildCommand(): Promise<BuiltPackage[]> {
|
export async function invokeReleaseBuildCommand(): Promise<BuiltPackage[]> {
|
||||||
const spinner = Ora().start('Building release output.');
|
const spinner = ora().start('Building release output.');
|
||||||
try {
|
try {
|
||||||
// Since we expect JSON to be printed from the `ng-dev release build` command,
|
// Since we expect JSON to be printed from the `ng-dev release build` command,
|
||||||
// we spawn the process in silent mode. We have set up an Ora progress spinner.
|
// we spawn the process in silent mode. We have set up an Ora progress spinner.
|
||||||
const {stdout} = await spawnWithDebugOutput(
|
const {stdout} = await spawnWithDebugOutput(
|
||||||
'yarn', ['--silent', 'ng-dev', 'release', 'build', '--json'], {mode: 'silent'});
|
'yarn', ['--silent', 'ng-dev', 'release', 'build', '--json'], {mode: 'silent'});
|
||||||
spinner.stop();
|
spinner.stop();
|
||||||
info(green(` ✓ Built release output for all packages.`));
|
info(green(' ✓ Built release output for all packages.'));
|
||||||
// The `ng-dev release build` command prints a JSON array to stdout
|
// The `ng-dev release build` command prints a JSON array to stdout
|
||||||
// that represents the built release packages and their output paths.
|
// that represents the built release packages and their output paths.
|
||||||
return JSON.parse(stdout.trim());
|
return JSON.parse(stdout.trim());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
spinner.stop();
|
spinner.stop();
|
||||||
error(e);
|
error(e);
|
||||||
error(red(` ✘ An error occurred while building the release packages.`));
|
error(red(' ✘ An error occurred while building the release packages.'));
|
||||||
throw new FatalReleaseActionError();
|
throw new FatalReleaseActionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,10 +83,10 @@ export async function invokeYarnInstallCommand(projectDir: string): Promise<void
|
|||||||
// TODO: Consider using an Ora spinner instead to ensure minimal console output.
|
// TODO: Consider using an Ora spinner instead to ensure minimal console output.
|
||||||
await spawnWithDebugOutput(
|
await spawnWithDebugOutput(
|
||||||
'yarn', ['install', '--frozen-lockfile', '--non-interactive'], {cwd: projectDir});
|
'yarn', ['install', '--frozen-lockfile', '--non-interactive'], {cwd: projectDir});
|
||||||
info(green(` ✓ Installed project dependencies.`));
|
info(green(' ✓ Installed project dependencies.'));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error(e);
|
error(e);
|
||||||
error(red(` ✘ An error occurred while installing dependencies.`));
|
error(red(' ✘ An error occurred while installing dependencies.'));
|
||||||
throw new FatalReleaseActionError();
|
throw new FatalReleaseActionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,7 @@ export class ReleaseTool {
|
|||||||
// Only print the error message and stack if the error is not a known fatal release
|
// Only print the error message and stack if the error is not a known fatal release
|
||||||
// action error (for which we print the error gracefully to the console with colors).
|
// action error (for which we print the error gracefully to the console with colors).
|
||||||
if (!(e instanceof FatalReleaseActionError) && e instanceof Error) {
|
if (!(e instanceof FatalReleaseActionError) && e instanceof Error) {
|
||||||
console.error(e.message);
|
console.error(e);
|
||||||
console.error(e.stack);
|
|
||||||
}
|
}
|
||||||
return CompletionState.FATAL_ERROR;
|
return CompletionState.FATAL_ERROR;
|
||||||
} finally {
|
} finally {
|
||||||
@ -90,7 +89,7 @@ export class ReleaseTool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info(`Please select the type of release you want to perform.`);
|
info('Please select the type of release you want to perform.');
|
||||||
|
|
||||||
const {releaseAction} = await prompt<{releaseAction: ReleaseAction}>({
|
const {releaseAction} = await prompt<{releaseAction: ReleaseAction}>({
|
||||||
name: 'releaseAction',
|
name: 'releaseAction',
|
||||||
@ -108,9 +107,7 @@ export class ReleaseTool {
|
|||||||
*/
|
*/
|
||||||
private async _verifyNoUncommittedChanges(): Promise<boolean> {
|
private async _verifyNoUncommittedChanges(): Promise<boolean> {
|
||||||
if (this._git.hasUncommittedChanges()) {
|
if (this._git.hasUncommittedChanges()) {
|
||||||
error(
|
error(red(' ✘ There are changes which are not committed and should be discarded.'));
|
||||||
red(` ✘ There are changes which are not committed and should be ` +
|
|
||||||
`discarded.`));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -126,7 +123,7 @@ export class ReleaseTool {
|
|||||||
await this._git.github.repos.getBranch({...this._git.remoteParams, branch: nextBranchName});
|
await this._git.github.repos.getBranch({...this._git.remoteParams, branch: nextBranchName});
|
||||||
|
|
||||||
if (headSha !== data.commit.sha) {
|
if (headSha !== data.commit.sha) {
|
||||||
error(red(` ✘ Running release tool from an outdated local branch.`));
|
error(red(' ✘ Running release tool from an outdated local branch.'));
|
||||||
error(red(` Please make sure you are running from the "${nextBranchName}" branch.`));
|
error(red(` Please make sure you are running from the "${nextBranchName}" branch.`));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -68,5 +68,6 @@ async function isCommitClosingPullRequest(api: GitClient, sha: string, id: numbe
|
|||||||
const {data} = await api.github.repos.getCommit({...api.remoteParams, ref: sha});
|
const {data} = await api.github.repos.getCommit({...api.remoteParams, ref: sha});
|
||||||
// Matches the closing keyword supported in commit messages. See:
|
// Matches the closing keyword supported in commit messages. See:
|
||||||
// https://docs.github.com/en/enterprise/2.16/user/github/managing-your-work-on-github/closing-issues-using-keywords.
|
// https://docs.github.com/en/enterprise/2.16/user/github/managing-your-work-on-github/closing-issues-using-keywords.
|
||||||
return data.commit.message.match(new RegExp(`close[sd]? #${id}[^0-9]?`, 'i'));
|
return data.commit.message.match(
|
||||||
|
new RegExp(`(?:close[sd]?|fix(?:e[sd]?)|resolve[sd]?):? #${id}(?!\\d)`, 'i'));
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
|
@ -13,7 +13,7 @@ import {CutLongTermSupportPatchAction} from '../actions/cut-lts-patch';
|
|||||||
|
|
||||||
import {expectStagingAndPublishWithCherryPick, fakeNpmPackageQueryRequest, getTestingMocksForReleaseAction, parse, setupReleaseActionForTesting, testTmpDir} from './test-utils';
|
import {expectStagingAndPublishWithCherryPick, fakeNpmPackageQueryRequest, getTestingMocksForReleaseAction, parse, setupReleaseActionForTesting, testTmpDir} from './test-utils';
|
||||||
|
|
||||||
describe('cut a LTS patch action', () => {
|
describe('cut an LTS patch action', () => {
|
||||||
it('should be active', async () => {
|
it('should be active', async () => {
|
||||||
expect(await CutLongTermSupportPatchAction.isActive({
|
expect(await CutLongTermSupportPatchAction.isActive({
|
||||||
releaseCandidate: null,
|
releaseCandidate: null,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
load("//tools:defaults.bzl", "jasmine_node_test")
|
load("//tools:defaults.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Ora from 'ora';
|
import * as ora from 'ora';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import {Arguments, Argv, CommandModule} from 'yargs';
|
import {Arguments, Argv, CommandModule} from 'yargs';
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ import {getReleaseConfig} from '../config/index';
|
|||||||
import {setNpmTagForPackage} from '../versioning/npm-publish';
|
import {setNpmTagForPackage} from '../versioning/npm-publish';
|
||||||
|
|
||||||
|
|
||||||
/** Command line options for setting a NPM dist tag. */
|
/** Command line options for setting an NPM dist tag. */
|
||||||
export interface ReleaseSetDistTagOptions {
|
export interface ReleaseSetDistTagOptions {
|
||||||
tagName: string;
|
tagName: string;
|
||||||
targetVersion: string;
|
targetVersion: string;
|
||||||
@ -42,11 +42,11 @@ async function handler(args: Arguments<ReleaseSetDistTagOptions>) {
|
|||||||
const version = semver.parse(rawVersion);
|
const version = semver.parse(rawVersion);
|
||||||
|
|
||||||
if (version === null) {
|
if (version === null) {
|
||||||
error(red(`Invalid version specified. Unable to set NPM dist tag.`));
|
error(red(`Invalid version specified (${rawVersion}). Unable to set NPM dist tag.`));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const spinner = Ora().start();
|
const spinner = ora().start();
|
||||||
debug(`Setting "${tagName}" NPM dist tag for release packages to v${version}.`);
|
debug(`Setting "${tagName}" NPM dist tag for release packages to v${version}.`);
|
||||||
|
|
||||||
for (const pkgName of npmPackages) {
|
for (const pkgName of npmPackages) {
|
||||||
@ -69,7 +69,7 @@ async function handler(args: Arguments<ReleaseSetDistTagOptions>) {
|
|||||||
info(green(` ${bold(tagName)} will now point to ${bold(`v${version}`)}.`));
|
info(green(` ${bold(tagName)} will now point to ${bold(`v${version}`)}.`));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** CLI command module for setting a NPM dist tag. */
|
/** CLI command module for setting an NPM dist tag. */
|
||||||
export const ReleaseSetDistTagCommand: CommandModule<{}, ReleaseSetDistTagOptions> = {
|
export const ReleaseSetDistTagCommand: CommandModule<{}, ReleaseSetDistTagOptions> = {
|
||||||
builder,
|
builder,
|
||||||
handler,
|
handler,
|
||||||
|
@ -66,7 +66,7 @@ describe('ng-dev release set-dist-tag', () => {
|
|||||||
await invokeCommand('latest', '10.0');
|
await invokeCommand('latest', '10.0');
|
||||||
|
|
||||||
expect(console.error)
|
expect(console.error)
|
||||||
.toHaveBeenCalledWith('Invalid version specified. Unable to set NPM dist tag.');
|
.toHaveBeenCalledWith('Invalid version specified (10.0). Unable to set NPM dist tag.');
|
||||||
expect(process.exit).toHaveBeenCalledWith(1);
|
expect(process.exit).toHaveBeenCalledWith(1);
|
||||||
expect(process.exit).toHaveBeenCalledTimes(1);
|
expect(process.exit).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "versioning",
|
name = "versioning",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user