mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b36d53143a |
@@ -56,6 +56,11 @@ build --enable_runfiles
|
||||
build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=release"
|
||||
build:release --stamp
|
||||
|
||||
# Building AIO against local Angular deps requires stamping
|
||||
# versions in Angular packages due to CLI version checks.
|
||||
build:aio_local_deps --stamp
|
||||
build:aio_local_deps --workspace_status_command="yarn -s --cwd aio local-workspace-status"
|
||||
|
||||
# Snapshots should also be stamped with version control information.
|
||||
build:snapshot-build --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot"
|
||||
build:snapshot-build --stamp
|
||||
@@ -69,6 +74,14 @@ build:snapshot-build --stamp
|
||||
##########################################################
|
||||
build --flag_alias=aio_build_config=//aio:flag_aio_build_config
|
||||
|
||||
####################################
|
||||
# AIO first party dep substitution #
|
||||
# Turn on with #
|
||||
# --config=aio_local_deps #
|
||||
####################################
|
||||
|
||||
build:aio_local_deps --//aio:flag_aio_local_deps
|
||||
|
||||
###############################
|
||||
# Output #
|
||||
###############################
|
||||
@@ -105,6 +118,10 @@ common:remote --jobs=200
|
||||
|
||||
build:remote --google_default_credentials
|
||||
|
||||
# Limit the number of test jobs for on an AIO local deps build. The example tests running
|
||||
# concurrently pushes the circleci executor RAM usage to its limits.
|
||||
test:aio_local_deps --jobs=24
|
||||
|
||||
# Force remote exeuctions to consider the entire run as linux
|
||||
build:remote --cpu=k8
|
||||
build:remote --host_cpu=k8
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"devondcarew.bazel-code",
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 'Docs or angular.dev Bug Report'
|
||||
name: 'Docs or angular.io Bug Report'
|
||||
description: Report an issue in Angular's documentation or angular.io application
|
||||
|
||||
body:
|
||||
|
||||
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -21,16 +21,16 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@c83e99a12397014162531ca125c94549db55dd84
|
||||
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@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 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@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@c83e99a12397014162531ca125c94549db55dd84
|
||||
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@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
exit: true
|
||||
|
||||
# Indicate that the benchmark command was received.
|
||||
- uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
- uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3
|
||||
with:
|
||||
comment-id: ${{github.event.comment.id}}
|
||||
token: '${{secrets.BENCHMARK_POST_RESULTS_GITHUB_TOKEN}}'
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
|
||||
id: comment-branch
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
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@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
id: benchmark
|
||||
name: Running benchmark
|
||||
|
||||
- uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
- uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3
|
||||
with:
|
||||
issue-number: ${{github.event.issue.number}}
|
||||
token: '${{secrets.BENCHMARK_POST_RESULTS_GITHUB_TOKEN}}'
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
saucelabs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
SAUCE_USERNAME: ${{ vars.SAUCE_USERNAME }}
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Starting Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||
- name: Preparing Bazel-generated fixtures required in legacy tests
|
||||
run: |
|
||||
yarn bazel build //packages/core/test:downleveled_es5_fixture //packages/common/locales
|
||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||
mkdir -p dist/legacy-test-out/core/test/reflection/
|
||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||
dist/legacy-test-out/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||
# Locale files are needed for i18n tests running within Saucelabs. These are added
|
||||
# directly as sources so that the TypeScript compilation of `/packages/tsconfig.json`
|
||||
# can succeed. Note that the base locale and currencies files are checked-in, so
|
||||
# we do not need to re-generate those through Bazel.
|
||||
mkdir -p packages/common/locales/extra
|
||||
cp dist/bin/packages/common/locales/*.ts packages/common/locales
|
||||
cp dist/bin/packages/common/locales/extra/*.ts packages/common/locales/extra
|
||||
- name: Build bundle of tests to run on Saucelabs
|
||||
run: node tools/legacy-saucelabs/build-saucelabs-test-bundle.mjs
|
||||
- name: Wait and confirm Saucelabs tunnel has connected
|
||||
run: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
timeout-minutes: 3
|
||||
- name: Running tests on Saucelabs.
|
||||
run: KARMA_WEB_TEST_MODE=SL_REQUIRED yarn karma start ./karma-js.conf.js --single-run
|
||||
- name: Stop Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh stop
|
||||
+27
-76
@@ -5,7 +5,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- '[0-9]+.[0-9]+.x'
|
||||
- 'remove-aio-stuff'
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
@@ -24,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -59,13 +58,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -77,13 +76,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -94,17 +93,15 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- 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 --fast_adev
|
||||
- name: Run tests
|
||||
run: yarn bazel test //adev:test
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel test --config=aio_local_deps //adev:test
|
||||
|
||||
publish-snapshots:
|
||||
if: github.event_name == 'push'
|
||||
@@ -112,13 +109,13 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -130,7 +127,7 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -138,9 +135,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@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -179,7 +176,7 @@ jobs:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
@@ -187,66 +184,20 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
SAUCE_USERNAME: ${{ vars.SAUCE_USERNAME }}
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
- name: Run all saucelabs bazel tests
|
||||
run: |
|
||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "fixme-saucelabs", ...)')
|
||||
yarn bazel test --config=saucelabs --jobs=$JOBS ${TESTS}
|
||||
|
||||
saucelabs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
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@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- name: Starting Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||
- name: Preparing Bazel-generated fixtures required in legacy tests
|
||||
run: |
|
||||
yarn bazel build //packages/core/test:downleveled_es5_fixture //packages/common/locales
|
||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||
mkdir -p dist/legacy-test-out/core/test/reflection/
|
||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||
dist/legacy-test-out/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||
# Locale files are needed for i18n tests running within Saucelabs. These are added
|
||||
# directly as sources so that the TypeScript compilation of `/packages/tsconfig.json`
|
||||
# can succeed. Note that the base locale and currencies files are checked-in, so
|
||||
# we do not need to re-generate those through Bazel.
|
||||
mkdir -p packages/common/locales/extra
|
||||
cp dist/bin/packages/common/locales/*.ts packages/common/locales
|
||||
cp dist/bin/packages/common/locales/extra/*.ts packages/common/locales/extra
|
||||
- name: Build bundle of tests to run on Saucelabs
|
||||
run: node tools/legacy-saucelabs/build-saucelabs-test-bundle.mjs
|
||||
- name: Wait and confirm Saucelabs tunnel has connected
|
||||
run: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
timeout-minutes: 3
|
||||
- name: Running tests on Saucelabs.
|
||||
run: KARMA_WEB_TEST_MODE=SL_REQUIRED yarn karma start ./karma-js.conf.js --single-run
|
||||
- name: Stop Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh stop
|
||||
|
||||
adev-deploy:
|
||||
needs: [adev]
|
||||
if: needs.adev.result == 'success' && github.event_name == 'push' && github.ref_name == 'main'
|
||||
@@ -256,15 +207,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build //adev:build
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- name: Move generated project files into deployment directory
|
||||
run: cp -r dist/bin/adev/build adev/build
|
||||
- name: Setup firebase context
|
||||
|
||||
@@ -12,14 +12,14 @@ jobs:
|
||||
labels:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -13,8 +13,8 @@ jobs:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -22,15 +22,15 @@ jobs:
|
||||
version: ['https://next.angular.io/', 'https://angular.io/']
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@c83e99a12397014162531ca125c94549db55dd84
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Run basic e2e and deployment config tests.
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
|
||||
# Upload the results as artifacts.
|
||||
- name: 'Upload artifact'
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -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@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
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
|
||||
@@ -28,11 +28,11 @@ jobs:
|
||||
# This is needed as otherwise the PR creation will fail with `shallow update not allowed` when the forked branch is not in sync.
|
||||
fetch-depth: 0
|
||||
- name: Generate CLI help
|
||||
run: node adev/scripts/update-cli-help/index.mjs
|
||||
run: node aio/scripts/update-cli-help/index.mjs
|
||||
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@e6e98d32d7d4d350ecf4ec10ad9c7e75198daabd
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@c83e99a12397014162531ca125c94549db55dd84
|
||||
with:
|
||||
branch-prefix: update-cli-help
|
||||
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
|
||||
|
||||
+56
-5
@@ -7,7 +7,23 @@ export const format: FormatConfig = {
|
||||
'prettier': {
|
||||
'matchers': [
|
||||
'**/*.{yaml,yml}',
|
||||
'**/*.{js,ts}',
|
||||
'adev/**/*.{js,ts}',
|
||||
'devtools/**/*.{js,ts}',
|
||||
'tools/**/*.{js,ts}',
|
||||
'modules/**/*.{js,ts}',
|
||||
'scripts/**/*.{js,ts}',
|
||||
'packages/animations/**/*.{js,ts}',
|
||||
'packages/bazel/**/*.{js,ts}',
|
||||
'packages/benchpress/**/*.{js,ts}',
|
||||
'packages/common/**/*.{js,ts}',
|
||||
'packages/docs/**/*.{js,ts}',
|
||||
'packages/elements/**/*.{js,ts}',
|
||||
'packages/examples/**/*.{js,ts}',
|
||||
'packages/misc/**/*.{js,ts}',
|
||||
'packages/private/**/*.{js,ts}',
|
||||
'packages/router/**/*.{js,ts}',
|
||||
'packages/service-worker/**/*.{js,ts}',
|
||||
'packages/upgrade/**/*.{js,ts}',
|
||||
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
@@ -15,15 +31,50 @@ export const format: FormatConfig = {
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
],
|
||||
},
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
// Do not format generated ng-dev script
|
||||
'!dev-infra/ng-dev.js',
|
||||
'!dev-infra/build-worker.js',
|
||||
// Do not format compliance test-cases since they must match generated code
|
||||
'!packages/compiler-cli/test/compliance/test_cases/**/*.js',
|
||||
// Do not format the locale files which are checked-in for Google3, but generated using
|
||||
// the `generate-locales-tool` from `packages/common/locales`.
|
||||
'!packages/core/src/i18n/locale_en.ts',
|
||||
'!packages/common/locales/closure-locale.ts',
|
||||
'!packages/common/src/i18n/currencies.ts',
|
||||
// Test cases contain non valid code.
|
||||
'!packages/compiler-cli/test/compliance/test_cases/**/*.{js,ts}',
|
||||
// Ignore AIO as its pending removal.
|
||||
'!aio/**/*.{js,ts}',
|
||||
// Temporarily disable formatting for adev
|
||||
'!adev/**',
|
||||
|
||||
// Migrated to prettier
|
||||
'!devtools/**/*.{js,ts}',
|
||||
'!tools/**/*.{js,ts}',
|
||||
'!modules/**/*.{js,ts}',
|
||||
'!scripts/**/*.{js,ts}',
|
||||
'!packages/animations/**/*.{js,ts}',
|
||||
'!packages/bazel/**/*.{js,ts}',
|
||||
'!packages/benchpress/**/*.{js,ts}',
|
||||
'!packages/common/**/*.{js,ts}',
|
||||
'!packages/docs/**/*.{js,ts}',
|
||||
'!packages/elements/**/*.{js,ts}',
|
||||
'!packages/examples/**/*.{js,ts}',
|
||||
'!packages/misc/**/*.{js,ts}',
|
||||
'!packages/private/**/*.{js,ts}',
|
||||
'!packages/router/**/*.{js,ts}',
|
||||
'!packages/service-worker/**/*.{js,ts}',
|
||||
'!packages/upgrade/**/*.{js,ts}',
|
||||
],
|
||||
},
|
||||
'buildifier': true,
|
||||
|
||||
+22
-83
@@ -140,7 +140,7 @@ groups:
|
||||
- alxhub
|
||||
- crisbeto
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
|
||||
# =========================================================
|
||||
# Framework: Compiler
|
||||
@@ -183,7 +183,7 @@ groups:
|
||||
- crisbeto
|
||||
- devversion
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- AndrewKushnir
|
||||
|
||||
# =========================================================
|
||||
@@ -193,7 +193,7 @@ groups:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files.exclude("packages/core/schematics/*").exclude('packages/core/primitives/*'), [
|
||||
contains_any_globs(files.exclude("packages/core/schematics/*"), [
|
||||
'packages/core/**/{*,.*}',
|
||||
'packages/examples/core/**/{*,.*}',
|
||||
'packages/platform-browser/**/{*,.*}',
|
||||
@@ -358,7 +358,7 @@ groups:
|
||||
- crisbeto
|
||||
- devversion
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -378,7 +378,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -415,7 +415,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -438,7 +438,7 @@ groups:
|
||||
- andrewseguin
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -536,7 +536,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -615,7 +615,7 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
|
||||
# =========================================================
|
||||
# Framework: Testing
|
||||
@@ -644,7 +644,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -663,7 +663,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -682,7 +682,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -778,7 +778,7 @@ groups:
|
||||
- atscott
|
||||
- crisbeto
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
@@ -813,7 +813,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- dylhunn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- josephperrott
|
||||
- pkozlowski-opensource
|
||||
|
||||
@@ -867,7 +867,7 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
|
||||
# =========================================================
|
||||
# Docs: Marketing
|
||||
@@ -946,7 +946,7 @@ groups:
|
||||
- alxhub
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- jelbourn
|
||||
|
||||
# =========================================================
|
||||
@@ -1078,12 +1078,11 @@ groups:
|
||||
- josephperrott
|
||||
- jelbourn
|
||||
- bencodezen
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- dylhunn
|
||||
- AndrewKushnir
|
||||
- alxhub
|
||||
- crisbeto
|
||||
- devversion
|
||||
- atscott
|
||||
- pkozlowski-opensource
|
||||
- ~JeanMeche
|
||||
@@ -1144,7 +1143,7 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- AndrewKushnir
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- josephperrott
|
||||
|
||||
# =========================================================
|
||||
@@ -1243,7 +1242,7 @@ groups:
|
||||
- atscott
|
||||
- dylhunn
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: 3 # Request reviews from 3 people
|
||||
@@ -1269,7 +1268,7 @@ groups:
|
||||
- atscott
|
||||
- dylhunn
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
reviews:
|
||||
request: 2 # Request reviews from 2 people
|
||||
@@ -1295,7 +1294,7 @@ groups:
|
||||
- atscott
|
||||
- dylhunn
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
|
||||
####################################################################################
|
||||
@@ -1319,69 +1318,9 @@ groups:
|
||||
- andrewseguin
|
||||
- dgp1130
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- jessicajaniuk
|
||||
- josephperrott
|
||||
|
||||
# =========================================================
|
||||
# Primitives
|
||||
# =========================================================
|
||||
|
||||
# Angular team required reviews
|
||||
primitives:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/core/primitives/**/{*,.*}',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- pkozlowski-opensource # Pawel Kozlowski
|
||||
- alxhub # Alex Rickabaugh
|
||||
- thePunderWoman # Jessica Janiuk
|
||||
- dylhunn # Dylan Hunn
|
||||
- AndrewKushnir # Andrew Kushnir
|
||||
- atscott # Andrew Scott
|
||||
reviews:
|
||||
required: 1
|
||||
reviewed_for: optional
|
||||
labels:
|
||||
pending: 'requires: TGP'
|
||||
approved: 'requires: TGP'
|
||||
rejected: 'requires: TGP'
|
||||
|
||||
# External team required reviews
|
||||
primitives-shared:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'packages/core/primitives/**/{*,.*}',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- csmick # Cameron Smick
|
||||
- lannka # Hongfei Ding
|
||||
- eduhmc # Eduardo Huerta-Mercado
|
||||
- ehlemur # Edward Lesmes
|
||||
- ellenyuan # Ellen Yuan
|
||||
- jatraman # Jatin Ramanathan
|
||||
- jesse-good # Jesse Costello-Good
|
||||
- mturco # Matt Turco
|
||||
- neonstalwart # Ben Hockey
|
||||
- nicholasyu-google # Nicholas Yu
|
||||
- emspishak # Eric Spishak-Thomas
|
||||
- iteriani # Thomas Nguyen
|
||||
- tbondwilkinson # Tom Wilkinson
|
||||
- rahatarmanahmed # Rahat Ahmed
|
||||
reviews:
|
||||
required: 1
|
||||
reviewed_for: optional
|
||||
labels:
|
||||
pending: 'requires: TGP'
|
||||
approved: 'requires: TGP'
|
||||
rejected: 'requires: TGP'
|
||||
|
||||
####################################################################################
|
||||
# Override managed result groups
|
||||
#
|
||||
|
||||
Vendored
+1
@@ -6,5 +6,6 @@
|
||||
"recommendations": [
|
||||
"BazelBuild.vscode-bazel",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
],
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -1,10 +1,16 @@
|
||||
{
|
||||
// Format js and ts files on save with `clang-format.executable`
|
||||
// If `clang-format.executable` is not being used, these two settings should be removed otherwise it will break existing formatting.
|
||||
// You can instead run `yarn gulp format` to manually format your code.
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
// Please install https://marketplace.visualstudio.com/items?itemName=xaver.clang-format to take advantage of `clang-format` in VSCode.
|
||||
// (See https://clang.llvm.org/docs/ClangFormat.html for more info `clang-format`.)
|
||||
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
||||
// Exclude third party modules and build artifacts from the editor watchers/searches.
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
|
||||
+61
-522
@@ -1,541 +1,25 @@
|
||||
<a name="18.0.0-rc.0"></a>
|
||||
# 18.0.0-rc.0 (2024-05-01)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [44c0ed83a6](https://github.com/angular/angular/commit/44c0ed83a6499fa96f65a27bc5c926579c06b6d2) | fix | hide implementation details of ExperimentalPendingTasks ([#55516](https://github.com/angular/angular/pull/55516)) |
|
||||
| [a177abef1b](https://github.com/angular/angular/commit/a177abef1b0a0edc46dcca2d8c5c67669c55ff8f) | fix | render hooks should not specifically run outside the Angular zone ([#55399](https://github.com/angular/angular/pull/55399)) |
|
||||
| [a5c57c7484](https://github.com/angular/angular/commit/a5c57c7484f1dc3afab4ece4e969a4a7308cdeca) | fix | resolve error for multiple component instances that use fallback content ([#55478](https://github.com/angular/angular/pull/55478)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f93e5180be](https://github.com/angular/angular/commit/f93e5180be1e20a59ff68f12853653f4f3282846) | fix | resolve multiple structural issues with HttpClient migration ([#55557](https://github.com/angular/angular/pull/55557)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [aefee87074](https://github.com/angular/angular/commit/aefee87074f4a5b2531f989a1876ace6e6616da4) | fix | Scroller should scroll as soon as change detection completes ([#55105](https://github.com/angular/angular/pull/55105)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.7"></a>
|
||||
# 17.3.7 (2024-05-01)
|
||||
<a name="17.3.0-rc.0"></a>
|
||||
# 17.3.0-rc.0 (2024-03-06)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [51ac883167](https://github.com/angular/angular/commit/51ac8831670637b562dfa135bec1e27a0b49f21d) | fix | don't type check the bodies of control flow nodes in basic mode ([#55558](https://github.com/angular/angular/pull/55558)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [af0eb846a5](https://github.com/angular/angular/commit/af0eb846a572d0e9de2c6bb7016ddd339473dc00) | fix | render hooks should not specifically run outside the Angular zone ([#55399](https://github.com/angular/angular/pull/55399)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3eea50da64](https://github.com/angular/angular/commit/3eea50da644f6023e7f001b8738c54cb89aece4c) | fix | Scroller should scroll as soon as change detection completes ([#55105](https://github.com/angular/angular/pull/55105)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.6"></a>
|
||||
# 18.0.0-next.6 (2024-04-25)
|
||||
## Breaking Changes
|
||||
### animations
|
||||
- Deprecated `matchesElement` method has been removed from `AnimationDriver` as it is unused.
|
||||
### core
|
||||
- `async` has been removed, use `waitForAsync` instead.
|
||||
### http
|
||||
- By default we now prevent caching of HTTP requests that require authorization . To opt-out from this behaviour use the `includeRequestsWithAuthHeaders` option in `withHttpTransferCache`.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
withHttpTransferCache({
|
||||
includeRequestsWithAuthHeaders: true,
|
||||
})
|
||||
```
|
||||
### platform-browser
|
||||
- Deprecated `StateKey`, `TransferState` and `makeStateKey` have been removed from `@angular/platform-browser`, use the same APIs from `@angular/core`.
|
||||
## Deprecations
|
||||
### common
|
||||
- `getCurrencySymbol`, `getLocaleCurrencyCode`, `getLocaleCurrencyName`, `getLocaleCurrencySymbol`, `getLocaleDateFormat`, `getLocaleDateTimeFormat`, `getLocaleDayNames`, `getLocaleDayPeriods`, `getLocaleDirection`, `getLocaleEraNames`, `getLocaleExtraDayPeriodRules`, `getLocaleExtraDayPeriods`, `getLocaleFirstDayOfWeek`, `getLocaleId`, `getLocaleMonthNames`, `getLocaleNumberFormat`, `getLocaleNumberSymbol`, `getLocalePluralCase`, `getLocaleTimeFormat`, `getLocaleWeekEndRange`, `getNumberOfCurrencyDigits`
|
||||
### http
|
||||
- `HttpClientModule`, `HttpClientXsrfModule` and `HttpClientJsonpModule`
|
||||
|
||||
As mentionned, those modules can be replaced by provider function only.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bcce85af72](https://github.com/angular/angular/commit/bcce85af72a82634f60b31d66a5ef42ecd844ce8) | refactor | remove deprecated `matchesElement` from `AnimationDriver` ([#55479](https://github.com/angular/angular/pull/55479)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d34c033902](https://github.com/angular/angular/commit/d34c033902b4e7543796de6c57d0cfd09093eb43) | refactor | Deprecate Local Data API functions ([#54483](https://github.com/angular/angular/pull/54483)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7a16d7e969](https://github.com/angular/angular/commit/7a16d7e969eaf5a9475ffdd21a4bf637ce523856) | fix | don't type check the bodies of control flow nodes in basic mode ([#55360](https://github.com/angular/angular/pull/55360)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a730f09ae9](https://github.com/angular/angular/commit/a730f09ae9e729da79a3e0951e15e0139ef67713) | feat | Add a public API to establish events to be replayed and an attribute to mark an element with an event handler. ([#55356](https://github.com/angular/angular/pull/55356)) |
|
||||
| [5f06ca8f55](https://github.com/angular/angular/commit/5f06ca8f5539ed208bae0b110887b5538ac4041f) | feat | add HOST_TAG_NAME token ([#54751](https://github.com/angular/angular/pull/54751)) |
|
||||
| [ac863ded48](https://github.com/angular/angular/commit/ac863ded4818af3426ef5888c706a2bd8c79c0be) | feat | provide ExperimentalPendingTasks API ([#55487](https://github.com/angular/angular/pull/55487)) |
|
||||
| [5a10f405d3](https://github.com/angular/angular/commit/5a10f405d315a28b9a000c669e9b1cb3fa24a7f1) | fix | complete the removal of deprecation `async` function ([#55491](https://github.com/angular/angular/pull/55491)) |
|
||||
| [c175bca364](https://github.com/angular/angular/commit/c175bca36432b26851adb4ea9d850c2d07fba864) | fix | DeferBlockFixture.render should not wait for stability ([#55271](https://github.com/angular/angular/pull/55271)) |
|
||||
| [9894278e71](https://github.com/angular/angular/commit/9894278e712a50079af87898a63e1d19a462d015) | fix | make `ActivatedRoute` inject correct instance inside `@defer` blocks ([#55374](https://github.com/angular/angular/pull/55374)) |
|
||||
| [5948193e13](https://github.com/angular/angular/commit/5948193e1368eec86647b4c1c0b337a387b27087) | fix | skip defer timers on the server ([#55480](https://github.com/angular/angular/pull/55480)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6f88d80758](https://github.com/angular/angular/commit/6f88d8075895bd80592b1b7e0fba8202a58a5417) | feat | allow caching requests with different origins between server and client ([#55274](https://github.com/angular/angular/pull/55274)) |
|
||||
| [8eacb6e4b9](https://github.com/angular/angular/commit/8eacb6e4b982a5aa23cfbf9078dc4e19d9466d73) | feat | exclude caching for authenticated HTTP requests ([#55034](https://github.com/angular/angular/pull/55034)) |
|
||||
| [ef665a40a5](https://github.com/angular/angular/commit/ef665a40a580ff4df79617084ac83738f28ae924) | refactor | Deprecate `HttpClientModule` & related modules ([#54020](https://github.com/angular/angular/pull/54020)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f914f6a362](https://github.com/angular/angular/commit/f914f6a3628847c06cbdde9c90cd417fb2f4c61f) | feat | Migration schematics for `HttpClientModule` ([#54020](https://github.com/angular/angular/pull/54020)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cba336d4f1](https://github.com/angular/angular/commit/cba336d4f1badd601b24a58fc51bde995f45682d) | refactor | remove deprecated transfer state APIs ([#55474](https://github.com/angular/angular/pull/55474)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5674c644ab](https://github.com/angular/angular/commit/5674c644abf51ae8764befd3011742ff1febdf29) | fix | add `nonce` attribute to event record script ([#55495](https://github.com/angular/angular/pull/55495)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4a42961393](https://github.com/angular/angular/commit/4a42961393b3abf40f34374df059d3959dadecc0) | feat | `withNavigationErrorHandler` can convert errors to redirects ([#55370](https://github.com/angular/angular/pull/55370)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.6"></a>
|
||||
# 17.3.6 (2024-04-25)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [826861b1fa](https://github.com/angular/angular/commit/826861b1fa7693010743f5dd881fb31ec33eee52) | fix | DeferBlockFixture.render should not wait for stability ([#55271](https://github.com/angular/angular/pull/55271)) |
|
||||
| [5cf14da35c](https://github.com/angular/angular/commit/5cf14da35cce1ea4456bae4365d3dbe6667b1881) | fix | make `ActivatedRoute` inject correct instance inside `@defer` blocks ([#55374](https://github.com/angular/angular/pull/55374)) |
|
||||
| [8979fba2c5](https://github.com/angular/angular/commit/8979fba2c5813673767a133caeec9ac768d17329) | fix | skip defer timers on the server ([#55480](https://github.com/angular/angular/pull/55480)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.5"></a>
|
||||
# 18.0.0-next.5 (2024-04-17)
|
||||
## Breaking Changes
|
||||
### common
|
||||
- The deprecated `isPlatformWorkerUi` and `isPlatformWorkerApp` have been removed without replacement, as they serve no purpose since the removal of the WebWorker platform.
|
||||
### compiler
|
||||
- Angular only supports writable expressions inside of two-way bindings.
|
||||
### core
|
||||
- Angular will ensure change detection runs, even when the state update originates from
|
||||
outside the zone, tests may observe additional rounds of change
|
||||
detection compared to the previous behavior.
|
||||
|
||||
This change will be more likely to impact existing unit tests.
|
||||
This should usually be seen as more correct and the test should be updated,
|
||||
but in cases where it is too much effort to debug, the test can revert to the old behavior by adding
|
||||
`provideZoneChangeDetection({schedulingMode: NgZoneSchedulingMode.NgZoneOnly})`
|
||||
to the `TestBed` providers.
|
||||
|
||||
Similarly, applications which may want to update state outside the zone
|
||||
and _not_ trigger change detection can add
|
||||
`provideZoneChangeDetection({schedulingMode: NgZoneSchedulingMode.NgZoneOnly})`
|
||||
to the providers in `bootstrapApplication` or add
|
||||
`schedulingMode: NgZoneSchedulingMode.NgZoneOnly` to the
|
||||
`BootstrapOptions` of `bootstrapModule`.
|
||||
- Testability methods `increasePendingRequestCount`,
|
||||
`decreasePendingRequestCount` and `getPendingRequestCount` have been
|
||||
removed. This information is tracked with zones.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3b0de30b37](https://github.com/angular/angular/commit/3b0de30b37f558d4815ca9a61db1010aaf3df068) | refactor | remove deprecated `isPlatformWorkerApp` and `isPlatformWorkerUi` API ([#55302](https://github.com/angular/angular/pull/55302)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7d5bc1c628](https://github.com/angular/angular/commit/7d5bc1c62870d9c68e06eddec229a9b8988e92ee) | fix | remove container index from conditional instruction ([#55190](https://github.com/angular/angular/pull/55190)) |
|
||||
| [4eb0165750](https://github.com/angular/angular/commit/4eb0165750d8c65812502343a70ef4cc35c725b9) | fix | remove support for unassignable expressions in two-way bindings ([#55342](https://github.com/angular/angular/pull/55342)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fdd560ea14](https://github.com/angular/angular/commit/fdd560ea14f2f35608e26102c7fac0471a634b3e) | feat | Add ability to configure zone change detection to use zoneless scheduler ([#55252](https://github.com/angular/angular/pull/55252)) |
|
||||
| [bce5e2344f](https://github.com/angular/angular/commit/bce5e2344f312dc3a8a30d54e412958bd07180c1) | feat | Add build target for jsaction contract binary. ([#55319](https://github.com/angular/angular/pull/55319)) |
|
||||
| [f09c5a7bc4](https://github.com/angular/angular/commit/f09c5a7bc455a59aea133264cbf9fd9ef7509a7f) | feat | Add zoneless change detection provider as experimental ([#55329](https://github.com/angular/angular/pull/55329)) |
|
||||
| [d28614b90e](https://github.com/angular/angular/commit/d28614b90eff835639747e8961fe61e874c44666) | feat | Modify EventType from an enum to an object. ([#55323](https://github.com/angular/angular/pull/55323)) |
|
||||
| [1ee9f32621](https://github.com/angular/angular/commit/1ee9f32621f6d72e8038a08f5ad4a0cfe8bd6a13) | feat | Synchronize changes from internal JSAction codebase. ([#55182](https://github.com/angular/angular/pull/55182)) |
|
||||
| [de7447d15e](https://github.com/angular/angular/commit/de7447d15ed964ae26f0dace4cb3b08f5cccb1c1) | fix | Angular should not ignore changes that happen outside the zone ([#55102](https://github.com/angular/angular/pull/55102)) |
|
||||
| [0cec9e4f9a](https://github.com/angular/angular/commit/0cec9e4f9a90ec59f0e9838dcbd82705b1709fc0) | fix | Fix null dereference error `addEvent` ([#55353](https://github.com/angular/angular/pull/55353)) |
|
||||
| [6534c035c0](https://github.com/angular/angular/commit/6534c035c099b30987d6fd1346aea454b79cc79d) | fix | Remove deprecated Testability methods ([#53768](https://github.com/angular/angular/pull/53768)) |
|
||||
### service-worker
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3bc63eaaf3](https://github.com/angular/angular/commit/3bc63eaaf344712ac6de1c9618d4558d9443c848) | fix | avoid running CDs on `controllerchange` ([#54222](https://github.com/angular/angular/pull/54222)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.5"></a>
|
||||
# 17.3.5 (2024-04-17)
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.4"></a>
|
||||
# 18.0.0-next.4 (2024-04-10)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2a6f809507](https://github.com/angular/angular/commit/2a6f80950756530d5fb1147addabcb31025b0a78) | fix | invalid ImageKit quality parameter ([#55193](https://github.com/angular/angular/pull/55193)) |
|
||||
| [11705f58a7](https://github.com/angular/angular/commit/11705f58a77e9390163b0bc99439fb4c8928e531) | fix | skip transfer cache on client ([#55012](https://github.com/angular/angular/pull/55012)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [39624c6b12](https://github.com/angular/angular/commit/39624c6b129252af352c22c6d6f12ef153477bfc) | fix | output input flags as a literal ([#55215](https://github.com/angular/angular/pull/55215)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bd236cc150](https://github.com/angular/angular/commit/bd236cc150e1b21932612ecf91678be77a503d18) | fix | implement getDefinitionAtPosition for Angular templates ([#55269](https://github.com/angular/angular/pull/55269)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.4"></a>
|
||||
# 17.3.4 (2024-04-10)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [53427d875d](https://github.com/angular/angular/commit/53427d875d33de16b1dbb04e76a9fe32a2b8a445) | fix | invalid ImageKit quality parameter ([#55193](https://github.com/angular/angular/pull/55193)) |
|
||||
| [766548c3ec](https://github.com/angular/angular/commit/766548c3ecc06ffd8f06ed9a7d0cbb3db6f1b0f6) | fix | skip transfer cache on client ([#55012](https://github.com/angular/angular/pull/55012)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.3"></a>
|
||||
# 18.0.0-next.3 (2024-04-03)
|
||||
## Breaking Changes
|
||||
### router
|
||||
- Providers available to the routed components always
|
||||
come from the injector heirarchy of the routes and never inherit from
|
||||
the `RouterOutlet`. This means that providers available only to the
|
||||
component that defines the `RouterOutlet` will no longer be available to
|
||||
route components in any circumstances. This was already the case
|
||||
whenever routes defined providers, either through lazy loading an
|
||||
`NgModule` or through explicit `providers` on the route config.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f824911510](https://github.com/angular/angular/commit/f8249115102204dbb957a0d292ed5342ea5108e9) | fix | For `FatalDiagnosticError`, hide the `message` field without affecting the emit ([#55160](https://github.com/angular/angular/pull/55160)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c04ffb1fa6](https://github.com/angular/angular/commit/c04ffb1fa61f5164ee5eb7c05b7d76292042ff0b) | fix | use switch statements to narrow Angular switch blocks ([#55168](https://github.com/angular/angular/pull/55168)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [666d646575](https://github.com/angular/angular/commit/666d646575800e9326eebd513776f8e92b0357e9) | feat | Add event delegation library to queue up events and replay them when the application is ready ([#55121](https://github.com/angular/angular/pull/55121)) |
|
||||
| [146306a141](https://github.com/angular/angular/commit/146306a1417c378920d80a6d91fd847f22e407ab) | feat | add support for i18n hydration ([#54823](https://github.com/angular/angular/pull/54823)) |
|
||||
| [840c375255](https://github.com/angular/angular/commit/840c375255dc381674bb27746d9ababd14567c33) | fix | do not save point-in-time `setTimeout` and `rAF` references ([#55124](https://github.com/angular/angular/pull/55124)) |
|
||||
| [231e0a3528](https://github.com/angular/angular/commit/231e0a3528e152cb1de3a215d437f5104191445c) | fix | handle `ChainedInjector`s in injector debug utils ([#55144](https://github.com/angular/angular/pull/55144)) |
|
||||
| [a5fa279b6e](https://github.com/angular/angular/commit/a5fa279b6e9f5ab4005d6d33107f0e1bb48d05de) | fix | prevent i18n hydration from cleaning projected nodes ([#54823](https://github.com/angular/angular/pull/54823)) |
|
||||
| [f44a5e4604](https://github.com/angular/angular/commit/f44a5e460491a29e5c0cad5577bade8347d52e11) | fix | support content projection and VCRs in i18n ([#54823](https://github.com/angular/angular/pull/54823)) |
|
||||
| [914e4530b0](https://github.com/angular/angular/commit/914e4530b036eb20eb553dbb47f89183458066f4) | fix | test cleanup should not throw if Zone is not present ([#55096](https://github.com/angular/angular/pull/55096)) |
|
||||
| [a99cb7ce5b](https://github.com/angular/angular/commit/a99cb7ce5b77a125ab660da8ebef23ecb158e2e3) | fix | zoneless scheduler should check if Zone is defined before accessing it ([#55118](https://github.com/angular/angular/pull/55118)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1c736dc3b2](https://github.com/angular/angular/commit/1c736dc3b258a502360cda40b3a00c07102ccbf5) | feat | Unified Control State Change Events ([#54579](https://github.com/angular/angular/pull/54579)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a48afe0d94](https://github.com/angular/angular/commit/a48afe0d9478aca314e68552f4af77f4123563cd) | fix | avoid generating TS syntactic diagnostics for templates ([#55091](https://github.com/angular/angular/pull/55091)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0c20c4075a](https://github.com/angular/angular/commit/0c20c4075af753d8e5eaecb5f7114a48ced5ad96) | fix | avoid conflicts with some greek letters in control flow migration ([#55113](https://github.com/angular/angular/pull/55113)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [45ae7a6b60](https://github.com/angular/angular/commit/45ae7a6b60019bd49b8a58122a0d5bcbda7e245b) | feat | add withI18nSupport() in developer preview ([#55130](https://github.com/angular/angular/pull/55130)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [87f3f27f90](https://github.com/angular/angular/commit/87f3f27f9087d757e18e8e2a0f2fca6f2a2c7edf) | feat | Allow resolvers to return `RedirectCommand` ([#54556](https://github.com/angular/angular/pull/54556)) |
|
||||
| [3839cfbb18](https://github.com/angular/angular/commit/3839cfbb18fcc70cae5a6ba4ba7676b1c4acf7a0) | fix | Routed components never inherit `RouterOutlet` `EnvironmentInjector` ([#54265](https://github.com/angular/angular/pull/54265)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.2"></a>
|
||||
# 18.0.0-next.2 (2024-03-28)
|
||||
## Breaking Changes
|
||||
### compiler-cli
|
||||
- * Angular no longer supports TypeScript versions older than 5.4.
|
||||
### core
|
||||
- `ComponentFixture.whenStable` now matches the
|
||||
`ApplicationRef.isStable` observable. Prior to this change, stability
|
||||
of the fixture did not include everything that was considered in
|
||||
`ApplicationRef`. `whenStable` of the fixture will now include unfinished
|
||||
router navigations and unfinished `HttpClient` requests. This will cause
|
||||
tests that `await` the `whenStable` promise to time out when there are
|
||||
incomplete requests. To fix this, remove the `whenStable`,
|
||||
instead wait for another condition, or ensure `HttpTestingController`
|
||||
mocks responses for all requests. Try adding `HttpTestingController.verify()`
|
||||
before your `await fixture.whenStable` to identify the open requests.
|
||||
Also, make sure your tests wait for the stability promise. We found many
|
||||
examples of tests that did not, meaning the expectations did not execute
|
||||
within the test body.
|
||||
|
||||
In addition, `ComponentFixture.isStable` would synchronously switch to
|
||||
true in some scenarios but will now always be asynchronous.
|
||||
### router
|
||||
- When a a guard returns a `UrlTree` as a redirect, the
|
||||
redirecting navigation will now use `replaceUrl` if the initial
|
||||
navigation was also using the `replaceUrl` option. If this is not
|
||||
desirable, the redirect can configure new `NavigationBehaviorOptions` by
|
||||
returning a `RedirectCommand` with the desired options instead of `UrlTree`.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7fc7f3f05f](https://github.com/angular/angular/commit/7fc7f3f05f0139dd773032fd5ad308f8d2a9fcf5) | fix | capture all control flow branches for content projection in if blocks ([#54921](https://github.com/angular/angular/pull/54921)) |
|
||||
| [a369f43fbd](https://github.com/angular/angular/commit/a369f43fbdf45456bbae1caf71ef7becd15d1e90) | fix | capture switch block cases for content projection ([#54921](https://github.com/angular/angular/pull/54921)) |
|
||||
| [eb625d3783](https://github.com/angular/angular/commit/eb625d37839c3b9f20a2ffb3af06426f9910c8ac) | fix | declare for loop aliases in addition to new name ([#54942](https://github.com/angular/angular/pull/54942)) |
|
||||
| [bfd0bd574e](https://github.com/angular/angular/commit/bfd0bd574e9a2e1489a007393caae266512c0f04) | fix | invoke method-based tracking function with context ([#54960](https://github.com/angular/angular/pull/54960)) |
|
||||
| [e1650e3b13](https://github.com/angular/angular/commit/e1650e3b13556ab09c919cfdf97913fa0291622c) | fix | throw error if item name and context variables conflict ([#55045](https://github.com/angular/angular/pull/55045)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5bd188a394](https://github.com/angular/angular/commit/5bd188a394d30053099e2c83fe79136d590e5399) | feat | add partial compilation support for deferred blocks ([#54908](https://github.com/angular/angular/pull/54908)) |
|
||||
| [b02b31a915](https://github.com/angular/angular/commit/b02b31a915333e680cf96de5d0f965a6e2639028) | feat | drop support for TypeScript older than 5.4 ([#54961](https://github.com/angular/angular/pull/54961)) |
|
||||
| [78188e877a](https://github.com/angular/angular/commit/78188e877a4db8655bdd3dc5012b70b12a7234de) | fix | add diagnostic if initializer API is used outside of an initializer ([#54993](https://github.com/angular/angular/pull/54993)) |
|
||||
| [694ba79cbf](https://github.com/angular/angular/commit/694ba79cbf7aaed1079b1fabf53ea446162fc933) | fix | report cases where initializer APIs are used in a non-directive class ([#54993](https://github.com/angular/angular/pull/54993)) |
|
||||
| [6219341d26](https://github.com/angular/angular/commit/6219341d267ae7689299835b90f0afa0fe61e213) | fix | report errors when initializer APIs are used on private fields ([#54981](https://github.com/angular/angular/pull/54981)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a600a39d0c](https://github.com/angular/angular/commit/a600a39d0cf9bb8fc2b6786e6f31acb78b7acc6e) | feat | add support for fallback content in ng-content ([#54854](https://github.com/angular/angular/pull/54854)) |
|
||||
| [658cf8c384](https://github.com/angular/angular/commit/658cf8c3840b637284a5bb6c9751226d24ccbf9f) | fix | `ComponentFixture` stability should match `ApplicationRef` ([#54949](https://github.com/angular/angular/pull/54949)) |
|
||||
| [2fc11eae9e](https://github.com/angular/angular/commit/2fc11eae9ea65160866bf7ba46c10520ae9a141f) | fix | account for re-projected ng-content elements with fallback content ([#54854](https://github.com/angular/angular/pull/54854)) |
|
||||
| [1c0ec56c46](https://github.com/angular/angular/commit/1c0ec56c462cf18fb38aae29858165a08b5a2a82) | fix | correctly project single-root content inside control flow ([#54921](https://github.com/angular/angular/pull/54921)) |
|
||||
| [86a359b399](https://github.com/angular/angular/commit/86a359b399456e62335a0bcfe7c7fb48b7c2b781) | fix | establish proper injector resolution order for `@defer` blocks ([#55079](https://github.com/angular/angular/pull/55079)) |
|
||||
| [e02bcf89cf](https://github.com/angular/angular/commit/e02bcf89cf77c3118c649a7db68e66a78f16155c) | fix | Fix clearing of pending task in zoneless cleanup implementation ([#55074](https://github.com/angular/angular/pull/55074)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cf73983fdc](https://github.com/angular/angular/commit/cf73983fdc5fca955fbe729b231a207fc5cd70fd) | fix | include transferCache when cloning HttpRequest ([#54939](https://github.com/angular/angular/pull/54939)) |
|
||||
| [13554f9637](https://github.com/angular/angular/commit/13554f9637c222671253e733114cfbc815c6d33d) | fix | manage different body types for caching POST requests ([#54980](https://github.com/angular/angular/pull/54980)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6d1b82df32](https://github.com/angular/angular/commit/6d1b82df32049cfaba2f6a50b9639b6e3b722170) | fix | allow external projects to use provided compiler options ([#55035](https://github.com/angular/angular/pull/55035)) |
|
||||
| [4166dfc1b6](https://github.com/angular/angular/commit/4166dfc1b62a83b60203bfe45a6d4aa7148a0b23) | fix | prevent underlying TS Service from handling template files ([#55003](https://github.com/angular/angular/pull/55003)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [63688714ae](https://github.com/angular/angular/commit/63688714aeb788a24b030f9f9cdcc55e7fb0d758) | fix | account for variables in imports initializer ([#55081](https://github.com/angular/angular/pull/55081)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [60f1d681e0](https://github.com/angular/angular/commit/60f1d681e0ba66d3d94b0819f2c612f095c2d3d3) | fix | preserve replaceUrl when returning a urlTree from CanActivate ([#54042](https://github.com/angular/angular/pull/54042)) |
|
||||
| [eae75ff3f9](https://github.com/angular/angular/commit/eae75ff3f9f564b919debe3f9fa41ed1b073a22c) | fix | RouterLinkActive will always remove active classes when links are not active ([#54982](https://github.com/angular/angular/pull/54982)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.2"></a>
|
||||
# 17.3.2 (2024-03-28)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2b7bad5151](https://github.com/angular/angular/commit/2b7bad515100cbfa40b3e8d844bae13d43fd5602) | fix | invoke method-based tracking function with context ([#54960](https://github.com/angular/angular/pull/54960)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b478dfbfda](https://github.com/angular/angular/commit/b478dfbfda3f32fbe723a1e8725e86490422520d) | fix | report errors when initializer APIs are used on private fields ([#55070](https://github.com/angular/angular/pull/55070)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [708ba8115f](https://github.com/angular/angular/commit/708ba8115f7ad05201db5c529aefe4dd48fc64c5) | fix | establish proper injector resolution order for `@defer` blocks ([#55079](https://github.com/angular/angular/pull/55079)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cb433af0e1](https://github.com/angular/angular/commit/cb433af0e1ba61073eb4a02ccd75cf360e9fd409) | fix | include transferCache when cloning HttpRequest ([#54939](https://github.com/angular/angular/pull/54939)) |
|
||||
| [64f202cab9](https://github.com/angular/angular/commit/64f202cab9e7a5c873b17bbddd02368006426152) | fix | manage different body types for caching POST requests ([#54980](https://github.com/angular/angular/pull/54980)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2f9d94bc4a](https://github.com/angular/angular/commit/2f9d94bc4ab5a94e620a13404aba4e094f8b2344) | fix | account for variables in imports initializer ([#55081](https://github.com/angular/angular/pull/55081)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [365fd50407](https://github.com/angular/angular/commit/365fd504077d0e7509efc3077ea4ae8bbafb01f7) | fix | RouterLinkActive will always remove active classes when links are not active ([#54982](https://github.com/angular/angular/pull/54982)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.1"></a>
|
||||
# 18.0.0-next.1 (2024-03-20)
|
||||
## Breaking Changes
|
||||
### platform-browser-dynamic
|
||||
- No longer used `RESOURCE_CACHE_PROVIDER` APIs have been removed.
|
||||
### platform-server
|
||||
- deprecated `platformDynamicServer` has been removed. Add an `import @angular/compiler` and replace the usage with `platformServer`
|
||||
- deprecated `ServerTransferStateModule` has been removed. `TransferState` can be use without providing this module.
|
||||
- deprecated `useAbsoluteUrl` and `baseUrl` been removed from `PlatformConfig`. Provide and absolute `url` instead.
|
||||
- Legacy handling or Node.js URL parsing has been removed from `ServerPlatformLocation`.
|
||||
|
||||
The main differences are;
|
||||
- `pathname` is always suffixed with a `/`.
|
||||
- `port` is empty when `http:` protocol and port in url is `80`
|
||||
- `port` is empty when `https:` protocol and port in url is `443`
|
||||
### router
|
||||
- This change allows `Route.redirectTo` to be a function
|
||||
in addition to the previous string. Code which expects `redirectTo` to
|
||||
only be a string on `Route` objects will need to be adjusted.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [879bd80b57](https://github.com/angular/angular/commit/879bd80b571368bdc6e65c5415d98ad0f546267a) | fix | capture data bindings for content projection purposes in blocks ([#54876](https://github.com/angular/angular/pull/54876)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6aff144232](https://github.com/angular/angular/commit/6aff14423238f8995da8104e60c0baca26df2020) | fix | symbol feature detection for the compiler ([#54711](https://github.com/angular/angular/pull/54711)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [314112de99](https://github.com/angular/angular/commit/314112de99bb97475a0d8bdbddf84a3b3ce4a8fb) | fix | Prevent `markForCheck` during change detection from causing infinite loops ([#54900](https://github.com/angular/angular/pull/54900)) |
|
||||
### platform-browser-dynamic
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [eb20c1a8b1](https://github.com/angular/angular/commit/eb20c1a8b18e2e080c856e3e1bf7bcd02f3bfd28) | refactor | unused `RESOURCE_CACHE_PROVIDER` API has been removed ([#54875](https://github.com/angular/angular/pull/54875)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [07ac017731](https://github.com/angular/angular/commit/07ac017731f0e08ea3736f1f212093a28648a304) | refactor | remove deprecated `platformDynamicServer` API ([#54874](https://github.com/angular/angular/pull/54874)) |
|
||||
| [e8b588d8b7](https://github.com/angular/angular/commit/e8b588d8b7fc014aaef99d4b0c1e4567b4aa195d) | refactor | remove deprecated `ServerTransferStateModule` API ([#54874](https://github.com/angular/angular/pull/54874)) |
|
||||
| [3b1967ca64](https://github.com/angular/angular/commit/3b1967ca64479df9137b3ad7a0d04dbaff6496f4) | refactor | remove deprecated `useAbsoluteUrl` and `baseUrl` from `PlatformConfig` ([#54874](https://github.com/angular/angular/pull/54874)) |
|
||||
| [2357d3566c](https://github.com/angular/angular/commit/2357d3566c4d18dc40cbda6644ed459ef7703893) | refactor | remove legacy URL handling logic ([#54874](https://github.com/angular/angular/pull/54874)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2b802587f2](https://github.com/angular/angular/commit/2b802587f27186baa493c1dd01f42d568b652f38) | feat | Allow Route.redirectTo to be a function which returns a string or UrlTree ([#52606](https://github.com/angular/angular/pull/52606)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.1"></a>
|
||||
# 17.3.1 (2024-03-20)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c0788200e2](https://github.com/angular/angular/commit/c0788200e26406bacb90ee0079ea9753eebd1b32) | fix | capture data bindings for content projection purposes in blocks ([#54876](https://github.com/angular/angular/pull/54876)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [99e9474aa2](https://github.com/angular/angular/commit/99e9474aa2ccccdf4385fbac6b62b1a4585ed4b4) | fix | symbol feature detection for the compiler ([#54711](https://github.com/angular/angular/pull/54711)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="18.0.0-next.0"></a>
|
||||
# 18.0.0-next.0 (2024-03-14)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- `OnPush` views at the root of the application need to
|
||||
be marked dirty for their host bindings to refresh. Previously, the host
|
||||
bindings were refreshed for all root views without respecting the
|
||||
`OnPush` change detection strategy.
|
||||
- The `ComponentFixture` `autoDetect` feature will no
|
||||
longer refresh the component's host view when the component is `OnPush`
|
||||
and not marked dirty. This exposes existing issues in components which
|
||||
claim to be `OnPush` but do not correctly call `markForCheck` when they
|
||||
need to be refreshed. If this change causes test failures, the easiest
|
||||
fix is to change the component to `ChangeDetectionStrategy.Default`.
|
||||
- When Angular runs change detection, it will continue to
|
||||
refresh any views attached to `ApplicationRef` that are still marked for
|
||||
check after one round completes. In rare cases, this can result in infinite
|
||||
loops when certain patterns continue to mark views for check using
|
||||
`ChangeDetectorRef.detectChanges`. This will be surfaced as a runtime
|
||||
error with the `NG0103` code.
|
||||
- The `ComponentFixture.autoDetect` feature now executes
|
||||
change detection for the fixture within `ApplicationRef.tick`. This more
|
||||
closely matches the behavior of how a component would refresh in
|
||||
production. The order of component refresh in tests may be slightly
|
||||
affected as a result, especially when dealing with additional components
|
||||
attached to the application, such as dialogs. Tests sensitive to this
|
||||
type of change (such as screenshot tests) may need to be updated.
|
||||
Concretely, this change means that the component will refresh _before_
|
||||
additional views attached to `ApplicationRef` (i.e. dialog components).
|
||||
Prior to this change, the fixture component would refresh _after_ other
|
||||
views attached to the application.
|
||||
- The exact timing of change detection execution when
|
||||
using event or run coalescing with `NgZone` is now the first of either
|
||||
`setTimeout` or `requestAnimationFrame`. Code which relies on this
|
||||
timing (usually by accident) will need to be adjusted. If a callback
|
||||
needs to execute after change detection, we recommend `afterNextRender`
|
||||
instead of something like `setTimeout`.
|
||||
- Newly created and views marked for check and reattached
|
||||
during change detection are now guaranteed to be refreshed in that same
|
||||
change detection cycle. Previously, if they were attached at a location
|
||||
in the view tree that was already checked, they would either throw
|
||||
`ExpressionChangedAfterItHasBeenCheckedError` or not be refreshed until
|
||||
some future round of change detection. In rare circumstances, this
|
||||
correction can cause issues. We identified one instance that relied on
|
||||
the previous behavior by reading a value on initialization which was
|
||||
queued to be updated in a microtask instead of being available in the
|
||||
current change detection round. The component only read this value during
|
||||
initialization and did not read it again after the microtask updated it.
|
||||
### router
|
||||
- Guards can now return `RedirectCommand` for redirects
|
||||
in addition to `UrlTree`. Code which expects only `boolean` or `UrlTree`
|
||||
values in `Route` types will need to be adjusted.
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9b424d7224](https://github.com/angular/angular/commit/9b424d7224db46edb16c81979c7e231d5e3db5e9) | fix | preserve original reference to non-deferrable dependency ([#54759](https://github.com/angular/angular/pull/54759)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [64f870c12b](https://github.com/angular/angular/commit/64f870c12bae1ad66509f0d65f8d3e051aae6eaa) | fix | `ApplicationRef.tick` should respect OnPush for host bindings ([#53718](https://github.com/angular/angular/pull/53718)) ([#53718](https://github.com/angular/angular/pull/53718)) |
|
||||
| [8cad4e8cbe](https://github.com/angular/angular/commit/8cad4e8cbe2baf20dae7b7ef1f4253a4940cbba0) | fix | `ComponentFixture` `autoDetect` respects `OnPush` flag of host view ([#54824](https://github.com/angular/angular/pull/54824)) |
|
||||
| [ba8e465974](https://github.com/angular/angular/commit/ba8e46597435a827670f10b971b2c58f7033b180) | fix | Change Detection will continue to refresh views while marked for check ([#54734](https://github.com/angular/angular/pull/54734)) |
|
||||
| [24bc0ed4f2](https://github.com/angular/angular/commit/24bc0ed4f2de47bd998338d73cba394fb45dd497) | fix | ComponentFixture autodetect should detect changes within ApplicationRef.tick ([#54733](https://github.com/angular/angular/pull/54733)) |
|
||||
| [10c5cdb49c](https://github.com/angular/angular/commit/10c5cdb49c51c95086febd37f4d88a9b944d7e1c) | fix | ensure change detection runs in a reasonable timeframe with zone coalescing ([#54578](https://github.com/angular/angular/pull/54578)) |
|
||||
| [ad045efd4b](https://github.com/angular/angular/commit/ad045efd4b1565e01c14399998143538ebfbfd99) | fix | Ensure views marked for check are refreshed during change detection ([#54735](https://github.com/angular/angular/pull/54735)) |
|
||||
| [700c0520bb](https://github.com/angular/angular/commit/700c0520bb638952ba41a8d8260cf12afb078c0e) | fix | Update ApplicationRef.tick loop to only throw in dev mode ([#54848](https://github.com/angular/angular/pull/54848)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8735af08b9](https://github.com/angular/angular/commit/8735af08b976b30cf236a83f9e8b64b5ff62e9f3) | feat | Add ability to return `UrlTree` with `NavigationBehaviorOptions` from guards ([#45023](https://github.com/angular/angular/pull/45023)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.0"></a>
|
||||
# 17.3.0 (2024-03-13)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1a6beae8a2](https://github.com/angular/angular/commit/1a6beae8a2bdcff27d4c1e402f98246a52247906) | feat | Enable template pipeline by default. ([#54571](https://github.com/angular/angular/pull/54571)) |
|
||||
| [f386a04c9d](https://github.com/angular/angular/commit/f386a04c9ddc2951c8105d5cafcce7b4bedea569) | fix | handle two-way bindings to signal-based template variables in instruction generation ([#54714](https://github.com/angular/angular/pull/54714)) |
|
||||
| [1f129f114e](https://github.com/angular/angular/commit/1f129f114edb21137d74471dd6b652848d2ffb68) | fix | not catching for loop empty tracking expressions ([#54772](https://github.com/angular/angular/pull/54772)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [12dc4d074e](https://github.com/angular/angular/commit/12dc4d074e63edaff626003ad6136a8d122b2ba6) | fix | account for as expression in docs extraction ([#54414](https://github.com/angular/angular/pull/54414)) |
|
||||
| [da7fbb40f0](https://github.com/angular/angular/commit/da7fbb40f06e6e37504f69e7b335f8219f424de2) | fix | detect when the linker is working in unpublished angular and widen supported versions ([#54439](https://github.com/angular/angular/pull/54439)) |
|
||||
| [492e03f699](https://github.com/angular/angular/commit/492e03f699ca95df4cf854885253f63a5a1fb5c1) | fix | flag two-way bindings to non-signal values in templates ([#54714](https://github.com/angular/angular/pull/54714)) |
|
||||
| [5afa4f0ec1](https://github.com/angular/angular/commit/5afa4f0ec1b64b88ef875d48bd143e0f36e0a955) | fix | support `ModuleWithProviders` literal detection with `typeof` ([#54650](https://github.com/angular/angular/pull/54650)) |
|
||||
| [ae7dbe42de](https://github.com/angular/angular/commit/ae7dbe42de5779e578fb636938699b8ba85b33f6) | fix | unwrap expressions with type parameters in query read property ([#54647](https://github.com/angular/angular/pull/54647)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [331b16efd2](https://github.com/angular/angular/commit/331b16efd2f5af876e6dc0ad2474ee7a87b00de5) | feat | add API to inject attributes on the host node ([#54604](https://github.com/angular/angular/pull/54604)) |
|
||||
| [fb540e169a](https://github.com/angular/angular/commit/fb540e169a78a61f38d611f538eea8fdb0971f1d) | feat | add migration for invalid two-way bindings ([#54630](https://github.com/angular/angular/pull/54630)) |
|
||||
| [c687b8f453](https://github.com/angular/angular/commit/c687b8f4531252cd1c3dfbb9a7bd42bdbe666a36) | feat | expose new `output()` API ([#54650](https://github.com/angular/angular/pull/54650)) |
|
||||
| [c809069f21](https://github.com/angular/angular/commit/c809069f213244afd0e2d803a6a43510b218e6f5) | feat | introduce `outputFromObservable()` interop function ([#54650](https://github.com/angular/angular/pull/54650)) |
|
||||
| [aff65fd1f4](https://github.com/angular/angular/commit/aff65fd1f4a61ed76a6f9b623852f197eb3500e4) | feat | introduce `outputToObservable` interop helper ([#54650](https://github.com/angular/angular/pull/54650)) |
|
||||
| [974958913c](https://github.com/angular/angular/commit/974958913ca632971f878a045537472f2c99c665) | feat | support TypeScript 5.4 ([#54414](https://github.com/angular/angular/pull/54414)) |
|
||||
| [39a50f9a8d](https://github.com/angular/angular/commit/39a50f9a8df5afc4968d18924f3d9d7d6b649d3a) | fix | ensure all initializer functions run in an injection context ([#54761](https://github.com/angular/angular/pull/54761)) |
|
||||
| [243ccce624](https://github.com/angular/angular/commit/243ccce62475ae03a2e727d2b3cb2d51a595c4a7) | fix | exclude class attribute intended for projection matching from directive matching ([#54800](https://github.com/angular/angular/pull/54800)) |
|
||||
| [2909e9817d](https://github.com/angular/angular/commit/2909e9817daf69b6478d7d09229491a9a48cff16) | fix | prevent infinite loops in clobbered elements check ([#54425](https://github.com/angular/angular/pull/54425)) |
|
||||
| [33a6fab094](https://github.com/angular/angular/commit/33a6fab094205cc74aceb916e45c8afa22293cf4) | fix | apply TestBed provider overrides to `@defer` dependencies ([#54667](https://github.com/angular/angular/pull/54667)) |
|
||||
| [78e69117f0](https://github.com/angular/angular/commit/78e69117f07e8ae11aab3abe0343df815b3649be) | fix | generic inference for signal inputs may break with `--strictFunctionTypes` ([#54652](https://github.com/angular/angular/pull/54652)) |
|
||||
| [7243c704cf](https://github.com/angular/angular/commit/7243c704cf8a4986fae419793027458e142658f0) | fix | return a readonly signal on `asReadonly`. ([#54706](https://github.com/angular/angular/pull/54706)) |
|
||||
| [bb35414a38](https://github.com/angular/angular/commit/bb35414a38f8a8447d03c66dc5bf60b84409f9e3) | perf | speed up retrieval of `DestroyRef` in `EventEmitter` ([#54748](https://github.com/angular/angular/pull/54748)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8d37ed035c](https://github.com/angular/angular/commit/8d37ed035c9e9796ba9a7b1f055404ea220dbb3b) | fix | exclude caching for authenticated HTTP requests ([#54746](https://github.com/angular/angular/pull/54746)) |
|
||||
| [ffad7b8ea9](https://github.com/angular/angular/commit/ffad7b8ea9d1286ddb3ee7a2dac7dd33fd76b3aa) | fix | untrack various core operations ([#54614](https://github.com/angular/angular/pull/54614)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c1c7384e02](https://github.com/angular/angular/commit/c1c7384e02becc623c6a42985f7178ca98137264) | feat | Add reusable types for router guards ([#54580](https://github.com/angular/angular/pull/54580)) |
|
||||
| [7225485311](https://github.com/angular/angular/commit/722548531108e247660ebe6966b99b57d510b615) | fix | Navigations triggered by cancellation events should cancel previous navigation ([#54710](https://github.com/angular/angular/pull/54710)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
@@ -579,6 +63,46 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.0-next.1"></a>
|
||||
# 17.3.0-next.1 (2024-02-27)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [707bfc9b32](https://github.com/angular/angular/commit/707bfc9b326f321f302dccfdfebef7380c914eb5) | perf | `AsyncPipe` should not call `markForCheck` on subscription ([#54554](https://github.com/angular/angular/pull/54554)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1a6beae8a2](https://github.com/angular/angular/commit/1a6beae8a2bdcff27d4c1e402f98246a52247906) | feat | Enable template pipeline by default. ([#54571](https://github.com/angular/angular/pull/54571)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [12dc4d074e](https://github.com/angular/angular/commit/12dc4d074e63edaff626003ad6136a8d122b2ba6) | fix | account for as expression in docs extraction ([#54414](https://github.com/angular/angular/pull/54414)) |
|
||||
| [f578889ca2](https://github.com/angular/angular/commit/f578889ca2dbb22f2e050d4c4af6aa2d597bf70d) | fix | catch function instance properties in interpolated signal diagnostic ([#54325](https://github.com/angular/angular/pull/54325)) |
|
||||
| [f04ecc0cda](https://github.com/angular/angular/commit/f04ecc0cdaeb3a292a748b1ccc94ce70a573fc79) | fix | identify aliased initializer functions ([#54480](https://github.com/angular/angular/pull/54480)) |
|
||||
| [f5c566c079](https://github.com/angular/angular/commit/f5c566c0793eacf9ca146c8a6b8da15b0e8f4c4d) | fix | identify aliased initializer functions ([#54609](https://github.com/angular/angular/pull/54609)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [331b16efd2](https://github.com/angular/angular/commit/331b16efd2f5af876e6dc0ad2474ee7a87b00de5) | feat | add API to inject attributes on the host node ([#54604](https://github.com/angular/angular/pull/54604)) |
|
||||
| [974958913c](https://github.com/angular/angular/commit/974958913ca632971f878a045537472f2c99c665) | feat | support TypeScript 5.4 ([#54414](https://github.com/angular/angular/pull/54414)) |
|
||||
| [dcb9deb363](https://github.com/angular/angular/commit/dcb9deb3631ff4e839f738f2fb97ca6b894256ef) | fix | collect providers from NgModules while rendering `@defer` block ([#52881](https://github.com/angular/angular/pull/52881)) |
|
||||
| [ff40c9f762](https://github.com/angular/angular/commit/ff40c9f762b2c14870ac2859201ece9660087e79) | fix | fix typo in injectors.svg file ([#54596](https://github.com/angular/angular/pull/54596)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [71e0c7df69](https://github.com/angular/angular/commit/71e0c7df695f274a54d5ffb9dfc0587d06d3a953) | fix | resolve infinite loop for a single line element with a long tag name and angle bracket on a new line ([#54588](https://github.com/angular/angular/pull/54588)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.3.0-next.0"></a>
|
||||
# 17.3.0-next.0 (2024-02-21)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [da7fbb40f0](https://github.com/angular/angular/commit/da7fbb40f06e6e37504f69e7b335f8219f424de2) | fix | detect when the linker is working in unpublished angular and widen supported versions ([#54439](https://github.com/angular/angular/pull/54439)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.2.2"></a>
|
||||
# 17.2.2 (2024-02-21)
|
||||
### common
|
||||
@@ -1078,6 +602,21 @@ Live long and prosper 🖖🏻
|
||||
|
||||
Example after:
|
||||
|
||||
```typescript
|
||||
items.update(itemsArray => [itemsArray, …newItem]);
|
||||
```
|
||||
- The `mutate` method was removed from the `WritableSignal` interface and completely
|
||||
dropped from the public API surface. As an alternative please use the update method and
|
||||
make immutable changes to the object.
|
||||
|
||||
Example before:
|
||||
|
||||
```typescript
|
||||
items.mutate(itemsArray => itemsArray.push(newItem));
|
||||
```
|
||||
|
||||
Example after:
|
||||
|
||||
```typescript
|
||||
items.update(itemsArray => [itemsArray, …newItem]);
|
||||
```
|
||||
|
||||
+6
-1
@@ -207,7 +207,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#formatting-your-source-code).
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
@@ -389,6 +389,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
||||
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/main/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[corporate-cla]: https://cla.developers.google.com/about/google-corporate
|
||||
@@ -397,3 +398,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
||||
[discord]: https://discord.gg/angular
|
||||
[individual-cla]: https://cla.developers.google.com/about/google-individual
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[jsfiddle]: https://jsfiddle.net/
|
||||
[plunker]: https://plnkr.co/edit
|
||||
[runnable]: https://runnable.com/
|
||||
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1 align="center">Angular - The modern web developer's platform</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="adev/src/assets/images/press-kit/angular_icon_gradient.gif" alt="angular-logo" width="120px" height="120px"/>
|
||||
<img src="aio/src/assets/images/logos/angular/angular_renaissance.png" alt="angular-logo" width="120px" height="120px"/>
|
||||
<br>
|
||||
<em>Angular is a development platform for building mobile and desktop web applications
|
||||
<br> using TypeScript/JavaScript and other languages.</em>
|
||||
@@ -63,7 +63,22 @@ Get started with Angular, learn the fundamentals and explore advanced topics on
|
||||
|
||||
### Local Development
|
||||
|
||||
To contribute to the Angular Docs, check out the [Angular.dev README](adev/README.md)
|
||||
To contribute to Angular docs, you can setup a local environment with the following commands:
|
||||
|
||||
```bash
|
||||
# Clone Angular repo
|
||||
git clone https://github.com/angular/angular.git
|
||||
|
||||
# Navigate to project directory
|
||||
cd angular
|
||||
|
||||
# Install dependencies
|
||||
yarn
|
||||
|
||||
# Build and run local dev server
|
||||
# Note: Initial build will take some time
|
||||
yarn docs
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
@@ -152,8 +167,8 @@ Join the conversation and help the community.
|
||||
[angularmaterial]: https://material.angular.io/
|
||||
[cli]: https://angular.dev/tools/cli
|
||||
[architecture]: https://angular.dev/essentials
|
||||
[componentstemplates]: https://angular.dev/tutorials/learn-angular/1-components-in-angular
|
||||
[forms]: https://angular.dev/tutorials/learn-angular/15-forms
|
||||
[componentstemplates]: https://angular.dev/tutorials/learn-angular/components-in-angular
|
||||
[forms]: https://angular.dev/tutorials/learn-angular/forms
|
||||
[api]: https://angular.dev/api
|
||||
[angularelements]: https://angular.dev/guide/elements
|
||||
[ssr]: https://angular.dev/guide/ssr
|
||||
|
||||
@@ -2,12 +2,27 @@ workspace(
|
||||
name = "angular",
|
||||
managed_directories = {
|
||||
"@npm": ["node_modules"],
|
||||
"@aio_npm": ["aio/node_modules"],
|
||||
},
|
||||
)
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("//:yarn.bzl", "YARN_LABEL")
|
||||
|
||||
# Add a patch fix for rules_webtesting v0.3.5 required for enabling runfiles on Windows.
|
||||
# TODO: Remove the http_archive for this transitive dependency when a release is cut
|
||||
# for https://github.com/bazelbuild/rules_webtesting/commit/581b1557e382f93419da6a03b91a45c2ac9a9ec8
|
||||
# and the version is updated in rules_nodejs.
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//:tools/bazel-repo-patches/rules_webtesting__windows_runfiles_fix.patch",
|
||||
],
|
||||
sha256 = "e9abb7658b6a129740c0b3ef6f5a2370864e102a5ba5ffca2cea565829ed825a",
|
||||
urls = ["https://github.com/bazelbuild/rules_webtesting/releases/download/0.3.5/rules_webtesting.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
patches = [
|
||||
@@ -50,16 +65,16 @@ load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
|
||||
nodejs_register_toolchains(
|
||||
name = "nodejs",
|
||||
node_repositories = {
|
||||
"18.20.0-darwin_arm64": ("node-v18.20.0-darwin-arm64.tar.gz", "node-v18.20.0-darwin-arm64", "10066ad4dd9e03ea5c4c45ef8775420ff37b860de09bbdf87b97e0c07b1ea036"),
|
||||
"18.20.0-darwin_amd64": ("node-v18.20.0-darwin-x64.tar.gz", "node-v18.20.0-darwin-x64", "062ba71618e88e06321de5caa038843c350aababa2d315f3ca7b8551f8e66c1c"),
|
||||
"18.20.0-linux_arm64": ("node-v18.20.0-linux-arm64.tar.xz", "node-v18.20.0-linux-arm64", "afe51da9ffb38ac1e3a20d9a06efd403ced4bf8831ab554a02a088dd8392fd79"),
|
||||
"18.20.0-linux_ppc64le": ("node-v18.20.0-linux-ppc64le.tar.xz", "node-v18.20.0-linux-ppc64le", "9e652bbf53a3e37285b11dfb9d6a9bb8b02010c3b50e5c8229d4cc10e72681da"),
|
||||
"18.20.0-linux_s390x": ("node-v18.20.0-linux-s390x.tar.xz", "node-v18.20.0-linux-s390x", "a6c2a5796b9d9e9bf21da62ec89ff30b41a8108880b9eaa3c912f1ce795a7743"),
|
||||
"18.20.0-linux_amd64": ("node-v18.20.0-linux-x64.tar.xz", "node-v18.20.0-linux-x64", "03eea148e56785babb27930b05ed6bf311aaa3bc573c0399dd63cad2fe5713c7"),
|
||||
"18.20.0-windows_amd64": ("node-v18.20.0-win-x64.zip", "node-v18.20.0-win-x64", "1c0aab05cc6836a8f5148cca345b92ebc948a4a2013f18d117b7ade6ff05aca6"),
|
||||
"18.18.2-darwin_arm64": ("node-v18.18.2-darwin-arm64.tar.gz", "node-v18.18.2-darwin-arm64", "9f982cc91b28778dd8638e4f94563b0c2a1da7aba62beb72bd427721035ab553"),
|
||||
"18.18.2-darwin_amd64": ("node-v18.18.2-darwin-x64.tar.gz", "node-v18.18.2-darwin-x64", "5bb8da908ed590e256a69bf2862238c8a67bc4600119f2f7721ca18a7c810c0f"),
|
||||
"18.18.2-linux_arm64": ("node-v18.18.2-linux-arm64.tar.xz", "node-v18.18.2-linux-arm64", "2e630e18548627f61eaf573233da7949dc0a1df5eef3f486fa9820c5f6c121aa"),
|
||||
"18.18.2-linux_ppc64le": ("node-v18.18.2-linux-ppc64le.tar.xz", "node-v18.18.2-linux-ppc64le", "b0adff5cf5938266b711d6c724fb134d802e0dee40b3a3f73d162de1b3d11880"),
|
||||
"18.18.2-linux_s390x": ("node-v18.18.2-linux-s390x.tar.xz", "node-v18.18.2-linux-s390x", "c70ec2074b5e2b42c55bb4b8105418b67bf8a61c500d9376a07430dfcc341fdb"),
|
||||
"18.18.2-linux_amd64": ("node-v18.18.2-linux-x64.tar.xz", "node-v18.18.2-linux-x64", "75aba25ae76999309fc6c598efe56ce53fbfc221381a44a840864276264ab8ac"),
|
||||
"18.18.2-windows_amd64": ("node-v18.18.2-win-x64.zip", "node-v18.18.2-win-x64", "3bb0e51e579a41a22b3bf6cb2f3e79c03801aa17acbe0ca00fc555d1282e7acd"),
|
||||
},
|
||||
# We need at least Node 18.17 due to some transitive dependencies.
|
||||
node_version = "18.20.0",
|
||||
node_version = "18.18.2",
|
||||
)
|
||||
|
||||
# Download npm dependencies.
|
||||
@@ -75,7 +90,7 @@ yarn_install(
|
||||
"//:.yarnrc",
|
||||
"//:tools/npm-patches/@bazel+jasmine+5.8.1.patch",
|
||||
"//tools:postinstall-patches.js",
|
||||
"//tools/esm-interop:patches/npm/@angular+build-tooling+0.0.0-56d0b1f597b9e4b5d99f289f6904a220802164c1.patch",
|
||||
"//tools/esm-interop:patches/npm/@angular+build-tooling+0.0.0-e0ec7b60641d7f6369be45d8d02663fd50f320be.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+concatjs+5.8.1.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+esbuild+5.7.1.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+protractor+5.7.1.patch",
|
||||
@@ -94,6 +109,30 @@ yarn_install(
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
name = "aio_npm",
|
||||
# Note that we add the postinstall scripts here so that the dependencies are re-installed
|
||||
# when the postinstall patches are modified.
|
||||
data = [
|
||||
YARN_LABEL,
|
||||
"//:.yarnrc",
|
||||
"//:tools/npm-patches/@bazel+jasmine+5.8.1.patch",
|
||||
"//aio:tools/cli-patches/bazel-architect-output.patch",
|
||||
"//aio:tools/cli-patches/patch.js",
|
||||
],
|
||||
# Currently disabled due to:
|
||||
# 1. Missing Windows support currently.
|
||||
# 2. Incompatibilites with the `ts_library` rule.
|
||||
exports_directories_only = False,
|
||||
manual_build_file_contents = npm_package_archives(),
|
||||
package_json = "//aio:package.json",
|
||||
# We prefer to symlink the `node_modules` to only maintain a single install.
|
||||
# See https://github.com/angular/dev-infra/pull/446#issuecomment-1059820287 for details.
|
||||
symlink_node_modules = True,
|
||||
yarn = YARN_LABEL,
|
||||
yarn_lock = "//aio:yarn.lock",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
name = "aio_example_deps",
|
||||
# Rename the default js_library target from "node_modules" as this obscures the
|
||||
@@ -167,10 +206,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "845061fad5cb42a353ac394fe6450ec9f21d337acf5b98011ef29ddcb33e3671",
|
||||
strip_prefix = "rules_sass-9f8be59f5175d0dd3438d7da994b2782299e0c2c",
|
||||
sha256 = "974f5e14c54d300ca63a67910ebfcea6d838d8811fefc61184f2872107152705",
|
||||
strip_prefix = "rules_sass-888dd9c02709e228b60a8b3e51e2b16b2ca5279d",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/9f8be59f5175d0dd3438d7da994b2782299e0c2c.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/888dd9c02709e228b60a8b3e51e2b16b2ca5279d.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+18
-33
@@ -1,9 +1,8 @@
|
||||
load("@npm//@angular/build-tooling/bazel/remote-execution:index.bzl", "ENABLE_NETWORK")
|
||||
load("//:packages.bzl", "link_packages")
|
||||
load("@aio_npm//@angular/build-tooling/bazel/remote-execution:index.bzl", "ENABLE_NETWORK")
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")
|
||||
load("@npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
|
||||
load("@bazel_skylib//lib:collections.bzl", "collections")
|
||||
load("//adev/tools/local_deps:index.bzl", "ensure_local_package_deps", "link_local_packages")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
@@ -31,18 +30,7 @@ TEST_FILES = APPLICATION_FILES + [
|
||||
["**/*.spec.ts"],
|
||||
)
|
||||
|
||||
APPLICATION_ASSETS = [
|
||||
"//adev/src/assets/images",
|
||||
"//adev/src/assets/textures",
|
||||
"//adev/src/assets/previews",
|
||||
"//adev/src/assets:tutorials",
|
||||
"//adev/src/assets/icons",
|
||||
"//adev/src/assets:api",
|
||||
"//adev/src/assets:content",
|
||||
]
|
||||
|
||||
APPLICATION_DEPS = [
|
||||
"@npm//@angular/build",
|
||||
APPLICATION_DEPS = link_packages([
|
||||
"@npm//@angular-devkit/build-angular",
|
||||
"@npm//@angular/animations",
|
||||
"@npm//@angular/cdk",
|
||||
@@ -62,6 +50,13 @@ APPLICATION_DEPS = [
|
||||
"@npm//ogl",
|
||||
"@npm//rxjs",
|
||||
"@npm//typescript",
|
||||
"//adev/src/assets/images",
|
||||
"//adev/src/assets/textures",
|
||||
"//adev/src/assets/previews",
|
||||
"//adev/src/assets:tutorials",
|
||||
"//adev/src/assets/icons",
|
||||
"//adev/src/assets:api",
|
||||
"//adev/src/assets:content",
|
||||
"@npm//@typescript/vfs",
|
||||
"@npm//@codemirror/state",
|
||||
"@npm//@codemirror/view",
|
||||
@@ -78,16 +73,14 @@ APPLICATION_DEPS = [
|
||||
"@npm//@lezer/highlight",
|
||||
"@npm//@lezer/javascript",
|
||||
"@npm//@lezer/common",
|
||||
"@npm//@xterm/xterm",
|
||||
"@npm//algoliasearch",
|
||||
"@npm//xterm",
|
||||
"@npm//xterm-addon-fit",
|
||||
"@npm//angular-split",
|
||||
"@npm//zone.js",
|
||||
]
|
||||
])
|
||||
|
||||
TEST_DEPS = APPLICATION_DEPS + [
|
||||
TEST_DEPS = APPLICATION_DEPS + link_packages([
|
||||
"@npm//@angular/platform-browser-dynamic",
|
||||
"@npm//@angular/build-tooling/bazel/browsers/chromium",
|
||||
"@npm//@types/jasmine",
|
||||
"@npm//@types/node",
|
||||
"@npm//assert",
|
||||
@@ -97,13 +90,8 @@ TEST_DEPS = APPLICATION_DEPS + [
|
||||
"@npm//karma-coverage",
|
||||
"@npm//karma-jasmine",
|
||||
"@npm//karma-jasmine-html-reporter",
|
||||
]
|
||||
|
||||
# Create `npm_link` targets for all dependencies that correspond to a
|
||||
# first-party Angular package that can be built from `HEAD`.
|
||||
link_local_packages(
|
||||
all_deps = collections.uniq(APPLICATION_DEPS + TEST_DEPS),
|
||||
)
|
||||
"//aio/tools:windows-chromium-path",
|
||||
])
|
||||
|
||||
copy_to_bin(
|
||||
name = "application_files_bin",
|
||||
@@ -141,7 +129,7 @@ architect(
|
||||
"--output-path=build",
|
||||
] + config_based_architect_flags,
|
||||
chdir = "$(RULEDIR)",
|
||||
data = ensure_local_package_deps(APPLICATION_DEPS) + APPLICATION_ASSETS + [
|
||||
data = APPLICATION_DEPS + [
|
||||
":application_files_bin",
|
||||
],
|
||||
# Network is required to inline fonts.
|
||||
@@ -161,7 +149,7 @@ architect(
|
||||
"--watch",
|
||||
],
|
||||
chdir = package_name(),
|
||||
data = ensure_local_package_deps(APPLICATION_DEPS) + APPLICATION_ASSETS + [
|
||||
data = APPLICATION_DEPS + [
|
||||
":application_files_bin",
|
||||
],
|
||||
tags = [
|
||||
@@ -176,10 +164,7 @@ architect_test(
|
||||
"--no-watch",
|
||||
],
|
||||
chdir = package_name(),
|
||||
data = ensure_local_package_deps(TEST_DEPS) + TEST_FILES + APPLICATION_ASSETS + [
|
||||
"//aio/tools:windows-chromium-path",
|
||||
"@npm//@angular/build-tooling/bazel/browsers/chromium",
|
||||
],
|
||||
data = TEST_DEPS + TEST_FILES,
|
||||
env = {
|
||||
"CHROME_BIN": "../$(CHROMIUM)",
|
||||
},
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# [Angular.dev](https://www.angular.dev)
|
||||
|
||||
This site is built with Angular.
|
||||
|
||||
The content is written primarly in Markdown format located in `src/content`. For simple edits, you can directly edit the file on GitHub and generate a Pull Request.
|
||||
|
||||
## Local Development
|
||||
|
||||
For local development, [yarn](https://yarnpkg.com/) is the preferred package manager. You can setup a local environment with the following commands
|
||||
:
|
||||
|
||||
```bash
|
||||
# Clone Angular repo
|
||||
git clone https://github.com/angular/angular.git
|
||||
|
||||
# Navigate to project directory
|
||||
cd angular
|
||||
|
||||
# Install dependencies
|
||||
yarn
|
||||
|
||||
# Build and run local dev server
|
||||
# Note: Initial build will take some time
|
||||
yarn docs
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to report a bug, contribute some code, or improve the documentation? Excellent!
|
||||
|
||||
Read through our [contributing guidelines](CONTRIBUTING.md) to learn about our submission process, coding rules, and more.
|
||||
|
||||
And if you're new, check out one of our issues labeled as <kbd>[help wanted](https://github.com/angular/angular/labels/help%20wanted)</kbd> or <kbd>[good first issue](https://github.com/angular/angular/labels/good%20first%20issue)</kbd>.
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
+10
-9
@@ -17,9 +17,11 @@
|
||||
"prefix": "adev",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
"builder": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"externalDependencies": ["path"],
|
||||
"externalDependencies": [
|
||||
"path"
|
||||
],
|
||||
"outputPath": "dist/angular-dev",
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
@@ -27,7 +29,11 @@
|
||||
"polyfills": ["src/polyfills.ts", "zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/robots.txt", "src/assets"],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/robots.txt",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": ["@angular/docs/styles/global-styles.scss"],
|
||||
"scripts": [],
|
||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
||||
@@ -93,11 +99,6 @@
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": "dca119a9-da31-47f7-a6cb-b60541037021",
|
||||
"cache": {
|
||||
// Disable build caching as the cache folder will just be dropped
|
||||
// when run under Bazel sandboxed execution.
|
||||
"enabled": false
|
||||
}
|
||||
"analytics": "dca119a9-da31-47f7-a6cb-b60541037021"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Generating data for `angular.dev/cli`
|
||||
|
||||
This script updates the Angular CLI help JSON files stored in `adev/src/content/cli/help`. This files are used to generate the [angular.dev CLI](https://angular.dev/cli) pages.
|
||||
@@ -1,154 +0,0 @@
|
||||
import {execSync} from 'node:child_process';
|
||||
import {readFile, writeFile, readdir, mkdtemp, realpath, copyFile, unlink} from 'node:fs/promises';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {get} from 'node:https';
|
||||
import {dirname, resolve as resolvePath, posix, join} from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {existsSync, constants as fsConstants} from 'node:fs';
|
||||
|
||||
const GITHUB_API = 'https://api.github.com/repos/';
|
||||
const CLI_BUILDS_REPO = 'angular/cli-builds';
|
||||
const GITHUB_API_CLI_BUILDS = posix.join(GITHUB_API, CLI_BUILDS_REPO);
|
||||
|
||||
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
||||
const CLI_HELP_CONTENT_PATH = resolvePath(scriptDir, '../../src/content/cli/help');
|
||||
const CLI_SHA_PATH = join(CLI_HELP_CONTENT_PATH, 'build-info.json');
|
||||
|
||||
async function main() {
|
||||
if (!existsSync(CLI_SHA_PATH)) {
|
||||
throw new Error(`${CLI_SHA_PATH} does not exist.`);
|
||||
}
|
||||
|
||||
const branch = process.env.GITHUB_REF;
|
||||
const {sha: currentSha} = JSON.parse(await readFile(CLI_SHA_PATH, 'utf-8'));
|
||||
const latestSha = await getShaFromCliBuilds(branch);
|
||||
|
||||
console.log(`Comparing ${currentSha}...${latestSha}.`);
|
||||
const affectedFiles = await getAffectedFiles(currentSha, latestSha);
|
||||
const changedHelpFiles = affectedFiles.filter((file) => file.startsWith('help/'));
|
||||
|
||||
if (changedHelpFiles.length === 0) {
|
||||
console.log(`No 'help/**' files changed between ${currentSha} and ${latestSha}.`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`The below help files changed between ${currentSha} and ${latestSha}:\n` +
|
||||
changedHelpFiles.map((f) => '* ' + f).join('\n'),
|
||||
);
|
||||
|
||||
const temporaryDir = await realpath(await mkdtemp(join(tmpdir(), 'cli-src-')));
|
||||
const execOptions = {cwd: temporaryDir, stdio: 'inherit'};
|
||||
execSync('git init', execOptions);
|
||||
execSync('git remote add origin https://github.com/angular/cli-builds.git', execOptions);
|
||||
// fetch a commit
|
||||
execSync(`git fetch origin ${latestSha}`, execOptions);
|
||||
// reset this repository's main branch to the commit of interest
|
||||
execSync('git reset --hard FETCH_HEAD', execOptions);
|
||||
// get sha when files where changed
|
||||
const shaWhenFilesChanged = execSync(`git rev-list -1 ${latestSha} "help/"`, {
|
||||
encoding: 'utf8',
|
||||
cwd: temporaryDir,
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
}).trim();
|
||||
|
||||
// Delete existing JSON help files.
|
||||
const helpFilesUnlink = (await readdir(CLI_HELP_CONTENT_PATH))
|
||||
.filter((f) => f.endsWith('.json'))
|
||||
.map((f) => unlink(join(CLI_HELP_CONTENT_PATH, f)));
|
||||
|
||||
await Promise.allSettled(helpFilesUnlink);
|
||||
|
||||
// Copy new help files
|
||||
const tempHelpDir = join(temporaryDir, 'help');
|
||||
const helpFilesCopy = (await readdir(tempHelpDir)).map((f) => {
|
||||
const src = join(tempHelpDir, f);
|
||||
const dest = join(CLI_HELP_CONTENT_PATH, f);
|
||||
|
||||
return copyFile(src, dest, fsConstants.COPYFILE_FICLONE);
|
||||
});
|
||||
|
||||
await Promise.allSettled(helpFilesCopy);
|
||||
|
||||
// Write SHA to file.
|
||||
await writeFile(
|
||||
CLI_SHA_PATH,
|
||||
JSON.stringify(
|
||||
{
|
||||
branchName: branch,
|
||||
sha: shaWhenFilesChanged,
|
||||
},
|
||||
undefined,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
console.log('\nChanges: ');
|
||||
execSync(`git status --porcelain`, {stdio: 'inherit'});
|
||||
|
||||
console.log(`Successfully updated help files in '${CLI_HELP_CONTENT_PATH}'.\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SHA of a branch.
|
||||
*
|
||||
* @param {string} branch
|
||||
* @param {string} headSha
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
async function getShaFromCliBuilds(branch) {
|
||||
const sha = await httpGet(`${GITHUB_API_CLI_BUILDS}/commits/${branch}`, {
|
||||
headers: {Accept: 'application/vnd.github.VERSION.sha'},
|
||||
});
|
||||
|
||||
if (!sha) {
|
||||
throw new Error(`Unable to extract the SHA for '${branch}'.`);
|
||||
}
|
||||
|
||||
return sha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected files.
|
||||
*
|
||||
* @param {string} baseSha
|
||||
* @param {string} headSha
|
||||
* @returns Promise<string[]>
|
||||
*/
|
||||
async function getAffectedFiles(baseSha, headSha) {
|
||||
const {files} = JSON.parse(
|
||||
await httpGet(`${GITHUB_API_CLI_BUILDS}/compare/${baseSha}...${headSha}`),
|
||||
);
|
||||
return files.map((f) => f.filename);
|
||||
}
|
||||
|
||||
function httpGet(url, options = {}) {
|
||||
options.headers ??= {};
|
||||
options.headers[
|
||||
'Authorization'
|
||||
] = `token ${process.env.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN}`;
|
||||
// User agent is required
|
||||
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#user-agent-required
|
||||
options.headers['User-Agent'] = `AIO_Angular_CLI_Sources_Update`;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
get(url, options, (res) => {
|
||||
let data = '';
|
||||
res
|
||||
.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
})
|
||||
.on('end', () => {
|
||||
resolve(data);
|
||||
});
|
||||
}).on('error', (e) => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,74 +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
|
||||
*/
|
||||
|
||||
export const VERSIONS_CONFIG = {
|
||||
currentVersion: 'stable',
|
||||
historicalVersionsLinkPattern: 'https://v{{version}}.angular.dev',
|
||||
mainVersions: [
|
||||
{
|
||||
version: 'stable',
|
||||
url: 'https://angular.dev',
|
||||
},
|
||||
{
|
||||
version: 'v16',
|
||||
url: 'https://v16.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v15',
|
||||
url: 'https://v15.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v14',
|
||||
url: 'https://v14.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v13',
|
||||
url: 'https://v13.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v12',
|
||||
url: 'https://v12.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v11',
|
||||
url: 'https://v11.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v10',
|
||||
url: 'https://v10.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v9',
|
||||
url: 'https://v9.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v8',
|
||||
url: 'https://v8.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v7',
|
||||
url: 'https://v7.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v6',
|
||||
url: 'https://v6.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v5',
|
||||
url: 'https://v5.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v4',
|
||||
url: 'https://v4.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v2',
|
||||
url: 'https://v2.angular.io/docs',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -61,9 +61,6 @@
|
||||
<nav
|
||||
class="adev-nav-primary docs-scroll-hide"
|
||||
[class.adev-nav-primary--open]="isMobileNavigationOpened()"
|
||||
[class.adev-nav-primary--rc]="currentDocsVersionMode === 'rc'"
|
||||
[class.adev-nav-primary--next]="currentDocsVersionMode === 'next'"
|
||||
[class.adev-nav-primary--deprecated]="currentDocsVersionMode === 'deprecated'"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
@@ -125,6 +122,7 @@
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
<div class="adev-beta-version">Beta Docs</div>
|
||||
</a>
|
||||
|
||||
<!-- Version picker for v18+ -->
|
||||
|
||||
@@ -69,27 +69,6 @@
|
||||
padding-block-end: 2rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.adev-nav-primary--rc {
|
||||
// change nav background to indicate this is the rc docs
|
||||
background: linear-gradient(
|
||||
140deg,
|
||||
color-mix(in srgb, var(--orange-red), transparent 60%) 0%,
|
||||
color-mix(in srgb, var(--vivid-pink), transparent 40%) 15%,
|
||||
color-mix(in srgb, var(--electric-violet), transparent 70%) 25%,
|
||||
color-mix(in srgb, var(--bright-blue), transparent 60%) 90%,
|
||||
);
|
||||
}
|
||||
|
||||
&.adev-nav-primary--next {
|
||||
// change nav background to indicate this is the rc docs
|
||||
background-color: color-mix(in srgb, var(--orange-red), transparent 60%);
|
||||
}
|
||||
|
||||
&.adev-nav-primary--deprecated {
|
||||
// change nav background to indicate this is an outdated version of the docs
|
||||
background-color: color-mix(in srgb, var(--symbolic-gray), transparent 30%);
|
||||
}
|
||||
|
||||
// div containing mobile close button and adev-nav_top
|
||||
> div {
|
||||
display: flex;
|
||||
@@ -150,6 +129,13 @@
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.adev-beta-version {
|
||||
font-family: 'Material Symbols Outlined';
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
// version dropdown button
|
||||
.adev-version-button {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
|
||||
@@ -102,8 +102,6 @@ export class Navigation implements OnInit {
|
||||
openedMenu: MenuType | null = null;
|
||||
|
||||
currentDocsVersion = this.versionManager.currentDocsVersion;
|
||||
currentDocsVersionMode = this.versionManager.currentDocsVersion()?.version;
|
||||
|
||||
// Set the values of the search label and title only on the client, because the label is user-agent specific.
|
||||
searchLabel = this.isBrowser
|
||||
? isApple
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
*/
|
||||
|
||||
import {Injector} from '@angular/core';
|
||||
import {ENVIRONMENT, WINDOW, LOCAL_STORAGE} from '@angular/docs';
|
||||
import {ENVIRONMENT, WINDOW} from '@angular/docs';
|
||||
import {AnalyticsService} from './analytics.service';
|
||||
import {MockLocalStorage} from '@angular/docs/testing';
|
||||
|
||||
describe('AnalyticsService', () => {
|
||||
let service: AnalyticsService;
|
||||
@@ -19,7 +18,6 @@ describe('AnalyticsService', () => {
|
||||
let windowOnErrorHandler: (event: ErrorEvent) => void;
|
||||
|
||||
let mockWindow: any;
|
||||
let mockLocalStorage = new MockLocalStorage();
|
||||
|
||||
beforeEach(() => {
|
||||
gtagSpy = jasmine.createSpy('gtag');
|
||||
@@ -41,7 +39,6 @@ describe('AnalyticsService', () => {
|
||||
{provide: ENVIRONMENT, useValue: {}},
|
||||
{provide: AnalyticsService, deps: [WINDOW]},
|
||||
{provide: WINDOW, useFactory: () => mockWindow, deps: []},
|
||||
{provide: LOCAL_STORAGE, useValue: mockLocalStorage},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import {inject, Injectable} from '@angular/core';
|
||||
|
||||
import {WINDOW, ENVIRONMENT, LOCAL_STORAGE, STORAGE_KEY, setCookieConsent} from '@angular/docs';
|
||||
import {WINDOW, ENVIRONMENT} from '@angular/docs';
|
||||
|
||||
import {formatErrorEventForAnalytics} from './analytics-format-error';
|
||||
|
||||
@@ -28,7 +28,6 @@ interface WindowWithAnalytics extends Window {
|
||||
export class AnalyticsService {
|
||||
private environment = inject(ENVIRONMENT);
|
||||
private window: WindowWithAnalytics = inject(WINDOW);
|
||||
private readonly localStorage = inject(LOCAL_STORAGE);
|
||||
|
||||
constructor() {
|
||||
this._installGlobalSiteTag();
|
||||
@@ -65,21 +64,6 @@ export class AnalyticsService {
|
||||
window.gtag = function () {
|
||||
window.dataLayer?.push(arguments);
|
||||
};
|
||||
|
||||
// Cookie banner consent initial state
|
||||
// This code is modified in the @angular/docs package in the cookie-popup component.
|
||||
// Docs: https://developers.google.com/tag-platform/security/guides/consent
|
||||
if (this.localStorage) {
|
||||
if (this.localStorage.getItem(STORAGE_KEY) === 'true') {
|
||||
setCookieConsent('granted');
|
||||
} else {
|
||||
setCookieConsent('denied');
|
||||
}
|
||||
} else {
|
||||
// In case localStorage is not available, we default to denying cookies.
|
||||
setCookieConsent('denied');
|
||||
}
|
||||
|
||||
window.gtag('js', new Date());
|
||||
|
||||
// Configure properties before loading the script. This is necessary to avoid
|
||||
|
||||
@@ -10,7 +10,6 @@ import {HttpClient} from '@angular/common/http';
|
||||
import {Injectable, inject} from '@angular/core';
|
||||
import {DocContent, DocsContentLoader} from '@angular/docs';
|
||||
import {Router} from '@angular/router';
|
||||
import {firstValueFrom} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
@@ -28,13 +27,12 @@ export class ContentLoader implements DocsContentLoader {
|
||||
try {
|
||||
this.cache.set(
|
||||
path,
|
||||
firstValueFrom(
|
||||
this.httpClient
|
||||
.get(`assets/content/${path}`, {
|
||||
responseType: 'text',
|
||||
})
|
||||
.pipe(map((contents) => ({contents, id: path}))),
|
||||
),
|
||||
this.httpClient
|
||||
.get(`assets/content/${path}`, {
|
||||
responseType: 'text',
|
||||
})
|
||||
.pipe(map((contents) => ({contents, id: path})))
|
||||
.toPromise(),
|
||||
);
|
||||
} catch {
|
||||
this.router.navigateByUrl('/404');
|
||||
|
||||
@@ -82,7 +82,7 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
private watchPreferredColorScheme() {
|
||||
window.matchMedia(PREFERS_COLOR_SCHEME_DARK).addEventListener('change', (event) => {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
|
||||
const preferredScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferredScheme);
|
||||
});
|
||||
@@ -90,5 +90,5 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
function preferredScheme(): 'dark' | 'light' {
|
||||
return window.matchMedia(PREFERS_COLOR_SCHEME_DARK).matches ? 'dark' : 'light';
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,74 @@
|
||||
*/
|
||||
|
||||
import {Injectable, VERSION, computed, signal} from '@angular/core';
|
||||
import {VERSIONS_CONFIG} from '../constants/versions';
|
||||
|
||||
// TODO(josephperrott): extract this out of the file into a managed location.
|
||||
const VERSIONS_CONFIG = {
|
||||
currentVersion: 'stable',
|
||||
historicalVersionsLinkPattern: 'https://v{{version}}.angular.dev',
|
||||
mainVersions: [
|
||||
{
|
||||
version: 'stable',
|
||||
url: 'https://angular.dev',
|
||||
},
|
||||
{
|
||||
version: 'v16',
|
||||
url: 'https://v16.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v15',
|
||||
url: 'https://v15.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v14',
|
||||
url: 'https://v14.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v13',
|
||||
url: 'https://v13.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v12',
|
||||
url: 'https://v12.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v11',
|
||||
url: 'https://v11.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v10',
|
||||
url: 'https://v10.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v9',
|
||||
url: 'https://v9.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v8',
|
||||
url: 'https://v8.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v7',
|
||||
url: 'https://v7.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v6',
|
||||
url: 'https://v6.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v5',
|
||||
url: 'https://v5.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v4',
|
||||
url: 'https://v4.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v2',
|
||||
url: 'https://v2.angular.io/docs',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export interface Version {
|
||||
displayName: string;
|
||||
@@ -15,7 +82,7 @@ export interface Version {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export type VersionMode = 'stable' | 'deprecated' | 'rc' | 'next' | number;
|
||||
export type VersionMode = 'stable' | 'rc' | 'next' | number;
|
||||
|
||||
export const INITIAL_DOCS_VERSION = 17;
|
||||
export const VERSION_PATTERN_PLACEHOLDER = '{{version}}';
|
||||
@@ -61,9 +128,7 @@ export class VersionManager {
|
||||
|
||||
private getVersion(versionMode: VersionMode): string {
|
||||
if (versionMode === 'stable') {
|
||||
return 'v17';
|
||||
// Temporarily commenting out till this works correctly
|
||||
// return `v${VERSION.major}`;
|
||||
return `v${VERSION.major}`;
|
||||
}
|
||||
if (Number.isInteger(versionMode)) {
|
||||
return `v${versionMode}`;
|
||||
|
||||
@@ -115,7 +115,7 @@ The following steps are executed on project change:
|
||||
5. The previous project dependencies are compared with the new project dependencies.
|
||||
1. If there are differences, a `npm install` is triggered, hiding the preview and going to the install loading step.
|
||||
2. If there are no differences, the project is ready.
|
||||
6. Some states are reset, for example the "reveal answer" state if the previous project was in the "reveal answer" state.
|
||||
6. Some states are resetted, for example the "reveal answer" state if the previous project was in the "reveal answer" state.
|
||||
|
||||
## Components and services
|
||||
|
||||
@@ -200,7 +200,7 @@ Responsible for handling the download button in the embedded editor, fetching th
|
||||
|
||||
#### [`AlertManager`](./alert-manager.service.ts)
|
||||
|
||||
Manage the alerts displayed in the embedded editor, being the out of memory alert when multiple tabs are opened, and unsupported environments alerts.
|
||||
Manage the alerts displayed in the embedded editor, being the out of memory alert when multiple tabs are opened, and unsupported enviroments alerts.
|
||||
|
||||
#### [`TypingsLoader`](./typings-loader.service.ts)
|
||||
|
||||
|
||||
@@ -10,29 +10,7 @@
|
||||
@for (file of files(); track file) {
|
||||
<mat-tab #tab>
|
||||
<ng-template mat-tab-label>
|
||||
@if (tab.isActive && isRenamingFile()) {
|
||||
<form
|
||||
(submit)="renameFile($event, file.filename)"
|
||||
(docsClickOutside)="closeRenameFile()">
|
||||
<input
|
||||
name="rename-file"
|
||||
class="adev-rename-file-input"
|
||||
#renameFileInput
|
||||
(keydown)="$event.stopPropagation()"
|
||||
/>
|
||||
</form>
|
||||
} @else {
|
||||
{{ file.filename.replace('src/', '') }}
|
||||
}
|
||||
@if (tab.isActive && canRenameFile(file.filename)) {
|
||||
<button
|
||||
class="docs-rename-file"
|
||||
aria-label="rename file"
|
||||
(click)="onRenameButtonClick()"
|
||||
>
|
||||
<docs-icon>edit</docs-icon>
|
||||
</button>
|
||||
}
|
||||
@if (tab.isActive && canDeleteFile(file.filename)) {
|
||||
<button
|
||||
class="docs-delete-file"
|
||||
|
||||
@@ -79,8 +79,7 @@
|
||||
}
|
||||
|
||||
.adev-add-file,
|
||||
.docs-delete-file,
|
||||
.docs-rename-file {
|
||||
.docs-delete-file {
|
||||
docs-icon {
|
||||
color: var(--gray-400);
|
||||
transition: color 0.3s ease;
|
||||
@@ -93,8 +92,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-delete-file,
|
||||
.docs-rename-file {
|
||||
.docs-delete-file {
|
||||
padding-inline-start: 0.1rem;
|
||||
padding-inline-end: 0;
|
||||
margin-block-start: 0.2rem;
|
||||
@@ -103,8 +101,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-new-file-input,
|
||||
.adev-rename-file-input {
|
||||
.adev-new-file-input {
|
||||
color: var(--primary-contrast);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('CodeEditor', () => {
|
||||
const tabs = await matTabGroup.getTabs();
|
||||
const expectedLabels = files.map((file, index) => {
|
||||
const label = file.filename.replace('src/', '');
|
||||
if (index === 0) return `${label} editdelete`;
|
||||
if (index === 0) return `${label} delete`;
|
||||
return label;
|
||||
});
|
||||
|
||||
|
||||
@@ -28,13 +28,9 @@ import {EmbeddedTutorialManager} from '../embedded-tutorial-manager.service';
|
||||
import {CodeMirrorEditor} from './code-mirror-editor.service';
|
||||
import {DiagnosticWithLocation, DiagnosticsState} from './services/diagnostics-state.service';
|
||||
import {DownloadManager} from '../download-manager.service';
|
||||
import {ClickOutside, IconComponent} from '@angular/docs';
|
||||
import {IconComponent} from '@angular/docs';
|
||||
|
||||
export const REQUIRED_FILES = new Set([
|
||||
'src/main.ts',
|
||||
'src/index.html',
|
||||
'src/app/app.component.ts',
|
||||
]);
|
||||
export const REQUIRED_FILES = new Set(['src/main.ts', 'src/index.html']);
|
||||
|
||||
@Component({
|
||||
selector: 'docs-tutorial-code-editor',
|
||||
@@ -42,7 +38,7 @@ export const REQUIRED_FILES = new Set([
|
||||
templateUrl: './code-editor.component.html',
|
||||
styleUrls: ['./code-editor.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [NgIf, NgFor, MatTabsModule, IconComponent, ClickOutside],
|
||||
imports: [NgIf, NgFor, MatTabsModule, IconComponent],
|
||||
})
|
||||
export class CodeEditor implements AfterViewInit, OnDestroy {
|
||||
@ViewChild('codeEditorWrapper') private codeEditorWrapperRef!: ElementRef<HTMLDivElement>;
|
||||
@@ -58,16 +54,6 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private renameFileInputRef?: ElementRef<HTMLInputElement>;
|
||||
@ViewChild('renameFileInput') protected set setRenameFileInputRef(
|
||||
element: ElementRef<HTMLInputElement>,
|
||||
) {
|
||||
if (element) {
|
||||
element.nativeElement.focus();
|
||||
this.renameFileInputRef = element;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
private readonly codeMirrorEditor = inject(CodeMirrorEditor);
|
||||
@@ -96,7 +82,6 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
|
||||
readonly errors = signal<DiagnosticWithLocation[]>([]);
|
||||
readonly files = this.codeMirrorEditor.openFiles;
|
||||
readonly isCreatingFile = signal<boolean>(false);
|
||||
readonly isRenamingFile = signal<boolean>(false);
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.codeMirrorEditor.init(this.codeEditorWrapperRef.nativeElement);
|
||||
@@ -119,12 +104,6 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
|
||||
this.displayErrorsBox.set(false);
|
||||
}
|
||||
|
||||
closeRenameFile(): void {
|
||||
this.isRenamingFile.set(false);
|
||||
}
|
||||
|
||||
canRenameFile = (filename: string) => this.canDeleteFile(filename);
|
||||
|
||||
canDeleteFile(filename: string) {
|
||||
return !REQUIRED_FILES.has(filename);
|
||||
}
|
||||
@@ -139,37 +118,6 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
|
||||
this.matTabGroup.selectedIndex = this.files().length;
|
||||
}
|
||||
|
||||
onRenameButtonClick() {
|
||||
this.isRenamingFile.set(true);
|
||||
}
|
||||
|
||||
async renameFile(event: SubmitEvent, oldPath: string) {
|
||||
if (!this.renameFileInputRef) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const renameFileInputValue = this.renameFileInputRef.nativeElement.value;
|
||||
|
||||
if (renameFileInputValue) {
|
||||
if (renameFileInputValue.includes('..')) {
|
||||
alert('File name can not contain ".."');
|
||||
return;
|
||||
}
|
||||
|
||||
// src is hidden from users, here we manually add it to the new filename
|
||||
const newFile = 'src/' + renameFileInputValue;
|
||||
|
||||
if (this.files().find(({filename}) => filename.includes(newFile))) {
|
||||
alert('File name already exists');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.codeMirrorEditor.renameFile(oldPath, newFile);
|
||||
}
|
||||
|
||||
this.isRenamingFile.set(false);
|
||||
}
|
||||
|
||||
async createFile(event: SubmitEvent) {
|
||||
if (!this.createFileInputRef) return;
|
||||
|
||||
|
||||
@@ -340,34 +340,6 @@ export class CodeMirrorEditor {
|
||||
this.changeCurrentFile(filename);
|
||||
}
|
||||
|
||||
async renameFile(oldPath: string, newPath: string) {
|
||||
const content = await this.nodeRuntimeSandbox.readFile(oldPath).catch((error) => {
|
||||
// empty content if file does not exist
|
||||
if (error.message.includes('ENOENT')) return '';
|
||||
else throw error;
|
||||
});
|
||||
|
||||
await this.nodeRuntimeSandbox.renameFile(oldPath, newPath).catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
this.embeddedTutorialManager.tutorialFiles.update((files) => {
|
||||
delete files[oldPath];
|
||||
files[newPath] = content;
|
||||
return files;
|
||||
});
|
||||
|
||||
this.embeddedTutorialManager.openFiles.update((files) => [
|
||||
...files.filter((file) => file !== oldPath),
|
||||
newPath,
|
||||
]);
|
||||
|
||||
this.setProjectFiles();
|
||||
this.updateVfsEnv();
|
||||
this.saveLibrariesTypes();
|
||||
this.changeCurrentFile(newPath);
|
||||
}
|
||||
|
||||
async deleteFile(deletedFile: string): Promise<void> {
|
||||
await this.nodeRuntimeSandbox.deleteFile(deletedFile);
|
||||
|
||||
|
||||
@@ -177,20 +177,6 @@ describe('NodeRuntimeSandbox', () => {
|
||||
expect(writeFileSpy).toHaveBeenCalledOnceWith(path, content);
|
||||
});
|
||||
|
||||
it('should call renameFile with proper parameters', async () => {
|
||||
setValuesToInitializeProject();
|
||||
|
||||
const fakeWebContainer = new FakeWebContainer();
|
||||
service['webContainerPromise'] = Promise.resolve(fakeWebContainer);
|
||||
const renameFileSpy = spyOn(fakeWebContainer.fs, 'rename');
|
||||
|
||||
const oldPath = 'oldPath';
|
||||
const newPath = 'newPath';
|
||||
|
||||
await service.renameFile(oldPath, newPath);
|
||||
expect(renameFileSpy).toHaveBeenCalledOnceWith(oldPath, newPath);
|
||||
});
|
||||
|
||||
it('should initialize the Angular CLI based on the tutorial config', async () => {
|
||||
setValuesToInitializeAngularCLI();
|
||||
|
||||
|
||||
@@ -270,16 +270,6 @@ export class NodeRuntimeSandbox {
|
||||
}
|
||||
}
|
||||
|
||||
async renameFile(oldPath: string, newPath: string): Promise<void> {
|
||||
const webContainer = await this.webContainerPromise!;
|
||||
|
||||
try {
|
||||
await webContainer.fs.rename(oldPath, newPath);
|
||||
} catch (err: any) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async readFile(filePath: string): Promise<string> {
|
||||
const webContainer = await this.webContainerPromise!;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import {inject} from '@angular/core';
|
||||
import {Subject} from 'rxjs';
|
||||
import {Terminal} from '@xterm/xterm';
|
||||
import {Terminal} from 'xterm';
|
||||
|
||||
import {WINDOW} from '@angular/docs';
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Terminal} from '@xterm/xterm';
|
||||
import {Terminal} from 'xterm';
|
||||
import {FitAddon} from 'xterm-addon-fit';
|
||||
import {InteractiveTerminal} from './interactive-terminal';
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -36,7 +36,6 @@
|
||||
box-sizing: border-box;
|
||||
transition: background 0.3s ease, border 0.3s ease;
|
||||
|
||||
h1,
|
||||
p {
|
||||
display: inline;
|
||||
font-size: 0.875rem;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<header class="adev-api-items-section-header">
|
||||
<h3 [attr.id]="group.id">
|
||||
@if (group.isFeatured) {
|
||||
<docs-icon aria-hidden>star</docs-icon>
|
||||
}
|
||||
<a routerLink="/api" [fragment]="group.id" class="adev-api-anchor" tabindex="-1">{{ group.title }}</a>
|
||||
</h3>
|
||||
@if (group.isFeatured) {
|
||||
<docs-icon>star</docs-icon>
|
||||
}
|
||||
<h3>{{ group.title }}</h3>
|
||||
</header>
|
||||
|
||||
<ul class="adev-api-items-section-grid">
|
||||
|
||||
+2
-14
@@ -1,7 +1,7 @@
|
||||
@use '@angular/docs/styles/anchor' as anchor;
|
||||
|
||||
.adev-api-items-section-header {
|
||||
display: flex;
|
||||
gap: 0.75em;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
fill: var(--primary-contrast);
|
||||
@@ -9,11 +9,6 @@
|
||||
|
||||
h3 {
|
||||
flex: 1;
|
||||
|
||||
display: flex;
|
||||
gap: 0.75em;
|
||||
align-items: flex-start;
|
||||
|
||||
margin-top: 1.43rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
@@ -105,10 +100,3 @@
|
||||
padding: 0.001rem 0.2rem 0.005rem;
|
||||
margin-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
.adev-api-anchor {
|
||||
color: inherit;
|
||||
|
||||
@include anchor.docs-anchor();
|
||||
}
|
||||
@@ -22,7 +22,6 @@ describe('ApiItemsSection', () => {
|
||||
|
||||
const fakeFeaturedGroup: ApiItemsGroup = {
|
||||
title: 'Featured',
|
||||
id: 'featured',
|
||||
isFeatured: true,
|
||||
items: [
|
||||
{
|
||||
@@ -49,7 +48,6 @@ describe('ApiItemsSection', () => {
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
title: 'Example group',
|
||||
id: 'example',
|
||||
isFeatured: false,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CONST, url: 'api/fakeTitle', isFeatured: false},
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
|
||||
import {NgFor, NgIf} from '@angular/common';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import ApiItemLabel from '../api-item-label/api-item-label.component';
|
||||
@@ -15,7 +16,7 @@ import {IconComponent} from '@angular/docs';
|
||||
@Component({
|
||||
selector: 'adev-api-items-section',
|
||||
standalone: true,
|
||||
imports: [ApiItemLabel, RouterLink, IconComponent],
|
||||
imports: [NgIf, NgFor, ApiItemLabel, RouterLink, IconComponent],
|
||||
templateUrl: './api-items-section.component.html',
|
||||
styleUrls: ['./api-items-section.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
+2
-25
@@ -108,6 +108,7 @@
|
||||
& > .docs-code {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-height: 93vh;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
|
||||
@@ -118,7 +119,6 @@
|
||||
|
||||
button {
|
||||
transition: background-color 0.3s ease;
|
||||
font-family: monospace;
|
||||
|
||||
&.hljs-ln-line {
|
||||
font-weight: 400;
|
||||
@@ -154,10 +154,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-cli-toc {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.adev-reference-tab {
|
||||
min-width: 50ch;
|
||||
margin-block-start: 2.5rem;
|
||||
@@ -271,9 +267,7 @@
|
||||
background-color: var(--octonary-contrast);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
border 0.3s ease;
|
||||
transition: background-color 0.3s ease, border 0.3s ease;
|
||||
|
||||
// h3 + code || # of overloads
|
||||
.docs-reference-header {
|
||||
@@ -358,10 +352,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-deprecation-message {
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
}
|
||||
|
||||
.docs-param-group {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
@@ -414,17 +404,4 @@
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-ref-content {
|
||||
padding: 1rem 0;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-block-start: 1px solid var(--senary-contrast);
|
||||
}
|
||||
|
||||
.docs-param-keyword {
|
||||
display: block;
|
||||
margin: 0 0 0.5rem 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-25
@@ -16,12 +16,12 @@ import {
|
||||
inject,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import {DOCUMENT, NgFor, NgIf, ViewportScroller} from '@angular/common';
|
||||
import {DOCUMENT, NgFor, NgIf} from '@angular/common';
|
||||
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
|
||||
import {takeUntilDestroyed, toSignal} from '@angular/core/rxjs-interop';
|
||||
import {distinctUntilChanged, filter, map, take} from 'rxjs/operators';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {distinctUntilChanged, map} from 'rxjs/operators';
|
||||
import {DocContent, DocViewer} from '@angular/docs';
|
||||
import {ActivatedRoute, Router, RouterLink, Scroll} from '@angular/router';
|
||||
import {ActivatedRoute, Router, RouterLink} from '@angular/router';
|
||||
import {ApiItemType} from './../interfaces/api-item-type';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {
|
||||
@@ -51,15 +51,6 @@ export default class ApiReferenceDetailsPage implements OnInit, AfterViewInit {
|
||||
private readonly document = inject(DOCUMENT);
|
||||
private readonly router = inject(Router);
|
||||
private readonly scrollHandler = inject(ReferenceScrollHandler);
|
||||
private readonly scroller = inject(ViewportScroller);
|
||||
private scrollEvent = toSignal(
|
||||
this.router.events.pipe(
|
||||
filter((e): e is Scroll => e instanceof Scroll),
|
||||
take(1),
|
||||
),
|
||||
{initialValue: null},
|
||||
);
|
||||
private cardsDisplayedOnInit = false;
|
||||
|
||||
ApiItemType = ApiItemType;
|
||||
|
||||
@@ -76,22 +67,10 @@ export default class ApiReferenceDetailsPage implements OnInit, AfterViewInit {
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.setActiveTab();
|
||||
if (this.canDisplayCards()) {
|
||||
this.cardsDisplayedOnInit = true;
|
||||
}
|
||||
this.listenToTabChange();
|
||||
}
|
||||
|
||||
membersCardsLoaded(): void {
|
||||
const event = this.scrollEvent();
|
||||
if (this.cardsDisplayedOnInit && event) {
|
||||
// Cards loaded after scroll event happened. We have to handle the scroll event manually
|
||||
if (event.position) {
|
||||
this.scroller.scrollToPosition(event.position);
|
||||
} else if (event.anchor) {
|
||||
this.scroller.scrollToAnchor(event.anchor);
|
||||
}
|
||||
}
|
||||
this.scrollHandler.setupListeners(API_TAB_CLASS_NAME);
|
||||
}
|
||||
|
||||
|
||||
+13
-15
@@ -3,11 +3,6 @@
|
||||
<h6>Getting Started</h6>
|
||||
<h1 tabindex="-1">API Reference</h1>
|
||||
</header>
|
||||
|
||||
@if (featuredGroup().items.length) {
|
||||
<adev-api-items-section [group]="featuredGroup()" class="adev-featured-list" />
|
||||
}
|
||||
|
||||
<form class="adev-reference-list-form">
|
||||
<docs-text-field
|
||||
name="query"
|
||||
@@ -27,20 +22,23 @@
|
||||
</div>
|
||||
<ul class="adev-reference-list-legend">
|
||||
@for (itemType of itemTypes; track itemType) {
|
||||
<li
|
||||
class="adev-reference-list-legend-item"
|
||||
[class.adev-reference-list-legend-item-active]="type() === itemType"
|
||||
(click)="filterByItemType(itemType)"
|
||||
>
|
||||
<docs-api-item-label [type]="itemType" mode="short" class="docs-api-item-label" />
|
||||
<span class="docs-api-item-label-full">{{ itemType | adevApiLabel : 'full' }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="adev-reference-list-legend-item"
|
||||
[class.adev-reference-list-legend-item-active]="type() === itemType"
|
||||
(click)="filterByItemType(itemType)"
|
||||
>
|
||||
<docs-api-item-label [type]="itemType" mode="short" class="docs-api-item-label" />
|
||||
<span>{{ itemType | adevApiLabel : 'full' }}</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</form>
|
||||
|
||||
@for (group of filteredGroups(); track group.id) {
|
||||
<adev-api-items-section [group]="group" />
|
||||
@if (featuredGroup().items.length) {
|
||||
<adev-api-items-section [group]="featuredGroup()" class="adev-featured-list" />
|
||||
} @for (group of filteredGroups(); track group) {
|
||||
<adev-api-items-section [group]="group" />
|
||||
}
|
||||
|
||||
<span id="deprecated-description" class="docs-deprecated-description">Deprecated</span>
|
||||
</div>
|
||||
|
||||
+7
-7
@@ -77,9 +77,8 @@
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap-reverse;
|
||||
gap: 1.5rem;
|
||||
padding-block-start: 1.5rem;
|
||||
padding-block-start: 0;
|
||||
padding-block-end: 2rem;
|
||||
border-block: 1px solid var(--senary-contrast);
|
||||
}
|
||||
|
||||
.adev-reference-list-form-part-two {
|
||||
@@ -90,12 +89,13 @@
|
||||
|
||||
.adev-featured-list {
|
||||
display: block;
|
||||
padding-block-end: 1rem;
|
||||
padding-block-end: 2rem;
|
||||
padding-block-start: 1.5rem;
|
||||
margin-block: 1rem;
|
||||
border-top: 0;
|
||||
margin-top: -1.5rem;
|
||||
border-block: 1px solid var(--senary-contrast);
|
||||
}
|
||||
|
||||
.docs-api-item-label-full {
|
||||
white-space: nowrap;
|
||||
|
||||
.docs-deprecated-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiReferenceManager} from './api-reference-manager.service';
|
||||
import ApiItemLabel from '../api-item-label/api-item-label.component';
|
||||
import {ApiLabel} from '../pipes/api-label.pipe';
|
||||
import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
|
||||
export const ALL_STATUSES_KEY = 'All';
|
||||
|
||||
@@ -46,12 +45,11 @@ export default class ApiReferenceList {
|
||||
type = signal(ALL_STATUSES_KEY);
|
||||
|
||||
featuredGroup = this.apiReferenceManager.featuredGroup;
|
||||
filteredGroups = computed((): ApiItemsGroup[] => {
|
||||
filteredGroups = computed(() => {
|
||||
return this.allGroups()
|
||||
.map((group) => ({
|
||||
title: group.title,
|
||||
isFeatured: group.isFeatured,
|
||||
id: group.id,
|
||||
items: group.items.filter((apiItem) => {
|
||||
return (
|
||||
(this.query()
|
||||
|
||||
+1
-4
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import {Injectable, signal} from '@angular/core';
|
||||
// This file is generated at build-time, error is expected here.
|
||||
import API_MANIFEST_JSON from '../../../../../src/assets/api/manifest.json';
|
||||
import {ANGULAR_PACKAGE_PREFIX, getApiUrl} from '../helpers/manifest.helper';
|
||||
import {ApiItem} from '../interfaces/api-item';
|
||||
@@ -15,7 +14,7 @@ import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import {ApiManifest} from '../interfaces/api-manifest';
|
||||
|
||||
export const FEATURED_API_ITEMS_KEY = 'apiFeaturedItems';
|
||||
export const FEATURED_GROUP_TITLE = 'Most Common';
|
||||
export const FEATURED_GROUP_TITLE = 'Featured';
|
||||
|
||||
export type FeaturedItemsByGroup = Record<string, ApiItem[]>;
|
||||
|
||||
@@ -41,7 +40,6 @@ export class ApiReferenceManager {
|
||||
// Represents group of the featured items.
|
||||
featuredGroup = signal<ApiItemsGroup>({
|
||||
title: FEATURED_GROUP_TITLE,
|
||||
id: 'featured',
|
||||
items: [],
|
||||
isFeatured: true,
|
||||
});
|
||||
@@ -60,7 +58,6 @@ export class ApiReferenceManager {
|
||||
|
||||
groups.push({
|
||||
title: packageNameWithoutPrefix,
|
||||
id: packageNameWithoutPrefix.replaceAll('/', '-'),
|
||||
items: packageApis
|
||||
.map((api) => {
|
||||
const url = getApiUrl(packageNameWithoutPrefix, api.name);
|
||||
|
||||
@@ -19,5 +19,4 @@ export enum ApiItemType {
|
||||
PIPE = 'pipe',
|
||||
NG_MODULE = 'ng_module',
|
||||
TYPE_ALIAS = 'type_alias',
|
||||
INITIALIZER_API_FUNCTION = 'initializer_api_function',
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import {ApiItem} from './api-item';
|
||||
|
||||
export interface ApiItemsGroup {
|
||||
title: string;
|
||||
id: string;
|
||||
items: ApiItem[];
|
||||
isFeatured?: boolean;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
|
||||
@Pipe({
|
||||
@@ -28,7 +27,6 @@ export class ApiLabel implements PipeTransform {
|
||||
[ApiItemType.PIPE]: 'P',
|
||||
[ApiItemType.NG_MODULE]: 'M',
|
||||
[ApiItemType.TYPE_ALIAS]: 'T',
|
||||
[ApiItemType.INITIALIZER_API_FUNCTION]: 'IA',
|
||||
};
|
||||
|
||||
private readonly fullLabelsMap: Record<ApiItemType, string> = {
|
||||
@@ -44,7 +42,6 @@ export class ApiLabel implements PipeTransform {
|
||||
[ApiItemType.PIPE]: 'Pipe',
|
||||
[ApiItemType.NG_MODULE]: 'Module',
|
||||
[ApiItemType.TYPE_ALIAS]: 'Type Alias',
|
||||
[ApiItemType.INITIALIZER_API_FUNCTION]: 'Initializer API',
|
||||
};
|
||||
|
||||
transform(value: ApiItemType, labelType: 'short' | 'full'): string {
|
||||
|
||||
@@ -160,6 +160,9 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(activeLines)) {
|
||||
line.classList.remove(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.getAllMemberCards().forEach((card) => {
|
||||
card.blur();
|
||||
});
|
||||
} else {
|
||||
const lines = this.document.querySelectorAll<HTMLButtonElement>(
|
||||
`button[${MEMBER_ID_ATTRIBUTE}="${currentActiveMemberId}"]`,
|
||||
@@ -167,7 +170,7 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(lines)) {
|
||||
line.classList.add(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.document.getElementById(`${currentActiveMemberId}`)?.focus({preventScroll: true});
|
||||
this.document.getElementById(`${currentActiveMemberId}`)?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,9 +179,7 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
return;
|
||||
}
|
||||
|
||||
if (card !== <HTMLElement>document.activeElement) {
|
||||
(<HTMLElement>document.activeElement).blur();
|
||||
}
|
||||
card.focus();
|
||||
|
||||
this.window.scrollTo({
|
||||
top: card!.offsetTop - this.membersMarginTopInPx(),
|
||||
@@ -210,9 +211,8 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
|
||||
this.resizeObserver = new ResizeObserver((_) => {
|
||||
this.ngZone.run(() => {
|
||||
const offsetTop = tabBody.getBoundingClientRect().top;
|
||||
if (offsetTop) {
|
||||
this.membersMarginTopInPx.set(offsetTop);
|
||||
if (tabBody.offsetTop) {
|
||||
this.membersMarginTopInPx.set(tabBody.offsetTop);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ class FakeDocViewer {
|
||||
@Input('documentFilePath') documentFilePath: string | undefined;
|
||||
}
|
||||
|
||||
// TODO: export this class, it's a helpful mock we could you on other tests.
|
||||
// TODO: export this class, it's a helpfull mock we could you on other tests.
|
||||
class FakeNodeRuntimeSandbox {
|
||||
loadingStep = signal(0);
|
||||
previewUrl$ = of();
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import {NavigationItem} from '@angular/docs';
|
||||
|
||||
// These 2 imports are expected to be red because they are generated a build time
|
||||
import FIRST_APP_TUTORIAL_NAV_DATA from '../../src/assets/tutorials/first-app/routes.json';
|
||||
import LEARN_ANGULAR_TUTORIAL_NAV_DATA from '../../src/assets/tutorials/learn-angular/routes.json';
|
||||
|
||||
@@ -118,11 +117,6 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'guide/components/outputs',
|
||||
contentPath: 'guide/components/outputs',
|
||||
},
|
||||
{
|
||||
label: 'output() function',
|
||||
path: 'guide/components/output-fn',
|
||||
contentPath: 'guide/components/output-function',
|
||||
},
|
||||
{
|
||||
label: 'Content projection with ng-content',
|
||||
path: 'guide/components/content-projection',
|
||||
@@ -932,28 +926,7 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
},
|
||||
{
|
||||
label: 'ng analytics',
|
||||
children: [
|
||||
{
|
||||
label: 'Overview',
|
||||
path: 'cli/analytics',
|
||||
},
|
||||
{
|
||||
label: 'disable',
|
||||
path: 'cli/analytics/disable',
|
||||
},
|
||||
{
|
||||
label: 'enable',
|
||||
path: 'cli/analytics/enable',
|
||||
},
|
||||
{
|
||||
label: 'info',
|
||||
path: 'cli/analytics/info',
|
||||
},
|
||||
{
|
||||
label: 'prompt',
|
||||
path: 'cli/analytics/prompt',
|
||||
},
|
||||
],
|
||||
path: 'cli/analytics',
|
||||
},
|
||||
{
|
||||
label: 'ng build',
|
||||
@@ -961,41 +934,11 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
},
|
||||
{
|
||||
label: 'ng cache',
|
||||
children: [
|
||||
{
|
||||
label: 'Overview',
|
||||
path: 'cli/cache',
|
||||
},
|
||||
{
|
||||
label: 'clear',
|
||||
path: 'cli/cache/clean',
|
||||
},
|
||||
{
|
||||
label: 'disable',
|
||||
path: 'cli/cache/disable',
|
||||
},
|
||||
{
|
||||
label: 'enable',
|
||||
path: 'cli/cache/enable',
|
||||
},
|
||||
{
|
||||
label: 'info',
|
||||
path: 'cli/cache/info',
|
||||
},
|
||||
],
|
||||
path: 'cli/cache',
|
||||
},
|
||||
{
|
||||
label: 'ng completion',
|
||||
children: [
|
||||
{
|
||||
label: 'Overview',
|
||||
path: 'cli/completion',
|
||||
},
|
||||
{
|
||||
label: 'script',
|
||||
path: 'cli/completion/script',
|
||||
},
|
||||
],
|
||||
path: 'cli/completion',
|
||||
},
|
||||
{
|
||||
label: 'ng config',
|
||||
@@ -1005,6 +948,10 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
label: 'ng deploy',
|
||||
path: 'cli/deploy',
|
||||
},
|
||||
{
|
||||
label: 'ng doc',
|
||||
path: 'cli/doc',
|
||||
},
|
||||
{
|
||||
label: 'ng e2e',
|
||||
path: 'cli/e2e',
|
||||
@@ -1015,80 +962,7 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
},
|
||||
{
|
||||
label: 'ng generate',
|
||||
children: [
|
||||
{
|
||||
label: 'Overview',
|
||||
path: 'cli/generate',
|
||||
},
|
||||
{
|
||||
label: 'app-shell',
|
||||
path: 'cli/generate/app-shell',
|
||||
},
|
||||
{
|
||||
label: 'application',
|
||||
path: 'cli/generate/application',
|
||||
},
|
||||
{
|
||||
label: 'class',
|
||||
path: 'cli/generate/class',
|
||||
},
|
||||
{
|
||||
label: 'component',
|
||||
path: 'cli/generate/component',
|
||||
},
|
||||
{
|
||||
label: 'config',
|
||||
path: 'cli/generate/config',
|
||||
},
|
||||
{
|
||||
label: 'enum',
|
||||
path: 'cli/generate/enum',
|
||||
},
|
||||
{
|
||||
label: 'environments',
|
||||
path: 'cli/generate/environments',
|
||||
},
|
||||
{
|
||||
label: 'guard',
|
||||
path: 'cli/generate/guard',
|
||||
},
|
||||
{
|
||||
label: 'interceptor',
|
||||
path: 'cli/generate/interceptor',
|
||||
},
|
||||
{
|
||||
label: 'interface',
|
||||
path: 'cli/generate/interface',
|
||||
},
|
||||
{
|
||||
label: 'library',
|
||||
path: 'cli/generate/library',
|
||||
},
|
||||
{
|
||||
label: 'module',
|
||||
path: 'cli/generate/module',
|
||||
},
|
||||
{
|
||||
label: 'pipe',
|
||||
path: 'cli/generate/pipe',
|
||||
},
|
||||
{
|
||||
label: 'resolver',
|
||||
path: 'cli/generate/resolver',
|
||||
},
|
||||
{
|
||||
label: 'service-worker',
|
||||
path: 'cli/generate/service-worker',
|
||||
},
|
||||
{
|
||||
label: 'service',
|
||||
path: 'cli/generate/service',
|
||||
},
|
||||
{
|
||||
label: 'web-worker',
|
||||
path: 'cli/generate/web-worker',
|
||||
},
|
||||
],
|
||||
path: 'cli/generate',
|
||||
},
|
||||
{
|
||||
label: 'ng lint',
|
||||
@@ -1248,16 +1122,6 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'errors/NG0912',
|
||||
contentPath: 'reference/errors/NG0912',
|
||||
},
|
||||
{
|
||||
label: 'NG0955: Track expression resulted in duplicated keys for a given collection',
|
||||
path: 'errors/NG0955',
|
||||
contentPath: 'reference/errors/NG0955',
|
||||
},
|
||||
{
|
||||
label: 'NG0956: Tracking expression caused re-creation of the DOM structure',
|
||||
path: 'errors/NG0956',
|
||||
contentPath: 'reference/errors/NG0956',
|
||||
},
|
||||
{
|
||||
label: 'NG1001: Argument Not Literal',
|
||||
path: 'errors/NG1001',
|
||||
@@ -1279,9 +1143,9 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
contentPath: 'reference/errors/NG3003',
|
||||
},
|
||||
{
|
||||
label: 'NG05000: Hydration with unsupported Zone.js instance.',
|
||||
path: 'errors/NG05000',
|
||||
contentPath: 'reference/errors/NG05000',
|
||||
label: 'NG5000: Hydration with unsupported Zone.js instance.',
|
||||
path: 'errors/NG5000',
|
||||
contentPath: 'reference/errors/NG5000',
|
||||
},
|
||||
{
|
||||
label: 'NG6100: NgModule.id Set to module.id anti-pattern',
|
||||
|
||||
@@ -8,7 +8,6 @@ copy_to_directory(
|
||||
"//adev/src/content",
|
||||
"//adev/src/content/best-practices",
|
||||
"//adev/src/content/best-practices/runtime-performance",
|
||||
"//adev/src/content/cli/help:cli_docs",
|
||||
"//adev/src/content/ecosystem",
|
||||
"//adev/src/content/ecosystem/service-workers",
|
||||
"//adev/src/content/guide",
|
||||
@@ -39,6 +38,7 @@ copy_to_directory(
|
||||
"//adev/src/content/tutorials",
|
||||
"//adev/src/content/tutorials/first-app:first-app-guides",
|
||||
"//adev/src/content/tutorials/learn-angular:learn-angular-guides",
|
||||
"//aio/content/cli/help:cli_docs",
|
||||
"//packages/animations:animations_docs",
|
||||
"//packages/animations/browser:animations_browser_docs",
|
||||
"//packages/animations/browser/testing:animations_browser_testing_docs",
|
||||
@@ -74,7 +74,7 @@ copy_to_directory(
|
||||
"//tools/manual_api_docs/elements:elements_docs",
|
||||
],
|
||||
replace_prefixes = {
|
||||
"adev/src/content/cli/help/cli_docs_html": "cli/",
|
||||
"aio/content/cli/**/": "cli/",
|
||||
"adev/src/content": "",
|
||||
"packages/**/": "api/",
|
||||
"tools/**/": "api/",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 3.4 MiB After Width: | Height: | Size: 3.4 MiB |
@@ -17,16 +17,16 @@ Use attribute binding template syntax to control the values of accessibility-rel
|
||||
When binding to ARIA attributes in Angular, you must use the `attr.` prefix. The ARIA specification depends specifically on HTML attributes rather than properties of DOM elements.
|
||||
|
||||
<docs-code language="html">
|
||||
<!-- Use attr. when binding to an ARIA attribute -->
|
||||
<button [attr.aria-label]="myActionLabel">…</button>
|
||||
<!-- Use attr. when binding to an ARIA attribute -->
|
||||
<button [attr.aria-label]="myActionLabel">…</button>
|
||||
</docs-code>
|
||||
|
||||
Note: This syntax is only necessary for attribute *bindings*.
|
||||
Static ARIA attributes require no extra syntax.
|
||||
|
||||
<docs-code language="html">
|
||||
<!-- Static ARIA attributes require no extra syntax -->
|
||||
<button aria-label="Save document">…</button>
|
||||
<!-- Static ARIA attributes require no extra syntax -->
|
||||
<button aria-label="Save document">…</button>
|
||||
</docs-code>
|
||||
|
||||
HELPFUL: By convention, HTML attributes use lowercase names \(`tabindex`\), while properties use camelCase names \(`tabIndex`\).
|
||||
@@ -76,15 +76,15 @@ The following example shows how to make a progress bar accessible by using host
|
||||
The ARIA attribute `aria-valuenow` is bound to the user's input.
|
||||
* In the template, the `aria-label` attribute ensures that the control is accessible to screen readers.
|
||||
|
||||
<docs-code-multifile>
|
||||
<docs-code-multifile
|
||||
path="adev/src/content/examples/accessibility/src/app/app.component.ts"
|
||||
preview>
|
||||
<docs-code
|
||||
path="adev/src/content/examples/accessibility/src/app/progress-bar.component.ts"
|
||||
language="ts"
|
||||
linenums
|
||||
highlight="[12, 20]"/>
|
||||
<docs-code
|
||||
path="adev/src/content/examples/accessibility/src/app/app.component.html"
|
||||
language="html"
|
||||
linenums
|
||||
highlight="[8, 9]"/>
|
||||
</docs-code-multifile>
|
||||
@@ -103,8 +103,8 @@ The following example shows how to find and focus the main content header in the
|
||||
|
||||
<docs-code language="typescript">
|
||||
|
||||
router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
|
||||
const mainHeader = document.querySelector('#main-content-header')
|
||||
router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
|
||||
const mainHeader = document.querySelector('#main-content-header')
|
||||
if (mainHeader) {
|
||||
mainHeader.focus();
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ If Angular handles an event within a component with OnPush strategy, the framewo
|
||||
|
||||
As an example, if Angular handles an event within `MainComponent`, the framework will run change detection in the entire component tree. Angular will ignore the subtree with root `LoginComponent` because it has `OnPush` and the event happened outside of its scope.
|
||||
|
||||
<img alt="Change detection propagation from OnPush component" src="assets/images/best-practices/runtime-performance/on-push-trigger.svg">
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
app[AppComponent] --- header[HeaderComponent];
|
||||
|
||||
@@ -19,7 +19,7 @@ For example, in the preceding screenshot, the second recorded change detection c
|
||||
Here are several techniques to remove slow computations:
|
||||
|
||||
* **Optimizing the underlying algorithm**. This is the recommended approach. If you can speed up the algorithm that is causing the problem, you can speed up the entire change detection mechanism.
|
||||
* **Caching using pure pipes**. You can move the heavy computation to a pure [pipe](guide/pipes). Angular reevaluates a pure pipe only if it detects that its inputs have changed, compared to the previous time Angular called it.
|
||||
* **Caching using pure pipes**. You can move the heavy computation to a pure [pipe](/guide/pipes). Angular reevaluates a pure pipe only if it detects that its inputs have changed, compared to the previous time Angular called it.
|
||||
* **Using memoization**. [Memoization](https://en.wikipedia.org/wiki/Memoization) is a similar technique to pure pipes, with the difference that pure pipes preserve only the last result from the computation where memoization could store multiple results.
|
||||
* **Avoid repaints/reflows in lifecycle hooks**. Certain [operations](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) cause the browser to either synchronously recalculate the layout of the page or re-render it. Since reflows and repaints are generally slow, you want to avoid performing them in every change detection cycle.
|
||||
|
||||
|
||||
@@ -151,14 +151,14 @@ Consistent conventions make it easy to quickly identify and reference assets of
|
||||
|
||||
| Symbol name | File name |
|
||||
|:--- |:--- |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) <br>export class AppComponent { } </docs-code> | app.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) <br>export class HeroesComponent { } </docs-code> | heroes.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) <br>export class HeroListComponent { } </docs-code> | hero-list.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) <br>export class HeroDetailComponent { } </docs-code> | hero-detail.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Directive({ … }) <br>export class ValidationDirective { } </docs-code> | validation.directive.ts |
|
||||
| <docs-code hideCopy language="typescript"> @NgModule({ … }) <br>export class AppModule </docs-code> | app.module.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ name: 'initCaps' }) <br>export class InitCapsPipe implements PipeTransform { } </docs-code> | init-caps.pipe.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() <br>export class UserProfileService { } </docs-code> | user-profile.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) 
export class AppComponent { } </docs-code> | app.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) 
export class HeroesComponent { } </docs-code> | heroes.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) 
export class HeroListComponent { } </docs-code> | hero-list.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Component({ … }) 
export class HeroDetailComponent { } </docs-code> | hero-detail.component.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Directive({ … }) 
export class ValidationDirective { } </docs-code> | validation.directive.ts |
|
||||
| <docs-code hideCopy language="typescript"> @NgModule({ … }) 
export class AppModule </docs-code> | app.module.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ name: 'initCaps' }) 
export class InitCapsPipe implements PipeTransform { } </docs-code> | init-caps.pipe.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() 
export class UserProfileService { } </docs-code> | user-profile.service.ts |
|
||||
|
||||
### Service names
|
||||
|
||||
@@ -186,9 +186,9 @@ Service names such as `Credit` are nouns and require a suffix and should be name
|
||||
|
||||
| Symbol name | File name |
|
||||
|:--- |:--- |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() <br>export class HeroDataService { } </docs-code> | hero-data.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() <br>export class CreditService { } </docs-code> | credit.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() <br>export class Logger { } </docs-code> | logger.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() 
export class HeroDataService { } </docs-code> | hero-data.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() 
export class CreditService { } </docs-code> | credit.service.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Injectable() 
export class Logger { } </docs-code> | logger.service.ts |
|
||||
|
||||
### Bootstrapping
|
||||
|
||||
@@ -293,8 +293,8 @@ Provides a consistent way to quickly identify and reference pipes.
|
||||
|
||||
| Symbol name | File name |
|
||||
|:--- |:--- |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ standalone: true, name: 'ellipsis' }) <br>export class EllipsisPipe implements PipeTransform { } </docs-code> | ellipsis.pipe.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ standalone: true, name: 'initCaps' }) <br>export class InitCapsPipe implements PipeTransform { } </docs-code> | init-caps.pipe.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ standalone: true, name: 'ellipsis' }) 
export class EllipsisPipe implements PipeTransform { } </docs-code> | ellipsis.pipe.ts |
|
||||
| <docs-code hideCopy language="typescript"> @Pipe({ standalone: true, name: 'initCaps' }) 
export class InitCapsPipe implements PipeTransform { } </docs-code> | init-caps.pipe.ts |
|
||||
|
||||
### Unit test file names
|
||||
|
||||
@@ -354,40 +354,40 @@ project root
|
||||
├── src
|
||||
│ ├── app
|
||||
│ │ ├── core
|
||||
│ │ │ └── exception.service.ts|spec.ts
|
||||
│ │ │ └── user-profile.service.ts|spec.ts
|
||||
│ │ │ └── exception.service.ts|spec.ts
|
||||
│ │ │ └── user-profile.service.ts|spec.ts
|
||||
│ │ ├── heroes
|
||||
│ │ │ ├── hero
|
||||
│ │ │ │ └── hero.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── hero.component.ts|html|css|spec.ts
|
||||
│ │ │ ├── hero-list
|
||||
│ │ │ │ └── hero-list.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── hero-list.component.ts|html|css|spec.ts
|
||||
│ │ │ ├── shared
|
||||
│ │ │ │ └── hero-button.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── hero-button.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── hero.model.ts
|
||||
│ │ │ │ └── hero.service.ts|spec.ts
|
||||
│ │ │ └── heroes.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── hero.service.ts|spec.ts
|
||||
│ │ │ └── heroes.component.ts|html|css|spec.ts
|
||||
│ │ │ └── heroes.routes.ts
|
||||
│ │ ├── shared
|
||||
│ │ │ └── init-caps.pipe.ts|spec.ts
|
||||
│ │ │ └── filter-text.component.ts|spec.ts
|
||||
│ │ │ └── filter-text.service.ts|spec.ts
|
||||
│ │ │ └── init-caps.pipe.ts|spec.ts
|
||||
│ │ │ └── filter-text.component.ts|spec.ts
|
||||
│ │ │ └── filter-text.service.ts|spec.ts
|
||||
│ │ ├── villains
|
||||
│ │ │ ├── villain
|
||||
│ │ │ │ └── …
|
||||
│ │ │ │ └── …
|
||||
│ │ │ ├── villain-list
|
||||
│ │ │ │ └── …
|
||||
│ │ │ │ └── …
|
||||
│ │ │ ├── shared
|
||||
│ │ │ │ └── …
|
||||
│ │ │ └── villains.component.ts|html|css|spec.ts
|
||||
│ │ │ │ └── …
|
||||
│ │ │ └── villains.component.ts|html|css|spec.ts
|
||||
│ │ │ └── villains.module.ts
|
||||
│ │ │ └── villains-routing.module.ts
|
||||
│ │ └── app.component.ts|html|css|spec.ts
|
||||
│ │ └── app.component.ts|html|css|spec.ts
|
||||
│ │ └── app.routes.ts
|
||||
│ └── main.ts
|
||||
│ └── index.html
|
||||
│ └── …
|
||||
└── node_modules/…
|
||||
└── …
|
||||
│ └── …
|
||||
└── node_modules/…
|
||||
└── …
|
||||
```
|
||||
|
||||
HELPFUL: While components in dedicated folders are widely preferred, another option for small applications is to keep components flat \(not in a dedicated folder\).
|
||||
@@ -506,15 +506,15 @@ project root
|
||||
├──├──app
|
||||
├──├──├── shared
|
||||
├──├──├──└── shared.module.ts
|
||||
├──├──├──└── init-caps.pipe.ts|spec.ts
|
||||
├──├──├──└── filter-text.component.ts|spec.ts
|
||||
├──├──├──└── filter-text.service.ts|spec.ts
|
||||
├──├──└── app.component.ts|html|css|spec.ts
|
||||
├──├──├──└── init-caps.pipe.ts|spec.ts
|
||||
├──├──├──└── filter-text.component.ts|spec.ts
|
||||
├──├──├──└── filter-text.service.ts|spec.ts
|
||||
├──├──└── app.component.ts|html|css|spec.ts
|
||||
├──├──└── app.module.ts
|
||||
├──├──└── app-routing.module.ts
|
||||
├──└── main.ts
|
||||
├──└── index.html
|
||||
└── …
|
||||
└── …
|
||||
```
|
||||
|
||||
<docs-code-multifile>
|
||||
@@ -761,7 +761,7 @@ An element may have more than one attribute directive applied.
|
||||
**Do** be consistent in your choice.
|
||||
|
||||
**Why**? <br />
|
||||
The property associated with `@HostBinding` or the method associated with `@HostListener` can be modified only in a single place —in the directive's class.
|
||||
The property associated with `@HostBinding` or the method associated with `@HostListener` can be modified only in a single place —in the directive's class.
|
||||
If you use the `host` metadata property, you must modify both the property/method declaration in the directive's class and the metadata in the decorator associated with the directive.
|
||||
|
||||
<docs-code header="app/shared/validator.directive.ts" path="adev/src/content/examples/styleguide/src/06-03/app/shared/validator.directive.ts"/>
|
||||
@@ -811,7 +811,7 @@ In this scenario it would be better to provide the service at the component leve
|
||||
|
||||
<docs-code header="src/app/treeshaking/service.ts" path="adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.ts"/>
|
||||
|
||||
### Use the @Injectable() class decorator
|
||||
### Use the @Injectable() class decorator
|
||||
|
||||
#### Style 07-04
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Keeping your Angular application up-to-date enables you to take advantage of lea
|
||||
|
||||
This document contains information and resources to help you keep your Angular applications and libraries up-to-date.
|
||||
|
||||
For information about our versioning policy and practices —including support and deprecation practices, as well as the release schedule— see [Angular versioning and releases](reference/releases "Angular versioning and releases").
|
||||
For information about our versioning policy and practices —including support and deprecation practices, as well as the release schedule— see [Angular versioning and releases](reference/releases "Angular versioning and releases").
|
||||
|
||||
HELPFUL: If you are currently using AngularJS, see [Upgrading from AngularJS](https://angular.io/guide/upgrade "Upgrading from Angular JS").
|
||||
*AngularJS* is the name for all v1.x versions of Angular.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "cli",
|
||||
srcs = glob(
|
||||
["**"],
|
||||
exclude = [
|
||||
"BUILD.bazel",
|
||||
],
|
||||
) + [
|
||||
"//adev/src/content/cli/help",
|
||||
"//adev/src/content/cli/help:build-info.json",
|
||||
],
|
||||
)
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"branchName": "refs/heads/main",
|
||||
"sha": "5bcfd647fd2a4224c03514c852fd0386bce2fbad"
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
{
|
||||
"name": "build",
|
||||
"command": "ng build [project]",
|
||||
"shortDescription": "Compiles an Angular application or library into an output directory named dist/ at the given output path.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/build/long-description.md",
|
||||
"longDescription": "The command can be used to build a project of type \"application\" or \"library\".\nWhen used to build a library, a different builder is invoked, and only the `ts-config`, `configuration`, `poll` and `watch` options are applied.\nAll other options apply only to building applications.\n\nThe application builder uses the [esbuild](https://esbuild.github.io/) build tool, with default configuration options specified in the workspace configuration file (`angular.json`) or with a named alternative configuration.\nA \"development\" configuration is created by default when you use the CLI to create the project, and you can use that configuration by specifying the `--configuration development`.\n\nThe configuration options generally correspond to the command options.\nYou can override individual configuration defaults by specifying the corresponding options on the command line.\nThe command can accept option names given in dash-case.\nNote that in the configuration file, you must specify names in camelCase.\n\nSome additional options can only be set through the configuration file,\neither by direct editing or with the `ng config` command.\nThese include `assets`, `styles`, and `scripts` objects that provide runtime-global resources to include in the project.\nResources in CSS, such as images and fonts, are automatically written and fingerprinted at the root of the output folder.\n\nFor further details, see [Workspace Configuration](reference/configs/workspace-config).\n",
|
||||
"aliases": [
|
||||
"b"
|
||||
],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "allowed-common-js-dependencies",
|
||||
"type": "array",
|
||||
"description": "A list of CommonJS or AMD packages that are allowed to be used without a build time warning. Use `'*'` to allow all."
|
||||
},
|
||||
{
|
||||
"name": "aot",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Build using Ahead of Time compilation."
|
||||
},
|
||||
{
|
||||
"name": "app-shell",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Generates an application shell during build time."
|
||||
},
|
||||
{
|
||||
"name": "base-href",
|
||||
"type": "string",
|
||||
"description": "Base url for the application being built."
|
||||
},
|
||||
{
|
||||
"name": "browser",
|
||||
"type": "string",
|
||||
"description": "The full path for the browser entry point to the application, relative to the current workspace."
|
||||
},
|
||||
{
|
||||
"name": "clear-screen",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Automatically clear the terminal screen during rebuilds."
|
||||
},
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "cross-origin",
|
||||
"type": "string",
|
||||
"default": "none",
|
||||
"enum": [
|
||||
"none",
|
||||
"anonymous",
|
||||
"use-credentials"
|
||||
],
|
||||
"description": "Define the crossorigin attribute setting of elements that provide CORS support."
|
||||
},
|
||||
{
|
||||
"name": "delete-output-path",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Delete the output path before building."
|
||||
},
|
||||
{
|
||||
"name": "deploy-url",
|
||||
"type": "string",
|
||||
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
|
||||
},
|
||||
{
|
||||
"name": "external-dependencies",
|
||||
"type": "array",
|
||||
"description": "Exclude the listed external dependencies from being bundled into the bundle. Instead, the created bundle relies on these dependencies to be available during runtime."
|
||||
},
|
||||
{
|
||||
"name": "extract-licenses",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Extract all licenses in a separate file."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "i18n-duplicate-translation",
|
||||
"type": "string",
|
||||
"default": "warning",
|
||||
"enum": [
|
||||
"warning",
|
||||
"error",
|
||||
"ignore"
|
||||
],
|
||||
"description": "How to handle duplicate translations for i18n."
|
||||
},
|
||||
{
|
||||
"name": "i18n-missing-translation",
|
||||
"type": "string",
|
||||
"default": "warning",
|
||||
"enum": [
|
||||
"warning",
|
||||
"error",
|
||||
"ignore"
|
||||
],
|
||||
"description": "How to handle missing translations for i18n."
|
||||
},
|
||||
{
|
||||
"name": "index",
|
||||
"type": "string",
|
||||
"description": "Configures the generation of the application's HTML index."
|
||||
},
|
||||
{
|
||||
"name": "inline-style-language",
|
||||
"type": "string",
|
||||
"default": "css",
|
||||
"enum": [
|
||||
"css",
|
||||
"less",
|
||||
"sass",
|
||||
"scss"
|
||||
],
|
||||
"description": "The stylesheet language to use for the application's inline component styles."
|
||||
},
|
||||
{
|
||||
"name": "localize",
|
||||
"type": "boolean",
|
||||
"description": "Translate the bundles in one or more locales."
|
||||
},
|
||||
{
|
||||
"name": "named-chunks",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Use file name for lazy loaded chunks."
|
||||
},
|
||||
{
|
||||
"name": "optimization",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration."
|
||||
},
|
||||
{
|
||||
"name": "output-hashing",
|
||||
"type": "string",
|
||||
"default": "none",
|
||||
"enum": [
|
||||
"none",
|
||||
"all",
|
||||
"media",
|
||||
"bundles"
|
||||
],
|
||||
"description": "Define the output filename cache-busting hashing mode."
|
||||
},
|
||||
{
|
||||
"name": "output-path",
|
||||
"type": "string",
|
||||
"description": "Specify the output path relative to workspace root."
|
||||
},
|
||||
{
|
||||
"name": "poll",
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
},
|
||||
{
|
||||
"name": "polyfills",
|
||||
"type": "array",
|
||||
"description": "A list of polyfills to include in the build. Can be a full path for a file, relative to the current workspace or module specifier. Example: 'zone.js'."
|
||||
},
|
||||
{
|
||||
"name": "prerender",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Prerender (SSG) pages of your application during build time."
|
||||
},
|
||||
{
|
||||
"name": "preserve-symlinks",
|
||||
"type": "boolean",
|
||||
"description": "Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set."
|
||||
},
|
||||
{
|
||||
"name": "progress",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Log progress to the console while building."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
},
|
||||
{
|
||||
"name": "server",
|
||||
"type": "string",
|
||||
"description": "The full path for the server entry point to the application, relative to the current workspace."
|
||||
},
|
||||
{
|
||||
"name": "service-worker",
|
||||
"type": "string",
|
||||
"description": "Generates a service worker configuration."
|
||||
},
|
||||
{
|
||||
"name": "source-map",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration."
|
||||
},
|
||||
{
|
||||
"name": "ssr",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Server side render (SSR) pages of your application during runtime."
|
||||
},
|
||||
{
|
||||
"name": "stats-json",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Generates a 'stats.json' file which can be analyzed with https://esbuild.github.io/analyze/."
|
||||
},
|
||||
{
|
||||
"name": "subresource-integrity",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Enables the use of subresource integrity validation."
|
||||
},
|
||||
{
|
||||
"name": "ts-config",
|
||||
"type": "string",
|
||||
"description": "The full path for the TypeScript configuration file, relative to the current workspace."
|
||||
},
|
||||
{
|
||||
"name": "verbose",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Adds more details to output logging."
|
||||
},
|
||||
{
|
||||
"name": "watch",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Run build when files change."
|
||||
},
|
||||
{
|
||||
"name": "web-worker-ts-config",
|
||||
"type": "string",
|
||||
"description": "TypeScript configuration for Web Worker modules."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"name": "cache",
|
||||
"command": "ng cache",
|
||||
"shortDescription": "Configure persistent disk cache and retrieve cache statistics.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/cache/long-description.md",
|
||||
"longDescription": "Angular CLI saves a number of cachable operations on disk by default.\n\nWhen you re-run the same build, the build system restores the state of the previous build and re-uses previously performed operations, which decreases the time taken to build and test your applications and libraries.\n\nTo amend the default cache settings, add the `cli.cache` object to your [Workspace Configuration](reference/configs/workspace-config).\nThe object goes under `cli.cache` at the top level of the file, outside the `projects` sections.\n\n```jsonc\n{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"cli\": {\n \"cache\": {\n // ...\n },\n },\n \"projects\": {},\n}\n```\n\nFor more information, see [cache options](reference/configs/workspace-config#cache-options).\n\n### Cache environments\n\nBy default, disk cache is only enabled for local environments. The value of environment can be one of the following:\n\n- `all` - allows disk cache on all machines.\n- `local` - allows disk cache only on development machines.\n- `ci` - allows disk cache only on continuous integration (CI) systems.\n\nTo change the environment setting to `all`, run the following command:\n\n```bash\nng config cli.cache.environment all\n```\n\nFor more information, see `environment` in [cache options](reference/configs/workspace-config#cache-options).\n\n<div class=\"alert is-helpful\">\n\nThe Angular CLI checks for the presence and value of the `CI` environment variable to determine in which environment it is running.\n\n</div>\n\n### Cache path\n\nBy default, `.angular/cache` is used as a base directory to store cache results.\n\nTo change this path to `.cache/ng`, run the following command:\n\n```bash\nng config cli.cache.path \".cache/ng\"\n```\n",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
}
|
||||
],
|
||||
"subcommands": [
|
||||
{
|
||||
"name": "clean",
|
||||
"command": "clean",
|
||||
"shortDescription": "Deletes persistent disk cache from disk.",
|
||||
"options": [],
|
||||
"aliases": [],
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "disable",
|
||||
"command": "disable",
|
||||
"shortDescription": "Disables persistent disk cache for all projects in the workspace.",
|
||||
"options": [],
|
||||
"aliases": [
|
||||
"off"
|
||||
],
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"command": "enable",
|
||||
"shortDescription": "Enables disk cache for all projects in the workspace.",
|
||||
"options": [],
|
||||
"aliases": [
|
||||
"on"
|
||||
],
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "info",
|
||||
"command": "info",
|
||||
"shortDescription": "Prints persistent disk cache configuration and statistics in the console.",
|
||||
"options": [],
|
||||
"aliases": [],
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "completion",
|
||||
"command": "ng completion",
|
||||
"shortDescription": "Set up Angular CLI autocompletion for your terminal.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/completion/long-description.md",
|
||||
"longDescription": "Setting up autocompletion configures your terminal, so pressing the `<TAB>` key while in the middle\nof typing will display various commands and options available to you. This makes it very easy to\ndiscover and use CLI commands without lots of memorization.\n\n\n\n## Automated setup\n\nThe CLI should prompt and ask to set up autocompletion for you the first time you use it (v14+).\nSimply answer \"Yes\" and the CLI will take care of the rest.\n\n```\n$ ng serve\n? Would you like to enable autocompletion? This will set up your terminal so pressing TAB while typing Angular CLI commands will show possible options and autocomplete arguments. (Enabling autocompletion will modify configuration files in your home directory.) Yes\nAppended `source <(ng completion script)` to `/home/my-username/.bashrc`. Restart your terminal or run:\n\nsource <(ng completion script)\n\nto autocomplete `ng` commands.\n\n# Serve output...\n```\n\nIf you already refused the prompt, it won't ask again. But you can run `ng completion` to\ndo the same thing automatically.\n\nThis modifies your terminal environment to load Angular CLI autocompletion, but can't update your\ncurrent terminal session. Either restart it or run `source <(ng completion script)` directly to\nenable autocompletion in your current session.\n\nTest it out by typing `ng ser<TAB>` and it should autocomplete to `ng serve`. Ambiguous arguments\nwill show all possible options and their documentation, such as `ng generate <TAB>`.\n\n## Manual setup\n\nSome users may have highly customized terminal setups, possibly with configuration files checked\ninto source control with an opinionated structure. `ng completion` only ever appends Angular's setup\nto an existing configuration file for your current shell, or creates one if none exists. If you want\nmore control over exactly where this configuration lives, you can manually set it up by having your\nshell run at startup:\n\n```bash\nsource <(ng completion script)\n```\n\nThis is equivalent to what `ng completion` will automatically set up, and gives power users more\nflexibility in their environments when desired.\n\n## Platform support\n\nAngular CLI supports autocompletion for the Bash and Zsh shells on MacOS and Linux operating\nsystems. On Windows, Git Bash and [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/)\nusing Bash or Zsh are supported.\n\n## Global install\n\nAutocompletion works by configuring your terminal to invoke the Angular CLI on startup to load the\nsetup script. This means the terminal must be able to find and execute the Angular CLI, typically\nthrough a global install that places the binary on the user's `$PATH`. If you get\n`command not found: ng`, make sure the CLI is installed globally which you can do with the `-g`\nflag:\n\n```bash\nnpm install -g @angular/cli\n```\n",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
}
|
||||
],
|
||||
"subcommands": [
|
||||
{
|
||||
"name": "script",
|
||||
"command": "script",
|
||||
"shortDescription": "Generate a bash and zsh real-time type-ahead autocompletion script.",
|
||||
"options": [],
|
||||
"aliases": [],
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"name": "config",
|
||||
"command": "ng config [json-path] [value]",
|
||||
"shortDescription": "Retrieves or sets Angular configuration values in the angular.json file for the workspace.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/config/long-description.md",
|
||||
"longDescription": "A workspace has a single CLI configuration file, `angular.json`, at the top level.\nThe `projects` object contains a configuration object for each project in the workspace.\n\nYou can edit the configuration directly in a code editor,\nor indirectly on the command line using this command.\n\nThe configurable property names match command option names,\nexcept that in the configuration file, all names must use camelCase,\nwhile on the command line options can be given dash-case.\n\nFor further details, see [Workspace Configuration](reference/configs/workspace-config).\n\nFor configuration of CLI usage analytics, see [ng analytics](cli/analytics).\n",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "global",
|
||||
"type": "boolean",
|
||||
"aliases": [
|
||||
"g"
|
||||
],
|
||||
"default": false,
|
||||
"description": "Access the global configuration in the caller's home directory."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "json-path",
|
||||
"type": "string",
|
||||
"description": "The configuration key to set or query, in JSON path format. For example: \"a[3].foo.bar[2]\". If no new value is provided, returns the current value of this key.",
|
||||
"positional": 0
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"description": "If provided, a new value for the given configuration key.",
|
||||
"positional": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "deploy",
|
||||
"command": "ng deploy [project]",
|
||||
"shortDescription": "Invokes the deploy builder for a specified project or for the default project in the workspace.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/deploy/long-description.md",
|
||||
"longDescription": "The command takes an optional project name, as specified in the `projects` section of the `angular.json` workspace configuration file.\nWhen a project name is not supplied, executes the `deploy` builder for the default project.\n\nTo use the `ng deploy` command, use `ng add` to add a package that implements deployment capabilities to your favorite platform.\nAdding the package automatically updates your workspace configuration, adding a deployment\n[CLI builder](tools/cli/cli-builder).\nFor example:\n\n```json\n\"projects\": {\n \"my-project\": {\n ...\n \"architect\": {\n ...\n \"deploy\": {\n \"builder\": \"@angular/fire:deploy\",\n \"options\": {}\n }\n }\n }\n}\n```\n",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "e2e",
|
||||
"command": "ng e2e [project]",
|
||||
"shortDescription": "Builds and serves an Angular application, then runs end-to-end tests.",
|
||||
"aliases": [
|
||||
"e"
|
||||
],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"name": "extract-i18n",
|
||||
"command": "ng extract-i18n [project]",
|
||||
"shortDescription": "Extracts i18n messages from source code.",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "browser-target",
|
||||
"type": "string",
|
||||
"deprecated": "Use 'buildTarget' instead.",
|
||||
"description": "A browser builder target to extract i18n messages in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`."
|
||||
},
|
||||
{
|
||||
"name": "build-target",
|
||||
"type": "string",
|
||||
"description": "A builder target to extract i18n messages in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`."
|
||||
},
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"type": "string",
|
||||
"default": "xlf",
|
||||
"enum": [
|
||||
"xmb",
|
||||
"xlf",
|
||||
"xlif",
|
||||
"xliff",
|
||||
"xlf2",
|
||||
"xliff2",
|
||||
"json",
|
||||
"arb",
|
||||
"legacy-migrate"
|
||||
],
|
||||
"description": "Output format for the generated file."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "out-file",
|
||||
"type": "string",
|
||||
"description": "Name of the file to output."
|
||||
},
|
||||
{
|
||||
"name": "output-path",
|
||||
"type": "string",
|
||||
"description": "Path where output will be placed."
|
||||
},
|
||||
{
|
||||
"name": "progress",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Log progress to the console."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "lint",
|
||||
"command": "ng lint [project]",
|
||||
"shortDescription": "Runs linting tools on Angular application code in a given project folder.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/lint/long-description.md",
|
||||
"longDescription": "The command takes an optional project name, as specified in the `projects` section of the `angular.json` workspace configuration file.\nWhen a project name is not supplied, executes the `lint` builder for all projects.\n\nTo use the `ng lint` command, use `ng add` to add a package that implements linting capabilities. Adding the package automatically updates your workspace configuration, adding a lint [CLI builder](tools/cli/cli-builder).\nFor example:\n\n```json\n\"projects\": {\n \"my-project\": {\n ...\n \"architect\": {\n ...\n \"lint\": {\n \"builder\": \"@angular-eslint/builder:lint\",\n \"options\": {}\n }\n }\n }\n}\n```\n",
|
||||
"aliases": [],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
{
|
||||
"name": "serve",
|
||||
"command": "ng serve [project]",
|
||||
"shortDescription": "Builds and serves your application, rebuilding on file changes.",
|
||||
"aliases": [
|
||||
"dev",
|
||||
"s"
|
||||
],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "allowed-hosts",
|
||||
"type": "array",
|
||||
"description": "List of hosts that are allowed to access the dev server. This option has no effect when using the 'application' or other esbuild-based builders."
|
||||
},
|
||||
{
|
||||
"name": "browser-target",
|
||||
"type": "string",
|
||||
"deprecated": "Use 'buildTarget' instead.",
|
||||
"description": "A browser builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`."
|
||||
},
|
||||
{
|
||||
"name": "build-target",
|
||||
"type": "string",
|
||||
"description": "A build builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`."
|
||||
},
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "disable-host-check",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Don't verify connected clients are part of allowed hosts. This option has no effect when using the 'application' or other esbuild-based builders."
|
||||
},
|
||||
{
|
||||
"name": "force-esbuild",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Force the development server to use the 'browser-esbuild' builder when building. This is a developer preview option for the esbuild-based build system."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "hmr",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Enable hot module replacement."
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"type": "string",
|
||||
"default": "localhost",
|
||||
"description": "Host to listen on."
|
||||
},
|
||||
{
|
||||
"name": "live-reload",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to reload the page on change, using live-reload."
|
||||
},
|
||||
{
|
||||
"name": "open",
|
||||
"type": "boolean",
|
||||
"aliases": [
|
||||
"o"
|
||||
],
|
||||
"default": false,
|
||||
"description": "Opens the url in default browser."
|
||||
},
|
||||
{
|
||||
"name": "poll",
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "number",
|
||||
"default": 4200,
|
||||
"description": "Port to listen on."
|
||||
},
|
||||
{
|
||||
"name": "prebundle",
|
||||
"type": "boolean",
|
||||
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
},
|
||||
{
|
||||
"name": "proxy-config",
|
||||
"type": "string",
|
||||
"description": "Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server."
|
||||
},
|
||||
{
|
||||
"name": "public-host",
|
||||
"type": "string",
|
||||
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies. This option has no effect when using the 'application' or other esbuild-based builders."
|
||||
},
|
||||
{
|
||||
"name": "serve-path",
|
||||
"type": "string",
|
||||
"description": "The pathname where the application will be served."
|
||||
},
|
||||
{
|
||||
"name": "ssl",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Serve using HTTPS."
|
||||
},
|
||||
{
|
||||
"name": "ssl-cert",
|
||||
"type": "string",
|
||||
"description": "SSL certificate to use for serving HTTPS."
|
||||
},
|
||||
{
|
||||
"name": "ssl-key",
|
||||
"type": "string",
|
||||
"description": "SSL key to use for serving HTTPS."
|
||||
},
|
||||
{
|
||||
"name": "verbose",
|
||||
"type": "boolean",
|
||||
"description": "Adds more details to output logging."
|
||||
},
|
||||
{
|
||||
"name": "watch",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Rebuild on change."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
{
|
||||
"name": "test",
|
||||
"command": "ng test [project]",
|
||||
"shortDescription": "Runs unit tests in a project.",
|
||||
"longDescriptionRelativePath": "@angular/cli/src/commands/test/long-description.md",
|
||||
"longDescription": "Takes the name of the project, as specified in the `projects` section of the `angular.json` workspace configuration file.\nWhen a project name is not supplied, it will execute for all projects.\n",
|
||||
"aliases": [
|
||||
"t"
|
||||
],
|
||||
"deprecated": false,
|
||||
"options": [
|
||||
{
|
||||
"name": "browsers",
|
||||
"type": "string",
|
||||
"description": "Override which browsers tests are run against. Set to `false` to not use any browser."
|
||||
},
|
||||
{
|
||||
"name": "code-coverage",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Output a code coverage report."
|
||||
},
|
||||
{
|
||||
"name": "code-coverage-exclude",
|
||||
"type": "array",
|
||||
"description": "Globs to exclude from code coverage."
|
||||
},
|
||||
{
|
||||
"name": "configuration",
|
||||
"type": "string",
|
||||
"aliases": [
|
||||
"c"
|
||||
],
|
||||
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section in angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations."
|
||||
},
|
||||
{
|
||||
"name": "exclude",
|
||||
"type": "array",
|
||||
"description": "Globs of files to exclude, relative to the project root."
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
"type": "boolean",
|
||||
"description": "Shows a help message for this command in the console."
|
||||
},
|
||||
{
|
||||
"name": "include",
|
||||
"type": "array",
|
||||
"description": "Globs of files to include, relative to project root. \nThere are 2 special cases:\n - when a path to directory is provided, all spec files ending \".spec.@(ts|tsx)\" will be included\n - when a path to a file is provided, and a matching spec file exists it will be included instead."
|
||||
},
|
||||
{
|
||||
"name": "inline-style-language",
|
||||
"type": "string",
|
||||
"default": "css",
|
||||
"enum": [
|
||||
"css",
|
||||
"less",
|
||||
"sass",
|
||||
"scss"
|
||||
],
|
||||
"description": "The stylesheet language to use for the application's inline component styles."
|
||||
},
|
||||
{
|
||||
"name": "karma-config",
|
||||
"type": "string",
|
||||
"description": "The name of the Karma configuration file."
|
||||
},
|
||||
{
|
||||
"name": "main",
|
||||
"type": "string",
|
||||
"description": "The name of the main entry-point file."
|
||||
},
|
||||
{
|
||||
"name": "poll",
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
},
|
||||
{
|
||||
"name": "polyfills",
|
||||
"type": "string",
|
||||
"description": "Polyfills to be included in the build."
|
||||
},
|
||||
{
|
||||
"name": "preserve-symlinks",
|
||||
"type": "boolean",
|
||||
"description": "Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set."
|
||||
},
|
||||
{
|
||||
"name": "progress",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Log progress to the console while building."
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"type": "string",
|
||||
"description": "The name of the project to build. Can be an application or a library.",
|
||||
"positional": 0
|
||||
},
|
||||
{
|
||||
"name": "reporters",
|
||||
"type": "array",
|
||||
"description": "Karma reporters to use. Directly passed to the karma runner."
|
||||
},
|
||||
{
|
||||
"name": "source-map",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration."
|
||||
},
|
||||
{
|
||||
"name": "ts-config",
|
||||
"type": "string",
|
||||
"description": "The name of the TypeScript configuration file."
|
||||
},
|
||||
{
|
||||
"name": "watch",
|
||||
"type": "boolean",
|
||||
"description": "Run build when files change."
|
||||
},
|
||||
{
|
||||
"name": "web-worker-ts-config",
|
||||
"type": "string",
|
||||
"description": "TypeScript configuration for Web Worker modules."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,8 +5,6 @@ It can improve the user experience by quickly launching a static rendered page (
|
||||
|
||||
This gives users a meaningful first paint of your application that appears quickly because the browser can render the HTML and CSS without the need to initialize any JavaScript.
|
||||
|
||||
Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||
|
||||
<docs-workflow>
|
||||
<docs-step title="Prepare the application">
|
||||
Do this with the following Angular CLI command:
|
||||
@@ -17,7 +15,7 @@ ng new my-app --routing
|
||||
|
||||
</docs-code>
|
||||
|
||||
For an existing application, you have to manually add the `Router` and defining a `<router-outlet>` within your application.
|
||||
For an existing application, you have to manually add the `RouterModule` and defining a `<router-outlet>` within your application.
|
||||
</docs-step>
|
||||
<docs-step title="Create the application shell">
|
||||
Use the Angular CLI to automatically create the application shell.
|
||||
@@ -30,24 +28,57 @@ ng generate app-shell
|
||||
|
||||
For more information about this command, see [App shell command](cli/generate#app-shell-command).
|
||||
|
||||
The command updates the application code and adds extra files to the project structure.
|
||||
After running this command you can see that the `angular.json` configuration file has been updated to add two new targets, with a few other changes.
|
||||
|
||||
<code-example language="text">
|
||||
|
||||
src
|
||||
├── app
|
||||
│ ├── app.config.server.ts # server application configuration
|
||||
│ └── app-shell # app-shell component
|
||||
│ ├── app-shell.component.html
|
||||
│ ├── app-shell.component.scss
|
||||
│ ├── app-shell.component.spec.ts
|
||||
│ └── app-shell.component.ts
|
||||
└── main.server.ts # main server application bootstrapping
|
||||
|
||||
</code-example>
|
||||
<docs-code language="json">
|
||||
|
||||
"server": {
|
||||
"builder": "@angular-devkit/build-angular:server",
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"outputPath": "dist/my-app/server",
|
||||
"main": "src/main.server.ts",
|
||||
"tsConfig": "tsconfig.server.json"
|
||||
},
|
||||
"configurations": {
|
||||
"development": {
|
||||
"outputHashing": "none",
|
||||
},
|
||||
"production": {
|
||||
"outputHashing": "media",
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"sourceMap": false,
|
||||
"optimization": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"app-shell": {
|
||||
"builder": "@angular-devkit/build-angular:app-shell",
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"route": "shell"
|
||||
},
|
||||
"configurations": {
|
||||
"development": {
|
||||
"browserTarget": "my-app:build:development",
|
||||
"serverTarget": "my-app:server:development",
|
||||
},
|
||||
"production": {
|
||||
"browserTarget": "my-app:build:production",
|
||||
"serverTarget": "my-app:server:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</docs-code>
|
||||
</docs-step>
|
||||
<docs-step title="Verify the application is built with the shell content">
|
||||
Use the Angular CLI to build the `app-shell` target.
|
||||
|
||||
<docs-code language="shell">
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ The `versionUpdates` is an `Observable` property of `SwUpdate` and emits four ev
|
||||
### Checking for updates
|
||||
|
||||
It's possible to ask the service worker to check if any updates have been deployed to the server.
|
||||
The service worker checks for updates during initialization and on each navigation request —that is, when the user navigates from a different address to your application.
|
||||
The service worker checks for updates during initialization and on each navigation request —that is, when the user navigates from a different address to your application.
|
||||
However, you might choose to manually check for updates if you have a site that changes frequently or want updates to happen on a schedule.
|
||||
|
||||
Do this with the `checkForUpdate()` method:
|
||||
|
||||
@@ -7,7 +7,7 @@ This topic describes the properties of the service worker configuration file.
|
||||
The `ngsw-config.json` JSON configuration file specifies which files and data URLs the Angular service worker should cache and how it should update the cached files and data.
|
||||
The [Angular CLI](tools/cli) processes this configuration file during `ng build`.
|
||||
|
||||
All file paths must begin with `/`, which corresponds to the deployment directory — usually `dist/<project-name>` in CLI projects.
|
||||
All file paths must begin with `/`, which corresponds to the deployment directory — usually `dist/<project-name>` in CLI projects.
|
||||
|
||||
Unless otherwise commented, patterns use a **limited*** glob format that internally will be converted into regex:
|
||||
|
||||
@@ -68,10 +68,10 @@ This field contains an array of asset groups, each of which defines a set of ass
|
||||
{
|
||||
"assetGroups": [
|
||||
{
|
||||
…
|
||||
…
|
||||
},
|
||||
{
|
||||
…
|
||||
…
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -169,10 +169,10 @@ This field contains an array of data groups, each of which defines a set of data
|
||||
{
|
||||
"dataGroups": [
|
||||
{
|
||||
…
|
||||
…
|
||||
},
|
||||
{
|
||||
…
|
||||
…
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -197,7 +197,7 @@ export interface DataGroup {
|
||||
maxSize: number;
|
||||
maxAge: string;
|
||||
timeout?: string;
|
||||
strategy?: 'freshness' | 'performance';
|
||||
strategy?: 'freshness' | 'performance';
|
||||
};
|
||||
cacheQueryOptions?: {
|
||||
ignoreSearch?: boolean;
|
||||
@@ -226,7 +226,7 @@ Only non-mutating requests (GET and HEAD) are cached.
|
||||
Occasionally APIs change formats in a way that is not backward-compatible.
|
||||
A new version of the application might not be compatible with the old API format and thus might not be compatible with existing cached resources from that API.
|
||||
|
||||
`version` provides a mechanism to indicate that the resources being cached have been updated in a backwards-incompatible way, and that the old cache entries —those from previous versions— should be discarded.
|
||||
`version` provides a mechanism to indicate that the resources being cached have been updated in a backwards-incompatible way, and that the old cache entries —those from previous versions— should be discarded.
|
||||
|
||||
`version` is an integer field and defaults to `1`.
|
||||
|
||||
@@ -306,7 +306,7 @@ In case you are not familiar, an [opaque response][https://fetch.spec.whatwg.org
|
||||
One of the characteristics of an opaque response is that the service worker is not allowed to read its status, meaning it can't check if the request was successful or not.
|
||||
See [Introduction to fetch()][https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types] for more details.
|
||||
|
||||
If you are not able to implement CORS — for example, if you don't control the origin — prefer using the `freshness` strategy for resources that result in opaque responses.
|
||||
If you are not able to implement CORS — for example, if you don't control the origin — prefer using the `freshness` strategy for resources that result in opaque responses.
|
||||
|
||||
</docs-callout>
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ Clients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100
|
||||
Last update tick: 1s496u
|
||||
Last update run: never
|
||||
Task queue:
|
||||
* init post-load (update, cleanup)
|
||||
* init post-load (update, cleanup)
|
||||
|
||||
Debug log:
|
||||
|
||||
@@ -232,7 +232,7 @@ HELPFUL: This version hash is the "latest manifest hash" listed above. Both clie
|
||||
Last update tick: 1s496u
|
||||
Last update run: never
|
||||
Task queue:
|
||||
* init post-load (update, cleanup)
|
||||
* init post-load (update, cleanup)
|
||||
|
||||
</docs-code>
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ To simulate a network issue, disable network interaction for your application.
|
||||
|
||||
In Chrome:
|
||||
|
||||
1. Select **Tools** > **Developer Tools** (from the Chrome menu located in the top right corner).
|
||||
1. Select **Tools** > **Developer Tools** (from the Chrome menu located in the top right corner).
|
||||
1. Go to the **Network tab**.
|
||||
1. Select **Offline** in the **Throttling** dropdown menu.
|
||||
|
||||
@@ -110,7 +110,7 @@ Make a change to the application, and watch the service worker install the updat
|
||||
<docs-code language="shell">
|
||||
|
||||
ng build
|
||||
npx http-server -p 8080 -c-1 dist/<project-name>/browser
|
||||
npx http-server -p 8080 -c-1 dist/<project-name>/browser
|
||||
|
||||
</docs-code>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Invoke push notifications by pushing a message with a valid payload.
|
||||
See `SwPush` for guidance.
|
||||
|
||||
HELPFUL: In Chrome, you can test push notifications without a backend.
|
||||
Open Devtools -> Application -> Service Workers and use the `Push` input to send a JSON notification payload.
|
||||
Open Devtools -> Application -> Service Workers and use the `Push` input to send a JSON notification payload.
|
||||
|
||||
## Notification click handling
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ To add a web worker to an existing project, use the Angular CLI `ng generate` co
|
||||
|
||||
<docs-code language="shell">
|
||||
|
||||
ng generate web-worker <location>
|
||||
ng generate web-worker <location>
|
||||
|
||||
</docs-code>
|
||||
|
||||
@@ -31,8 +31,8 @@ The command performs the following actions.
|
||||
|
||||
<docs-code language="typescript" header="src/app/app.worker.ts">
|
||||
|
||||
addEventListener('message', ({ data }) => {
|
||||
const response = `worker response to ${data}`;
|
||||
addEventListener('message', ({ data }) => {
|
||||
const response = `worker response to ${data}`;
|
||||
postMessage(response);
|
||||
});
|
||||
|
||||
@@ -45,8 +45,8 @@ The command performs the following actions.
|
||||
if (typeof Worker !== 'undefined') {
|
||||
// Create a new
|
||||
const worker = new Worker(new URL('./app.worker', import.meta.url));
|
||||
worker.onmessage = ({ data }) => {
|
||||
console.log(`page got message: ${data}`);
|
||||
worker.onmessage = ({ data }) => {
|
||||
console.log(`page got message: ${data}`);
|
||||
};
|
||||
worker.postMessage('hello');
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
load("//aio/content/examples:examples.bzl", "docs_example")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
docs_example(
|
||||
name = "architecture",
|
||||
)
|
||||
@@ -0,0 +1,94 @@
|
||||
import {protractor, browser, element, by, ElementFinder} from 'protractor';
|
||||
|
||||
const nameSuffix = 'X';
|
||||
|
||||
interface Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
describe('Architecture', () => {
|
||||
const expectedTitle = 'Architecture of Angular';
|
||||
const expectedH2 = ['Hero List', 'Sales Tax Calculator'];
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
|
||||
it(`has title '${expectedTitle}'`, async () => {
|
||||
expect(await browser.getTitle()).toEqual(expectedTitle);
|
||||
});
|
||||
|
||||
it(`has h2 '${expectedH2}'`, async () => {
|
||||
const h2 = await element.all(by.css('h2')).map((elt: any) => elt.getText());
|
||||
expect(h2).toEqual(expectedH2);
|
||||
});
|
||||
|
||||
describe('Hero', heroTests);
|
||||
describe('Salex tax', salesTaxTests);
|
||||
});
|
||||
|
||||
function heroTests() {
|
||||
const targetHero: Hero = {id: 2, name: 'Dr Nice'};
|
||||
|
||||
it('has the right number of heroes', async () => {
|
||||
const page = getPageElts();
|
||||
expect(await page.heroes.count()).toEqual(3);
|
||||
});
|
||||
|
||||
it('has no hero details initially', async () => {
|
||||
const page = getPageElts();
|
||||
expect(await page.heroDetail.isPresent()).toBeFalsy('no hero detail');
|
||||
});
|
||||
|
||||
it('shows selected hero details', async () => {
|
||||
await element(by.cssContainingText('li', targetHero.name)).click();
|
||||
const page = getPageElts();
|
||||
const hero = await heroFromDetail(page.heroDetail);
|
||||
expect(hero.id).toEqual(targetHero.id);
|
||||
expect(hero.name).toEqual(targetHero.name);
|
||||
});
|
||||
|
||||
it(`shows updated hero name in details`, async () => {
|
||||
const input = element.all(by.css('input')).first();
|
||||
await input.sendKeys(nameSuffix);
|
||||
const page = getPageElts();
|
||||
const hero = await heroFromDetail(page.heroDetail);
|
||||
const newName = targetHero.name + nameSuffix;
|
||||
expect(hero.id).toEqual(targetHero.id);
|
||||
expect(hero.name).toEqual(newName);
|
||||
});
|
||||
}
|
||||
|
||||
function salesTaxTests() {
|
||||
it('has no sales tax initially', async () => {
|
||||
const page = getPageElts();
|
||||
expect(await page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info');
|
||||
});
|
||||
|
||||
it('shows sales tax', async () => {
|
||||
const page = getPageElts();
|
||||
await page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER);
|
||||
expect(await page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00');
|
||||
});
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
function getPageElts() {
|
||||
return {
|
||||
heroes: element.all(by.css('app-root li')),
|
||||
heroDetail: element(by.css('app-root app-hero-detail')),
|
||||
salesTaxAmountInput: element(by.css('app-root app-sales-tax input')),
|
||||
salesTaxDetail: element(by.css('app-root app-sales-tax div')),
|
||||
};
|
||||
}
|
||||
|
||||
async function heroFromDetail(detail: ElementFinder): Promise<Hero> {
|
||||
// Get hero id from the first <div>
|
||||
const id = await detail.all(by.css('div')).first().getText();
|
||||
// Get name from the h2
|
||||
const name = await detail.element(by.css('app-hero-detail h2')).getText();
|
||||
return {
|
||||
id: +id.slice(id.indexOf(' ') + 1),
|
||||
name: name.substring(0, name.lastIndexOf(' ')),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// #docregion import
|
||||
import {Component} from '@angular/core';
|
||||
// #enddocregion import
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>Architecture Example</h1>
|
||||
<app-hero-list></app-hero-list>
|
||||
<app-sales-tax></app-sales-tax>
|
||||
`,
|
||||
})
|
||||
export class AppComponent {}
|
||||
@@ -0,0 +1,22 @@
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
// #docregion imports
|
||||
import {NgModule} from '@angular/core';
|
||||
import {AppComponent} from './app.component';
|
||||
// #enddocregion imports
|
||||
import {HeroDetailComponent} from './hero-detail.component';
|
||||
import {HeroListComponent} from './hero-list.component';
|
||||
import {SalesTaxComponent} from './sales-tax.component';
|
||||
import {HeroService} from './hero.service';
|
||||
import {BackendService} from './backend.service';
|
||||
import {Logger} from './logger.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule, FormsModule],
|
||||
declarations: [AppComponent, HeroDetailComponent, HeroListComponent, SalesTaxComponent],
|
||||
providers: [BackendService, HeroService, Logger],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
// #docregion export
|
||||
export class AppModule {}
|
||||
// #enddocregion export
|
||||
@@ -0,0 +1,25 @@
|
||||
import {Injectable, Type} from '@angular/core';
|
||||
|
||||
import {Logger} from './logger.service';
|
||||
import {Hero} from './hero';
|
||||
|
||||
const HEROES = [
|
||||
new Hero('Windstorm', 'Weather mastery'),
|
||||
new Hero('Dr Nice', 'Killing them with kindness'),
|
||||
new Hero('Magneta', 'Manipulates metallic objects'),
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
export class BackendService {
|
||||
constructor(private logger: Logger) {}
|
||||
|
||||
getAll(type: Type<any>): PromiseLike<any[]> {
|
||||
if (type === Hero) {
|
||||
// TODO: get from the database
|
||||
return Promise.resolve<Hero[]>(HEROES);
|
||||
}
|
||||
const err = new Error('Cannot get object of this type');
|
||||
this.logger.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user