mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
330 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4039f073f8 | |||
| a43057c059 | |||
| 7f19f7b825 | |||
| b23c31a496 | |||
| dfa2044af9 | |||
| a0388409e3 | |||
| c15b8ed631 | |||
| aff8bb222c | |||
| 1cb113cdec | |||
| aef4b05c62 | |||
| 52c7bde082 | |||
| 71557463f0 | |||
| 447b6e958f | |||
| 67d4449db4 | |||
| 2fcafb65c5 | |||
| 1febf523e3 | |||
| fca6122d09 | |||
| 47dc4ffd1a | |||
| f90ca1cfcf | |||
| 5a111064b8 | |||
| d416beee7b | |||
| 1ebba5442f | |||
| d025a07329 | |||
| c716ccffec | |||
| 9139fe0d95 | |||
| 4dec06d724 | |||
| 5af3222e35 | |||
| 1e3196b0c9 | |||
| 3b674e8cb3 | |||
| 0cd75257de | |||
| 05df189731 | |||
| 3df1dccebe | |||
| a9d4ccfff3 | |||
| 983cc2f6fd | |||
| a84227263d | |||
| 56a8408de4 | |||
| c6c08f6365 | |||
| 37ead5ffb5 | |||
| 18c9352d21 | |||
| d16a992b12 | |||
| 0b00039a45 | |||
| 4065c5f715 | |||
| 37661b6ec1 | |||
| 170a4376ea | |||
| 197b393aa6 | |||
| 2bbd1c972d | |||
| 6434bcce0c | |||
| 6f541b81d2 | |||
| 36a36ea034 | |||
| 69df2c0f8a | |||
| 7a336c159d | |||
| 6ddb250391 | |||
| 7d6ae95807 | |||
| da06239a41 | |||
| 0dd95c503f | |||
| 318718ce64 | |||
| 1b0c84a5ec | |||
| 827c3c15f4 | |||
| aa51dcdcdc | |||
| 62c00ab254 | |||
| 46e3de0f0a | |||
| dc966ceb6a | |||
| edbbbb1e44 | |||
| 6d88ce1525 | |||
| 009b068988 | |||
| 1c5fb1e5c1 | |||
| 790143eb9b | |||
| d8bdf56145 | |||
| 239fe6f83e | |||
| fd66f97885 | |||
| c303673a65 | |||
| 25f593ce2a | |||
| 4dfa6f1942 | |||
| 2f34f9f272 | |||
| a0ee6bdfe4 | |||
| d1df128725 | |||
| e6fea458ed | |||
| 7bf4906f27 | |||
| 3d7b31c113 | |||
| 086ae5e1b5 | |||
| eeeaadc7e9 | |||
| 6a6cb01bb3 | |||
| 2aa9775078 | |||
| c3c9a9eed3 | |||
| 85468ef630 | |||
| 863401b858 | |||
| c5c28f9f52 | |||
| 70afb41f8e | |||
| 1feadba215 | |||
| cf0ae2ec45 | |||
| b0e2cdd470 | |||
| c8f61d295a | |||
| 718bfd2fb7 | |||
| bf9db2897e | |||
| 8a6cc39aec | |||
| 9866f91ef6 | |||
| b86b1e8810 | |||
| 768f0410b9 | |||
| b7f2a8b180 | |||
| 72ae1064fe | |||
| 942517966b | |||
| 6712456847 | |||
| 101f072b74 | |||
| 44b94b1564 | |||
| d5a337dee1 | |||
| f7de67ba75 | |||
| f50fa15fa3 | |||
| 78f3d849ba | |||
| c4faee4722 | |||
| 9b539a18ba | |||
| 9a0c96489a | |||
| 1545ddcb4b | |||
| fdbb09f2ec | |||
| cab3adfdd1 | |||
| 5115050928 | |||
| d0cf624305 | |||
| 1aa0a8800c | |||
| a7cfb42c03 | |||
| 6c8d000016 | |||
| 494385cac0 | |||
| 2c34e37df9 | |||
| 1714e9ea0e | |||
| 032017174e | |||
| ddee59f58c | |||
| e9b2fe7ce5 | |||
| ab067a3d2e | |||
| 856c5f02c5 | |||
| ff01e33d69 | |||
| a4e27e9a03 | |||
| f54fdc5f76 | |||
| e6029bcf2c | |||
| 4787eced1b | |||
| cdafe8b01e | |||
| d0d6079f54 | |||
| 3f88fbdfa7 | |||
| abfd7783b0 | |||
| 6f91972ae4 | |||
| 0f17623398 | |||
| d3a0c2559a | |||
| 9a59f7613c | |||
| 47b09f8f18 | |||
| 5b3933f1ae | |||
| 9ac638548f | |||
| e7a3452852 | |||
| fa40feee1d | |||
| 5129daed1b | |||
| d733c69ce9 | |||
| 9c0ad1b434 | |||
| fad3d8e3a5 | |||
| b9a134b8eb | |||
| 54485f7f4b | |||
| bf2ba7a059 | |||
| dc8f11b4fd | |||
| 4bed062bc9 | |||
| be7110342b | |||
| 93c735cae7 | |||
| c8349ef2f6 | |||
| c35c0c7f2f | |||
| a59c3fe74e | |||
| e7cc89e3b0 | |||
| 74e1796a1e | |||
| 4e0fc81491 | |||
| 55cd8c2d73 | |||
| 7ecf13db06 | |||
| 071ab50c7c | |||
| 21b0fd3d13 | |||
| 1269d2e4f2 | |||
| 32ba8b5025 | |||
| 91b3466e97 | |||
| 657061e528 | |||
| aaf053c288 | |||
| 4d9385b5fd | |||
| d7a5eadbfa | |||
| ea78278635 | |||
| e64271df92 | |||
| b695ff02cb | |||
| 6c51c29925 | |||
| 11b527cecd | |||
| 01fb2b1b80 | |||
| 09df37507f | |||
| 54fe7ca055 | |||
| 5d9f124876 | |||
| 1846874f1f | |||
| 434ff7f1a0 | |||
| 91f8963d86 | |||
| a786bb6f4b | |||
| 9aef481172 | |||
| f9a38a4b73 | |||
| d47ea29b89 | |||
| baa31fb1a1 | |||
| d17555a7c6 | |||
| 06f5879e42 | |||
| c4dcfdf644 | |||
| 04f225d516 | |||
| 57184d0895 | |||
| 2e4db98877 | |||
| 2d03187a1d | |||
| cb826866f3 | |||
| e127c420f6 | |||
| 21838501b6 | |||
| 6dbe4b7369 | |||
| cd8e0c3ae0 | |||
| 615f85f84e | |||
| 0c82de5fe5 | |||
| 9349bcfee7 | |||
| 3a4caec61c | |||
| b24fec7215 | |||
| 5747c7a48b | |||
| cf2be036c9 | |||
| b93a1b8df7 | |||
| 6dd4f7e67a | |||
| e6e0c72118 | |||
| 32c9aadd6a | |||
| 862e7708e3 | |||
| 88614f0a1b | |||
| 21ca05d5c9 | |||
| e30ff9f688 | |||
| f1105f9bab | |||
| b0c962db4a | |||
| c1085fc134 | |||
| 124fab9c91 | |||
| e96d9e3e51 | |||
| 04ba24eeeb | |||
| eefc3896f8 | |||
| 1243113feb | |||
| 63b4448a05 | |||
| ebb678616a | |||
| 74d83f4f3d | |||
| 2648e75441 | |||
| 07939d671c | |||
| 372f6559db | |||
| f8f0af5310 | |||
| e539e16073 | |||
| bb12572d8e | |||
| 68643d2ddc | |||
| fead94d4ec | |||
| 090f7a38f1 | |||
| 92e7a45d43 | |||
| 3fa15e7bb9 | |||
| a833eb283f | |||
| 54d1d3e453 | |||
| acee6ce483 | |||
| 0b5592dcc9 | |||
| d296791daa | |||
| 19ecc2f300 | |||
| eb6c2ecf2a | |||
| 14587546aa | |||
| 5fd1b8fb77 | |||
| 3a7e531526 | |||
| d9533445dd | |||
| 5e675b1354 | |||
| 00f9d5a321 | |||
| d2bca12049 | |||
| 7ecec96d3b | |||
| d19cb9e485 | |||
| 69f18f99d9 | |||
| 7ebf93f9f8 | |||
| 7b68bf01fb | |||
| 6410539818 | |||
| e3221efa7f | |||
| ecb8db04e4 | |||
| 37c5ff61c6 | |||
| ea589628a7 | |||
| e221067e1c | |||
| e61da79b3c | |||
| aa318860db | |||
| 359eb4df1b | |||
| dc404f0a8e | |||
| 383543e5f9 | |||
| 0c99e56f97 | |||
| a12a9fe4f9 | |||
| 8b5aeebb54 | |||
| 02f26cf56a | |||
| 94e1ee9eef | |||
| 9385dc457c | |||
| 8b4d217466 | |||
| 16d637eb6a | |||
| 05a4299ea6 | |||
| 1b607655b6 | |||
| 9089293adf | |||
| e91434fd71 | |||
| 01e18cde8e | |||
| 3712624dfa | |||
| 7f341416f9 | |||
| d962dc9be1 | |||
| 0cb0cd47af | |||
| 6d21572825 | |||
| 1dc28b05c0 | |||
| aee6ab93d6 | |||
| df80ab9d4c | |||
| 1be49f70d0 | |||
| f142d48b8d | |||
| 95fb3b4c14 | |||
| 2bf5732026 | |||
| 2a52ce8019 | |||
| 0f7c4338dc | |||
| 29384b5344 | |||
| 86f3816abd | |||
| c71cc659f9 | |||
| ee492c979b | |||
| b167365bde | |||
| 069282f462 | |||
| 51e79aaf73 | |||
| 001b0ba185 | |||
| 0ee9c7037b | |||
| 4f3ea59c1e | |||
| 1ff640dfb3 | |||
| 32cc250080 | |||
| 75d394eb2e | |||
| 794e80b057 | |||
| 7d37cf7877 | |||
| 85f8db7539 | |||
| 7ce2640a28 | |||
| 68a4bf35e9 | |||
| 882c0ea8a1 | |||
| 1c8ad18dd6 | |||
| afdbeae46c | |||
| ebecdea206 | |||
| 47333e4aa0 | |||
| 68eba763fe | |||
| ab17a84da6 | |||
| b2d971b143 | |||
| a94d0db4db | |||
| fb67fc2a0e | |||
| 8e830f942f | |||
| 405f2f0a41 | |||
| 139a4afdbd | |||
| 8550bd0683 | |||
| 78505746ee | |||
| d29ced91a1 |
+2
-6
@@ -35,11 +35,10 @@ integration/standalone-bootstrap/node_modules
|
||||
integration/terser/node_modules
|
||||
integration/trusted-types/node_modules
|
||||
integration/typings_test_rxjs7/node_modules
|
||||
integration/legacy-animations/node_modules
|
||||
integration/legacy-animations-async/node_modules
|
||||
integration/typings_test_ts59/node_modules
|
||||
integration/typings_test_ts58/node_modules
|
||||
modules/ssr-benchmarks/node_modules
|
||||
|
||||
|
||||
# For rules_js
|
||||
adev/node_modules
|
||||
adev/shared-docs/node_modules
|
||||
@@ -62,10 +61,7 @@ packages/platform-server/node_modules
|
||||
packages/platform-browser-dynamic/node_modules
|
||||
packages/router/node_modules
|
||||
packages/zone.js/node_modules
|
||||
packages/zone.js/test/typings/node_modules
|
||||
packages/upgrade/node_modules
|
||||
packages/benchpress/node_modules
|
||||
packages/service-worker/node_modules
|
||||
packages/zone.js/test/typings/node_modules
|
||||
packages/zone.js/node_modules
|
||||
tools/bazel/rules_angular_store/node_modules
|
||||
|
||||
@@ -169,6 +169,8 @@ 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
|
||||
# --full_build_adev will run adev build/serve in a full mode, performing prerendering and DCE.
|
||||
build --flag_alias=full_build_adev=//adev:full_build_adev
|
||||
|
||||
####################################################
|
||||
# User bazel configuration
|
||||
|
||||
@@ -12,7 +12,6 @@ esbuild_checked_in(
|
||||
entry_point = ":lib/main.mts",
|
||||
external = [
|
||||
"undici",
|
||||
"pnpapi",
|
||||
],
|
||||
metafile = False,
|
||||
platform = "node",
|
||||
|
||||
+2983
-15228
File diff suppressed because one or more lines are too long
@@ -5,9 +5,9 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/saucelabs@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Starting Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
|
||||
@@ -15,22 +15,22 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
adev-build:
|
||||
runs-on: ubuntu-latest-8core
|
||||
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@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Build adev
|
||||
run: pnpm bazel build //adev:build.production
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: pnpm bazel build //adev:build --full_build_adev --config=release
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -16,6 +16,6 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
+46
-38
@@ -21,7 +21,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check code lint
|
||||
@@ -39,20 +41,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
disable-package-manager-cache: true
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Cache downloaded Cypress binary
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: '~/.cache/Cypress'
|
||||
key: cypress-cache-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -66,17 +63,18 @@ jobs:
|
||||
start: pnpm bazel run //devtools/src:devserver
|
||||
wait-on: 'http://localhost:4200'
|
||||
wait-on-timeout: 300
|
||||
install: false
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -85,14 +83,16 @@ jobs:
|
||||
run: pnpm test:ci
|
||||
|
||||
integration-tests:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -102,14 +102,14 @@ jobs:
|
||||
|
||||
adev:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -117,20 +117,20 @@ jobs:
|
||||
- name: Run tests
|
||||
run: pnpm bazel test //adev/...
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: pnpm bazel build //adev:build
|
||||
run: pnpm bazel build //adev:build --config=release
|
||||
|
||||
publish-snapshots:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -139,14 +139,20 @@ jobs:
|
||||
|
||||
zone-js:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./node_modules
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -180,12 +186,14 @@ jobs:
|
||||
- run: pnpm -C packages/zone.js/test/typings test
|
||||
|
||||
# saucelabs:
|
||||
# runs-on: ubuntu-latest
|
||||
# runs-on: ubuntu-latest-4core
|
||||
# env:
|
||||
# SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
# steps:
|
||||
# - name: Initialize environment
|
||||
# uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b5a3609f89c06eb4037dce22a93641213a5d1508
|
||||
# with:
|
||||
# cache-node-modules: true
|
||||
# - name: Install node modules
|
||||
# run: pnpm install --frozen-lockfile
|
||||
# - uses: ./.github/actions/saucelabs-legacy
|
||||
@@ -193,18 +201,18 @@ jobs:
|
||||
adev-deploy:
|
||||
needs: [adev]
|
||||
if: needs.adev.result == 'success'
|
||||
runs-on: ubuntu-latest-8core
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Build adev
|
||||
run: pnpm bazel build //adev:build.production --config=release
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: pnpm bazel build //adev:build --full_build_adev --config=release
|
||||
- name: Deploy to firebase
|
||||
uses: ./.github/actions/deploy-docs-site
|
||||
with:
|
||||
|
||||
@@ -13,13 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: angular/dev-infra/github-actions/pull-request-labeling@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/pull-request-labeling@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -8,22 +8,22 @@ jobs:
|
||||
# Bazel saucelabs job resides in `manual.yml` because it's currently unstable, but
|
||||
# kept as "runnable" for debugging/stabilization effort purposes.
|
||||
bazel-saucelabs:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/saucelabs@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: pnpm bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
workflows: ${{ steps.workflows.outputs.workflows }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- id: workflows
|
||||
@@ -36,16 +36,16 @@ jobs:
|
||||
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
|
||||
# identity federation. This allows us to request short lived credentials on demand, rather than storing
|
||||
# credentials in secrets long term. More information can be found at:
|
||||
# https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform
|
||||
- uses: 'google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed' # v2
|
||||
- uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # v2
|
||||
with:
|
||||
project_id: 'internal-200822'
|
||||
workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular'
|
||||
|
||||
+40
-30
@@ -19,7 +19,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check code lint
|
||||
@@ -37,7 +39,7 @@ jobs:
|
||||
- name: Check code format
|
||||
run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
|
||||
- name: Check Package Licenses
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
|
||||
|
||||
@@ -45,18 +47,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
disable-package-manager-cache: true
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
- name: Cache downloaded Cypress binary
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: '~/.cache/Cypress'
|
||||
key: cypress-cache-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -70,17 +67,18 @@ jobs:
|
||||
start: pnpm bazel run //devtools/src:devserver
|
||||
wait-on: 'http://localhost:4200'
|
||||
wait-on-timeout: 300
|
||||
install: false
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run CI tests for framework
|
||||
@@ -97,14 +95,16 @@ jobs:
|
||||
retention-days: 1
|
||||
|
||||
integration-tests:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run integration CI tests for framework
|
||||
@@ -112,31 +112,37 @@ jobs:
|
||||
|
||||
adev:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
labels: ubuntu-latest-8core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run tests
|
||||
run: pnpm bazel test //adev/...
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: pnpm bazel build //adev:build
|
||||
run: pnpm bazel build //adev:build --config=release
|
||||
|
||||
zone-js:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@80db036355181684ed07021a175e9f039190d3d6
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./node_modules
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@b7672ff60456719e6d9b0cc052abc73a7adc8df2
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@80db036355181684ed07021a175e9f039190d3d6
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -157,6 +163,8 @@ jobs:
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/
|
||||
cp dist/bin/packages/zone.js/test/closure/zone.closure.js ./packages/zone.js/build/test/zone.closure.mjs
|
||||
|
||||
# Install
|
||||
- run: pnpm -C packages/zone.js install --frozen-lockfile
|
||||
# Run zone.js tools tests
|
||||
- run: pnpm -C packages/zone.js promisefinallytest
|
||||
- run: pnpm -C packages/zone.js jest:test
|
||||
@@ -166,12 +174,14 @@ jobs:
|
||||
- run: pnpm -C packages/zone.js/test/typings test
|
||||
|
||||
# saucelabs:
|
||||
# runs-on: ubuntu-latest
|
||||
# runs-on: ubuntu-latest-4core
|
||||
# env:
|
||||
# SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
# steps:
|
||||
# - name: Initialize environment
|
||||
# uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b5a3609f89c06eb4037dce22a93641213a5d1508
|
||||
# with:
|
||||
# cache-node-modules: true
|
||||
# - name: Install node modules
|
||||
# run: pnpm install --frozen-lockfile
|
||||
# - uses: ./.github/actions/saucelabs-legacy
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Run analysis'
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -47,6 +47,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
|
||||
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
env:
|
||||
ANGULAR_CDK_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CDK_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR CDK apis (if necessary)
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
uses: peter-evans/create-pull-request@v7.0.8 # v7.0.8
|
||||
with:
|
||||
token: ${{ secrets.ANGULAR_ROBOT_ACCESS_TOKEN }}
|
||||
push-to-fork: 'angular-robot/angular'
|
||||
@@ -52,7 +52,6 @@ jobs:
|
||||
labels: |
|
||||
action: merge
|
||||
area: docs
|
||||
target: automation
|
||||
commit-message: |
|
||||
docs: update Angular CDK apis
|
||||
|
||||
@@ -67,7 +66,7 @@ jobs:
|
||||
env:
|
||||
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR CLI help (if necessary)
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
uses: peter-evans/create-pull-request@v7.0.8 # v7.0.8
|
||||
with:
|
||||
token: ${{ secrets.ANGULAR_ROBOT_ACCESS_TOKEN }}
|
||||
push-to-fork: 'angular-robot/angular'
|
||||
@@ -82,7 +81,6 @@ jobs:
|
||||
labels: |
|
||||
action: merge
|
||||
area: docs
|
||||
target: automation
|
||||
commit-message: |
|
||||
docs: update Angular CLI help
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export const format: FormatConfig = {
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format the locale files which are checked-in for Google3, but generated using
|
||||
// the `generate-locales-tool` from `packages/common/locales`.
|
||||
'!packages/core/src/i18n/locale_en.ts',
|
||||
|
||||
@@ -2,6 +2,7 @@ import {ReleaseConfig} from '@angular/ng-dev';
|
||||
|
||||
/** Configuration for the `ng-dev release` command. */
|
||||
export const release: ReleaseConfig = {
|
||||
rulesJsInteropMode: true,
|
||||
publishRegistry: 'https://wombat-dressing-room.appspot.com',
|
||||
representativeNpmPackage: '@angular/core',
|
||||
npmPackages: [
|
||||
|
||||
+5
-22
@@ -56,8 +56,8 @@
|
||||
|
||||
version: 3
|
||||
|
||||
#availability:
|
||||
# users_unavailable: []
|
||||
availability:
|
||||
users_unavailable: ['devversion']
|
||||
|
||||
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
||||
# used throughout the config.
|
||||
@@ -135,9 +135,6 @@ groups:
|
||||
- kirjs
|
||||
- JoostK
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
|
||||
# =========================================================
|
||||
# Framework: General (most code in our packages)
|
||||
@@ -181,9 +178,6 @@ groups:
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- JeanMeche
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
|
||||
# =========================================================
|
||||
# Framework: Security-sensitive files which require extra review
|
||||
@@ -237,9 +231,6 @@ groups:
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
|
||||
# =========================================================
|
||||
# Tooling: Compiler API shared with Angular CLI
|
||||
@@ -293,9 +284,6 @@ groups:
|
||||
- MarkTechson
|
||||
- mmalerba
|
||||
- ~hawkgs
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
|
||||
# =========================================================
|
||||
# Angular DevTools
|
||||
@@ -333,6 +321,7 @@ groups:
|
||||
'.gemini/**/{*,.*}',
|
||||
'.ng-dev/**/{*,.*}',
|
||||
'.vscode/**/{*,.*}',
|
||||
'.yarn/**/{*,.*}',
|
||||
'contributing-docs/*.md',
|
||||
'contributing-docs/images/**/{*,.*}',
|
||||
'goldens/{*,.*}',
|
||||
@@ -409,12 +398,9 @@ groups:
|
||||
- ~iteriani
|
||||
- ~tbondwilkinson
|
||||
- ~rahatarmanahmed
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
reviews:
|
||||
request: 2
|
||||
required: 1
|
||||
request: 3 # Request reviews from 3 people
|
||||
required: 2 # Require that 2 people approve
|
||||
reviewed_for: required
|
||||
|
||||
# ================================================
|
||||
@@ -439,9 +425,6 @@ groups:
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
reviews:
|
||||
request: 2 # Request reviews from 2 people
|
||||
required: 1 # Require that 1 person approve
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Yarn Vendoring
|
||||
We utilize Yarn's `yarn-path` configuration in a shared `.yarnrc` file to enforce
|
||||
everyone using the same version of Yarn. Yarn checks the `.yarnrc` file to
|
||||
determine if yarn should delegate the command to a vendored version at the
|
||||
provided path.
|
||||
|
||||
## How to update
|
||||
To update to the latest version of Yarn as our vendored version:
|
||||
- Run this command
|
||||
```sh
|
||||
yarn policies set-version latest
|
||||
```
|
||||
- Remove the previous version
|
||||
+148049
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
yarn-path ".yarn/releases/yarn-1.22.22.cjs"
|
||||
+14
-7
@@ -1,7 +1,7 @@
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_library")
|
||||
load("@devinfra//bazel/validation:defs.bzl", "validate_ts_version_matching")
|
||||
load("@npm//:defs.bzl", "npm_link_all_packages")
|
||||
load("//tools:defaults.bzl", "copy_to_bin")
|
||||
load("//:yarn.bzl", "YARN_PATH")
|
||||
load("//tools:defaults.bzl", "copy_to_bin", "js_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
@@ -9,7 +9,9 @@ exports_files([
|
||||
"LICENSE",
|
||||
"karma-js.conf.js",
|
||||
"browser-providers.conf.js",
|
||||
YARN_PATH,
|
||||
"package.json",
|
||||
"angular.json",
|
||||
])
|
||||
|
||||
npm_link_all_packages(
|
||||
@@ -23,11 +25,6 @@ filegroup(
|
||||
srcs = ["package.json"],
|
||||
)
|
||||
|
||||
validate_ts_version_matching(
|
||||
module_lock_file = "MODULE.bazel.lock",
|
||||
package_json = "package.json",
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "tsconfig.json",
|
||||
actual = "//packages:tsconfig-build.json",
|
||||
@@ -63,6 +60,16 @@ config_setting(
|
||||
values = {"stamp": "true"},
|
||||
)
|
||||
|
||||
js_binary(
|
||||
name = "yarn_vendored",
|
||||
data = [".yarn/releases/yarn-1.22.22.cjs"],
|
||||
entry_point = ".yarn/releases/yarn-1.22.22.cjs",
|
||||
visibility = [
|
||||
"//integration:__subpackages__",
|
||||
"//modules/ssr-benchmarks:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "sauce_connect",
|
||||
actual = select({
|
||||
|
||||
+59
-143
@@ -1,146 +1,3 @@
|
||||
<a name="20.3.3"></a>
|
||||
# 20.3.3 (2025-10-02)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f51ab32fb3](https://github.com/angular/angular/commit/f51ab32fb3000ae34c077b049ff2f7b8e3e22d14) | fix | recover template literals with broken expressions ([#64150](https://github.com/angular/angular/pull/64150)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [542cd0019a](https://github.com/angular/angular/commit/542cd0019aa509e399282ccf7cb5fa6208cef70e) | fix | do not rename ARIA property bindings to attributes ([#64089](https://github.com/angular/angular/pull/64089)) |
|
||||
| [0e928fbc4a](https://github.com/angular/angular/commit/0e928fbc4a351303c4ce081a679f4a38c0acd5e6) | fix | Fixes animations in conjunction with content projection ([#63776](https://github.com/angular/angular/pull/63776)) |
|
||||
| [e5157bd933](https://github.com/angular/angular/commit/e5157bd933c41836fb431659f42dfb4cdbe0d2d1) | fix | prevents unintended early termination of leave animations and hoisting ([#64088](https://github.com/angular/angular/pull/64088)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1710cbd7d4](https://github.com/angular/angular/commit/1710cbd7d484ccd5e9ab39b95a44e2d222f4262d) | fix | handle shorthand property declarations in NgModule ([#64160](https://github.com/angular/angular/pull/64160)) |
|
||||
| [77b6305a4b](https://github.com/angular/angular/commit/77b6305a4b5db88f9c1130acf80095b502a0eca1) | fix | skip migration for inputs with 'this' references ([#64142](https://github.com/angular/angular/pull/64142)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.3.2"></a>
|
||||
# 20.3.2 (2025-09-24)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ba40153ac0](https://github.com/angular/angular/commit/ba40153ac07fc721585a1224fda09a654672cb74) | fix | capture metadata for undecorated fields ([#63904](https://github.com/angular/angular/pull/63904)) |
|
||||
| [1d4f81c8ee](https://github.com/angular/angular/commit/1d4f81c8eedf5ea69c51c720f8dc5c5d12a62ba2) | fix | resolve import alias in defer blocks ([#63966](https://github.com/angular/angular/pull/63966)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9515a70933](https://github.com/angular/angular/commit/9515a709331883f0ca9857ed46a5262b01979a26) | fix | fix narrowing of `Resource.hasValue()` ([#63994](https://github.com/angular/angular/pull/63994)) |
|
||||
| [e78451cf8a](https://github.com/angular/angular/commit/e78451cf8a48322879e83b33fecc0b5854947afb) | fix | prevent animations renderer from impacting `animate.leave` ([#63921](https://github.com/angular/angular/pull/63921)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1fd8d5d446](https://github.com/angular/angular/commit/1fd8d5d446f909a16a127ba117a0f423c7a5db0c) | fix | Emit `FormResetEvent` when resetting control ([#64034](https://github.com/angular/angular/pull/64034)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [16d0d43ad4](https://github.com/angular/angular/commit/16d0d43ad4903b69b8dcd9b76c48b5089e7f82ee) | fix | handle import aliases to the same module name ([#63934](https://github.com/angular/angular/pull/63934)) |
|
||||
| [3ebaeccb46](https://github.com/angular/angular/commit/3ebaeccb466119ee43eeaa486f5e132c85e9caa2) | fix | handle reused templates in control flow migration ([#63996](https://github.com/angular/angular/pull/63996)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.3.1"></a>
|
||||
# 20.3.1 (2025-09-17)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7fb5a8087e](https://github.com/angular/angular/commit/7fb5a8087ee8fb0451cedbe6ac4ce972eca4b56e) | fix | Add support for `aria-invalid` ([#63748](https://github.com/angular/angular/pull/63748)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8843707919](https://github.com/angular/angular/commit/88437079190cef9ee522a3e2defa6e2672c2d030) | fix | only bind inputs that are part of microsyntax to a structural directive ([#52453](https://github.com/angular/angular/pull/52453)) |
|
||||
| [38c9921ff3](https://github.com/angular/angular/commit/38c9921ff387d235981a79e26dc8bc7e60a2e10c) | fix | signal not invoked diagnostic not raised when input has same name in template ([#63754](https://github.com/angular/angular/pull/63754)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [802dbcc2a0](https://github.com/angular/angular/commit/802dbcc2a0c5d3784cb04b4c78ea71ed0925327c) | fix | prevent animation events from being cleaned up on destroy ([#63414](https://github.com/angular/angular/pull/63414)) |
|
||||
| [3ec8a5c753](https://github.com/angular/angular/commit/3ec8a5c7536cdd2c1db7db4bfbc2d4995156a833) | fix | Prevent leave animations on a move operation ([#63745](https://github.com/angular/angular/pull/63745)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6e54bdfdcb](https://github.com/angular/angular/commit/6e54bdfdcb01522ee46865fadec911f960fff730) | fix | fix route-lazy-loading migration ([#63818](https://github.com/angular/angular/pull/63818)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.3.0"></a>
|
||||
# 20.3.0 (2025-09-10)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.
|
||||
|
||||
Before:
|
||||
```ts
|
||||
const bootstrap = () => bootstrapApplication(AppComponent, config);
|
||||
```
|
||||
|
||||
After:
|
||||
```ts
|
||||
const bootstrap = (context: BootstrapContext) =>
|
||||
bootstrapApplication(AppComponent, config, context);
|
||||
```
|
||||
|
||||
A schematic is provided to automatically update `main.server.ts` files to pass the `BootstrapContext` to the `bootstrapApplication` call.
|
||||
|
||||
In addition, `getPlatform()` and `destroyPlatform()` will now return `null` and be a no-op respectively when running in a server environment.
|
||||
|
||||
(cherry picked from commit 8bf80c9d2314b4f2bcf3df83ae01552a6fc49834)
|
||||
###
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a3f808d7c8](https://github.com/angular/angular/commit/a3f808d7c8cc59a4fd69f2e4b8d21a6510efa046) | fix | remove refresh button from transfer state tab ([#63592](https://github.com/angular/angular/pull/63592)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6117ccee2e](https://github.com/angular/angular/commit/6117ccee2e1507fb00549cd70e064282645db803) | feat | introduce `BootstrapContext` for improved server bootstrapping ([#63636](https://github.com/angular/angular/pull/63636)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.2.4"></a>
|
||||
# 20.2.4 (2025-09-03)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dc64f3e478](https://github.com/angular/angular/commit/dc64f3e478c5cc1e354a0ff7cf5965b817b345d6) | fix | Fixed inject migration schematics for migrate destructured properties ([#62832](https://github.com/angular/angular/pull/62832)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d1d32db972](https://github.com/angular/angular/commit/d1d32db97260c1e57c2937588002feb4271c7774) | fix | prevent false warning for duplicate state serialization ([#63525](https://github.com/angular/angular/pull/63525)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.2.3"></a>
|
||||
# 20.2.3 (2025-08-29)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [479a919f42](https://github.com/angular/angular/commit/479a919f42517193653384220adab5b89dd74e3d) | fix | fixes regression with event parsing and animate prefix ([#63470](https://github.com/angular/angular/pull/63470)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f87fad3fff](https://github.com/angular/angular/commit/f87fad3fff62cebf2868e06cba48e0f27b719d24) | fix | avoid injecting internal error handler from a destroyed injector ([#62275](https://github.com/angular/angular/pull/62275)) |
|
||||
| [114906d2d6](https://github.com/angular/angular/commit/114906d2d68d98c98961d858abd3ae714d4809a3) | fix | Fix cancellation of animation enter classes ([#63442](https://github.com/angular/angular/pull/63442)) |
|
||||
| [596b545130](https://github.com/angular/angular/commit/596b5451309b8ce4f08a1cd36e6b3610507d52f9) | fix | Prevent an error on cleanup when an `rxResource` `stream` threw before returning an `Observable` ([#63342](https://github.com/angular/angular/pull/63342)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.2.2"></a>
|
||||
# 20.2.2 (2025-08-27)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d7b6045d61](https://github.com/angular/angular/commit/d7b6045d61582d20a17802e769dc1441984988f0) | fix | fixes animations on elements with structural directives ([#63390](https://github.com/angular/angular/pull/63390)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6c421ed65d](https://github.com/angular/angular/commit/6c421ed65d050765a18eafc51fe7257abc5682ce) | fix | Ensures `@for` loop animations never get cancelled ([#63328](https://github.com/angular/angular/pull/63328)) |
|
||||
| [9093e0e132](https://github.com/angular/angular/commit/9093e0e132f99c2b590c31b299871bcd493b7de0) | fix | fix memory leak with leaving nodes tracking ([#63328](https://github.com/angular/angular/pull/63328)) |
|
||||
| [c8f07daf8f](https://github.com/angular/angular/commit/c8f07daf8f2c7e8c6641eb4368379a3f5f1d1f52) | fix | Fixes `animate.leave` binding to a string with spaces ([#63366](https://github.com/angular/angular/pull/63366)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.2.1"></a>
|
||||
# 20.2.1 (2025-08-21)
|
||||
### compiler
|
||||
@@ -150,6 +7,30 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.0-next.0"></a>
|
||||
# 21.0.0-next.0 (2025-08-20)
|
||||
## Breaking Changes
|
||||
### compiler-cli
|
||||
- The Angular compiler now produces an error when the
|
||||
the `emitDeclarationOnly` TS compiler option is enabled as this mode is
|
||||
not supported.
|
||||
### router
|
||||
- `lastSuccessfulNavigation` is now a signal and needs to be invoked
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [be7110342b](https://github.com/angular/angular/commit/be7110342b61d837822524d4f60f56a7f859f594) | fix | disallow compiling with the `emitDeclarationOnly` TS compiler option enabled ([#61609](https://github.com/angular/angular/pull/61609)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4bed062bc9](https://github.com/angular/angular/commit/4bed062bc9f2a0a66c9af3cb8aeb42ee023c6393) | feat | Provide http services in root ([#56212](https://github.com/angular/angular/pull/56212)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4e0fc81491](https://github.com/angular/angular/commit/4e0fc81491bfe6e4eac5c59ef0bde908a3d58413) | feat | convert `lastSuccessfulNavigation` to signal ([#63057](https://github.com/angular/angular/pull/63057)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.2.0"></a>
|
||||
# 20.2.0 (2025-08-20)
|
||||
## Deprecations
|
||||
@@ -234,6 +115,41 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.1.8"></a>
|
||||
# 20.1.8 (2025-08-20)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [691f5ed033](https://github.com/angular/angular/commit/691f5ed0332d813801f599448577a2c1d450a5ad) | fix | error when ng-content fallback has translated children ([#63156](https://github.com/angular/angular/pull/63156)) |
|
||||
| [b1dec9bc50](https://github.com/angular/angular/commit/b1dec9bc50f5694cfa1e3629fd48543126debd10) | fix | incorrect source span for expression AST inside template attribute ([#63175](https://github.com/angular/angular/pull/63175)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cda402f1d8](https://github.com/angular/angular/commit/cda402f1d8bddeedc9aca1979a9bf01be32f81b2) | fix | account for expression with type arguments during HMR extraction ([#63261](https://github.com/angular/angular/pull/63261)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.1.7"></a>
|
||||
# 20.1.7 (2025-08-13)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d9e37908a5](https://github.com/angular/angular/commit/d9e37908a5f42a4226fd6e2d3493abf35ee5a99a) | fix | incorrect spans for AST inside input value with leading space ([#63082](https://github.com/angular/angular/pull/63082)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4aa120ac00](https://github.com/angular/angular/commit/4aa120ac000a569a29e45e9c6db9e4f32c61d183) | fix | error when type checking host bindings of generic directive ([#63061](https://github.com/angular/angular/pull/63061)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [322042c5b3](https://github.com/angular/angular/commit/322042c5b30e181019bfdaa6a57fc5abaea7adc1) | fix | destroying the effect on `afterRenderEffect` ([#63001](https://github.com/angular/angular/pull/63001)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5fd79424e3](https://github.com/angular/angular/commit/5fd79424e34ea4bbbfca68bf80ca5541aece829f) | fix | attempt to resolve component resources in JIT mode ([#63062](https://github.com/angular/angular/pull/63062)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.1.6"></a>
|
||||
# 20.1.6 (2025-08-06)
|
||||
|
||||
|
||||
+16
-23
@@ -5,41 +5,41 @@ module(
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_pkg", version = "1.1.0")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.5.2")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.5.0")
|
||||
bazel_dep(name = "aspect_rules_ts", version = "3.7.0")
|
||||
bazel_dep(name = "aspect_rules_js", version = "2.6.0")
|
||||
bazel_dep(name = "aspect_rules_js", version = "2.5.0")
|
||||
bazel_dep(name = "aspect_rules_esbuild", version = "0.22.1")
|
||||
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.0")
|
||||
bazel_dep(name = "aspect_rules_rollup", version = "2.0.1")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.2")
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.21.2")
|
||||
bazel_dep(name = "tar.bzl", version = "0.5.6")
|
||||
bazel_dep(name = "yq.bzl", version = "0.3.1")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.1")
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.21.1")
|
||||
bazel_dep(name = "tar.bzl", version = "0.5.5")
|
||||
bazel_dep(name = "yq.bzl", version = "0.2.0")
|
||||
bazel_dep(name = "rules_angular")
|
||||
git_override(
|
||||
module_name = "rules_angular",
|
||||
commit = "4010ef96de0c46db7764adc2f262258c9de3d718",
|
||||
commit = "17eac47ea99057f7473a7d93292e76327c894ed9",
|
||||
remote = "https://github.com/devversion/rules_angular.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "devinfra")
|
||||
git_override(
|
||||
module_name = "devinfra",
|
||||
commit = "b7672ff60456719e6d9b0cc052abc73a7adc8df2",
|
||||
commit = "00a4cf14cdc374867673a52ecb556f356da8bec0",
|
||||
remote = "https://github.com/angular/dev-infra.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_sass")
|
||||
git_override(
|
||||
module_name = "rules_sass",
|
||||
commit = "4a54e0e4e75fc6456ff874e53fb4a78bdfeb44b9",
|
||||
commit = "76078d5e9776a0080dcee496e90b88d8a6179c19",
|
||||
remote = "https://github.com/devversion/rules_sass.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_browsers")
|
||||
git_override(
|
||||
module_name = "rules_browsers",
|
||||
commit = "6749ba4c0dc5e04536369fa91fdb2d827b6705ff",
|
||||
commit = "8ee9ae3216ef26516c8ef20537c89857343cdc3a",
|
||||
remote = "https://github.com/devversion/rules_browsers.git",
|
||||
)
|
||||
|
||||
@@ -58,10 +58,6 @@ use_repo(node, "nodejs_linux_s390x")
|
||||
use_repo(node, "nodejs_windows_amd64")
|
||||
|
||||
pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm")
|
||||
pnpm.pnpm(
|
||||
name = "pnpm",
|
||||
pnpm_version = "10.16.1",
|
||||
)
|
||||
use_repo(pnpm, "pnpm")
|
||||
|
||||
npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm")
|
||||
@@ -108,20 +104,17 @@ rules_ts_ext.deps(
|
||||
name = "angular_npm_typescript",
|
||||
# Obtained by: curl --silent https://registry.npmjs.org/typescript/5.9.2 | jq -r '.dist.integrity'
|
||||
ts_integrity = "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
ts_version = "5.9.2",
|
||||
ts_version_from = "//:package.json",
|
||||
)
|
||||
use_repo(rules_ts_ext, **{"npm_typescript": "angular_npm_typescript"})
|
||||
|
||||
# TODO: Figure out how to make ng_project update whenever the packages/core::pkg target changes.
|
||||
rules_angular = use_extension("@rules_angular//setup:extensions.bzl", "rules_angular")
|
||||
|
||||
use_repo_rule("@rules_angular//setup:repositories.bzl", "configurable_deps_repo")(
|
||||
name = "rules_angular_configurable_deps",
|
||||
angular_compiler_cli = "@angular//:node_modules/@angular/compiler-cli",
|
||||
typescript = "@angular//:node_modules/typescript",
|
||||
rules_angular.setup(
|
||||
name = "components_rules_angular_configurable_deps",
|
||||
angular_compiler_cli = "//:node_modules/@angular/compiler-cli",
|
||||
typescript = "//:node_modules/typescript",
|
||||
)
|
||||
|
||||
override_repo(rules_angular, "rules_angular_configurable_deps")
|
||||
use_repo(rules_angular, **{"rules_angular_configurable_deps": "components_rules_angular_configurable_deps"})
|
||||
|
||||
register_toolchains(
|
||||
"@devinfra//bazel/git-toolchain:git_linux_toolchain",
|
||||
|
||||
Generated
+98
-42
@@ -16,8 +16,8 @@
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.11.0/MODULE.bazel": "cb1ba9f9999ed0bc08600c221f532c1ddd8d217686b32ba7d45b0713b5131452",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.14.0/MODULE.bazel": "2b31ffcc9bdc8295b2167e07a757dbbc9ac8906e7028e5170a3708cecaac119f",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.3/MODULE.bazel": "253d739ba126f62a5767d832765b12b59e9f8d2bc88cc1572f4a73e46eb298ca",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.21.2/MODULE.bazel": "276347663a25b0d5bd6cad869252bea3e160c4d980e764b15f3bae7f80b30624",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.21.2/source.json": "f42051fa42629f0e59b7ac2adf0a55749144b11f1efcd8c697f0ee247181e526",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.21.1/MODULE.bazel": "07e3ce3eaaa50dbd0be7fa0094e36890478937adc780ec53e77fd9fe543af8b1",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.21.1/source.json": "cb7d22ce044efa47c6e251107a35b8a919f5cd35254190d825adff1b7ae21e6e",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.7.7/MODULE.bazel": "491f8681205e31bb57892d67442ce448cda4f472a8e6b3dc062865e29a64f89c",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "812d2dd42f65dca362152101fbec418029cc8fd34cbad1a2fde905383d705838",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.9.3/MODULE.bazel": "66baf724dbae7aff4787bf2245cc188d50cb08e07789769730151c0943587c14",
|
||||
@@ -27,8 +27,8 @@
|
||||
"https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.0/source.json": "45fa9603cdfe100575a12d8b65fa425fe8713dd8c9f0cdf802168b670bc0e299",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.0.0/MODULE.bazel": "b45b507574aa60a92796e3e13c195cd5744b3b8aff516a9c0cb5ae6a048161c5",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.4.2/MODULE.bazel": "0d01db38b96d25df7ed952a5e96eac4b3802723d146961974bf020f6dd07591d",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.6.0/MODULE.bazel": "5a6f8dbc5b170769453f1819d469fe54b0e4b86a0e82e13fde8e5a45438a1890",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.6.0/source.json": "e1e20b259d4f1b0a5d8b99d57b418c96f306e1c77f96e9ea1c9f1068a628b211",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.5.0/MODULE.bazel": "12bb9ffdfda5b952644ffa75a69fac1e63da788ad445b056d3ccc70ad39825ac",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.5.0/source.json": "884ab90109fb7b92488d8187dfd8e0b93be105d2e42b06d887ab4730ba7d77da",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_rollup/2.0.1/MODULE.bazel": "296e3a053658c2af989ba9bd62a205e6d1fa84bdd6dd5249196546e6b84770ec",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_rollup/2.0.1/source.json": "2fe8ac1ccb4de74bf884761e070010280b272d94e3997205b361b91c75409726",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.6.3/MODULE.bazel": "d09db394970f076176ce7bab5b5fa7f0d560fd4f30b8432ea5e2c2570505b130",
|
||||
@@ -49,8 +49,6 @@
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.34.0/source.json": "dfa5c4b01110313153b484a735764d247fee5624bbab63d25289e43b151a657a",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
|
||||
"https://bcr.bazel.build/modules/bazel_lib/3.0.0-beta.1/MODULE.bazel": "407729e232f611c3270005b016b437005daa7b1505826798ea584169a476e878",
|
||||
"https://bcr.bazel.build/modules/bazel_lib/3.0.0-beta.1/source.json": "72bfbe19a3936675719157798de64631e9ac54c2b41f13b544b821d094f4840a",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
|
||||
@@ -64,8 +62,7 @@
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.8.1/source.json": "7ebaefba0b03efe59cac88ed5bbc67bcf59a3eff33af937345ede2a38b2d368a",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||
"https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8",
|
||||
@@ -152,8 +149,7 @@
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.2.0/MODULE.bazel": "ec27907f55eb34705adb4e8257952162a2d4c3ed0f0b3b4c3c1aad1fac7be35e",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.3.0/MODULE.bazel": "45345e4aba35dd6e4701c1eebf5a4e67af4ed708def9ebcdc6027585b34ee52d",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.0/MODULE.bazel": "546d0cf79f36f9f6e080816045f97234b071c205f4542e3351bd4424282a8810",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.2/MODULE.bazel": "7f9ea68a0ce6d82905ce9f74e76ab8a8b4531ed4c747018c9d76424ad0b3370d",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.2/source.json": "6a6ca0940914d55c550d1417cad13a56c9900e23f651a762d8ccc5a64adcf661",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.0/source.json": "ac075bc5babebc25a0adc88ee885f2c8d8520d141f6e139ba9dfa0eedb5be908",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/1.1.0/MODULE.bazel": "9db8031e71b6ef32d1846106e10dd0ee2deac042bd9a2de22b4761b0c3036453",
|
||||
@@ -187,13 +183,12 @@
|
||||
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.6/MODULE.bazel": "c5b8bfa6bc7b640883d41bfec4a200fb45c16a2a7b2fb081323f499197cfcc09",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.6/source.json": "848b3a4eaf2bb4a09ab78533c348e19a6723c7d5f820eb1dceb0eeb5e5914ac1",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.5/MODULE.bazel": "4bfab9bbc7a1966c2c5f7371f5848f5e2d27c465951b4435adc9aaf00ed681da",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.5/source.json": "67c322bd9f9a6714b9d55d4df36ddc222976a7fbb2070410ef036f68cdf2eeb7",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.2.0/MODULE.bazel": "6f3a675677db8885be4d607fde14cc51829715e3a879fb016eb9bf336786ce6d",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.1/MODULE.bazel": "9bcb7151b3cd4681b89d350530eaf7b45e32a44dda94843b8932b0cb1cd4594a",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.1/source.json": "f0b0f204a2a6b0e34b4c9541efe8c04f2ef1af65948daa784eccea738b21dbd2",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.2.0/source.json": "ff33c6f75da6848caade494240b6824cf00e7e6b8892100f4253984e1dfae2af",
|
||||
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
|
||||
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
|
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
|
||||
@@ -232,7 +227,7 @@
|
||||
},
|
||||
"@@aspect_rules_esbuild~//esbuild:extensions.bzl%esbuild": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "NeP8heP5Z49UtK5ZkdaSGN2wdf2vyTLxJfpSPeyvV24=",
|
||||
"bzlTransitiveDigest": "D8qNgGrrdZct3S3KMxl6kgSKedwrEWvW34y5AVoV4PQ=",
|
||||
"usagesDigest": "u8wMZJd6Ovxb3YTmhoM3sMbh11Qwrv5EHaggdNi5Wb8=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -412,8 +407,8 @@
|
||||
},
|
||||
"@@aspect_rules_js~//npm:extensions.bzl%pnpm": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "eebwHza1XBCmrNmoTUnW56khfYFfcwZpPWjM1Nvu3sk=",
|
||||
"usagesDigest": "LXGqD89vujoiYUGLlPI1UcHEdy3p899TrYwtpQUR2hM=",
|
||||
"bzlTransitiveDigest": "0Kn7fvnVxLaVWd5Q+UPHLEIH0A8dYAnRoL8iW6cFIJI=",
|
||||
"usagesDigest": "iPZn5zAjYcx2ly5xwkl7dCcCxl5n+ty6enw5W6/RG3o=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -423,11 +418,11 @@
|
||||
"ruleClassName": "npm_import_rule",
|
||||
"attributes": {
|
||||
"package": "pnpm",
|
||||
"version": "10.16.1",
|
||||
"version": "8.6.7",
|
||||
"root_package": "",
|
||||
"link_workspace": "",
|
||||
"link_packages": {},
|
||||
"integrity": "sha512-DhVaomKduGcrSehHXaYiaqS96oX9zf3BU1CHSUbU88kfqvZMvcSl0auAAvRz1cP87c0ZeYnPA5D5ut08BGeHBg==",
|
||||
"integrity": "sha512-vRIWpD/L4phf9Bk2o/O2TDR8fFoJnpYrp2TKqTIZF/qZ2/rgL3qKXzHofHgbXsinwMoSEigz28sqk3pQ+yMEQQ==",
|
||||
"url": "",
|
||||
"commit": "",
|
||||
"patch_args": [
|
||||
@@ -452,7 +447,7 @@
|
||||
"ruleClassName": "npm_import_links",
|
||||
"attributes": {
|
||||
"package": "pnpm",
|
||||
"version": "10.16.1",
|
||||
"version": "8.6.7",
|
||||
"dev": false,
|
||||
"root_package": "",
|
||||
"link_packages": {},
|
||||
@@ -550,8 +545,10 @@
|
||||
"@@aspect_rules_ts~//ts:extensions.bzl%ext": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "9IJp6IlB/FMHFBJe4MX/DQM4zi3oArC8yqYE/+NyPwk=",
|
||||
"usagesDigest": "dQksgKjptt43p6K/aEOYjcWKS47HbtBzBSMhEYqUYts=",
|
||||
"usagesDigest": "1rX5zKEA5AF0V7MwOa4Uu00O9/xtmOXAgV3jUGUxeQk=",
|
||||
"recordedFileInputs": {
|
||||
"@@//package.json": "ec188498a5070d792486104602dac93c675ca86076b1b91bcd9927985ea3d738",
|
||||
"@@devinfra~//bazel/package.json": "960bcecf963a211f96a3967c7cfb5d3e1cea08d94b27056a3e8dbf2fad1e2dd3",
|
||||
"@@rules_browsers~//package.json": "45572077938c7a4916e4aaedf7db7ce8425854ab92f35348cff02a2134023bb8"
|
||||
},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -561,7 +558,8 @@
|
||||
"bzlFile": "@@aspect_rules_ts~//ts/private:npm_repositories.bzl",
|
||||
"ruleClassName": "http_archive_version",
|
||||
"attributes": {
|
||||
"version": "5.9.2",
|
||||
"version": "",
|
||||
"version_from": "@@//:package.json",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"urls": [
|
||||
"https://registry.npmjs.org/typescript/-/typescript-{}.tgz"
|
||||
@@ -583,7 +581,8 @@
|
||||
"bzlFile": "@@aspect_rules_ts~//ts/private:npm_repositories.bzl",
|
||||
"ruleClassName": "http_archive_version",
|
||||
"attributes": {
|
||||
"version": "5.9.2",
|
||||
"version": "",
|
||||
"version_from": "@@devinfra~//bazel:package.json",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"urls": [
|
||||
"https://registry.npmjs.org/typescript/-/typescript-{}.tgz"
|
||||
@@ -625,7 +624,7 @@
|
||||
"@@aspect_tools_telemetry~//:extension.bzl%telemetry": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "gA7tPEdJXhskzPIEUxjX9IdDrM6+WjfbgXJ8Ez47umk=",
|
||||
"usagesDigest": "GEL1puRyMuoDKpELV0EDVcA/hQ0OdxZ9UR/t2Vtj7a0=",
|
||||
"usagesDigest": "tH6KsPz1uWO2OjNaRD1bEd5rnHtyNuMwWpFkIds3hg0=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -636,7 +635,7 @@
|
||||
"attributes": {
|
||||
"deps": {
|
||||
"aspect_rules_ts": "3.7.0",
|
||||
"aspect_rules_js": "2.6.0",
|
||||
"aspect_rules_js": "2.5.0",
|
||||
"aspect_tools_telemetry": "0.2.8"
|
||||
}
|
||||
}
|
||||
@@ -695,11 +694,19 @@
|
||||
"@@rules_angular~//setup:extensions.bzl%rules_angular": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "fkaH7HMicL3g7/NDaFzlq39kcLopMyQ3KdbDn+5CRzA=",
|
||||
"usagesDigest": "c/HgGZ21I+QxW0XkaMGJK0N3nV5rdEiNEcPkToa4i9M=",
|
||||
"usagesDigest": "1oeycgV+w0mSegt2ycKii5zoBkwEZzF4+hcp4rOX7sg=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"components_rules_angular_configurable_deps": {
|
||||
"bzlFile": "@@rules_angular~//setup:repositories.bzl",
|
||||
"ruleClassName": "configurable_deps_repo",
|
||||
"attributes": {
|
||||
"angular_compiler_cli": "@@rules_angular~//:node_modules/@angular/compiler-cli",
|
||||
"typescript": "@@rules_angular~//:node_modules/typescript"
|
||||
}
|
||||
},
|
||||
"rules_angular_configurable_deps": {
|
||||
"bzlFile": "@@rules_angular~//setup:repositories.bzl",
|
||||
"ruleClassName": "configurable_deps_repo",
|
||||
@@ -1129,8 +1136,8 @@
|
||||
},
|
||||
"@@rules_nodejs~//nodejs:extensions.bzl%node": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "FmfMiNXAxRoLWw3NloQbssosE1egrSvzirbQnso7j7E=",
|
||||
"usagesDigest": "xHkFztDWYtKJ37XnwOK4sKovvRwpnGtzZns6k+dDdyI=",
|
||||
"bzlTransitiveDigest": "hdICB1K7PX7oWtO8oksVTBDNt6xxiNERpcO4Yxoa0Gc=",
|
||||
"usagesDigest": "wKnieRDVg5P05DNKjiUSVbzaCxzv9IOZ9TE2JMxlfrg=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -4132,7 +4139,7 @@
|
||||
},
|
||||
"@@rules_sass~//src/toolchain:extensions.bzl%sass": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "RA58Nyrsn03Z5YmQnpmBw3mqlVck++XIrx34amsqU/E=",
|
||||
"bzlTransitiveDigest": "+GauQp6nWf/mHsJ/XVWUL2JTuC15MuxATrVcAgDpclc=",
|
||||
"usagesDigest": "FPXQ5+6+DFGdSdCMXLwFaruzstMFlLH6N0TRxi0sSH8=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -4150,18 +4157,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"linux_arm64_sass": {
|
||||
"bzlFile": "@@rules_sass~//src/toolchain:configure_sass.bzl",
|
||||
"ruleClassName": "configure_sass",
|
||||
"attributes": {
|
||||
"file": "@rules_sass//src/compiler/built:sass_linux_arm",
|
||||
"sha256": "",
|
||||
"constraints": [
|
||||
"@@platforms//os:linux",
|
||||
"@@platforms//cpu:arm64"
|
||||
]
|
||||
}
|
||||
},
|
||||
"darwin_amd64_sass": {
|
||||
"bzlFile": "@@rules_sass~//src/toolchain:configure_sass.bzl",
|
||||
"ruleClassName": "configure_sass",
|
||||
@@ -4190,10 +4185,71 @@
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@tar.bzl~//tar:extensions.bzl%toolchains": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "x8T4avQwaccwFRDkBObSMray93ZBHwpcjsZTPQOyII0=",
|
||||
"usagesDigest": "aQJiuhjXhigIjDvDZxsHPfosrrHvNBHV55yj8QdZQgs=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"bsd_tar_toolchains": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:toolchain.bzl",
|
||||
"ruleClassName": "tar_toolchains_repo",
|
||||
"attributes": {
|
||||
"user_repository_name": "bsd_tar_toolchains"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_darwin_amd64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "darwin_amd64"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_darwin_arm64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "darwin_arm64"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_linux_amd64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "linux_amd64"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_linux_arm64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "linux_arm64"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_windows_amd64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "windows_amd64"
|
||||
}
|
||||
},
|
||||
"bsd_tar_toolchains_windows_arm64": {
|
||||
"bzlFile": "@@tar.bzl~//tar/toolchain:platforms.bzl",
|
||||
"ruleClassName": "bsdtar_binary_repo",
|
||||
"attributes": {
|
||||
"platform": "windows_arm64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@yq.bzl~//yq:extensions.bzl%yq": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "61Uz+o5PnlY0jJfPZEUNqsKxnM/UCLeWsn5VVCc8u5Y=",
|
||||
"usagesDigest": "nLGf5KtJBc5QgdHE6qeQEjHPMTR04zHAEmjUJdZfZyo=",
|
||||
"usagesDigest": "hTf7RXXlm85DQds3r44JRfN0JwKFbTZsXmDKAzPHvAo=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
|
||||
+40
-47
@@ -1,3 +1,4 @@
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
load("@npm//:defs.bzl", "npm_link_all_packages")
|
||||
load("@rules_angular//src/architect:ng_application.bzl", "ng_application")
|
||||
load("@rules_angular//src/architect:ng_config.bzl", "ng_config")
|
||||
@@ -62,12 +63,7 @@ APPLICATION_DEPS = [
|
||||
"//adev:node_modules/@types/node",
|
||||
"//adev:node_modules/@types/dom-navigation",
|
||||
|
||||
# The imports below are packages that our code does not directly import, but our upstream deps import from
|
||||
# these locations directly. By design, rather than hoisting these packages into the "root" node_modules the
|
||||
# dependency is found in (i.e. ./adev/node_modules), rules_js places all of each package's dependencies in
|
||||
# a "hoisted" location within the `.aspect_rules_js/` directories in the node_modules directory. This prevents
|
||||
# the bundler from being able to find it as expected. We instead specifically provide it as a dep within bazel
|
||||
# as a mechanism of "hoisting" the package for our usage by this target.
|
||||
# Deep imports
|
||||
"//adev:node_modules/@algolia/client-common",
|
||||
"//adev:node_modules/@algolia/requester-browser-xhr",
|
||||
"//adev:node_modules/@algolia/requester-node-http",
|
||||
@@ -98,56 +94,53 @@ TEST_DEPS = [
|
||||
|
||||
ng_config(name = "ng_config")
|
||||
|
||||
ng_application(
|
||||
name = "build",
|
||||
srcs = APPLICATION_FILES + APPLICATION_DEPS,
|
||||
args = [
|
||||
bool_flag(
|
||||
name = "full_build_adev",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "prod_build",
|
||||
flag_values = {
|
||||
":full_build_adev": "true",
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "dev_build",
|
||||
flag_values = {
|
||||
":full_build_adev": "false",
|
||||
},
|
||||
)
|
||||
|
||||
config_based_architect_env = select({
|
||||
":dev_build": {
|
||||
"NG_BUILD_PARTIAL_SSR": "1",
|
||||
},
|
||||
":prod_build": {
|
||||
"NG_BUILD_OPTIMIZE_CHUNKS": "1",
|
||||
},
|
||||
})
|
||||
|
||||
config_based_architect_flags = select({
|
||||
":dev_build": [
|
||||
"--configuration",
|
||||
"development",
|
||||
],
|
||||
env = {
|
||||
"NG_BUILD_PARTIAL_SSR": "1",
|
||||
},
|
||||
ng_config = ":ng_config",
|
||||
node_modules = "//adev:node_modules",
|
||||
project_name = "angular-dev",
|
||||
serve_args = [
|
||||
"--port",
|
||||
"4201",
|
||||
],
|
||||
tags = [
|
||||
# Tagged as manual as both build and build.production use the same output directory.
|
||||
"manual",
|
||||
# RBE significantly slows down the build because the CLI executes multiple CPU-intensive instances of esbuild.
|
||||
# Furthermore, the current RBE machine pool lacks high-spec machines.
|
||||
"no-remote-exec",
|
||||
],
|
||||
)
|
||||
|
||||
ng_application(
|
||||
name = "build.production",
|
||||
srcs = APPLICATION_FILES + APPLICATION_DEPS,
|
||||
args = [
|
||||
":prod_build": [
|
||||
"--configuration",
|
||||
"production",
|
||||
],
|
||||
env = {
|
||||
"NG_BUILD_OPTIMIZE_CHUNKS": "1",
|
||||
},
|
||||
})
|
||||
|
||||
ng_application(
|
||||
name = "build",
|
||||
srcs = APPLICATION_FILES + APPLICATION_DEPS,
|
||||
args = config_based_architect_flags,
|
||||
env = config_based_architect_env,
|
||||
ng_config = ":ng_config",
|
||||
node_modules = "//adev:node_modules",
|
||||
project_name = "angular-dev",
|
||||
serve_args = [
|
||||
"--port",
|
||||
"4201",
|
||||
],
|
||||
tags = [
|
||||
# Tagged as manual as both build and build.production use the same output directory.
|
||||
"manual",
|
||||
# RBE significantly slows down the build because the CLI executes multiple CPU-intensive instances of esbuild.
|
||||
# Furthermore, the current RBE machine pool lacks high-spec machines.
|
||||
"no-remote-exec",
|
||||
],
|
||||
)
|
||||
|
||||
ng_test(
|
||||
|
||||
@@ -51,14 +51,3 @@ pnpm bazel clean
|
||||
# If that doesn't work, try it with the expunge flag
|
||||
pnpm bazel clean --expunge
|
||||
```
|
||||
|
||||
|
||||
## High level architecture
|
||||
|
||||
The angular.dev website is a modern Angular application that utilizes Static Site Generation (SSG) to deliver pre-rendered, high-performance content to users.
|
||||
|
||||
The architecture is designed for efficiency and maintainability:
|
||||
|
||||
Content Sources: The documentation is sourced from two main places within the monorepo. The guides and tutorials are written in Markdown files, while the API reference pages are automatically generated by extracting documentation directly from the TypeScript source code of the Angular framework packages.
|
||||
|
||||
Build Process: During the build process, the Markdown files are converted into HTML. Simultaneously, the API documentation is extracted from the code comments. This content is then integrated into the Angular application.
|
||||
+7
-7
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@angular-devkit/build-angular": "20.3.3",
|
||||
"@angular-devkit/build-angular": "21.0.0-next.0",
|
||||
"@angular/animations": "workspace:*",
|
||||
"@angular/build": "20.3.3",
|
||||
"@angular/cdk": "20.2.7",
|
||||
"@angular/cli": "20.3.3",
|
||||
"@angular/build": "21.0.0-next.0",
|
||||
"@angular/cdk": "21.0.0-next.0",
|
||||
"@angular/cli": "21.0.0-next.0",
|
||||
"@angular/common": "workspace:*",
|
||||
"@angular/compiler-cli": "workspace:*",
|
||||
"@angular/compiler": "workspace:*",
|
||||
"@angular/core": "workspace:*",
|
||||
"@angular/docs": "workspace:*",
|
||||
"@angular/forms": "workspace:*",
|
||||
"@angular/material": "20.2.7",
|
||||
"@angular/material": "21.0.0-next.0",
|
||||
"@angular/platform-browser": "workspace:*",
|
||||
"@angular/platform-server": "workspace:*",
|
||||
"@angular/router": "workspace:*",
|
||||
"@angular/ssr": "20.3.3",
|
||||
"@angular/ssr": "21.0.0-next.0",
|
||||
"@codemirror/autocomplete": "6.18.6",
|
||||
"@codemirror/commands": "6.8.1",
|
||||
"@codemirror/lang-angular": "0.1.4",
|
||||
@@ -53,7 +53,7 @@
|
||||
"karma-jasmine-html-reporter": "2.1.0",
|
||||
"karma-jasmine": "5.1.0",
|
||||
"marked": "16.2.0",
|
||||
"mermaid": "11.10.0",
|
||||
"mermaid": "11.10.1",
|
||||
"ngx-progressbar": "14.0.0",
|
||||
"open-in-idx": "0.1.1",
|
||||
"playwright-core": "1.55.0",
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
//tslint:disable:no-console
|
||||
import assert from 'node:assert';
|
||||
import {execSync} from 'node:child_process';
|
||||
import {existsSync, constants as fsConstants} from 'node:fs';
|
||||
import {copyFile, mkdtemp, readdir, readFile, realpath, unlink, writeFile} from 'node:fs/promises';
|
||||
@@ -20,93 +19,72 @@ export async function copyJsonAssets({repo, githubApi, assetsPath, destPath}) {
|
||||
throw new Error(`${buildInfoPath} does not exist.`);
|
||||
}
|
||||
|
||||
assert(process.env.GITHUB_REF);
|
||||
const currentBranch = process.env.GITHUB_REF;
|
||||
const branch = process.env.GITHUB_REF;
|
||||
const {sha: currentSha} = JSON.parse(await readFile(buildInfoPath, 'utf-8'));
|
||||
const latestSha = await githubApi.getShaForBranch(branch);
|
||||
|
||||
const {sha: storedSha, branchName: storedBranch} = JSON.parse(
|
||||
await readFile(buildInfoPath, 'utf-8'),
|
||||
);
|
||||
|
||||
let downstreamBranch = currentBranch;
|
||||
let latestSha = await githubApi.getShaForBranch(currentBranch);
|
||||
if (
|
||||
latestSha.includes('No commit') &&
|
||||
currentBranch !== 'refs/heads/main' &&
|
||||
currentBranch !== storedBranch
|
||||
) {
|
||||
// In some cases, such as when a new branch is created for a feature,
|
||||
// the branch may not exist in the downstream repo. For example, during an
|
||||
// exceptional minor release (e.g. FW 20.3.x and Components: 20.2.x).
|
||||
// In such scenarios, we fallback to the last known branch.
|
||||
latestSha = await githubApi.getShaForBranch(storedBranch);
|
||||
downstreamBranch = storedBranch;
|
||||
}
|
||||
|
||||
console.log(`Comparing ${storedSha}...${latestSha}.`);
|
||||
const affectedFiles = await githubApi.getAffectedFiles(storedSha, latestSha);
|
||||
console.log(`Comparing ${currentSha}...${latestSha}.`);
|
||||
const affectedFiles = await githubApi.getAffectedFiles(currentSha, latestSha);
|
||||
const changedFiles = affectedFiles.filter((file) => file.startsWith(`${assetsPath}/`));
|
||||
|
||||
let shaWhenFilesChanged;
|
||||
if (changedFiles.length > 0) {
|
||||
console.log(
|
||||
`The below files changed between ${storedSha} and ${latestSha}:\n` +
|
||||
changedFiles.map((f) => '* ' + f).join('\n'),
|
||||
);
|
||||
|
||||
const temporaryDir = await realpath(await mkdtemp(join(tmpdir(), 'copy-json-assets-')));
|
||||
const execOptions = {cwd: temporaryDir, stdio: 'inherit'};
|
||||
execSync('git init', execOptions);
|
||||
execSync(`git remote add origin https://github.com/${repo}.git`, execOptions);
|
||||
// fetch a commit
|
||||
execSync(`git fetch origin ${latestSha}`, execOptions);
|
||||
// reset this repository's main branch to the commit of interest
|
||||
execSync('git reset --hard FETCH_HEAD', execOptions);
|
||||
// get sha when files where changed
|
||||
shaWhenFilesChanged = execSync(`git rev-list -1 ${latestSha} "${assetsPath}/"`, {
|
||||
encoding: 'utf8',
|
||||
cwd: temporaryDir,
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
}).trim();
|
||||
|
||||
// Delete existing asset files.
|
||||
const apiFilesUnlink = (await readdir(destPath))
|
||||
.filter((f) => f.endsWith('.json'))
|
||||
.map((f) => unlink(join(destPath, f)));
|
||||
|
||||
await Promise.allSettled(apiFilesUnlink);
|
||||
|
||||
// Copy new asset files
|
||||
const tempAssetsDir = join(temporaryDir, assetsPath);
|
||||
const assetFilesCopy = (await readdir(tempAssetsDir)).map((f) => {
|
||||
const src = join(tempAssetsDir, f);
|
||||
const dest = join(destPath, f);
|
||||
|
||||
return copyFile(src, dest, fsConstants.COPYFILE_FICLONE);
|
||||
});
|
||||
|
||||
await Promise.allSettled(assetFilesCopy);
|
||||
|
||||
console.log(`Successfully updated asset files in '${destPath}'.\n`);
|
||||
} else {
|
||||
console.log(`No '${assetsPath}/**' files changed between ${storedSha} and ${latestSha}.`);
|
||||
if (changedFiles.length === 0) {
|
||||
console.log(`No '${assetsPath}/**' files changed between ${currentSha} and ${latestSha}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`The below files changed between ${currentSha} and ${latestSha}:\n` +
|
||||
changedFiles.map((f) => '* ' + f).join('\n'),
|
||||
);
|
||||
|
||||
const temporaryDir = await realpath(await mkdtemp(join(tmpdir(), 'copy-json-assets-')));
|
||||
const execOptions = {cwd: temporaryDir, stdio: 'inherit'};
|
||||
execSync('git init', execOptions);
|
||||
execSync(`git remote add origin https://github.com/${repo}.git`, execOptions);
|
||||
// fetch a commit
|
||||
execSync(`git fetch origin ${latestSha}`, execOptions);
|
||||
// reset this repository's main branch to the commit of interest
|
||||
execSync('git reset --hard FETCH_HEAD', execOptions);
|
||||
// get sha when files where changed
|
||||
const shaWhenFilesChanged = execSync(`git rev-list -1 ${latestSha} "${assetsPath}/"`, {
|
||||
encoding: 'utf8',
|
||||
cwd: temporaryDir,
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
}).trim();
|
||||
|
||||
// Delete existing asset files.
|
||||
const apiFilesUnlink = (await readdir(destPath))
|
||||
.filter((f) => f.endsWith('.json'))
|
||||
.map((f) => unlink(join(destPath, f)));
|
||||
|
||||
await Promise.allSettled(apiFilesUnlink);
|
||||
|
||||
// Copy new asset files
|
||||
const tempAssetsDir = join(temporaryDir, assetsPath);
|
||||
const assetFilesCopy = (await readdir(tempAssetsDir)).map((f) => {
|
||||
const src = join(tempAssetsDir, f);
|
||||
const dest = join(destPath, f);
|
||||
|
||||
return copyFile(src, dest, fsConstants.COPYFILE_FICLONE);
|
||||
});
|
||||
|
||||
await Promise.allSettled(assetFilesCopy);
|
||||
|
||||
// Write SHA to file.
|
||||
await writeFile(
|
||||
buildInfoPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
branchName: downstreamBranch,
|
||||
sha: shaWhenFilesChanged ?? storedSha,
|
||||
branchName: branch,
|
||||
sha: shaWhenFilesChanged,
|
||||
},
|
||||
undefined,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
// The below command will show uncommitted changes.
|
||||
// This is expected because the framework repo and component/cli might have different minors
|
||||
// (e.g. during exceptional minor releases), leading to changes that need to be committed.
|
||||
console.log('\nChanges: ');
|
||||
execSync(`git status --porcelain`, {stdio: 'inherit'});
|
||||
|
||||
console.log(`Successfully updated asset files in '${destPath}'.\n`);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import {RouterLink} from '@angular/router';
|
||||
export class Breadcrumb {
|
||||
private readonly navigationState = inject(NavigationState);
|
||||
|
||||
readonly breadcrumbItems = computed(() => {
|
||||
breadcrumbItems = computed(() => {
|
||||
const breadcrumbs: NavigationItem[] = [];
|
||||
let activeItem = this.navigationState.activeNavigationItem()?.parent;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div>
|
||||
<a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">
|
||||
<button type="button" class="docs-primary-btn" [attr.text]="'Learn more'" aria-label="Learn More">
|
||||
<button class="docs-primary-btn" [attr.text]="'Learn more'" aria-label="Learn More">
|
||||
Learn more
|
||||
</button>
|
||||
</a>
|
||||
|
||||
@@ -11,7 +11,7 @@ import {LOCAL_STORAGE} from '../../providers/index';
|
||||
import {setCookieConsent} from '../../utils';
|
||||
|
||||
/**
|
||||
* Declare gtag as part of the window in this file as gtag is expected to already be loaded.
|
||||
* Decelare gtag as part of the window in this file as gtag is expected to already be loaded.
|
||||
*/
|
||||
declare const window: Window & typeof globalThis & {gtag?: Function};
|
||||
|
||||
@@ -27,7 +27,7 @@ export class CookiePopup {
|
||||
private readonly localStorage = inject(LOCAL_STORAGE);
|
||||
|
||||
/** Whether the user has accepted the cookie disclaimer. */
|
||||
readonly hasAccepted = signal(false);
|
||||
hasAccepted = signal<boolean>(false);
|
||||
|
||||
constructor() {
|
||||
// Needs to be in a try/catch, because some browsers will
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import {
|
||||
inject,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
|
||||
@@ -23,7 +24,7 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 2000;
|
||||
|
||||
@Component({
|
||||
selector: 'button[docs-copy-source-code]',
|
||||
imports: [IconComponent],
|
||||
imports: [CommonModule, IconComponent],
|
||||
templateUrl: './copy-source-code-button.component.html',
|
||||
host: {
|
||||
'type': 'button',
|
||||
|
||||
@@ -20,7 +20,6 @@ ng_project(
|
||||
"//adev:node_modules/@angular/material",
|
||||
"//adev:node_modules/@angular/router",
|
||||
"//adev/shared-docs/components/icon",
|
||||
"//adev/shared-docs/components/slide-toggle",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/pipes",
|
||||
"//adev/shared-docs/services",
|
||||
|
||||
@@ -3,115 +3,106 @@
|
||||
class="docs-navigation-list docs-faceted-list"
|
||||
[class.docs-navigation-list-dropdown]="isDropdownView()"
|
||||
>
|
||||
@for (itemGroup of groupItems(navigationItems); track $index) {
|
||||
@let groupLabel = itemGroup[0];
|
||||
@let items = itemGroup[1];
|
||||
@if (groupLabel) {
|
||||
<li class="docs-navigation-group">{{groupLabel | titlecase}}</li>
|
||||
}
|
||||
@for (item of items; track $index) {
|
||||
<li class="docs-faceted-list-item">
|
||||
@if (item.path) {
|
||||
@if (item.isExternal) {
|
||||
<a
|
||||
[href]="item.path"
|
||||
target="_blank"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
@for (item of navigationItems; track $index) {
|
||||
<li class="docs-faceted-list-item">
|
||||
@if (item.path) {
|
||||
@if (item.isExternal) {
|
||||
<a
|
||||
[href]="item.path"
|
||||
target="_blank"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
<span
|
||||
[class.docs-external-link]="item.isExternal"
|
||||
class="docs-faceted-list-item-text"
|
||||
>
|
||||
<span
|
||||
[class.docs-external-link]="item.isExternal"
|
||||
class="docs-faceted-list-item-text"
|
||||
>
|
||||
{{ item.label }}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
{{ item.label }}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
|
||||
@if (item.children && item.level! > 1 && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<a
|
||||
[routerLink]="'/' + item.path"
|
||||
routerLinkActive="docs-faceted-list-item-active"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
(click)="emitClickOnLink()"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{item.label}}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
|
||||
@if (item.children && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
@if (item.children && item.level! > 1 && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<!-- Nav Section Header -->
|
||||
@if (item.level !== collapsableLevel() && item.level !== expandableLevel()) {
|
||||
<div
|
||||
class="docs-secondary-nav-header"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{item.label}}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
<a
|
||||
[routerLink]="'/' + item.path"
|
||||
routerLinkActive="docs-faceted-list-item-active"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
(click)="emitClickOnLink()"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{item.label}}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
|
||||
<!-- Nav Button Expand/Collapse -->
|
||||
@if (
|
||||
(item.children && item.level === expandableLevel()) || item.level === collapsableLevel()
|
||||
) {
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(item)"
|
||||
[attr.aria-label]="(item.isExpanded ? 'Collapse' : 'Expand') + ' ' + item.label"
|
||||
[attr.aria-expanded]="item.isExpanded"
|
||||
class="docs-secondary-nav-button"
|
||||
[class.docs-faceted-list-item-active]="item | isActiveNavigationItem: activeItem()"
|
||||
[class.docs-expanded-button]="item.children && item.level == collapsableLevel()"
|
||||
[class.docs-not-expanded-button]="item.children && item.level === expandableLevel()"
|
||||
[class.docs-nav-item-has-icon]="
|
||||
@if (item.children && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
} @else {
|
||||
<!-- Nav Section Header -->
|
||||
@if (item.level !== collapsableLevel() && item.level !== expandableLevel()) {
|
||||
<div
|
||||
class="docs-secondary-nav-header"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{item.label}}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Nav Button Expand/Collapse -->
|
||||
@if (
|
||||
(item.children && item.level === expandableLevel()) || item.level === collapsableLevel()
|
||||
) {
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(item)"
|
||||
[attr.aria-label]="(item.isExpanded ? 'Collapse' : 'Expand') + ' ' + item.label"
|
||||
[attr.aria-expanded]="item.isExpanded"
|
||||
class="docs-secondary-nav-button"
|
||||
[class.docs-faceted-list-item-active]="item | isActiveNavigationItem: activeItem()"
|
||||
[class.docs-expanded-button]="item.children && item.level == collapsableLevel()"
|
||||
[class.docs-not-expanded-button]="item.children && item.level === expandableLevel()"
|
||||
[class.docs-nav-item-has-icon]="
|
||||
item.children && item.level === expandableLevel() && !item.isExpanded"
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
@if (item.children && item.level === collapsableLevel()) {
|
||||
<docs-icon>arrow_back</docs-icon>
|
||||
}
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{ item.label }}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
</button>
|
||||
}
|
||||
[matTooltip]="item.label"
|
||||
[matTooltipDisabled]="item.label.length < 27"
|
||||
matTooltipPosition="after"
|
||||
[attr.aria-label]="item.label"
|
||||
[matTooltipClass]="'API-tooltip'"
|
||||
>
|
||||
@if (item.children && item.level === collapsableLevel()) {
|
||||
<docs-icon>arrow_back</docs-icon>
|
||||
}
|
||||
<span class="docs-faceted-list-item-text">
|
||||
{{ item.label }}
|
||||
<ng-container *ngTemplateOutlet="itemStatus; context: {$implicit: item}" />
|
||||
</span>
|
||||
</button>
|
||||
}
|
||||
@if (displayItemsToLevel() > item.level && item.children?.length > 0) {
|
||||
<ng-container
|
||||
*ngTemplateOutlet="navigationList; context: {$implicit: item.children, level: item.level}"
|
||||
/>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
}
|
||||
@if (displayItemsToLevel() > item.level && item.children?.length > 0) {
|
||||
<ng-container *ngTemplateOutlet="navigationList; context: {$implicit: item.children}" />
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
@@ -185,11 +185,3 @@ a,
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-navigation-group {
|
||||
padding: 0.5rem 0.5rem 0.5rem 1rem;
|
||||
background: var(--septenary-contrast);
|
||||
&:not(:first-child) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ import {NavigationState} from '../../services/index';
|
||||
import {RouterLink, RouterLinkActive} from '@angular/router';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
import {IsActiveNavigationItem} from '../../pipes';
|
||||
import {NgTemplateOutlet, TitleCasePipe} from '@angular/common';
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
import {ReactiveFormsModule} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-navigation-list',
|
||||
@@ -25,8 +24,6 @@ import {ReactiveFormsModule} from '@angular/forms';
|
||||
IsActiveNavigationItem,
|
||||
NgTemplateOutlet,
|
||||
MatTooltipModule,
|
||||
ReactiveFormsModule,
|
||||
TitleCasePipe,
|
||||
],
|
||||
templateUrl: './navigation-list.component.html',
|
||||
styleUrls: ['./navigation-list.component.scss'],
|
||||
@@ -34,10 +31,10 @@ import {ReactiveFormsModule} from '@angular/forms';
|
||||
})
|
||||
export class NavigationList {
|
||||
readonly navigationItems = input.required<NavigationItem[]>();
|
||||
readonly displayItemsToLevel = input(2);
|
||||
readonly displayItemsToLevel = input<number>(2);
|
||||
readonly collapsableLevel = input<number | undefined>();
|
||||
readonly expandableLevel = input(2);
|
||||
readonly isDropdownView = input(false);
|
||||
readonly expandableLevel = input<number>(2);
|
||||
readonly isDropdownView = input<boolean>(false);
|
||||
|
||||
readonly linkClicked = output<void>();
|
||||
|
||||
@@ -59,33 +56,4 @@ export class NavigationList {
|
||||
emitClickOnLink(): void {
|
||||
this.linkClicked.emit();
|
||||
}
|
||||
|
||||
private hasCategories(items: NavigationItem[]): boolean {
|
||||
return items.some((item) => !!item.category);
|
||||
}
|
||||
|
||||
protected groupItems(items: NavigationItem[]): Map<string, NavigationItem[]> {
|
||||
const hasCategories = this.hasCategories(items);
|
||||
if (hasCategories) {
|
||||
const others: NavigationItem[] = [];
|
||||
const categorizedItems = new Map<string, NavigationItem[]>();
|
||||
for (const item of items) {
|
||||
const category = item.category || 'Other';
|
||||
if (category === 'Other') {
|
||||
others.push(item);
|
||||
continue;
|
||||
}
|
||||
if (!categorizedItems.has(category)) {
|
||||
categorizedItems.set(category, []);
|
||||
}
|
||||
categorizedItems.get(category)!.push(item);
|
||||
}
|
||||
if (others.length) {
|
||||
categorizedItems.set('Other', others);
|
||||
}
|
||||
return categorizedItems;
|
||||
} else {
|
||||
return new Map([['', items]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,49 +12,35 @@
|
||||
@if (searchResults().length) {
|
||||
<ul class="docs-search-results docs-mini-scroll-track">
|
||||
@for (result of searchResults(); track result.id) {
|
||||
<li docsSearchItem [item]="result" class="docs-search-result">
|
||||
<li docsSearchItem [item]="result">
|
||||
<a
|
||||
[routerLink]="'/' + result.url | relativeLink: 'pathname'"
|
||||
[fragment]="result.url | relativeLink: 'hash'"
|
||||
(click)="history.addItem(result)"
|
||||
>
|
||||
<div>
|
||||
<p class="docs-search-result__label">
|
||||
<div class="docs-result-icon-and-type">
|
||||
<!-- Icon -->
|
||||
<span class="docs-search-result-icon" aria-hidden="true">
|
||||
<i role="presentation" class="material-symbols-outlined docs-icon-small">
|
||||
{{ result.type === 'code' ? 'code' : 'description'}}
|
||||
</i>
|
||||
</span>
|
||||
|
||||
<!-- Page title -->
|
||||
<span [innerHtml]="result.labelHtml"></span>
|
||||
@if (result.package) {
|
||||
<span
|
||||
[innerHTML]="result.package"
|
||||
class="docs-search-result__label__package"
|
||||
></span>
|
||||
}
|
||||
</p>
|
||||
<!-- Results type -->
|
||||
<span class="docs-search-results__type" [innerHtml]="result.labelHtml"></span>
|
||||
</div>
|
||||
|
||||
@if (result.subLabelHtml) {
|
||||
<p class="docs-search-result__sub-label">
|
||||
<span class="docs-search-result-icon" aria-hidden="true">
|
||||
<i role="presentation" class="material-symbols-outlined docs-icon-small">
|
||||
grid_3x3
|
||||
</i>
|
||||
</span>
|
||||
<span [innerHtml]="result.subLabelHtml"></span>
|
||||
</p>
|
||||
}
|
||||
|
||||
@if (result.contentHtml) {
|
||||
<p class="docs-search-result__content" [innerHtml]="result.contentHtml"></p>
|
||||
<span
|
||||
class="docs-search-results__type docs-search-results__lvl2"
|
||||
[innerHtml]="result.subLabelHtml"
|
||||
>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<p class="docs-search-result__category">
|
||||
{{ result.category }}
|
||||
</p>
|
||||
|
||||
<!-- Page title -->
|
||||
<span class="docs-result-page-title">{{ result.category }}</span>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
||||
@@ -38,21 +38,11 @@ dialog {
|
||||
margin: 0;
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
|
||||
.docs-search-result {
|
||||
li {
|
||||
border-inline-start: 2px solid var(--senary-contrast);
|
||||
margin-inline-start: 1rem;
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.docs-search-result-icon {
|
||||
display: inline-block;
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
padding-inline-end: 1rem;
|
||||
padding-block: 0.25rem;
|
||||
|
||||
/**
|
||||
* This rule needs ng-deep to be applied to elements that are created via a [innerHTML] binding
|
||||
@@ -71,50 +61,17 @@ dialog {
|
||||
color: var(--secondary-contrast);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
&__label,
|
||||
&__sub-label,
|
||||
&__content {
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
&__label,
|
||||
&__sub-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-weight: 600;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__package {
|
||||
font-size: 0.75rem;
|
||||
.docs-search-result-icon {
|
||||
i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__content,
|
||||
&__category {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__sub-label,
|
||||
&__content {
|
||||
margin-block-start: 0.375rem;
|
||||
margin-inline-start: 2rem;
|
||||
color: var(--quaternary-contrast);
|
||||
}
|
||||
|
||||
&__category {
|
||||
font-weight: 400;
|
||||
color: var(--quaternary-contrast);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--septenary-contrast); // stylelint-disable-line
|
||||
}
|
||||
@@ -123,14 +80,44 @@ dialog {
|
||||
&.active {
|
||||
background-color: var(--octonary-contrast); // stylelint-disable-line
|
||||
border-inline-start: 2px solid var(--primary-contrast);
|
||||
|
||||
.docs-search-result__label,
|
||||
.docs-search-result__sub-label,
|
||||
.docs-search-result__content {
|
||||
color: var(--primary-contrast);
|
||||
a {
|
||||
span:not(.docs-result-page-title),
|
||||
.docs-search-results__type {
|
||||
color: var(--primary-contrast);
|
||||
i {
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-search-result-icon,
|
||||
.docs-search-results__type,
|
||||
.docs-result-page-title {
|
||||
color: var(--quaternary-contrast);
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
transition: color 0.3s ease;
|
||||
padding: 0.75rem;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
.docs-search-results__lvl2 {
|
||||
display: inline-block;
|
||||
margin-inline-start: 2rem;
|
||||
padding-block-start: 0;
|
||||
}
|
||||
|
||||
.docs-search-results__lvl3 {
|
||||
margin-inline-start: 2rem;
|
||||
padding-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-result-page-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +127,14 @@ dialog {
|
||||
color: var(--gray-400);
|
||||
}
|
||||
|
||||
.docs-result-icon-and-type {
|
||||
display: flex;
|
||||
|
||||
.docs-search-results__type {
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-search-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -51,10 +51,10 @@ import {SearchHistoryComponent} from '../search-history/search-history.component
|
||||
styleUrls: ['./search-dialog.component.scss'],
|
||||
})
|
||||
export class SearchDialog {
|
||||
readonly onClose = output();
|
||||
readonly dialog = viewChild.required<ElementRef<HTMLDialogElement>>('searchDialog');
|
||||
readonly items = viewChildren(SearchItem);
|
||||
readonly textField = viewChild(TextField);
|
||||
onClose = output();
|
||||
dialog = viewChild.required<ElementRef<HTMLDialogElement>>('searchDialog');
|
||||
items = viewChildren(SearchItem);
|
||||
textField = viewChild(TextField);
|
||||
|
||||
readonly history = inject(SearchHistory);
|
||||
private readonly search = inject(Search);
|
||||
@@ -67,9 +67,9 @@ export class SearchDialog {
|
||||
this.injector,
|
||||
).withWrap();
|
||||
|
||||
readonly searchQuery = this.search.searchQuery;
|
||||
readonly resultsResource = this.search.resultsResource;
|
||||
readonly searchResults = this.search.searchResults;
|
||||
searchQuery = this.search.searchQuery;
|
||||
resultsResource = this.search.resultsResource;
|
||||
searchResults = this.search.searchResults;
|
||||
|
||||
// We use a FormControl instead of relying on NgModel+signal to avoid
|
||||
// the issue https://github.com/angular/angular/issues/13568
|
||||
|
||||
@@ -22,7 +22,6 @@ ng_project(
|
||||
],
|
||||
deps = [
|
||||
"//adev:node_modules/@angular/cdk",
|
||||
"//adev:node_modules/@angular/common",
|
||||
"//adev:node_modules/@angular/core",
|
||||
"//adev:node_modules/@angular/router",
|
||||
"//adev/shared-docs/directives",
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
<ng-template #searchItem let-item="item" let-type="type">
|
||||
<i role="presentation" class="material-symbols-outlined type-icon" aria-hidden="true">
|
||||
{{ type === 'recent' ? 'history' : 'star' }}
|
||||
</i>
|
||||
<span [innerHTML]="item.labelHtml" class="label"></span>
|
||||
|
||||
@if (item.subLabelHtml) {
|
||||
<i role="presentation" class="material-symbols-outlined" aria-hidden="true"> arrow_right </i>
|
||||
<span [innerHTML]="item.subLabelHtml" class="sub-label"></span>
|
||||
}
|
||||
</ng-template>
|
||||
|
||||
@let items = history.items();
|
||||
|
||||
@if (items.recent.length) {
|
||||
@@ -22,10 +10,8 @@
|
||||
[fragment]="item.url | relativeLink: 'hash'"
|
||||
(click)="history.addItem(item)"
|
||||
>
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="searchItem"
|
||||
[ngTemplateOutletContext]="{item, type: 'recent'}"
|
||||
/>
|
||||
<i role="presentation" class="material-symbols-outlined" aria-hidden="true"> history </i>
|
||||
<span [innerHTML]="item.labelHtml"></span>
|
||||
</a>
|
||||
|
||||
<button
|
||||
@@ -34,9 +20,7 @@
|
||||
(click)="history.makeFavorite(item)"
|
||||
title="Make favorite"
|
||||
>
|
||||
<i role="presentation" class="material-symbols-outlined type-icon" aria-hidden="true">
|
||||
star
|
||||
</i>
|
||||
<i role="presentation" class="material-symbols-outlined" aria-hidden="true"> star </i>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -64,10 +48,8 @@
|
||||
[routerLink]="'/' + item.url | relativeLink: 'pathname'"
|
||||
[fragment]="item.url | relativeLink: 'hash'"
|
||||
>
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="searchItem"
|
||||
[ngTemplateOutletContext]="{item, type: 'favorite'}"
|
||||
/>
|
||||
<i role="presentation" class="material-symbols-outlined" aria-hidden="true"> star </i>
|
||||
<span [innerHTML]="item.labelHtml"></span>
|
||||
</a>
|
||||
|
||||
<button
|
||||
|
||||
@@ -41,23 +41,9 @@
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--secondary-contrast);
|
||||
transition: color 0.3s ease;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
.type-icon {
|
||||
margin-inline-end: 0.75rem;
|
||||
}
|
||||
|
||||
span {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
&.sub-label {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-contrast);
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {toSignal} from '@angular/core/rxjs-interop';
|
||||
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
|
||||
import {SearchHistory} from '../../services';
|
||||
import {RelativeLink} from '../../pipes';
|
||||
@@ -26,7 +25,7 @@ import {SearchItem} from '../../directives';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-search-history',
|
||||
imports: [NgTemplateOutlet, RelativeLink, RouterLink, SearchItem],
|
||||
imports: [RelativeLink, RouterLink, SearchItem],
|
||||
templateUrl: './search-history.component.html',
|
||||
styleUrl: './search-history.component.scss',
|
||||
host: {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule} from '@angular/forms';
|
||||
import {ChangeDetectionStrategy, Component, model, forwardRef, input, signal} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
|
||||
type SelectOptionValue = string | number | boolean;
|
||||
|
||||
@@ -19,7 +20,7 @@ export interface SelectOption {
|
||||
@Component({
|
||||
selector: 'docs-select',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [FormsModule],
|
||||
imports: [CommonModule, FormsModule],
|
||||
templateUrl: './select.component.html',
|
||||
styleUrls: ['./select.component.scss'],
|
||||
providers: [
|
||||
@@ -37,7 +38,7 @@ export class Select implements ControlValueAccessor {
|
||||
readonly id = input.required<string>({alias: 'selectId'});
|
||||
readonly name = input.required<string>();
|
||||
readonly options = input.required<SelectOption[]>();
|
||||
readonly disabled = model(false);
|
||||
readonly disabled = model<boolean>(false);
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
private onChange: (value: SelectOptionValue) => void = (_: SelectOptionValue) => {};
|
||||
|
||||
@@ -13,7 +13,6 @@ ng_project(
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
"//adev/shared-docs/components/navigation-list:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev:node_modules/@angular/common",
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, forwardRef, model, input, signal} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-slide-toggle',
|
||||
imports: [CommonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './slide-toggle.component.html',
|
||||
styleUrls: ['./slide-toggle.component.scss'],
|
||||
@@ -25,7 +27,7 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
export class SlideToggle implements ControlValueAccessor {
|
||||
readonly buttonId = input.required<string>();
|
||||
readonly label = input.required<string>();
|
||||
readonly disabled = model(false);
|
||||
readonly disabled = model<boolean>(false);
|
||||
|
||||
// Implemented as part of ControlValueAccessor.
|
||||
private onChange: (value: boolean) => void = (_: boolean) => {};
|
||||
|
||||
@@ -38,7 +38,7 @@ export class TableOfContents {
|
||||
|
||||
tableOfContentItems = this.tableOfContentsLoader.tableOfContentItems;
|
||||
|
||||
readonly activeItemId = signal<string | null>(null);
|
||||
activeItemId = signal<string | null>(null);
|
||||
TableOfContentsLevel = TableOfContentsLevel;
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -17,13 +17,14 @@ import {
|
||||
model,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-text-field',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [FormsModule, IconComponent],
|
||||
imports: [CommonModule, FormsModule, IconComponent],
|
||||
templateUrl: './text-field.component.html',
|
||||
styleUrls: ['./text-field.component.scss'],
|
||||
providers: [
|
||||
|
||||
@@ -29,16 +29,16 @@ export class TopLevelBannerComponent {
|
||||
* separately for different events or instances. Without a unique ID,
|
||||
* closing one banner could inadvertently hide other banners for different events.
|
||||
*/
|
||||
readonly id = input.required<string>();
|
||||
id = input.required<string>();
|
||||
// Optional URL link that the banner should navigate to when clicked.
|
||||
readonly link = input<string>();
|
||||
link = input<string>();
|
||||
// Text content to be displayed in the banner.
|
||||
readonly text = input.required<string>();
|
||||
text = input.required<string>();
|
||||
// Optional expiry date. Setting the default expiry as a future date so we
|
||||
// don't have to deal with undefined signal values.
|
||||
readonly expiry = input(new Date('3000-01-01'), {transform: parseDate});
|
||||
expiry = input(new Date('3000-01-01'), {transform: parseDate});
|
||||
// Whether the user has closed the banner or the survey has expired.
|
||||
readonly hasClosed = linkedSignal(() => {
|
||||
hasClosed = linkedSignal(() => {
|
||||
const expired = Date.now() > this.expiry().getTime();
|
||||
|
||||
// Needs to be in a try/catch, because some browsers will
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
// $screen-xl is the breakpoint where Main content stop being fluid and made fixed
|
||||
|
||||
>*:not(docs-table-of-contents) {
|
||||
max-width: calc(mq.$screen-xl - var(--secondary-nav-width) - var(--primary-nav-width) - var(--layout-padding)*2)
|
||||
max-width: calc(mq.$screen-xxl - var(--secondary-nav-width) - var(--primary-nav-width) - var(--layout-padding)*2)
|
||||
}
|
||||
|
||||
pre {
|
||||
|
||||
@@ -109,10 +109,7 @@ describe('DocViewer', () => {
|
||||
expect(exampleViewer).not.toBeNull();
|
||||
expect(exampleViewer.componentInstance.view()).toBe(CodeExampleViewMode.SNIPPET);
|
||||
|
||||
const copySourceCodeButton = fixture.debugElement.query(By.directive(CopySourceCodeButton));
|
||||
expect(copySourceCodeButton).not.toBeNull();
|
||||
|
||||
const checkIcon = copySourceCodeButton.query(By.directive(IconComponent));
|
||||
const checkIcon = fixture.debugElement.query(By.directive(IconComponent));
|
||||
expect((checkIcon.nativeElement as HTMLElement).classList).toContain(
|
||||
`material-symbols-outlined`,
|
||||
);
|
||||
|
||||
@@ -61,8 +61,8 @@ export const GITHUB_CONTENT_URL = 'https://github.com/angular/angular/blob/main/
|
||||
},
|
||||
})
|
||||
export class DocViewer {
|
||||
readonly docContent = input<string | undefined>();
|
||||
readonly hasToc = input(false);
|
||||
docContent = input<string | undefined>();
|
||||
hasToc = input(false);
|
||||
readonly contentLoaded = output<void>();
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
@@ -188,7 +188,6 @@ export class DocViewer {
|
||||
path: string,
|
||||
): Promise<void> {
|
||||
const preview = Boolean(placeholder.getAttribute('preview'));
|
||||
const hideCode = Boolean(placeholder.getAttribute('hideCode'));
|
||||
const title = placeholder.getAttribute('header') ?? undefined;
|
||||
const firstCodeSnippetTitle =
|
||||
snippets.length > 0 ? (snippets[0].title ?? snippets[0].name) : undefined;
|
||||
@@ -200,7 +199,6 @@ export class DocViewer {
|
||||
path,
|
||||
files: snippets,
|
||||
preview,
|
||||
hideCode,
|
||||
id: this.countOfExamples,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,42 +1,23 @@
|
||||
<div class="docs-example-viewer" role="group">
|
||||
<header class="docs-example-viewer-actions">
|
||||
@if (showCode()) {
|
||||
@if (view() === CodeExampleViewMode.SNIPPET) {
|
||||
<span>{{ exampleMetadata()?.title }}</span>
|
||||
}
|
||||
@if (view() === CodeExampleViewMode.SNIPPET) {
|
||||
<span>{{ exampleMetadata()?.title }}</span>
|
||||
}
|
||||
|
||||
@if (view() === CodeExampleViewMode.MULTI_FILE) {
|
||||
<mat-tab-group #codeTabs animationDuration="0ms" mat-stretch-tabs="false">
|
||||
@for (tab of tabs(); track tab) {
|
||||
<mat-tab [label]="tab.name" />
|
||||
}
|
||||
</mat-tab-group>
|
||||
}
|
||||
} @else {
|
||||
<!-- Title placeholder -->
|
||||
<span aria-hidden="true"> </span>
|
||||
@if (view() === CodeExampleViewMode.MULTI_FILE) {
|
||||
<mat-tab-group #codeTabs animationDuration="0ms" mat-stretch-tabs="false">
|
||||
@for (tab of tabs(); track tab) {
|
||||
<mat-tab [label]="tab.name"></mat-tab>
|
||||
}
|
||||
</mat-tab-group>
|
||||
}
|
||||
|
||||
<div class="docs-example-viewer-icons">
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
class="docs-example-code-toggle"
|
||||
[attr.aria-checked]="showCode()"
|
||||
[attr.aria-label]="showCode() ? 'Hide code' : 'Show code'"
|
||||
(click)="showCode.set(!showCode())"
|
||||
[matTooltip]="showCode() ? 'Hide code' : 'Show code'"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<docs-icon>{{showCode() ? 'code_off' : 'code'}}</docs-icon>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="docs-example-copy-link"
|
||||
[attr.aria-label]="'Copy link to ' + exampleMetadata()?.title + ' example to the clipboard'"
|
||||
(click)="copyLink()"
|
||||
matTooltip="Copy link to example"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<i aria-hidden="true">
|
||||
<svg
|
||||
@@ -60,9 +41,8 @@
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggleExampleVisibility()"
|
||||
[attr.title]="(expanded() ? 'Collapse' : 'Expand') + ' example'"
|
||||
[attr.aria-label]="(expanded() ? 'Collapse' : 'Expand') + ' code example'"
|
||||
matTooltip="{{ expanded() ? 'Collapse' : 'Expand' }} example"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<i aria-hidden="true">
|
||||
@if (!expanded()) {
|
||||
@@ -97,18 +77,16 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@if (showCode()) {
|
||||
<div
|
||||
class="docs-example-viewer-code-wrapper"
|
||||
[class.docs-example-viewer-snippet]="view() === CodeExampleViewMode.SNIPPET"
|
||||
[class.docs-example-viewer-multi-file]="view() === CodeExampleViewMode.MULTI_FILE"
|
||||
>
|
||||
<button docs-copy-source-code></button>
|
||||
@if (snippetCode()?.sanitizedContent; as content) {
|
||||
<div [innerHTML]="content"></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div
|
||||
class="docs-example-viewer-code-wrapper"
|
||||
[class.docs-example-viewer-snippet]="view() === CodeExampleViewMode.SNIPPET"
|
||||
[class.docs-example-viewer-multi-file]="view() === CodeExampleViewMode.MULTI_FILE"
|
||||
>
|
||||
<button docs-copy-source-code></button>
|
||||
@if (snippetCode()?.sanitizedContent; as content) {
|
||||
<div [innerHTML]="content"></div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (exampleComponent) {
|
||||
<div class="docs-example-viewer-preview">
|
||||
@@ -122,10 +100,9 @@
|
||||
<a
|
||||
[href]="githubUrl()"
|
||||
target="_blank"
|
||||
title="Open example on GitHub"
|
||||
class="docs-example-github-link"
|
||||
aria-label="Open example on GitHub"
|
||||
matTooltip="Open example on GitHub"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<i aria-hidden="true">
|
||||
<svg
|
||||
@@ -151,9 +128,8 @@
|
||||
[href]="stackblitzUrl()"
|
||||
target="_blank"
|
||||
class="docs-example-stackblitz-link"
|
||||
aria-label="Edit example in StackBlitz"
|
||||
matTooltip="Edit example in StackBlitz"
|
||||
matTooltipPosition="above"
|
||||
title="Edit this example in StackBlitz"
|
||||
aria-label="Edit this example in StackBlitz"
|
||||
>
|
||||
<i aria-hidden="true">
|
||||
<svg
|
||||
|
||||
@@ -57,25 +57,25 @@
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
|
||||
a,
|
||||
button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
color: var(--gray-400);
|
||||
svg {
|
||||
fill: var(--gray-400);
|
||||
}
|
||||
}
|
||||
|
||||
path {
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
a,
|
||||
button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
path {
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--tertiary-contrast);
|
||||
fill: var(--tertiary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-46
@@ -35,6 +35,7 @@ describe('ExampleViewer', () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ExampleViewer],
|
||||
providers: [
|
||||
// TODO: Find why tests warn that zone.js is still loaded
|
||||
provideZonelessChangeDetection(),
|
||||
{provide: EXAMPLE_VIEWER_CONTENT_LOADER, useValue: exampleContentSpy},
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {fragment: 'fragment'}}},
|
||||
@@ -215,7 +216,7 @@ describe('ExampleViewer', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
const stackblitzButton = fixture.debugElement.query(
|
||||
By.css('a[aria-label="Edit example in StackBlitz"]'),
|
||||
By.css('a[aria-label="Edit this example in StackBlitz"]'),
|
||||
);
|
||||
expect(stackblitzButton).toBeTruthy();
|
||||
expect(stackblitzButton.nativeElement.href).toBe(component.stackblitzUrl());
|
||||
@@ -272,50 +273,6 @@ describe('ExampleViewer', () => {
|
||||
button.click();
|
||||
expect(spy.calls.argsFor(0)[0].trim()).toBe(`${window.location.href}#example-1`);
|
||||
});
|
||||
|
||||
it('should hide code content when `hideCode` is true', async () => {
|
||||
componentRef.setInput(
|
||||
'metadata',
|
||||
getMetadata({
|
||||
hideCode: true,
|
||||
}),
|
||||
);
|
||||
|
||||
await component.renderExample();
|
||||
fixture.detectChanges();
|
||||
|
||||
// Initially, the code should be hidden.
|
||||
expect(component.showCode()).toBeFalse();
|
||||
let codeContainer = fixture.debugElement.query(By.css('.docs-example-viewer-code-wrapper'));
|
||||
expect(codeContainer).toBeNull();
|
||||
});
|
||||
|
||||
it('should expand/collapse code content with toggle button.', async () => {
|
||||
componentRef.setInput('metadata', getMetadata());
|
||||
|
||||
await component.renderExample();
|
||||
fixture.detectChanges();
|
||||
|
||||
// Initially, the code should be visible.
|
||||
expect(component.showCode()).toBeTrue();
|
||||
let codeContainer = fixture.debugElement.query(By.css('.docs-example-viewer-code-wrapper'));
|
||||
expect(codeContainer).not.toBeNull();
|
||||
|
||||
const codeToggleButton = fixture.debugElement.query(By.css('.docs-example-code-toggle'));
|
||||
codeToggleButton.nativeElement.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.showCode()).toBeFalse();
|
||||
codeContainer = fixture.debugElement.query(By.css('.docs-example-viewer-code-wrapper'));
|
||||
expect(codeContainer).toBeNull();
|
||||
|
||||
codeToggleButton.nativeElement.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.showCode()).toBeTrue();
|
||||
codeContainer = fixture.debugElement.query(By.css('.docs-example-viewer-code-wrapper'));
|
||||
expect(codeContainer).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
const getMetadata = (value: Partial<ExampleMetadata> = {}): ExampleMetadata => {
|
||||
@@ -326,7 +283,6 @@ const getMetadata = (value: Partial<ExampleMetadata> = {}): ExampleMetadata => {
|
||||
{name: 'example.css', sanitizedContent: ''},
|
||||
],
|
||||
preview: false,
|
||||
hideCode: false,
|
||||
...value,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,15 +21,13 @@ import {
|
||||
Type,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import {DOCUMENT, NgTemplateOutlet} from '@angular/common';
|
||||
import {CommonModule, DOCUMENT} from '@angular/common';
|
||||
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {CopySourceCodeButton} from '../../copy-source-code-button/copy-source-code-button.component';
|
||||
import {IconComponent} from '../../icon/icon.component';
|
||||
import {ExampleMetadata, Snippet} from '../../../interfaces/index';
|
||||
import {EXAMPLE_VIEWER_CONTENT_LOADER} from '../../../providers/index';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
|
||||
export enum CodeExampleViewMode {
|
||||
SNIPPET = 'snippet',
|
||||
@@ -43,7 +41,7 @@ export const HIDDEN_CLASS_NAME = 'hidden';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-example-viewer',
|
||||
imports: [CopySourceCodeButton, MatTabsModule, MatTooltipModule, IconComponent, NgTemplateOutlet],
|
||||
imports: [CommonModule, CopySourceCodeButton, MatTabsModule],
|
||||
templateUrl: './example-viewer.component.html',
|
||||
styleUrls: ['./example-viewer.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
@@ -73,18 +71,17 @@ export class ExampleViewer {
|
||||
CodeExampleViewMode = CodeExampleViewMode;
|
||||
exampleComponent?: Type<unknown>;
|
||||
|
||||
readonly expandable = signal<boolean>(false);
|
||||
readonly expanded = signal<boolean>(false);
|
||||
readonly snippetCode = signal<Snippet | undefined>(undefined);
|
||||
readonly showCode = signal<boolean>(true);
|
||||
readonly tabs = computed(() =>
|
||||
expandable = signal<boolean>(false);
|
||||
expanded = signal<boolean>(false);
|
||||
snippetCode = signal<Snippet | undefined>(undefined);
|
||||
tabs = computed(() =>
|
||||
this.exampleMetadata()?.files.map((file) => ({
|
||||
name:
|
||||
file.title ?? (this.shouldDisplayFullName() ? file.name : this.getFileExtension(file.name)),
|
||||
code: file.sanitizedContent,
|
||||
})),
|
||||
);
|
||||
readonly view = computed(() =>
|
||||
view = computed(() =>
|
||||
this.exampleMetadata()?.files.length === 1
|
||||
? CodeExampleViewMode.SNIPPET
|
||||
: CodeExampleViewMode.MULTI_FILE,
|
||||
@@ -100,10 +97,6 @@ export class ExampleViewer {
|
||||
|
||||
this.snippetCode.set(this.exampleMetadata()?.files[0]);
|
||||
|
||||
if (this.exampleMetadata()?.hideCode) {
|
||||
this.showCode.set(false);
|
||||
}
|
||||
|
||||
afterNextRender(
|
||||
() => {
|
||||
// Several function below query the DOM directly, we need to wait until the DOM is rendered.
|
||||
|
||||
@@ -21,7 +21,7 @@ export class SearchItem implements Highlightable {
|
||||
// We can't migrate them to signals yet
|
||||
@Input() disabled = false;
|
||||
|
||||
readonly item = input<SearchResultItem | undefined>();
|
||||
item = input<SearchResultItem | undefined>();
|
||||
|
||||
private readonly elementRef = inject(ElementRef<HTMLLIElement>);
|
||||
|
||||
|
||||
@@ -38,6 +38,4 @@ export interface ExampleMetadata {
|
||||
files: Snippet[];
|
||||
/** True when ExampleViewer should have preview */
|
||||
preview: boolean;
|
||||
/** Whether to hide code example by default. */
|
||||
hideCode: boolean;
|
||||
}
|
||||
|
||||
@@ -16,5 +16,4 @@ export interface NavigationItem {
|
||||
parent?: NavigationItem;
|
||||
contentPath?: string;
|
||||
status?: 'new' | 'updated';
|
||||
category?: string;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ export interface SearchResultItem {
|
||||
type: 'doc' | 'code';
|
||||
labelHtml: string | null;
|
||||
subLabelHtml: string | null;
|
||||
contentHtml: string | null;
|
||||
package: string | null;
|
||||
url: string;
|
||||
|
||||
id: string;
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
"name": "@angular/docs",
|
||||
"version": "0.0.0-PLACEHOLDER",
|
||||
"peerDependencies": {
|
||||
"@angular/cdk": "^20.2.0-next",
|
||||
"@angular/common": "^20.2.0-next",
|
||||
"@angular/core": "^20.2.0-next",
|
||||
"@angular/forms": "^20.2.0-next",
|
||||
"@angular/material": "^20.2.0-next",
|
||||
"@angular/platform-browser": "^20.2.0-next",
|
||||
"@angular/router": "^20.2.0-next",
|
||||
"@angular/ssr": "^20.2.0-next",
|
||||
"@angular/cdk": "^21.0.0-next",
|
||||
"@angular/common": "^21.0.0-next",
|
||||
"@angular/core": "^21.0.0-next",
|
||||
"@angular/forms": "^21.0.0-next",
|
||||
"@angular/material": "^21.0.0-next",
|
||||
"@angular/platform-browser": "^21.0.0-next",
|
||||
"@angular/router": "^21.0.0-next",
|
||||
"@angular/ssr": "^21.0.0-next",
|
||||
"algoliasearch": "^5.0.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@ import type {DocEntry, EntryCollection, FunctionEntry, JsDocTagEntry} from '@ang
|
||||
export interface ManifestEntry {
|
||||
name: string;
|
||||
type: string;
|
||||
category: string | undefined;
|
||||
deprecated: {version: string | undefined} | undefined;
|
||||
developerPreview: {version: string | undefined} | undefined;
|
||||
experimental: {version: string | undefined} | undefined;
|
||||
@@ -86,7 +85,6 @@ export function generateManifest(apiCollections: EntryCollection[]): Manifest {
|
||||
developerPreview: getTagSinceVersion(entry, 'developerPreview'),
|
||||
experimental: getTagSinceVersion(entry, 'experimental'),
|
||||
stable: getTagSinceVersion(entry, 'publicApi'),
|
||||
category: getTag(entry, 'category')?.comment.trim(),
|
||||
}));
|
||||
|
||||
const existingEntry = manifest.find((entry) => entry.moduleName === collection.moduleName);
|
||||
|
||||
@@ -50,7 +50,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
{
|
||||
name: 'PI',
|
||||
@@ -59,7 +58,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -75,7 +73,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -113,7 +110,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -129,7 +125,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -167,7 +162,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
{
|
||||
name: 'TAO',
|
||||
@@ -176,7 +170,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -210,7 +203,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: {version: undefined},
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
{
|
||||
name: 'XI',
|
||||
@@ -219,7 +211,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: {version: undefined},
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -280,7 +271,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -341,7 +331,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: {version: undefined},
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -381,7 +370,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: {version: undefined},
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -397,7 +385,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -435,7 +422,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: undefined,
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
{
|
||||
name: 'XI',
|
||||
@@ -444,7 +430,6 @@ describe('api manifest generation', () => {
|
||||
deprecated: undefined,
|
||||
experimental: {version: undefined},
|
||||
stable: undefined,
|
||||
category: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -5,10 +5,6 @@ package(default_visibility = ["//adev/shared-docs/pipeline/api-gen:__subpackages
|
||||
esbuild(
|
||||
name = "bin",
|
||||
entry_point = ":index.mts",
|
||||
external = [
|
||||
"jsdom",
|
||||
"playwright-core",
|
||||
],
|
||||
format = "esm",
|
||||
output = "bin.mjs",
|
||||
platform = "node",
|
||||
|
||||
@@ -103,6 +103,13 @@ async function main() {
|
||||
|
||||
const [srcs, outputFilenameExecRootRelativePath] = rawParamLines;
|
||||
|
||||
// TODO: Remove when we are using Bazel v6+
|
||||
// On RBE, the output directory is not created properly due to a bug.
|
||||
// https://github.com/bazelbuild/bazel/commit/4310aeb36c134e5fc61ed5cdfdf683f3e95f19b7.
|
||||
if (!existsSync(outputFilenameExecRootRelativePath)) {
|
||||
mkdirSync(outputFilenameExecRootRelativePath, {recursive: true});
|
||||
}
|
||||
|
||||
// Docs rendering happens in three phases that occur here:
|
||||
// 1) Aggregate all the raw extracted doc info.
|
||||
// 2) Transform the raw data to a renderable state.
|
||||
|
||||
@@ -21,10 +21,6 @@ export function setCurrentSymbol(symbol: string): void {
|
||||
currentSymbol = symbol;
|
||||
}
|
||||
|
||||
export function getSymbols() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
export function getCurrentSymbol(): string | undefined {
|
||||
return currentSymbol;
|
||||
}
|
||||
|
||||
@@ -79,14 +79,12 @@ describe('markdown to html', () => {
|
||||
|
||||
// In the description
|
||||
const descriptionItem = entry.querySelector('.docs-reference-description')!;
|
||||
expect(descriptionItem.innerHTML).toContain(
|
||||
'<a href="/api/core/afterRender"><code>afterRender</code></a>',
|
||||
);
|
||||
expect(descriptionItem.innerHTML).toContain('<a href="/api/core/afterRender">afterRender</a>');
|
||||
|
||||
// In the card
|
||||
const cardItem = entry.querySelectorAll('.docs-reference-card-item')[1];
|
||||
expect(cardItem.innerHTML).toContain(
|
||||
'<a href="/api/core/AfterRenderPhase#MixedReadWrite"><code>AfterRenderPhase.MixedReadWrite</code></a>',
|
||||
'<a href="/api/core/AfterRenderPhase#MixedReadWrite">AfterRenderPhase.MixedReadWrite</a>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-39
@@ -6,10 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {initHighlighter} from '../../../../shared/shiki.mjs';
|
||||
import {setHighlighterInstance} from '../../shiki/shiki.mjs';
|
||||
import {setCurrentSymbol, setSymbols} from '../../symbol-context.mjs';
|
||||
import {addHtmlAdditionalLinks, addHtmlDescription} from '../../transforms/jsdoc-transforms.mjs';
|
||||
import {addHtmlAdditionalLinks} from '../../transforms/jsdoc-transforms.mjs';
|
||||
|
||||
// @ts-ignore This compiles fine, but Webstorm doesn't like the ESM import in a CJS context.
|
||||
describe('jsdoc transforms', () => {
|
||||
@@ -153,40 +151,4 @@ describe('jsdoc transforms', () => {
|
||||
|
||||
expect(entryFn).toThrowError(/Forbidden relative link: cli\/build ng build/);
|
||||
});
|
||||
|
||||
it('should parse markdown in descriptions', async () => {
|
||||
setHighlighterInstance(await initHighlighter());
|
||||
|
||||
setSymbols(
|
||||
Object.fromEntries([
|
||||
['Route', 'test'],
|
||||
['Router', 'angular/router'],
|
||||
['Router.someMethod', 'test'],
|
||||
['Router.someMethodWithParenthesis', 'test'],
|
||||
['FormGroup', 'test'],
|
||||
['FormGroup.someMethod', 'test'],
|
||||
]),
|
||||
);
|
||||
|
||||
const entry = addHtmlDescription({
|
||||
description: `
|
||||
\`\`\`angular-ts
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
function setupRouter() {
|
||||
const router = inject(Router);
|
||||
}
|
||||
\`\`\`
|
||||
`,
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
// Should have some shiki variables (meaning the description was highlighted).
|
||||
expect(entry.htmlDescription).toContain('--shiki');
|
||||
|
||||
// Having docs-code means that the description was parsed and formatted correctly (by the shared marked renderer)
|
||||
expect(entry.htmlDescription).toContain('class="docs-code"');
|
||||
|
||||
expect(entry.htmlDescription).toContain('/api/angular/router/Router');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,17 +14,13 @@ import {
|
||||
CliCommandRenderable,
|
||||
CliOptionRenderable,
|
||||
} from '../entities/renderables.mjs';
|
||||
import {parseMarkdown} from '../../../shared/marked/parse.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
|
||||
/** Given an unprocessed CLI entry, get the fully renderable CLI entry. */
|
||||
export function getCliRenderable(command: CliCommand): CliCommandRenderable {
|
||||
return {
|
||||
...command,
|
||||
subcommands: command.subcommands?.map((sub) => getCliRenderable(sub)),
|
||||
htmlDescription: parseMarkdown(command.longDescription ?? command.shortDescription, {
|
||||
highlighter: getHighlighterInstance(),
|
||||
}),
|
||||
htmlDescription: marked.parse(command.longDescription ?? command.shortDescription) as string,
|
||||
cards: getCliCardsRenderable(command),
|
||||
argumentsLabel: getArgumentsLabel(command),
|
||||
hasOptions: getOptions(command).length > 0,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {marked} from 'marked';
|
||||
import {JsDocTagEntry} from '../entities.mjs';
|
||||
|
||||
import {getDeprecatedEntry, getTagSinceVersion} from '../entities/categorization.mjs';
|
||||
@@ -25,14 +26,7 @@ import {
|
||||
} from '../entities/traits.mjs';
|
||||
|
||||
import {addApiLinksToHtml} from './code-transforms.mjs';
|
||||
import {
|
||||
getCurrentSymbol,
|
||||
getSymbols,
|
||||
getSymbolUrl,
|
||||
unknownSymbolMessage,
|
||||
} from '../symbol-context.mjs';
|
||||
import {parseMarkdown} from '../../../shared/marked/parse.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {getCurrentSymbol, getSymbolUrl, unknownSymbolMessage} from '../symbol-context.mjs';
|
||||
|
||||
const JS_DOC_USAGE_NOTE_TAGS: Set<string> = new Set(['remarks', 'usageNotes', 'example']);
|
||||
export const JS_DOC_SEE_TAG = 'see';
|
||||
@@ -105,11 +99,7 @@ export function addHtmlUsageNotes<T extends HasJsDocTags>(entry: T): T & HasHtml
|
||||
|
||||
/** Given a markdown JsDoc text, gets the rendered HTML. */
|
||||
function getHtmlForJsDocText(text: string): string {
|
||||
const mdToParse = convertLinks(wrapExampleHtmlElementsWithCode(text));
|
||||
const parsed = parseMarkdown(mdToParse, {
|
||||
apiEntries: getSymbols(),
|
||||
highlighter: getHighlighterInstance(),
|
||||
});
|
||||
const parsed = marked.parse(convertLinks(wrapExampleHtmlElementsWithCode(text))) as string;
|
||||
return addApiLinksToHtml(parsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export const docsAlertExtension = {
|
||||
let match: DocsAlert | undefined;
|
||||
for (const key of Object.keys(AlertSeverityLevel)) {
|
||||
// Capture group 1: all alert text content after the severity level
|
||||
const rule = new RegExp('^s*' + key + ': (.*?)(?:\n{2,}|\s*$)', 's');
|
||||
const rule = new RegExp('^s*' + key + ': (.*?)\n(\n|$)', 's');
|
||||
const possibleMatch = rule.exec(src);
|
||||
|
||||
if (possibleMatch?.[1]) {
|
||||
|
||||
@@ -72,7 +72,7 @@ function getStandardCard(renderer: RendererThis, token: DocsCardToken) {
|
||||
return `
|
||||
<a href="${token.href}" ${anchorTarget(token.href)} class="docs-card">
|
||||
<div>
|
||||
${token.title ? `<h3>${token.title}</h3>` : ''}
|
||||
<h3>${token.title}</h3>
|
||||
${parseWithoutCreatingLinks(renderer, token)}
|
||||
</div>
|
||||
<span>${token.link ? token.link : 'Learn more'}</span>
|
||||
@@ -82,7 +82,7 @@ function getStandardCard(renderer: RendererThis, token: DocsCardToken) {
|
||||
return `
|
||||
<div class="docs-card">
|
||||
<div>
|
||||
${token.title ? `<h3>${token.title}</h3>` : ''}
|
||||
<h3>${token.title}</h3>
|
||||
${renderer.parser.parse(token.tokens)}
|
||||
</div>
|
||||
${token.link ? `<span>${token.link}</span>` : ''}
|
||||
@@ -111,7 +111,7 @@ function getCardWithSvgIllustration(renderer: RendererThis, token: DocsCardToken
|
||||
${illustration}
|
||||
<div class="docs-card-text-content">
|
||||
<div>
|
||||
${token.title ? `<h3>${token.title}</h3>` : ''}
|
||||
<h3>${token.title}</h3>
|
||||
${renderer.parser.parse(token.tokens)}
|
||||
</div>
|
||||
<span>${token.link ? token.link : 'Learn more'}</span>
|
||||
@@ -123,7 +123,7 @@ function getCardWithSvgIllustration(renderer: RendererThis, token: DocsCardToken
|
||||
<div class="docs-card docs-card-with-svg">
|
||||
${illustration}
|
||||
<div class="docs-card-text-content">
|
||||
${token.title ? `<h3>${token.title}</h3>` : ''}
|
||||
<h3>${token.title}</h3>
|
||||
${renderer.parser.parse(token.tokens)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,8 +20,6 @@ export interface DocsCodeMultifileToken extends Tokens.Generic {
|
||||
paneTokens: Token[];
|
||||
// True if we should display preview
|
||||
preview: boolean;
|
||||
/** Whether to hide code example by default. */
|
||||
hideCode: boolean;
|
||||
}
|
||||
|
||||
// Capture group 1: all attributes on the opening tag
|
||||
@@ -30,7 +28,6 @@ const multiFileCodeRule = /^\s*<docs-code-multifile(.*?)>(.*?)<\/docs-code-multi
|
||||
|
||||
const pathRule = /path="([^"]*)"/;
|
||||
const previewRule = /preview/;
|
||||
const hideCodeRule = /hideCode/;
|
||||
|
||||
export const docsCodeMultifileExtension = {
|
||||
name: 'docs-code-multifile',
|
||||
@@ -45,7 +42,6 @@ export const docsCodeMultifileExtension = {
|
||||
const attr = match[1].trim();
|
||||
const path = pathRule.exec(attr);
|
||||
const preview = previewRule.exec(attr) ? true : false;
|
||||
const hideCode = hideCodeRule.exec(attr) ? true : false;
|
||||
|
||||
const token: DocsCodeMultifileToken = {
|
||||
type: 'docs-code-multifile',
|
||||
@@ -54,7 +50,6 @@ export const docsCodeMultifileExtension = {
|
||||
panes: match[2].trim(),
|
||||
paneTokens: [],
|
||||
preview: preview,
|
||||
hideCode,
|
||||
};
|
||||
this.lexer.blockTokens(token.panes, token.paneTokens);
|
||||
return token;
|
||||
@@ -74,9 +69,6 @@ export const docsCodeMultifileExtension = {
|
||||
if (token.preview) {
|
||||
el.setAttribute('preview', `${token.preview}`);
|
||||
}
|
||||
if (token.hideCode) {
|
||||
el.setAttribute('hideCode', 'true');
|
||||
}
|
||||
|
||||
return el.outerHTML;
|
||||
},
|
||||
|
||||
@@ -32,7 +32,6 @@ const languageRule = /language="([^"]*)"/;
|
||||
const visibleLinesRule = /visibleLines="([^"]*)"/;
|
||||
const visibleRegionRule = /visibleRegion="([^"]*)"/;
|
||||
const previewRule = /preview/;
|
||||
const hideCodeRule = /hideCode/;
|
||||
|
||||
export const docsCodeExtension = {
|
||||
name: 'docs-code',
|
||||
@@ -54,7 +53,6 @@ export const docsCodeExtension = {
|
||||
const visibleLines = visibleLinesRule.exec(attr);
|
||||
const visibleRegion = visibleRegionRule.exec(attr);
|
||||
const preview = previewRule.exec(attr) ? true : false;
|
||||
const hideCode = hideCodeRule.exec(attr) ? true : false;
|
||||
const classes = classRule.exec(attr);
|
||||
|
||||
let code = match[2]?.trim() ?? '';
|
||||
@@ -78,7 +76,6 @@ export const docsCodeExtension = {
|
||||
visibleLines: visibleLines?.[1],
|
||||
visibleRegion: visibleRegion?.[1],
|
||||
preview: preview,
|
||||
hideCode,
|
||||
classes: classes?.[1]?.split(' '),
|
||||
};
|
||||
return token;
|
||||
|
||||
@@ -36,8 +36,6 @@ export interface CodeToken extends Tokens.Generic {
|
||||
visibleRegion?: string;
|
||||
/* Whether we should display preview */
|
||||
preview?: boolean;
|
||||
/** Whether to hide code example by default. */
|
||||
hideCode?: boolean;
|
||||
/* The lines to display highlighting on */
|
||||
highlight?: string;
|
||||
|
||||
@@ -65,7 +63,7 @@ export function formatCode(token: CodeToken, context: RendererContext): string {
|
||||
`).firstElementChild!;
|
||||
|
||||
applyContainerAttributesAndClasses(containerEl, token);
|
||||
processForApiLinks(containerEl, context.apiEntries ?? {});
|
||||
processForApiLinks(containerEl, context.apiEntries);
|
||||
|
||||
return containerEl.outerHTML;
|
||||
}
|
||||
@@ -123,9 +121,6 @@ function applyContainerAttributesAndClasses(el: Element, token: CodeToken) {
|
||||
if (token.preview) {
|
||||
el.setAttribute('preview', 'true');
|
||||
}
|
||||
if (token.hideCode) {
|
||||
el.setAttribute('hideCode', 'true');
|
||||
}
|
||||
if (token.language === 'mermaid') {
|
||||
el.setAttribute('mermaid', 'true');
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import {listRender} from './transformations/list.mjs';
|
||||
import {imageRender} from './transformations/image.mjs';
|
||||
import {textRender} from './transformations/text.mjs';
|
||||
import {headingRender} from './transformations/heading.mjs';
|
||||
import {codeRender, codespanRender} from './transformations/code.mjs';
|
||||
import {codespanRender} from './transformations/code.mjs';
|
||||
import {HighlighterGeneric} from 'shiki';
|
||||
|
||||
export interface RendererContext {
|
||||
markdownFilePath?: string;
|
||||
apiEntries?: Record<string, string>;
|
||||
markdownFilePath: string;
|
||||
apiEntries: Record<string, string>;
|
||||
highlighter: HighlighterGeneric<any, any>;
|
||||
}
|
||||
|
||||
@@ -40,5 +40,4 @@ export class AdevDocsRenderer extends Renderer {
|
||||
override text = textRender;
|
||||
override heading = headingRender;
|
||||
override codespan = codespanRender;
|
||||
override code = codeRender;
|
||||
}
|
||||
|
||||
@@ -16,5 +16,3 @@ CRITICAL: Use Critical to call out potential bad stuff or alert the reader they
|
||||
IMPORTANT: Use Important for information that's crucial to comprehending the text or to completing some task.
|
||||
|
||||
HELPFUL: Use Best practice to call out practices that are known to be successful or better than alternatives.
|
||||
|
||||
NOTE: THIS NOTE WITHOUT A LINE RETURN
|
||||
@@ -34,10 +34,4 @@ describe('markdown to html', () => {
|
||||
|
||||
expect(noteEl?.textContent?.trim()).toContain(`This is a multiline note`);
|
||||
});
|
||||
|
||||
it(`should handle alerts without a line return`, () => {
|
||||
const noteEl = markdownDocument.querySelector(`.docs-alert-note:last-of-type`);
|
||||
|
||||
expect(noteEl?.textContent?.trim()).toContain(`THIS NOTE WITHOUT A LINE RETURN`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,4 @@
|
||||
<docs-card title="Link Card" link="Try It Now" href="in/app/link">
|
||||
Card Content with a symbol: `CommonModule`
|
||||
</docs-card>
|
||||
<docs-card title="Image Card" imgSrc="./angular.svg"></docs-card>
|
||||
<docs-card title="" link="Open on Playground" href="/playground">
|
||||
The fastest way to play with an Angular app. No setup required.
|
||||
</docs-card>
|
||||
<docs-card title="Image Card" imgSrc="./angular.svg"></docs-card>
|
||||
@@ -27,7 +27,7 @@ describe('markdown to html', () => {
|
||||
expect(cardEl.tagName).not.toBe('A');
|
||||
});
|
||||
|
||||
it('creates cards with links', () => {
|
||||
it('creates cards withs links', () => {
|
||||
const cardEl = markdownDocument.querySelectorAll('.docs-card')[1];
|
||||
|
||||
expect(cardEl.querySelector('h3')?.textContent?.trim()).toBe('Link Card');
|
||||
@@ -48,12 +48,4 @@ describe('markdown to html', () => {
|
||||
expect(cardEl.querySelector('h3')?.textContent?.trim()).toBe('Image Card');
|
||||
expect(cardEl.querySelector('svg')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('does not create empty h3 tags when title is empty', () => {
|
||||
const cardEl = markdownDocument.querySelectorAll('.docs-card')[3];
|
||||
|
||||
expect(cardEl.querySelector('h3')).toBeNull();
|
||||
expect(cardEl.tagName).toBe('A');
|
||||
expect(cardEl.getAttribute('href')).toBe('/playground');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
[Angular Site](https://angular.dev)
|
||||
[same page](#test)
|
||||
[same site](../other/page)
|
||||
[npm packages](https://docs.npmjs.com/getting-started/what-is-npm "What is npm?")
|
||||
[same site](../other/page)
|
||||
@@ -31,10 +31,4 @@ describe('markdown to html', () => {
|
||||
it('should render internal links that are relative paths', () => {
|
||||
expect(parsedMarkdown).toContain('<a href="../other/page">same site</a>');
|
||||
});
|
||||
|
||||
it('should render links with title attributes properly quoted', () => {
|
||||
expect(parsedMarkdown).toContain(
|
||||
'<a href="https://docs.npmjs.com/getting-started/what-is-npm" title="What is npm?" target="_blank">npm packages</a>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ describe('markdown to html', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
(global as any).HANDLE_MERMAID = true;
|
||||
// This test was flaky, 1st attemp to fix it is by inlining the markdown content
|
||||
const markdownContent = `
|
||||
\`\`\`mermaid
|
||||
graph TD;
|
||||
@@ -51,7 +52,7 @@ describe('markdown to html', () => {
|
||||
});
|
||||
|
||||
markdownDocument = JSDOM.fragment(await markedInstance.parse(markdownContent));
|
||||
}, 25_000);
|
||||
}, 15_000);
|
||||
|
||||
it('should create an svg for each mermaid code block', () => {
|
||||
expect(markdownDocument.querySelectorAll('svg')).toHaveSize(3);
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
import {Tokens} from 'marked';
|
||||
import {AdevDocsRenderer} from '../renderer.mjs';
|
||||
import {getSymbolUrl} from '../../linking.mjs';
|
||||
import {codeToHtml} from '../../shiki.mjs';
|
||||
|
||||
export function codespanRender(this: AdevDocsRenderer, token: Tokens.Codespan) {
|
||||
const apiLink = getSymbolUrl(token.text, this.context.apiEntries ?? {});
|
||||
const apiLink = getSymbolUrl(token.text, this.context.apiEntries);
|
||||
if (apiLink) {
|
||||
const htmlToken: Tokens.HTML = {
|
||||
type: 'html',
|
||||
@@ -32,15 +31,3 @@ export function codespanRender(this: AdevDocsRenderer, token: Tokens.Codespan) {
|
||||
}
|
||||
return this.defaultRenderer.codespan(token);
|
||||
}
|
||||
|
||||
export function codeRender(this: AdevDocsRenderer, {text, lang}: Tokens.Code): string {
|
||||
const highlightResult = codeToHtml(this.context.highlighter, text, lang)
|
||||
// remove spaces/line-breaks between elements to not mess-up `pre` style
|
||||
.replace(/>\s+</g, '><');
|
||||
|
||||
return `
|
||||
<div class="docs-code" role="group">
|
||||
${highlightResult}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function headingRender(this: AdevDocsRenderer, {depth, tokens}: Tokens.He
|
||||
|
||||
export function formatHeading(
|
||||
{text, depth}: {text: string; depth: number},
|
||||
markdownFilePath?: string,
|
||||
markdownFilePath: string,
|
||||
): string {
|
||||
if (depth === 1) {
|
||||
return `
|
||||
@@ -51,22 +51,18 @@ export function formatHeading(
|
||||
|
||||
// TODO(josephperrott): Set edit content url based on the owner, repo and branch.
|
||||
|
||||
/** The base url for editing the a file in the repository. */
|
||||
/** The base url for edting the a file in the repository. */
|
||||
const GITHUB_EDIT_CONTENT_URL = 'https://github.com/angular/angular/edit/main';
|
||||
|
||||
/** Get the page title with edit button to modify the page source. */
|
||||
export function getPageTitle(text: string, filePath?: string): string {
|
||||
export function getPageTitle(text: string, filePath: string): string {
|
||||
return `
|
||||
<!-- Page title -->
|
||||
<div class="docs-page-title">
|
||||
<h1 tabindex="-1">${text}</h1>
|
||||
${
|
||||
filePath
|
||||
? `<a class="docs-github-links" target="_blank" href="${GITHUB_EDIT_CONTENT_URL}/${filePath}" title="Edit this page" aria-label="Edit this page">
|
||||
<a class="docs-github-links" target="_blank" href="${GITHUB_EDIT_CONTENT_URL}/${filePath}" title="Edit this page" aria-label="Edit this page">
|
||||
<!-- Pencil -->
|
||||
<docs-icon role="presentation">edit</docs-icon>
|
||||
</a>`
|
||||
: ''
|
||||
}
|
||||
</a>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ export function linkRender(this: Renderer, {href, title, tokens}: Tokens.Link) {
|
||||
return this.parser.parseInline(tokens);
|
||||
}
|
||||
|
||||
const titleAttribute = title ? ` title="${title}"` : '';
|
||||
const titleAttribute = title ? ` title=${title}` : '';
|
||||
return `<a href="${href}"${titleAttribute}${anchorTarget(href)}>${this.parser.parseInline(tokens)}</a>`;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ ng_project(
|
||||
"//adev:node_modules/rxjs",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/providers",
|
||||
"//adev/shared-docs/utils",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export class NavigationState {
|
||||
private readonly _isMobileNavVisible = signal<boolean>(false);
|
||||
private readonly _level = linkedSignal(() => this._expandedItems().length);
|
||||
|
||||
readonly primaryActiveRouteItem = signal<string | null>(null);
|
||||
primaryActiveRouteItem = signal<string | null>(null);
|
||||
activeNavigationItem = this._activeNavigationItem.asReadonly();
|
||||
expandedItems = this._expandedItems.asReadonly();
|
||||
isMobileNavVisible = this._isMobileNavVisible.asReadonly();
|
||||
@@ -119,7 +119,7 @@ export class NavigationState {
|
||||
/**
|
||||
* return the actual navigation items, that is to say the one that match the current level
|
||||
*/
|
||||
private actualExpandedItems(): NavigationItem[] {
|
||||
private actualExpandedItems() {
|
||||
return this.expandedItems().slice(0, this.level());
|
||||
}
|
||||
|
||||
|
||||
@@ -19,47 +19,38 @@ export const MAX_RECENT_HISTORY_SIZE = 10;
|
||||
export interface HistoryItem {
|
||||
id: string;
|
||||
labelHtml: string;
|
||||
subLabelHtml?: string;
|
||||
url: string;
|
||||
isFavorite: boolean;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
function cleanUpHtml(label: string | null): string {
|
||||
return (label || '').replace(/<\/?mark>/g, '');
|
||||
}
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class SearchHistory {
|
||||
private readonly localStorage = inject(LOCAL_STORAGE);
|
||||
private readonly history = signal<Map<string, HistoryItem>>(new Map());
|
||||
|
||||
private readonly allItems = computed(() =>
|
||||
private allItems = computed(() =>
|
||||
Array.from(this.history().values()).sort((a, b) => b.createdAt - a.createdAt),
|
||||
);
|
||||
|
||||
readonly items = computed<{recent: HistoryItem[]; favorite: HistoryItem[]}>(() => ({
|
||||
items = computed<{recent: HistoryItem[]; favorite: HistoryItem[]}>(() => ({
|
||||
recent: this.allItems().filter((v) => !v.isFavorite),
|
||||
favorite: this.allItems().filter((v) => v.isFavorite),
|
||||
}));
|
||||
|
||||
readonly hasItems = computed(() => this.allItems().length > 0);
|
||||
hasItems = computed(() => this.allItems().length > 0);
|
||||
|
||||
constructor() {
|
||||
this.loadHistory();
|
||||
}
|
||||
|
||||
addItem(item: SearchResultItem | HistoryItem): void {
|
||||
// We don't want to reset nor update the creation date of favorites
|
||||
if (this.history().get(item.id)?.isFavorite) {
|
||||
return;
|
||||
}
|
||||
|
||||
addItem(item: SearchResultItem | HistoryItem) {
|
||||
this.updateHistory((map) => {
|
||||
const labelHtml = (item.labelHtml || '').replace(/<\/?mark>/g, '');
|
||||
|
||||
map.set(item.id, {
|
||||
id: item.id,
|
||||
labelHtml: cleanUpHtml(item.labelHtml),
|
||||
subLabelHtml: item.subLabelHtml ? cleanUpHtml(item.subLabelHtml) : undefined,
|
||||
labelHtml,
|
||||
url: item.url,
|
||||
isFavorite: false,
|
||||
createdAt: Date.now(),
|
||||
@@ -73,13 +64,13 @@ export class SearchHistory {
|
||||
});
|
||||
}
|
||||
|
||||
removeItem(item: SearchResultItem | HistoryItem): void {
|
||||
removeItem(item: SearchResultItem | HistoryItem) {
|
||||
this.updateHistory((map) => {
|
||||
map.delete(item.id);
|
||||
});
|
||||
}
|
||||
|
||||
makeFavorite(item: SearchResultItem | HistoryItem): void {
|
||||
makeFavorite(item: SearchResultItem | HistoryItem) {
|
||||
this.updateHistory((map) => {
|
||||
const updated = map.get(item.id);
|
||||
if (updated) {
|
||||
@@ -92,7 +83,7 @@ export class SearchHistory {
|
||||
});
|
||||
}
|
||||
|
||||
private loadHistory(): void {
|
||||
private loadHistory() {
|
||||
let parsedData: HistoryItem[];
|
||||
|
||||
try {
|
||||
@@ -109,7 +100,7 @@ export class SearchHistory {
|
||||
this.history.set(history);
|
||||
}
|
||||
|
||||
private updateHistory(updateFn: (map: Map<string, HistoryItem>) => void): void {
|
||||
private updateHistory(updateFn: (map: Map<string, HistoryItem>) => void) {
|
||||
const history = new Map(this.history());
|
||||
updateFn(history);
|
||||
this.history.set(history);
|
||||
|
||||
@@ -48,7 +48,7 @@ export class Search {
|
||||
private readonly config = inject(ENVIRONMENT);
|
||||
private readonly client = inject(ALGOLIA_CLIENT);
|
||||
|
||||
readonly resultsResource = resource({
|
||||
resultsResource = resource({
|
||||
params: () => this.searchQuery() || undefined, // coerces empty string to undefined
|
||||
loader: async ({params: query, abortSignal}) => {
|
||||
// Until we have a better alternative we debounce by awaiting for a short delay.
|
||||
@@ -97,7 +97,7 @@ export class Search {
|
||||
},
|
||||
});
|
||||
|
||||
readonly searchResults = linkedSignal<SearchResultItem[] | undefined, SearchResultItem[]>({
|
||||
searchResults = linkedSignal<SearchResultItem[] | undefined, SearchResultItem[]>({
|
||||
source: this.resultsResource.value,
|
||||
computation: (next, prev) => (!next && this.searchQuery() ? prev?.value : next) ?? [],
|
||||
});
|
||||
@@ -141,11 +141,10 @@ export class Search {
|
||||
|
||||
const items = result.hits as unknown as SearchResult[];
|
||||
|
||||
return this.getUniqueSearchResultItems(items).map((hitItem: SearchResult): SearchResultItem => {
|
||||
return this.getUniqueSearchResultItems(items).map((hitItem: SearchResult) => {
|
||||
const content = hitItem._snippetResult.content;
|
||||
const hierarchy = hitItem._snippetResult.hierarchy;
|
||||
const category = hitItem.hierarchy?.lvl0 ?? null;
|
||||
const hasSubLabel = hierarchy?.lvl2 || hierarchy?.lvl3 || hierarchy?.lvl4;
|
||||
const hasSubLabel = content || hierarchy?.lvl2 || hierarchy?.lvl3 || hierarchy?.lvl4;
|
||||
|
||||
return {
|
||||
id: hitItem.objectID,
|
||||
@@ -156,8 +155,6 @@ export class Search {
|
||||
subLabelHtml: this.parseLabelToHtml(
|
||||
hasSubLabel ? this.getBestSnippetForMatch(hitItem) : null,
|
||||
),
|
||||
contentHtml: content ? this.parseLabelToHtml(content.value) : null,
|
||||
package: category === 'Reference' ? extractPackageNameFromUrl(hitItem.url) : null,
|
||||
|
||||
category: hitItem.hierarchy?.lvl0 ?? null,
|
||||
};
|
||||
@@ -165,6 +162,11 @@ export class Search {
|
||||
}
|
||||
|
||||
private getBestSnippetForMatch(result: SearchResult): string {
|
||||
// if there is content, return it
|
||||
if (result._snippetResult.content !== undefined) {
|
||||
return result._snippetResult.content.value;
|
||||
}
|
||||
|
||||
const hierarchy = result._snippetResult.hierarchy;
|
||||
if (hierarchy === undefined) {
|
||||
return '';
|
||||
@@ -217,7 +219,7 @@ function matched(snippet: SnippetResult | undefined): boolean {
|
||||
/**
|
||||
* Temporary helper to implement the debounce functionality on the search resource
|
||||
*/
|
||||
function wait(ms: number, signal: AbortSignal): Promise<void> {
|
||||
function wait(ms: number, signal: AbortSignal) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => resolve(), ms);
|
||||
|
||||
@@ -231,11 +233,3 @@ function wait(ms: number, signal: AbortSignal): Promise<void> {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function extractPackageNameFromUrl(url: string): string | null {
|
||||
const extractedSegment = url.match(/\/api\/(.*)\/.*#?/);
|
||||
if (extractedSegment == null) {
|
||||
return null;
|
||||
}
|
||||
return `<code>@angular/${extractedSegment[1]}</code>`;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
--electric-violet: oklch(53.18% 0.28 296.97); // #8514f5
|
||||
--french-violet: oklch(47.66% 0.246 305.88); // #8001c6
|
||||
--vivid-pink: oklch(69.02% 0.277 332.77); // #f637e3
|
||||
--always-pink: oklch(69.02% 0.277 332.77); // #f637e3
|
||||
--hot-pink: oklch(59.91% 0.239 8.14); // #e90464
|
||||
--hot-red: oklch(61.42% 0.238 15.34); // #f11653
|
||||
--orange-red: oklch(63.32% 0.24 31.68); // #fa2c04
|
||||
@@ -24,7 +23,6 @@
|
||||
|
||||
// subtle-purple is used for inline-code bg, docs-card hover bg & docs-code header bg
|
||||
--subtle-purple: color-mix(in srgb, var(--bright-blue) 5%, white 10%);
|
||||
--subtle-blue: color-mix(in srgb, var(--bright-blue) 5%, white 95%);
|
||||
--light-blue: color-mix(in srgb, var(--bright-blue), white 50%);
|
||||
--light-violet: color-mix(in srgb, var(--electric-violet), white 65%);
|
||||
--light-orange: color-mix(in srgb, var(--orange-red), white 50%);
|
||||
@@ -213,7 +211,6 @@
|
||||
--electric-violet: color-mix(in srgb, oklch(53.18% 0.28 296.97), var(--full-contrast) 70%);
|
||||
--french-violet: color-mix(in srgb, oklch(47.66% 0.246 305.88), var(--full-contrast) 70%);
|
||||
--vivid-pink: color-mix(in srgb, oklch(69.02% 0.277 332.77), var(--full-contrast) 70%);
|
||||
// --always-pink we keep the same in light mode
|
||||
--hot-pink: color-mix(in srgb, oklch(59.91% 0.239 8.14), var(--full-contrast) 70%);
|
||||
--hot-red: color-mix(in srgb, oklch(61.42% 0.238 15.34), var(--full-contrast) 70%);
|
||||
--orange-red: color-mix(in srgb, oklch(63.32% 0.24 31.68), var(--full-contrast) 60%);
|
||||
@@ -223,7 +220,6 @@
|
||||
--deprecated-docs-bg: var(--deprecated-dark); // Alias specifically for deprecated docs
|
||||
|
||||
--light-pink: color-mix(in srgb, var(--vivid-pink) 5%, var(--page-background) 75%);
|
||||
--subtle-blue: color-mix(in srgb, var(--bright-blue) 5%, var(--page-background) 90%);
|
||||
|
||||
--symbolic-purple: color-mix(in srgb, oklch(42.86% 0.29 266.4), var(--full-contrast) 65%);
|
||||
--symbolic-gray: color-mix(in srgb, oklch(66.98% 0 0), var(--full-contrast) 65%);
|
||||
|
||||
@@ -5,18 +5,6 @@ $screen-lg: 1200px;
|
||||
$screen-xl: 1430px;
|
||||
$screen-xxl: 1800px;
|
||||
|
||||
@mixin breakpoints-vars {
|
||||
// The app-scroller also relies on these values to determine the scroll offset.
|
||||
:root {
|
||||
--screen-xs: #{$screen-xs};
|
||||
--screen-sm: #{$screen-sm};
|
||||
--screen-md: #{$screen-md};
|
||||
--screen-lg: #{$screen-lg};
|
||||
--screen-xl: #{$screen-xl};
|
||||
--screen-xxl: #{$screen-xxl};
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-phone-only {
|
||||
@media (max-width: $screen-xs) {
|
||||
@content;
|
||||
@@ -24,43 +12,43 @@ $screen-xxl: 1800px;
|
||||
}
|
||||
|
||||
@mixin for-tablet-portrait-up {
|
||||
@media (min-width: calc($screen-xs + 0.01px)) {
|
||||
@media (min-width: calc($screen-xs + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-tablet {
|
||||
@media (min-width: calc($screen-xs + 0.01px)) and (max-width: $screen-md) {
|
||||
@media (min-width: calc($screen-xs + .01px)) and (max-width: $screen-md) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-tablet-up {
|
||||
@media (min-width: calc($screen-sm + 0.01px)) {
|
||||
@media (min-width: calc($screen-sm + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-tablet-landscape-up {
|
||||
@media (min-width: calc($screen-md + 0.01px)) {
|
||||
@media (min-width: calc($screen-md + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-desktop-up {
|
||||
@media (min-width: calc($screen-lg + 0.01px)) {
|
||||
@media (min-width: calc($screen-lg + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-large-desktop-up {
|
||||
@media (min-width: calc($screen-xl + 0.01px)) {
|
||||
@media (min-width: calc($screen-xl + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin for-extra-large-desktop-up {
|
||||
@media (min-width: calc($screen-xxl + 0.01px)) {
|
||||
@media (min-width: calc($screen-xxl + .01px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@@ -87,4 +75,4 @@ $screen-xxl: 1800px;
|
||||
@media (max-width: $screen-sm) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background: var(--page-background);
|
||||
color: var(--primary-contrast);
|
||||
padding: 1.5rem;
|
||||
border: 1px solid var(--senary-contrast);
|
||||
@@ -41,7 +40,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
* + *:not(a):not(code):not(span):not(div) {
|
||||
* + *:not(a):not(code):not(span) {
|
||||
margin-block: 1.5rem;
|
||||
}
|
||||
|
||||
@@ -52,7 +51,6 @@
|
||||
flex-grow: 1;
|
||||
margin-block-start: 0;
|
||||
padding-inline: 1.5rem;
|
||||
padding-block: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
@@ -60,6 +58,7 @@
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0;
|
||||
margin-block-start: 1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
p {
|
||||
@@ -89,7 +88,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--subtle-blue);
|
||||
background: var(--subtle-purple);
|
||||
|
||||
span {
|
||||
background-position: 0% 0%;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
left: calc(var(--gutter) * -1);
|
||||
top: 1rem;
|
||||
top: 2.7rem;
|
||||
bottom: 0;
|
||||
|
||||
&::before {
|
||||
@@ -39,8 +39,7 @@
|
||||
border-radius: 50%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border: 1px solid transparent;
|
||||
background-image:
|
||||
linear-gradient(var(--page-background), var(--page-background)),
|
||||
background-image: linear-gradient(var(--page-background), var(--page-background)),
|
||||
var(--pink-to-purple-horizontal-gradient);
|
||||
background-origin: border-box;
|
||||
background-clip: content-box, border-box;
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
@include api-item-label.api-item-label();
|
||||
@include faceted-list.faceted-list();
|
||||
|
||||
@include mq.breakpoints-vars();
|
||||
@include mq.for-phone-only();
|
||||
@include mq.for-tablet-portrait-up();
|
||||
@include mq.for-tablet-landscape-up();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user