mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
348 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Starting Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
|
||||
@@ -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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/saucelabs@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8d3cb7b9e1b3edd1dc168376689d27407d2dfa7a
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
- 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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
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@8360e1562157bf2bd918701be6f43323c6445c76
|
||||
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
|
||||
@@ -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__",
|
||||
|
||||
+256
-356
@@ -1,76 +1,252 @@
|
||||
<a name="18.2.9"></a>
|
||||
# 18.2.9 (2024-10-23)
|
||||
<a name="19.0.2"></a>
|
||||
# 19.0.2 (2024-12-04)
|
||||
### 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)) |
|
||||
| [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 |
|
||||
| -- | -- | -- |
|
||||
| [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.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)) |
|
||||
<a name="19.0.1"></a>
|
||||
# 19.0.1 (2024-11-26)
|
||||
### 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)) |
|
||||
| [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 |
|
||||
| -- | -- | -- |
|
||||
| [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.
|
||||
### platform-browser
|
||||
- The deprecated `BrowserModule.withServerTransition` method has been removed. Please use the `APP_ID` DI token to set the application id instead.
|
||||
### compiler
|
||||
| [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 |
|
||||
| -- | -- | -- |
|
||||
| [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)) |
|
||||
### 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)) |
|
||||
### 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)) |
|
||||
| [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 +254,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 +322,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 +353,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 +375,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 +388,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 +397,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 +435,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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,7 +7,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},
|
||||
|
||||
@@ -26,8 +26,7 @@ import {
|
||||
ViewContainerRef,
|
||||
ViewEncapsulation,
|
||||
ɵPendingTasks as PendingTasks,
|
||||
EventEmitter,
|
||||
Output,
|
||||
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.0.0",
|
||||
"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"
|
||||
},
|
||||
|
||||
@@ -52,6 +52,8 @@ 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,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @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 +17,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 +55,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,5 +1,5 @@
|
||||
// @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 +178,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 +241,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 +399,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: ''}];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
FunctionEntry,
|
||||
InitializerApiFunctionEntry,
|
||||
InterfaceEntry,
|
||||
JsDocTagEntry,
|
||||
MemberEntry,
|
||||
MemberType,
|
||||
MethodEntry,
|
||||
@@ -125,7 +126,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 +134,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. */
|
||||
|
||||
@@ -21,11 +21,7 @@ export async function initHighlighter() {
|
||||
});
|
||||
}
|
||||
|
||||
export function codeToHtml(
|
||||
code: string,
|
||||
language: string | undefined,
|
||||
options?: {removeFunctionKeyword?: boolean},
|
||||
): string {
|
||||
export function codeToHtml(code: string, language: string | undefined): string {
|
||||
const html = highlighter.codeToHtml(code, {
|
||||
lang: language ?? 'text',
|
||||
themes: {
|
||||
@@ -36,9 +32,6 @@ export function codeToHtml(
|
||||
defaultColor: false,
|
||||
});
|
||||
|
||||
if (options?.removeFunctionKeyword) {
|
||||
return replaceKeywordFromShikiHtml('function', html);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ export const signatureCard = (
|
||||
// Always omit types in signature headers, to keep them short.
|
||||
true,
|
||||
)}
|
||||
removeFunctionKeyword={true}
|
||||
/>
|
||||
</code>
|
||||
) : (
|
||||
|
||||
@@ -11,10 +11,8 @@ import {RawHtml} from './raw-html';
|
||||
import {codeToHtml} from '../shiki/shiki';
|
||||
|
||||
/** Component to render a header of the CLI page. */
|
||||
export function HighlightTypeScript(props: {code: string; removeFunctionKeyword?: boolean}) {
|
||||
const result = codeToHtml(props.code, 'typescript', {
|
||||
removeFunctionKeyword: props.removeFunctionKeyword,
|
||||
});
|
||||
export function HighlightTypeScript(props: {code: string; }) {
|
||||
const result = codeToHtml(props.code, 'typescript');
|
||||
|
||||
return <RawHtml value={result} />;
|
||||
}
|
||||
|
||||
@@ -669,6 +669,91 @@
|
||||
"startLine": 103,
|
||||
"endLine": 125
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linkedSignal",
|
||||
"signatures": [
|
||||
{
|
||||
"name": "linkedSignal",
|
||||
"entryType": "function",
|
||||
"description": "Creates a writable signals whose value is initialized and reset by the linked, reactive computation.",
|
||||
"generics": [{"name": "D"}],
|
||||
"isNewType": false,
|
||||
"jsdocTags": [{"name": "developerPreview", "comment": ""}],
|
||||
"params": [
|
||||
{
|
||||
"name": "computation",
|
||||
"description": "",
|
||||
"type": "() => D",
|
||||
"isOptional": false,
|
||||
"isRestParam": false
|
||||
},
|
||||
{
|
||||
"name": "options",
|
||||
"description": "",
|
||||
"type": "{ equal?: ValueEqualityFn<NoInfer<D>> | undefined; } | undefined",
|
||||
"isOptional": true,
|
||||
"isRestParam": false
|
||||
}
|
||||
],
|
||||
"rawComment": "/**\n * Creates a writable signals whose value is initialized and reset by the linked, reactive computation.\n *\n * @developerPreview\n */",
|
||||
"returnType": "WritableSignal<D>"
|
||||
},
|
||||
{
|
||||
"name": "linkedSignal",
|
||||
"entryType": "function",
|
||||
"description": "Creates a writable signals whose value is initialized and reset by the linked, reactive computation.\nThis is an advanced API form where the computation has access to the previous value of the signal and the computation result.",
|
||||
"generics": [{"name": "S"}, {"name": "D"}],
|
||||
"isNewType": false,
|
||||
"jsdocTags": [{"name": "developerPreview", "comment": ""}],
|
||||
"params": [
|
||||
{
|
||||
"name": "options",
|
||||
"description": "",
|
||||
"type": "{ source: () => S; computation: (source: NoInfer<S>, previous?: { source: NoInfer<S>; value: NoInfer<D>; } | undefined) => D; equal?: ValueEqualityFn<NoInfer<D>> | undefined; }",
|
||||
"isOptional": false,
|
||||
"isRestParam": false
|
||||
}
|
||||
],
|
||||
"rawComment": "/**\n * Creates a writable signals whose value is initialized and reset by the linked, reactive computation.\n * This is an advanced API form where the computation has access to the previous value of the signal and the computation result.\n *\n * @developerPreview\n */",
|
||||
"returnType": "WritableSignal<D>"
|
||||
}
|
||||
],
|
||||
"implementation": {
|
||||
"params": [
|
||||
{
|
||||
"name": "optionsOrComputation",
|
||||
"description": "",
|
||||
"type": "{ source: () => S; computation: ComputationFn<S, D>; equal?: ValueEqualityFn<D> | undefined; } | (() => D)",
|
||||
"isOptional": false,
|
||||
"isRestParam": false
|
||||
},
|
||||
{
|
||||
"name": "options",
|
||||
"description": "",
|
||||
"type": "{ equal?: ValueEqualityFn<D> | undefined; } | undefined",
|
||||
"isOptional": true,
|
||||
"isRestParam": false
|
||||
}
|
||||
],
|
||||
"isNewType": false,
|
||||
"returnType": "WritableSignal<D>",
|
||||
"generics": [{"name": "S"}, {"name": "D"}],
|
||||
"name": "linkedSignal",
|
||||
"description": "",
|
||||
"entryType": "function",
|
||||
"jsdocTags": [],
|
||||
"rawComment": ""
|
||||
},
|
||||
"entryType": "function",
|
||||
"description": "",
|
||||
"jsdocTags": [],
|
||||
"rawComment": "",
|
||||
"source": {
|
||||
"filePath": "/packages/core/src/render3/reactivity/linked_signal.ts",
|
||||
"startLine": 112,
|
||||
"endLine": 115
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import {runfiles} from '@bazel/runfiles';
|
||||
import {readFile} from 'fs/promises';
|
||||
import {getRenderable} from '../processing';
|
||||
import {DocEntryRenderable} from '../entities/renderables';
|
||||
import {initHighlighter} from '../shiki/shiki';
|
||||
import {configureMarkedGlobally} from '../marked/configuration';
|
||||
|
||||
// Note: The tests will probably break if the schema of the api extraction changes.
|
||||
// All entries in the fake-entries are extracted from Angular's api.
|
||||
// You can just generate them an copy/replace the items in the fake-entries file.
|
||||
|
||||
describe('renderable', () => {
|
||||
const entries = new Map<string, DocEntryRenderable>();
|
||||
|
||||
beforeAll(async () => {
|
||||
await initHighlighter();
|
||||
await configureMarkedGlobally();
|
||||
|
||||
const entryContent = await readFile(runfiles.resolvePackageRelative('fake-entries.json'), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
const entryJson = JSON.parse(entryContent) as any;
|
||||
for (const entry of entryJson.entries) {
|
||||
const renderableJson = getRenderable(entry, '@angular/fakeentry') as DocEntryRenderable;
|
||||
entries.set(entry['name'], renderableJson);
|
||||
}
|
||||
});
|
||||
|
||||
it('should compute the flags correctly', () => {
|
||||
// linkedSignal has the developerPreview tag on the overloads not on the main entry.
|
||||
const linkedSignal = entries.get('linkedSignal');
|
||||
expect(linkedSignal).toBeDefined();
|
||||
expect(linkedSignal!.isDeprecated).toBe(false);
|
||||
expect(linkedSignal!.isDeveloperPreview).toBe(true);
|
||||
expect(linkedSignal!.isExperimental).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import {makeGenericsText} from '../../transforms/code-transforms';
|
||||
|
||||
describe('makeGenericsText', () => {
|
||||
it('should return an empty string if no generics are provided', () => {
|
||||
expect(makeGenericsText(undefined)).toBe('');
|
||||
expect(makeGenericsText([])).toBe('');
|
||||
});
|
||||
|
||||
it('should return a single generic type without constraints or default', () => {
|
||||
const generics = [{name: 'T', constraint: undefined, default: undefined}];
|
||||
expect(makeGenericsText(generics)).toBe('<T>');
|
||||
});
|
||||
|
||||
it('should handle a single generic type with a constraint', () => {
|
||||
const generics = [{name: 'T', constraint: 'string', default: undefined}];
|
||||
expect(makeGenericsText(generics)).toBe('<T extends string>');
|
||||
});
|
||||
|
||||
it('should handle a single generic type with a default value', () => {
|
||||
const generics = [{name: 'T', default: 'number', constraint: undefined}];
|
||||
expect(makeGenericsText(generics)).toBe('<T = number>');
|
||||
});
|
||||
|
||||
it('should handle a single generic type with both constraint and default value', () => {
|
||||
const generics = [{name: 'T', constraint: 'string', default: 'number'}];
|
||||
expect(makeGenericsText(generics)).toBe('<T extends string = number>');
|
||||
});
|
||||
|
||||
it('should handle multiple generic types without constraints or defaults', () => {
|
||||
const generics = [
|
||||
{name: 'T', constraint: undefined, default: undefined},
|
||||
{name: 'U', constraint: undefined, default: undefined},
|
||||
];
|
||||
expect(makeGenericsText(generics)).toBe('<T, U>');
|
||||
});
|
||||
|
||||
it('should handle multiple generic types with constraints and defaults', () => {
|
||||
const generics = [
|
||||
{name: 'T', constraint: 'string', default: 'number'},
|
||||
{name: 'U', constraint: 'boolean', default: undefined},
|
||||
{name: 'V', default: 'any', constraint: undefined},
|
||||
];
|
||||
expect(makeGenericsText(generics)).toBe(
|
||||
'<T extends string = number, U extends boolean, V = any>',
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle complex generics with mixed constraints and defaults', () => {
|
||||
const generics = [
|
||||
{name: 'A', constraint: 'string', default: undefined},
|
||||
{name: 'B', constraint: undefined, default: undefined},
|
||||
{name: 'C', default: 'number', constraint: undefined},
|
||||
{name: 'D', constraint: 'boolean', default: 'true'},
|
||||
];
|
||||
expect(makeGenericsText(generics)).toBe(
|
||||
'<A extends string, B, C = number, D extends boolean = true>',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -9,6 +9,7 @@
|
||||
import {
|
||||
DocEntry,
|
||||
FunctionSignatureMetadata,
|
||||
GenericEntry,
|
||||
MemberEntry,
|
||||
MemberTags,
|
||||
ParameterEntry,
|
||||
@@ -66,9 +67,7 @@ export function addRenderableCodeToc<T extends DocEntry & HasModuleName>(
|
||||
const metadata = mapDocEntryToCode(entry);
|
||||
appendPrefixAndSuffix(entry, metadata);
|
||||
|
||||
let codeWithSyntaxHighlighting = codeToHtml(metadata.contents, 'typescript', {
|
||||
removeFunctionKeyword: true,
|
||||
});
|
||||
let codeWithSyntaxHighlighting = codeToHtml(metadata.contents, 'typescript');
|
||||
|
||||
if (isDecoratorEntry(entry)) {
|
||||
// Shiki requires a keyword for correct formating of Decorators
|
||||
@@ -242,7 +241,8 @@ export function mapDocEntryToCode(entry: DocEntry): CodeTableOfContentsData {
|
||||
}
|
||||
|
||||
if (isTypeAliasEntry(entry)) {
|
||||
const contents = `type ${entry.name} = ${entry.type}`;
|
||||
const generics = makeGenericsText(entry.generics);
|
||||
const contents = `type ${entry.name}${generics} = ${entry.type}`;
|
||||
|
||||
if (isDeprecated) {
|
||||
const numberOfLinesOfCode = getNumberOfLinesOfCode(contents);
|
||||
@@ -332,8 +332,10 @@ function getMethodCodeLine(
|
||||
displayParamsInNewLines: boolean = false,
|
||||
isFunction: boolean = false,
|
||||
): string {
|
||||
const generics = makeGenericsText(member.generics);
|
||||
|
||||
displayParamsInNewLines &&= member.params.length > 0;
|
||||
return `${isFunction ? 'function' : ''}${memberTags.join(' ')} ${member.name}(${displayParamsInNewLines ? '\n ' : ''}${member.params
|
||||
return `${isFunction ? 'function' : ''}${memberTags.join(' ')} ${member.name}${generics}(${displayParamsInNewLines ? '\n ' : ''}${member.params
|
||||
.map((param) => mapParamEntry(param))
|
||||
.join(`,${displayParamsInNewLines ? '\n ' : ' '}`)}${
|
||||
displayParamsInNewLines ? '\n' : ''
|
||||
@@ -442,13 +444,7 @@ function appendPrefixAndSuffix(entry: DocEntry, codeTocData: CodeTableOfContents
|
||||
};
|
||||
|
||||
if (isClassEntry(entry) || isInterfaceEntry(entry)) {
|
||||
const generics =
|
||||
entry.generics?.length > 0
|
||||
? `<${entry.generics
|
||||
.map((g) => (g.constraint ? `${g.name} extends ${g.constraint}` : g.name))
|
||||
.join(', ')}>`
|
||||
: '';
|
||||
|
||||
const generics = makeGenericsText(entry.generics);
|
||||
const extendsStr = entry.extends ? ` extends ${entry.extends}` : '';
|
||||
// TODO: remove the ? when we distinguish Class & Decorator entries
|
||||
const implementsStr =
|
||||
@@ -501,3 +497,45 @@ export function addApiLinksToHtml(htmlString: string): string {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a TypeScript generics string based on an array of generic type entries.
|
||||
*
|
||||
* This function takes an array of generic type entries and returns a formatted string
|
||||
* representing TypeScript generics syntax, including any constraints and default values
|
||||
* specified in each entry.
|
||||
*
|
||||
* @param generics - An array of `GenericEntry` objects representing the generics to be formatted,
|
||||
* or `undefined` if there are no generics.
|
||||
*
|
||||
* @returns A formatted string representing TypeScript generics syntax, or an empty string if no generics are provided.
|
||||
*/
|
||||
export function makeGenericsText(generics: GenericEntry[] | undefined): string {
|
||||
if (!generics?.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const parts: string[] = ['<'];
|
||||
|
||||
for (let index = 0; index < generics.length; index++) {
|
||||
const {constraint, default: defaultVal, name} = generics[index];
|
||||
|
||||
parts.push(name);
|
||||
|
||||
if (constraint) {
|
||||
parts.push(' extends ', constraint);
|
||||
}
|
||||
|
||||
if (defaultVal !== undefined) {
|
||||
parts.push(' = ', defaultVal);
|
||||
}
|
||||
|
||||
if (index < generics.length - 1) {
|
||||
parts.push(', ');
|
||||
}
|
||||
}
|
||||
|
||||
parts.push('>');
|
||||
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import {getLinkToModule} from './url-transforms';
|
||||
import {addApiLinksToHtml} from './code-transforms';
|
||||
import {getCurrentSymbol, getModuleName, logUnknownSymbol} from '../symbol-context';
|
||||
|
||||
export const JS_DOC_REMARKS_TAG = 'remarks';
|
||||
export const JS_DOC_USAGE_NOTES_TAG = 'usageNotes';
|
||||
export const JS_DOC_SEE_TAG = 'see';
|
||||
export const JS_DOC_DESCRIPTION_TAG = 'description';
|
||||
@@ -96,7 +97,9 @@ export function addHtmlAdditionalLinks<T extends HasJsDocTags & HasModuleName>(
|
||||
}
|
||||
|
||||
export function addHtmlUsageNotes<T extends HasJsDocTags>(entry: T): T & HasHtmlUsageNotes {
|
||||
const usageNotesTag = entry.jsdocTags.find((tag) => tag.name === JS_DOC_USAGE_NOTES_TAG);
|
||||
const usageNotesTag = entry.jsdocTags.find(
|
||||
({name}) => name === JS_DOC_USAGE_NOTES_TAG || name === JS_DOC_REMARKS_TAG,
|
||||
);
|
||||
const htmlUsageNotes = usageNotesTag
|
||||
? (marked.parse(
|
||||
convertJsDocExampleToHtmlExample(wrapExampleHtmlElementsWithCode(usageNotesTag.comment)),
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^16.1.1",
|
||||
"@angular/common": "^16.1.1",
|
||||
"@angular/compiler": "^16.1.1",
|
||||
"@angular/core": "^16.1.1",
|
||||
"@angular/forms": "^16.1.1",
|
||||
"@angular/platform-browser": "^16.1.1",
|
||||
"@angular/platform-browser-dynamic": "^16.1.1",
|
||||
"@angular/router": "^16.1.1",
|
||||
"@angular/animations": "^19.0.0",
|
||||
"@angular/common": "^19.0.0",
|
||||
"@angular/compiler": "^19.0.0",
|
||||
"@angular/core": "^19.0.0",
|
||||
"@angular/forms": "^19.0.0",
|
||||
"@angular/platform-browser": "^19.0.0",
|
||||
"@angular/platform-browser-dynamic": "^19.0.0",
|
||||
"@angular/router": "^19.0.0",
|
||||
"rxjs": "~7.4.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.1.0",
|
||||
"@angular/cli": "^16.1.0",
|
||||
"@angular/compiler-cli": "^16.1.1",
|
||||
"@angular-devkit/build-angular": "^19.0.0",
|
||||
"@angular/cli": "^19.0.0",
|
||||
"@angular/compiler-cli": "^19.0.0",
|
||||
"@types/jasmine": "~3.10.0",
|
||||
"@types/node": "^12.11.1",
|
||||
"jasmine-core": "~3.10.0",
|
||||
@@ -34,6 +34,6 @@
|
||||
"karma-coverage": "~2.0.3",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"typescript": "~5.0.3"
|
||||
"typescript": "~5.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-root',
|
||||
template: '<h2>Example template</h2>',
|
||||
styles: [
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/common": "^17.0.0-rc.1",
|
||||
"@angular/compiler": "^17.0.0-rc.1",
|
||||
"@angular/core": "^17.0.0-rc.1",
|
||||
"@angular/platform-browser": "^17.0.0-rc.1",
|
||||
"@angular/common": "^19.0.0",
|
||||
"@angular/compiler": "^19.0.0",
|
||||
"@angular/core": "^19.0.0",
|
||||
"@angular/platform-browser": "^19.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.0.0-rc.2",
|
||||
"@angular/cli": "^17.0.0-rc.2",
|
||||
"@angular/compiler-cli": "^17.0.0-rc.1",
|
||||
"typescript": "~5.2.0"
|
||||
"@angular-devkit/build-angular": "^19.0.0",
|
||||
"@angular/cli": "^19.0.0",
|
||||
"@angular/compiler-cli": "^19.0.0",
|
||||
"typescript": "~5.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import {NavigationItem} from '../interfaces/index';
|
||||
|
||||
@Pipe({
|
||||
name: 'isActiveNavigationItem',
|
||||
standalone: true,
|
||||
})
|
||||
export class IsActiveNavigationItem implements PipeTransform {
|
||||
// Check whether provided item: `itemToCheck` should be marked as active, based on `activeItem`.
|
||||
|
||||
@@ -11,7 +11,6 @@ import {normalizePath, removeTrailingSlash} from '../utils/index';
|
||||
|
||||
@Pipe({
|
||||
name: 'relativeLink',
|
||||
standalone: true,
|
||||
})
|
||||
export class RelativeLink implements PipeTransform {
|
||||
transform(absoluteUrl: string, result: 'relative' | 'pathname' | 'hash' = 'relative'): string {
|
||||
|
||||
@@ -10,4 +10,3 @@ export * from './navigation-state.service';
|
||||
export {TOC_SKIP_CONTENT_MARKER, TableOfContentsLoader} from './table-of-contents-loader.service';
|
||||
export {TableOfContentsScrollSpy} from './table-of-contents-scroll-spy.service';
|
||||
export * from './search.service';
|
||||
export * from './inject-async.service';
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {
|
||||
DestroyRef,
|
||||
ENVIRONMENT_INITIALIZER,
|
||||
EnvironmentInjector,
|
||||
Injectable,
|
||||
Injector,
|
||||
Provider,
|
||||
ProviderToken,
|
||||
Type,
|
||||
createEnvironmentInjector,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
|
||||
/**
|
||||
* Convience method for lazy loading an injection token.
|
||||
*/
|
||||
export async function injectAsync<T>(
|
||||
injector: Injector,
|
||||
providerLoader: () => Promise<ProviderToken<T>>,
|
||||
): Promise<T> {
|
||||
const injectImpl = injector.get(InjectAsyncImpl);
|
||||
return injectImpl.get(injector, providerLoader);
|
||||
}
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
class InjectAsyncImpl<T> {
|
||||
private overrides = new WeakMap(); // no need to cleanup
|
||||
override<T>(type: Type<T>, mock: Type<unknown>) {
|
||||
this.overrides.set(type, mock);
|
||||
}
|
||||
|
||||
async get(injector: Injector, providerLoader: () => Promise<ProviderToken<T>>): Promise<T> {
|
||||
const type = await providerLoader();
|
||||
|
||||
// Check if we have overrides, O(1), low overhead
|
||||
if (this.overrides.has(type)) {
|
||||
const override = this.overrides.get(type);
|
||||
return new override();
|
||||
}
|
||||
|
||||
if (!(injector instanceof EnvironmentInjector)) {
|
||||
// this is the DestroyRef of the component
|
||||
const destroyRef = injector.get(DestroyRef);
|
||||
|
||||
// This is the parent injector of the injector we're creating
|
||||
const environmentInjector = injector.get(EnvironmentInjector);
|
||||
|
||||
// Creating an environment injector to destroy it afterwards
|
||||
const newInjector = createEnvironmentInjector([type as Provider], environmentInjector);
|
||||
|
||||
// Destroy the injector to trigger DestroyRef.onDestroy on our service
|
||||
destroyRef.onDestroy(() => {
|
||||
newInjector.destroy();
|
||||
});
|
||||
|
||||
// We want to create the new instance of our service with our new injector
|
||||
injector = newInjector;
|
||||
}
|
||||
|
||||
return injector.get(type)!;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to mock the lazy loaded module in `injectAsync`
|
||||
*
|
||||
* @usage
|
||||
* TestBed.configureTestingModule({
|
||||
* providers: [
|
||||
* mockAsyncProvider(SandboxService, fakeSandboxService)
|
||||
* ]
|
||||
* });
|
||||
*/
|
||||
export function mockAsyncProvider<T>(type: Type<T>, mock: Type<unknown>) {
|
||||
return [
|
||||
{
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
multi: true,
|
||||
useValue: () => {
|
||||
inject(InjectAsyncImpl).override(type, mock);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -19,11 +19,9 @@ import {RESIZE_EVENT_DELAY} from '../constants/index';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {auditTime, debounceTime, fromEvent, startWith} from 'rxjs';
|
||||
import {WINDOW} from '../providers/index';
|
||||
import {shouldReduceMotion} from '../utils/index';
|
||||
import {TableOfContentsLoader} from './table-of-contents-loader.service';
|
||||
|
||||
export const SCROLL_EVENT_DELAY = 20;
|
||||
export const SCROLL_FINISH_DELAY = SCROLL_EVENT_DELAY * 2;
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
// The service is responsible for listening for scrolling and resizing,
|
||||
@@ -35,6 +33,7 @@ export class TableOfContentsScrollSpy {
|
||||
private readonly viewportScroller = inject(ViewportScroller);
|
||||
private readonly injector = inject(EnvironmentInjector);
|
||||
private contentSourceElement: HTMLElement | null = null;
|
||||
|
||||
private lastContentWidth = 0;
|
||||
|
||||
activeItemId = signal<string | null>(null);
|
||||
@@ -65,24 +64,6 @@ export class TableOfContentsScrollSpy {
|
||||
this.viewportScroller.scrollToPosition([0, 0]);
|
||||
}
|
||||
|
||||
scrollToSection(id: string): void {
|
||||
if (shouldReduceMotion()) {
|
||||
this.offsetToSection(id);
|
||||
} else {
|
||||
const section = this.document.getElementById(id);
|
||||
section?.scrollIntoView({behavior: 'smooth', block: 'start'});
|
||||
// We don't want to set the active item here, it would mess up the animation
|
||||
// The scroll event handler will handle it for us
|
||||
}
|
||||
}
|
||||
|
||||
private offsetToSection(id: string): void {
|
||||
const section = this.document.getElementById(id);
|
||||
section?.scrollIntoView({block: 'start'});
|
||||
// Here we need to set the active item manually because scroll events might not be fired
|
||||
this.activeItemId.set(id);
|
||||
}
|
||||
|
||||
// After window resize, we should update top value of each table content item
|
||||
private setResizeEventHandlers(destroyRef: DestroyRef) {
|
||||
fromEvent(this.window, 'resize')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user