mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
225 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c486c9682 | |||
| 3fe21333ce | |||
| 97e8265570 | |||
| da93046920 | |||
| 017825b0f4 | |||
| 58365e04a2 | |||
| 2435291dda | |||
| 5cb44aa2fd | |||
| 375e60610e | |||
| ca39926de2 | |||
| dd8490f384 | |||
| 2e9a21a6ad | |||
| 744e20641a | |||
| 63a9027720 | |||
| ef55d48dee | |||
| 8d4b4ff7bf | |||
| 2e3fa28b93 | |||
| eeaec924ef | |||
| 40e1edc977 | |||
| 4482cbd22c | |||
| d695398414 | |||
| f3f1f85bed | |||
| c6896a30c0 | |||
| db78666196 | |||
| e847487d4f | |||
| 238f2a8bc9 | |||
| 2de7679b0b | |||
| 06391d1eb8 | |||
| 0cd9538f24 | |||
| 241858d20b | |||
| f303838d95 | |||
| bc4a6a9715 | |||
| 429700590c | |||
| ca459177d6 | |||
| 04a1d50bc8 | |||
| fc4d8bb78c | |||
| 756aa8f600 | |||
| 4586d2341d | |||
| f466c89d1f | |||
| 8876283f47 | |||
| e74ea10f5d | |||
| b74c02a6b8 | |||
| 9f6605d11b | |||
| a42f0ba65e | |||
| ea2fd1b66a | |||
| a6f09adb55 | |||
| 47c712e51e | |||
| 6f637718d1 | |||
| 54deaae3ba | |||
| cd88f1486e | |||
| 37a6da30ca | |||
| afc72b06fe | |||
| 0fb114274c | |||
| 86086169e7 | |||
| 99a0b90073 | |||
| 52a31d0ed8 | |||
| 4b6deb5ac2 | |||
| f933a38e3d | |||
| 46a2c5f8cc | |||
| 9e3d54cf2d | |||
| a997e08c6f | |||
| 7d59eb0a96 | |||
| 924a2768df | |||
| 7df133dcc2 | |||
| 2a0ac20824 | |||
| 67eb402024 | |||
| 4883ae686c | |||
| 57cb448de5 | |||
| 0bd668c943 | |||
| 2c0bb7fb0e | |||
| 735cdf3761 | |||
| 948fb5f937 | |||
| 9f1a5fa5da | |||
| cab06bd125 | |||
| cdc5e39532 | |||
| ed8e7c727b | |||
| e08cc50f3c | |||
| ca7456e722 | |||
| b353ad5bac | |||
| bd6d18b977 | |||
| 3b218a72ce | |||
| 4367c44f7f | |||
| b69bf37841 | |||
| 05a05b628b | |||
| c21f41d6d4 | |||
| 413db303f4 | |||
| 752ebd62c9 | |||
| 7001b5d633 | |||
| fccf375df1 | |||
| 8d85de7fe1 | |||
| 4c2b0d94e2 | |||
| 57174bb60b | |||
| 7a4a5253ea | |||
| c5a0e909ac | |||
| d07ce6156e | |||
| e3b874b4fb | |||
| 1ac37f932f | |||
| 8650f0dee2 | |||
| 030d77010d | |||
| 96ca49d145 | |||
| 8264382a6b | |||
| f5a5215166 | |||
| 5cd00f167c | |||
| 22f89c0a2d | |||
| c442912532 | |||
| 9f9dd901ae | |||
| 30e42df518 | |||
| 566499af1d | |||
| 4a5f37d216 | |||
| 74567f1c8a | |||
| 64399b26c0 | |||
| 1b296dbb80 | |||
| cddc426e18 | |||
| 8109013b0f | |||
| f25d7e880f | |||
| f240c70971 | |||
| 0172477ff2 | |||
| 0702d4a560 | |||
| 798aee7a83 | |||
| c477e876e3 | |||
| ecd0daf8fd | |||
| 6eca767811 | |||
| d8d6478d0e | |||
| 0c4d7e061e | |||
| 293dc3b046 | |||
| 8dca5a11f5 | |||
| 45fca0bc95 | |||
| 85819b9cdb | |||
| 87378a773d | |||
| 96dd0c715e | |||
| ccddacf11d | |||
| b216e76838 | |||
| 0d31904a96 | |||
| aa3df2a7d4 | |||
| 50b7901169 | |||
| 1439f059a3 | |||
| ac211d46b0 | |||
| 356984d9ba | |||
| 7ac94dd664 | |||
| 49aff2726f | |||
| 6c14c9324f | |||
| c0c7216c5f | |||
| 25e4f04d9f | |||
| 259707e31c | |||
| d17ba9bc87 | |||
| a4923f1f17 | |||
| e603450592 | |||
| c6861eefa4 | |||
| 910742389f | |||
| 98d545fafa | |||
| 7786e35faa | |||
| 49101330f8 | |||
| 4507704a7e | |||
| 854b839531 | |||
| 89f7b00e59 | |||
| f12b01ec88 | |||
| 0c8aaf082e | |||
| a4f024fb07 | |||
| e2e0f08d99 | |||
| e194fbfbaa | |||
| 8ad1ee764b | |||
| f222bee8fa | |||
| 9a9a00e0f9 | |||
| 5f9cac037b | |||
| 9778326f10 | |||
| fac5a7cf4e | |||
| ae145d19c6 | |||
| 30b6d34a49 | |||
| 3e0b7c1bdc | |||
| a58a35dfe4 | |||
| a7c9fbb087 | |||
| 20811aad27 | |||
| df453c3549 | |||
| 1f6c96a1dc | |||
| 656549d88a | |||
| c0f0baac58 | |||
| d38aa4f103 | |||
| 7397b6648a | |||
| 0fe9331958 | |||
| 7620f506c0 | |||
| 62ad2f0c71 | |||
| 424a26b3c7 | |||
| 18bd1a5ccb | |||
| 8922a11693 | |||
| 4e0341050b | |||
| 0616dc2839 | |||
| dc228c6fc1 | |||
| b1a7249c24 | |||
| 9ff4893bc0 | |||
| 025f7af694 | |||
| 1c4a99a6d1 | |||
| 51d53fc728 | |||
| be882c3efb | |||
| 18fa6d7556 | |||
| bb8a5a4c70 | |||
| 9c00506a26 | |||
| 79e8539ce2 | |||
| 6f79507ea7 | |||
| 6616019735 | |||
| 4d4858fa28 | |||
| 538fe47d9d | |||
| b07c549802 | |||
| 6f6ad0279b | |||
| d08f91f861 | |||
| 28aa7b3188 | |||
| 6ac0a68d73 | |||
| ea19bff302 | |||
| 1112e9196a | |||
| 0d8a5c4665 | |||
| 76ceebad04 | |||
| 99c2d76651 | |||
| 246cb9c381 | |||
| d7c75c6edb | |||
| 0daca457bb | |||
| 12f9ed01cc | |||
| 69713413f7 | |||
| 43d6816f9e | |||
| 4c4fea1304 | |||
| c6df89c827 | |||
| 9cae9b4a8c | |||
| 29b959ce31 | |||
| a24b24e8a4 | |||
| f51c008744 | |||
| 3dedd6a07a | |||
| 881376eb42 |
@@ -177,6 +177,9 @@ test:saucelabs --flaky_test_attempts=1
|
||||
|
||||
# --ng_perf will ask the Ivy compiler to produce performance results for each build.
|
||||
build --flag_alias=ng_perf=//packages/compiler-cli:ng_perf
|
||||
# --adev_fast will run adev build/serve in a faster mode, skipping things like prerendering
|
||||
# for local development.
|
||||
build --flag_alias=fast_adev=//adev:fast_build_mode
|
||||
|
||||
####################################################
|
||||
# User bazel configuration
|
||||
|
||||
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# This workflow builds the previews for pull requests when a certain label is applied.
|
||||
# The actual deployment happens as part of a dedicated second workflow to avoid security
|
||||
# issues where the building would otherwise occur in an authorized context where secrets
|
||||
# could be leaked. More details can be found here:
|
||||
|
||||
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
|
||||
|
||||
name: Build adev for preview deployment
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [synchronize, labeled]
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
adev-build:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'adev: preview') ||
|
||||
(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@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@73777547f819464aa5f48071b966eed34fd2c402
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
artifact-build-revision: '${{github.event.pull_request.head.sha}}'
|
||||
deploy-directory: './dist/bin/adev/build/browser'
|
||||
@@ -0,0 +1,50 @@
|
||||
# This workflow runs whenever the ADEV build workflow has completed. Deployment happens
|
||||
# as part of a dedicated second workflow to avoid security issues where the building would
|
||||
# otherwise occur in an authorized context where secrets could be leaked.
|
||||
#
|
||||
# More details can be found here:
|
||||
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
|
||||
|
||||
name: Deploying adev preview to Firebase
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['Build adev for preview deployment']
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
# Needed in order to be able to comment on the pull request.
|
||||
pull-requests: write
|
||||
# Needed in order to checkout the repository
|
||||
contents: read
|
||||
# Needed in order to retrieve the artifacts from the previous job
|
||||
actions: read
|
||||
|
||||
env:
|
||||
PREVIEW_PROJECT: ng-dev-previews
|
||||
PREVIEW_SITE: ng-dev-previews-fw
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
- name: Configure Firebase deploy target
|
||||
working-directory: ./
|
||||
run: |
|
||||
# We can use `npx` as the Firebase deploy actions uses it too.
|
||||
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@73777547f819464aa5f48071b966eed34fd2c402
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
firebase-config-dir: './adev'
|
||||
firebase-public-dir: './adev/build/browser'
|
||||
firebase-project-id: '${{env.PREVIEW_PROJECT}}'
|
||||
firebase-service-key: '${{secrets.FIREBASE_PREVIEW_SERVICE_TOKEN}}'
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
run: yarn bazel test --config=aio_local_deps //adev:test
|
||||
|
||||
aio-local:
|
||||
runs-on:
|
||||
@@ -184,7 +184,7 @@ jobs:
|
||||
run: yarn --cwd aio deploy-production
|
||||
- name: Notify about failed deployment
|
||||
if: ${{ failure() }}
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v=v1.24.0
|
||||
uses: slackapi/slack-github-action@2a8087d4af6f83146a87539a70defe909fe6dbe6 # v=v1.24.0
|
||||
with:
|
||||
channel-id: 'C07DT5M6V,CKV1F72BG'
|
||||
slack-message: 'Deploy to aio job failed for ${{ github.base_ref }} branch failed on build ${{ github.event.after }}: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
@@ -235,9 +235,11 @@ jobs:
|
||||
//packages/zone.js/test/closure:closure_js \
|
||||
|
||||
- run: |
|
||||
rm -Rf packages/zone.js/build
|
||||
rm -Rf packages/zone.js/test/extra/*.umd.js
|
||||
|
||||
mkdir -p packages/zone.js/build/
|
||||
mkdir -p packages/zone.js/build/test/
|
||||
mkdir -p packages/zone.js/test/
|
||||
|
||||
cp dist/bin/packages/zone.js/bundles/zone.umd.js packages/zone.js/build/zone.umd.js
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
|
||||
yarn -s ng-dev commit-message pre-commit-validate --file $1 2>/dev/null
|
||||
|
||||
+1
-4
@@ -1,11 +1,8 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
|
||||
yarn -s ng-dev format staged 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "WARNING: failed to run file formatting (ng-dev format staged)"
|
||||
fi
|
||||
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
|
||||
yarn -s ng-dev commit-message restore-commit-message-draft $1 $2 2>/dev/null
|
||||
|
||||
+44
-1
@@ -5,7 +5,32 @@ import {FormatConfig} from '@angular/ng-dev';
|
||||
*/
|
||||
export const format: FormatConfig = {
|
||||
'prettier': {
|
||||
'matchers': ['**/*.{yaml,yml}'],
|
||||
'matchers': [
|
||||
'**/*.{yaml,yml}',
|
||||
'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',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
],
|
||||
},
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
@@ -31,6 +56,24 @@ export const format: FormatConfig = {
|
||||
'!packages/common/src/i18n/currencies.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,
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
"packages/http/**",
|
||||
"**/.gitignore",
|
||||
"**/.gitkeep",
|
||||
"**/yarn.lock",
|
||||
"**/package.json",
|
||||
"**/third_party/**",
|
||||
"**/tsconfig-build.json",
|
||||
"**/tsconfig-tsec.json",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"tabs": false,
|
||||
"embeddedLanguageFormatting": "off",
|
||||
"singleQuote": true,
|
||||
"semicolon": true,
|
||||
"quoteProps": "preserve",
|
||||
|
||||
+13
-2
@@ -166,8 +166,9 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- crisbeto
|
||||
- JoostK
|
||||
- devversion
|
||||
- dylhunn
|
||||
- JoostK
|
||||
|
||||
# =========================================================
|
||||
# Framework: Migrations
|
||||
@@ -352,6 +353,7 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- crisbeto
|
||||
- devversion
|
||||
- dylhunn
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
@@ -1069,9 +1071,16 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- twerske
|
||||
- josephperrott
|
||||
- jelbourn
|
||||
- bencodezen
|
||||
- jessicajaniuk
|
||||
- dylhunn
|
||||
- AndrewKushnir
|
||||
- alxhub
|
||||
- crisbeto
|
||||
- atscott
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
# Docs-infra
|
||||
@@ -1150,6 +1159,7 @@ groups:
|
||||
- josephperrott
|
||||
- mgechev
|
||||
- twerske
|
||||
- ~jeanmeche
|
||||
|
||||
# =========================================================
|
||||
# Dev-infra
|
||||
@@ -1394,6 +1404,7 @@ groups:
|
||||
- devversion # Paul Gschwendtner
|
||||
- dgp1130 # Doug Parker
|
||||
- dylhunn # Dylan Hunn
|
||||
- jeanmeche # Matthieu Riegler
|
||||
- jelbourn # Jeremy Elbourn
|
||||
- jessicajaniuk # Jessica Janiuk
|
||||
- JiaLiPassion # Jia Li
|
||||
|
||||
+105
-205
@@ -1,3 +1,102 @@
|
||||
<a name="17.1.3"></a>
|
||||
# 17.1.3 (2024-02-08)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bc4a6a9715](https://github.com/angular/angular/commit/bc4a6a9715547881ed8e65169a5aaebfd3188a7f) | fix | do not error due to multiple components named equally ([#54273](https://github.com/angular/angular/pull/54273)) |
|
||||
| [a997e08c6f](https://github.com/angular/angular/commit/a997e08c6f5c5321e5d18f3368ff0886fa133d59) | fix | handle default imports in defer blocks ([#53695](https://github.com/angular/angular/pull/53695)) |
|
||||
| [63a9027720](https://github.com/angular/angular/commit/63a9027720611002c6ee3b443a11e9feff213059) | fix | interpolatedSignalNotInvoked diagnostic for model signals ([#54338](https://github.com/angular/angular/pull/54338)) |
|
||||
| [40e1edc977](https://github.com/angular/angular/commit/40e1edc977fbe398adc535167f8ede2db8985656) | fix | properly catch fatal diagnostics in type checking ([#54309](https://github.com/angular/angular/pull/54309)) |
|
||||
| [9f6605d11b](https://github.com/angular/angular/commit/9f6605d11b7ee75f289b5a2ed69e201d65b038d8) | fix | support jumping to definitions of signal-based inputs ([#54233](https://github.com/angular/angular/pull/54233)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7df133dcc2](https://github.com/angular/angular/commit/7df133dcc243cd6b0f779fa35de7f916e6938301) | fix | `afterRender` hooks should allow updating state ([#54074](https://github.com/angular/angular/pull/54074)) |
|
||||
| [744e20641a](https://github.com/angular/angular/commit/744e20641a21d18c324bd9c157c8912d38741826) | fix | Fix possible infinite loop with `markForCheck` by partially reverting [#54074](https://github.com/angular/angular/pull/54074) ([#54329](https://github.com/angular/angular/pull/54329)) |
|
||||
| [0fb114274c](https://github.com/angular/angular/commit/0fb114274cead9f317a2fc902cc3a3f6b046e708) | fix | update imports to be compatible with rxjs 6 ([#54193](https://github.com/angular/angular/pull/54193)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [238f2a8bc9](https://github.com/angular/angular/commit/238f2a8bc9c46b0d08aff163349ecc1493441a69) | fix | Clear internal transition when navigation finalizes ([#54261](https://github.com/angular/angular/pull/54261)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.2"></a>
|
||||
# 17.1.2 (2024-01-31)
|
||||
###
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ccddacf11d](https://github.com/angular/angular/commit/ccddacf11deaebeda12e1bdb6e93ec401397d352) | fix | cta clickability issue in adev homepage. ([#52905](https://github.com/angular/angular/pull/52905)) |
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [98d545fafa](https://github.com/angular/angular/commit/98d545fafa7fc3b1fb3ae049ce655e33ef9bd423) | fix | cleanup DOM elements when root view is removed with async animations ([#53033](https://github.com/angular/angular/pull/53033)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cdc5e39532](https://github.com/angular/angular/commit/cdc5e3953237a192beafd6330f9d9e36ede34f2c) | fix | The date pipe should return ISO format for week and week-year as intended in the unit test. ([#53879](https://github.com/angular/angular/pull/53879)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f12b01ec88](https://github.com/angular/angular/commit/f12b01ec88eaf18041c2e46335428627aa0d7744) | fix | Update type check block to fix control flow source mappings ([#53980](https://github.com/angular/angular/pull/53980)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c477e876e3](https://github.com/angular/angular/commit/c477e876e39495b855b096440d53cf1dd1ad33c6) | fix | change defer block fixture default behavior to playthrough ([#54088](https://github.com/angular/angular/pull/54088)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8264382a6b](https://github.com/angular/angular/commit/8264382a6bf389fb3fca75fa2d6c0a2aa5a1e42f) | fix | error in standalone migration when non-array value is used as declarations in TestBed ([#54122](https://github.com/angular/angular/pull/54122)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.1"></a>
|
||||
# 17.1.1 (2024-01-24)
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f222bee8fa](https://github.com/angular/angular/commit/f222bee8fa037f437761e5f7f127f22f280e9154) | fix | revert commit that replaced `last` helper with native `Array.at(-1)` ([#54021](https://github.com/angular/angular/pull/54021)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0"></a>
|
||||
# 17.1.0 (2024-01-17)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [79ff91a813](https://github.com/angular/angular/commit/79ff91a813e544929cb5eb5f9aab762a9f3d0435) | fix | allow TS jsDocParsingMode host option to be programmatically set ([#53126](https://github.com/angular/angular/pull/53126)) |
|
||||
| [5613051a8b](https://github.com/angular/angular/commit/5613051a8bd2626ae347292807b2bf21085c4c02) | fix | allow TS jsDocParsingMode host option to be programmatically set again ([#53292](https://github.com/angular/angular/pull/53292)) |
|
||||
| [df8a825910](https://github.com/angular/angular/commit/df8a825910951bebf34a4eede42f3ce5cd3e6fb7) | fix | project empty block root node ([#53620](https://github.com/angular/angular/pull/53620)) |
|
||||
| [478d622265](https://github.com/angular/angular/commit/478d6222650884478314985e3d5132587c4f670c) | fix | project empty block root node in template pipeline ([#53620](https://github.com/angular/angular/pull/53620)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [abdc7e4578](https://github.com/angular/angular/commit/abdc7e45786667e4283912024a641975f1917d97) | feat | support type-checking for generic signal inputs ([#53521](https://github.com/angular/angular/pull/53521)) |
|
||||
| [e620b3a724](https://github.com/angular/angular/commit/e620b3a724cb615af24b7779c0ab492d24efb8cc) | fix | add compiler option to disable control flow content projection diagnostic ([#53311](https://github.com/angular/angular/pull/53311)) |
|
||||
| [4c1d69e288](https://github.com/angular/angular/commit/4c1d69e2880f22745c820eee630d10071e4fa86b) | fix | add diagnostic for control flow that prevents content projection ([#53190](https://github.com/angular/angular/pull/53190)) |
|
||||
| [76ceebad04](https://github.com/angular/angular/commit/76ceebad047f62972654a8c934c77d8d02d9fa14) | fix | do not throw fatal error if extended type check fails ([#53896](https://github.com/angular/angular/pull/53896)) |
|
||||
| [1a6eaa0fea](https://github.com/angular/angular/commit/1a6eaa0fea1024b919e17ac9d2e8c07df7916de8) | fix | input transform in local compilation mode ([#53645](https://github.com/angular/angular/pull/53645)) |
|
||||
| [56a76d73e0](https://github.com/angular/angular/commit/56a76d73e037aeea1975808d5c51608fd23d4fa6) | fix | modify `getConstructorDependencies` helper to work with reflection host after the previous change ([#52215](https://github.com/angular/angular/pull/52215)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [863be4b698](https://github.com/angular/angular/commit/863be4b6981dc60ca0610b0e61d2ba1f5759e2a3) | feat | expose new `input` API for signal-based inputs ([#53872](https://github.com/angular/angular/pull/53872)) |
|
||||
| [94096c6ede](https://github.com/angular/angular/commit/94096c6ede67436a349ae07901f2bb418bf9f461) | feat | support TypeScript 5.3 ([#52572](https://github.com/angular/angular/pull/52572)) |
|
||||
| [69b384c0d1](https://github.com/angular/angular/commit/69b384c0d16f631741339d8757c32ef08260cfce) | fix | `SignalNode` reactive node incorrectly exposing unset field ([#53571](https://github.com/angular/angular/pull/53571)) |
|
||||
| [6f79507ea7](https://github.com/angular/angular/commit/6f79507ea7f272d8d09250e222ca831f407867d8) | fix | Change defer block fixture default behavior to playthrough ([#53956](https://github.com/angular/angular/pull/53956)) |
|
||||
| [32f908ab70](https://github.com/angular/angular/commit/32f908ab70f1b9ed3f92df1cae05ddde68932404) | fix | do not accidentally inherit input transforms when overridden ([#53571](https://github.com/angular/angular/pull/53571)) |
|
||||
| [bdd61c768a](https://github.com/angular/angular/commit/bdd61c768a28b56c68634b99c036986499829f45) | fix | replace assertion with more intentional error ([#52234](https://github.com/angular/angular/pull/52234)) |
|
||||
| [0daca457bb](https://github.com/angular/angular/commit/0daca457bb5bb6ffe14b7037264f8497eb5b3daf) | fix | TestBed should still use the microtask queue to schedule effects ([#53843](https://github.com/angular/angular/pull/53843)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5c1d441029](https://github.com/angular/angular/commit/5c1d4410298e20cb03d7a1ddf7931538b6a181b4) | feat | Add info property to `NavigationExtras` ([#53303](https://github.com/angular/angular/pull/53303)) |
|
||||
| [50d7916278](https://github.com/angular/angular/commit/50d79162785bb8d3e158a7a4a3733f4c75d3b127) | feat | Add router configuration to resolve navigation promise on error ([#48910](https://github.com/angular/angular/pull/48910)) |
|
||||
| [a5a9b408e2](https://github.com/angular/angular/commit/a5a9b408e2eb64dcf1d3ca16da4897649dd2fc34) | feat | Add transient info to RouterLink input ([#53784](https://github.com/angular/angular/pull/53784)) |
|
||||
| [726530a9af](https://github.com/angular/angular/commit/726530a9af9c8daf7295cc3548f24e70f380d70e) | feat | Allow `onSameUrlNavigation: 'ignore'` in `navigateByUrl` ([#52265](https://github.com/angular/angular/pull/52265)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.9"></a>
|
||||
# 17.0.9 (2024-01-10)
|
||||
### common
|
||||
@@ -30,36 +129,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.5"></a>
|
||||
# 17.1.0-next.5 (2023-12-21)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3a689c2050](https://github.com/angular/angular/commit/3a689c20509ed5972b3831988fc0014d293d0cc3) | fix | correctly intercept index in loop tracking function ([#53604](https://github.com/angular/angular/pull/53604)) |
|
||||
| [df8a825910](https://github.com/angular/angular/commit/df8a825910951bebf34a4eede42f3ce5cd3e6fb7) | fix | project empty block root node ([#53620](https://github.com/angular/angular/pull/53620)) |
|
||||
| [478d622265](https://github.com/angular/angular/commit/478d6222650884478314985e3d5132587c4f670c) | fix | project empty block root node in template pipeline ([#53620](https://github.com/angular/angular/pull/53620)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [aecb675fa5](https://github.com/angular/angular/commit/aecb675fa5059e510e0223e00fa114d92e799b04) | fix | avoid repeated work when parsing version ([#53598](https://github.com/angular/angular/pull/53598)) |
|
||||
| [872e7f25fe](https://github.com/angular/angular/commit/872e7f25fea8a01f980e4e406ad382a9e187ce5c) | fix | tree shake version class ([#53598](https://github.com/angular/angular/pull/53598)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d49333edc3](https://github.com/angular/angular/commit/d49333edc3fe170c57d953aa2d8df58d0db379e0) | fix | cf migration - detect and error when result is invalid i18n nesting ([#53638](https://github.com/angular/angular/pull/53638)) ([#53639](https://github.com/angular/angular/pull/53639)) |
|
||||
| [8e2178792d](https://github.com/angular/angular/commit/8e2178792d474e84817c27851cd6b9600deb15b5) | fix | cf migration - ensure full check runs for all imports ([#53637](https://github.com/angular/angular/pull/53637)) |
|
||||
| [22b95de9bc](https://github.com/angular/angular/commit/22b95de9bcb92267b8f848a1aafa71af70d5577b) | fix | cf migration - fix bug in attribute formatting ([#53636](https://github.com/angular/angular/pull/53636)) |
|
||||
| [b40bb22a66](https://github.com/angular/angular/commit/b40bb22a66a3c2ae478778f3ef0be0ce971a1b2c) | fix | cf migration - improve import declaration handling ([#53622](https://github.com/angular/angular/pull/53622)) |
|
||||
| [8bf752539f](https://github.com/angular/angular/commit/8bf752539f6b4b5955e3d61a76423910af55181b) | fix | cf migration - preserve indentation on attribute strings ([#53625](https://github.com/angular/angular/pull/53625)) |
|
||||
| [7bb312fcf6](https://github.com/angular/angular/commit/7bb312fcf612c57d6606ae14f21707f10d8ff9ce) | fix | cf migration - stop removing empty newlines from i18n blocks ([#53578](https://github.com/angular/angular/pull/53578)) |
|
||||
| [db6b4a6bc4](https://github.com/angular/angular/commit/db6b4a6bc479b0fac0a4a99e1a202c38d1ea8944) | fix | Fix cf migration bug with parsing for loop conditions properly ([#53558](https://github.com/angular/angular/pull/53558)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [502f300757](https://github.com/angular/angular/commit/502f3007575a5445c2876c92548415cb003582b1) | fix | Should not freeze original object used for route data ([#53635](https://github.com/angular/angular/pull/53635)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.8"></a>
|
||||
# 17.0.8 (2023-12-21)
|
||||
### compiler
|
||||
@@ -89,45 +158,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.4"></a>
|
||||
# 17.1.0-next.4 (2023-12-13)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b98d8f79ed](https://github.com/angular/angular/commit/b98d8f79ed4979fb91661dbdfb6266a917b41474) | fix | handle ambient types in input transform function ([#51474](https://github.com/angular/angular/pull/51474)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9e5456912a](https://github.com/angular/angular/commit/9e5456912a699315f1f5e8458d35df946c01dc12) | fix | generate less type checking code in for loops ([#53515](https://github.com/angular/angular/pull/53515)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2565121851](https://github.com/angular/angular/commit/25651218512becb3a491b1c94d643a5066a6d3cb) | fix | Avoid refreshing a host view twice when using transplanted views ([#53021](https://github.com/angular/angular/pull/53021)) |
|
||||
| [629343f247](https://github.com/angular/angular/commit/629343f24741760e76d98ea1005debaf4775bfc7) | fix | Multiple subscribers to ApplicationRef.isStable should all see values ([#53541](https://github.com/angular/angular/pull/53541)) |
|
||||
| [42f4f70e97](https://github.com/angular/angular/commit/42f4f70e97b47f7ffcf15e8af2c1a3fa3f393903) | fix | remove signal equality check short-circuit ([#53446](https://github.com/angular/angular/pull/53446)) |
|
||||
| [f35adcb9b2](https://github.com/angular/angular/commit/f35adcb9b255741515d54bbce694f4cd34aac249) | fix | update feature usage marker ([#53542](https://github.com/angular/angular/pull/53542)) |
|
||||
| [1fc5442947](https://github.com/angular/angular/commit/1fc5442947b07be7c11fe7c79b9e69f9458c8108) | perf | avoid changes Observable creation on QueryList ([#53498](https://github.com/angular/angular/pull/53498)) |
|
||||
| [e3a6bf9b6c](https://github.com/angular/angular/commit/e3a6bf9b6c3bef03df9bfc8f05b817bc875cbad6) | perf | optimize memory allocation when reconcilling lists ([#52245](https://github.com/angular/angular/pull/52245)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a02767956a](https://github.com/angular/angular/commit/a02767956a00e0b44b690411f01584f6660c83ea) | fix | CF Migration - ensure bound ngIfElse cases ignore line breaks ([#53435](https://github.com/angular/angular/pull/53435)) |
|
||||
| [6aa1bb78e8](https://github.com/angular/angular/commit/6aa1bb78e8b9ca866b3c2d84f4005a0e67f2b6bc) | fix | cf migration - undo changes when html fails to parse post migration ([#53530](https://github.com/angular/angular/pull/53530)) |
|
||||
| [cc02852ac4](https://github.com/angular/angular/commit/cc02852ac44bfea13e8b9d5768694a094fc2c4b5) | fix | CF migration only remove newlines of changed template content ([#53508](https://github.com/angular/angular/pull/53508)) |
|
||||
| [ce1076785c](https://github.com/angular/angular/commit/ce1076785c98ecc9660637cafa4a62a63be8d315) | fix | cf migration validate structure of ngswitch before migrating ([#53530](https://github.com/angular/angular/pull/53530)) |
|
||||
| [1f5c8bf116](https://github.com/angular/angular/commit/1f5c8bf116783c25234ab7fa301a0be842e58007) | fix | ensure we do not overwrite prior template replacements in migration ([#53393](https://github.com/angular/angular/pull/53393)) |
|
||||
| [79f791543b](https://github.com/angular/angular/commit/79f791543b607eea1bb6a28b9c744760ba4fd028) | fix | fix cf migration import removal when errors occur ([#53502](https://github.com/angular/angular/pull/53502)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fdb9cb7a5b](https://github.com/angular/angular/commit/fdb9cb7a5be4695abaa60efc89ecd50ddb9e9e6e) | fix | Get correct base path when using "." as base href when serving from the file:// protocol. ([#53547](https://github.com/angular/angular/pull/53547)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [48c5041687](https://github.com/angular/angular/commit/48c50416872313f23d2759232c990cf8d2de6996) | fix | provide more actionable error message when route is not matched in production mode ([#53523](https://github.com/angular/angular/pull/53523)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.7"></a>
|
||||
# 17.0.7 (2023-12-13)
|
||||
### compiler
|
||||
@@ -167,47 +197,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.3"></a>
|
||||
# 17.1.0-next.3 (2023-12-06)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5613051a8b](https://github.com/angular/angular/commit/5613051a8bd2626ae347292807b2bf21085c4c02) | fix | allow TS jsDocParsingMode host option to be programmatically set again ([#53292](https://github.com/angular/angular/pull/53292)) |
|
||||
| [77ac4cd324](https://github.com/angular/angular/commit/77ac4cd32491d0c994cb4ea50372601c955cec3d) | fix | generate proper code for nullish coalescing in styling host bindings ([#53305](https://github.com/angular/angular/pull/53305)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e620b3a724](https://github.com/angular/angular/commit/e620b3a724cb615af24b7779c0ab492d24efb8cc) | fix | add compiler option to disable control flow content projection diagnostic ([#53311](https://github.com/angular/angular/pull/53311)) |
|
||||
| [d7a83f9521](https://github.com/angular/angular/commit/d7a83f95213cdd5d3ceefbc95fa1190856b0198c) | fix | avoid conflicts with built-in global variables in for loop blocks ([#53319](https://github.com/angular/angular/pull/53319)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [77939a3bd3](https://github.com/angular/angular/commit/77939a3bd39073d07e24797a4632ec2d2a6b92e0) | fix | cleanup signal consumers for all views ([#53351](https://github.com/angular/angular/pull/53351)) |
|
||||
| [899f6c4a12](https://github.com/angular/angular/commit/899f6c4a12127f87aeedf47ee128ce949ebe717c) | fix | handle hydration of multiple nodes projected in a single slot ([#53270](https://github.com/angular/angular/pull/53270)) |
|
||||
| [4b23221b4e](https://github.com/angular/angular/commit/4b23221b4e5f8be7bcffc8ace255143653550d3d) | fix | support hydration for cases when content is re-projected using ng-template ([#53304](https://github.com/angular/angular/pull/53304)) |
|
||||
| [82609d471c](https://github.com/angular/angular/commit/82609d471c9802b847a5654918eca1ba3ebb29b3) | fix | support swapping hydrated views in `@for` loops ([#53274](https://github.com/angular/angular/pull/53274)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1c1e8c477b](https://github.com/angular/angular/commit/1c1e8c477b8d5c8deecf05744bd1d5f7c86d2e14) | fix | CF migration - ensure NgIfElse attributes are properly removed ([#53298](https://github.com/angular/angular/pull/53298)) |
|
||||
| [2998d482dd](https://github.com/angular/angular/commit/2998d482dd3f1f5ff7f08260c3947ded74dac126) | fix | CF Migration - Fix case of aliases on i18n ng-templates preventing removal ([#53299](https://github.com/angular/angular/pull/53299)) |
|
||||
| [aad5e5bd0e](https://github.com/angular/angular/commit/aad5e5bd0e7f6581f51fc3a23c98a7f11219a8f8) | fix | CF Migration add support for ngIf with just a then ([#53297](https://github.com/angular/angular/pull/53297)) |
|
||||
| [6f75471307](https://github.com/angular/angular/commit/6f75471307a9458d0cffd0ee2bbf4190640c3c3a) | fix | CF Migration fix missing alias for bound ngifs ([#53296](https://github.com/angular/angular/pull/53296)) |
|
||||
| [2a5a8f6f05](https://github.com/angular/angular/commit/2a5a8f6f052961c010a68a05d868f50220f2fcf2) | fix | Change CF Migration ng-template placeholder generation and handling ([#53394](https://github.com/angular/angular/pull/53394)) |
|
||||
| [03e2f1bb25](https://github.com/angular/angular/commit/03e2f1bb25693d1a5f4e53fc4f4cd1937cf6bda1) | fix | fix regexp for else and then in cf migration ([#53257](https://github.com/angular/angular/pull/53257)) |
|
||||
| [f4a96a9160](https://github.com/angular/angular/commit/f4a96a9160927903c38e172f6375c4bc5f8e0905) | fix | handle aliases on bound ngIf migrations ([#53261](https://github.com/angular/angular/pull/53261)) |
|
||||
| [5a0ed28c9d](https://github.com/angular/angular/commit/5a0ed28c9d3f1c7507feee482e37c3346d52b033) | fix | handle nested ng-template replacement safely in CF migration ([#53368](https://github.com/angular/angular/pull/53368)) |
|
||||
| [01b18a4248](https://github.com/angular/angular/commit/01b18a4248f068df33c0ca8a2d62ef2fc69f941c) | fix | handle templates outside of component in cf migration ([#53368](https://github.com/angular/angular/pull/53368)) |
|
||||
| [9834fd2738](https://github.com/angular/angular/commit/9834fd27387ed5edc65bed56aa003fc45d250420) | fix | remove setting that removes comments in CF migration ([#53350](https://github.com/angular/angular/pull/53350)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5c1d441029](https://github.com/angular/angular/commit/5c1d4410298e20cb03d7a1ddf7931538b6a181b4) | feat | Add info property to `NavigationExtras` ([#53303](https://github.com/angular/angular/pull/53303)) |
|
||||
| [50d7916278](https://github.com/angular/angular/commit/50d79162785bb8d3e158a7a4a3733f4c75d3b127) | feat | Add router configuration to resolve navigation promise on error ([#48910](https://github.com/angular/angular/pull/48910)) |
|
||||
| [1940280d27](https://github.com/angular/angular/commit/1940280d27bb3ece585d6345dbd742d208f46912) | fix | Ensure canMatch guards run on wildcard routes ([#53239](https://github.com/angular/angular/pull/53239)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.6"></a>
|
||||
# 17.0.6 (2023-12-06)
|
||||
### compiler
|
||||
@@ -247,43 +236,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.2"></a>
|
||||
# 17.1.0-next.2 (2023-11-29)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [79ff91a813](https://github.com/angular/angular/commit/79ff91a813e544929cb5eb5f9aab762a9f3d0435) | fix | allow TS jsDocParsingMode host option to be programmatically set ([#53126](https://github.com/angular/angular/pull/53126)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4c1d69e288](https://github.com/angular/angular/commit/4c1d69e2880f22745c820eee630d10071e4fa86b) | fix | add diagnostic for control flow that prevents content projection ([#53190](https://github.com/angular/angular/pull/53190)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [58cf389d80](https://github.com/angular/angular/commit/58cf389d8095dd522a998b6b9a7d7b8da1656644) | fix | avoid stale provider info when TestBed.overrideProvider is used ([#52918](https://github.com/angular/angular/pull/52918)) |
|
||||
| [c7c7ea9813](https://github.com/angular/angular/commit/c7c7ea9813f6dcf91c096bb37d36bfe0c715a04f) | fix | inherit host directives ([#52992](https://github.com/angular/angular/pull/52992)) |
|
||||
| [b35c6731e5](https://github.com/angular/angular/commit/b35c6731e51de9c33707010fc780cbaa559be6c3) | fix | Reattached views that are dirty from a signal update should refresh ([#53001](https://github.com/angular/angular/pull/53001)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dbca1c9d61](https://github.com/angular/angular/commit/dbca1c9d618be4d195d779ef80606c6d22f7c977) | fix | Add ngForTemplate support to control flow migration ([#53076](https://github.com/angular/angular/pull/53076)) |
|
||||
| [53912fdf74](https://github.com/angular/angular/commit/53912fdf74e1224f95edc3dd550c51451e613c44) | fix | allows colons in ngIf else cases to migrate ([#53076](https://github.com/angular/angular/pull/53076)) |
|
||||
| [fadfee4324](https://github.com/angular/angular/commit/fadfee43247acec7e450d5cc929a0a6780a54bd1) | fix | cf migration fix migrating empty switch default ([#53237](https://github.com/angular/angular/pull/53237)) |
|
||||
| [b2aeaf5d97](https://github.com/angular/angular/commit/b2aeaf5d97327842a5bb657e9f02bb4f1358304b) | fix | CF migration log warning when collection aliasing detected in `@for` ([#53238](https://github.com/angular/angular/pull/53238)) |
|
||||
| [c6326289f8](https://github.com/angular/angular/commit/c6326289f87089b3415ba0f3e371206b8a396b66) | fix | cf migration removes unnecessary bound ngifelse attribute ([#53236](https://github.com/angular/angular/pull/53236)) |
|
||||
| [e6f10e81d2](https://github.com/angular/angular/commit/e6f10e81d2486b5cc1f468777b7e1057d3f09dc5) | fix | control flow migration formatting fixes ([#53076](https://github.com/angular/angular/pull/53076)) |
|
||||
| [6291c8db09](https://github.com/angular/angular/commit/6291c8db092c0ab67f6789cc03c19dfa0bdc251d) | fix | fix off by one issue with template removal in CF migration ([#53255](https://github.com/angular/angular/pull/53255)) |
|
||||
| [f1b7d40057](https://github.com/angular/angular/commit/f1b7d400575a6a02a2fc2b642c2b8c15cca9b3c4) | fix | fixes CF migration i18n ng-template offsets ([#53212](https://github.com/angular/angular/pull/53212)) |
|
||||
| [a738b48717](https://github.com/angular/angular/commit/a738b48717e16613b34c3e50480cd49f2a31858f) | fix | fixes control flow migration common module removal ([#53076](https://github.com/angular/angular/pull/53076)) |
|
||||
| [a3599515bb](https://github.com/angular/angular/commit/a3599515bb2513fbcb2899284c7f6b4bc021ddaf) | fix | properly handle ngIfThen cases in CF migration ([#53256](https://github.com/angular/angular/pull/53256)) |
|
||||
| [8a52674faa](https://github.com/angular/angular/commit/8a52674faacefd4042726383fdf0aed59a04fb7e) | fix | Update CF migration to skip templates with duplicate ng-template names ([#53204](https://github.com/angular/angular/pull/53204)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [29e0834c4d](https://github.com/angular/angular/commit/29e0834c4deecfa8bf384b5e4359796c8123afcd) | fix | Resolvers in different parts of the route tree should be able to execute together ([#52934](https://github.com/angular/angular/pull/52934)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.5"></a>
|
||||
# 17.0.5 (2023-11-29)
|
||||
### core
|
||||
@@ -313,39 +265,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.1"></a>
|
||||
# 17.1.0-next.1 (2023-11-20)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [29c5416d14](https://github.com/angular/angular/commit/29c5416d14638a05a894269aa5dbe67e98754418) | fix | remove `load` on image once it fails to load ([#52990](https://github.com/angular/angular/pull/52990)) |
|
||||
| [7affa57754](https://github.com/angular/angular/commit/7affa5775427e92ef6e949c879765b7c8aa172da) | fix | scan images once page is loaded ([#52991](https://github.com/angular/angular/pull/52991)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ec2d6e7b9c](https://github.com/angular/angular/commit/ec2d6e7b9c2b386247d1320ee89f8e3ac5e5a0dd) | fix | changed after checked error in for loops ([#52935](https://github.com/angular/angular/pull/52935)) |
|
||||
| [406049b95e](https://github.com/angular/angular/commit/406049b95e5234f17a7a18839ac848640f53fdde) | fix | generate i18n instructions for blocks ([#52958](https://github.com/angular/angular/pull/52958)) |
|
||||
| [d9d566d315](https://github.com/angular/angular/commit/d9d566d31540582d73201675d0b8ed901261669e) | fix | nested for loops incorrectly calculating computed variables ([#52931](https://github.com/angular/angular/pull/52931)) |
|
||||
| [5fb707f81a](https://github.com/angular/angular/commit/5fb707f81aee43751e61d2ed0861afc9b85bc85a) | fix | produce placeholder for blocks in i18n bundles ([#52958](https://github.com/angular/angular/pull/52958)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b4d022e230](https://github.com/angular/angular/commit/b4d022e230ca141b12437949d11dc384bfe5c082) | fix | add diagnostic for control flow that prevents content projection ([#52726](https://github.com/angular/angular/pull/52726)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ed0fbd4071](https://github.com/angular/angular/commit/ed0fbd4071339b1af22d82bac07d51c6c41790cd) | fix | cleanup loading promise when no dependencies are defined ([#53031](https://github.com/angular/angular/pull/53031)) |
|
||||
| [1ce31d819b](https://github.com/angular/angular/commit/1ce31d819b2e4f4425a41f07167a6edce98e77e1) | fix | handle local refs when `getDeferBlocks` is invoked in tests ([#52973](https://github.com/angular/angular/pull/52973)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e33f6e0f1a](https://github.com/angular/angular/commit/e33f6e0f1a483cad908fa6d7376d62332797499c) | fix | control flow migration fails for async pipe with unboxing of observable ([#52756](https://github.com/angular/angular/pull/52756)) ([#52972](https://github.com/angular/angular/pull/52972)) |
|
||||
| [5564d020cd](https://github.com/angular/angular/commit/5564d020cdcea8273b65cf69c45c3f935195af66) | fix | Fixes control flow migration if then else case ([#53006](https://github.com/angular/angular/pull/53006)) |
|
||||
| [28f6cbf9c9](https://github.com/angular/angular/commit/28f6cbf9c91f957b4926fe34610387e1f1919d4f) | fix | fixes migrations of nested switches in control flow ([#53010](https://github.com/angular/angular/pull/53010)) |
|
||||
| [e090b48bf8](https://github.com/angular/angular/commit/e090b48bf8534761d46523be57a7889a325bcdec) | fix | tweaks to formatting in control flow migration ([#53058](https://github.com/angular/angular/pull/53058)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.4"></a>
|
||||
# 17.0.4 (2023-11-20)
|
||||
### common
|
||||
@@ -379,24 +298,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0-next.0"></a>
|
||||
# 17.1.0-next.0 (2023-11-15)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [56a76d73e0](https://github.com/angular/angular/commit/56a76d73e037aeea1975808d5c51608fd23d4fa6) | fix | modify `getConstructorDependencies` helper to work with reflection host after the previous change ([#52215](https://github.com/angular/angular/pull/52215)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [94096c6ede](https://github.com/angular/angular/commit/94096c6ede67436a349ae07901f2bb418bf9f461) | feat | support TypeScript 5.3 ([#52572](https://github.com/angular/angular/pull/52572)) |
|
||||
| [bdd61c768a](https://github.com/angular/angular/commit/bdd61c768a28b56c68634b99c036986499829f45) | fix | replace assertion with more intentional error ([#52234](https://github.com/angular/angular/pull/52234)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [726530a9af](https://github.com/angular/angular/commit/726530a9af9c8daf7295cc3548f24e70f380d70e) | feat | Allow `onSameUrlNavigation: 'ignore'` in `navigateByUrl` ([#52265](https://github.com/angular/angular/pull/52265)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.0.3"></a>
|
||||
# 17.0.3 (2023-11-15)
|
||||
### animations
|
||||
@@ -489,17 +390,16 @@ Live long and prosper 🖖🏻
|
||||
|
||||
Node.js v16 is planned to be End-of-Life on 2023-09-11. Angular will stop supporting Node.js v16 in Angular v17. For Node.js release schedule details, please see: https://github.com/nodejs/release#release-schedule
|
||||
### common
|
||||
-
|
||||
- the NgSwitch directive now defaults to the === equality operator,
|
||||
migrating from the previously used ==. NgSwitch expressions and / or
|
||||
migrating from the previously used == operator. NgSwitch expressions and / or
|
||||
individual condition values need adjusting to this stricter equality
|
||||
check. The added warning message should help pinpointing NgSwitch
|
||||
usages where adjustements are needed.
|
||||
check. The added warning message should help pin-pointing NgSwitch
|
||||
usages where adjustments are needed.
|
||||
### core
|
||||
- Angular now required `zone.js` version `~0.14.0`
|
||||
- Angular now requires `zone.js` version `~0.14.0`
|
||||
- Versions of TypeScript older than 5.2 are no longer supported.
|
||||
- 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
|
||||
dropped from the public API surface. As an alternative, please use the `update` method and
|
||||
make immutable changes to the object.
|
||||
|
||||
Example before:
|
||||
@@ -597,7 +497,7 @@ Live long and prosper 🖖🏻
|
||||
- Swapping out the context object for `EmbeddedViewRef`
|
||||
is no longer supported. Support for this was introduced with v12.0.0, but
|
||||
this pattern is rarely used. There is no replacement, but you can use
|
||||
simple assignments in most cases, or `Object.assign , or alternatively
|
||||
simple assignments in most cases, or `Object.assign` , or alternatively
|
||||
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
|
||||
as an example).
|
||||
|
||||
|
||||
@@ -61,6 +61,25 @@ Get started with Angular, learn the fundamentals and explore advanced topics on
|
||||
- [Lazy Loading][lazyloading]
|
||||
- [Animations][animations]
|
||||
|
||||
### Local Development
|
||||
|
||||
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
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -196,10 +196,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "7a90567717c3417a23ff4b21963a698a6e9aa669ac9e682121ea33f218a2816a",
|
||||
strip_prefix = "rules_sass-425ecafa8268bc013d684216363fe75bc802323e",
|
||||
sha256 = "386ef2b97bd4342e45db450ce7eb5acb343d22f7580c0bbae89186dc009fa14e",
|
||||
strip_prefix = "rules_sass-d970cb53ad159e7fd1d3a99a00a530cc2c83eff9",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/425ecafa8268bc013d684216363fe75bc802323e.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/d970cb53ad159e7fd1d3a99a00a530cc2c83eff9.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+66
-3
@@ -1,6 +1,7 @@
|
||||
load("//:packages.bzl", "link_packages")
|
||||
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")
|
||||
load("@npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
@@ -21,6 +22,13 @@ APPLICATION_FILES = [
|
||||
],
|
||||
)
|
||||
|
||||
TEST_FILES = APPLICATION_FILES + [
|
||||
"karma.conf.js",
|
||||
"tsconfig.spec.json",
|
||||
] + glob(
|
||||
["**/*.spec.ts"],
|
||||
)
|
||||
|
||||
APPLICATION_DEPS = link_packages([
|
||||
"@npm//@angular-devkit/build-angular",
|
||||
"@npm//@angular/animations",
|
||||
@@ -69,17 +77,56 @@ APPLICATION_DEPS = link_packages([
|
||||
"@npm//angular-split",
|
||||
])
|
||||
|
||||
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",
|
||||
"@npm//jasmine",
|
||||
"@npm//jasmine-core",
|
||||
"@npm//karma-chrome-launcher",
|
||||
"@npm//karma-coverage",
|
||||
"@npm//karma-jasmine",
|
||||
"@npm//karma-jasmine-html-reporter",
|
||||
"//aio/tools:windows-chromium-path",
|
||||
])
|
||||
|
||||
copy_to_bin(
|
||||
name = "application_files_bin",
|
||||
srcs = APPLICATION_FILES,
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "fast_build_mode",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "fast",
|
||||
flag_values = {
|
||||
":fast_build_mode": "true",
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "full",
|
||||
flag_values = {
|
||||
":fast_build_mode": "false",
|
||||
},
|
||||
)
|
||||
|
||||
config_based_architect_flags = select({
|
||||
":fast": ["--no-prerender"],
|
||||
":full": ["--prerender"],
|
||||
})
|
||||
|
||||
architect(
|
||||
name = "build",
|
||||
args = [
|
||||
"angular-dev:build",
|
||||
"--output-path=build-app",
|
||||
],
|
||||
"--output-path=build",
|
||||
] + config_based_architect_flags,
|
||||
chdir = "$(RULEDIR)",
|
||||
data = APPLICATION_DEPS + [
|
||||
":application_files_bin",
|
||||
@@ -100,3 +147,19 @@ architect(
|
||||
":application_files_bin",
|
||||
],
|
||||
)
|
||||
|
||||
architect_test(
|
||||
name = "test",
|
||||
args = [
|
||||
"angular-dev:test",
|
||||
"--no-watch",
|
||||
],
|
||||
chdir = package_name(),
|
||||
data = TEST_DEPS + TEST_FILES,
|
||||
env = {
|
||||
"CHROME_BIN": "../$(CHROMIUM)",
|
||||
},
|
||||
toolchains = [
|
||||
"@npm//@angular/build-tooling/bazel/browsers/chromium:toolchain_alias",
|
||||
],
|
||||
)
|
||||
|
||||
+1
-2
@@ -26,8 +26,6 @@
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
"server": "src/main.server.ts",
|
||||
// TODO(josephperrott): enabled prerender
|
||||
"prerender": false,
|
||||
"polyfills": ["src/polyfills.ts", "zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
@@ -89,6 +87,7 @@
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"include": ["src/app"],
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["@angular/docs/styles/global-styles.scss"],
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"hosting": {
|
||||
"target": "angular-docs",
|
||||
"public": "./build/browser",
|
||||
"ignore": ["**/.*"],
|
||||
"headers": [
|
||||
{
|
||||
"source": "assets/tutorials/common/*.jpg",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cross-Origin-Resource-Policy",
|
||||
"value": "cross-origin"
|
||||
},
|
||||
{
|
||||
"key": "Access-Control-Allow-Origin",
|
||||
"value": "*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "public,max-age=31536000,immutable"
|
||||
},
|
||||
{
|
||||
"key": "Access-Control-Allow-Origin",
|
||||
"value": "*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/[0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].js",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cross-Origin-Embedder-Policy",
|
||||
"value": "require-corp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/@(ngsw-worker.js|ngsw.json)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/**",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cross-Origin-Opener-Policy",
|
||||
"value": "same-origin"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "Cross-Origin-Embedder-Policy",
|
||||
"value": "require-corp"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
const {getAdjustedChromeBinPathForWindows} = require('../aio/tools/windows-chromium-path');
|
||||
|
||||
process.env.CHROME_BIN = getAdjustedChromeBinPathForWindows();
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
{'reporter:jasmine-seed': ['type', JasmineSeedReporter]},
|
||||
],
|
||||
proxies: {
|
||||
'/dummy/image': 'src/assets/images/logos/angular/angular.png',
|
||||
},
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
random: true,
|
||||
seed: '',
|
||||
},
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/site'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'text-summary' }
|
||||
],
|
||||
},
|
||||
reporters: ['progress', 'kjhtml', 'jasmine-seed'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
base: 'ChromeHeadless',
|
||||
// See /integration/README.md#browser-tests for more info on these args
|
||||
flags: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio'],
|
||||
},
|
||||
},
|
||||
browsers: ['ChromeHeadlessNoSandbox'],
|
||||
browserNoActivityTimeout: 60000,
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
|
||||
// Helpers
|
||||
function JasmineSeedReporter(baseReporterDecorator) {
|
||||
baseReporterDecorator(this);
|
||||
|
||||
this.onBrowserComplete = (browser, result) => {
|
||||
const seed = result.order && result.order.random && result.order.seed;
|
||||
if (seed) this.write(`${browser}: Randomized with seed ${seed}.\n`);
|
||||
};
|
||||
|
||||
this.onRunComplete = () => undefined;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
@if (displaySecondaryNav()) {
|
||||
<adev-secondary-navigation />
|
||||
}
|
||||
<div class="adev-app-main-content">
|
||||
<div class="docs-app-main-content">
|
||||
<!--
|
||||
Avoid rendering cookies popup on the server,
|
||||
since there is no benefit of doing this and
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
// If navs are open, render a blurry background over content
|
||||
&:has(.adev-nav-secondary--open),
|
||||
&:has(.docs-nav-secondary--open),
|
||||
&:has(.adev-nav-primary--open) {
|
||||
.adev-app-main-content {
|
||||
.docs-app-main-content {
|
||||
&::after {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-app-main-content {
|
||||
.docs-app-main-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
|
||||
<nav
|
||||
class="adev-nav-primary adev-scroll-hide"
|
||||
class="adev-nav-primary docs-scroll-hide"
|
||||
[class.adev-nav-primary--open]="isMobileNavigationOpened()"
|
||||
>
|
||||
<button
|
||||
@@ -126,7 +126,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Version picker for v18+ -->
|
||||
<!-- <div class="adev-nav-item">
|
||||
<div class="adev-nav-item">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Select Angular version"
|
||||
@@ -166,7 +166,7 @@
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
</div> -->
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Search -->
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
|
||||
|
||||
import {ProgressBarComponent} from './progress-bar.component';
|
||||
import {PROGRESS_BAR_DELAY, ProgressBarComponent} from './progress-bar.component';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
|
||||
describe('ProgressBarComponent', () => {
|
||||
let component: ProgressBarComponent;
|
||||
@@ -16,7 +17,7 @@ describe('ProgressBarComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProgressBarComponent],
|
||||
imports: [ProgressBarComponent, RouterTestingModule],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProgressBarComponent);
|
||||
@@ -24,7 +25,13 @@ describe('ProgressBarComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should call progressBar.complete() on route change', fakeAsync(async () => {
|
||||
const progressBarCompleteSpy = spyOn(component.progressBar, 'complete');
|
||||
|
||||
const harness = await RouterTestingHarness.create();
|
||||
await harness.navigateByUrl('/');
|
||||
|
||||
tick(PROGRESS_BAR_DELAY);
|
||||
expect(progressBarCompleteSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import {filter, map, switchMap, take} from 'rxjs/operators';
|
||||
|
||||
/** Time to wait after navigation starts before showing the progress bar. This delay allows a small amount of time to skip showing the progress bar when a navigation is effectively immediate. 30ms is approximately the amount of time we can wait before a delay is perceptible.*/
|
||||
const PROGRESS_BAR_DELAY = 30;
|
||||
export const PROGRESS_BAR_DELAY = 30;
|
||||
|
||||
@Component({
|
||||
selector: 'adev-progress-bar',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div [attr.id]="SECONDARY_NAV_ID" class="adev-secondary-nav-mask" [class.adev-nav-secondary--open]="isSecondaryNavVisible()" (docsClickOutside)="close()" [docsClickOutsideIgnore]="[PRIMARY_NAV_ID]">
|
||||
<div class="adev-nav-secondary adev-scroll-track-transparent" [style.transform]="translateX()" [style.transition]="transition">
|
||||
<div [attr.id]="SECONDARY_NAV_ID" class="adev-secondary-nav-mask" [class.docs-nav-secondary--open]="isSecondaryNavVisible()" (docsClickOutside)="close()" [docsClickOutsideIgnore]="[PRIMARY_NAV_ID]">
|
||||
<div class="docs-nav-secondary docs-scroll-track-transparent" [style.transform]="translateX()" [style.transition]="transition">
|
||||
<!-- Secondary Nav -->
|
||||
@if (navigationItems && navigationItems.length > 0) {
|
||||
<docs-navigation-list
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
transform: translateX(0);
|
||||
z-index: 99;
|
||||
transition: transform 0.3s ease;
|
||||
&:has(.adev-nav-secondary--open) {
|
||||
&:has(.docs-nav-secondary--open) {
|
||||
transform: translateX(82px);
|
||||
transition: transform 0.3s ease-in 0.3s;
|
||||
}
|
||||
@@ -46,7 +46,7 @@
|
||||
@include mq.for-tablet-landscape-down {
|
||||
transform: translateX(-100%);
|
||||
|
||||
&.adev-nav-secondary--open {
|
||||
&.docs-nav-secondary--open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@
|
||||
// exit immediately
|
||||
transition: transform 0.45s ease-in;
|
||||
|
||||
&.adev-nav-secondary--open {
|
||||
&.docs-nav-secondary--open {
|
||||
transform: translateX(0);
|
||||
// enter delayed
|
||||
transition: transform 0.45s ease-out 0.2s;
|
||||
@@ -64,8 +64,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
// seconday nav - translated on x to display levels
|
||||
.adev-nav-secondary {
|
||||
// secondary nav - translated on x to display levels
|
||||
.docs-nav-secondary {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: var(--secondary-nav-width);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Injector} from '@angular/core';
|
||||
import {WINDOW} from '@angular/docs';
|
||||
import {ENVIRONMENT, WINDOW} from '@angular/docs';
|
||||
import {AnalyticsService} from './analytics.service';
|
||||
|
||||
describe('AnalyticsService', () => {
|
||||
@@ -36,6 +36,7 @@ describe('AnalyticsService', () => {
|
||||
|
||||
injector = Injector.create({
|
||||
providers: [
|
||||
{provide: ENVIRONMENT, useValue: {}},
|
||||
{provide: AnalyticsService, deps: [WINDOW]},
|
||||
{provide: WINDOW, useFactory: () => mockWindow, deps: []},
|
||||
],
|
||||
|
||||
@@ -45,7 +45,7 @@ export class CustomErrorHandler implements ErrorHandler {
|
||||
openErrorSnackBar(): void {
|
||||
this.snackBar
|
||||
.openFromComponent(ErrorSnackBar, {
|
||||
panelClass: 'adev-invert-mode',
|
||||
panelClass: 'docs-invert-mode',
|
||||
data: {
|
||||
message: `Our docs have been updated, reload the page to see the latest.`,
|
||||
actionText: `Reload`,
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface ErrorSnackBarData {
|
||||
template: `
|
||||
{{ message }}
|
||||
<button
|
||||
class="adev-primary-btn"
|
||||
class="docs-primary-btn"
|
||||
type="button"
|
||||
matSnackBarAction
|
||||
[attr.text]="actionText"
|
||||
|
||||
@@ -14,8 +14,8 @@ import {Subject} from 'rxjs';
|
||||
// Keep these constants in sync with the code in index.html
|
||||
|
||||
export const THEME_PREFERENCE_LOCAL_STORAGE_KEY = 'themePreference';
|
||||
export const DARK_MODE_CLASS_NAME = 'adev-dark-mode';
|
||||
export const LIGHT_MODE_CLASS_NAME = 'adev-light-mode';
|
||||
export const DARK_MODE_CLASS_NAME = 'docs-dark-mode';
|
||||
export const LIGHT_MODE_CLASS_NAME = 'docs-light-mode';
|
||||
export const PREFERS_COLOR_SCHEME_DARK = '(prefers-color-scheme: dark)';
|
||||
|
||||
export type Theme = 'dark' | 'light' | 'auto';
|
||||
@@ -38,13 +38,13 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
this.loadThemePreference();
|
||||
this.watchPreferedColorScheme();
|
||||
this.watchPreferredColorScheme();
|
||||
}
|
||||
|
||||
setTheme(theme: Theme): void {
|
||||
this.theme.set(theme);
|
||||
this.setThemeInLocalStorage();
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferedScheme() : theme);
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferredScheme() : theme);
|
||||
}
|
||||
|
||||
// 1. Read theme preferences stored in localStorage
|
||||
@@ -54,7 +54,7 @@ export class ThemeManager {
|
||||
const useTheme = savedUserPreference ?? 'auto';
|
||||
|
||||
this.theme.set(useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferedScheme() : useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferredScheme() : useTheme);
|
||||
}
|
||||
|
||||
// Set theme classes on the body element
|
||||
@@ -81,14 +81,14 @@ export class ThemeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private watchPreferedColorScheme() {
|
||||
private watchPreferredColorScheme() {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
|
||||
const preferedScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferedScheme);
|
||||
const preferredScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferredScheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function preferedScheme(): 'dark' | 'light' {
|
||||
function preferredScheme(): 'dark' | 'light' {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
@@ -10,22 +10,70 @@ import {Injectable, VERSION, computed, signal} from '@angular/core';
|
||||
|
||||
// TODO(josephperrott): extract this out of the file into a managed location.
|
||||
const VERSIONS_CONFIG = {
|
||||
currentVersion: "stable",
|
||||
historicalVersionsLinkPattern: "https://v{{version}}.angular.dev",
|
||||
currentVersion: 'stable',
|
||||
historicalVersionsLinkPattern: 'https://v{{version}}.angular.dev',
|
||||
mainVersions: [
|
||||
{
|
||||
version: "stable",
|
||||
url: "https://angular.dev"
|
||||
version: 'stable',
|
||||
url: 'https://angular.dev',
|
||||
},
|
||||
{
|
||||
version: "rc",
|
||||
url: "https://rc.angular.dev"
|
||||
version: 'v16',
|
||||
url: 'https://v16.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: "next",
|
||||
url: "https://next.angular.dev"
|
||||
}
|
||||
]
|
||||
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 {
|
||||
|
||||
@@ -95,7 +95,7 @@ export class AlertManager {
|
||||
}
|
||||
|
||||
this.snackBar.openFromComponent(ErrorSnackBar, {
|
||||
panelClass: 'adev-invert-mode',
|
||||
panelClass: 'docs-invert-mode',
|
||||
data: {
|
||||
message,
|
||||
actionText: 'I understand',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- Code Editor Tabs -->
|
||||
<div class="adev-code-editor-tabs">
|
||||
<div class="docs-code-editor-tabs">
|
||||
<div class="adev-tabs-and-plus">
|
||||
<mat-tab-group animationDuration="0ms" mat-stretch-tabs="false">
|
||||
<!--
|
||||
@@ -13,7 +13,7 @@
|
||||
{{ file.filename.replace('src/', '') }}
|
||||
@if (tab.isActive && canDeleteFile(file.filename)) {
|
||||
<button
|
||||
class="adev-delete-file"
|
||||
class="docs-delete-file"
|
||||
aria-label="Delete file"
|
||||
(click)="deleteFile(file.filename)"
|
||||
>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.adev-code-editor-tabs {
|
||||
.docs-code-editor-tabs {
|
||||
display: flex;
|
||||
background: var(--octonary-contrast);
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
|
||||
.adev-add-file,
|
||||
.adev-delete-file {
|
||||
.docs-delete-file {
|
||||
docs-icon {
|
||||
color: var(--gray-400);
|
||||
transition: color 0.3s ease;
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-delete-file {
|
||||
.docs-delete-file {
|
||||
padding-inline-start: 0.1rem;
|
||||
padding-inline-end: 0;
|
||||
margin-block-start: 0.2rem;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {EmbeddedTutorialManager} from '../embedded-tutorial-manager.service';
|
||||
|
||||
import {CodeEditor, REQUIRED_FILES} from './code-editor.component';
|
||||
import {CodeMirrorEditor} from './code-mirror-editor.service';
|
||||
import {FakeChangeDetectorRef} from '../../../../../shared/src/lib/utils/test-utils.spec';
|
||||
import {FakeChangeDetectorRef} from '@angular/docs/testing';
|
||||
import {TutorialType} from '@angular/docs';
|
||||
|
||||
const files = [
|
||||
|
||||
@@ -66,7 +66,7 @@ export const getTooltipExtension = (
|
||||
dom: tooltip,
|
||||
|
||||
// Note: force the tooltip to scroll to the top on mount and on position change
|
||||
// because depending on the position of the mouse and the siez of the tooltip content,
|
||||
// because depending on the position of the mouse and the size of the tooltip content,
|
||||
// the tooltip might render with its initial scroll position on the bottom
|
||||
mount: (_) => forceTooltipScrollTop(),
|
||||
positioned: (_) => forceTooltipScrollTop(),
|
||||
@@ -92,7 +92,7 @@ function forceTooltipScrollTop() {
|
||||
|
||||
function getMarkedHtmlFromString(content: string): HTMLDivElement {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = marked(content);
|
||||
wrapper.innerHTML = marked(content) as string;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ function getTagsHtml(tags: JSDocTagInfo[]): HTMLDivElement {
|
||||
}
|
||||
}
|
||||
|
||||
tagsWrapper.innerHTML = marked(contentString);
|
||||
tagsWrapper.innerHTML = marked(contentString) as string;
|
||||
|
||||
return tagsWrapper;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="adev-editor-container" #editorContainer>
|
||||
<as-split class="adev-editor" [direction]="splitDirection" restrictMove="true" gutterSize="5">
|
||||
<as-split class="docs-editor" [direction]="splitDirection" restrictMove="true" gutterSize="5">
|
||||
<as-split-area class="adev-left-side" [size]="50">
|
||||
<!-- Code Editor -->
|
||||
@if (!displayOnlyTerminal()) {
|
||||
@@ -16,9 +16,9 @@
|
||||
</as-split-area>
|
||||
|
||||
<as-split-area [size]="50">
|
||||
<!-- Preview, Termnial & Console -->
|
||||
<!-- Preview, Terminal & Console -->
|
||||
@if (!displayOnlyTerminal()) {
|
||||
<as-split class="adev-right-side" direction="vertical" restrictMove="true" gutterSize="5">
|
||||
<as-split class="docs-right-side" direction="vertical" restrictMove="true" gutterSize="5">
|
||||
<!-- Preview Section: for larger screens -->
|
||||
@if (!displayPreviewInMatTabGroup()) {
|
||||
<as-split-area [size]="50" [order]="1">
|
||||
@@ -34,9 +34,9 @@
|
||||
</as-split-area>
|
||||
}
|
||||
|
||||
<as-split-area class="adev-editor-tabs-and-refresh" [size]="50" [order]="2">
|
||||
<as-split-area class="docs-editor-tabs-and-refresh" [size]="50" [order]="2">
|
||||
<!-- Container to hide preview, console and footer when only the interactive terminal is used -->
|
||||
<mat-tab-group class="adev-editor-tabs" animationDuration="0ms" mat-stretch-tabs="false">
|
||||
<mat-tab-group class="docs-editor-tabs" animationDuration="0ms" mat-stretch-tabs="false">
|
||||
@if (displayPreviewInMatTabGroup()) {
|
||||
<mat-tab label="Preview">
|
||||
<docs-tutorial-preview />
|
||||
|
||||
@@ -32,7 +32,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
|
||||
// If files are displayed, shpare the space
|
||||
&:has(.adev-editor-tabs) {
|
||||
&:has(.docs-editor-tabs) {
|
||||
.adev-tutorial-code-editor {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@@ -56,7 +56,7 @@ $width-breakpoint: 950px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.adev-right-side {
|
||||
.docs-right-side {
|
||||
height: 100%;
|
||||
|
||||
// prevent border flicker when resizing editor
|
||||
@@ -71,7 +71,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
}
|
||||
|
||||
.adev-editor-tabs-and-refresh {
|
||||
.docs-editor-tabs-and-refresh {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
@@ -81,7 +81,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
|
||||
// preview, terminal, console side/container of the embedded editor
|
||||
.adev-editor-tabs {
|
||||
.docs-editor-tabs {
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,9 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import type {FileSystemTree} from '@webcontainer/api';
|
||||
|
||||
import type {
|
||||
TutorialConfig,
|
||||
TutorialMetadata,
|
||||
} from '@angular/docs';
|
||||
import {
|
||||
TUTORIALS_COMMON_DIRECTORY,
|
||||
TUTORIALS_METADATA_WEB_PATH,
|
||||
TUTORIALS_SOURCE_CODE_WEB_PATH,
|
||||
TutorialType,
|
||||
} from '@angular/docs';
|
||||
import type {TutorialConfig, TutorialMetadata} from '@angular/docs';
|
||||
import {TUTORIALS_ASSETS_WEB_PATH} from '../editor/constants';
|
||||
import {TutorialType} from '@angular/docs';
|
||||
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
|
||||
|
||||
describe('EmbeddedTutorialManager', () => {
|
||||
@@ -252,13 +245,7 @@ describe('EmbeddedTutorialManager', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
const commonSourceCode: FileSystemTree = {
|
||||
'common.ts': {
|
||||
file: {
|
||||
contents: 'code',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const metadata: TutorialMetadata = {
|
||||
tutorialFiles: {'app.js': ''},
|
||||
openFiles: ['app.js'],
|
||||
@@ -271,14 +258,13 @@ describe('EmbeddedTutorialManager', () => {
|
||||
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
fetchMock.and.returnValues(
|
||||
Promise.resolve(new Response(JSON.stringify(commonSourceCode))),
|
||||
Promise.resolve(new Response(JSON.stringify(tutorialSourceCode))),
|
||||
Promise.resolve(new Response(JSON.stringify(metadata))),
|
||||
);
|
||||
|
||||
await service.fetchAndSetTutorialFiles(tutorial);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(3);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(service.tutorialId()).toEqual(tutorial);
|
||||
expect(service.tutorialFilesystemTree()).toEqual(tutorialSourceCode);
|
||||
@@ -289,8 +275,6 @@ describe('EmbeddedTutorialManager', () => {
|
||||
|
||||
expect(service.type()).toEqual(metadata.type);
|
||||
|
||||
expect(service.commonFilesystemTree()).toEqual(commonSourceCode);
|
||||
|
||||
expect(service.hiddenFiles()).toEqual(metadata.hiddenFiles);
|
||||
expect(service.answerFiles()).toEqual(metadata.answerFiles!);
|
||||
});
|
||||
@@ -299,15 +283,11 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`)
|
||||
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
|
||||
|
||||
await expectAsync(service.fetchAndSetTutorialFiles(tutorial)).toBeRejectedWithError(
|
||||
@@ -315,38 +295,15 @@ describe('EmbeddedTutorialManager', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the tutorial common project cannot be fetched', async () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
await expectAsync(service.fetchAndSetTutorialFiles(tutorial)).toBeRejectedWithError(
|
||||
'Missing source code for tutorial common',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not set shouldReinstallDependencies if project did not change', async () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -368,15 +325,12 @@ describe('EmbeddedTutorialManager', () => {
|
||||
it('should trigger shouldReInstallDependencies if new metadata has different dependencies', async () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -404,14 +358,10 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -437,14 +387,10 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -472,16 +418,12 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
const allFiles = ['file1.ts', 'file2.ts'];
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -507,16 +449,12 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
const allFiles = ['file1.ts', 'file2.ts'];
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
@@ -539,16 +477,12 @@ describe('EmbeddedTutorialManager', () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
const allFiles = ['file1.ts', 'file2.ts'];
|
||||
|
||||
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
|
||||
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
|
||||
Promise.resolve(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
|
||||
@@ -15,7 +15,7 @@ import {TutorialType} from '@angular/docs';
|
||||
import {
|
||||
FakeWebContainer,
|
||||
FakeWebContainerProcess,
|
||||
} from '../../../../shared/src/lib/utils/test-utils.spec';
|
||||
} from '@angular/docs/testing';
|
||||
import {AlertManager} from './alert-manager.service';
|
||||
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
|
||||
import {LoadingStep} from './enums/loading-steps';
|
||||
|
||||
@@ -26,7 +26,7 @@ export const DEV_SERVER_READY_MSG = 'Watch mode enabled. Watching for file chang
|
||||
export const OUT_OF_MEMORY_MSG = 'Out of memory';
|
||||
|
||||
const enum PROCESS_EXIT_CODE {
|
||||
SUCCESS = 0, // process exited succesfully
|
||||
SUCCESS = 0, // process exited successfully
|
||||
ERROR = 10, // process exited with error
|
||||
SIGTERM = 143, // 143 = gracefully terminated by SIGTERM, e.g. Ctrl + C
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export class NodeRuntimeSandbox {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSanbox
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSandbox
|
||||
// in an unsupported environment.
|
||||
if (this.nodeRuntimeState.error()) {
|
||||
return;
|
||||
@@ -155,7 +155,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for an Angular project
|
||||
*/
|
||||
private async initProject(): Promise<void> {
|
||||
// prevent re-initializion
|
||||
// prevent re-initialization
|
||||
if (this._isProjectInitialized()) return;
|
||||
|
||||
// clean up the sandbox if it was initialized before so that the CLI can
|
||||
@@ -230,7 +230,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for the Angular CLI
|
||||
*/
|
||||
private async initAngularCli() {
|
||||
// prevent re-initializion
|
||||
// prevent re-initialization
|
||||
if (this._isAngularCliInitialized()) return;
|
||||
|
||||
// clean up the sandbox if a project was initialized before so the CLI can
|
||||
@@ -292,7 +292,7 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
const terminal = this.terminalHandler.interactiveTerminalInstance;
|
||||
|
||||
// use WebContainer spawn directly so that the proccess isn't killed on
|
||||
// use WebContainer spawn directly so that the process isn't killed on
|
||||
// cleanup
|
||||
const shellProcess = await webContainer.spawn('bash');
|
||||
|
||||
@@ -516,10 +516,10 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
/**
|
||||
* Kill existing processes and remove files from the WebContainer
|
||||
* when switching tutorials that have diferent requirements
|
||||
* when switching tutorials that have different requirements
|
||||
*/
|
||||
private async cleanup() {
|
||||
// await the proccess to be killed before removing the files because
|
||||
// await the process to be killed before removing the files because
|
||||
// a process can create files during the promise
|
||||
await this.killExistingProcesses();
|
||||
await this.removeFiles();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="adev-preview-error adev-light-mode adev-mini-scroll-track">
|
||||
<div class="adev-preview-error docs-light-mode docs-mini-scroll-track">
|
||||
@switch (true) {
|
||||
@case (error()?.type === ErrorType.UNSUPPORTED_BROWSER_ENVIRONMENT) {
|
||||
@if(isIos) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
:host {
|
||||
display: block;
|
||||
|
||||
.adev-dark-mode & {
|
||||
.docs-dark-mode & {
|
||||
.adev-embedded-editor-preview-container {
|
||||
background: var(--gray-100);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import {By} from '@angular/platform-browser';
|
||||
|
||||
import {Terminal} from './terminal.component';
|
||||
import {TerminalHandler, TerminalType} from './terminal-handler.service';
|
||||
import {FakeEventTarget, WINDOW} from '@angular/docs';
|
||||
import {WINDOW} from '@angular/docs';
|
||||
import {FakeEventTarget} from '@angular/docs/testing';
|
||||
|
||||
describe('Terminal', () => {
|
||||
let component: Terminal;
|
||||
|
||||
@@ -80,7 +80,7 @@ export class TypingsLoader {
|
||||
.readFile(`./node_modules/${library}/package.json`, 'utf-8')
|
||||
.catch((error) => {
|
||||
// Note: "ENOENT" errors occurs:
|
||||
// - While reseting the NodeRuntimeSandbox.
|
||||
// - While resetting the NodeRuntimeSandbox.
|
||||
// - When the library is not a dependency in the project, its package.json won't exist.
|
||||
//
|
||||
// In both cases we ignore the error to continue the process.
|
||||
|
||||
@@ -14,7 +14,7 @@ import {ActivatedRoute} from '@angular/router';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adev-docs',
|
||||
selector: 'docs-docs',
|
||||
standalone: true,
|
||||
imports: [CommonModule, DocViewer],
|
||||
styleUrls: ['./docs.component.scss'],
|
||||
|
||||
@@ -8,13 +8,6 @@
|
||||
</p>
|
||||
<p class="adev-banner-cta">Read about our beta launch</p>
|
||||
</a>
|
||||
<a href="https://goo.gle/angular-event" class="adev-banner" target="_blank">
|
||||
<p>
|
||||
<code>ng update</code>
|
||||
to Angular v17 on November 8th!
|
||||
</p>
|
||||
<p class="adev-banner-cta">Learn more</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="adev-canvas"></div>
|
||||
@@ -88,6 +81,6 @@
|
||||
</div>
|
||||
<div class="adev-arrow"></div>
|
||||
<a routerLink="{{ctaLink}}" class="adev-cta">
|
||||
<button class="adev-primary-btn" [attr.text]="'Learn Angular'" aria-label="Learn Angular">Learn Angular</button>
|
||||
<button class="docs-primary-btn" [attr.text]="'Learn Angular'" aria-label="Learn Angular">Learn Angular</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
width: 100%;
|
||||
|
||||
// While editor is loading, display an svg of the editor
|
||||
.adev-dark-mode & {
|
||||
.docs-dark-mode & {
|
||||
.adev-editor-scroll-container img {
|
||||
content: url('../../../assets/images/editor-dark-horizontal.svg');
|
||||
@include mq.for-tablet-down {
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.adev-light-mode & {
|
||||
.docs-light-mode & {
|
||||
.adev-editor-scroll-container img {
|
||||
content: url('../../../assets/images/editor-light-horizontal.svg');
|
||||
@include mq.for-tablet-down {
|
||||
@@ -142,7 +142,8 @@
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s linear;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.5s linear, visibility 0.5s linear;
|
||||
|
||||
button {
|
||||
font-size: 1rem;
|
||||
@@ -307,6 +308,7 @@
|
||||
.adev-cta,
|
||||
.adev-arrow {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiItemLabel from './api-item-label.component';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
|
||||
describe('ApiItemLabel', () => {
|
||||
let component: ApiItemLabel;
|
||||
@@ -23,7 +24,32 @@ describe('ApiItemLabel', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should by default display short label for Class', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
});
|
||||
|
||||
it('should display full label for Class when labelMode equals full', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'full';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('Class');
|
||||
});
|
||||
|
||||
it('should display short label for Class when labelMode equals short', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'short';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from '../pipes/api-label.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'adev-api-item-label',
|
||||
selector: 'docs-api-item-label',
|
||||
standalone: true,
|
||||
templateUrl: './api-item-label.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
@for (apiItem of group.items; track apiItem.url) {
|
||||
<li [class.adev-api-items-section-item-deprecated]="apiItem.isDeprecated">
|
||||
<a [routerLink]="'/' + apiItem.url" class="adev-api-items-section-item" [attr.aria-describedby]="apiItem.isDeprecated ? 'deprecated-description' : null">
|
||||
<adev-api-item-label
|
||||
<docs-api-item-label
|
||||
[type]="apiItem.itemType"
|
||||
mode="short"
|
||||
class="adev-api-item-label"
|
||||
class="docs-api-item-label"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span class="adev-item-title">{{ apiItem.title }}</span>
|
||||
</a>
|
||||
@if (apiItem.isDeprecated) {
|
||||
<span class="adev-deprecated">
|
||||
<span class="docs-deprecated">
|
||||
<!>
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.adev-deprecated {
|
||||
.docs-deprecated {
|
||||
font-family: var(--code-font);
|
||||
background-color: var(--senary-contrast);
|
||||
color: var(--tertiary-contrast);
|
||||
|
||||
+79
-4
@@ -13,17 +13,44 @@ import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import {ApiReferenceManager} from '../api-reference-list/api-reference-manager.service';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiItemsSection', () => {
|
||||
let component: ApiItemsSection;
|
||||
let fixture: ComponentFixture<ApiItemsSection>;
|
||||
let apiReferenceManagerSpy: jasmine.SpyObj<ApiReferenceManager>;
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
const fakeFeaturedGroup: ApiItemsGroup = {
|
||||
title: 'Featured',
|
||||
isFeatured: true,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CLASS, url: 'api/fakeTitle', isFeatured: true},
|
||||
{
|
||||
title: 'Fake Featured Title',
|
||||
itemType: ApiItemType.CLASS,
|
||||
url: 'api/fakeFeaturedTitle',
|
||||
isFeatured: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Deprecated Title',
|
||||
itemType: ApiItemType.CONST,
|
||||
url: 'api/fakeDeprecatedTitle',
|
||||
isFeatured: false,
|
||||
isDeprecated: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Standard Title',
|
||||
itemType: ApiItemType.DIRECTIVE,
|
||||
url: 'api/fakeTitle',
|
||||
isFeatured: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
title: 'Example group',
|
||||
isFeatured: false,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CONST, url: 'api/fakeTitle', isFeatured: false},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -34,12 +61,60 @@ describe('ApiItemsSection', () => {
|
||||
});
|
||||
fixture = TestBed.createComponent(ApiItemsSection);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should render star icon for featured group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render star icon for standard group', () => {
|
||||
component.group = fakeGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should render list of all APIs of provided group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const apis = fixture.debugElement.queryAll(By.css('.adev-api-items-section-grid li'));
|
||||
|
||||
expect(apis.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should display deprecated icon for deprecated API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const deprecatedApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .docs-deprecated'),
|
||||
);
|
||||
const deprecatedApiTitle = deprecatedApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(deprecatedApiIcons.length).toBe(1);
|
||||
expect(deprecatedApiIcons[0]).toBeTruthy();
|
||||
expect(deprecatedApiTitle?.nativeElement.innerText).toBe('Fake Deprecated Title');
|
||||
});
|
||||
|
||||
it('should display star icon for featured API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const featuredApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .adev-api-items-section-item-featured'),
|
||||
);
|
||||
const featuredApiTitle = featuredApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(featuredApiIcons.length).toBe(1);
|
||||
expect(featuredApiIcons[0]).toBeTruthy();
|
||||
expect(featuredApiTitle?.nativeElement.innerText).toBe('Fake Featured Title');
|
||||
});
|
||||
});
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
<div class="adev-header-and-tabs adev-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="headerInnerHtml()" class="adev-reference-header"></docs-viewer>
|
||||
<div class="adev-header-and-tabs docs-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="headerInnerHtml()" class="docs-reference-header"></docs-viewer>
|
||||
|
||||
<mat-tab-group class="adev-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()">
|
||||
<mat-tab-group class="docs-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()">
|
||||
@for (tab of tabs(); track tab) {
|
||||
<mat-tab [label]="tab.title">
|
||||
<div class="adev-reference-tab-body">
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
@if (canDisplayCards() && membersMarginTopInPx() > 0) {
|
||||
<docs-viewer
|
||||
class="adev-reference-members-container"
|
||||
class="docs-reference-members-container"
|
||||
[docContent]="membersInnerHtml()"
|
||||
[style.marginTop.px]="membersMarginTopInPx()"
|
||||
(contentLoaded)="membersCardsLoaded()">
|
||||
|
||||
+25
-25
@@ -38,7 +38,7 @@
|
||||
@include mq.for-desktop-up {
|
||||
// this section should only be independently scrollable if
|
||||
// the API tab is active & the screen is wide enough
|
||||
&:has(.adev-reference-api-tab),
|
||||
&:has(.docs-reference-api-tab),
|
||||
&.adev-cli-content {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -48,10 +48,10 @@
|
||||
overflow-y: scroll;
|
||||
width: 50%;
|
||||
}
|
||||
&:has(.adev-reference-api-tab) {
|
||||
&:has(.docs-reference-api-tab) {
|
||||
width: 60%;
|
||||
}
|
||||
&:not(.adev-reference-api-tab) {
|
||||
&:not(.docs-reference-api-tab) {
|
||||
max-width: var(--page-width);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-header {
|
||||
.docs-reference-header {
|
||||
> p {
|
||||
color: var(--secondary-contrast);
|
||||
margin-block-start: 0;
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-api-tab {
|
||||
.docs-reference-api-tab {
|
||||
display: flex;
|
||||
gap: 1.81rem;
|
||||
align-items: flex-start;
|
||||
@@ -155,7 +155,7 @@
|
||||
margin-block-start: 2.5rem;
|
||||
}
|
||||
|
||||
.adev-reference-members-container {
|
||||
.docs-reference-members-container {
|
||||
width: 40%;
|
||||
padding: 0 var(--layout-padding) 1rem 0;
|
||||
box-sizing: border-box;
|
||||
@@ -172,7 +172,7 @@
|
||||
}
|
||||
|
||||
// Sidebar
|
||||
.adev-reference-members {
|
||||
.docs-reference-members {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
@@ -182,7 +182,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-title {
|
||||
.docs-reference-title {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -217,7 +217,7 @@
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.adev-reference-category {
|
||||
.docs-reference-category {
|
||||
color: var(--gray-400);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
@@ -225,7 +225,7 @@
|
||||
letter-spacing: -0.00875rem;
|
||||
}
|
||||
|
||||
.adev-reference-member-card {
|
||||
.docs-reference-member-card {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
border-radius: 0.25rem;
|
||||
position: relative;
|
||||
@@ -248,7 +248,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:has(.adev-reference-card-body) {
|
||||
&:has(.docs-reference-card-body) {
|
||||
header {
|
||||
border-radius: 0.25rem 0.25rem 0 0;
|
||||
border-bottom: 1px solid var(--senary-contrast);
|
||||
@@ -266,7 +266,7 @@
|
||||
transition: background-color 0.3s ease, border 0.3s ease;
|
||||
|
||||
// h3 + code || # of overloads
|
||||
.adev-reference-header {
|
||||
.docs-reference-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -299,7 +299,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-card-body {
|
||||
.docs-reference-card-body {
|
||||
padding: 0.25rem 1.25rem;
|
||||
background: var(--septenary-contrast);
|
||||
transition: background-color 0.3s ease;
|
||||
@@ -316,14 +316,14 @@
|
||||
}
|
||||
|
||||
// when it's not the only card...
|
||||
.adev-reference-card-item:has(~ .adev-reference-card-item) {
|
||||
.docs-reference-card-item:has(~ .docs-reference-card-item) {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
margin-block: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
// & the last card
|
||||
.adev-reference-card-item:last-child {
|
||||
.docs-reference-card-item:last-child {
|
||||
&:not(:first-of-type) {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
margin-block: 1rem;
|
||||
@@ -332,7 +332,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-card-item {
|
||||
.docs-reference-card-item {
|
||||
span {
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
@@ -342,31 +342,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-function-definition {
|
||||
.docs-function-definition {
|
||||
&:has(*) {
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.adev-param-group {
|
||||
.docs-param-group {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
// If it's the only param group...
|
||||
.adev-param-group:not(:has(~ .adev-param-group)) {
|
||||
.docs-param-group:not(:has(~ .docs-param-group)) {
|
||||
margin-block: 1rem;
|
||||
}
|
||||
|
||||
.adev-return-type {
|
||||
.docs-return-type {
|
||||
padding-block: 1rem;
|
||||
|
||||
// & does not follow a function definition
|
||||
&:not(.adev-function-definition + .adev-return-type) {
|
||||
&:not(.docs-function-definition + .docs-return-type) {
|
||||
border-block-start: 1px solid var(--senary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.adev-param-keyword {
|
||||
.docs-param-keyword {
|
||||
color: var(--primary-contrast);
|
||||
font-family: var(--code-font);
|
||||
margin-inline-end: 0.5rem;
|
||||
@@ -381,7 +381,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-deprecated {
|
||||
.docs-deprecated {
|
||||
color: var(--page-background);
|
||||
background-color: var(--quaternary-contrast);
|
||||
width: max-content;
|
||||
@@ -391,11 +391,11 @@
|
||||
}
|
||||
|
||||
// deprecated markers beside header
|
||||
.adev-reference-header ~ .adev-deprecated {
|
||||
.docs-reference-header ~ .docs-deprecated {
|
||||
margin-block-start: 0.5rem;
|
||||
}
|
||||
|
||||
.adev-parameter-description {
|
||||
.docs-parameter-description {
|
||||
p:first-child {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
|
||||
+38
-7
@@ -17,22 +17,25 @@ import {provideRouter} from '@angular/router';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
|
||||
import ApiReferenceDetailsPage from './api-reference-details-page.component';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiReferenceDetailsPage', () => {
|
||||
let component: ApiReferenceDetailsPage;
|
||||
let loader: HarnessLoader;
|
||||
let harness: RouterTestingHarness;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
membersMarginTopInPx: signal(0),
|
||||
membersMarginTopInPx: signal(10),
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT_WITH_TABS = `<div class="adev-reference-tabs">
|
||||
<div data-tab="API" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" class="adev-reference-tab"></div>
|
||||
const SAMPLE_CONTENT_WITH_TABS = `<div class="docs-reference-tabs">
|
||||
<div data-tab="API" data-tab-url="api" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" data-tab-url="description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" data-tab-url="examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" data-tab-url="usage-notes" class="adev-reference-tab"></div>
|
||||
<div class="docs-reference-members-container"></div>
|
||||
</div>`;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -54,7 +57,7 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
const harness = await RouterTestingHarness.create();
|
||||
harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', ApiReferenceDetailsPage);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
@@ -72,4 +75,32 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
|
||||
expect(tabs.length).toBe(4);
|
||||
}));
|
||||
|
||||
it('should display members cards when API tab is active', waitForAsync(async () => {
|
||||
const matTabGroup = await loader.getHarness(MatTabGroupHarness);
|
||||
const tabs = await matTabGroup.getTabs();
|
||||
|
||||
let membersCard = harness.fixture.debugElement.query(
|
||||
By.css('.docs-reference-members-container'),
|
||||
);
|
||||
expect(membersCard).toBeTruthy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[1].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.docs-reference-members-container'));
|
||||
expect(membersCard).toBeFalsy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[0].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.docs-reference-members-container'));
|
||||
expect(membersCard).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should setup scroll listeners when API members are loaded', () => {
|
||||
const setupListenersSpy = spyOn(fakeApiReferenceScrollHandler, 'setupListeners');
|
||||
|
||||
component.membersCardsLoaded();
|
||||
|
||||
expect(setupListenersSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@
|
||||
[class.adev-reference-list-legend-item-active]="type() === itemType"
|
||||
(click)="filterByItemType(itemType)"
|
||||
>
|
||||
<adev-api-item-label [type]="itemType" mode="short" class="adev-api-item-label" />
|
||||
<docs-api-item-label [type]="itemType" mode="short" class="docs-api-item-label" />
|
||||
<span>{{ itemType | adevApiLabel : 'full' }}</span>
|
||||
</li>
|
||||
}
|
||||
@@ -40,5 +40,5 @@
|
||||
<adev-api-items-section [group]="group" />
|
||||
}
|
||||
|
||||
<span id="deprecated-description" class="adev-deprecated-description">Deprecated</span>
|
||||
<span id="deprecated-description" class="docs-deprecated-description">Deprecated</span>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -96,6 +96,6 @@
|
||||
}
|
||||
|
||||
|
||||
.adev-deprecated-description {
|
||||
.docs-deprecated-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+17
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiReferenceList from './api-reference-list.component';
|
||||
import ApiReferenceList, {ALL_STATUSES_KEY} from './api-reference-list.component';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {ApiReferenceManager} from './api-reference-manager.service';
|
||||
import {signal} from '@angular/core';
|
||||
@@ -95,4 +95,20 @@ describe('ApiReferenceList', () => {
|
||||
|
||||
expect(component.filteredGroups()![0].items).toEqual([fakeItem2]);
|
||||
});
|
||||
|
||||
it('should set selected type when provided type is different than selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
});
|
||||
|
||||
it('should reset selected type when provided type is equal to selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ALL_STATUSES_KEY);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<div class="adev-header-and-tabs adev-cli-content adev-scroll-track-transparent">
|
||||
<div class="adev-header-and-tabs adev-cli-content docs-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="mainContentInnerHtml()" />
|
||||
</div>
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reference-type-and-default {
|
||||
.docs-reference-type-and-default {
|
||||
width: 4.375rem;
|
||||
flex-shrink: 0;
|
||||
span {
|
||||
|
||||
+33
-7
@@ -6,16 +6,18 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import CliReferenceDetailsPage from './cli-reference-details-page.component';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
import {signal} from '@angular/core';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||||
|
||||
describe('CliReferenceDetailsPage', () => {
|
||||
let component: CliReferenceDetailsPage;
|
||||
let fixture: ComponentFixture<CliReferenceDetailsPage>;
|
||||
let harness: RouterTestingHarness;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
@@ -23,18 +25,42 @@ describe('CliReferenceDetailsPage', () => {
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT = `
|
||||
<div class="cli">
|
||||
<div class="docs-reference-cli-content">First column content</div>
|
||||
<div class="docs-reference-members-container">Members content</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CliReferenceDetailsPage, RouterTestingModule],
|
||||
providers: [
|
||||
provideRouter([
|
||||
{
|
||||
path: '**',
|
||||
component: CliReferenceDetailsPage,
|
||||
data: {
|
||||
'docContent': {
|
||||
id: 'id',
|
||||
contents: SAMPLE_CONTENT,
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
|
||||
fixture = TestBed.createComponent(CliReferenceDetailsPage);
|
||||
component = fixture.componentInstance;
|
||||
harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', CliReferenceDetailsPage);
|
||||
TestbedHarnessEnvironment.loader(fixture);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should set content on init', () => {
|
||||
expect(component.mainContentInnerHtml()).toBe('First column content');
|
||||
expect(component.cardsInnerHtml()).toBe('Members content');
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import {map} from 'rxjs/operators';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME} from '../constants/api-reference-prerender.constants';
|
||||
|
||||
export const CLI_MAIN_CONTENT_SELECTOR = '.adev-reference-cli-content';
|
||||
export const CLI_MAIN_CONTENT_SELECTOR = '.docs-reference-cli-content';
|
||||
export const CLI_TOC = '.adev-reference-cli-toc';
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
*/
|
||||
|
||||
export const API_REFERENCE_DETAILS_PAGE_CONTENT_CLASS_NAME = '.adev-reference-content';
|
||||
export const API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME = '.adev-reference-header';
|
||||
export const API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME = '.adev-reference-members-container';
|
||||
export const API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME = '.docs-reference-header';
|
||||
export const API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME = '.docs-reference-members-container';
|
||||
export const API_REFERENCE_TAB_BODY_CLASS_NAME = '.adev-reference-tab-body';
|
||||
export const API_REFERENCE_TAB_ATTRIBUTE = 'data-tab';
|
||||
export const API_REFERENCE_TAB_URL_ATTRIBUTE = 'data-tab-url';
|
||||
export const API_REFERENCE_TAB_API_LABEL = 'API';
|
||||
export const API_REFERENCE_TAB_QUERY_PARAM = 'tab';
|
||||
export const API_TAB_CLASS_NAME = '.adev-reference-api-tab';
|
||||
export const API_REFERENCE_MEMBER_CARD_CLASS_NAME = '.adev-reference-member-card';
|
||||
export const API_TAB_CLASS_NAME = '.docs-reference-api-tab';
|
||||
export const API_REFERENCE_MEMBER_CARD_CLASS_NAME = '.docs-reference-member-card';
|
||||
export const API_TAB_ACTIVE_CODE_LINE = 'hljs-ln-line-highlighted';
|
||||
export const HIGHLIGHT_JS_CODE_LINE_CLASS_NAME = 'hljs-ln-line';
|
||||
export const MEMBER_ID_ATTRIBUTE = 'member-id';
|
||||
|
||||
@@ -56,10 +56,12 @@ export function getApiNavigationItems(): NavigationItem[] {
|
||||
|
||||
const packageNavigationItem: NavigationItem = {
|
||||
label: packageNameWithoutPrefix,
|
||||
children: packageApis.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
})),
|
||||
children: packageApis
|
||||
.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label)),
|
||||
};
|
||||
|
||||
apiNavigationItems.push(packageNavigationItem);
|
||||
|
||||
@@ -6,11 +6,23 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from './api-label.pipe';
|
||||
|
||||
describe('ApiLabel', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new ApiLabel();
|
||||
expect(pipe).toBeTruthy();
|
||||
let pipe: ApiLabel;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new ApiLabel();
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'short');
|
||||
expect(result).toBe('C');
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'full');
|
||||
expect(result).toBe('Class');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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,6 +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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@use '@angular/docs/styles/media-queries' as mq;
|
||||
|
||||
// horizozntal tutorial nav bar
|
||||
// horizontal tutorial nav bar
|
||||
.adev-tutorial-nav-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -21,7 +21,7 @@
|
||||
transition: background-color 0.3s ease;
|
||||
container: nav-container / inline-size;
|
||||
|
||||
&:has(.adev-reveal-answer-button) {
|
||||
&:has(.docs-reveal-answer-button) {
|
||||
@container tutorial-content (max-width: 430px) {
|
||||
padding-block-end: calc(1.5rem + 85px);
|
||||
}
|
||||
@@ -115,7 +115,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adev-reveal-answer-button {
|
||||
.docs-reveal-answer-button {
|
||||
height: 2.875rem;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@if (shouldRenderContent()) {
|
||||
<div
|
||||
#content
|
||||
class="adev-tutorial-content"
|
||||
class="docs-tutorial-content"
|
||||
[class.adev-nav-open]="showNavigationDropdown()"
|
||||
>
|
||||
<!-- Tutorial Nav: Current Tutorial Title and Nav Buttons -->
|
||||
@@ -30,7 +30,7 @@
|
||||
@if (shouldRenderEmbeddedEditor()) {
|
||||
<div
|
||||
#editor
|
||||
class="adev-tutorial-editor"
|
||||
class="docs-tutorial-editor"
|
||||
[class.adev-split-tutorial]="shouldRenderContent()"
|
||||
>
|
||||
@if (embeddedEditorComponent) {
|
||||
@@ -59,7 +59,7 @@
|
||||
#revealAnswerButton
|
||||
(click)="answerRevealed() ? handleResetAnswer() : handleRevealAnswer()"
|
||||
[disabled]="!canRevealAnswer()"
|
||||
class="adev-reveal-answer-button adev-reveal-desktop-button adev-primary-btn"
|
||||
class="docs-reveal-answer-button adev-reveal-desktop-button docs-primary-btn"
|
||||
[attr.text]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[attr.aria-label]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[class.adev-reset-answer-button]="answerRevealed()"
|
||||
@@ -74,7 +74,7 @@
|
||||
[download]="stepName() + '.zip'"
|
||||
[href]="localTutorialZipUrl()"
|
||||
>
|
||||
<button class="adev-download-button adev-primary-btn">
|
||||
<button class="adev-download-button docs-primary-btn">
|
||||
<docs-icon>download</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
@@ -83,26 +83,26 @@
|
||||
<div class="adev-nav-arrows">
|
||||
@if (previousStepPath) {
|
||||
<a [routerLink]="previousStepPath">
|
||||
<button class="adev-primary-btn">
|
||||
<button class="docs-primary-btn">
|
||||
<docs-icon>chevron_left</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
}
|
||||
@if (!previousStepPath) {
|
||||
<button class="adev-primary-btn" disabled>
|
||||
<button class="docs-primary-btn" disabled>
|
||||
<docs-icon>chevron_left</docs-icon>
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (nextStepPath) {
|
||||
<a [routerLink]="nextStepPath">
|
||||
<button class="adev-primary-btn">
|
||||
<button class="docs-primary-btn">
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
}
|
||||
@if (!nextStepPath) {
|
||||
<button class="adev-primary-btn" disabled>
|
||||
<button class="docs-primary-btn" disabled>
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
</button>
|
||||
}
|
||||
@@ -115,7 +115,7 @@
|
||||
#revealAnswerButton
|
||||
(click)="answerRevealed() ? handleResetAnswer() : handleRevealAnswer()"
|
||||
[disabled]="!canRevealAnswer()"
|
||||
class="adev-reveal-answer-button adev-reveal-mobile-button adev-primary-btn"
|
||||
class="docs-reveal-answer-button adev-reveal-mobile-button docs-primary-btn"
|
||||
[attr.text]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[attr.aria-label]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[class.adev-reset-answer-button]="answerRevealed()"
|
||||
|
||||
@@ -36,8 +36,8 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
|
||||
// if there is an embedded editor in view, apply column width
|
||||
&:has(.adev-tutorial-editor) {
|
||||
.adev-tutorial-content {
|
||||
&:has(.docs-tutorial-editor) {
|
||||
.docs-tutorial-content {
|
||||
width: $column-width;
|
||||
|
||||
@include mq.for-tablet-landscape-down {
|
||||
@@ -50,7 +50,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
// if tutorial nav exists, size editor to fit vertically within viewport on mobile
|
||||
@include mq.for-tablet-landscape-down {
|
||||
&:has(.adev-tutorial-nav-container) {
|
||||
.adev-tutorial-editor {
|
||||
.docs-tutorial-editor {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
|
||||
@include mq.for-phone-only {
|
||||
&:has(.adev-tutorial-nav-container) {
|
||||
.adev-tutorial-editor {
|
||||
.docs-tutorial-editor {
|
||||
// account for reveal answer button height when on smaller screens
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
@@ -66,7 +66,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
}
|
||||
|
||||
.adev-tutorial-content {
|
||||
.docs-tutorial-content {
|
||||
max-width: var(--page-width);
|
||||
min-width: 300px;
|
||||
width: 100%;
|
||||
@@ -127,7 +127,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
}
|
||||
|
||||
.adev-tutorial-editor {
|
||||
.docs-tutorial-editor {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
EmbeddedEditor,
|
||||
EmbeddedTutorialManager,
|
||||
NodeRuntimeSandbox
|
||||
} from '@angular/docs';
|
||||
} from '../../editor';
|
||||
|
||||
import {mockAsyncProvider} from '../../core/services/inject-async';
|
||||
import Tutorial from './tutorial.component';
|
||||
|
||||
@@ -125,6 +125,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () => import('./features/home/home.component'),
|
||||
data: {label: 'Home'}
|
||||
},
|
||||
{
|
||||
path: PagePrefix.DOCS,
|
||||
@@ -141,7 +142,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: PagePrefix.PLAYGROUND,
|
||||
loadComponent: () => import('./features/playground/playground.component'),
|
||||
data: {...commonTutorialRouteData},
|
||||
data: {...commonTutorialRouteData, label: 'Playground'},
|
||||
},
|
||||
...SUB_NAVIGATION_ROUTES,
|
||||
...API_REFERENCE_ROUTES,
|
||||
|
||||
@@ -943,6 +943,7 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
{
|
||||
path: DefaultPage.TUTORIALS,
|
||||
contentPath: 'tutorials/home',
|
||||
label: 'Tutorials'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1336,6 +1337,11 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'reference/migrations/typed-forms',
|
||||
contentPath: 'reference/migrations/typed-forms',
|
||||
},
|
||||
{
|
||||
label: 'Control Flow Syntax',
|
||||
path: 'reference/migrations/control-flow',
|
||||
contentPath: 'reference/migrations/control-flow',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -65,10 +65,13 @@ copy_to_directory(
|
||||
"//packages/upgrade:upgrade_docs",
|
||||
"//packages/upgrade/static:upgrade_static_docs",
|
||||
"//packages/upgrade/static/testing:upgrade_static_testing_docs",
|
||||
"//tools/manual_api_docs/blocks:blocks_docs",
|
||||
"//tools/manual_api_docs/elements:elements_docs",
|
||||
],
|
||||
replace_prefixes = {
|
||||
"adev/src/content": "",
|
||||
"packages/**/": "api/",
|
||||
"tools/**/": "api/",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 157 288"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="adev-directives-svg"
|
||||
class="docs-directives-svg"
|
||||
>
|
||||
<g style="mix-blend-mode: multiply;">
|
||||
<path
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 433 182"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="adev-roadmap-svg"
|
||||
class="docs-roadmap-svg"
|
||||
>
|
||||
<path
|
||||
d="M26.0339 81.4492H316.739L406.475 153.601H114.71L26.0339 81.4492Z"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 297 205"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="adev-what-is-angular-svg"
|
||||
class="docs-what-is-angular-svg"
|
||||
>
|
||||
<g style="mix-blend-mode: multiply;">
|
||||
<path
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -19,7 +19,7 @@ In the image above, there is a series of change detection calls triggered by eve
|
||||
|
||||
## Run tasks outside `NgZone`
|
||||
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/guide/zone).
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/api/core/NgZone).
|
||||
|
||||
<docs-code header="Run outside of the Zone" language='ts' linenums>
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
|
||||
@@ -43,7 +43,7 @@ It also includes troubleshooting information and any recommended manual changes
|
||||
For simple updates, the CLI command [`ng update`](cli/update) is all you need.
|
||||
Without additional arguments, [`ng update`](cli/update) lists the updates that are available to you and provides recommended steps to update your application to the most current version.
|
||||
|
||||
[Angular Versioning and Releases](reference/releases#versioning "Angular Release Practices, Versioning") describes the level of change that you can expect based a release's version number.
|
||||
[Angular Versioning and Releases](reference/releases#versioning "Angular Release Practices, Versioning") describes the level of change that you can expect based on a release's version number.
|
||||
It also describes supported update paths.
|
||||
|
||||
## Resource summary
|
||||
|
||||
@@ -78,7 +78,7 @@ For example, imagine the following scenario:
|
||||
1. After some time, a new version of the application is deployed to the server.
|
||||
This newer version includes the files `index.html`, `main.<main-hash-2>.js` and `lazy-chunk.<lazy-hash-2>.js`.
|
||||
|
||||
IMPORANT: The hashes are different now, because the content of the files changed. The old version is no longer available on the server.
|
||||
IMPORTANT: The hashes are different now, because the content of the files changed. The old version is no longer available on the server.
|
||||
|
||||
1. In the meantime, the user's browser decides to evict `lazy-chunk.<lazy-hash-1>.js` from its cache.
|
||||
Browsers might decide to evict specific (or all) resources from a cache in order to reclaim disk space.
|
||||
|
||||
@@ -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/
|
||||
npx http-server -p 8080 -c-1 dist/<project-name>/browser
|
||||
|
||||
</docs-code>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Architect } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { schema } from '@angular-devkit/core';
|
||||
import { promises as fs } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Copy File Builder', () => {
|
||||
let architect: Architect;
|
||||
@@ -19,7 +20,7 @@ describe('Copy File Builder', () => {
|
||||
|
||||
// This will either take a Node package name, or a path to the directory
|
||||
// for the package.json file.
|
||||
await architectHost.addBuilderFromPackage('..');
|
||||
await architectHost.addBuilderFromPackage(join(__dirname, '..'));
|
||||
});
|
||||
|
||||
it('can copy files', async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HeroModule } from './hero.module';
|
||||
import { HEROES } from './mock-heroes';
|
||||
|
||||
@Injectable({
|
||||
// we declare that this service should be created
|
||||
// by any injector that includes HeroModule.
|
||||
providedIn: HeroModule,
|
||||
})
|
||||
export class HeroService {
|
||||
getHeroes() { return HEROES; }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('forms-overvoew App', () => {
|
||||
describe('forms-overview App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user