mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
397 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ec91da095f | |||
| c3cd2273e2 | |||
| d6cccbae82 | |||
| 6d3245ecd6 | |||
| 326337ecba | |||
| 8d7598f776 | |||
| 9bf047562c | |||
| 241c0004e9 | |||
| 5b841fde1d | |||
| af3d6c7d19 | |||
| ff03fc8ac0 | |||
| 34ded10fa6 | |||
| 7e61217170 | |||
| cd764a3115 | |||
| ffae7df6e8 | |||
| ae0802d63c | |||
| c521ce133f | |||
| 3af585b98e | |||
| 044e1d8007 | |||
| 6d56dc332c | |||
| 1cd0eb83d2 | |||
| 9d73fe605e | |||
| f87cdd9280 | |||
| 308950dafa | |||
| 8bc3693f7a | |||
| 98471dfc08 | |||
| 850a2ad899 | |||
| c9ce08a7ea | |||
| d0e0446149 | |||
| b58123bfd8 | |||
| 3e8e9483db | |||
| e2c8c6f269 | |||
| 47e314f418 | |||
| 4dfe7f1cce | |||
| a7fb45fba2 | |||
| 28c00cbc8b | |||
| 7ad1f27d83 | |||
| e18adff76d | |||
| 0c40bb28e1 | |||
| 6338c1bece | |||
| 54a1bcee20 | |||
| dc8fd113a5 | |||
| e0aa93e67f | |||
| 7e4d312aed | |||
| 8eb20463bf | |||
| d75c4d2d12 | |||
| 3c0e4938a7 | |||
| 41a600f3ae | |||
| 5f3ba068f1 | |||
| 6ae3ce7c81 | |||
| 7d2308f8ba | |||
| 0df7b1e0ed | |||
| b8a2ae01d5 | |||
| b5807c5bc7 | |||
| ad927bcf18 | |||
| 5cd35cb9d1 | |||
| a107bf8ddb | |||
| bc5ca99678 | |||
| b65eea574a | |||
| bee3394b5b | |||
| af6280d06f | |||
| f62a3508d1 | |||
| 4a03b7453b | |||
| 0fe3760626 | |||
| 9a87aa398b | |||
| f72a1b15ca | |||
| c453f5dc2f | |||
| f3c388ecda | |||
| e4b85d15d4 | |||
| c639210314 | |||
| 4392ccedf9 | |||
| e17ff71c31 | |||
| 9cbebc6dda | |||
| 7c5f990001 | |||
| d1cbdd6acb | |||
| 7b5bacc228 | |||
| b1828065f3 | |||
| 028cf73f7c | |||
| db7ea92a26 | |||
| 3954036485 | |||
| 5ae0d32d51 | |||
| 9bee4a3c08 | |||
| cca70cbc62 | |||
| 3eedb98df2 | |||
| ea4acaf9eb | |||
| 0a56d82900 | |||
| bc6efa758d | |||
| dabbeb6498 | |||
| e86b179a01 | |||
| 293dce929d | |||
| 9f99196d23 | |||
| d6f4b104e3 | |||
| 4792db9a6d | |||
| 31f73cd9d3 | |||
| ee7aca1096 | |||
| 8c49a14c6e | |||
| 3145ca4fed | |||
| d23a5d5cae | |||
| d6da6313c1 | |||
| 22a6ff788f | |||
| 9660d69a7a | |||
| c64f0d86f8 | |||
| 2e4e485655 | |||
| 4852e57d9a | |||
| 4246f43556 | |||
| f6e448529f | |||
| 552092d742 | |||
| 01837167a2 | |||
| 43309d066d | |||
| 18091e72cb | |||
| 4c1abc4fc1 | |||
| 0c86d3e1f3 | |||
| bea852fa15 | |||
| 914f540a43 | |||
| fbf0c8226e | |||
| f0ecbe62de | |||
| 118803035f | |||
| bae473d718 | |||
| 83d2a09922 | |||
| 03a14b5034 | |||
| 21106bf3cd | |||
| 08b9452f01 | |||
| beec8969ee | |||
| b386b1aa6f | |||
| fb1fa8b0fc | |||
| ea0bf74e31 | |||
| 70547ebce0 | |||
| b8a450bbed | |||
| 9a9d1bfcdc | |||
| b21f96dc0e | |||
| cb5ea19cde | |||
| fa84477f26 | |||
| 48b48c1eea | |||
| a41ac8329a | |||
| 307ed7dba9 | |||
| 84f45ea3ff | |||
| de0d5c768b | |||
| bafcf2c292 | |||
| 671fdce9c1 | |||
| 6bee546c4d | |||
| ea5d74bb34 | |||
| d69a4e1e15 | |||
| 78cf51b12a | |||
| 600bab4356 | |||
| d7dfd47232 | |||
| 9fdec75c08 | |||
| a20689dc88 | |||
| 46d173d60f | |||
| 26d75b0315 | |||
| 97625d22c0 | |||
| ffbe7635d1 | |||
| c30ae2d069 | |||
| a0ca7d1513 | |||
| b2eccad3d6 | |||
| d3491c7cee | |||
| 5ce10264a4 | |||
| a6d2d2dc10 | |||
| ab701f4a24 | |||
| 9796067515 | |||
| 836ed79c89 | |||
| fe1a771c9a | |||
| 99715104a1 | |||
| 6b057bcfdb | |||
| 52912f064b | |||
| 9a01c42214 | |||
| 818659c6ec | |||
| 8694f919ad | |||
| ab4f81044c | |||
| ec674c6a68 | |||
| a3be5b0f25 | |||
| 28254ca134 | |||
| 4b7f295e8d | |||
| b767b660b6 | |||
| 273ee7a290 | |||
| 7c9f42540b | |||
| 678f333956 | |||
| ac52ce8ae7 | |||
| d87f4830bb | |||
| d4f5c85f60 | |||
| baedea7b3f | |||
| 472dd58537 | |||
| 69c29639fa | |||
| f4e2777994 | |||
| 4970ebab57 | |||
| ca032a2289 | |||
| a983865bff | |||
| e6e7a4e22b | |||
| 502ee0e722 | |||
| 4dfe5b6cef | |||
| e4dc7f1361 | |||
| 154e6052d3 | |||
| bf8ee41877 | |||
| 5838f43774 | |||
| c4357ebcc1 | |||
| 7bd56fd296 | |||
| e7566c3c47 | |||
| b2802e573a | |||
| 02b258a2ed | |||
| f696ecb424 | |||
| c79dd4e722 | |||
| 88c253ff61 | |||
| 2c04430a3e | |||
| 2c05f4ce9c | |||
| 805d8f1ca1 | |||
| 392b9920a0 | |||
| 51df77583c | |||
| 497fe97ada | |||
| 1192c89671 | |||
| 36a5712b67 | |||
| df210a463b | |||
| e6514b9f3d | |||
| e33b19592f | |||
| 806a61b5a6 | |||
| e5d3abb298 | |||
| 80f56954ce | |||
| 2be161d015 | |||
| 91a616fca7 | |||
| c53e3ac300 | |||
| 21ccc2333a | |||
| 5b7e768226 | |||
| ee499473ef | |||
| 02555bf5ef | |||
| e7131231fe | |||
| fa1b021aad | |||
| 5fe57d4fbb | |||
| f503c15ea9 | |||
| 715caea46b | |||
| d892b4aa2b | |||
| 29001ea586 | |||
| 506413cf23 | |||
| acca96c3e1 | |||
| 5ffec9a3af | |||
| f8248b948d | |||
| 45537eb648 | |||
| 23530a47de | |||
| e1e2e3fb67 | |||
| 4abb64580f | |||
| 87dc5003a2 | |||
| e26797b38e | |||
| c570be385c | |||
| b84ed2b628 | |||
| cfecdd50e7 | |||
| 29207d84a3 | |||
| 7082688a14 | |||
| a5e7a02f9b | |||
| 26602fcaae | |||
| 560282aa9b | |||
| 51933ef5a6 | |||
| 71ee81af2c | |||
| d190f82147 | |||
| b59c218b2d | |||
| dc5d2b7c34 | |||
| 829aa5dade | |||
| a32eb1ccbe | |||
| c77b53be11 | |||
| b834d7f5ee | |||
| 549c0ad2bd | |||
| d92001acd4 | |||
| 1996794957 | |||
| 320560b254 | |||
| 9bbb01c85e | |||
| 7cff2b73d2 | |||
| 3df159f54a | |||
| 746ea40c37 | |||
| 64661dd0dd | |||
| b6a998b2fd | |||
| 10540b54f9 | |||
| a524f42635 | |||
| 923cc33c6d | |||
| 9395aae1f7 | |||
| c988b91759 | |||
| e1c7327064 | |||
| c53ad709b1 | |||
| d6749683ba | |||
| c5511dc458 | |||
| 1848d2719f | |||
| f8322bd7cb | |||
| 499b227e11 | |||
| 791ee323dc | |||
| 4bebc9d5e4 | |||
| a314878bb5 | |||
| 7c4e0766be | |||
| fda8f70e29 | |||
| c4a84920b2 | |||
| 671fafac95 | |||
| b62c4534b2 | |||
| 3c0b2441fd | |||
| 3aa02635db | |||
| ab701ad1a6 | |||
| 65a0a1d416 | |||
| 0ec9533a6f | |||
| 203aa0c124 | |||
| 4a0d9eb01e | |||
| 1ead8ba765 | |||
| 10e6a25643 | |||
| 5eb3db8686 | |||
| f994539f6b | |||
| 728bfbbb31 | |||
| 4a0dc3c712 | |||
| d4d76ead80 | |||
| e85ac5c7cb | |||
| 8ae84be3df | |||
| b0711d74c4 | |||
| 5c9e2e41e1 | |||
| 3db099c8e6 | |||
| 85fa27d92a | |||
| 5b5828e856 | |||
| e7ac965b29 | |||
| c36a1c023b | |||
| 90509f88fe | |||
| a32e897c5a | |||
| ba84a02a6b | |||
| 11f86a0a08 | |||
| 996593809c | |||
| e6b05c72ea | |||
| 6e0af6dbbb | |||
| 36f4457b69 | |||
| 61565eafee | |||
| 23b1316822 | |||
| c5e676bb87 | |||
| 86d8f6bda8 | |||
| 3f82c3f0eb | |||
| 5278f194e5 | |||
| efa7baa976 | |||
| f87a773278 | |||
| da1cd6fc59 | |||
| 257d5b9979 | |||
| 8a38b68561 | |||
| 3b130087e9 | |||
| 22cd6869ef | |||
| abd0da7265 | |||
| b25121ee4a | |||
| d7a7c80066 | |||
| f1aab73189 | |||
| 1a919034a1 | |||
| 44a7257303 | |||
| 600ef5eff2 | |||
| 0ca14e2c72 | |||
| 8d00d0fe85 | |||
| ea9bfff739 | |||
| bb6e0aab1b | |||
| b5b0b4af29 | |||
| ea086905c3 | |||
| ee1d06c8fa | |||
| dcd16b43f3 | |||
| 3230d78c54 | |||
| 616b411a6d | |||
| d504452e2f | |||
| ddef41e897 | |||
| 8709359a1f | |||
| dbe612f2cd | |||
| 3e50842593 | |||
| 3d918de05f | |||
| a899623b51 | |||
| 7cb6adcb50 | |||
| fd7716440b | |||
| 98f54cb134 | |||
| 23531f249e | |||
| c6a21cc7f9 | |||
| df14cb6f8e | |||
| f815d7b8c8 | |||
| 90c7ec39a0 | |||
| eafe9040a2 | |||
| 7a65cdd911 | |||
| 1806fcce82 | |||
| 598c397c85 | |||
| 98804fd4be | |||
| ad3fbe6d97 | |||
| 2de5314400 | |||
| c0d606195c | |||
| 1efc4bb9e6 | |||
| 2d3a689660 | |||
| cf7f8c7c03 | |||
| 7dfb127c03 | |||
| 93c3f7a931 | |||
| 395cb34599 | |||
| 00b79f8157 | |||
| 50e99b66e5 | |||
| 0b2f18ff25 | |||
| 77fa588025 | |||
| d7283bf740 | |||
| f34268161b | |||
| 9c4bcb16ca | |||
| 0730d9d748 | |||
| a49c35ec76 | |||
| 917e99db42 | |||
| da9c0c5044 | |||
| d5998daa3d | |||
| 486c5a9d7e | |||
| 28516fd852 | |||
| c79b62ced2 | |||
| c095679f92 | |||
| aadcfda224 | |||
| d9ac59c88f | |||
| 61a732d71e | |||
| a36b54d63e | |||
| f418b49547 |
+7
-7
@@ -8,32 +8,32 @@ dist
|
||||
|
||||
# All integration test node_modules folders
|
||||
integration/animations/node_modules
|
||||
integration/animations-async/node_modules
|
||||
integration/cli-elements-universal/node_modules
|
||||
integration/cli-hello-world/node_modules
|
||||
integration/cli-hello-world-ivy-i18n/node_modules
|
||||
integration/cli-hello-world-lazy/node_modules
|
||||
integration/cli-hello-world-mocha/node_modules
|
||||
integration/cli-signal-inputs/node_modules
|
||||
integration/platform-server-hydration/node_modules
|
||||
integration/defer/node_modules
|
||||
integration/dynamic-compiler/node_modules
|
||||
integration/forms/node_modules
|
||||
integration/injectable-def/node_modules
|
||||
integration/ivy-i18n/node_modules
|
||||
integration/ng-add-localize/node_modules
|
||||
integration/ng_elements/node_modules
|
||||
integration/ng_update/node_modules
|
||||
integration/ng_update_migrations/node_modules
|
||||
integration/ng-add-localize/node_modules
|
||||
integration/nodenext_resolution/node_modules
|
||||
integration/npm_package_archives.bzl/node_modules
|
||||
integration/platform-server/node_modules
|
||||
integration/platform-server-hydration/node_modules
|
||||
integration/service-worker-schema/node_modules
|
||||
integration/side-effects/node_modules
|
||||
integration/standalone-bootstrap/node_modules
|
||||
integration/terser/node_modules
|
||||
integration/trusted-types/node_modules
|
||||
integration/typings_test_rxjs7/node_modules
|
||||
integration/typings_test_ts49/node_modules
|
||||
integration/typings_test_ts50/node_modules
|
||||
integration/typings_test_ts51/node_modules
|
||||
integration/typings_test_ts52/node_modules
|
||||
integration/typings_test_ts55/node_modules
|
||||
integration/typings_test_ts56/node_modules
|
||||
integration/typings_test_ts57/node_modules
|
||||
modules/ssr-benchmarks/node_modules
|
||||
|
||||
@@ -78,12 +78,6 @@ query --output=label_kind
|
||||
# By default, failing tests don't print any output, it goes to the log file
|
||||
test --test_output=errors
|
||||
|
||||
################################
|
||||
# Settings for CircleCI #
|
||||
################################
|
||||
|
||||
# Bazel flags for CircleCI are in /.circleci/bazel.linux.rc and /.circleci/bazel.windows.rc
|
||||
|
||||
##################################
|
||||
# Remote Build Execution support #
|
||||
# Turn on these settings with #
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Encryption
|
||||
|
||||
Based on https://github.com/circleci/encrypted-files
|
||||
|
||||
In the CircleCI web UI, we have a secret variable called `KEY`
|
||||
https://circleci.com/gh/angular/angular/edit#env-vars
|
||||
which is only exposed to non-fork builds
|
||||
(see "Pass secrets to builds from forked pull requests" under
|
||||
https://circleci.com/gh/angular/angular/edit#advanced-settings)
|
||||
|
||||
We use this as a symmetric AES encryption key to encrypt tokens like
|
||||
a GitHub token that enables publishing snapshots.
|
||||
|
||||
To create the github_token file, we take this approach:
|
||||
- Find the angular-builds:token in the internal pw database
|
||||
- Go inside the CircleCI default docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it circleci/node:10.12`
|
||||
- echo "https://[token]:@github.com" > credentials
|
||||
- openssl aes-256-cbc -e -in credentials -out .circleci/github_token -k $KEY
|
||||
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
|
||||
@@ -1,16 +0,0 @@
|
||||
# Settings in this file should be OS agnostic. Use the bazel.<OS>.rc files for OS specific settings.
|
||||
|
||||
# Print all the options that apply to the build.
|
||||
# This helps us diagnose which options override others
|
||||
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||
build --announce_rc
|
||||
|
||||
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||
# By default this is set in the project `.bazelrc` to `1`.
|
||||
test --flaky_test_attempts=3
|
||||
|
||||
# More details on failures
|
||||
build --verbose_failures=true
|
||||
|
||||
# CI supports colors but Bazel does not detect it.
|
||||
common --color=yes
|
||||
@@ -1,23 +0,0 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=/home/circleci/bazel_repository_cache
|
||||
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||
# Limit Bazel to consuming resources that fit in CircleCI "2xlarge+" class
|
||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||
build --local_cpu_resources=20
|
||||
build --local_ram_resources=40960
|
||||
|
||||
# All build executed remotely should be done using our RBE configuration.
|
||||
build:remote --google_default_credentials
|
||||
|
||||
build --config=remote
|
||||
@@ -1,17 +0,0 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to $env:ProgramData\bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Manually set the local resources used in windows CI runs
|
||||
build --local_ram_resources=120000
|
||||
build --local_cpu_resources=32
|
||||
|
||||
# All windows jobs run on master and should use http caching
|
||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||
build --remote_accept_cached=true
|
||||
build --remote_upload_local_results=true
|
||||
build --google_default_credentials
|
||||
@@ -1,16 +0,0 @@
|
||||
# This config is remaining in place to prevent pull requests failing because of CircleCI config missing.
|
||||
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
pass:
|
||||
docker:
|
||||
- image: cimg/base:2022.05
|
||||
steps:
|
||||
- run: echo "This too shall pass (always)"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
default_workflow:
|
||||
jobs:
|
||||
- pass
|
||||
@@ -1,76 +0,0 @@
|
||||
####################################################################################################
|
||||
# Helpers for defining environment variables for CircleCI.
|
||||
#
|
||||
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
|
||||
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
|
||||
# the default `bash` shell).
|
||||
#
|
||||
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
|
||||
####################################################################################################
|
||||
|
||||
# Set and print an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
|
||||
# visible to anyone through the CI logs.
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 "$2";
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
# Set (without printing) an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are secret, i.e. should not be visible to
|
||||
# everyone through the CI logs.
|
||||
#
|
||||
# Usage: `setSecretVar <name> <value>`
|
||||
function setSecretVar() {
|
||||
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
|
||||
# (Keep original shell options to restore at the end.)
|
||||
local -r originalShellOptions=$(set +o);
|
||||
set +x -eu -o pipefail;
|
||||
|
||||
local assignmentStatement="export $1=\"${2:-}\";"
|
||||
|
||||
echo "${assignmentStatement}" >> $BASH_ENV;
|
||||
eval "${assignmentStatement}"
|
||||
|
||||
# Restore original shell options.
|
||||
eval "$originalShellOptions";
|
||||
}
|
||||
|
||||
|
||||
# Create a function to set an environment variable, when called.
|
||||
#
|
||||
# Use this function for creating setter for public environment variables that require expensive or
|
||||
# time-consuming computations and may not be needed. When needed, you can call this function to set
|
||||
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
|
||||
#
|
||||
# Arguments:
|
||||
# - `<name>`: The name of the environment variable. The generated setter function will be
|
||||
# `setPublicVar_<name>`.
|
||||
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
|
||||
# executed lazily, it must be properly escaped. For example:
|
||||
# ```sh
|
||||
# # DO NOT do this:
|
||||
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
|
||||
#
|
||||
# # DO this isntead:
|
||||
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
|
||||
# ```
|
||||
#
|
||||
# Usage: `createPublicVarSetter <name> <code>`
|
||||
#
|
||||
# Example:
|
||||
# ```sh
|
||||
# createPublicVarSetter MY_VAR 'echo "FOO"';
|
||||
# echo $MY_VAR; # Not defined
|
||||
#
|
||||
# setPublicVar_MY_VAR;
|
||||
# source $BASH_ENV;
|
||||
# echo $MY_VAR; # FOO
|
||||
# ```
|
||||
function createPublicVarSetter() {
|
||||
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
cp "${PROJECT_ROOT}/.circleci/bazel.linux.rc" ".bazelrc.user";
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Variables
|
||||
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
|
||||
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||
####################################################################################################
|
||||
setPublicVar CI "$CI"
|
||||
setPublicVar PROJECT_ROOT "$projectDir";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
|
||||
# workflows of such builds).
|
||||
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
|
||||
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
|
||||
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
|
||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
|
||||
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define "lazy" PUBLIC environment variables for CircleCI.
|
||||
# (I.e. functions to set an environment variable when called.)
|
||||
####################################################################################################
|
||||
createPublicVarSetter CI_STABLE_BRANCH "\$(npm info @angular/core dist-tags.latest | sed -r 's/^\\s*([0-9]+\\.[0-9]+)\\.[0-9]+.*$/\\1.x/')";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SECRET environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SauceLabs environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar SAUCE_USERNAME "angular-framework";
|
||||
setSecretVar SAUCE_ACCESS_KEY "f4bf7c639c5a-c6bb-d6a4-a4b5-800aa111";
|
||||
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
|
||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||
|
||||
####################################################################################################
|
||||
# Create shell script in /tmp for Bazel actions to access CI envs without
|
||||
# busting the cache. Used by payload-size.sh script in integration tests.
|
||||
####################################################################################################
|
||||
readonly bazelVarEnv="/tmp/bazel-ci-env.sh"
|
||||
echo "# Setup by /.circle/env.sh" > $bazelVarEnv
|
||||
echo "export PROJECT_ROOT=\"${PROJECT_ROOT}\";" >> $bazelVarEnv
|
||||
echo "export CI_BRANCH=\"${CI_BRANCH}\";" >> $bazelVarEnv
|
||||
echo "export CI_BUILD_URL=\"${CI_BUILD_URL}\";" >> $bazelVarEnv
|
||||
echo "export CI_COMMIT=\"${CI_COMMIT}\";" >> $bazelVarEnv
|
||||
echo "export CI_PULL_REQUEST=\"${CI_PULL_REQUEST}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_NAME=\"${CI_REPO_NAME}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_OWNER=\"${CI_REPO_OWNER}\";" >> $bazelVarEnv
|
||||
echo "export CI_SECRET_PAYLOAD_FIREBASE_TOKEN=\"${CI_SECRET_PAYLOAD_FIREBASE_TOKEN}\";" >> $bazelVarEnv
|
||||
|
||||
####################################################################################################
|
||||
# Platform-specific environment setup (which can leverage the base variables from here)
|
||||
####################################################################################################
|
||||
|
||||
# Conditionally, load additional environment settings based on the current VM
|
||||
# operating system running. We detect Windows by checking for `%AppData%`.
|
||||
if [[ -n "${APPDATA}" ]]; then
|
||||
source ${projectDir}/.circleci/env.windows.sh
|
||||
else
|
||||
source ${projectDir}/.circleci/env.linux.sh
|
||||
fi
|
||||
@@ -1,13 +0,0 @@
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
cp "${PROJECT_ROOT}/.circleci/bazel.windows.rc" ".bazelrc.user";
|
||||
|
||||
# Override the `PATH` environment variable so that the windows-nvm NodeJS version
|
||||
# always has precedence over potential existing NodeJS versions from the image.
|
||||
setPublicVar PATH "/c/Program Files/nodejs/:$PATH"
|
||||
|
||||
# Expose the Bazelisk version. We need to run Bazelisk globally since Windows has problems launching
|
||||
# Bazel from a node modules directoy that might be modified by the Bazel Yarn install then.
|
||||
setPublicVar BAZELISK_VERSION \
|
||||
"$(cd ${PROJECT_ROOT}; node -p 'require("./package.json").devDependencies["@bazel/bazelisk"]')"
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Install bazel remote cache proxy
|
||||
# This is temporary until the feature is no longer experimental on CircleCI.
|
||||
# See remote cache documentation in /docs/BAZEL.md
|
||||
|
||||
set -u -e
|
||||
|
||||
readonly DOWNLOAD_URL="https://5-116431813-gh.circle-artifacts.com/0/pkg/bazel-remote-proxy-$(uname -s)_$(uname -m)"
|
||||
|
||||
curl --fail -o ~/bazel-remote-proxy "$DOWNLOAD_URL"
|
||||
chmod +x ~/bazel-remote-proxy
|
||||
@@ -1,6 +1,5 @@
|
||||
# Image metadata and config.
|
||||
# Ideally, the Node.js version should match what we use on CI.
|
||||
# See `executors > default-executor` in `.circleci/config.yml`.
|
||||
FROM cimg/node:18.13.0@sha256:45d0ee279f522c4562a464df71108104cc9b2187205333ffd0707d4f05589731
|
||||
|
||||
|
||||
@@ -12,7 +11,7 @@ LABEL name="Angular dev environment" \
|
||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||
|
||||
|
||||
# Switch to `root` (CircleCI images use `circleci` as the user).
|
||||
# Switch to `root`.
|
||||
USER root
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,9 +5,9 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/saucelabs@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Starting Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
|
||||
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4
|
||||
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -21,16 +21,16 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --full_build_adev --config=release
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -13,9 +13,9 @@ jobs:
|
||||
assistant_to_the_branch_manager:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
|
||||
id: comment-branch
|
||||
|
||||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
# Specify repository as the PR branch might be from a fork.
|
||||
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
+22
-24
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
@@ -41,13 +41,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -59,13 +59,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -76,32 +76,30 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --config=release
|
||||
# TODO: re-enable tests once the next release is shipped
|
||||
# Tests are broken because of https://github.com/angular/angular/issues/54858
|
||||
# - name: Run tests
|
||||
# run: yarn bazel test //adev/...
|
||||
- name: Run tests
|
||||
run: yarn bazel test //adev/...
|
||||
|
||||
publish-snapshots:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -113,7 +111,7 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -121,9 +119,9 @@ jobs:
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -160,7 +158,7 @@ jobs:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
@@ -173,11 +171,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
|
||||
@@ -12,14 +12,14 @@ jobs:
|
||||
labels:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -13,8 +13,8 @@ jobs:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -13,17 +13,17 @@ jobs:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/saucelabs@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Performance Tracking
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
id-token: 'write'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
list:
|
||||
timeout-minutes: 3
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
workflows: ${{ steps.workflows.outputs.workflows }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn -s install --frozen-lockfile
|
||||
- id: workflows
|
||||
run: echo "workflows=$(yarn -s ng-dev perf workflows --list)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
workflow:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
needs: list
|
||||
strategy:
|
||||
matrix:
|
||||
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn -s install --frozen-lockfile
|
||||
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
|
||||
# identity federation. This allows us to request short lived credentials on demand, rather than storing
|
||||
# credentials in secrets long term. More information can be found at:
|
||||
# https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform
|
||||
- uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # v2
|
||||
with:
|
||||
project_id: 'internal-200822'
|
||||
workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular'
|
||||
service_account: 'measures-uploader@internal-200822.iam.gserviceaccount.com'
|
||||
- run: yarn ng-dev perf workflows --name ${{ matrix.workflow }} --commit-sha ${{github.sha}}
|
||||
+21
-23
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
- name: Check code format
|
||||
run: yarn ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
|
||||
- name: Check Package Licenses
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
|
||||
|
||||
@@ -47,13 +47,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -65,13 +65,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -83,19 +83,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
run: yarn tsx ./scripts/build/build-packages-dist.mts
|
||||
- name: Archive build artifacts
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: pr-artifacts-${{ github.event.number }}
|
||||
path: dist/packages-dist/
|
||||
@@ -105,26 +105,24 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --config=release
|
||||
# TODO: re-enable tests once the next release is shipped
|
||||
# Tests are broken because of https://github.com/angular/angular/issues/54858
|
||||
# - name: Run tests
|
||||
# run: yarn bazel test //adev/...
|
||||
- name: Run tests
|
||||
run: yarn bazel test //adev/...
|
||||
|
||||
zone-js:
|
||||
runs-on:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -132,9 +130,9 @@ jobs:
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -171,7 +169,7 @@ jobs:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -47,6 +47,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
uses: github/codeql-action/upload-sarif@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
# Setting `persist-credentials: false` prevents the github-action account from being the
|
||||
# account that is attempted to be used for authentication, instead the remote is set to
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
env:
|
||||
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
branch-prefix: update-cli-help
|
||||
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
|
||||
|
||||
+2
-10
@@ -4,11 +4,8 @@
|
||||
/bazel-out
|
||||
/integration/bazel/bazel-*
|
||||
*.log
|
||||
/node_modules/
|
||||
|
||||
# CircleCI temporary file for cache key computation.
|
||||
# See `save_month_to_file` in `.circleci/config.yml`.
|
||||
month.txt
|
||||
node_modules/
|
||||
modules/ssr-benchmarks/node_modules/
|
||||
|
||||
# Include when developing application packages.
|
||||
pubspec.lock
|
||||
@@ -57,10 +54,5 @@ baseline.json
|
||||
# Husky
|
||||
.husky/_
|
||||
|
||||
|
||||
# Ignore cache created with the Angular CLI.
|
||||
.angular/
|
||||
|
||||
# Ignore AIO files, useful when changing branches
|
||||
aio/node_modules
|
||||
aio/out-tsc
|
||||
@@ -6,7 +6,7 @@ export const caretaker: CaretakerConfig = {
|
||||
githubQueries: [
|
||||
{
|
||||
name: 'Merge Queue',
|
||||
query: `is:pr is:open status:success label:"action: merge"`,
|
||||
query: `is:pr is:open label:"action: merge"`,
|
||||
},
|
||||
{
|
||||
name: 'Merge Assistance Queue',
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
workflows:
|
||||
build-adev:
|
||||
name: Build adev
|
||||
prepare:
|
||||
- bazel clean
|
||||
workflow:
|
||||
- bazel build //adev:build
|
||||
@@ -8,6 +8,7 @@ export const format: FormatConfig = {
|
||||
'matchers': [
|
||||
'**/*.{yaml,yml}',
|
||||
'**/*.{js,ts}',
|
||||
'devtools/**/*.{js,ts,html,scss}',
|
||||
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
|
||||
@@ -3,15 +3,7 @@
|
||||
"separateFilePatterns": ["packages/core/primitives/**"],
|
||||
"alwaysExternalFilePatterns": [
|
||||
"packages/*",
|
||||
"packages/bazel/*",
|
||||
"packages/bazel/src/*",
|
||||
"packages/bazel/src/api-extractor/**",
|
||||
"packages/bazel/src/builders/**",
|
||||
"packages/bazel/src/ng_module/**",
|
||||
"packages/bazel/src/ng_package/**",
|
||||
"packages/bazel/src/protractor/**",
|
||||
"packages/bazel/src/schematics/**",
|
||||
"packages/bazel/src/types_bundle/**",
|
||||
"packages/bazel/**",
|
||||
"packages/compiler-cli/linker/**",
|
||||
"packages/compiler-cli/src/ngtsc/sourcemaps/**",
|
||||
"packages/compiler-cli/src/ngtsc/testing/**",
|
||||
@@ -27,6 +19,7 @@
|
||||
"packages/localize/**",
|
||||
"packages/private/**",
|
||||
"packages/service-worker/**",
|
||||
"packages/ssr/BUILD.bazel",
|
||||
"packages/common/locales/generate-locales-tool/**",
|
||||
"packages/common/locales/index.bzl",
|
||||
"packages/http/**",
|
||||
|
||||
+2
-1
@@ -6,5 +6,6 @@
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"quoteProps": "preserve",
|
||||
"bracketSpacing": false
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
||||
+14
-2
@@ -57,7 +57,7 @@
|
||||
version: 3
|
||||
|
||||
availability:
|
||||
users_unavailable: ['atscott']
|
||||
users_unavailable: ['atscott', 'devversion']
|
||||
|
||||
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
||||
# used throughout the config.
|
||||
@@ -189,6 +189,7 @@ groups:
|
||||
- devversion
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Framework: Common
|
||||
@@ -208,6 +209,7 @@ groups:
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Framework: Http
|
||||
@@ -227,6 +229,7 @@ groups:
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Framework: Elements
|
||||
@@ -246,6 +249,7 @@ groups:
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Framework: Forms
|
||||
@@ -300,6 +304,7 @@ groups:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/platform-server/**/{*,.*}',
|
||||
'packages/ssr/**/{*,.*}',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
@@ -375,6 +380,7 @@ groups:
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Framework: Benchmarks
|
||||
@@ -536,6 +542,7 @@ groups:
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- josephperrott
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Docs: Packaging, Tooling, Releasing
|
||||
@@ -603,6 +610,7 @@ groups:
|
||||
- pkozlowski-opensource
|
||||
- MarkTechson
|
||||
- ~JeanMeche
|
||||
- kirjs
|
||||
|
||||
# =========================================================
|
||||
# Angular DevTools
|
||||
@@ -633,7 +641,6 @@ groups:
|
||||
- >
|
||||
contains_any_globs(files.exclude('.pullapprove.yml'), [
|
||||
'{*,.*}',
|
||||
'.circleci/**/{*,.*}',
|
||||
'.devcontainer/**/{*,.*}',
|
||||
'.github/**/{*,.*}',
|
||||
'.husky/**/{*,.*}',
|
||||
@@ -684,6 +691,8 @@ groups:
|
||||
conditions:
|
||||
- author in ["angular-robot"]
|
||||
reviewers:
|
||||
users:
|
||||
- ~alan-agius4
|
||||
teams:
|
||||
- framework-team
|
||||
|
||||
@@ -707,6 +716,7 @@ groups:
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
- ~iteriani
|
||||
- ~tbondwilkinson
|
||||
- ~rahatarmanahmed
|
||||
@@ -732,6 +742,7 @@ groups:
|
||||
- alxhub
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- kirjs
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
@@ -760,6 +771,7 @@ groups:
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- pkozlowski-opensource
|
||||
- kirjs
|
||||
|
||||
####################################################################################
|
||||
# Special Cases
|
||||
|
||||
+1430
-910
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,4 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
yarn-path ".yarn/releases/yarn-1.22.19.cjs"
|
||||
yarn-path ".yarn/releases/yarn-1.22.22.cjs"
|
||||
|
||||
+2
-2
@@ -64,8 +64,8 @@ config_setting(
|
||||
|
||||
nodejs_binary(
|
||||
name = "yarn_vendored",
|
||||
data = [".yarn/releases/yarn-1.22.19.cjs"],
|
||||
entry_point = ".yarn/releases/yarn-1.22.19.cjs",
|
||||
data = [".yarn/releases/yarn-1.22.22.cjs"],
|
||||
entry_point = ".yarn/releases/yarn-1.22.22.cjs",
|
||||
visibility = [
|
||||
"//integration:__subpackages__",
|
||||
"//modules/ssr-benchmarks:__subpackages__",
|
||||
|
||||
+278
-355
@@ -1,76 +1,275 @@
|
||||
<a name="18.2.9"></a>
|
||||
# 18.2.9 (2024-10-23)
|
||||
<a name="19.0.4"></a>
|
||||
# 19.0.4 (2024-12-12)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b0ab653965](https://github.com/angular/angular/commit/b0ab653965cf88fcfde23fc6a6cc78ce3121a30f) | fix | report when NgModule imports or exports itself ([#58231](https://github.com/angular/angular/pull/58231)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.10"></a>
|
||||
# 19.0.0-next.10 (2024-10-16)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Angular directives, components and pipes are now standalone by default. Specify `standalone: false` for declarations that are currently declared in `@NgModule`s. `ng update` for v19 will take care of this automatically.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0c9d721ac1](https://github.com/angular/angular/commit/0c9d721ac157662b2602cf0278ba4b79325f6882) | feat | add support for the `typeof` keyword in template expressions. ([#58183](https://github.com/angular/angular/pull/58183)) |
|
||||
| [a3cb530d84](https://github.com/angular/angular/commit/a3cb530d846bf4d15802b9f42b6dee5c9a3a08ee) | fix | handle typeof expressions in serializer ([#58217](https://github.com/angular/angular/pull/58217)) |
|
||||
| [ba4340875a](https://github.com/angular/angular/commit/ba4340875ac8e338ff1390fc7897eecc704ef7c5) | fix | ignore placeholder-only i18n messages ([#58154](https://github.com/angular/angular/pull/58154)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [231e6ff6ca](https://github.com/angular/angular/commit/231e6ff6ca0dae0289a03615bcaed29455c2d4b8) | feat | generate the HMR replacement module ([#58205](https://github.com/angular/angular/pull/58205)) |
|
||||
| [fb44323c51](https://github.com/angular/angular/commit/fb44323c51da5a86853aafd8a70ce0c25d6c0d7f) | fix | incorrectly generating relative file paths on case-insensitive platforms ([#58150](https://github.com/angular/angular/pull/58150)) |
|
||||
| [7e612171709](https://github.com/angular/angular/commit/7e6121717098462b4f53dc7212064243f2bcf024) | fix | consider pre-release versions when detecting feature support ([#59061](https://github.com/angular/angular/pull/59061)) |
|
||||
| [cd764a31152](https://github.com/angular/angular/commit/cd764a31152004d37aa621efc4990c090d86f1e0) | fix | error in unused standalone imports diagnostic ([#59064](https://github.com/angular/angular/pull/59064)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6b8c494d05](https://github.com/angular/angular/commit/6b8c494d05e545830fffb9626153480af6339ddc) | feat | flipping the default value for `standalone` to `true` ([#58169](https://github.com/angular/angular/pull/58169)) |
|
||||
| [3f1e7ab6ae](https://github.com/angular/angular/commit/3f1e7ab6ae984149004c449c04301b434ea64d2a) | feat | promote `outputFromObservable` & `outputToObservable` to stable. ([#58214](https://github.com/angular/angular/pull/58214)) |
|
||||
| [97c44a1d6c](https://github.com/angular/angular/commit/97c44a1d6c41be250d585fba5af2bc2af4d98ae2) | feat | Promote `takeUntilDestroyed` to stable. ([#58200](https://github.com/angular/angular/pull/58200)) |
|
||||
| [819ff034ce](https://github.com/angular/angular/commit/819ff034ce7cf014cedef60510b83af9340efa71) | feat | treat directives, pipes, components as by default ([#58229](https://github.com/angular/angular/pull/58229)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.9"></a>
|
||||
# 19.0.0-next.9 (2024-10-10)
|
||||
## Breaking Changes
|
||||
### compiler
|
||||
- `this.foo` property reads no longer refer to template context variables. If you intended to read the template variable, do not use `this.`.
|
||||
### core
|
||||
- The deprecated `factories` property in `KeyValueDiffers` has been removed.
|
||||
### localize
|
||||
- The `name` option in the `ng add @localize` schematic has been removed in favor of the `project` option.
|
||||
| [34ded10fa60](https://github.com/angular/angular/commit/34ded10fa6061a12531de8837a436cf0a1ac20b8) | fix | Fix a bug where snapshotted functions are being run twice if they return a nullish/falsey value. ([#59073](https://github.com/angular/angular/pull/59073)) |
|
||||
### platform-browser
|
||||
- The deprecated `BrowserModule.withServerTransition` method has been removed. Please use the `APP_ID` DI token to set the application id instead.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [09f589f000](https://github.com/angular/angular/commit/09f589f0006f4b428b675b83c12c0dc8ebb7e45f) | fix | `this.a` should always refer to class property `a` ([#55183](https://github.com/angular/angular/pull/55183)) |
|
||||
| [e8d1944999](https://github.com/angular/angular/commit/e8d1944999e1fdfbd67630d475334c0d7f41a0eb) | fix | add multiple :host and nested selectors support ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [82144b6d63](https://github.com/angular/angular/commit/82144b6d63d072d112d1a7f4dcc018a1d64bb994) | fix | allow combinators inside pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [292ea4714f](https://github.com/angular/angular/commit/292ea4714fb7e76cf1748d2f9059991e05c42574) | fix | fix comment typo ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [69529d8873](https://github.com/angular/angular/commit/69529d8873fbd7888ab68fddc6e7c654c5065764) | fix | fix parsing of the :host-context with pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [2374b87b64](https://github.com/angular/angular/commit/2374b87b643e0373f85cf126d4b01b2fff785f64) | fix | preserve attributes attached to :host selector ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [46a6324c82](https://github.com/angular/angular/commit/46a6324c82a41b69c16a4c8c9f3fc52d1ecf6917) | fix | scope :host-context inside pseudo selectors, do not decrease specificity ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [bc5f1175e9](https://github.com/angular/angular/commit/bc5f1175e9f39dfa2699c4de19ee9af4ce4b50d1) | fix | transform pseudo selectors correctly for the encapsulated view ([#57796](https://github.com/angular/angular/pull/57796)) |
|
||||
| [ae0802d63c5](https://github.com/angular/angular/commit/ae0802d63c50307791e8a5d765573836dfe89075) | fix | collect external component styles from server rendering ([#59031](https://github.com/angular/angular/pull/59031)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.3"></a>
|
||||
# 19.0.3 (2024-12-04)
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.2"></a>
|
||||
# 19.0.2 (2024-12-04)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8d8c03abc4](https://github.com/angular/angular/commit/8d8c03abc40099da268d7301f029954f3e3f1c90) | fix | defer symbols only used in types ([#58104](https://github.com/angular/angular/pull/58104)) |
|
||||
| [9f99196d23](https://github.com/angular/angular/commit/9f99196d239479bcba0b42a18a5155ed5a1764ff) | fix | account for multiple generated namespace imports in HMR ([#58924](https://github.com/angular/angular/pull/58924)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ee426c62f0](https://github.com/angular/angular/commit/ee426c62f07579ec7dc89ce9582972cc1e3471d4) | fix | allow signal write error ([#57973](https://github.com/angular/angular/pull/57973)) |
|
||||
| [67db4305c2](https://github.com/angular/angular/commit/67db4305c2261625fd54d284c29e94e26cb19488) | fix | clean up afterRender after it is executed ([#58119](https://github.com/angular/angular/pull/58119)) |
|
||||
| [656b5d3e78](https://github.com/angular/angular/commit/656b5d3e78004229a76488e0de1eb1d3508d8f6d) | fix | Re-assign error codes to be within core bounds (<1000) ([#53455](https://github.com/angular/angular/pull/53455)) |
|
||||
| [97fb86d331](https://github.com/angular/angular/commit/97fb86d3310ae891ba4d894a8d3479eda08bd4c2) | perf | set encapsulation to `None` for empty component styles ([#57130](https://github.com/angular/angular/pull/57130)) |
|
||||
| [c15ec36bd1](https://github.com/angular/angular/commit/c15ec36bd1dcff4c7c387337a5bcfd928994db2f) | refactor | remove deprecated `factories` Property in `KeyValueDiffers` ([#58064](https://github.com/angular/angular/pull/58064)) |
|
||||
| [4792db9a6d](https://github.com/angular/angular/commit/4792db9a6d3a7dc076c9b200cd31a53a4fd30683) | fix | Explicitly manage TracingSnapshot lifecycle and dispose of it once it's been used. ([#58929](https://github.com/angular/angular/pull/58929)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7b5bacc228](https://github.com/angular/angular/commit/7b5bacc2285803e6ac9691c2dae2361ddca9da9a) | fix | class content being deleted in some edge cases ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
| [d1cbdd6acb](https://github.com/angular/angular/commit/d1cbdd6acb228773e0fb33958978a14e12be178f) | fix | correctly strip away parameters surrounded by comments in inject migration ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
| [e17ff71c31](https://github.com/angular/angular/commit/e17ff71c318a1b32d5207b7516856f330f2bcf5a) | fix | don't migrate classes with parameters that can't be injected ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
| [7c5f990001](https://github.com/angular/angular/commit/7c5f990001c4aac9f48c5461421579c398295356) | fix | inject migration aggressively removing imports ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
| [4392ccedf9](https://github.com/angular/angular/commit/4392ccedf997e79486af7ad60172eea98ed3351f) | fix | inject migration dropping code if everything except super is removed ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
| [9cbebc6dda](https://github.com/angular/angular/commit/9cbebc6dda89d2fdfc52799aef1ea895dcac2d00) | fix | preserve type literals and tuples in inject migrations ([#58959](https://github.com/angular/angular/pull/58959)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f3c388ecda](https://github.com/angular/angular/commit/f3c388ecda5e836946031a554827cdaee9801734) | fix | remove peer dependency on animations ([#58997](https://github.com/angular/angular/pull/58997)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.1"></a>
|
||||
# 19.0.1 (2024-11-26)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fb1fa8b0fc](https://github.com/angular/angular/commit/fb1fa8b0fc04c9cfac6551ca27bee89dcd7c72ac) | fix | more accurate diagnostics for host binding parser errors ([#58870](https://github.com/angular/angular/pull/58870)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [502ee0e722](https://github.com/angular/angular/commit/502ee0e7221a9e7cfa0fa3bd92298d3b650a7713) | fix | correctly clear template HMR internal renderer cache ([#58724](https://github.com/angular/angular/pull/58724)) |
|
||||
| [99715104a1](https://github.com/angular/angular/commit/99715104a1a787c3899dfbfac6b44f28c7d24356) | fix | correctly perform lazy routes migration for components with additional decorators ([#58796](https://github.com/angular/angular/pull/58796)) |
|
||||
| [118803035f](https://github.com/angular/angular/commit/118803035f366acdffc577ec857b888f764bb338) | fix | Ensure _tick is always run within the TracingSnapshot. ([#58881](https://github.com/angular/angular/pull/58881)) |
|
||||
| [08b9452f01](https://github.com/angular/angular/commit/08b9452f012b2ef660f767c2f0a4bf86bb15bb61) | fix | Ensure resource sets an error ([#58855](https://github.com/angular/angular/pull/58855)) |
|
||||
| [84f45ea3ff](https://github.com/angular/angular/commit/84f45ea3ffe02003350c6c19fdafdc6f4d521ccb) | fix | make component id generation more stable between client and server builds ([#58813](https://github.com/angular/angular/pull/58813)) |
|
||||
| [d3491c7cee](https://github.com/angular/angular/commit/d3491c7cee3d110da1adb51f8047b4e1976ece71) | fix | Prevents race condition of cleanup for incremental hydration ([#58722](https://github.com/angular/angular/pull/58722)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4dfe5b6cef](https://github.com/angular/angular/commit/4dfe5b6cefd7901a466b37b660f8b3a051a06cb3) | fix | work around TypeScript 5.7 issue ([#58731](https://github.com/angular/angular/pull/58731)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a983865bff](https://github.com/angular/angular/commit/a983865bffa828a982ef7e56204924d9c2989ead) | fix | add fix for individual unused imports ([#58719](https://github.com/angular/angular/pull/58719)) |
|
||||
| [e6e7a4e22b](https://github.com/angular/angular/commit/e6e7a4e22b0a654808e5eb88a30cd6effa383332) | fix | allow fixes to run without template info ([#58719](https://github.com/angular/angular/pull/58719)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5ce10264a4](https://github.com/angular/angular/commit/5ce10264a434ffc8e31cdc68208d2c3c7f8378ed) | fix | fix provide-initializer migration when using useFactory ([#58518](https://github.com/angular/angular/pull/58518)) |
|
||||
| [d4f5c85f60](https://github.com/angular/angular/commit/d4f5c85f60133550303d59b3f9e3e34f14ca63ce) | fix | handle parameters with initializers in inject migration ([#58769](https://github.com/angular/angular/pull/58769)) |
|
||||
| [a6d2d2dc10](https://github.com/angular/angular/commit/a6d2d2dc104608f14c3850b21bc23ba75ca04e4d) | fix | Mark hoisted properties as removed in inject migration ([#58804](https://github.com/angular/angular/pull/58804)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0"></a>
|
||||
# 19.0.0 (2024-11-19)
|
||||
|
||||
Blog post: https://blog.angular.dev/meet-angular-v19-7b29dfd05b84
|
||||
|
||||
## Breaking Changes
|
||||
### compiler
|
||||
- `this.foo` property reads no longer refer to template context variables. If you intended to read the template variable, do not use `this.`.
|
||||
- changes to CSS selectors parsing where introduced, mainly to: pseudo selectors `:where()` and `:is()`,
|
||||
parsing of `:host` and `host-context`, parsing selectors within pseudo selector arguments (for instance comma separated selectors).
|
||||
These changes could lead to a different specificity of the resulting selectors and/or previously broken selectors being applied now,
|
||||
for example `:where(:host)` used to transform to `:where()[ng-host]` and is being `:where([ng-host])` now. Unlike the previous outcome,
|
||||
the new result can target elements and therefore could lead to breakages.
|
||||
### core
|
||||
- Angular directives, components and pipes are now standalone by default.
|
||||
* Specify `standalone: false` for declarations that are currently declared in modules.
|
||||
* `ng update` for v19 will take care of this automatically.
|
||||
- TypeScript versions less than 5.5 are no longer supported.
|
||||
- Timing changes for `effect` API (in developer preview):
|
||||
|
||||
* effects which are triggered outside of change detection run as part of
|
||||
the change detection process instead of as a microtask. Depending on the
|
||||
specifics of application/test setup, this can result in them executing
|
||||
earlier or later (or requiring additional test steps to trigger; see below
|
||||
examples).
|
||||
|
||||
* effects which are triggered during change detection (e.g. by input
|
||||
signals) run _earlier_, before the component's template.
|
||||
|
||||
- `ExperimentalPendingTasks` has been renamed to `PendingTasks`.
|
||||
- The `autoDetect` feature of `ComponentFixture` will now
|
||||
attach the fixture to the `ApplicationRef`. As a result, errors during
|
||||
automatic change detection of the fixture be reported to the `ErrorHandler`.
|
||||
This change may cause custom error handlers to observe new failures that were previously unreported.
|
||||
- `createComponent` will now render default fallback with empty `projectableNodes`.
|
||||
|
||||
* When passing an empty array to `projectableNodes` in the `createComponent` API, the default fallback content
|
||||
of the `ng-content` will be rendered if present. To prevent rendering the default content, pass `document.createTextNode('')` as a `projectableNode`.
|
||||
|
||||
```ts
|
||||
// The first ng-content will render the default fallback content if present
|
||||
createComponent(MyComponent. { projectableNodes: [[], [secondNode]] });
|
||||
|
||||
// To prevent projecting the default fallback content:
|
||||
createComponent(MyComponent. { projectableNodes: [[document.createTextNode('')], [secondNode]] });
|
||||
|
||||
```
|
||||
- Errors that are thrown during `ApplicationRef.tick`
|
||||
will now be rethrown when using `TestBed`. These errors should be
|
||||
resolved by ensuring the test environment is set up correctly to
|
||||
complete change detection successfully. There are two alternatives to
|
||||
catch the errors:
|
||||
|
||||
* Instead of waiting for automatic change detection to happen, trigger
|
||||
it synchronously and expect the error. For example, a jasmine test
|
||||
could write `expect(() => TestBed.inject(ApplicationRef).tick()).toThrow()`
|
||||
* `TestBed` will reject any outstanding `ComponentFixture.whenStable` promises. A jasmine test,
|
||||
for example, could write `expectAsync(fixture.whenStable()).toBeRejected()`.
|
||||
|
||||
As a last resort, you can configure errors to _not_ be rethrown by
|
||||
setting `rethrowApplicationErrors` to `false` in `TestBed.configureTestingModule`.
|
||||
- The timers that are used for zone coalescing and hybrid
|
||||
mode scheduling (which schedules an application state synchronization
|
||||
when changes happen outside the Angular zone) will now run in the zone
|
||||
above Angular rather than the root zone. This will mostly affect tests
|
||||
which use `fakeAsync`: these timers will now be visible to `fakeAsync`
|
||||
and can be affected by `tick` or `flush`.
|
||||
- The deprecated `factories` property in `KeyValueDiffers` has been removed.
|
||||
### elements
|
||||
- as part of switching away from custom CD behavior to the
|
||||
hybrid scheduler, timing of change detection around custom elements has
|
||||
changed subtly. These changes make elements more efficient, but can cause
|
||||
tests which encoded assumptions about how or when elements would be checked
|
||||
to require updating.
|
||||
### localize
|
||||
- The `name` option in the `ng add `@localize`` schematic has been removed in favor of the `project` option.
|
||||
### platform-browser
|
||||
- The deprecated `BrowserModule.withServerTransition` method has been removed. Please use the `APP_ID` DI token to set the application id instead.
|
||||
### router
|
||||
- The `Router.errorHandler` property has been removed.
|
||||
Adding an error handler should be configured in either
|
||||
`withNavigationErrorHandler` with `provideRouter` or the `errorHandler`
|
||||
property in the extra options of `RouterModule.forRoot`. In addition,
|
||||
the error handler cannot be used to change the return value of the
|
||||
router navigation promise or prevent it from rejecting. Instead, if you
|
||||
want to prevent the promise from rejecting, use `resolveNavigationPromiseOnError`.
|
||||
- The return type of the `Resolve` interface now includes
|
||||
`RedirectCommand`.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [24c6373820](https://github.com/angular/angular/commit/24c6373820231faf9d012a2e4d7ea945d3e8513b) | feat | add optional rounded transform support in cloudinary image loader ([#55364](https://github.com/angular/angular/pull/55364)) |
|
||||
| [50f08e6c4b](https://github.com/angular/angular/commit/50f08e6c4bf1caeeb08d3505ce7fabd466b9c76b) | feat | automatically use sizes auto in NgOptimizedImage ([#57479](https://github.com/angular/angular/pull/57479)) |
|
||||
| [13c13067bc](https://github.com/angular/angular/commit/13c13067bc3ed50cb80b0a86e62655448adb3051) | feat | disable keyvalue sorting using null compareFn ([#57487](https://github.com/angular/angular/pull/57487)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a2e4ee0cb3](https://github.com/angular/angular/commit/a2e4ee0cb3d40cadc05e28d58b06853973944456) | feat | add diagnostic for unused standalone imports ([#57605](https://github.com/angular/angular/pull/57605)) |
|
||||
| [0c9d721ac1](https://github.com/angular/angular/commit/0c9d721ac157662b2602cf0278ba4b79325f6882) | feat | add support for the `typeof` keyword in template expressions. ([#58183](https://github.com/angular/angular/pull/58183)) |
|
||||
| [09f589f000](https://github.com/angular/angular/commit/09f589f0006f4b428b675b83c12c0dc8ebb7e45f) | fix | `this.a` should always refer to class property `a` ([#55183](https://github.com/angular/angular/pull/55183)) |
|
||||
| [98804fd4be](https://github.com/angular/angular/commit/98804fd4beb6292f5a50ce728424fdb33c47f654) | fix | add more specific matcher for hydrate never block ([#58360](https://github.com/angular/angular/pull/58360)) |
|
||||
| [b25121ee4a](https://github.com/angular/angular/commit/b25121ee4aba427954fef074a967b9332654be84) | fix | avoid having to duplicate core environment ([#58444](https://github.com/angular/angular/pull/58444)) |
|
||||
| [560282aa9b](https://github.com/angular/angular/commit/560282aa9b3204ad8311017905beed63072c7303) | fix | control flow nodes with root at the end projected incorrectly ([#58607](https://github.com/angular/angular/pull/58607)) |
|
||||
| [2be161d015](https://github.com/angular/angular/commit/2be161d015ce6bab0142b6e6c34a8ede6341f627) | fix | fix `:host` parsing in pseudo-selectors ([#58681](https://github.com/angular/angular/pull/58681)) |
|
||||
| [806a61b5a6](https://github.com/angular/angular/commit/806a61b5a619d98c0226ba6a566b1562f6e16e5a) | fix | fix multiline selectors ([#58681](https://github.com/angular/angular/pull/58681)) |
|
||||
| [a3cb530d84](https://github.com/angular/angular/commit/a3cb530d846bf4d15802b9f42b6dee5c9a3a08ee) | fix | handle typeof expressions in serializer ([#58217](https://github.com/angular/angular/pull/58217)) |
|
||||
| [ba4340875a](https://github.com/angular/angular/commit/ba4340875ac8e338ff1390fc7897eecc704ef7c5) | fix | ignore placeholder-only i18n messages ([#58154](https://github.com/angular/angular/pull/58154)) |
|
||||
| [e5d3abb298](https://github.com/angular/angular/commit/e5d3abb29842412f82a67562aceff245d493ec53) | fix | resolve `:host:host-context(.foo)` ([#58681](https://github.com/angular/angular/pull/58681)) |
|
||||
| [80f56954ce](https://github.com/angular/angular/commit/80f56954cecf763e36bdcfbbd592a82d693eeef7) | fix | transform chained pseudo-selectors ([#58681](https://github.com/angular/angular/pull/58681)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d9687f43dd](https://github.com/angular/angular/commit/d9687f43dd2ccfcf7dd3ee4f9066ce727f3224c6) | feat | 'strictStandalone' flag enforces standalone ([#57935](https://github.com/angular/angular/pull/57935)) |
|
||||
| [9e87593055](https://github.com/angular/angular/commit/9e87593055a5314a67090bd15d5552c23b538050) | feat | ensure template style elements are preprocessed as inline styles ([#57429](https://github.com/angular/angular/pull/57429)) |
|
||||
| [231e6ff6ca](https://github.com/angular/angular/commit/231e6ff6ca0dae0289a03615bcaed29455c2d4b8) | feat | generate the HMR replacement module ([#58205](https://github.com/angular/angular/pull/58205)) |
|
||||
| [dbe612f2cd](https://github.com/angular/angular/commit/dbe612f2cd59adecdab3abb270b014c4b26e472c) | fix | disable standalone by default on older versions of Angular ([#58405](https://github.com/angular/angular/pull/58405)) |
|
||||
| [d4d76ead80](https://github.com/angular/angular/commit/d4d76ead802837bc6cc7908bc9ebfefa73eb9969) | fix | do not fail fatal when references to non-existent module are discovered ([#58515](https://github.com/angular/angular/pull/58515)) |
|
||||
| [33fe252c58](https://github.com/angular/angular/commit/33fe252c588ee94d6ef99e8070d35c483ec24fda) | fix | do not report unused declarations coming from an imported array ([#57940](https://github.com/angular/angular/pull/57940)) |
|
||||
| [fb44323c51](https://github.com/angular/angular/commit/fb44323c51da5a86853aafd8a70ce0c25d6c0d7f) | fix | incorrectly generating relative file paths on case-insensitive platforms ([#58150](https://github.com/angular/angular/pull/58150)) |
|
||||
| [22cd6869ef](https://github.com/angular/angular/commit/22cd6869ef453c342b206f84e857ef6c34922fa5) | fix | make the unused imports diagnostic easier to read ([#58468](https://github.com/angular/angular/pull/58468)) |
|
||||
| [9bbb01c85e](https://github.com/angular/angular/commit/9bbb01c85e763b0457456a2393a834db15008671) | fix | report individual diagnostics for unused imports ([#58589](https://github.com/angular/angular/pull/58589)) |
|
||||
| [4716c3b966](https://github.com/angular/angular/commit/4716c3b9660b01f4ef3642fb774270b7f4a13d1a) | perf | reduce duplicate component style resolution ([#57502](https://github.com/angular/angular/pull/57502)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6ea8e1e9aa](https://github.com/angular/angular/commit/6ea8e1e9aae028572873cf97aa1949c8153f458f) | feat | Add a schematics to migrate to `standalone: false`. ([#57643](https://github.com/angular/angular/pull/57643)) |
|
||||
| [3ebe6b4ad4](https://github.com/angular/angular/commit/3ebe6b4ad401337e18619edc34477ae98226fa3e) | feat | Add async `run` method on `ExperimentalPendingTasks` ([#56546](https://github.com/angular/angular/pull/56546)) |
|
||||
| [69fc5ae922](https://github.com/angular/angular/commit/69fc5ae9229b872a9ad70eb920087af2a378fead) | feat | Add incremental hydration public api ([#58249](https://github.com/angular/angular/pull/58249)) |
|
||||
| [8ebbae88ca](https://github.com/angular/angular/commit/8ebbae88ca48b8aa78cd85deedbed19d44b8227e) | feat | Add rxjs operator prevent app stability until an event ([#56533](https://github.com/angular/angular/pull/56533)) |
|
||||
| [19edf2c057](https://github.com/angular/angular/commit/19edf2c057f7587bc16812685d31a556521ad414) | feat | add syntactic sugar for initializers ([#53152](https://github.com/angular/angular/pull/53152)) |
|
||||
| [c93b510f9b](https://github.com/angular/angular/commit/c93b510f9b2e23aa7a3848a04c05249fde14a9b1) | feat | allow passing `undefined` without needing to include it in the type argument of `input` ([#57621](https://github.com/angular/angular/pull/57621)) |
|
||||
| [ab25a192ba](https://github.com/angular/angular/commit/ab25a192ba664863ad68d224b9b2df78da22769a) | feat | allow running output migration on a subset of paths ([#58299](https://github.com/angular/angular/pull/58299)) |
|
||||
| [fc59e2a7b7](https://github.com/angular/angular/commit/fc59e2a7b7afa491a5ea740284a742574805eb36) | feat | change effect() execution timing & no-op `allowSignalWrites` ([#57874](https://github.com/angular/angular/pull/57874)) |
|
||||
| [8bcc663a53](https://github.com/angular/angular/commit/8bcc663a53888717cdf4ce0c23404caa00abb1b2) | feat | drop support for TypeScript 5.4 ([#57577](https://github.com/angular/angular/pull/57577)) |
|
||||
| [18d8d44b1f](https://github.com/angular/angular/commit/18d8d44b1f3d56a4eda68f2cafded7529e08d0f1) | feat | experimental `resource()` API for async dependencies ([#58255](https://github.com/angular/angular/pull/58255)) |
|
||||
| [9762b24b5e](https://github.com/angular/angular/commit/9762b24b5e8d7ab3ed2321959492a77b01d8ae57) | feat | experimental impl of `rxResource()` ([#58255](https://github.com/angular/angular/pull/58255)) |
|
||||
| [6b8c494d05](https://github.com/angular/angular/commit/6b8c494d05e545830fffb9626153480af6339ddc) | feat | flipping the default value for `standalone` to `true` ([#58169](https://github.com/angular/angular/pull/58169)) |
|
||||
| [e6e5d29e83](https://github.com/angular/angular/commit/e6e5d29e830a0a74d7677d5f2345f29391064853) | feat | initial version of the output migration ([#57604](https://github.com/angular/angular/pull/57604)) |
|
||||
| [be2e49639b](https://github.com/angular/angular/commit/be2e49639bda831831ad62d49253db942a83fd46) | feat | introduce `afterRenderEffect` ([#57549](https://github.com/angular/angular/pull/57549)) |
|
||||
| [ec386e7f12](https://github.com/angular/angular/commit/ec386e7f1216e0047392e75ab686b310b073eb42) | feat | introduce debugName optional arg to framework signal functions ([#57073](https://github.com/angular/angular/pull/57073)) |
|
||||
| [8311f00faa](https://github.com/angular/angular/commit/8311f00faaf282d1a5b1ddca29247a2fba94a692) | feat | introduce the reactive linkedSignal ([#58189](https://github.com/angular/angular/pull/58189)) |
|
||||
| [1b1519224d](https://github.com/angular/angular/commit/1b1519224d10c1cd25d05d7b958772b9adee1e1a) | feat | mark input, output and model APIs as stable ([#57804](https://github.com/angular/angular/pull/57804)) |
|
||||
| [a7eff3ffaa](https://github.com/angular/angular/commit/a7eff3ffaaecbcb3034130d475ff7b4e41a1e1cc) | feat | mark signal-based query APIs as stable ([#57921](https://github.com/angular/angular/pull/57921)) |
|
||||
| [a1f229850a](https://github.com/angular/angular/commit/a1f229850ad36da009f772faa831da173a60268c) | feat | migrate ExperimentalPendingTasks to PendingTasks ([#57533](https://github.com/angular/angular/pull/57533)) |
|
||||
| [3f1e7ab6ae](https://github.com/angular/angular/commit/3f1e7ab6ae984149004c449c04301b434ea64d2a) | feat | promote `outputFromObservable` & `outputToObservable` to stable. ([#58214](https://github.com/angular/angular/pull/58214)) |
|
||||
| [97c44a1d6c](https://github.com/angular/angular/commit/97c44a1d6c41be250d585fba5af2bc2af4d98ae2) | feat | Promote `takeUntilDestroyed` to stable. ([#58200](https://github.com/angular/angular/pull/58200)) |
|
||||
| [e5adf92965](https://github.com/angular/angular/commit/e5adf9296595644e415d5c147df08890be01ba77) | feat | stabilize `@let` syntax ([#57813](https://github.com/angular/angular/pull/57813)) |
|
||||
| [b063468027](https://github.com/angular/angular/commit/b0634680272569501146bb7a9cdfe53033e25971) | feat | support TypeScript 5.6 ([#57424](https://github.com/angular/angular/pull/57424)) |
|
||||
| [819ff034ce](https://github.com/angular/angular/commit/819ff034ce7cf014cedef60510b83af9340efa71) | feat | treat directives, pipes, components as by default ([#58229](https://github.com/angular/angular/pull/58229)) |
|
||||
| [ee426c62f0](https://github.com/angular/angular/commit/ee426c62f07579ec7dc89ce9582972cc1e3471d4) | fix | allow signal write error ([#57973](https://github.com/angular/angular/pull/57973)) |
|
||||
| [c095679f92](https://github.com/angular/angular/commit/c095679f927ad67fec6c18cb140ea550ae02639e) | fix | avoid breaking change with apps using rxjs 6.x ([#58341](https://github.com/angular/angular/pull/58341)) |
|
||||
| [71ee81af2c](https://github.com/angular/angular/commit/71ee81af2c4c5854a54cf94a48d5829da41878a7) | fix | clean up event contract once hydration is done ([#58174](https://github.com/angular/angular/pull/58174)) |
|
||||
| [f03d274e87](https://github.com/angular/angular/commit/f03d274e87c919514a70d02c0699523957de7386) | fix | ComponentFixture autoDetect feature works like production ([#55228](https://github.com/angular/angular/pull/55228)) |
|
||||
| [950a5540f1](https://github.com/angular/angular/commit/950a5540f15118e7360506ad82ec9dab5a11f789) | fix | Ensure the `ViewContext` is retained after closure minification ([#57903](https://github.com/angular/angular/pull/57903)) |
|
||||
| [7b1e5be20b](https://github.com/angular/angular/commit/7b1e5be20b99c88246c6be78a4dcd64eb55cee1a) | fix | fallback to default ng-content with empty projectable nodes. ([#57480](https://github.com/angular/angular/pull/57480)) |
|
||||
| [0300dd2e18](https://github.com/angular/angular/commit/0300dd2e18f064f2f57f7371e0dc5c01218b5019) | fix | Fix fixture.detectChanges with autoDetect disabled and zoneless ([#57416](https://github.com/angular/angular/pull/57416)) |
|
||||
| [5fe57d4fbb](https://github.com/angular/angular/commit/5fe57d4fbb578c35a8e8ef037ae8c19c8a0e901c) | fix | fixes issues with control flow and incremental hydration ([#58644](https://github.com/angular/angular/pull/58644)) |
|
||||
| [51933ef5a6](https://github.com/angular/angular/commit/51933ef5a6ce62df37945fa22e87e3868288e318) | fix | prevent errors on contract cleanup ([#58614](https://github.com/angular/angular/pull/58614)) |
|
||||
| [fd7716440b](https://github.com/angular/angular/commit/fd7716440bec8f7ed042d79bafacf3048d45cd47) | fix | Prevents trying to trigger incremental hydration on CSR ([#58366](https://github.com/angular/angular/pull/58366)) |
|
||||
| [656b5d3e78](https://github.com/angular/angular/commit/656b5d3e78004229a76488e0de1eb1d3508d8f6d) | fix | Re-assign error codes to be within core bounds (<1000) ([#53455](https://github.com/angular/angular/pull/53455)) |
|
||||
| [6e0af6dbbb](https://github.com/angular/angular/commit/6e0af6dbbbe5e9a9e2e5809ada0b7b5a7e456402) | fix | resolve forward-referenced host directives during directive matching ([#58492](https://github.com/angular/angular/pull/58492)) |
|
||||
| [468d3fb9b1](https://github.com/angular/angular/commit/468d3fb9b1c3dd6dff86afcb6d8f89cc4c29b24b) | fix | rethrow errors during ApplicationRef.tick in TestBed ([#57200](https://github.com/angular/angular/pull/57200)) |
|
||||
| [226a67dabb](https://github.com/angular/angular/commit/226a67dabba90a488ad09ce7bb026b8883c90d4a) | fix | Schedulers run in zone above Angular rather than root ([#57553](https://github.com/angular/angular/pull/57553)) |
|
||||
| [97fb86d331](https://github.com/angular/angular/commit/97fb86d3310ae891ba4d894a8d3479eda08bd4c2) | perf | set encapsulation to `None` for empty component styles ([#57130](https://github.com/angular/angular/pull/57130)) |
|
||||
| [c15ec36bd1](https://github.com/angular/angular/commit/c15ec36bd1dcff4c7c387337a5bcfd928994db2f) | refactor | remove deprecated `factories` Property in `KeyValueDiffers` ([#58064](https://github.com/angular/angular/pull/58064)) |
|
||||
### elements
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fe5c4e086a](https://github.com/angular/angular/commit/fe5c4e086add655bf53315d71b0736ff758c7199) | fix | support `output()`-shaped outputs ([#57535](https://github.com/angular/angular/pull/57535)) |
|
||||
| [0cebfd7462](https://github.com/angular/angular/commit/0cebfd7462c6a7c6c3b0d66720c436a4b0eea19d) | fix | switch to `ComponentRef.setInput` & remove custom scheduler ([#56728](https://github.com/angular/angular/pull/56728)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3e7d724037](https://github.com/angular/angular/commit/3e7d724037cca4d256b1442eda20d6c6ad91d279) | feat | add ability to clear a FormRecord ([#50750](https://github.com/angular/angular/pull/50750)) |
|
||||
| [18b6f3339f](https://github.com/angular/angular/commit/18b6f3339f46b37ee67fce2fa8a900cc73b2f23c) | fix | fix FormRecord type inference ([#50750](https://github.com/angular/angular/pull/50750)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4b9accdf16](https://github.com/angular/angular/commit/4b9accdf166f3990b3706de83ada15937fe786e2) | feat | promote `withRequestsMadeViaParent` to stable. ([#58221](https://github.com/angular/angular/pull/58221)) |
|
||||
| [057cf7fb6b](https://github.com/angular/angular/commit/057cf7fb6bd2ac37a7a30d3a143e6737e386247f) | fix | preserve all headers from Headers object ([#57802](https://github.com/angular/angular/pull/57802)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8da9fb49b5](https://github.com/angular/angular/commit/8da9fb49b54e50de2d028691f73fb773def62ecd) | feat | add code fix for unused standalone imports ([#57605](https://github.com/angular/angular/pull/57605)) |
|
||||
| [1f067f4507](https://github.com/angular/angular/commit/1f067f4507b6e908fe991d5de0dc4d3a627ab2f9) | feat | add code reactoring action to migrate `@Input` to signal-input ([#57214](https://github.com/angular/angular/pull/57214)) |
|
||||
| [56ee47f2ec](https://github.com/angular/angular/commit/56ee47f2ec6e983e2ffdf59476ab29a92590811e) | feat | allow code refactorings to compute edits asynchronously ([#57214](https://github.com/angular/angular/pull/57214)) |
|
||||
| [bc83fc1e2e](https://github.com/angular/angular/commit/bc83fc1e2ebac1a99b6e8ed63cea48f48dd7c863) | feat | support converting to signal queries in VSCode extension ([#58106](https://github.com/angular/angular/pull/58106)) |
|
||||
| [5c4305f024](https://github.com/angular/angular/commit/5c4305f0248ac3cc1adc76aebd3ef8af041039dc) | feat | support migrating full classes to signal inputs in VSCode ([#57975](https://github.com/angular/angular/pull/57975)) |
|
||||
| [6342befff8](https://github.com/angular/angular/commit/6342befff8ee491f37e8912cccb0099bbbf01042) | feat | support migrating full classes to signal queries ([#58263](https://github.com/angular/angular/pull/58263)) |
|
||||
| [7ecfd89592](https://github.com/angular/angular/commit/7ecfd8959219b6e2ec19e1244a6694711daf1782) | fix | The suppress diagnostics option should work for external templates ([#57873](https://github.com/angular/angular/pull/57873)) |
|
||||
### localize
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
@@ -78,22 +277,47 @@
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dff4de0f75](https://github.com/angular/angular/commit/dff4de0f75741bc629462bb8da833b876c754453) | feat | add a combined migration for all signals APIs ([#58259](https://github.com/angular/angular/pull/58259)) |
|
||||
| [b6bc93803c](https://github.com/angular/angular/commit/b6bc93803c246d47aac0d2d8619271d42b249a4a) | feat | add schematic to migrate to signal queries ([#58032](https://github.com/angular/angular/pull/58032)) |
|
||||
| [2bfc64daf1](https://github.com/angular/angular/commit/2bfc64daf1cad9be8099759e8de7a361555ad5d1) | feat | expose output as function migration ([#58299](https://github.com/angular/angular/pull/58299)) |
|
||||
| [59fe9bc772](https://github.com/angular/angular/commit/59fe9bc77236f1374427a851e55b0fa5216d9cf9) | feat | introduce signal input migration as `ng generate` schematic ([#57805](https://github.com/angular/angular/pull/57805)) |
|
||||
| [90c7ec39a0](https://github.com/angular/angular/commit/90c7ec39a06e5c14711e0a42e2d6a478cde2b9cc) | fix | inject migration always inserting generated variables before super call ([#58393](https://github.com/angular/angular/pull/58393)) |
|
||||
| [7a65cdd911](https://github.com/angular/angular/commit/7a65cdd911cbbf22445c916fc754d3a3304bc5fe) | fix | inject migration not inserting generated code after super call in some cases ([#58393](https://github.com/angular/angular/pull/58393)) |
|
||||
| [c1aa411cf1](https://github.com/angular/angular/commit/c1aa411cf13259d991c8f224a2bafc3e9763fe8d) | fix | properly resolve tsconfig paths on windows ([#58137](https://github.com/angular/angular/pull/58137)) |
|
||||
| [e26797b38e](https://github.com/angular/angular/commit/e26797b38efe0ac813601c10581f34b7591954c1) | fix | replace removed NgModules in tests with their exports ([#58627](https://github.com/angular/angular/pull/58627)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c36a1c023b](https://github.com/angular/angular/commit/c36a1c023b34f9b2056e1bef6364787e8495bfad) | fix | correctly add external stylesheets to ShadowDOM components ([#58482](https://github.com/angular/angular/pull/58482)) |
|
||||
| [5c61f46409](https://github.com/angular/angular/commit/5c61f46409855bb8fe66d71a9c16c00753032987) | refactor | remove deprecated `BrowserModule.withServerTransition` method ([#58062](https://github.com/angular/angular/pull/58062)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9e82559de4](https://github.com/angular/angular/commit/9e82559de4e99a1aedf645a05b01fc08d3f4b1b1) | fix | destroy `PlatformRef` when error happens during the `bootstrap()` phase ([#58112](https://github.com/angular/angular/pull/58112)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f271021e19](https://github.com/angular/angular/commit/f271021e190ede70bfd181d46f0a468a8e7fa144) | feat | Add `routerOutletData` input to `RouterOutlet` directive ([#57051](https://github.com/angular/angular/pull/57051)) |
|
||||
| [b2790813a6](https://github.com/angular/angular/commit/b2790813a62e4dfdd77e27d1bb82201788476d06) | fix | Align RouterModule.forRoot errorHandler with provider error handler ([#57050](https://github.com/angular/angular/pull/57050)) |
|
||||
| [a49c35ec76](https://github.com/angular/angular/commit/a49c35ec769461b9eb490719f0aa3e5aea8e243f) | fix | remove setter for `injector` on `OutletContext` ([#58343](https://github.com/angular/angular/pull/58343)) |
|
||||
| [7436d3180e](https://github.com/angular/angular/commit/7436d3180ea5ad2c0b58d920bd45f8641a14cc8d) | fix | Update Resolve interface to include RedirectCommand like ResolveFn ([#57309](https://github.com/angular/angular/pull/57309)) |
|
||||
### service-worker
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8ddce80a0b](https://github.com/angular/angular/commit/8ddce80a0bab4ebbd0f7db1c85ee27e4f0249db9) | feat | allow specifying maxAge for entire application ([#49601](https://github.com/angular/angular/pull/49601)) |
|
||||
| [1479af978c](https://github.com/angular/angular/commit/1479af978cd2bbe4ee9f1ca9682684b8e5135fa7) | feat | finish implementation of refreshAhead feature ([#53356](https://github.com/angular/angular/pull/53356)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.9"></a>
|
||||
# 18.2.9 (2024-10-23)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b0ab653965](https://github.com/angular/angular/commit/b0ab653965cf88fcfde23fc6a6cc78ce3121a30f) | fix | report when NgModule imports or exports itself ([#58231](https://github.com/angular/angular/pull/58231)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.8"></a>
|
||||
# 18.2.8 (2024-10-10)
|
||||
### compiler
|
||||
@@ -121,45 +345,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.8"></a>
|
||||
# 19.0.0-next.8 (2024-10-02)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c3115b882e](https://github.com/angular/angular/commit/c3115b882ebbe4f971e1f06bb1ce2cdf43327bb0) | fix | execute checks and remove placeholder when image is already loaded ([#55444](https://github.com/angular/angular/pull/55444)) |
|
||||
| [b7bd429951](https://github.com/angular/angular/commit/b7bd42995130f80ea74ed5b905446f09a98a9480) | fix | prevent warning about oversize image twice ([#58021](https://github.com/angular/angular/pull/58021)) |
|
||||
| [e8b2d5fad8](https://github.com/angular/angular/commit/e8b2d5fad8aece3b2e3f4a7ed1356642f68ee275) | fix | skip checking whether SVGs are oversized ([#57966](https://github.com/angular/angular/pull/57966)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d9687f43dd](https://github.com/angular/angular/commit/d9687f43dd2ccfcf7dd3ee4f9066ce727f3224c6) | feat | 'strictStandalone' flag enforces standalone ([#57935](https://github.com/angular/angular/pull/57935)) |
|
||||
| [39ccaf4cc4](https://github.com/angular/angular/commit/39ccaf4cc457894a3cf0455349e1c016a858751a) | fix | correctly get the type of nested function call expressions ([#57010](https://github.com/angular/angular/pull/57010)) |
|
||||
| [33fe252c58](https://github.com/angular/angular/commit/33fe252c588ee94d6ef99e8070d35c483ec24fda) | fix | do not report unused declarations coming from an imported array ([#57940](https://github.com/angular/angular/pull/57940)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3240598158](https://github.com/angular/angular/commit/32405981582030d7eb5d307f44b9c00fb384c480) | fix | provide flag to opt into manual cleanup for after render hooks ([#57917](https://github.com/angular/angular/pull/57917)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [22dafa658b](https://github.com/angular/angular/commit/22dafa658bdf5536c3002e7f312efe0dfbc7236d) | fix | cleanup JSONP script listeners once loading completed ([#57877](https://github.com/angular/angular/pull/57877)) |
|
||||
| [057cf7fb6b](https://github.com/angular/angular/commit/057cf7fb6bd2ac37a7a30d3a143e6737e386247f) | fix | preserve all headers from Headers object ([#57802](https://github.com/angular/angular/pull/57802)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5c4305f024](https://github.com/angular/angular/commit/5c4305f0248ac3cc1adc76aebd3ef8af041039dc) | feat | support migrating full classes to signal inputs in VSCode ([#57975](https://github.com/angular/angular/pull/57975)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b6bc93803c](https://github.com/angular/angular/commit/b6bc93803c246d47aac0d2d8619271d42b249a4a) | feat | add schematic to migrate to signal queries ([#58032](https://github.com/angular/angular/pull/58032)) |
|
||||
| [ef577b2d2b](https://github.com/angular/angular/commit/ef577b2d2b62ba0a48a120b9631296812e9049d3) | fix | delete constructor if it only has super call ([#58013](https://github.com/angular/angular/pull/58013)) |
|
||||
### upgrade
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5f56a65837](https://github.com/angular/angular/commit/5f56a6583753f5aaff8a43e1e5f9a376433d0c0c) | fix | support input signal bindings ([#57020](https://github.com/angular/angular/pull/57020)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.7"></a>
|
||||
# 18.2.7 (2024-10-02)
|
||||
### common
|
||||
@@ -191,80 +376,11 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.7"></a>
|
||||
# 19.0.0-next.7 (2024-09-25)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Changes to effect timing which generally has two implications:
|
||||
|
||||
* effects which are triggered outside of change detection run as part of
|
||||
the change detection process instead of as a microtask. Depending on the
|
||||
specifics of application/test setup, this can result in them executing
|
||||
earlier or later (or requiring additional test steps to trigger; see below
|
||||
examples).
|
||||
|
||||
* effects which are triggered during change detection (e.g. by input
|
||||
signals) run _earlier_, before the component's template.
|
||||
|
||||
We've seen a few common failure cases:
|
||||
|
||||
* Tests which used to rely on the `Promise` timing of effects now need to
|
||||
`await whenStable()` or call `.detectChanges()` in order for effects to
|
||||
run.
|
||||
|
||||
* Tests which use faked clocks may need to fast-forward/flush the clock to
|
||||
cause effects to run.
|
||||
|
||||
* `effect()`s triggered during CD could rely on the application being fully
|
||||
rendered (for example, they could easily read computed styles, etc). With
|
||||
the change, they run before the component's updates and can get incorrect
|
||||
answers. The recent `afterRenderEffect()` API is a natural replacement for
|
||||
this style of effect.
|
||||
|
||||
* `effect()`s which synchronize with the forms system are particularly
|
||||
timing-sensitive and might need to adjust their initialization timing.
|
||||
- `ExperimentalPendingTasks` has been renamed to
|
||||
`PendingTasks`.
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fc59e2a7b7](https://github.com/angular/angular/commit/fc59e2a7b7afa491a5ea740284a742574805eb36) | feat | change effect() execution timing & no-op `allowSignalWrites` ([#57874](https://github.com/angular/angular/pull/57874)) |
|
||||
| [a7eff3ffaa](https://github.com/angular/angular/commit/a7eff3ffaaecbcb3034130d475ff7b4e41a1e1cc) | feat | mark signal-based query APIs as stable ([#57921](https://github.com/angular/angular/pull/57921)) |
|
||||
| [a1f229850a](https://github.com/angular/angular/commit/a1f229850ad36da009f772faa831da173a60268c) | feat | migrate ExperimentalPendingTasks to PendingTasks ([#57533](https://github.com/angular/angular/pull/57533)) |
|
||||
| [950a5540f1](https://github.com/angular/angular/commit/950a5540f15118e7360506ad82ec9dab5a11f789) | fix | Ensure the `ViewContext` is retained after closure minification ([#57903](https://github.com/angular/angular/pull/57903)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7ecfd89592](https://github.com/angular/angular/commit/7ecfd8959219b6e2ec19e1244a6694711daf1782) | fix | The suppress diagnostics option should work for external templates ([#57873](https://github.com/angular/angular/pull/57873)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.6"></a>
|
||||
# 18.2.6 (2024-09-25)
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.6"></a>
|
||||
# 19.0.0-next.6 (2024-09-18)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f611faadfe](https://github.com/angular/angular/commit/f611faadfedd8dc2c3291da98e2c2c60fe3984bd) | fix | extended diagnostics not validating ICUs ([#57845](https://github.com/angular/angular/pull/57845)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3ebe6b4ad4](https://github.com/angular/angular/commit/3ebe6b4ad401337e18619edc34477ae98226fa3e) | feat | Add async `run` method on `ExperimentalPendingTasks` ([#56546](https://github.com/angular/angular/pull/56546)) |
|
||||
| [1b1519224d](https://github.com/angular/angular/commit/1b1519224d10c1cd25d05d7b958772b9adee1e1a) | feat | mark input, output and model APIs as stable ([#57804](https://github.com/angular/angular/pull/57804)) |
|
||||
| [e5adf92965](https://github.com/angular/angular/commit/e5adf9296595644e415d5c147df08890be01ba77) | feat | stabilize `@let` syntax ([#57813](https://github.com/angular/angular/pull/57813)) |
|
||||
| [4231e8f28f](https://github.com/angular/angular/commit/4231e8f28ffe8f55dddc2af0647b5b04fa8445d7) | fix | Handle `@let` declaration with array when `preparingForHydration` ([#57816](https://github.com/angular/angular/pull/57816)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [59fe9bc772](https://github.com/angular/angular/commit/59fe9bc77236f1374427a851e55b0fa5216d9cf9) | feat | introduce signal input migration as `ng generate` schematic ([#57805](https://github.com/angular/angular/pull/57805)) |
|
||||
| [6144612940](https://github.com/angular/angular/commit/614461294041d7a2331bf7528907f37353205115) | fix | account for explicit standalone: false in migration ([#57803](https://github.com/angular/angular/pull/57803)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.5"></a>
|
||||
# 18.2.5 (2024-09-18)
|
||||
### compiler-cli
|
||||
@@ -282,15 +398,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.5"></a>
|
||||
# 19.0.0-next.5 (2024-09-11)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c93b510f9b](https://github.com/angular/angular/commit/c93b510f9b2e23aa7a3848a04c05249fde14a9b1) | feat | allow passing `undefined` without needing to include it in the type argument of `input` ([#57621](https://github.com/angular/angular/pull/57621)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.4"></a>
|
||||
# 18.2.4 (2024-09-11)
|
||||
### compiler
|
||||
@@ -304,60 +411,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.4"></a>
|
||||
# 19.0.0-next.4 (2024-09-09)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [40ff18f87a](https://github.com/angular/angular/commit/40ff18f87a04fd1c00dea9fee1568bfe52acf25c) | fix | produce less noisy errors when parsing control flow ([#57711](https://github.com/angular/angular/pull/57711)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6ea8e1e9aa](https://github.com/angular/angular/commit/6ea8e1e9aae028572873cf97aa1949c8153f458f) | feat | Add a schematics to migrate to `standalone: false`. ([#57643](https://github.com/angular/angular/pull/57643)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cbec46a51d](https://github.com/angular/angular/commit/cbec46a51d22a1238cc8bf1ebdf343d031b8f0ba) | feat | migrate .pipe calls in outputs used in tests ([#57691](https://github.com/angular/angular/pull/57691)) |
|
||||
| [68e5370a66](https://github.com/angular/angular/commit/68e5370a66633f4b069d6adffa95c2ea94291820) | feat | remove complete calls for migrated outputs ([#57671](https://github.com/angular/angular/pull/57671)) |
|
||||
| [9da21f798d](https://github.com/angular/angular/commit/9da21f798de2033af9d39a8a9b255ef2fe74f948) | feat | replace .next usage on outputs ([#57654](https://github.com/angular/angular/pull/57654)) |
|
||||
| [71f5ef2aa5](https://github.com/angular/angular/commit/71f5ef2aa53a74bab7d0543f98870d81c44c4978) | fix | change imports to be G3 compatible ([#57654](https://github.com/angular/angular/pull/57654)) |
|
||||
| [3a264db866](https://github.com/angular/angular/commit/3a264db86611cba9b69780d7f01ee25787278320) | fix | properly handle comments in output migration ([#57691](https://github.com/angular/angular/pull/57691)) |
|
||||
| [fc95a9adff](https://github.com/angular/angular/commit/fc95a9adff42da53dfeee5df8c42be25e8559708) | fix | replace leftover modules with their exports during pruning ([#57684](https://github.com/angular/angular/pull/57684)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.3"></a>
|
||||
# 19.0.0-next.3 (2024-09-04)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- * TypeScript versions less than 5.5 are no longer supported.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a2e4ee0cb3](https://github.com/angular/angular/commit/a2e4ee0cb3d40cadc05e28d58b06853973944456) | feat | add diagnostic for unused standalone imports ([#57605](https://github.com/angular/angular/pull/57605)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8bcc663a53](https://github.com/angular/angular/commit/8bcc663a53888717cdf4ce0c23404caa00abb1b2) | feat | drop support for TypeScript 5.4 ([#57577](https://github.com/angular/angular/pull/57577)) |
|
||||
| [e6e5d29e83](https://github.com/angular/angular/commit/e6e5d29e830a0a74d7677d5f2345f29391064853) | feat | initial version of the output migration ([#57604](https://github.com/angular/angular/pull/57604)) |
|
||||
| [be2e49639b](https://github.com/angular/angular/commit/be2e49639bda831831ad62d49253db942a83fd46) | feat | introduce `afterRenderEffect` ([#57549](https://github.com/angular/angular/pull/57549)) |
|
||||
### elements
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fe5c4e086a](https://github.com/angular/angular/commit/fe5c4e086add655bf53315d71b0736ff758c7199) | fix | support `output()`-shaped outputs ([#57535](https://github.com/angular/angular/pull/57535)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c2892fee58](https://github.com/angular/angular/commit/c2892fee58d28ffec0dfeaad6a5d6822c040cf03) | fix | Dynamicaly call the global fetch implementation ([#57531](https://github.com/angular/angular/pull/57531)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8da9fb49b5](https://github.com/angular/angular/commit/8da9fb49b54e50de2d028691f73fb773def62ecd) | feat | add code fix for unused standalone imports ([#57605](https://github.com/angular/angular/pull/57605)) |
|
||||
| [1f067f4507](https://github.com/angular/angular/commit/1f067f4507b6e908fe991d5de0dc4d3a627ab2f9) | feat | add code refactoring action to migrate `@Input` to signal-input ([#57214](https://github.com/angular/angular/pull/57214)) |
|
||||
| [56ee47f2ec](https://github.com/angular/angular/commit/56ee47f2ec6e983e2ffdf59476ab29a92590811e) | feat | allow code refactorings to compute edits asynchronously ([#57214](https://github.com/angular/angular/pull/57214)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.3"></a>
|
||||
# 18.2.3 (2024-09-04)
|
||||
### http
|
||||
@@ -367,67 +420,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.2"></a>
|
||||
# 19.0.0-next.2 (2024-08-28)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Render default fallback with empty `projectableNodes`.
|
||||
|
||||
When passing an empty array to `projectableNodes` in the `createComponent` API, the default fallback content of the `ng-content` will be rendered if present. To prevent rendering the default content, pass `document.createTextNode('')` as a `projectableNode`.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
// The first ng-content will render the default fallback content if present
|
||||
createComponent(MyComponent. { projectableNodes: [[], [secondNode]] });
|
||||
|
||||
// To prevent projecting the default fallback content:
|
||||
createComponent(MyComponent. { projectableNodes: [[document.createTextNode('')], [secondNode]] });
|
||||
|
||||
```
|
||||
- The timers that are used for zone coalescing and hybrid
|
||||
mode scheduling (which schedules an application state synchronization
|
||||
when changes happen outside the Angular zone) will now run in the zone
|
||||
above Angular rather than the root zone. This will mostly affect tests
|
||||
which use `fakeAsync`: these timers will now be visible to `fakeAsync`
|
||||
and can be affected by `tick` or `flush`.
|
||||
### elements
|
||||
- as part of switching away from custom CD behavior to the
|
||||
hybrid scheduler, timing of change detection around custom elements has
|
||||
changed subtly. These changes make elements more efficient, but can cause
|
||||
tests which encoded assumptions about how or when elements would be checked
|
||||
to require updating.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [50f08e6c4bf](https://github.com/angular/angular/commit/50f08e6c4bf1caeeb08d3505ce7fabd466b9c76b) | feat | automatically use sizes auto in NgOptimizedImage ([#57479](https://github.com/angular/angular/pull/57479)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4716c3b9660](https://github.com/angular/angular/commit/4716c3b9660b01f4ef3642fb774270b7f4a13d1a) | perf | reduce duplicate component style resolution ([#57502](https://github.com/angular/angular/pull/57502)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a3cdbfe87f5](https://github.com/angular/angular/commit/a3cdbfe87f5a8daef11a154ef3edb5a3a5c12f77) | fix | avoid leaking memory if component throws during creation ([#57546](https://github.com/angular/angular/pull/57546)) |
|
||||
| [7a99815146e](https://github.com/angular/angular/commit/7a99815146eb78074aa3ed6db73c6e87042df692) | fix | Do not bubble capture events. ([#57476](https://github.com/angular/angular/pull/57476)) |
|
||||
| [7b1e5be20b9](https://github.com/angular/angular/commit/7b1e5be20b99c88246c6be78a4dcd64eb55cee1a) | fix | fallback to default ng-content with empty projectable nodes. ([#57480](https://github.com/angular/angular/pull/57480)) |
|
||||
| [0300dd2e18f](https://github.com/angular/angular/commit/0300dd2e18f064f2f57f7371e0dc5c01218b5019) | fix | Fix fixture.detectChanges with autoDetect disabled and zoneless ([#57416](https://github.com/angular/angular/pull/57416)) |
|
||||
| [226a67dabba](https://github.com/angular/angular/commit/226a67dabba90a488ad09ce7bb026b8883c90d4a) | fix | Schedulers run in zone above Angular rather than root ([#57553](https://github.com/angular/angular/pull/57553)) |
|
||||
### elements
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0cebfd7462c](https://github.com/angular/angular/commit/0cebfd7462c6a7c6c3b0d66720c436a4b0eea19d) | fix | switch to `ComponentRef.setInput` & remove custom scheduler ([#56728](https://github.com/angular/angular/pull/56728)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8f6308457f0](https://github.com/angular/angular/commit/8f6308457f0f03e9bbd09f4bc10d1c61fd41d22c) | fix | Do not unnecessarily run matcher twice on route matching ([#57530](https://github.com/angular/angular/pull/57530)) |
|
||||
### upgrade
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c9d90786d0a](https://github.com/angular/angular/commit/c9d90786d0a6421bbb21b9d1649d031b34e3fa5d) | fix | Address Trusted Types violations in @angular/upgrade ([#57454](https://github.com/angular/angular/pull/57454)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.2"></a>
|
||||
# 18.2.2 (2024-08-28)
|
||||
### core
|
||||
@@ -466,75 +458,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.1"></a>
|
||||
# 19.0.0-next.1 (2024-08-22)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- The `autoDetect` feature of `ComponentFixture` will now
|
||||
attach the fixture to the `ApplicationRef`. As a result, errors during
|
||||
automatic change detection of the fixture be reported to the `ErrorHandler`.
|
||||
This change may cause custom error handlers to observe new failures that were previously unreported.
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9e87593055](https://github.com/angular/angular/commit/9e87593055a5314a67090bd15d5552c23b538050) | feat | ensure template style elements are preprocessed as inline styles ([#57429](https://github.com/angular/angular/pull/57429)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b063468027](https://github.com/angular/angular/commit/b0634680272569501146bb7a9cdfe53033e25971) | feat | support TypeScript 5.6 ([#57424](https://github.com/angular/angular/pull/57424)) |
|
||||
| [3b0dca75d6](https://github.com/angular/angular/commit/3b0dca75d6dab6039253edd00c436715775bd0dd) | fix | Allow zoneless scheduler to run inside `fakeAsync` ([#56932](https://github.com/angular/angular/pull/56932)) |
|
||||
| [f03d274e87](https://github.com/angular/angular/commit/f03d274e87c919514a70d02c0699523957de7386) | fix | ComponentFixture autoDetect feature works like production ([#55228](https://github.com/angular/angular/pull/55228)) |
|
||||
| [d4449fce21](https://github.com/angular/angular/commit/d4449fce21bebbb18f9e1341f1675cdbec7e83ac) | fix | handle hydration of components that project content conditionally ([#57383](https://github.com/angular/angular/pull/57383)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4ae66f25d0](https://github.com/angular/angular/commit/4ae66f25d01ffd603872b3df3faf5c5c555b6446) | fix | account for members with doc strings and no modifiers ([#57389](https://github.com/angular/angular/pull/57389)) |
|
||||
| [ac93839d69](https://github.com/angular/angular/commit/ac93839d694929fdf16c610994a369d4efb2823a) | fix | avoid migrating route component in tests ([#57317](https://github.com/angular/angular/pull/57317)) |
|
||||
| [58a79b6e43](https://github.com/angular/angular/commit/58a79b6e435f2a46a7ab17ff5538083e05340b6f) | fix | preserve type when using inject decorator ([#57389](https://github.com/angular/angular/pull/57389)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="19.0.0-next.0"></a>
|
||||
# 19.0.0-next.0 (2024-08-14)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Errors that are thrown during `ApplicationRef.tick`
|
||||
will now be rethrown when using `TestBed`. These errors should be
|
||||
resolved by ensuring the test environment is set up correctly to
|
||||
complete change detection successfully. There are two alternatives to
|
||||
catch the errors:
|
||||
|
||||
* Instead of waiting for automatic change detection to happen, trigger
|
||||
it synchronously and expect the error. For example, a jasmine test
|
||||
could write `expect(() => TestBed.inject(ApplicationRef).tick()).toThrow()`
|
||||
* `TestBed` will reject any outstanding `ComponentFixture.whenStable` promises. A jasmine test,
|
||||
for example, could write `expectAsync(fixture.whenStable()).toBeRejected()`.
|
||||
|
||||
As a last resort, you can configure errors to _not_ be rethrown by
|
||||
setting `rethrowApplicationErrors` to `false` in `TestBed.configureTestingModule`.
|
||||
### router
|
||||
- The `Router.errorHandler` property has been removed.
|
||||
Adding an error handler should be configured in either
|
||||
`withNavigationErrorHandler` with `provideRouter` or the `errorHandler`
|
||||
property in the extra options of `RouterModule.forRoot`. In addition,
|
||||
the error handler cannot be used to change the return value of the
|
||||
router navigation promise or prevent it from rejecting. Instead, if you
|
||||
want to prevent the promise from rejecting, use `resolveNavigationPromiseOnError`.
|
||||
- The return type of the `Resolve` interface now includes
|
||||
`RedirectCommand`.
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [468d3fb9b1](https://github.com/angular/angular/commit/468d3fb9b1c3dd6dff86afcb6d8f89cc4c29b24b) | fix | rethrow errors during ApplicationRef.tick in TestBed ([#57200](https://github.com/angular/angular/pull/57200)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f271021e19](https://github.com/angular/angular/commit/f271021e190ede70bfd181d46f0a468a8e7fa144) | feat | Add `routerOutletData` input to `RouterOutlet` directive ([#57051](https://github.com/angular/angular/pull/57051)) |
|
||||
| [b2790813a6](https://github.com/angular/angular/commit/b2790813a62e4dfdd77e27d1bb82201788476d06) | fix | Align RouterModule.forRoot errorHandler with provider error handler ([#57050](https://github.com/angular/angular/pull/57050)) |
|
||||
| [7436d3180e](https://github.com/angular/angular/commit/7436d3180ea5ad2c0b58d920bd45f8641a14cc8d) | fix | Update Resolve interface to include RedirectCommand like ResolveFn ([#57309](https://github.com/angular/angular/pull/57309)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.2.0"></a>
|
||||
# 18.2.0 (2024-08-14)
|
||||
### compiler
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@ The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is opti
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (examples: CircleCi, SauceLabs)
|
||||
* **ci**: Changes to our CI configuration files and scripts (examples: Github Actions, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/angular/workflows/angular/tree/main">
|
||||
<img src="https://img.shields.io/circleci/build/github/angular/angular/main.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/@angular/core">
|
||||
<img src="https://img.shields.io/npm/v/@angular/core.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen" alt="Angular on npm" />
|
||||
</a>
|
||||
@@ -35,12 +32,6 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://app.circleci.com/insights/github/angular/angular/workflows/default_workflow?branch=main">
|
||||
<img src="https://dl.circleci.com/insights-snapshot/gh/angular/angular/main/default_workflow/badge.svg" alt="InsightsSnapshot" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -143,10 +143,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "b00f13a280fc60ef2a1d142b31c629075bac841c980a0c3462190f338e5d584a",
|
||||
strip_prefix = "rules_sass-6e23fb1351f392f7fe7a07038cd537770fe97742",
|
||||
sha256 = "1b11ce2e7ced21522c83e6c64e9256eb18cd8d89afb8a69e18e6f3e2d3a138a8",
|
||||
strip_prefix = "rules_sass-df7d2a95e1fa6e15bdb8a796756e276b2289f29a",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/6e23fb1351f392f7fe7a07038cd537770fe97742.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/df7d2a95e1fa6e15bdb8a796756e276b2289f29a.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
//tslint:disable:no-console
|
||||
import {execSync} from 'node:child_process';
|
||||
import {readFile, writeFile, readdir, mkdtemp, realpath, copyFile, unlink} from 'node:fs/promises';
|
||||
import {tmpdir} from 'node:os';
|
||||
|
||||
@@ -10,7 +10,6 @@ import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-algolia-icon',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [],
|
||||
templateUrl: './algolia-icon.component.html',
|
||||
|
||||
@@ -13,7 +13,6 @@ import {RouterLink} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-breadcrumb',
|
||||
standalone: true,
|
||||
imports: [RouterLink],
|
||||
templateUrl: './breadcrumb.component.html',
|
||||
styleUrls: ['./breadcrumb.component.scss'],
|
||||
|
||||
@@ -19,7 +19,6 @@ export const STORAGE_KEY = 'docs-accepts-cookies';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-cookie-popup',
|
||||
standalone: true,
|
||||
templateUrl: './cookie-popup.component.html',
|
||||
styleUrls: ['./cookie-popup.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
-1
@@ -120,7 +120,6 @@ describe('CopySourceCodeButton', () => {
|
||||
`,
|
||||
imports: [CopySourceCodeButton],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
})
|
||||
class CodeSnippetWrapper {
|
||||
code = signal('');
|
||||
|
||||
-1
@@ -24,7 +24,6 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 2000;
|
||||
|
||||
@Component({
|
||||
selector: 'button[docs-copy-source-code]',
|
||||
standalone: true,
|
||||
imports: [CommonModule, IconComponent],
|
||||
templateUrl: './copy-source-code-button.component.html',
|
||||
host: {
|
||||
|
||||
@@ -1 +1 @@
|
||||
<ng-content></ng-content>
|
||||
<ng-content />
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
|
||||
@Component({
|
||||
selector: 'docs-icon',
|
||||
standalone: true,
|
||||
templateUrl: './icon.component.html',
|
||||
styleUrl: './icon.component.scss',
|
||||
host: {
|
||||
|
||||
@@ -1,76 +1,75 @@
|
||||
<ng-template #navigationList let-navigationItems>
|
||||
<ul
|
||||
class="docs-navigation-list docs-faceted-list"
|
||||
[class.docs-navigation-list-dropdown]="isDropdownView"
|
||||
[class.docs-navigation-list-dropdown]="isDropdownView()"
|
||||
>
|
||||
@for (item of navigationItems; track $index) {
|
||||
<li
|
||||
class="docs-faceted-list-item"
|
||||
[class.docs-navigation-link-hidden]="displayItemsToLevel && item.level > displayItemsToLevel"
|
||||
>
|
||||
@if (item.path) { @if (item.isExternal) {
|
||||
<a [href]="item.path" target="_blank">
|
||||
<span [class.docs-external-link]="item.isExternal">{{ item.label }}</span>
|
||||
@if (item.children && item.level! > 1 && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<a
|
||||
[routerLink]="'/' + item.path"
|
||||
[routerLinkActiveOptions]="{
|
||||
queryParams: 'ignored',
|
||||
fragment: 'ignored',
|
||||
matrixParams: 'exact',
|
||||
paths: 'exact',
|
||||
exact: false
|
||||
}"
|
||||
routerLinkActive="docs-faceted-list-item-active"
|
||||
(click)="emitClickOnLink()"
|
||||
>
|
||||
<span>{{ item.label }}</span>
|
||||
@if (item.children && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} } @else {
|
||||
<!-- Nav Section Header -->
|
||||
@if (item.level !== collapsableLevel && item.level !== expandableLevel) {
|
||||
<div class="docs-secondary-nav-header">
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
}
|
||||
<li class="docs-faceted-list-item">
|
||||
@if (item.path) {
|
||||
@if (item.isExternal) {
|
||||
<a [href]="item.path" target="_blank">
|
||||
<span [class.docs-external-link]="item.isExternal">{{ item.label }}</span>
|
||||
@if (item.children && item.level! > 1 && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<a
|
||||
[routerLink]="'/' + item.path"
|
||||
[routerLinkActiveOptions]="{
|
||||
queryParams: 'ignored',
|
||||
fragment: 'ignored',
|
||||
matrixParams: 'exact',
|
||||
paths: 'exact',
|
||||
exact: false
|
||||
}"
|
||||
routerLinkActive="docs-faceted-list-item-active"
|
||||
(click)="emitClickOnLink()"
|
||||
>
|
||||
<span>{{item.label}}</span>
|
||||
@if (item.children && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
} @else {
|
||||
<!-- Nav Section Header -->
|
||||
@if (item.level !== collapsableLevel() && item.level !== expandableLevel()) {
|
||||
<div class="docs-secondary-nav-header">
|
||||
<span>{{item.label}}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Nav Button Expand/Collapse -->
|
||||
@if ((item.children && item.level === expandableLevel) || item.level === collapsableLevel) {
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(item)"
|
||||
attr.aria-label="{{ item.isExpanded ? 'Collapse' : 'Expand' }} {{ item.label }}"
|
||||
[attr.aria-expanded]="item.isExpanded"
|
||||
class="docs-secondary-nav-button"
|
||||
[class.docs-faceted-list-item-active]="item | isActiveNavigationItem: activeItem()"
|
||||
[class.docs-expanded-button]="item.children && item.level == collapsableLevel"
|
||||
[class.docs-not-expanded-button]="item.children && item.level === expandableLevel"
|
||||
[class.docs-nav-item-has-icon]="
|
||||
item.children && item.level === expandableLevel && !item.isExpanded
|
||||
"
|
||||
>
|
||||
@if (item.children && item.level === collapsableLevel) {
|
||||
<docs-icon>arrow_back</docs-icon>
|
||||
<!-- Nav Button Expand/Collapse -->
|
||||
@if (
|
||||
(item.children && item.level === expandableLevel()) || item.level === collapsableLevel()
|
||||
) {
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(item)"
|
||||
[attr.aria-label]="(item.isExpanded ? 'Collapse' : 'Expand') + ' ' + item.label"
|
||||
[attr.aria-expanded]="item.isExpanded"
|
||||
class="docs-secondary-nav-button"
|
||||
[class.docs-faceted-list-item-active]="item | isActiveNavigationItem: activeItem()"
|
||||
[class.docs-expanded-button]="item.children && item.level == collapsableLevel()"
|
||||
[class.docs-not-expanded-button]="item.children && item.level === expandableLevel()"
|
||||
[class.docs-nav-item-has-icon]="
|
||||
item.children && item.level === expandableLevel() && !item.isExpanded
|
||||
"
|
||||
>
|
||||
@if (item.children && item.level === collapsableLevel()) {
|
||||
<docs-icon>arrow_back</docs-icon>
|
||||
}
|
||||
<span>{{ item.label }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
<span>{{ item.label }}</span>
|
||||
</button>
|
||||
} } @if (item.children?.length > 0) {
|
||||
<ng-container
|
||||
*ngTemplateOutlet="navigationList; context: {$implicit: item.children}"
|
||||
></ng-container>
|
||||
}
|
||||
</li>
|
||||
@if (displayItemsToLevel() > item.level && item.children?.length > 0) {
|
||||
<ng-container *ngTemplateOutlet="navigationList; context: {$implicit: item.children}" />
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<ng-container
|
||||
*ngTemplateOutlet="navigationList; context: {$implicit: navigationItems}"
|
||||
></ng-container>
|
||||
<ng-container *ngTemplateOutlet="navigationList; context: {$implicit: navigationItems()}" />
|
||||
|
||||
@@ -45,10 +45,6 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.docs-navigation-link-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.docs-nav-item-has-icon {
|
||||
&::after {
|
||||
// FIXME: for some reason this disappears when transformed
|
||||
@@ -77,7 +73,9 @@
|
||||
font-family: var(--inter-font);
|
||||
line-height: 160%;
|
||||
letter-spacing: -0.00875rem;
|
||||
transition: color 0.3s ease, background 0.3s ease;
|
||||
transition:
|
||||
color 0.3s ease,
|
||||
background 0.3s ease;
|
||||
text-align: left; // forces left alignment of text in button
|
||||
|
||||
&.docs-secondary-nav-button-active {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {NavigationList} from './navigation-list.component';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {NavigationItem} from '../../interfaces';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {provideExperimentalZonelessChangeDetection, signal} from '@angular/core';
|
||||
import {NavigationState} from '../../services';
|
||||
|
||||
@@ -37,18 +37,21 @@ describe('NavigationList', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [NavigationList, RouterTestingModule],
|
||||
imports: [NavigationList],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{provide: NavigationState, useClass: FakeNavigationListState},
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(NavigationList);
|
||||
fixture.componentRef.setInput('navigationItems', []);
|
||||
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should display provided navigation structure', () => {
|
||||
component.navigationItems = [...navigationItems];
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.detectChanges();
|
||||
|
||||
const links = fixture.debugElement.queryAll(By.css('a'));
|
||||
@@ -59,7 +62,7 @@ describe('NavigationList', () => {
|
||||
});
|
||||
|
||||
it('should append `docs-navigation-list-dropdown` when isDropdownView is true', () => {
|
||||
component.isDropdownView = true;
|
||||
fixture.componentRef.setInput('isDropdownView', true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const ulElement = fixture.debugElement.query(By.css('ul.docs-navigation-list-dropdown'));
|
||||
@@ -68,7 +71,7 @@ describe('NavigationList', () => {
|
||||
});
|
||||
|
||||
it('should not append `docs-navigation-list-dropdown` when isDropdownView is false', () => {
|
||||
component.isDropdownView = false;
|
||||
fixture.componentRef.setInput('isDropdownView', false);
|
||||
fixture.detectChanges();
|
||||
|
||||
const ulElement = fixture.debugElement.query(By.css('ul.docs-navigation-list-dropdown'));
|
||||
@@ -78,7 +81,7 @@ describe('NavigationList', () => {
|
||||
|
||||
it('should emit linkClicked when user clicked on link', () => {
|
||||
const emitClickOnLinkSpy = spyOn(component, 'emitClickOnLink');
|
||||
component.navigationItems = [...navigationItems];
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const guideLink = fixture.debugElement.query(By.css('a[href="/guide"]'));
|
||||
@@ -102,7 +105,7 @@ describe('NavigationList', () => {
|
||||
const toggleItemSpy = spyOn(navigationState, 'toggleItem');
|
||||
const itemToToggle = navigationItems[1];
|
||||
|
||||
component.expandableLevel = 1;
|
||||
fixture.componentRef.setInput('expandableLevel', 1);
|
||||
component.toggle(itemToToggle);
|
||||
|
||||
expect(toggleItemSpy).toHaveBeenCalledOnceWith(itemToToggle);
|
||||
@@ -113,30 +116,40 @@ describe('NavigationList', () => {
|
||||
const toggleItemSpy = spyOn(navigationState, 'toggleItem');
|
||||
const itemToToggle = navigationItems[1].children![1];
|
||||
|
||||
component.collapsableLevel = 2;
|
||||
fixture.componentRef.setInput('collapsableLevel', 2);
|
||||
component.toggle(itemToToggle);
|
||||
|
||||
expect(toggleItemSpy).toHaveBeenCalledOnceWith(itemToToggle);
|
||||
});
|
||||
|
||||
it('should display items to provided level', () => {
|
||||
component.navigationItems = [...navigationItems];
|
||||
component.displayItemsToLevel = 1;
|
||||
it('should display only items to provided level (Level 1)', () => {
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.componentRef.setInput('displayItemsToLevel', 1);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const visibleItems = fixture.debugElement.queryAll(
|
||||
By.css('li.docs-faceted-list-item:not(.docs-navigation-link-hidden)'),
|
||||
);
|
||||
const hiddenItems = fixture.debugElement.queryAll(
|
||||
By.css('li.docs-faceted-list-item.docs-navigation-link-hidden'),
|
||||
);
|
||||
const items = fixture.debugElement.queryAll(By.css('li.docs-faceted-list-item'));
|
||||
|
||||
expect(visibleItems.length).toBe(2);
|
||||
expect(visibleItems[0].nativeElement.innerText).toBe(navigationItems[0].label);
|
||||
expect(visibleItems[1].nativeElement.innerText).toBe(navigationItems[1].label);
|
||||
expect(hiddenItems.length).toBe(2);
|
||||
expect(hiddenItems[0].nativeElement.innerText).toBe(navigationItems[1].children![0].label);
|
||||
expect(hiddenItems[1].nativeElement.innerText).toBe(navigationItems[1].children![1].label);
|
||||
expect(items.length).toBe(2);
|
||||
expect(items[0].nativeElement.innerText).toBe(navigationItems[0].label);
|
||||
expect(items[1].nativeElement.innerText).toBe(navigationItems[1].label);
|
||||
});
|
||||
|
||||
it('should display all items (Level 2)', () => {
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.componentRef.setInput('displayItemsToLevel', 2);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const items = fixture.debugElement.queryAll(By.css('li.docs-faceted-list-item'));
|
||||
|
||||
expect(items.length).toBe(4);
|
||||
|
||||
expect(items[0].nativeElement.innerText).toBe(navigationItems[0].label);
|
||||
expect(items[1].nativeElement.innerText.startsWith(navigationItems[1].label)).toBeTrue();
|
||||
|
||||
const secondItemChildren = navigationItems[1].children || [];
|
||||
|
||||
expect(items[2].nativeElement.innerText).toBe(secondItemChildren[0].label);
|
||||
expect(items[3].nativeElement.innerText).toBe(secondItemChildren[1].label);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,48 +6,39 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, inject, input, output} from '@angular/core';
|
||||
import {NavigationItem} from '../../interfaces/index';
|
||||
import {NavigationState} from '../../services/index';
|
||||
import {RouterLink, RouterLinkActive} from '@angular/router';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
import {IsActiveNavigationItem} from '../../pipes/is-active-navigation-item.pipe';
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-navigation-list',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink, RouterLinkActive, IconComponent, IsActiveNavigationItem],
|
||||
imports: [RouterLink, RouterLinkActive, IconComponent, IsActiveNavigationItem, NgTemplateOutlet],
|
||||
templateUrl: './navigation-list.component.html',
|
||||
styleUrls: ['./navigation-list.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NavigationList {
|
||||
@Input({required: true}) navigationItems: NavigationItem[] = [];
|
||||
@Input() displayItemsToLevel: number = 2;
|
||||
@Input() collapsableLevel: number | undefined = undefined;
|
||||
@Input() expandableLevel: number = 2;
|
||||
@Input() isDropdownView = false;
|
||||
readonly navigationItems = input.required<NavigationItem[]>();
|
||||
readonly displayItemsToLevel = input<number>(2);
|
||||
readonly collapsableLevel = input<number | undefined>();
|
||||
readonly expandableLevel = input<number>(2);
|
||||
readonly isDropdownView = input<boolean>(false);
|
||||
|
||||
@Output() linkClicked = new EventEmitter<void>();
|
||||
readonly linkClicked = output<void>();
|
||||
|
||||
private readonly navigationState = inject(NavigationState);
|
||||
|
||||
expandedItems = this.navigationState.expandedItems;
|
||||
activeItem = this.navigationState.activeNavigationItem;
|
||||
readonly activeItem = this.navigationState.activeNavigationItem;
|
||||
|
||||
toggle(item: NavigationItem): void {
|
||||
if (
|
||||
item.level === 1 &&
|
||||
item.level !== this.expandableLevel &&
|
||||
item.level !== this.collapsableLevel
|
||||
item.level !== this.expandableLevel() &&
|
||||
item.level !== this.collapsableLevel()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
(ngModelChange)="updateSearchQuery($event)"
|
||||
class="docs-search-input"
|
||||
placeholder="Search docs"
|
||||
></docs-text-field>
|
||||
/>
|
||||
|
||||
@if (searchResults() && searchResults()!.length > 0) {
|
||||
<ul class="docs-search-results docs-mini-scroll-track">
|
||||
@@ -31,7 +31,7 @@
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="highlightSnippet"
|
||||
[ngTemplateOutletContext]="{snippet}"
|
||||
></ng-container>
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="highlightSnippet"
|
||||
[ngTemplateOutletContext]="{snippet}"
|
||||
></ng-container>
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
@@ -70,7 +70,8 @@
|
||||
|
||||
<div class="docs-algolia">
|
||||
<span>Search by</span>
|
||||
<a href="https://www.algolia.com/developers/" target="_blank" rel="noopener">
|
||||
<a target="_blank" rel="noopener"
|
||||
href="https://www.algolia.com/developers/?utm_source=angular.dev&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch">
|
||||
<docs-algolia-icon />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -36,6 +36,7 @@ dialog {
|
||||
ul {
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
list-style-type: none;
|
||||
padding-inline: 0;
|
||||
padding-block-start: 1rem;
|
||||
|
||||
@@ -39,7 +39,6 @@ import {SearchResult, SnippetResult} from '../../interfaces';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-search-dialog',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ClickOutside,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<select [attr.id]="id" [attr.name]="name" [ngModel]="selectedOption()" (ngModelChange)="setOption($event)">
|
||||
@for (item of options; track item) {
|
||||
<select
|
||||
[attr.id]="id()"
|
||||
[attr.name]="name()"
|
||||
[ngModel]="selectedOption()"
|
||||
(ngModelChange)="setOption($event)"
|
||||
>
|
||||
@for (item of options(); track item) {
|
||||
<option [value]="item.value">{{ item.label }}</option>
|
||||
}
|
||||
</select>
|
||||
|
||||
@@ -22,6 +22,12 @@ describe('Select', () => {
|
||||
});
|
||||
fixture = TestBed.createComponent(Select);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
// Sets the required inputs
|
||||
fixture.componentRef.setInput('selectId', 'id');
|
||||
fixture.componentRef.setInput('name', 'name');
|
||||
fixture.componentRef.setInput('options', []);
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule} from '@angular/forms';
|
||||
import {ChangeDetectionStrategy, Component, Input, forwardRef, signal} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, model, forwardRef, input, signal} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
|
||||
type SelectOptionValue = string | number | boolean;
|
||||
@@ -19,7 +19,6 @@ export interface SelectOption {
|
||||
|
||||
@Component({
|
||||
selector: 'docs-select',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, FormsModule],
|
||||
templateUrl: './select.component.html',
|
||||
@@ -36,10 +35,10 @@ export interface SelectOption {
|
||||
},
|
||||
})
|
||||
export class Select implements ControlValueAccessor {
|
||||
@Input({required: true, alias: 'selectId'}) id!: string;
|
||||
@Input({required: true}) name!: string;
|
||||
@Input({required: true}) options!: SelectOption[];
|
||||
@Input() disabled = false;
|
||||
readonly id = input.required<string>({alias: 'selectId'});
|
||||
readonly name = input.required<string>();
|
||||
readonly options = input.required<SelectOption[]>();
|
||||
readonly disabled = model<boolean>(false);
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
private onChange: (value: SelectOptionValue) => void = (_: SelectOptionValue) => {};
|
||||
@@ -64,11 +63,11 @@ export class Select implements ControlValueAccessor {
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
this.disabled.set(isDisabled);
|
||||
}
|
||||
|
||||
setOption($event: SelectOptionValue): void {
|
||||
if (this.disabled) {
|
||||
if (this.disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<label [attr.for]="buttonId">
|
||||
<span class="docs-label">{{ label }}</span>
|
||||
<label [attr.for]="buttonId()">
|
||||
<span class="docs-label">{{ label() }}</span>
|
||||
<div class="docs-toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
[id]="buttonId"
|
||||
[id]="buttonId()"
|
||||
role="switch"
|
||||
(click)="toggle()"
|
||||
[class.docs-toggle-active]="checked()"
|
||||
|
||||
@@ -21,6 +21,8 @@ describe('SlideToggle', () => {
|
||||
providers: [provideExperimentalZonelessChangeDetection()],
|
||||
});
|
||||
fixture = TestBed.createComponent(SlideToggle);
|
||||
fixture.componentRef.setInput('buttonId', 'id');
|
||||
fixture.componentRef.setInput('label', 'foo');
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, Input, forwardRef, signal} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, forwardRef, model, input, signal} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-slide-toggle',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './slide-toggle.component.html',
|
||||
@@ -26,9 +25,9 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
],
|
||||
})
|
||||
export class SlideToggle implements ControlValueAccessor {
|
||||
@Input({required: true}) buttonId!: string;
|
||||
@Input({required: true}) label!: string;
|
||||
@Input() disabled = false;
|
||||
readonly buttonId = input.required<string>();
|
||||
readonly label = input.required<string>();
|
||||
readonly disabled = model<boolean>(false);
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
private onChange: (value: boolean) => void = (_: boolean) => {};
|
||||
@@ -53,12 +52,12 @@ export class SlideToggle implements ControlValueAccessor {
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
this.disabled.set(isDisabled);
|
||||
}
|
||||
|
||||
// Toggles the checked state of the slide-toggle.
|
||||
toggle(): void {
|
||||
if (this.disabled) {
|
||||
if (this.disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ describe('TableOfContents', () => {
|
||||
spyOn(tableOfContentsLoaderSpy, 'buildTableOfContent').and.returnValue();
|
||||
tableOfContentsLoaderSpy.tableOfContentItems.set(items);
|
||||
fixture = TestBed.createComponent(TableOfContents);
|
||||
fixture.componentRef.setInput('contentSourceElement', document.createElement('div'));
|
||||
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
DestroyRef,
|
||||
Input,
|
||||
input,
|
||||
computed,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
@@ -22,7 +22,6 @@ import {IconComponent} from '../icon/icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-table-of-contents',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './table-of-contents.component.html',
|
||||
styleUrls: ['./table-of-contents.component.scss'],
|
||||
@@ -30,7 +29,7 @@ import {IconComponent} from '../icon/icon.component';
|
||||
})
|
||||
export class TableOfContents {
|
||||
// Element that contains the content from which the Table of Contents is built
|
||||
@Input({required: true}) contentSourceElement!: HTMLElement;
|
||||
readonly contentSourceElement = input.required<HTMLElement>();
|
||||
|
||||
private readonly scrollSpy = inject(TableOfContentsScrollSpy);
|
||||
private readonly tableOfContentsLoader = inject(TableOfContentsLoader);
|
||||
@@ -43,8 +42,8 @@ export class TableOfContents {
|
||||
TableOfContentsLevel = TableOfContentsLevel;
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.tableOfContentsLoader.buildTableOfContent(this.contentSourceElement);
|
||||
this.scrollSpy.startListeningToScroll(this.contentSourceElement, this.destroyRef);
|
||||
this.tableOfContentsLoader.buildTableOfContent(this.contentSourceElement());
|
||||
this.scrollSpy.startListeningToScroll(this.contentSourceElement(), this.destroyRef);
|
||||
}
|
||||
|
||||
scrollToTop(): void {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
@if (!hideIcon) {
|
||||
<docs-icon class="docs-icon_high-contrast">search</docs-icon>
|
||||
@if (!hideIcon()) {
|
||||
<docs-icon class="docs-icon_high-contrast">search</docs-icon>
|
||||
}
|
||||
<input
|
||||
#inputRef
|
||||
type="text"
|
||||
[attr.placeholder]="placeholder"
|
||||
[attr.name]="name"
|
||||
[attr.placeholder]="placeholder()"
|
||||
[attr.name]="name()"
|
||||
[ngModel]="value()"
|
||||
(ngModelChange)="setValue($event)"
|
||||
class="docs-text-field"
|
||||
|
||||
@@ -10,11 +10,12 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
ViewChild,
|
||||
input,
|
||||
afterNextRender,
|
||||
forwardRef,
|
||||
signal,
|
||||
model,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
@@ -22,7 +23,6 @@ import {IconComponent} from '../icon/icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-text-field',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, FormsModule, IconComponent],
|
||||
templateUrl: './text-field.component.html',
|
||||
@@ -39,13 +39,13 @@ import {IconComponent} from '../icon/icon.component';
|
||||
},
|
||||
})
|
||||
export class TextField implements ControlValueAccessor {
|
||||
@ViewChild('inputRef') private input?: ElementRef<HTMLInputElement>;
|
||||
readonly input = viewChild.required<ElementRef<HTMLInputElement>>('inputRef');
|
||||
|
||||
@Input() name: string | null = null;
|
||||
@Input() placeholder: string | null = null;
|
||||
@Input() disabled = false;
|
||||
@Input() hideIcon = false;
|
||||
@Input() autofocus = false;
|
||||
readonly name = input<string | null>(null);
|
||||
readonly placeholder = input<string | null>(null);
|
||||
readonly disabled = model<boolean>(false);
|
||||
readonly hideIcon = input<boolean>(false);
|
||||
readonly autofocus = input<boolean>(false);
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
private onChange: (value: string) => void = (_: string) => {};
|
||||
@@ -55,8 +55,8 @@ export class TextField implements ControlValueAccessor {
|
||||
|
||||
constructor() {
|
||||
afterNextRender(() => {
|
||||
if (this.autofocus) {
|
||||
this.input?.nativeElement.focus();
|
||||
if (this.autofocus()) {
|
||||
this.input().nativeElement.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -78,11 +78,11 @@ export class TextField implements ControlValueAccessor {
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
this.disabled.set(isDisabled);
|
||||
}
|
||||
|
||||
setValue(value: string): void {
|
||||
if (this.disabled) {
|
||||
if (this.disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
@if (!hasClosed()) {
|
||||
@if (link()) {
|
||||
<a [href]="link()" class="docs-top-level-banner">
|
||||
<h1 tabindex="-1" class="docs-top-level-banner-cta background">{{ text() }}</h1>
|
||||
<h1 tabindex="0" class="docs-top-level-banner-cta shimmer">{{ text() }}</h1>
|
||||
</a>
|
||||
} @else {
|
||||
<div class="docs-top-level-banner">
|
||||
<h1 tabindex="-1" class="docs-top-level-banner-cta background">{{ text() }}</h1>
|
||||
<h1 tabindex="0" class="docs-top-level-banner-cta shimmer">{{ text() }}</h1>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button class="docs-top-level-banner-close" type="button" (click)="close()">
|
||||
<docs-icon class="docs-icon_high-contrast">close</docs-icon>
|
||||
</button>
|
||||
@if (link()) {
|
||||
<a [href]="link()" class="docs-top-level-banner">
|
||||
<h1 tabindex="-1" class="docs-top-level-banner-cta shimmer">{{ text() }}</h1>
|
||||
<h1 tabindex="0" class="docs-top-level-banner-cta background"><span class="docs-top-level-banner-cta__text">{{ text()
|
||||
}}</span></h1>
|
||||
</a>
|
||||
} @else {
|
||||
<div class="docs-top-level-banner">
|
||||
<h1 tabindex="-1" class="docs-top-level-banner-cta shimmer">{{ text() }}</h1>
|
||||
<h1 tabindex="0" class="docs-top-level-banner-cta background"><span class="docs-top-level-banner-cta__text">{{ text()
|
||||
}}</span></h1>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button class="docs-top-level-banner-close" type="button" (click)="close()">
|
||||
<docs-icon class="docs-icon_high-contrast">close</docs-icon>
|
||||
</button>
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
:host {
|
||||
&:not(:empty) {
|
||||
z-index: 50;
|
||||
z-index: var(--z-index-top-level-banner);
|
||||
position: fixed;
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: auto;
|
||||
width: 100vw;
|
||||
padding: .5rem;
|
||||
border-bottom: 1px solid var(--septenary-contrast);
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
@@ -12,16 +16,22 @@
|
||||
}
|
||||
|
||||
a.docs-top-level-banner {
|
||||
width: 100%;
|
||||
display: inherit;
|
||||
display: grid;
|
||||
width: auto;
|
||||
margin: 0rem 2.5rem;
|
||||
|
||||
&:hover{
|
||||
h1.docs-top-level-banner-cta.background{
|
||||
span.docs-top-level-banner-cta__text::after{
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
h1.docs-top-level-banner-cta {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
grid-row-start: 1;
|
||||
grid-column-start: 1;
|
||||
font-size: 0.875rem;
|
||||
margin: 0;
|
||||
width: fit-content;
|
||||
@@ -29,45 +39,46 @@
|
||||
|
||||
&.background {
|
||||
color: var(--tertiary-contrast);
|
||||
|
||||
& .docs-top-level-banner-cta__text{
|
||||
position:relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: calc(100% + 2rem);
|
||||
height: 1px;
|
||||
bottom: -2px;
|
||||
left: -1rem;
|
||||
background: var(--tertiary-contrast);
|
||||
transform: scaleX(0);
|
||||
transform-origin: bottom right;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:not(.background) {
|
||||
color: transparent;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
background: var(--tertiary-contrast);
|
||||
transform: scaleX(0);
|
||||
transform-origin: bottom right;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-top-level-banner-close {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
right: 0.5rem;
|
||||
right: 1.4rem;
|
||||
color: var(--tertiary-contrast);
|
||||
padding-left: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
.shimmer {
|
||||
background: var(--red-to-pink-to-purple-horizontal-gradient);
|
||||
z-index: 1;
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
background-repeat: no-repeat;
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {STORAGE_KEY_PREFIX, TopLevelBannerComponent} from './top-level-banner.component';
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, inject, input, OnInit, signal} from '@angular/core';
|
||||
import {ExternalLink} from '../../directives';
|
||||
import {LOCAL_STORAGE} from '../../providers';
|
||||
@@ -7,7 +15,6 @@ export const STORAGE_KEY_PREFIX = 'docs-was-closed-top-banner-';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-top-level-banner',
|
||||
standalone: true,
|
||||
imports: [ExternalLink, IconComponent],
|
||||
templateUrl: './top-level-banner.component.html',
|
||||
styleUrl: './top-level-banner.component.scss',
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
h5,
|
||||
h6 {
|
||||
.docs-anchor {
|
||||
margin-block-start: 2.5rem;
|
||||
margin-block-start: 0.75rem;
|
||||
display: inline-block;
|
||||
color: inherit;
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {provideNoopAnimations} from '@angular/platform-browser/animations';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {ExampleViewerContentLoader} from '../../../interfaces';
|
||||
import {EXAMPLE_VIEWER_CONTENT_LOADER} from '../../../providers';
|
||||
import {CodeExampleViewMode, ExampleViewer} from '../example-viewer/example-viewer.component';
|
||||
@@ -29,14 +29,14 @@ describe('DocViewer', () => {
|
||||
const exampleDocContentWithExampleViewerPlaceholders = `<div class="docs-code linenums" visibleLines="[12, 31]" expanded="true" path="hello-world/hello-world-new.ts">
|
||||
<div class="docs-code-header">A styled code example</div>
|
||||
<pre>
|
||||
<code><div class="hljs-ln-line"><span class="hljs-comment">/*!</div><div class="hljs-ln-line"> * @license</div><div class="hljs-ln-line"> * Copyright Google LLC All Rights Reserved.</div><div class="hljs-ln-line"> *</div><div class="hljs-ln-line"> * Use of this source code is governed by an MIT-style license that can be</div><div class="hljs-ln-line"> * found in the LICENSE file at https://angular.dev/license</div><div class="hljs-ln-line"> */</span></div><div class="hljs-ln-line"></div><div class="hljs-ln-line remove"><span class="hljs-keyword">import</span> {ChangeDetectorRef, Component, <span class="hljs-keyword">inject</span>, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line add"><span class="hljs-keyword">import</span> {Component, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line"><span class="hljs-keyword">import</span> {CommonModule} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;</div><div class="hljs-ln-line"></div><div class="hljs-ln-line highlighted">@Component({</div><div class="hljs-ln-line highlighted"> selector: <span class="hljs-string">'hello-world'</span>,</div><div class="hljs-ln-line highlighted"> standalone: <span class="hljs-keyword">true</span>,</div><div class="hljs-ln-line highlighted"> imports: [CommonModule],</div><div class="hljs-ln-line highlighted"> templateUrl: <span class="hljs-string">'./hello-world.html'</span>,</div><div class="hljs-ln-line highlighted"> styleUrls: [<span class="hljs-string">'./hello-world.css'</span>],</div><div class="hljs-ln-line highlighted">})</div><div class="hljs-ln-line">export <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> HelloWorldComponent {</div><div class="hljs-ln-line remove"> world = <span class="hljs-string">'World'</span>;</div><div class="hljs-ln-line add"> world = <span class="hljs-string">'World!!!'</span>;</div><div class="hljs-ln-line"> <span class="hljs-keyword">count</span> = signal(<span class="hljs-number">0</span>);</div><div class="hljs-ln-line remove"> changeDetector = <span class="hljs-keyword">inject</span>(ChangeDetectorRef);</div><div class="hljs-ln-line"></div><div class="hljs-ln-line"> increase(): <span class="hljs-keyword">void</span> {</div><div class="hljs-ln-line"> <span class="hljs-keyword">this</span>.<span class="hljs-keyword">count</span>.update((<span class="hljs-keyword">previous</span>) => {</div><div class="hljs-ln-line highlighted"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">previous</span> + <span class="hljs-number">1</span>;</div><div class="hljs-ln-line"> });</div><div class="hljs-ln-line remove"> <span class="hljs-keyword">this</span>.changeDetector.detectChanges();</div><div class="hljs-ln-line"> }</div><div class="hljs-ln-line">}</div><div class="hljs-ln-line"></div></code>
|
||||
<code><div class="hljs-ln-line"><span class="hljs-comment">/*!</div><div class="hljs-ln-line"> * @license</div><div class="hljs-ln-line"> * Copyright Google LLC All Rights Reserved.</div><div class="hljs-ln-line"> *</div><div class="hljs-ln-line"> * Use of this source code is governed by an MIT-style license that can be</div><div class="hljs-ln-line"> * found in the LICENSE file at https://angular.dev/license</div><div class="hljs-ln-line"> */</span></div><div class="hljs-ln-line"></div><div class="hljs-ln-line remove"><span class="hljs-keyword">import</span> {ChangeDetectorRef, Component, <span class="hljs-keyword">inject</span>, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line add"><span class="hljs-keyword">import</span> {Component, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line"><span class="hljs-keyword">import</span> {CommonModule} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;</div><div class="hljs-ln-line"></div><div class="hljs-ln-line highlighted">@Component({</div><div class="hljs-ln-line highlighted"> selector: <span class="hljs-string">'hello-world'</span>,</div><div class="hljs-ln-line highlighted"> imports: [CommonModule],</div><div class="hljs-ln-line highlighted"> templateUrl: <span class="hljs-string">'./hello-world.html'</span>,</div><div class="hljs-ln-line highlighted"> styleUrls: [<span class="hljs-string">'./hello-world.css'</span>],</div><div class="hljs-ln-line highlighted">})</div><div class="hljs-ln-line">export <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> HelloWorldComponent {</div><div class="hljs-ln-line remove"> world = <span class="hljs-string">'World'</span>;</div><div class="hljs-ln-line add"> world = <span class="hljs-string">'World!!!'</span>;</div><div class="hljs-ln-line"> <span class="hljs-keyword">count</span> = signal(<span class="hljs-number">0</span>);</div><div class="hljs-ln-line remove"> changeDetector = <span class="hljs-keyword">inject</span>(ChangeDetectorRef);</div><div class="hljs-ln-line"></div><div class="hljs-ln-line"> increase(): <span class="hljs-keyword">void</span> {</div><div class="hljs-ln-line"> <span class="hljs-keyword">this</span>.<span class="hljs-keyword">count</span>.update((<span class="hljs-keyword">previous</span>) => {</div><div class="hljs-ln-line highlighted"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">previous</span> + <span class="hljs-number">1</span>;</div><div class="hljs-ln-line"> });</div><div class="hljs-ln-line remove"> <span class="hljs-keyword">this</span>.changeDetector.detectChanges();</div><div class="hljs-ln-line"> }</div><div class="hljs-ln-line">}</div><div class="hljs-ln-line"></div></code>
|
||||
</pre>
|
||||
</div>`;
|
||||
|
||||
const exampleDocContentWithExpandedExampleViewerPlaceholders = `<div class="docs-code-multifile" expanded="true" path="hello-world/hello-world-new.ts">
|
||||
<div class="docs-code" visibleLines="[12, 31]" path="hello-world/hello-world-new.ts">
|
||||
<pre>
|
||||
<code><div class="hljs-ln-line"><span class="hljs-comment">/*!</div><div class="hljs-ln-line"> * @license</div><div class="hljs-ln-line"> * Copyright Google LLC All Rights Reserved.</div><div class="hljs-ln-line"> *</div><div class="hljs-ln-line"> * Use of this source code is governed by an MIT-style license that can be</div><div class="hljs-ln-line"> * found in the LICENSE file at https://angular.dev/license</div><div class="hljs-ln-line"> */</span></div><div class="hljs-ln-line"></div><div class="hljs-ln-line remove"><span class="hljs-keyword">import</span> {ChangeDetectorRef, Component, <span class="hljs-keyword">inject</span>, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line add"><span class="hljs-keyword">import</span> {Component, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line"><span class="hljs-keyword">import</span> {CommonModule} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;</div><div class="hljs-ln-line"></div><div class="hljs-ln-line">@Component({</div><div class="hljs-ln-line"> selector: <span class="hljs-string">'hello-world'</span>,</div><div class="hljs-ln-line"> standalone: <span class="hljs-keyword">true</span>,</div><div class="hljs-ln-line"> imports: [CommonModule],</div><div class="hljs-ln-line"> templateUrl: <span class="hljs-string">'./hello-world.html'</span>,</div><div class="hljs-ln-line"> styleUrls: [<span class="hljs-string">'./hello-world.css'</span>],</div><div class="hljs-ln-line">})</div><div class="hljs-ln-line">export <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> HelloWorldComponent {</div><div class="hljs-ln-line remove"> world = <span class="hljs-string">'World'</span>;</div><div class="hljs-ln-line add"> world = <span class="hljs-string">'World!!!'</span>;</div><div class="hljs-ln-line"> <span class="hljs-keyword">count</span> = signal(<span class="hljs-number">0</span>);</div><div class="hljs-ln-line remove"> changeDetector = <span class="hljs-keyword">inject</span>(ChangeDetectorRef);</div><div class="hljs-ln-line"></div><div class="hljs-ln-line"> increase(): <span class="hljs-keyword">void</span> {</div><div class="hljs-ln-line"> <span class="hljs-keyword">this</span>.<span class="hljs-keyword">count</span>.update((<span class="hljs-keyword">previous</span>) => {</div><div class="hljs-ln-line"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">previous</span> + <span class="hljs-number">1</span>;</div><div class="hljs-ln-line"> });</div><div class="hljs-ln-line remove"> <span class="hljs-keyword">this</span>.changeDetector.detectChanges();</div><div class="hljs-ln-line"> }</div><div class="hljs-ln-line">}</div><div class="hljs-ln-line"></div></code>
|
||||
<code><div class="hljs-ln-line"><span class="hljs-comment">/*!</div><div class="hljs-ln-line"> * @license</div><div class="hljs-ln-line"> * Copyright Google LLC All Rights Reserved.</div><div class="hljs-ln-line"> *</div><div class="hljs-ln-line"> * Use of this source code is governed by an MIT-style license that can be</div><div class="hljs-ln-line"> * found in the LICENSE file at https://angular.dev/license</div><div class="hljs-ln-line"> */</span></div><div class="hljs-ln-line"></div><div class="hljs-ln-line remove"><span class="hljs-keyword">import</span> {ChangeDetectorRef, Component, <span class="hljs-keyword">inject</span>, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line add"><span class="hljs-keyword">import</span> {Component, signal} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;</div><div class="hljs-ln-line"><span class="hljs-keyword">import</span> {CommonModule} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;</div><div class="hljs-ln-line"></div><div class="hljs-ln-line">@Component({</div><div class="hljs-ln-line"> selector: <span class="hljs-string">'hello-world'</span>,</div><div class="hljs-ln-line"> imports: [CommonModule],</div><div class="hljs-ln-line"> templateUrl: <span class="hljs-string">'./hello-world.html'</span>,</div><div class="hljs-ln-line"> styleUrls: [<span class="hljs-string">'./hello-world.css'</span>],</div><div class="hljs-ln-line">})</div><div class="hljs-ln-line">export <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> HelloWorldComponent {</div><div class="hljs-ln-line remove"> world = <span class="hljs-string">'World'</span>;</div><div class="hljs-ln-line add"> world = <span class="hljs-string">'World!!!'</span>;</div><div class="hljs-ln-line"> <span class="hljs-keyword">count</span> = signal(<span class="hljs-number">0</span>);</div><div class="hljs-ln-line remove"> changeDetector = <span class="hljs-keyword">inject</span>(ChangeDetectorRef);</div><div class="hljs-ln-line"></div><div class="hljs-ln-line"> increase(): <span class="hljs-keyword">void</span> {</div><div class="hljs-ln-line"> <span class="hljs-keyword">this</span>.<span class="hljs-keyword">count</span>.update((<span class="hljs-keyword">previous</span>) => {</div><div class="hljs-ln-line"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">previous</span> + <span class="hljs-number">1</span>;</div><div class="hljs-ln-line"> });</div><div class="hljs-ln-line remove"> <span class="hljs-keyword">this</span>.changeDetector.detectChanges();</div><div class="hljs-ln-line"> }</div><div class="hljs-ln-line">}</div><div class="hljs-ln-line"></div></code>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="docs-code linenums" path="hello-world/hello-world.html">
|
||||
@@ -80,8 +80,10 @@ describe('DocViewer', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [DocViewer, NoopAnimationsModule, RouterTestingModule],
|
||||
imports: [DocViewer],
|
||||
providers: [
|
||||
provideNoopAnimations(),
|
||||
provideRouter([]),
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
{provide: EXAMPLE_VIEWER_CONTENT_LOADER, useValue: exampleContentSpy},
|
||||
{provide: NavigationState, useValue: navigationStateSpy},
|
||||
|
||||
@@ -25,9 +25,8 @@ import {
|
||||
Type,
|
||||
ViewContainerRef,
|
||||
ViewEncapsulation,
|
||||
ɵPendingTasks as PendingTasks,
|
||||
EventEmitter,
|
||||
Output,
|
||||
ɵPendingTasksInternal as PendingTasks,
|
||||
output,
|
||||
} from '@angular/core';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {TOC_SKIP_CONTENT_MARKER, NavigationState} from '../../../services/index';
|
||||
@@ -55,7 +54,6 @@ export const GITHUB_CONTENT_URL =
|
||||
|
||||
@Component({
|
||||
selector: DOCS_VIEWER_SELECTOR,
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
template: '',
|
||||
styleUrls: ['docs-viewer.component.scss'],
|
||||
@@ -68,7 +66,7 @@ export const GITHUB_CONTENT_URL =
|
||||
export class DocViewer implements OnChanges {
|
||||
@Input() docContent?: string;
|
||||
@Input() hasToc = false;
|
||||
@Output() contentLoaded = new EventEmitter<void>();
|
||||
readonly contentLoaded = output<void>();
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly document = inject(DOCUMENT);
|
||||
@@ -134,7 +132,7 @@ export class DocViewer implements OnChanges {
|
||||
// Render ToC
|
||||
this.renderTableOfContents(contentContainer);
|
||||
|
||||
this.contentLoaded.next();
|
||||
this.contentLoaded.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ import {ExampleViewer} from './example-viewer.component';
|
||||
import {DocsContentLoader, ExampleMetadata, ExampleViewerContentLoader} from '../../../interfaces';
|
||||
import {DOCS_CONTENT_LOADER, EXAMPLE_VIEWER_CONTENT_LOADER} from '../../../providers';
|
||||
import {Component, provideExperimentalZonelessChangeDetection} from '@angular/core';
|
||||
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {provideNoopAnimations} from '@angular/platform-browser/animations';
|
||||
import {HarnessLoader} from '@angular/cdk/testing';
|
||||
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
@@ -35,8 +35,9 @@ describe('ExampleViewer', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ExampleViewer, NoopAnimationsModule],
|
||||
imports: [ExampleViewer],
|
||||
providers: [
|
||||
provideNoopAnimations(),
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
{provide: EXAMPLE_VIEWER_CONTENT_LOADER, useValue: exampleContentSpy},
|
||||
{provide: DOCS_CONTENT_LOADER, useValue: contentServiceSpy},
|
||||
@@ -225,6 +226,5 @@ const getMetadata = (value: Partial<ExampleMetadata> = {}): ExampleMetadata => {
|
||||
|
||||
@Component({
|
||||
template: '',
|
||||
standalone: true,
|
||||
})
|
||||
class ExampleComponent {}
|
||||
|
||||
@@ -41,7 +41,6 @@ export const HIDDEN_CLASS_NAME = 'hidden';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-example-viewer',
|
||||
standalone: true,
|
||||
imports: [CommonModule, forwardRef(() => DocViewer), CopySourceCodeButton, MatTabsModule],
|
||||
templateUrl: './example-viewer.component.html',
|
||||
styleUrls: ['./example-viewer.component.scss'],
|
||||
|
||||
@@ -68,7 +68,6 @@ describe('ClickOutside', () => {
|
||||
</div>
|
||||
`,
|
||||
imports: [ClickOutside],
|
||||
standalone: true,
|
||||
})
|
||||
class ExampleComponent {
|
||||
docsClickOutsideIgnore = ['ignoreThisButton'];
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
*/
|
||||
|
||||
import {DOCUMENT} from '@angular/common';
|
||||
import {Directive, ElementRef, EventEmitter, Input, Output, inject} from '@angular/core';
|
||||
import {Directive, ElementRef, Input, inject, output} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[docsClickOutside]',
|
||||
standalone: true,
|
||||
host: {
|
||||
'(document:click)': 'onClick($event)',
|
||||
},
|
||||
})
|
||||
export class ClickOutside {
|
||||
@Input('docsClickOutsideIgnore') public ignoredElementsIds: string[] = [];
|
||||
@Output('docsClickOutside') public clickOutside = new EventEmitter<void>();
|
||||
public readonly clickOutside = output<void>({alias: 'docsClickOutside'});
|
||||
|
||||
private readonly document = inject(DOCUMENT);
|
||||
private readonly elementRef = inject(ElementRef<HTMLElement>);
|
||||
|
||||
@@ -72,6 +72,5 @@ describe('ExternalLink', () => {
|
||||
></a>
|
||||
`,
|
||||
imports: [ExternalLink, RouterLink],
|
||||
standalone: true,
|
||||
})
|
||||
class ExampleComponentWithLinks {}
|
||||
|
||||
@@ -20,12 +20,10 @@ import {WINDOW} from '../../providers/index';
|
||||
host: {
|
||||
'[attr.target]': 'target',
|
||||
},
|
||||
standalone: true,
|
||||
})
|
||||
export class ExternalLink implements OnInit {
|
||||
private readonly anchor: ElementRef<HTMLAnchorElement> = inject(ElementRef);
|
||||
private readonly platformId = inject(PLATFORM_ID);
|
||||
private readonly window = inject(WINDOW);
|
||||
|
||||
target?: '_blank' | '_self' | '_parent' | '_top' | '';
|
||||
|
||||
@@ -38,7 +36,7 @@ export class ExternalLink implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isExternalLink(this.anchor.nativeElement.href, this.window.location.origin)) {
|
||||
if (isExternalLink(this.anchor.nativeElement.href)) {
|
||||
this.target = '_blank';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import {SearchResult} from '../../interfaces/search-results';
|
||||
|
||||
@Directive({
|
||||
selector: '[docsSearchItem]',
|
||||
standalone: true,
|
||||
host: {
|
||||
'[class.active]': 'isActive',
|
||||
},
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
"name": "@angular/docs",
|
||||
"version": "0.0.0-PLACEHOLDER",
|
||||
"peerDependencies": {
|
||||
"@angular/cdk": "^19.0.0-next",
|
||||
"@angular/common": "^19.0.0-next",
|
||||
"@angular/core": "^19.0.0-next",
|
||||
"@angular/forms": "^19.0.0-next",
|
||||
"@angular/material": "^19.0.0-next",
|
||||
"@angular/platform-browser": "^19.0.0-next",
|
||||
"@angular/router": "^19.0.0-next",
|
||||
"@angular/ssr": "^19.0.0-next",
|
||||
"@angular/cdk": "^19.1.0-next",
|
||||
"@angular/common": "^19.1.0-next",
|
||||
"@angular/core": "^19.1.0-next",
|
||||
"@angular/forms": "^19.1.0-next",
|
||||
"@angular/material": "^19.1.0-next",
|
||||
"@angular/platform-browser": "^19.1.0-next",
|
||||
"@angular/router": "^19.1.0-next",
|
||||
"@angular/ssr": "^19.1.0-next",
|
||||
"algoliasearch": "^5.0.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
@@ -21,7 +21,7 @@
|
||||
"fflate": "^0.8.2",
|
||||
"html-entities": "~2.5.2",
|
||||
"jsdom": "~25.0.0",
|
||||
"marked": "~14.1.0",
|
||||
"marked": "~15.0.0",
|
||||
"mermaid": "^11.0.0",
|
||||
"shiki": "^1.10.3"
|
||||
},
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
load("@angular//tools/esm-interop:index.bzl", "nodejs_binary")
|
||||
load("@npm//@angular/build-tooling/bazel/esbuild:index.bzl", "esbuild")
|
||||
load("@npm//@angular/build-tooling/bazel:defaults.bzl", "ts_library")
|
||||
load("@npm//@angular/build-tooling/bazel/esbuild:index.bzl", "esbuild_esm_bundle")
|
||||
|
||||
package(default_visibility = ["//adev/shared-docs/pipeline/api-gen:__subpackages__"])
|
||||
|
||||
esbuild(
|
||||
esbuild_esm_bundle(
|
||||
name = "bin",
|
||||
entry_point = ":index.ts",
|
||||
external = [
|
||||
"@angular/compiler-cli",
|
||||
"typescript",
|
||||
],
|
||||
format = "esm",
|
||||
output = "bin.mjs",
|
||||
platform = "node",
|
||||
target = "es2022",
|
||||
@@ -24,7 +23,12 @@ esbuild(
|
||||
|
||||
ts_library(
|
||||
name = "extract_api_to_json_lib",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
srcs = glob(
|
||||
["**/*.ts"],
|
||||
exclude = [
|
||||
"**/*.spec.ts",
|
||||
],
|
||||
),
|
||||
devmode_module = "commonjs",
|
||||
tsconfig = "//adev:tsconfig.json",
|
||||
deps = [
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import path from 'path';
|
||||
// @ts-ignore This compiles fine, but Webstorm doesn't like the ESM import in a CJS context.
|
||||
@@ -11,6 +19,7 @@ import {
|
||||
ClassEntry,
|
||||
} from '@angular/compiler-cli';
|
||||
import ts from 'typescript';
|
||||
import {EXAMPLES_PATH, interpolateCodeExamples} from './interpolate_code_examples';
|
||||
|
||||
function main() {
|
||||
const [paramFilePath] = process.argv.slice(2);
|
||||
@@ -52,12 +61,20 @@ function main() {
|
||||
rootDir: '.',
|
||||
skipLibCheck: true,
|
||||
target: ts.ScriptTarget.ES2022,
|
||||
// This is necessary because otherwise types that include `| null` are not included in the documentation.
|
||||
strictNullChecks: true,
|
||||
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
||||
experimentalDecorators: true,
|
||||
};
|
||||
|
||||
// Code examples should not be fed to the compiler.
|
||||
const filesWithoutExamples = srcs.split(',').filter((src) => !src.startsWith(EXAMPLES_PATH));
|
||||
const compilerHost = createCompilerHost({options: compilerOptions});
|
||||
const program: NgtscProgram = new NgtscProgram(srcs.split(','), compilerOptions, compilerHost);
|
||||
const program: NgtscProgram = new NgtscProgram(
|
||||
filesWithoutExamples,
|
||||
compilerOptions,
|
||||
compilerHost,
|
||||
);
|
||||
|
||||
const extraEntries: DocEntry[] = (extraEntriesSrcs ?? '')
|
||||
.split(',')
|
||||
@@ -70,6 +87,8 @@ function main() {
|
||||
const extractedEntries = apiDoc.entries;
|
||||
const combinedEntries = extractedEntries.concat(extraEntries);
|
||||
|
||||
interpolateCodeExamples(combinedEntries);
|
||||
|
||||
const normalized = moduleName.replace('@', '').replace(/[\/]/g, '_');
|
||||
|
||||
const output = JSON.stringify({
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {DocEntry} from '@angular/compiler-cli';
|
||||
import {basename, dirname, resolve} from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export const EXAMPLES_PATH = 'packages/examples';
|
||||
|
||||
// It's assumed that all markers start with #.
|
||||
const REGION_START_MARKER = '#docregion';
|
||||
const REGION_END_MARKER = '#enddocregion';
|
||||
|
||||
// Used only for clean up of leftovers comments
|
||||
const TS_COMMENT_REGION_REGEX = /[ \t]*\/\/[ \t]*#(docregion|enddocregion)[ \t]*[\w-]*(\n|$)/g;
|
||||
const HTML_COMMENT_REGION_REGEX =
|
||||
/[ \t]*<!--[ \t]*#(docregion|enddocregion)[ \t]*[\w-]*[ \t]*-->(\n|$)/g;
|
||||
|
||||
const examplesCache = new Map<string, Map<string, string>>(); // <file_path, <region, example>>
|
||||
|
||||
type FileType = 'ts' | 'js' | 'html';
|
||||
|
||||
type RegionStartToken = {name: string; startIdx: number};
|
||||
|
||||
const MD_CTYPE_MAP: {[key in FileType]: string} = {
|
||||
'ts': 'angular-ts',
|
||||
'js': 'javascript',
|
||||
'html': 'angular-html',
|
||||
};
|
||||
|
||||
/**
|
||||
* Interpolate code examples in the `DocEntry`-ies JSDocs content and raw comments in place.
|
||||
* The examples are wrapped in a Markdown code block.
|
||||
*
|
||||
* @param entries Target `DocEntry`-ies array that has its examples substituted with the actual TS code.
|
||||
* @param examplesFiles A set with all examples files sources.
|
||||
*/
|
||||
export function interpolateCodeExamples(entries: DocEntry[]): void {
|
||||
for (const entry of entries) {
|
||||
entry.rawComment = replaceExample(entry.rawComment);
|
||||
|
||||
for (const jsdocTag of entry.jsdocTags) {
|
||||
jsdocTag.comment = replaceExample(jsdocTag.comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceExample(text: string): string {
|
||||
const examplesTagRegex = /{@example (\S+) region=(['"])([^'"]+)\2\s*}/g;
|
||||
|
||||
return text.replace(examplesTagRegex, (_: string, path: string, __: string, region: string) => {
|
||||
const example = getExample(path, region);
|
||||
if (!example) {
|
||||
throw new Error(`Missing code example ${EXAMPLES_PATH}/${path}#${region}`);
|
||||
}
|
||||
|
||||
return example;
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the example wrapped in a Markdown code block or an empty string, if the example doesn't exist. */
|
||||
function getExample(path: string, region: string): string {
|
||||
let fileExamples = examplesCache.get(path);
|
||||
const src = `${EXAMPLES_PATH}/${path}`;
|
||||
const fullPath = resolve(dirname(src), basename(src));
|
||||
const fileType = path.split('.').pop() as FileType;
|
||||
|
||||
if (!fileExamples) {
|
||||
const contents = fs.readFileSync(fullPath, {encoding: 'utf8'});
|
||||
|
||||
fileExamples = extractExamplesFromContents(contents, fileType);
|
||||
examplesCache.set(path, fileExamples);
|
||||
}
|
||||
|
||||
const example = fileExamples.get(region);
|
||||
if (!example) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return `\`\`\`${MD_CTYPE_MAP[fileType]}\n${example}\n\`\`\``;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract `#docregion` examples from file contents represented as a string.
|
||||
*
|
||||
* @param contents File contents represented as a string
|
||||
* @param fileType File type
|
||||
* @returns A map with all available examples in a given file contents
|
||||
*/
|
||||
function extractExamplesFromContents(contents: string, fileType: FileType): Map<string, string> {
|
||||
let markerBuffer = '';
|
||||
let paramBuffer = '';
|
||||
let markerFound = false;
|
||||
|
||||
const regionStack: RegionStartToken[] = [];
|
||||
const examples = new Map<string, string>();
|
||||
|
||||
// Iterate over the contents string and determine the start and end indices.
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
const char = contents[i];
|
||||
|
||||
// Build the marker string.
|
||||
if (char === REGION_START_MARKER[0]) {
|
||||
markerBuffer = char;
|
||||
} else if (markerBuffer && !markerFound) {
|
||||
if (!/\s/.test(char)) {
|
||||
markerBuffer += char;
|
||||
} else {
|
||||
markerFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (markerFound && !/\s/.test(char)) {
|
||||
// Build a param string.
|
||||
paramBuffer += char;
|
||||
} else if ((markerFound && char === '\n') || (paramBuffer && char === ' ')) {
|
||||
// Resolve found marker.
|
||||
switch (markerBuffer) {
|
||||
case REGION_START_MARKER:
|
||||
// Push the current index to the stack, if a start marker.
|
||||
regionStack.push({
|
||||
name: paramBuffer,
|
||||
startIdx: i + 1,
|
||||
});
|
||||
break;
|
||||
case REGION_END_MARKER:
|
||||
if (regionStack.length) {
|
||||
// Check whether the end marker has a parameter or not.
|
||||
// If not, pop from the stack (it corresponds to the last inserted token).
|
||||
// If yes, pull the corresponding token.
|
||||
let tokenIdx = paramBuffer ? regionStack.findIndex((t) => t.name === paramBuffer) : -1;
|
||||
let token: RegionStartToken;
|
||||
|
||||
if (tokenIdx > -1) {
|
||||
token = regionStack.splice(tokenIdx, 1)[0];
|
||||
} else {
|
||||
token = regionStack.pop()!;
|
||||
}
|
||||
|
||||
// Caclculate the end index (should represent the start of the marker).
|
||||
const endIdx =
|
||||
i - REGION_END_MARKER.length - (paramBuffer ? paramBuffer.length + 1 : 0);
|
||||
|
||||
let example = contents.substring(token.startIdx, endIdx);
|
||||
example = removeLeftoverCommentsFromExample(example, fileType);
|
||||
|
||||
// A code example can be composed by multiple regions;
|
||||
// hence, we check for an existing one.
|
||||
const existing = examples.get(token.name);
|
||||
example = (!!existing ? existing + '\n' : '') + example;
|
||||
examples.set(token.name, example);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
markerBuffer = '';
|
||||
paramBuffer = '';
|
||||
}
|
||||
}
|
||||
|
||||
return examples;
|
||||
}
|
||||
|
||||
function removeLeftoverCommentsFromExample(example: string, fileType: FileType): string {
|
||||
example = example.trim();
|
||||
|
||||
switch (fileType) {
|
||||
case 'ts':
|
||||
case 'js':
|
||||
return example
|
||||
.replace(/\n[ \t]*?\/\/\s*$/, '') // We can have only a trailing TS comment leftover
|
||||
.replace(TS_COMMENT_REGION_REGEX, '');
|
||||
case 'html':
|
||||
return example
|
||||
.replace(/(^\s*-->\n)|(\n[ \t]*?<!--\s*$)/g, '')
|
||||
.replace(HTML_COMMENT_REGION_REGEX, '');
|
||||
default:
|
||||
return example;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
load("//adev/shared-docs/pipeline/api-gen/extraction:extract_api_to_json.bzl", "extract_api_to_json")
|
||||
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
|
||||
|
||||
package(default_visibility = ["//adev/shared-docs/pipeline/api-gen:__subpackages__"])
|
||||
|
||||
@@ -39,3 +40,21 @@ filegroup(
|
||||
name = "source_files",
|
||||
srcs = ["fake-source.ts"],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "unit_test_lib",
|
||||
testonly = True,
|
||||
srcs =
|
||||
glob(["*.spec.ts"]) + [
|
||||
"fake-examples.ts",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/pipeline/api-gen/extraction:extract_api_to_json_lib",
|
||||
"@angular//packages/compiler-cli",
|
||||
],
|
||||
)
|
||||
|
||||
jasmine_node_test(
|
||||
name = "unit_tests",
|
||||
deps = [":unit_test_lib"],
|
||||
)
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
export class Version {
|
||||
constructor(public sha: string = '') {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*!
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
const JSDOCS_RAWCONTENT_FILE = `
|
||||
// #docregion class
|
||||
class Foo {}
|
||||
// #enddocregion
|
||||
|
||||
// #docregion function
|
||||
function bar() {}
|
||||
// #enddocregion
|
||||
`;
|
||||
|
||||
const SINGLE_EXAMPLE_FILE = `
|
||||
import {foo} from 'bar';
|
||||
|
||||
// #docregion foo
|
||||
foo('Hello world!');
|
||||
// #enddocregion
|
||||
`;
|
||||
|
||||
const MULTIPLE_EXAMPLES_FILE = `
|
||||
import {foo} from 'bar';
|
||||
|
||||
// #docregion example-1
|
||||
foo(null);
|
||||
// #enddocregion
|
||||
|
||||
foo('');
|
||||
|
||||
// #docregion example-2
|
||||
type Test = 'a' | 'b';
|
||||
// #enddocregion
|
||||
`;
|
||||
|
||||
const NESTED_EXAMPLES_FILE = `
|
||||
import {foo} from 'bar';
|
||||
|
||||
// #docregion out
|
||||
function baz() {
|
||||
// #docregion in
|
||||
const leet = 1337;
|
||||
// #enddocregion
|
||||
}
|
||||
// #enddocregion
|
||||
`;
|
||||
|
||||
const REGIONS_EXAMPLE_FILE = `
|
||||
import {foo} from 'bar';
|
||||
|
||||
// #docregion fn
|
||||
function baz() {
|
||||
// #enddocregion
|
||||
const leet = 1337;
|
||||
|
||||
if (true) {
|
||||
console.log(leet);
|
||||
}
|
||||
|
||||
// #docregion fn
|
||||
}
|
||||
// #enddocregion
|
||||
`;
|
||||
|
||||
const OVERLAP_PARAM_EXAMPLE_FILE = `
|
||||
// #docregion 1st
|
||||
import {foo} from 'bar';
|
||||
|
||||
// #docregion 2nd
|
||||
class Baz {
|
||||
constructor () {}
|
||||
// #enddocregion 1st
|
||||
|
||||
example () {}
|
||||
}
|
||||
// #enddocregion 2nd
|
||||
`;
|
||||
|
||||
const COMPLEX_EXAMPLE_FILE = `
|
||||
import {foo} from 'bar';
|
||||
// #docregion ex-1
|
||||
import {baz} from 'foo';
|
||||
// #enddocregion
|
||||
|
||||
// #docregion ex-2
|
||||
function test() {}
|
||||
// #enddocregion
|
||||
|
||||
// #docregion ex-3
|
||||
function test2() {
|
||||
// #docregion ex-4
|
||||
const leet = 1337;
|
||||
// #enddocregion
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
// #docregion ex-2
|
||||
baz();
|
||||
// #enddocregion
|
||||
|
||||
// #docregion ex-5
|
||||
const A = 'a';
|
||||
// #docregion ex-6
|
||||
const B = 'b';
|
||||
// #enddocregion ex-5
|
||||
const C = 'c';
|
||||
// #enddocregion ex-6
|
||||
`;
|
||||
|
||||
const HTML_EXAMPLE_FILE = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Angular</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- #docregion tags -->
|
||||
<i>Foo</i>
|
||||
<!-- #enddocregion -->
|
||||
<strong>Bar</strong>
|
||||
<!-- #docregion tags -->
|
||||
<p>Baz</p>
|
||||
<!-- #enddocregion -->
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
export const mockReadFileSync = (path: string): string => {
|
||||
switch (path.split('/').pop()) {
|
||||
case 'jsdocs_raw.ts':
|
||||
return JSDOCS_RAWCONTENT_FILE;
|
||||
case 'single.ts':
|
||||
return SINGLE_EXAMPLE_FILE;
|
||||
case 'multi.ts':
|
||||
return MULTIPLE_EXAMPLES_FILE;
|
||||
case 'nested.ts':
|
||||
return NESTED_EXAMPLES_FILE;
|
||||
case 'regions.ts':
|
||||
return REGIONS_EXAMPLE_FILE;
|
||||
case 'overlap.ts':
|
||||
return OVERLAP_PARAM_EXAMPLE_FILE;
|
||||
case 'complex.ts':
|
||||
return COMPLEX_EXAMPLE_FILE;
|
||||
case 'index.html':
|
||||
return HTML_EXAMPLE_FILE;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
// @ts-ignore Intentionally nonexistent path for testing purposes.
|
||||
import {Version} from '@angular/dummy-package';
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*!
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import {interpolateCodeExamples} from '../interpolate_code_examples';
|
||||
import {DocEntry} from '@angular/compiler-cli';
|
||||
import {mockReadFileSync} from './fake-examples';
|
||||
|
||||
const tsMdBlock = (code: string) => '```angular-ts\n' + code + '\n```';
|
||||
const htmlMdBlock = (code: string) => '```angular-html\n' + code + '\n```';
|
||||
|
||||
const entriesBuilder = (comment: string): DocEntry[] => [
|
||||
{jsdocTags: [], rawComment: comment} as unknown as DocEntry,
|
||||
];
|
||||
|
||||
const getComment = (entries: DocEntry[]) => entries[0].rawComment;
|
||||
|
||||
describe('interpolate_code_examples', () => {
|
||||
beforeAll(() => {
|
||||
spyOn(fs, 'readFileSync').and.callFake(mockReadFileSync as any);
|
||||
});
|
||||
|
||||
it('should interpolate both JSDoc tags comments and raw comment', () => {
|
||||
const entries: Partial<DocEntry>[] = [
|
||||
{
|
||||
jsdocTags: [
|
||||
{
|
||||
name: '',
|
||||
comment: `{@example dummy/jsdocs_raw.ts region='class'}`,
|
||||
},
|
||||
],
|
||||
rawComment: `{@example dummy/jsdocs_raw.ts region='function'}`,
|
||||
},
|
||||
];
|
||||
|
||||
interpolateCodeExamples(entries as DocEntry[]);
|
||||
|
||||
const {jsdocTags, rawComment} = entries[0];
|
||||
|
||||
expect(jsdocTags![0].comment).toEqual(tsMdBlock('class Foo {}'));
|
||||
expect(rawComment).toEqual(tsMdBlock('function bar() {}'));
|
||||
});
|
||||
|
||||
it('should interpolate a single example', () => {
|
||||
const entries = entriesBuilder(`Code: {@example dummy/single.ts region='foo'}`);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
expect(getComment(entries)).toEqual('Code: ' + tsMdBlock("foo('Hello world!');"));
|
||||
});
|
||||
|
||||
it('should interpolate multiple examples', () => {
|
||||
const entries = entriesBuilder(
|
||||
`First: {@example dummy/multi.ts region='example-1'} Second: {@example dummy/multi.ts region='example-2'}`,
|
||||
);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
expect(getComment(entries)).toEqual(
|
||||
`First: ${tsMdBlock('foo(null);')} Second: ${tsMdBlock("type Test = 'a' | 'b';")}`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should interpolate nested examples', () => {
|
||||
const entries = entriesBuilder(
|
||||
`Outer: {@example dummy/nested.ts region='out'} Inner: {@example dummy/nested.ts region='in'}`,
|
||||
);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
const outer = `function baz() {
|
||||
const leet = 1337;
|
||||
}`;
|
||||
|
||||
expect(getComment(entries)).toEqual(
|
||||
`Outer: ${tsMdBlock(outer)} Inner: ${tsMdBlock('const leet = 1337;')}`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should interpolate a single example with multiple regions', () => {
|
||||
const entries = entriesBuilder(`Code: {@example dummy/regions.ts region='fn'}`);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
expect(getComment(entries)).toEqual('Code: ' + tsMdBlock('function baz() {\n}'));
|
||||
});
|
||||
|
||||
it('should support examples defined by overlapping regions', () => {
|
||||
const entries = entriesBuilder(
|
||||
`1st: {@example dummy/overlap.ts region='1st'} 2nd: {@example dummy/overlap.ts region='2nd'}`,
|
||||
);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
const first = `import {foo} from 'bar';
|
||||
|
||||
class Baz {
|
||||
constructor () {}`;
|
||||
|
||||
const second = `class Baz {
|
||||
constructor () {}
|
||||
|
||||
example () {}
|
||||
}`;
|
||||
|
||||
expect(getComment(entries)).toEqual(`1st: ${tsMdBlock(first)} 2nd: ${tsMdBlock(second)}`);
|
||||
});
|
||||
|
||||
it('should support multiple region combinations simultaneously', () => {
|
||||
const targetStr = `1: {@example dummy/complex.ts region='ex-1'}
|
||||
2: {@example dummy/complex.ts region='ex-2'}
|
||||
3: {@example dummy/complex.ts region='ex-3'}
|
||||
4: {@example dummy/complex.ts region='ex-4'}
|
||||
5: {@example dummy/complex.ts region='ex-5'}
|
||||
6: {@example dummy/complex.ts region='ex-6'}`;
|
||||
|
||||
const entries = entriesBuilder(targetStr);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
const output = `1: ${tsMdBlock("import {baz} from 'foo';")}
|
||||
2: ${tsMdBlock('function test() {}\nbaz();')}
|
||||
3: ${tsMdBlock(`function test2() {
|
||||
const leet = 1337;
|
||||
}`)}
|
||||
4: ${tsMdBlock('const leet = 1337;')}
|
||||
5: ${tsMdBlock("const A = 'a';\nconst B = 'b';")}
|
||||
6: ${tsMdBlock("const B = 'b';\nconst C = 'c';")}`;
|
||||
|
||||
expect(getComment(entries)).toEqual(output);
|
||||
});
|
||||
|
||||
it('should support HTML files', () => {
|
||||
const entries = entriesBuilder(`HTML: {@example dummy/index.html region='tags'}`);
|
||||
|
||||
interpolateCodeExamples(entries);
|
||||
|
||||
expect(getComment(entries)).toEqual(`HTML: ${htmlMdBlock(' <i>Foo</i>\n <p>Baz</p>')}`);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,13 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
// @ts-ignore This compiles fine, but Webstorm doesn't like the ESM import in a CJS context.
|
||||
import type {DocEntry, EntryCollection, JsDocTagEntry} from '@angular/compiler-cli';
|
||||
import type {DocEntry, EntryCollection, JsDocTagEntry, FunctionEntry} from '@angular/compiler-cli';
|
||||
|
||||
export interface ManifestEntry {
|
||||
name: string;
|
||||
@@ -17,78 +25,37 @@ export type Manifest = {
|
||||
entries: ManifestEntry[];
|
||||
}[];
|
||||
|
||||
/** Gets a unique lookup key for an API, e.g. "@angular/core/ElementRef". */
|
||||
function getApiLookupKey(moduleName: string, name: string) {
|
||||
return `${moduleName}/${name}`;
|
||||
}
|
||||
/** Gets whether the given entry has a given JsDoc tag. */
|
||||
function hasTag(entry: DocEntry | FunctionEntry, tag: string, every = false) {
|
||||
const hasTagName = (t: JsDocTagEntry) => t.name === tag;
|
||||
|
||||
/** Gets whether the given entry has the "@deprecated" JsDoc tag. */
|
||||
function hasDeprecatedTag(entry: DocEntry) {
|
||||
return entry.jsdocTags.some((t: JsDocTagEntry) => t.name === 'deprecated');
|
||||
}
|
||||
if (every && 'signatures' in entry && entry.signatures.length > 1) {
|
||||
// For overloads we need to check all signatures.
|
||||
return entry.signatures.every((s) => s.jsdocTags.some(hasTagName));
|
||||
}
|
||||
|
||||
/** Gets whether the given entry has the "@developerPreview" JsDoc tag. */
|
||||
function hasDeveloperPreviewTag(entry: DocEntry) {
|
||||
return entry.jsdocTags.some((t: JsDocTagEntry) => t.name === 'developerPreview');
|
||||
}
|
||||
const jsdocTags = [
|
||||
...entry.jsdocTags,
|
||||
...((entry as FunctionEntry).signatures?.flatMap((s) => s.jsdocTags) ?? []),
|
||||
...((entry as FunctionEntry).implementation?.jsdocTags ?? []),
|
||||
];
|
||||
|
||||
/** Gets whether the given entry has the "@experimental" JsDoc tag. */
|
||||
function hasExperimentalTag(entry: DocEntry) {
|
||||
return entry.jsdocTags.some((t: JsDocTagEntry) => t.name === 'experimental');
|
||||
return jsdocTags.some(hasTagName);
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is deprecated in the manifest. */
|
||||
function isDeprecated(
|
||||
lookup: Map<string, DocEntry[]>,
|
||||
moduleName: string,
|
||||
entry: DocEntry,
|
||||
): boolean {
|
||||
const entriesWithSameName = lookup.get(getApiLookupKey(moduleName, entry.name));
|
||||
|
||||
// If there are multiple entries with the same name in the same module, only
|
||||
// mark them as deprecated if *all* of the entries with the same name are
|
||||
// deprecated (e.g. function overloads).
|
||||
if (entriesWithSameName && entriesWithSameName.length > 1) {
|
||||
return entriesWithSameName.every((entry) => hasDeprecatedTag(entry));
|
||||
}
|
||||
|
||||
return hasDeprecatedTag(entry);
|
||||
function isDeprecated(entry: DocEntry): boolean {
|
||||
return hasTag(entry, 'deprecated', /* every */ true);
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is hasDeveloperPreviewTag in the manifest. */
|
||||
function isDeveloperPreview(
|
||||
lookup: Map<string, DocEntry[]>,
|
||||
moduleName: string,
|
||||
entry: DocEntry,
|
||||
): boolean {
|
||||
const entriesWithSameName = lookup.get(getApiLookupKey(moduleName, entry.name));
|
||||
|
||||
// If there are multiple entries with the same name in the same module, only
|
||||
// mark them as developer preview if *all* of the entries with the same name
|
||||
// are hasDeveloperPreviewTag (e.g. function overloads).
|
||||
if (entriesWithSameName && entriesWithSameName.length > 1) {
|
||||
return entriesWithSameName.every((entry) => hasDeveloperPreviewTag(entry));
|
||||
}
|
||||
|
||||
return hasDeveloperPreviewTag(entry);
|
||||
function isDeveloperPreview(entry: DocEntry): boolean {
|
||||
return hasTag(entry, 'developerPreview');
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is hasExperimentalTag in the manifest. */
|
||||
function isExperimental(
|
||||
lookup: Map<string, DocEntry[]>,
|
||||
moduleName: string,
|
||||
entry: DocEntry,
|
||||
): boolean {
|
||||
const entriesWithSameName = lookup.get(getApiLookupKey(moduleName, entry.name));
|
||||
|
||||
// If there are multiple entries with the same name in the same module, only
|
||||
// mark them as developer preview if *all* of the entries with the same name
|
||||
// are hasExperimentalTag (e.g. function overloads).
|
||||
if (entriesWithSameName && entriesWithSameName.length > 1) {
|
||||
return entriesWithSameName.every((entry) => hasExperimentalTag(entry));
|
||||
}
|
||||
|
||||
return hasExperimentalTag(entry);
|
||||
function isExperimental(entry: DocEntry): boolean {
|
||||
return hasTag(entry, 'experimental');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,31 +63,14 @@ function isExperimental(
|
||||
* extract_api_to_json.
|
||||
*/
|
||||
export function generateManifest(apiCollections: EntryCollection[]): Manifest {
|
||||
// Filter out repeated entries for function overloads, but also keep track of
|
||||
// all symbols keyed to their lookup key. We need this lookup later for
|
||||
// determining whether to mark an entry as deprecated.
|
||||
const entryLookup = new Map<string, DocEntry[]>();
|
||||
for (const collection of apiCollections) {
|
||||
collection.entries = collection.entries.filter((entry) => {
|
||||
const lookupKey = getApiLookupKey(collection.moduleName, entry.name);
|
||||
if (entryLookup.has(lookupKey)) {
|
||||
entryLookup.get(lookupKey)!.push(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
entryLookup.set(lookupKey, [entry]);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
const manifest: Manifest = [];
|
||||
for (const collection of apiCollections) {
|
||||
const entries = collection.entries.map((entry) => ({
|
||||
const entries = collection.entries.map((entry: DocEntry) => ({
|
||||
name: entry.name,
|
||||
type: entry.entryType,
|
||||
isDeprecated: isDeprecated(entryLookup, collection.moduleName, entry),
|
||||
isDeveloperPreview: isDeveloperPreview(entryLookup, collection.moduleName, entry),
|
||||
isExperimental: isExperimental(entryLookup, collection.moduleName, entry),
|
||||
isDeprecated: isDeprecated(entry),
|
||||
isDeveloperPreview: isDeveloperPreview(entry),
|
||||
isExperimental: isExperimental(entry),
|
||||
}));
|
||||
|
||||
const existingEntry = manifest.find((entry) => entry.moduleName === collection.moduleName);
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import {generateManifest} from './generate_manifest';
|
||||
import type {EntryCollection} from '@angular/compiler-cli';
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
export function superNavigate() {}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
// @ts-ignore This compiles fine, but Webstorm doesn't like the ESM import in a CJS context.
|
||||
import {DocEntry, EntryType, JsDocTagEntry} from '@angular/compiler-cli';
|
||||
import {DocEntry, EntryType, FunctionEntry, JsDocTagEntry} from '@angular/compiler-cli';
|
||||
import {generateManifest, Manifest} from '../generate_manifest';
|
||||
|
||||
describe('api manifest generation', () => {
|
||||
@@ -178,44 +186,40 @@ describe('api manifest generation', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should deduplicate function overloads', () => {
|
||||
const manifest = generateManifest([
|
||||
{
|
||||
moduleName: '@angular/core',
|
||||
entries: [
|
||||
entry({name: 'save', entryType: EntryType.Function}),
|
||||
entry({name: 'save', entryType: EntryType.Function}),
|
||||
],
|
||||
normalizedModuleName: 'angular_core',
|
||||
moduleLabel: 'core',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(manifest).toEqual([
|
||||
{
|
||||
moduleName: '@angular/core',
|
||||
moduleLabel: 'core',
|
||||
normalizedModuleName: 'angular_core',
|
||||
entries: [
|
||||
{
|
||||
name: 'save',
|
||||
type: EntryType.Function,
|
||||
isDeprecated: false,
|
||||
isDeveloperPreview: false,
|
||||
isExperimental: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not mark a function as deprecated if only one overload is deprecated', () => {
|
||||
const manifest = generateManifest([
|
||||
{
|
||||
moduleName: '@angular/core',
|
||||
entries: [
|
||||
entry({name: 'save', entryType: EntryType.Function}),
|
||||
entry({name: 'save', entryType: EntryType.Function, jsdocTags: jsdocTags('deprecated')}),
|
||||
functionEntry({
|
||||
name: 'save',
|
||||
entryType: EntryType.Function,
|
||||
jsdocTags: [],
|
||||
signatures: [
|
||||
{
|
||||
name: 'save',
|
||||
returnType: 'void',
|
||||
jsdocTags: [],
|
||||
description: '',
|
||||
entryType: EntryType.Function,
|
||||
params: [],
|
||||
generics: [],
|
||||
isNewType: false,
|
||||
rawComment: '',
|
||||
},
|
||||
{
|
||||
name: 'save',
|
||||
returnType: 'void',
|
||||
jsdocTags: jsdocTags('deprecated'),
|
||||
description: '',
|
||||
entryType: EntryType.Function,
|
||||
params: [],
|
||||
generics: [],
|
||||
isNewType: false,
|
||||
rawComment: '',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
normalizedModuleName: 'angular_core',
|
||||
moduleLabel: 'core',
|
||||
@@ -245,8 +249,35 @@ describe('api manifest generation', () => {
|
||||
{
|
||||
moduleName: '@angular/core',
|
||||
entries: [
|
||||
entry({name: 'save', entryType: EntryType.Function, jsdocTags: jsdocTags('deprecated')}),
|
||||
entry({name: 'save', entryType: EntryType.Function, jsdocTags: jsdocTags('deprecated')}),
|
||||
functionEntry({
|
||||
name: 'save',
|
||||
entryType: EntryType.Function,
|
||||
jsdocTags: [],
|
||||
signatures: [
|
||||
{
|
||||
name: 'save',
|
||||
returnType: 'void',
|
||||
jsdocTags: jsdocTags('deprecated'),
|
||||
description: '',
|
||||
entryType: EntryType.Function,
|
||||
params: [],
|
||||
generics: [],
|
||||
isNewType: false,
|
||||
rawComment: '',
|
||||
},
|
||||
{
|
||||
name: 'save',
|
||||
returnType: 'void',
|
||||
jsdocTags: jsdocTags('deprecated'),
|
||||
description: '',
|
||||
entryType: EntryType.Function,
|
||||
params: [],
|
||||
generics: [],
|
||||
isNewType: false,
|
||||
rawComment: '',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
normalizedModuleName: 'angular_core',
|
||||
moduleLabel: 'core',
|
||||
@@ -376,6 +407,15 @@ function entry(patch: Partial<DocEntry>): DocEntry {
|
||||
};
|
||||
}
|
||||
|
||||
function functionEntry(patch: Partial<FunctionEntry>): FunctionEntry {
|
||||
return entry({
|
||||
entryType: EntryType.Function,
|
||||
implementation: [],
|
||||
signatures: [],
|
||||
...patch,
|
||||
} as FunctionEntry) as FunctionEntry;
|
||||
}
|
||||
|
||||
/** Creates a fake jsdoc tag entry list that contains a tag with the given name */
|
||||
function jsdocTags(name: string): JsDocTagEntry[] {
|
||||
return [{name, comment: ''}];
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
/** The JSON data file format for CLI reference info. */
|
||||
export interface CliCommand {
|
||||
name: string;
|
||||
|
||||
@@ -94,7 +94,9 @@ export interface ConstantEntry extends DocEntry {
|
||||
}
|
||||
|
||||
/** Documentation entity for a type alias. */
|
||||
export type TypeAliasEntry = ConstantEntry;
|
||||
export interface TypeAliasEntry extends ConstantEntry {
|
||||
generics: GenericEntry[];
|
||||
}
|
||||
|
||||
/** Documentation entity for a TypeScript class. */
|
||||
export interface ClassEntry extends DocEntry {
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {
|
||||
ClassEntry,
|
||||
ConstantEntry,
|
||||
@@ -8,6 +16,7 @@ import {
|
||||
FunctionEntry,
|
||||
InitializerApiFunctionEntry,
|
||||
InterfaceEntry,
|
||||
JsDocTagEntry,
|
||||
MemberEntry,
|
||||
MemberType,
|
||||
MethodEntry,
|
||||
@@ -125,7 +134,7 @@ export function isSetterEntry(entry: MemberEntry): entry is PropertyEntry {
|
||||
|
||||
/** Gets whether the given entry is deprecated. */
|
||||
export function isDeprecatedEntry<T extends HasJsDocTags>(entry: T) {
|
||||
return entry.jsdocTags.some((tag) => tag.name === 'deprecated');
|
||||
return hasTag(entry, 'deprecated', /* every */ true);
|
||||
}
|
||||
|
||||
export function getDeprecatedEntry<T extends HasJsDocTags>(entry: T) {
|
||||
@@ -133,13 +142,30 @@ export function getDeprecatedEntry<T extends HasJsDocTags>(entry: T) {
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is developer preview. */
|
||||
export function isDeveloperPreview<T extends HasJsDocTags>(entry: T) {
|
||||
return entry.jsdocTags.some((tag) => tag.name === 'developerPreview');
|
||||
export function isDeveloperPreview<T extends HasJsDocTags | FunctionEntry>(entry: T) {
|
||||
return hasTag(entry, 'developerPreview', false);
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is is experimental. */
|
||||
export function isExperimental<T extends HasJsDocTags>(entry: T) {
|
||||
return entry.jsdocTags.some((tag) => tag.name === 'experimental');
|
||||
return hasTag(entry, 'experimental');
|
||||
}
|
||||
/** Gets whether the given entry has a given JsDoc tag. */
|
||||
function hasTag<T extends HasJsDocTags | FunctionEntry>(entry: T, tag: string, every = false) {
|
||||
const hasTagName = (t: JsDocTagEntry) => t.name === tag;
|
||||
|
||||
if (every && 'signatures' in entry && entry.signatures.length > 1) {
|
||||
// For overloads we need to check all signatures.
|
||||
return entry.signatures.every((s) => s.jsdocTags.some(hasTagName));
|
||||
}
|
||||
|
||||
const jsdocTags = [
|
||||
...entry.jsdocTags,
|
||||
...((entry as FunctionEntry).signatures?.flatMap((s) => s.jsdocTags) ?? []),
|
||||
...((entry as FunctionEntry).implementation?.jsdocTags ?? []),
|
||||
];
|
||||
|
||||
return jsdocTags.some(hasTagName);
|
||||
}
|
||||
|
||||
/** Gets whether the given entry is a cli entry. */
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @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.dev/license
|
||||
*/
|
||||
|
||||
import {JsDocTagEntry, MemberEntry, ParameterEntry} from '../entities';
|
||||
|
||||
import {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user