Compare commits

...

223 Commits

Author SHA1 Message Date
Matthew Beck 57ce2b64ef release: cut the v21.2.5 release 2026-03-18 17:33:53 -06:00
Angular Robot 5393d8ea2c docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-18 14:08:01 -06:00
SkyZeroZx 675d4fb489 docs: update import and note formatting in guides
(cherry picked from commit a8bf957086)
2026-03-18 13:04:21 -07:00
Jessica Janiuk 851ef77318 Revert "refactor(core): Ensure determineLongestAnimation is run synchronously after style applies"
This reverts commit 318ade062e.

(cherry picked from commit 890c97301f)
2026-03-18 10:30:40 -07:00
Yenya030 5800f17e19 refactor(service-worker): remove unnecessary cast in mock redirect check
Use the typed Response.redirected property directly in the service-worker test mock instead of casting to any.

(cherry picked from commit 57a07d0058)
2026-03-18 10:26:26 -07:00
Yenya030 e19150d2b5 fix(service-worker): preserve redirect policy on reconstructed asset requests
Preserve the redirect mode when rebuilding asset requests in newRequestWithMetadata(). This keeps explicit redirect:error semantics intact across service-worker redirect handling.

Update the worker test mocks to model redirect defaults correctly and add focused regression coverage for redirected lazy assets with redirect:error.

(cherry picked from commit 07abfbcc6c)
2026-03-18 10:26:25 -07:00
SkyZeroZx 0e496c1d85 docs(docs-infra): improve semantic HTML in update guide
Improves update guide's semantic HTML
2026-03-18 09:42:32 -06:00
kirjs 737777ef72 docs: add Angular Developer Skill updates
Includes:

- Imports and setup instructions

- Validation examples (sync, async, conditional)

- FieldState vs FormField distinction

- Common pitfalls and best practices

- Full-featured example application

(cherry picked from commit ed150e52d1)
2026-03-17 17:39:44 -07:00
marktechson fa26e7271f docs: adds angular-developer skill
Adds a new agent skill focused on providing fundamentals to coding agents and adhering
to modern Angular code including Signals, Signal Forms and other latest updates.

(cherry picked from commit 8291b16a36)
2026-03-17 17:39:43 -07:00
aparziale 076d41c3f6 fix(migrations): prevent trailing comma syntax errors after removing NgStyle
This fixes an issue where when removing NgStyle from the imports array of a component, an extra trailing comma would be left behind if it was the last element in that component`.

(cherry picked from commit 730684b9ce)
2026-03-17 17:01:28 -07:00
JoostK a8f80c1f99 refactor(core): declare explicit reactive node prototypes types
These type annotations allow TS to associate the object's properties
with their corresponding declaration in the interfaces, enabling
much better code navigation. For example, "Find all implementations"
for `ReactiveNode.producerRecomputeValue` now finds the implementation
in `COMPUTED_NODE` and `LINKED_SIGNAL_NODE`.

(cherry picked from commit 1eaf92077f)
2026-03-17 13:00:15 -07:00
JoostK bf948be4c2 fix(core): run linked signal equality check without reactive consumer
This commit ports the changes in #55818 from `computed` to `linkedSignal`,
which duplicates the core logic to recompute the downstream value for an
upstream change.

(cherry picked from commit 523d69a768)
2026-03-17 12:59:42 -07:00
yogeshwaran-c 23ea431c4e fix(compiler): parse named HTML entities containing digits
The lexer's isNamedEntityEnd function stopped scanning entity names
when encountering a digit character, causing 24 valid HTML named
entities with digits in their names (e.g. ¹, ½, ▓)
to be treated as plain text instead of decoded to their corresponding
Unicode characters.

Fixes #51323

(cherry picked from commit 75560ce43d)
2026-03-17 12:54:45 -07:00
Alan Agius 2fb767b139 build: remove redundant Bazel lockfile update workarounds
Renovate now natively supports updating Bazel lockfiles.

This change removes the `postUpgradeTasks` workaround in Renovate config

(cherry picked from commit a37dd59fc4)
2026-03-17 12:53:11 -07:00
Angular Robot b10e305ccc build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-17 13:52:37 -06:00
Alan Agius f0d19b88b1 docs: clarify X-Forwarded-Prefix header validation rules
(cherry picked from commit d0086e493b)
2026-03-17 12:50:15 -07:00
Kristiyan Kostadinov 67e0ba7e03 fix(compiler-cli): generic types not filled out correctly in type check block
Fixes a regression caused by the recent TCB changes where we moved the type parameter processing earlier in the pipeline and stopped properly accounting for the `TcbGenericContextBehavior`.

Fixes #67704.

(cherry picked from commit 9769560da7)
2026-03-17 12:21:31 -07:00
Angular Robot ca328eab8f docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-16 14:47:18 -06:00
Andrew Scott faeeef678a feat(dev-infra): add PR review agent skill
This commit introduces an AI agent skill for reviewing pull requests
against the Angular repository. It establishes guidelines for ensuring
code cleanliness, performance, testing, API design, and payload size.

It supports performing reviews through both the GitHub CLI (remote) and
local editing, factoring in package-specific guidelines (e.g., router)
and prioritizing user approval before posting comments. By checking existing
comments first, the agent can avoid duplicate reviews.

This provides the AI agent with a reproducible workflow for providing
constructive, manual PR feedback.

(cherry picked from commit 2e34924647)
2026-03-16 13:25:51 -07:00
Angular Robot 4d786517d3 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-16 10:54:17 -06:00
Kristiyan Kostadinov 26c43d14ba fix(compiler-cli): escape template literal in TCB
Fixes a regression introduced by #67381 where we weren't escaping backticks in template literals.

Fixes #67675.

(cherry picked from commit 2bd708fb6b)
2026-03-16 09:47:29 -07:00
Max Millien 1890c3008b fix(core): clean up dehydrated views during HMR component replacement
During HMR, `recreateLView()` destroys the old LView and removes its
DOM nodes, but never cleans up dehydrated view DOM nodes stored in
`LContainer[DEHYDRATED_VIEWS]`. These are SSR-rendered DOM nodes
preserved by Angular's hydration system. When the new view renders,
both the old dehydrated DOM and the new DOM coexist, causing visible
duplication (e.g. `<app-shell>` header/footer appearing twice).

Call `cleanupLView` from the hydration cleanup module after
`destroyLView` and before `removeViewFromDOM` to remove any remaining
dehydrated DOM nodes before the replacement view is rendered.

Fixes #66503

(cherry picked from commit dc0446552a)
2026-03-16 09:04:11 -07:00
hawkgs cbb2266984 test(devtools): fix and update flaky component-tree tests
Due to the design of the `ng.getComponent` spy and a race condition where sometimes a `<script>` is added to the test DOM, the `getRootElements` tests used to fail sometimes because those `<script>`s were marked as roots which caused a distortion in the roots count checks. The commit addresses that and also adds an additional test for non-application root Angular components.

(cherry picked from commit 77d7378ffd)
2026-03-16 09:03:47 -07:00
SkyZeroZx ea4847aae5 docs(docs-infra): add spacing between reference option and description
Add a spacing class to `docs-reference-option` to prevent the text from appearing too close together.

(cherry picked from commit 3720b2de0f)
2026-03-16 09:00:50 -07:00
Akash Patel 5fa3052ed1 docs: update uninstallation commands for Karma packages
Added 'jasmine-core' to the list of packages to uninstall when migrating to Vitest.

(cherry picked from commit b9ff865b49)
2026-03-16 08:59:38 -07:00
SkyZeroZx 86718fbbe1 docs: fix type code block language
fix type code block language

(cherry picked from commit acd6f690bd)
2026-03-16 08:59:13 -07:00
guidettj de5fbb7deb docs: use lighter lodash isEqual import in equality example
(cherry picked from commit 7d483f28a4)
2026-03-16 08:58:44 -07:00
Angular Robot f39896da99 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-13 16:25:45 -06:00
ibrahim-hussien-dev 21cab20dae docs: combine multiple documentation typo fixes
(cherry picked from commit e127927807)
2026-03-13 12:10:59 -07:00
Angular Robot 2d28e9b392 build: update pnpm to v10.32.1
See associated pull request for more information.
2026-03-13 13:08:54 -06:00
Alan Agius 5b46a63c08 build: update rules_angular dependency commit hash
Update rules_angular to latest sha
2026-03-13 13:07:06 -06:00
Alan Agius 03fb3cd463 refactor: ensure modules with 'declare global' are correctly handled by Rollup
Explicitly adding an `export {}` to modules containing declare global fixes an issue where Rollup would incorrectly claim that the global variable is not defined in the emitted .d.ts files.

Needed to land the latest rules_angular.
2026-03-13 13:07:06 -06:00
SkyZeroZx 67a73192bf docs(docs-infra): remove tap highlight for API reference list filter
Prevents the default translucent highlight from appearing on touch devices when interacting with the API reference list filter.

(cherry picked from commit 7cd474d1d6)
2026-03-13 12:04:06 -07:00
Jessica Janiuk e5ed276f27 refactor(core): Ensure determineLongestAnimation is run synchronously after style applies
This adds a setTimeout, which guarantees that we call getAnimations one frame after a reflow is finished. This means getAnimations will return data, avoiding needing the expensive fallback of getComputedStyles. It also updates the cleanup to prevent a potential memory leak if the component is destroyed before the timeout runs.

(cherry picked from commit 318ade062e)
2026-03-13 12:03:15 -07:00
Kristiyan Kostadinov 334ae10168 fix(compiler): ensure generated code compiles
Initial pass to make sure some common cases produce code that compiles.
2026-03-13 12:53:47 -06:00
Kristiyan Kostadinov 1f2dc72e8a refactor(compiler-cli): update ast factories to account for type nodes
Updates the Babel and TypeScript AST factories to account to produce type nodes.
2026-03-13 12:53:47 -06:00
Kristiyan Kostadinov e3b0e5a0b3 refactor(compiler-cli): add type nodes to translator
Updates the translator and AST factories to account for type nodes.
2026-03-13 12:53:47 -06:00
Kristiyan Kostadinov 10b0dd94e9 refactor(compiler-cli): add generic for type nodes to AST factories
Updates the type factories and various usage sites to add a generic for type nodes.
2026-03-13 12:53:47 -06:00
Jessica Janiuk 6f41efc689 refactor(core): Update determineLongestAnimation to account for playback rate
This updates the determineLongestAnimation code to also calculate the playback rate in with the duration, which should also account for timing when testing with playback rates changed in devtools.

(cherry picked from commit 17d8a88ddc)
2026-03-12 16:36:54 -07:00
Kristiyan Kostadinov bfb8b177ac refactor(compiler-cli): remove more unused code
Cleans up some more usages of TS factory APIs and some unused functions.
2026-03-12 16:21:50 -06:00
Kristiyan Kostadinov 2feced366a refactor(compiler-cli): replace typescript usage in type reference emits
Replaces our usage of TypeScript APIs in several places that emit references to type nodes. Also deletes some unused code.
2026-03-12 16:21:50 -06:00
Alan Agius 5d755be01c refactor: ensure modules with 'declare global' are correctly handled by Rollup
Explicitly adding an `export {}` to modules containing `declare global` fixes an issue where Rollup would incorrectly claim that the `global` variable is not defined in the emitted `.d.ts` files.

Needed to land the latest `rules_angular`.

(cherry picked from commit bb628d8b50)
2026-03-12 13:58:03 -07:00
Matthew Beck 8017617fd9 release: cut the v21.2.4 release 2026-03-12 12:58:02 -06:00
Kristiyan Kostadinov ed2d324f9c fix(compiler): disallow translations of iframe src
Fixes that the compiler was allowing translations of `src` attributes in iframes which can be a security issue.

(cherry picked from commit 78dea55351)
2026-03-12 10:01:31 -07:00
Kristiyan Kostadinov d1dcd16c5b fix(core): sanitize translated form attributes
Fixes that we weren't sanitizing the `form` and `formaction` attributes when they're used together with translations.

(cherry picked from commit de0eb4c656)
2026-03-12 10:01:30 -07:00
Jessica Janiuk abbd8797bb fix(core): reverts "feat(core): add support for nested animations"
This reverts commit ea2016a6dc.

This reverts the support for nested animations due to the global scope of how nested animations were gathered.
This caused issues where on route navigations, all child nodes with animations would be queued and run before the navigation would occur.
We'll be revisiting the nested animations with a more tightened scope of when those leave animations will occur.

fixes: #67552
(cherry picked from commit 999c14eaab)
2026-03-12 09:58:07 -07:00
Angular Robot c06e3a0bb4 build: update bazel dependencies
See associated pull request for more information.
2026-03-11 14:41:33 -07:00
wokis 8ba2844da5 docs: document coverageExclude option for excluding files from coverage
(cherry picked from commit 3d25953e69)
2026-03-11 21:31:10 +00:00
Jon Snow 74698d58ec docs(forms): clarify zoneless change detection for reactive FormArray updates
Document that reactive forms model mutations such as FormArray.push() do not schedule component change detection in zoneless applications and show the recommended ways to notify Angular.

Fixes #65536

(cherry picked from commit 88235a0d12)
2026-03-11 14:13:27 -07:00
Andrew Scott a7e3d764e5 release: bump VSCode extension version to 21.2.3 (#67629) 2026-03-11 14:09:57 -07:00
Alan Agius 7907e982ee test: remove duplicate tests
These tests are duplicate and have been removed.
2026-03-11 13:35:26 -07:00
Alan Agius adda6c5c10 build: update aspect_rules_js to 3.0.2
This updates the major version of `aspect_rules_js`.
2026-03-11 13:35:26 -07:00
Andrew Scott e7593653be release: cut the v21.2.3 release 2026-03-11 12:03:13 -07:00
JoostK 21b1c3b2ee fix(core): include signal debug names in their toString() representation
The `toString()` implementations in the primitives package intended to include
the debug name, yet the debug name was evaluated during construction before it
could ever have been assigned. This commit fixes that.

The Angular wrappers override the `toString()` representation to evaluate signals
ad-hoc instead of showing their internal state, and this commit aligns their
behavior to include the debug name in `toString` as well.

(cherry picked from commit b401c18674)
2026-03-11 18:28:39 +00:00
SkyZeroZx 6c73aaca30 refactor(common): Removes unused generic type parameters from KeyValueDiffers
Remove unused generic type parameters from KeyValueDiffers methods

(cherry picked from commit 0837d25a70)
2026-03-11 17:49:15 +00:00
Matthieu Riegler c98eab794c refactor(core): remove old resource params
G3 has been cleaned up we can drop those.

(cherry picked from commit 4842f5a3b7)
2026-03-11 17:44:16 +00:00
Thomas Willberger d45fced21b docs: remove duplicate aria-hidden attribute in angular aria ngTree example
(cherry picked from commit eafce6ed09)
2026-03-11 17:03:13 +00:00
SkyZeroZx ed48c41f65 refactor(compiler-cli): simplifies IncrementalCompilation.fresh
Removes the `ts.Program` argument from the `IncrementalCompilation.fresh` method.

(cherry picked from commit 66e72efef4)
2026-03-11 16:41:05 +00:00
Ibrahim Hussien 75135586d6 docs: combine multiple documentation improvements into one PR
(cherry picked from commit 903d51e855)
2026-03-11 16:29:49 +00:00
Angular Robot ff697707ba build: update pnpm to v10.32.0
See associated pull request for more information.
2026-03-11 09:28:49 -07:00
SkyZeroZx 7d76103999 docs(docs-infra): fix close button clickability and prevent layout shift
Adjust the z-index to ensure the close button remains clickable.

Also remove an unnecessary `position: relative` that was causing
layout shifts in the docs UI, which resulted in a visible and
unintended layout movement.

(cherry picked from commit 3ce1d9a755)
2026-03-11 16:28:10 +00:00
Matthieu Riegler 575f3023c1 refactor(core): interface cleanup
Should be fine to land this time.

(cherry picked from commit a675950e44)
2026-03-10 19:44:36 +00:00
Andrew Scott 4c86ed382d refactor(compiler-cli): abstract type check block metadata to be AST-free
This commit refactors the template type checking metadata interfaces to use detached, serializable metadata rather than retaining direct references to ts.Node or ts.Declaration instances.

A new tcb_adapter translates traditional TypeScript AST-bound metadata into these decoupled structures. This abstraction lays the groundwork for supporting native preprocessors (such as Rust or ts-go) which serialize metadata over JSON rather than passing live TypeScript objects.

Key changes:
- Introduced TcbDirectiveMetadata, TcbComponentMetadata, TcbReferenceMetadata, and TcbPipeMetadata to replace TypeCheckableDirectiveMeta where appropriate.
- Substituted deep TS compilation AST references with string module names and source spans to preserve out-of-band diagnostic capabilities.
- Detached generic typeParameters and transformType properties into synthesized, standalone TS mappings.
- Updated generateTypeCheckBlock and corresponding Operations to consume the new metadata.
2026-03-10 12:39:18 -07:00
Kristiyan Kostadinov 224e60ecb1 fix(core): sanitize translated attribute bindings with interpolations
Fixes that we weren't sanitizing attribute bindings with interpolations if they're marked for translation, for example: `<a href="{{evilLink}}" i18n-href></a>`.

Also adds a bit more test coverage for our sanitization.

(cherry picked from commit 8630319f74)
2026-03-10 18:13:54 +00:00
Kristiyan Kostadinov 492e7560e6 build: include localize in dev app
Includes `$localize` in the dev app so it's easier to test some code paths.

(cherry picked from commit f80ac30875)
2026-03-10 18:13:53 +00:00
Jon Snow 09638ec7c3 docs(core): clarify provideZoneChangeDetection usage in v21+
Clarify that provideZoneChangeDetection() is used to opt applications into NgZone/ZoneJS-based change detection and to configure NgZone options such as eventCoalescing.

Fixes #67498

(cherry picked from commit 196933863b)
2026-03-10 17:21:13 +00:00
Guseyn ab35383285 docs: fix first-app code getHousingLocationById housing.service.ts
1. Get location by Id work with `${this.url}/${id}`
2. Method getHousingLocationById returned empty object, api return object type, locationJson[0] ?? {} - give in result empty object.

(cherry picked from commit 9794e756f9)
2026-03-10 17:02:43 +00:00
Angular Robot 934e2732b3 build: lock file maintenance
See associated pull request for more information.
2026-03-10 09:59:30 -07:00
Guseyn c20dabda2a docs: fix first-app 13 step docs code row numbers
Fix docs code row numbers.

(cherry picked from commit 7bc7c57636)
2026-03-10 16:59:08 +00:00
Kristiyan Kostadinov 62a97f7e4b fix(core): ensure definitions compile
Includes the following changes to make sure the definitions for injectable compiler:
1. The types for the `factory` function now include the `parent` parameter.
2. `ɵɵFactoryDeclaration` is now defined as a function. We need this since the provider definition gets passed into the inejctable definition by reference.
3. `ɵɵdefineInjectable`, `ɵɵdefineNgModule` and `ɵɵdefinePipe` now return the typed definition, rather than `unknown`. This aligns with what we do for components and directives.

(cherry picked from commit f9ede9ec98)
2026-03-10 16:58:22 +00:00
Eugene Serkin 106cf4ee90 docs: Update migration docs for vitest
This update fixes minor grammar mistakes

(cherry picked from commit 20496988b1)
2026-03-10 16:23:53 +00:00
Angular Robot 024e307ab0 build: update pnpm to v10.31.0
See associated pull request for more information.
2026-03-09 17:00:10 -07:00
SkyZeroZx 77b035eca6 docs: Adds @see links and update defer reference
(cherry picked from commit 6073493c5b)
2026-03-09 23:59:43 +00:00
Sonu Kapoor 4a9b715b3a test(forms): cover transformedValue without FormField context
Adds a test verifying that `transformedValue` exposes parse errors via
the returned signal's `parseErrors()` property when no FormField
context is present.

This ensures that:
- parse errors are still observable without DI-based field propagation
- the model is not updated when `parse` omits `value`
- valid input clears parse errors and updates the model

This test protects the documented contract that DI-based error
propagation is expected for FormValueControl usage, while standalone
usage relies on explicit consumption of `parseErrors()`.

(cherry picked from commit 71b8159b37)
2026-03-09 23:41:52 +00:00
Jessica Janiuk 420aa725ae docs: Update animation docs for element removal order
This update the docs to be clear that descendent node animations will happen before the parent node is removed.

fixes: #67526
(cherry picked from commit 8c17721333)
2026-03-09 23:40:48 +00:00
Matthieu Riegler c499c578c9 ci: fix exclusion of manual_api_docs
On top of #67253, dev-infra should be required for docs files

(cherry picked from commit bf93ff83d8)
2026-03-09 23:27:47 +00:00
Matthieu Riegler 0588133210 refactor(core): remove private export of getDebugNode
This is a public api

(cherry picked from commit 0afe3c00ae)
2026-03-09 18:21:23 +00:00
Andrew Scott 6416a31c1b refactor(core): update componentDeclaration to include isSignal
This is in DirectiveDeclaration and in the golden files with ComponentDeclaration
so I assume it was an accidental omission.

(cherry picked from commit e97f5139ec)
2026-03-09 18:17:42 +00:00
Andrew Scott b2b903957a release: cut the v21.2.2 release 2026-03-09 11:11:43 -07:00
Matthieu Riegler bd72571583 refactor(devtools): prevent spamming the message bus
This commit adds some state on the bus to prevent sending unecessary messages to the main window.

(cherry picked from commit 263b819a75)
2026-03-09 10:46:08 -07:00
Kam 628f3f99db docs: add Turkish community translation of Angular documentation
add a link to the community-driven Turkish translation of Angular
documentation to make it easier for Turkish-speaking developers to
discover localized docs.

The translation project is maintained by the community and hosted at:
https://github.com/erkamyaman/angular-tr

Providing documentation in developers' native languages helps lower
the barrier to entry and supports wider Angular adoption in the
Turkish-speaking developer community.

(cherry picked from commit 03465360bd)
2026-03-09 10:29:25 -07:00
hawkgs 79ac570c26 refactor(devtools): fix browser-specific styles infra
Fix browser-specific styles infrastructure. PR #62786 cleans up part of the code, but there are still services that attempt to load these stylesheets on `main`.

(cherry picked from commit ed3dc10fea)
2026-03-09 10:22:02 -07:00
Angular Robot 276c12a349 build: update dependency node to v22.22.1
See associated pull request for more information.
2026-03-06 15:32:15 -08:00
Angular Robot 104ac117ea docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-06 15:04:42 -08:00
Angular Robot c2a74548d9 build: update all github actions
See associated pull request for more information.
2026-03-06 14:36:16 -08:00
Kristiyan Kostadinov e7d1d8def3 refactor(core): add tracing for component creation
Adds tracing support for component creations.

(cherry picked from commit c19066c741)
2026-03-06 17:48:27 +00:00
Kristiyan Kostadinov 4a390b6c73 refactor(core): track the tracing service in the LView environment
Adds the `TracingService` to the `LView[ENVIRONMENT]` so we don't have to inject it everywhere.

(cherry picked from commit e433ba9a80)
2026-03-06 17:48:27 +00:00
Anushka Geeta Singh 5a486a65cf docs(router): Add example of relative navigation and multiple array values
Adds an example to docs with relative navigation and multiple values in
the commands array.

(cherry picked from commit 418cb61f2f)
2026-03-06 17:47:44 +00:00
Kristiyan Kostadinov c822bf8e76 fix(compiler-cli): always parenthesize object literals in TCB
This is a follow-up to #67381 which introduced a subtle bug where depending on the type checking configuration, we may put an object literal directly in the TCB body which the TS compiler ends up interpreting as a block. These changes resolve the issue by always wrapping the literal in parentheses.
2026-03-05 14:12:25 -08:00
Kristiyan Kostadinov 31e2c99007 refactor(compiler-cli): resolve presubmit issues
Resolves issues caught during the presubmit.
2026-03-05 14:12:25 -08:00
Kristiyan Kostadinov f8b6bd0cbe refactor(compiler-cli): escape quotes used in string expressions
TypeScript has functionality that automatically escapes quotes in string literals. These changes update the places where we may need to do the same ourselves.
2026-03-05 14:12:25 -08:00
Kristiyan Kostadinov 5349b027b8 refactor(compiler-cli): delete unused utilities
Deletes utilities that we no longer use.
2026-03-05 14:12:25 -08:00
Kristiyan Kostadinov 8f8d67dc57 refactor(compiler-cli): initial decoupling from TypeScript factory APIs
Initial pass to move usages of TS `factory` APIs to the new `TcbExpr`.
2026-03-05 14:12:25 -08:00
Kristiyan Kostadinov 23153a06dd refactor(compiler-cli): introduce new primitive for generating TCB code
Introduces the `TcbExpr` class that will be used to generate TCB code without going through TypeScript's factory APIs.
2026-03-05 14:12:25 -08:00
Alan Agius fd3b4413f3 docs: add a new section on nonces and caching considerations to the security guide.
(cherry picked from commit e5f99edda5)
2026-03-05 18:03:35 +00:00
Leon Senft 670d1660c4 feat(forms): add 'blur' option to debounce rule
Expands the `debounce` rule configuration to accept `'blur'`. When this option
is provided, the rule will delay model synchronization until the field loses
focus (is touched). This introduces a debouncer that defers resolution
until the framework automatically aborts pending debounces upon touch events.

(cherry picked from commit c767d678cf)
2026-03-05 17:55:18 +00:00
Angular Robot 8ca0237d99 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-04 16:27:39 -08:00
Joey Perrott 3576019c0f build: no longer require release mode for releases
This commit updates the github.mjs configuration to set requireReleaseModeForRelease to false, removing the requirement to use release mode for releases in the angular/angular repository.

(cherry picked from commit a6941adce8)
2026-03-04 22:48:59 +00:00
Doug Parker 05d022d5e6 fix(compiler-cli): ignore generated ngDevMode signal branch for code coverage
The Angular compiler unconditionally adds a debug name transform for signals
which generates a conditional on `ngDevMode` (e.g., `ngDevMode ? { debugName: "xyz" } : []`).
During testing, `ngDevMode` is true, so the true branch executes but the
false branch is never executed. Consequently, coverage tools report the
false branch as an untested line/branch, preventing 100% test coverage.

This commit adds a synthetic `/* istanbul ignore next */` comment to the
generated false branch so that Istanbul ignores it. We only include the
istanbul comment (instead of additionally including c8) to focus on the
established standard for Angular CLI/Karma coverage while maintaining
compatibility with modern Vitest setups, since @vitest/coverage-v8 now
natively respects the fallback istanbul comment.

Fixes #64583

(cherry picked from commit dc4cf649b6)
2026-03-04 22:42:57 +00:00
Andrew Scott 1df1697c6e fix(compiler): prevent mutation of children array in RecursiveVisitor
RecursiveVisitor.visitIfBlockBranch was permanently mutating the children array by pushing the expressionAlias into it. This change clones the array before pushing to avoid this side effect.

(cherry picked from commit 72a17afaf3)
2026-03-04 22:41:36 +00:00
Andrew Scott 05476ea21b release: bump VSCode extension version to 21.2.2 (#67449) 2026-03-04 12:40:40 -08:00
Jessica Janiuk f38169d0a7 release: cut the v21.2.1 release 2026-03-04 11:34:05 -08:00
Jessica Janiuk 6d7446bc6c refactor(core): account for shadow roots in animations
This adds a util function to get the proper target, properly accounting for shadow roots.

(cherry picked from commit fda08b7a89)
2026-03-04 18:16:43 +00:00
SkyZeroZx c25c84d7dc docs: add customization options for browser URL in routing guide
(cherry picked from commit 9208421290)
2026-03-04 18:10:29 +00:00
Angular Robot f4160c2073 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-04 10:01:57 -08:00
Jessica Janiuk 93c6dc6395 Revert "refactor(http): Improves base64 encoding/decoding with feature detection (#67002)"
This reverts commit aafeb1d2bd.

(cherry picked from commit 5338b5912c)
2026-03-04 17:19:14 +00:00
Jessica Janiuk 76431ed3e3 Revert "fix(http): correctly cache blob responses in transfer cache (#67002)"
This reverts commit 1f057afaac.

(cherry picked from commit 7eb33713b9)
2026-03-04 17:19:14 +00:00
Jessica Janiuk b4ec3cc4e4 fix(core): prevent child animation elements from being orphaned
When routing between two different routes, child animations were not finishing, causing elements to be left behind in the dom. The fix ensures the proper fallback is handled to avoid automatically cancelled custom events. This ensures the animation-fallback cancelling the animation actually completes, and ensures the element is removed.

fixes: #67400
(cherry picked from commit 9e64147b73)
2026-03-04 16:21:41 +00:00
Angular Robot 84e79f5add build: update pnpm to v10.30.3
See associated pull request for more information.
2026-03-04 08:03:41 -08:00
SkyZeroZx 2eecf0d9a2 docs: add documentation for dynamic validation schemas
(cherry picked from commit 9fa36d1a71)
2026-03-04 16:01:36 +00:00
Kristiyan Kostadinov da57d1af73 build: use TypeScript 5.9 for patch builds
Partially rolls back to using TypeScript 5.9 for the builds on the patch branch, because we bundle our TypeScript version with the language service which can introduce unexpected breakages for users.

Note that we still allow users to install TypeScript 6.
2026-03-04 07:59:23 -08:00
Georgi Serev 58ea4d2ee8 docs(docs-infra): add Azerbaijani community translation
Add https://angular.az (Azerbaijani) to the community translations section.

(cherry picked from commit e8676b5412)
2026-03-04 15:58:23 +00:00
SkyZeroZx 277ade97ac fix(http): correctly cache blob responses in transfer cache (#67002)
Previously, Blob values were passed to `Uint8Array` this resulted in silently producing an empty array (length = 0) without throwing an error, leading to empty cached data

PR Close #67002
2026-03-04 15:56:59 +00:00
SkyZeroZx aeb9b819d2 refactor(http): Improves base64 encoding/decoding with feature detection (#67002)
Use feature detection for `Uint8Array.prototype.toBase64` and
`Uint8Array.fromBase64`, falling back to the existing implementation
when native support is not available

PR Close #67002
2026-03-04 15:56:59 +00:00
Angular Robot 657d532ad1 build: update dependency preact-render-to-string to v6.6.6
See associated pull request for more information.
2026-03-03 14:48:18 -08:00
Angular Robot 8dafd2413a build: update dependency aspect_rules_jasmine to v2.0.4
See associated pull request for more information.
2026-03-03 14:46:02 -08:00
Angular Robot 796b9a714a build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-03 14:22:51 -08:00
Krueger01 dd551b1ff3 refactor(compiler-cli): update old angular.io references to angular.dev
Update comment references from the old site angular.io to the new site
angular.dev.

(cherry picked from commit 0e9d58ef09)
2026-03-03 22:22:23 +00:00
Andrew Scott 84adb2fb3b refactor(router): Permit deferring commit of traversal navigations
This updates the state manager to allow intercepting and deferring commits of traversal navigations.
The issues that were encountered in the past appear to be resolved in Chrome.
The behavior of redirect is still undefined in this case, so there is an added TODO.

(cherry picked from commit 778b748694)
2026-03-03 22:09:15 +00:00
Angular Robot 98343ea35e build: update cross-repo angular dependencies to b1b4bd0
See associated pull request for more information.
2026-03-03 10:36:54 -08:00
Angular Robot c4226a10d0 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-03 09:54:56 -08:00
Sai Kumar Kola 5e545069ac docs: fix side navigation bar foreground colors in both dark and light modes #67379
(cherry picked from commit 46c996a977)
2026-03-03 17:13:11 +00:00
SkyZeroZx ecf0bb4668 test(http): refactors HTTP client tests to use TestBed and providers
Updates HTTP client, JSONP, and XSRF tests to utilize `TestBed` for setup.

(cherry picked from commit ead6bb1f52)
2026-03-03 17:12:39 +00:00
Ben Hong 0d54c5f0e2 docs: modernize testing service guide
(cherry picked from commit 5955738bc4)
2026-03-03 17:12:03 +00:00
Angular Robot 8f6ca1d9f9 build: lock file maintenance
See associated pull request for more information.
2026-03-03 09:08:50 -08:00
Angular Robot 1f51c61372 build: update cross-repo angular dependencies to 2648276
See associated pull request for more information.
2026-03-02 12:22:46 -08:00
Jessica Janiuk f5e9a862c2 refactor(core): ignore infinite animations in animate api
This ensures that when calculating longest animations, we completely ignore infinite animations. This will prevent mistakes with using the API and hopefully catch any unexpected bugs.

fixes: #67350
(cherry picked from commit 9758ea9ee9)
2026-03-02 19:40:19 +00:00
Angular Robot 0c8a2858b9 build: update cross-repo angular dependencies to v21.2.0
See associated pull request for more information.
2026-03-02 11:32:52 -08:00
Matthieu Riegler a79e8afbad docs: update doc for provideZoneChangeDetection
fixes #67209

(cherry picked from commit a2d5048ff3)
2026-03-02 19:02:34 +00:00
SkyZeroZx 7b7faef739 docs: fixed note on event replay
(cherry picked from commit d793ee0bb7)
2026-03-02 18:59:21 +00:00
Joey Perrott 95afc09206 ci: update the path to the labeling github actions
Update the paths to the labeling github actions after the refactor in dev-infra

(cherry picked from commit 787db90e08)
2026-03-02 18:55:57 +00:00
kirjs 23cb9a4291 refactor(forms): address feedback
Refactor the normalizeFormArgs utility to include the internal FieldAdapter

(cherry picked from commit d2e33e86b9)
2026-03-02 16:46:47 +00:00
kirjs 0a863ba03f refactor(forms): hide adapter in public options
Moves adapter to internal options to prevent exposure but keep compatibility.

(cherry picked from commit 985d828f12)
2026-03-02 16:46:47 +00:00
Jessica Janiuk e923d88398 fix(core): Prevent removal of elements during drag and drop
This addresses a reported issue where elements were being fully removed from the DOM during drag and drop operations.

fixes: #67257
(cherry picked from commit 0b59cba85d)
2026-03-02 16:46:13 +00:00
Angular Robot 150f0b3c30 build: update cross-repo angular dependencies to 90e509f
See associated pull request for more information.
2026-03-02 08:42:55 -08:00
Angular Robot fc5f9d03cf build: update pnpm to v10.30.3
See associated pull request for more information.
2026-03-02 08:37:49 -08:00
Angular Robot 498d9cdda4 build: update cross-repo angular dependencies to 9cc4778
See associated pull request for more information.
2026-02-27 09:11:11 -08:00
Angular Robot fd8d29a157 build: update dependency bazel to v8.6.0
See associated pull request for more information.
2026-02-27 09:10:15 -08:00
Jessica Janiuk e2e9a9a531 fix(core): adds transfer cache to httpResource to fix hydration
This should prevent the microtask problem with hydration and httpResource.

fixes: #62897
(cherry picked from commit 88685cb3b6)
2026-02-27 17:09:26 +00:00
Matthieu Riegler 35fd8b567a build: use different default port for dev-app
Same as ADEV, currently the CLI prompts for another port if 4200 is busy but the toolchain doesn't support prompts.

By defaulting to 4201 we avoid regular CLI apps from preventing to run the dev-app

(cherry picked from commit 9bb4f02bef)
2026-02-27 17:04:19 +00:00
Angular Robot 4e9648d184 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 14:32:59 -08:00
Angular Robot 54a0541013 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 13:42:33 -08:00
Joey Perrott 9c0587f755 build: update to latest sha of dev-infra repo
Update to the latest sha of the dev-infra repo

(cherry picked from commit d1ebbbe9bc)
2026-02-26 20:42:17 +00:00
Joey Perrott ac06941bcf build: update to latest sha of dev-infra repo
Update to the latest sha of the dev-infra repo

(cherry picked from commit 385b9485c4)
2026-02-26 20:22:25 +00:00
Joey Perrott 907415c801 ci: set up automated issue labeling
Sets up automated issue labeling action

(cherry picked from commit 37b4d16357)
2026-02-26 20:22:25 +00:00
Angular Robot 225a56677e build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 10:40:54 -08:00
Joey Perrott 944181869d ci: set up linting for upcoming agent skills
Add validation/linting on CI for agent skills files

(cherry picked from commit 078da3cbda)
2026-02-26 18:04:30 +00:00
Joey Perrott 3d3e6cbf20 build: update repository locations for bazel rules
The repositories for `rules_sass`, `rules_angular`, and `rules_browsers`
were recently transferred from devversion to the angular organization.
This commit updates the internal bazel module rules to rely on
the new repository locations.

(cherry picked from commit b4f68acaa1)
2026-02-26 17:57:15 +00:00
Angular Robot 2158bf8bb8 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 09:44:02 -08:00
Matthieu Riegler 1b46b6db18 docs: add info around route level services
fixes #67313

(cherry picked from commit 95f12c87aa)
2026-02-26 16:20:02 +00:00
Matthieu Riegler f23f3e7f5f docs: add mention of identity tracking for field iterations
related to #66711

(cherry picked from commit 7d92d4454b)
2026-02-26 15:52:58 +00:00
Angular Robot 9414da5b7e build: update all github actions
See associated pull request for more information.
2026-02-26 07:50:54 -08:00
Angular Robot 8078abe893 build: update bazel dependencies
See associated pull request for more information.
2026-02-26 07:50:17 -08:00
Joey Perrott 661e800302 release: bump VSCode extension version to 21.2.1 2026-02-25 15:34:03 -08:00
Angular Robot c960a6e492 build: update cross-repo angular dependencies to v21.2.0
See associated pull request for more information.
2026-02-25 15:11:49 -08:00
Angular Robot 2eeb4b5666 build: update cross-repo angular dependencies to v21.2.0
See associated pull request for more information.
2026-02-25 12:47:33 -08:00
Hien 8f19cf8d84 docs(forms): fix casing of 'FormField' to 'formField' in templates
(cherry picked from commit de0cc817cd)
2026-02-25 20:46:06 +00:00
Jessica Janiuk 50a9ed190d release: cut the v21.2.0 release 2026-02-25 11:29:08 -08:00
Angular Robot e437980659 build: update cross-repo angular dependencies
See associated pull request for more information.

Closes #67275 as a pr takeover
2026-02-25 10:26:00 -08:00
Angular Robot d3ab1ea5f2 build: lock file maintenance
See associated pull request for more information.
2026-02-25 08:52:48 -08:00
Sonu Kapoor fe7b26e403 docs(forms): transformedValue parse error wiring
(cherry picked from commit 547ed65b6f)
2026-02-25 16:13:16 +00:00
SkyZeroZx 70e4c7fbab refactor(common): log a warning when a KeyValuePipe receives a signal
Add signal warning for `KeyValuePipe` and consolidates the `invalidPipeArgumentError` function into a `utils`

(cherry picked from commit 97ed3d9e85)
2026-02-25 16:11:34 +00:00
Angular Robot a25f74238e build: update jasmine dependencies to v6.1.0
See associated pull request for more information.
2026-02-25 07:57:47 -08:00
Angular Robot 61ad0f8b90 build: update pnpm to v10.30.2
See associated pull request for more information.
2026-02-25 07:54:45 -08:00
Matthieu Riegler a86c3214c2 ci: update pullapprove for manual_api docs
The markdown files shouldn't require dev-infra approval.

(cherry picked from commit 0cd00b91ef)
2026-02-24 23:23:34 +00:00
Anushka Geeta Singh 706cfecaee docs: update README to clarify app setup confirmation
Improved wording to clarify how beginners can verify their environment and IDE are correctly set up after running the app.

(cherry picked from commit bdbb7cc7af)
2026-02-24 22:22:32 +00:00
Angular Robot 63cb3f4fa8 build: update bazel dependencies
See associated pull request for more information.
2026-02-24 14:10:29 -08:00
Matthieu Riegler 787cd875b0 refactor(vscode-extension): Add support for exhaustive type check in the syntax
`@default never` will be considered a keyword on its own.

(cherry picked from commit db11e74b3d)
2026-02-24 19:23:50 +00:00
Matthieu Riegler 1a151f2dae docs: add docs for @switch Exhaustive type checking
(cherry picked from commit 9dc3ca44ec)
2026-02-24 18:53:47 +00:00
Munir Issa Said 6b112e6c6c docs: fix roadmap introduction text
(cherry picked from commit 035b151a17)
2026-02-24 18:52:38 +00:00
Doug Parker 7d58b798c6 fix(core): block creation of sensitive URI attributes from ICU messages
Translators are not allowed to write HTML which creates URI attributes. I opted to ban any values going into an attribute at all, to prevent even links to malicious content, rather than just sanitizing URIs.

I also converted this blocklist into an allowlist. Now, we only allowing setting known attributes (while sanitizing URI attributes). This significantly reduces risk of missing a vulnerable attribute and does not require an exhaustive list of all potential attributes.

BREAKING CHANGE: Angular now only applies known attributes from HTML in translated ICU content. Unknown attributes are dropped and not rendered.

(cherry picked from commit 306f367899)
2026-02-24 18:50:41 +00:00
Alan Agius ab1c84eed9 docs: consolidate validation rules for Host and X-Forwarded-Host headers into a single point.
(cherry picked from commit c57ba8c6e6)
2026-02-24 17:24:34 +00:00
Matthieu Riegler 103a44f690 docs: improve responsiveness of the homepage
This fixes some layout issues when on mobile.

(cherry picked from commit 9e0acc5930)
2026-02-24 17:23:43 +00:00
Shuaib Hasan Akib de9092eb23 docs: inline documentation and remove unused references
Replaces referenced doc blocks with inline documentation,
cleans up unused referenced code, and fixes broken list formatting

(cherry picked from commit 8739a22d28)
2026-02-24 17:22:54 +00:00
Jens Kuehlers 0b0b34565a docs: minor roadmap update (Ecosystem/vitest)
(cherry picked from commit dea858979e)
2026-02-24 17:22:13 +00:00
Angular Robot b17a7e062f build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-24 09:21:23 -08:00
Shuaib Hasan Akib 7c976c3453 docs: remove inconsistent padding in update page
Removes extra padding applied to the update page so its layout
matches the rest of the documentation where no padding exists
between the title and content.

(cherry picked from commit 15b51d0777)
2026-02-24 17:20:55 +00:00
SkyZeroZx eb6bce0ff5 docs: Add image loader config with height parameter
(cherry picked from commit c7dc7054dc)
2026-02-23 23:30:35 +00:00
Suguru Inatomi 30e486a41c fix(docs-infra): use shared heading ID generation logic
This commit extracts the heading ID generation logic into a shared utility
and updates both the route generation script and the markdown pipeline to use it.

This ensures consistency between the generated routes and the rendered
documentation, and fixes an issue where custom heading IDs (`{#id}`)
were ignored during route generation.

Fixes #67200

(cherry picked from commit bedfcb5644)
2026-02-23 23:16:55 +00:00
Matthieu Riegler a73d5435d8 docs: Add a compiler entry to the roadmap
(cherry picked from commit fbabd092f3)
2026-02-23 23:11:30 +00:00
marktechson b9d3fe3b44 docs: update and reformat the roadmap
(cherry picked from commit 53c1a1cee7)
2026-02-23 21:28:43 +00:00
Angular Robot c9ecf9e40b build: update cross-repo angular dependencies to v21.2.0-rc.1
See associated pull request for more information.
2026-02-23 13:17:58 -08:00
Shuaib Hasan Akib 2f213de593 refactor(core): remove outdated TODO comments
Cleans up TODO comments that are no longer planned

Fixes #67191

(cherry picked from commit 5ac1c025f9)
2026-02-23 18:19:57 +00:00
Matthieu Riegler ec32591dd7 docs: mention browser mode debugging
(cherry picked from commit a9ac7f87d7)
2026-02-23 18:19:27 +00:00
Miles Malerba 02b7f5e4f7 ci: remove mmalerba from reviewers
remove mmalerba from reviewers

(cherry picked from commit 0af9e3e9ee)
2026-02-23 18:19:02 +00:00
Angular Robot 31bf694599 build: update pnpm to v10.30.1
See associated pull request for more information.
2026-02-23 09:12:54 -08:00
Miles Malerba bdfb60f3e3 fix(forms): use consistent error format returned from parse
Aligns the errors returned from the `parse` function in
`transformedValue` to use the same convention as the rest of signal
forms (a property called `error` that can contain a single error or list
of errors)

(cherry picked from commit 23fd8fa586)
2026-02-23 17:11:55 +00:00
SkyZeroZx e99b92a1f0 docs: add Route Loading Strategies section and update navigation links
(cherry picked from commit 163dd8ee38)
2026-02-23 17:11:15 +00:00
Alan Agius 5c24de5ee8 docs: move server-side security and host validation documentation from ssr.md to security.md.
(cherry picked from commit 099b4a8bbb)
2026-02-23 17:08:56 +00:00
Alan Agius fad5def327 feat(docs-infra): add hideDollar option to hide the dollar sign prefix in shell code blocks.
The dollar sign is not always required.

(cherry picked from commit efcf76ea61)
2026-02-23 17:08:56 +00:00
Alan Agius de2eab6820 docs: convert SSR guide's important note list to HTML <ul> for proper rendering.
(cherry picked from commit 75fd6c0ff2)
2026-02-23 17:08:56 +00:00
Alan Agius ea1aeb3d45 docs: add documentation for SSR security and host validation, including details on allowedHosts configuration
This document adds more information about `allowedHost` option

(cherry picked from commit 944aefe854)
2026-02-23 17:08:55 +00:00
Jaime Burgos 35f0663ce8 refactor(core): guards stringify calls with ngDevMode
The `stringify` function is only needed for debugging purposes and
should not be called in production mode.

(cherry picked from commit c89d94bd58)
2026-02-20 21:24:31 +00:00
SkyZeroZx 2eeeabb760 fix(common): fix LCP image detection with duplicate URLs
Addresses an issue where the LCP image observer incorrectly identified LCP elements when the same image URL was used multiple times on a page

Fixes #53278

(cherry picked from commit 38749698d0)
2026-02-20 21:23:27 +00:00
Jessica Janiuk 87372893ea ci: update ng-dev config and pullapprove
This updates the pullapprove to remove the auto labeling of requires: TGP and instead moves it to the ng-dev config for pr updates.

(cherry picked from commit d7ddebca90)
2026-02-20 19:02:14 +00:00
cexbrayat 631f60d1f9 fix(forms): preserve parse errors when parse returns value
Fixes #67170 by keeping the errors even a value is returned from the parse function.

(cherry picked from commit fe25c57a5c)
2026-02-20 18:28:57 +00:00
Ben Hong 390efd51e7 docs: add new debugging and troubleshooting di guide
(cherry picked from commit 13e019a1bb)
2026-02-20 18:01:16 +00:00
splincode c2cedd1954 refactor(compiler-cli): improve diagnostic with help link
Add help link to extended template diagnostic messages to provide
users with additional guidance and documentation resources. This
enhancement improves developer experience by making it easier to
understand and resolve complex template issues through direct
access to relevant Angular documentation with detailed examples
and explanations for each diagnostic type.

(cherry picked from commit 66b472e2bc)
2026-02-20 17:40:21 +00:00
Matthieu Riegler 3c4deaa52b refactor(common): log a warning when a JsonPipe receives a signal
The JsonPipe does not unwrap signals and `JSON.stringify` will return `undefined` for signals.
To avoid confusion, we log a warning when a signal is passed to the pipe.

(cherry picked from commit 0d652ba4da)
2026-02-20 17:17:05 +00:00
Matthieu Riegler b5eea233df docs: improve signal demo example
(cherry picked from commit b7cf37d3e1)
2026-02-20 17:15:37 +00:00
SkyZeroZx c0cb6040f8 fix(compiler-cli): detect uninvoked functions in defer trigger expressions
Wrap `@defer` trigger expressions (`when`, `prefetch when`, `hydrate when`)
in a conditional context within the TCB to enable TypeScript's TS2774
diagnostic for detecting functions used without invocation.

Previously, signals and functions passed to `when` triggers without
parentheses would silently evaluate to truthy, causing unexpected behavior.
Now the compiler reports an error when a function is used as a condition
without being called.

(cherry picked from commit f90e5565e0)
2026-02-20 16:57:08 +00:00
Bas ten Feld fb901f7eda docs(docs-infra): fix typo 'requiredSync' instead of 'requireSync'
(cherry picked from commit 57edfaf435)
2026-02-20 16:53:24 +00:00
Matthieu Riegler 17da2c392e docs(docs-infra): remove toString from the API docs
(cherry picked from commit fc8140cff4)
2026-02-20 16:52:01 +00:00
Angular Robot 6cf0100fe4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 18:12:11 -08:00
kbrilla d2137928e8 perf(language-service): use lightweight project warmup for Angular analysis
avoid per-file semantic diagnostics work when warming up a newly loaded project.
add ensureProjectAnalyzed() to the language-service API and use it from the server startup path.
implement warmup through public compiler API access with existing perf tracing, and add legacy test coverage for the new warmup flow.

(cherry picked from commit 39f62fa408)
2026-02-20 02:11:06 +00:00
Matthieu Riegler 1d4783c01c refactor(language-service): split tests to reduce risk of timeouts
Because we've had to many timeouts recently

(cherry picked from commit 550b3ba01b)
2026-02-20 02:10:34 +00:00
SkyZeroZx 9ee99c7cc0 docs: update NgTemplateOutlet documentation with injector
(cherry picked from commit 67b22d509a)
2026-02-20 00:06:29 +00:00
Angular Robot 5b8a403220 build: update rules_browsers digest to ceb5275
See associated pull request for more information.

Closes #67141 as a pr takeover
2026-02-19 16:01:02 -08:00
SkyZeroZx 9c8f2dab7d docs: add section on reactive context and async operations
(cherry picked from commit f68078b3e3)
2026-02-19 23:59:59 +00:00
SkyZeroZx 9f1a78ca74 docs(docs-infra): preserve content before docs-card-container in adev
The tokenizer regex pattern `[^<]*` was consuming all non-`<` content
before custom HTML tags, causing lost content.

Changed to `\s*` which only allows leading whitespace, letting marked
properly tokenize preceding content.

(cherry picked from commit bc473cf60f)
2026-02-19 23:48:49 +00:00
Angular Robot d45440eda4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 13:31:08 -08:00
Matthieu Riegler eb7c593fda ci: add zone.js to minimumReleaseAgeExclude
This is a package we control the release of.

(cherry picked from commit d501506aa6)
2026-02-19 20:41:24 +00:00
Walter Breakell 48802fd7ed docs: fix grammar, syntax, and broken link in elements guide
(cherry picked from commit 7d21996b1e)
2026-02-19 20:39:04 +00:00
Joey Perrott 5cea3576cf docs: update changelog to note no changes in 21.1.5 release
(cherry picked from commit e8cc910965)
2026-02-19 19:23:48 +00:00
Angular Robot 913bb6ad14 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 11:22:42 -08:00
Angular Robot 79f1cd462e docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-02-19 09:03:46 -08:00
SkyZeroZx 4ea3cafdc8 docs(docs-infra): fixed missing gray color palette definitions for light and dark modes
Adds the missing gray color palette definitions for both light and dark modes

(cherry picked from commit 1771d54fb7)
2026-02-19 16:55:02 +00:00
Angular Robot 94b9a3ef70 build: update all github actions
See associated pull request for more information.
2026-02-19 08:52:00 -08:00
Angular Robot c5afb88d9a build: update cross-repo angular dependencies to v21.2.0-rc.0
See associated pull request for more information.
2026-02-19 08:51:02 -08:00
Andrew Scott f58f9c892e release: cut the zone.js-0.16.1 release
(cherry picked from commit ac8b5ff938)
2026-02-18 16:26:41 -08:00
Andrew Scott 7f33cbeb6c release: bump VSCode extension version to 21.2.0 (#67134) 2026-02-18 15:48:34 -08:00
Andrew Scott dd630ef955 build: update version target to prep for 21.2.0 release for vscode extension (#67132)
build: update version target to prep for 21.2.0 release for vscode extension
2026-02-18 15:14:45 -08:00
Matthew Beck 13fd2b1aa3 release: cut the v21.2.0-rc.0 release 2026-02-18 14:38:30 -08:00
663 changed files with 47765 additions and 27995 deletions
-1
View File
@@ -1 +0,0 @@
../.gemini/skills
+133
View File
@@ -0,0 +1,133 @@
---
name: PR Review
description: Guidelines and tools for reviewing pull requests in the Angular repository.
---
# PR Review Guidelines
When reviewing a pull request for the `angular` repository, follow these essential guidelines to ensure high-quality contributions:
1. **Context & Ecosystem**:
- Keep in mind that this is the core Angular framework. Changes here can impact millions of developers.
- Be mindful of backwards compatibility. Breaking changes require strict approval processes and deprecation periods.
2. **Key Focus Areas**:
- **Comprehensive Reviews**: You **MUST always** perform a deep, comprehensive review of the _entire_ pull request. If the user asks you to look into a specific issue, file, or area of concern, you must investigate that specific area _in addition to_ reviewing the rest of the PR's substantive changes. Do not terminate your review after addressing only the user's focal point.
- **Package-Specific Guidelines**: Check if there are specific guidelines for the package being modified in the `reference/` directory (e.g., `reference/router.md`). Always prioritize these rules for their respective packages.
- **Commit Messages**: Evaluate the quality of commit messages. They should explain the _why_ behind the change, not just the _what_. Someone should be able to look at the commit history years from now and clearly understand the context and reasoning for the change.
- **Code Cleanliness**: Ensure the code is readable, maintainable, and follows Angular's project standards.
- **Performance**: Look out for code that might negatively impact runtime performance or bundle size, particularly in hot paths like change detection or rendering.
- **Testing**: Ensure all new logic has comprehensive tests, including edge cases. **Do NOT run tests locally** as part of your review process. CI handles this automatically, and running tests locally is redundant and inefficient.
- **API Design**: Ensure new public APIs are well-designed, consistent with existing APIs, and properly documented.
- **Payload Size**: Pay attention to the impact of changes on the final client payload size.
3. **Execution Workflow**:
Determine the appropriate review method. If the user explicitly asks for a `local` or `remote` review in their request, that takes precedence. Otherwise, use the GitHub MCP or available scripts to determine if the review should be `local` or `remote`.
**Common Review Practices (Applies to both Local and Remote)**
- **Preparation & Checklist**:
- First, create a task list (e.g., in `task.md`) that you can easily reference containing **all** the review requirements from the "Key Focus Areas" section (Commit Messages, Performance, Testing, etc.), along with any specific review notes or requests from the user.
- Before doing an in-depth review, expand this list into more detailed items of what you plan to explore and verify in the PR.
- As you conduct the review, check off items in this list, adding your assessment or findings underneath each item.
- At the end of your review, refer back to the checklist to ensure every single requirement was completely verified.
- **Fetch PR Metadata Safely**: When you need to read the PR description or context, do NOT use `gh pr view <PR_NUMBER>` by itself, as its default GraphQL query may fail due to lack of `read:org` and `read:discussion` token scopes. Instead, use `read_url_content` on the PR URL or use `gh pr view <PR_NUMBER> --json title,body,state,author`.
- **Check Existing Comments First**: Before formulating feedback, use the GitHub MCP or available scripts to fetch existing comments on the PR. Review this feedback to avoid duplicate comments, and incorporate its insights into your own review process.
- **Constructive Feedback**: Provide clear, actionable, and polite feedback. Explain the _why_ behind your suggestions or edits. Do **NOT** leave inline comments purely to praise, agree with, or acknowledge a correct implementation detail, as this clutters the review. If you want to praise the PR, do so in the single general PR comment.
**A. Local Code Review (If the PR is owned by the author requesting the review)**
- **Checkout**: Check out the PR branch locally (if it doesn't already exist, fetch it).
- **Review & Edit**: Execute the review directly on the code. Instead of adding inline PR comments for suggestions, format the codebase or apply the edits directly to the files.
- **Feedback**: Summarize the review findings and the concrete changes you made in a message to the user, referencing the completed items from your checklist.
- **Do NOT Commit or Push**: Leave the changes uncommitted in the working directory so the user can easily review the pending edits locally. Let the user know the changes are ready for their review, but do not ask for approval to push.
- **Resolve Comments**: Once the user confirms the changes are good and should be committed/pushed, respond to the existing comments as 'resolved' using the GitHub MCP or available scripts.
**B. Remote Code Review (For all other PRs)**
- **Batching Comments (MCP Server - Preferred)**: If you have the GitHub MCP Server configured, you **MUST** follow this workflow to avoid spamming the author with multiple notifications:
1. Create a pending review using `mcp_github-mcp-server_pull_request_review_write` (method `create`).
2. Add your inline comments to the pending review using `mcp_github-mcp-server_add_comment_to_pending_review`.
3. Submit the review using `mcp_github-mcp-server_pull_request_review_write` (method `submit_pending`).
- **Batching Comments (Scripts - Fallback)**: If you do **NOT** have access to the GitHub MCP Server (e.g., specific MCP tools are missing from your context), fallback to using the provided scripts. Use `post_inline_comment.sh` to stage your comments locally. Once all comments are staged, you **MUST** call `submit_pr_review.sh` to publish them as a single batched review (and send a single notification). Try to keep comments minimal or use a general comment if you have many suggestions.
- **Use Suggested Changes**: Whenever appropriate (e.g., for simple code fixes, refactoring suggestions, or typo corrections), prefer using GitHub's **Suggested Changes** syntax (`suggestion ... `) in your inline comments. This allows the author to apply your suggested code improvements with a single click in the GitHub UI.
- **Review Type**: Never mark an external PR review as an "approval" unless explicitly instructed by a repo maintainer. Always use "Request Changes" or "Comment". Note that some tools might only support commenting.
- **Require User Approval Before Posting**: Prepare your review comments and present them to the user, alongside a summary of your completed checklist. Do NOT post comments to the PR without explicitly asking the user for permission first. Only post the review after the user approves.
- **Prefix Agent Comments**: To make it clear when comments are generated and posted by an AI agent rather than a human user, **always** prefix your review comments with `AGENT: `.
## Available Tools
The following tools are available for remote interactions. We prefer using standard **GitHub MCP Server** tools when available. If you do not have the MCP server set up, you **MUST** fallback to using the custom bash scripts.
### GitHub MCP Tools (Preferred)
- `mcp_github-mcp-server_pull_request_review_write`
- `mcp_github-mcp-server_add_comment_to_pending_review`
### Custom Bash Scripts (Fallback)
The following scripts are provided as fallbacks if the MCP server is not available. Note that they rely on the `gh` CLI being correctly installed and authenticated in the local environment.
### `determine_review_type.sh`
Determines whether to use the Local or Remote review workflow by checking if the currently authenticated GitHub user via the `gh` CLI matches the author of the pull request.
**Usage:**
```bash
.agent/skills/pr_review/scripts/determine_review_type.sh <PR_NUMBER>
```
### `get_pr_comments.sh`
Fetches all existing inline comments on a PR using the GitHub API. This is crucial for reviewing other contributors' feedback and avoiding duplicate comments. It outputs JSON containing the `id`, `path`, `line`, `body`, and `user` for each comment.
**Usage:**
```bash
.agent/skills/pr_review/scripts/get_pr_comments.sh <PR_NUMBER>
```
### `reply_pr_comment.sh`
Replies to an existing PR comment thread. This is useful for marking comments as resolved after addressing them in a local code review. Note that the `COMMENT_ID` must be the ID of the top-level comment in the thread.
**Usage:**
```bash
.agent/skills/pr_review/scripts/reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>
```
### `post_inline_comment.sh`
The GitHub CLI `gh pr review` command does not natively support adding inline comments to specific lines of code via its standard flags. This script wraps the GitHub API to stage comments locally. They will not be published until you call `submit_pr_review.sh`.
**Usage:**
```bash
.agent/skills/pr_review/scripts/post_inline_comment.sh <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>
```
**Example:**
```bash
.agent/skills/pr_review/scripts/post_inline_comment.sh 12345 "packages/core/src/render3/instructions/element.ts" 42 "AGENT: Consider the performance implications here."
```
### `submit_pr_review.sh`
Submits all locally staged inline comments as a single batched review via the GitHub Pull Request Reviews API.
**Usage:**
```bash
.agent/skills/pr_review/scripts/submit_pr_review.sh <PR_NUMBER> <EVENT_TYPE> [BODY]
```
**Options:**
- `EVENT_TYPE`: Must be `COMMENT`, `APPROVE`, or `REQUEST_CHANGES`. Never use `APPROVE` for external PRs.
- `BODY`: (Optional) A general summary comment for the review.
**Example:**
```bash
.agent/skills/pr_review/scripts/submit_pr_review.sh 12345 COMMENT "AGENT: I have left a few inline suggestions for your consideration."
```
@@ -0,0 +1,7 @@
# Router PR Review Guidelines
When reviewing pull requests that modify the Angular Router (`packages/router`), pay special attention to the following:
- **Timing Sensitivity**: The router is extremely sensitive to timing changes. Any changes that alter the asynchronous timing of navigations, resolvers, or guards are almost always breaking changes and must be scrutinized carefully.
- **Testing Practices**: Tests should usually use the `RouterTestingHarness`. Many existing tests are older and do not use this harness. Do not blindly follow the shape of existing tests when writing or reviewing new ones; encourage the use of modern testing utilities.
- **Feature Justification**: Changes to router core code should be well-justified. Consider whether the change is proven to be a core developer ask, such as resolving a highly upvoted GitHub issue or addressing a critical bug.
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail
# determine_review_type.sh <PR_NUMBER>
# Determines if the PR should be reviewed locally or remotely based on author.
if [ -z "$1" ]; then
echo "Usage: determine_review_type.sh <PR_NUMBER>"
exit 1
fi
PR_NUMBER=$1
# Get current authenticated user
CURRENT_USER=$(gh api user -q .login 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Error: Could not determine current GitHub user. Are you logged in to gh?"
exit 1
fi
# Get PR author
PR_AUTHOR=$(gh pr view "$PR_NUMBER" --json author -q .author.login 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Error: Could not retrieve PR information for $PR_NUMBER."
exit 1
fi
if [ "$CURRENT_USER" = "$PR_AUTHOR" ]; then
echo "local"
else
echo "remote"
fi
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
# get_pr_comments.sh
# Fetches existing inline comments on a PR to avoid duplicate reviews.
# Usage: ./get_pr_comments.sh <PR_NUMBER>
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <PR_NUMBER>"
exit 1
fi
PR_NUMBER="$1"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Fetch comments
gh api \
--paginate \
-H "Accept: application/vnd.github+json" \
"/repos/${REPO}/pulls/${PR_NUMBER}/comments" \
--jq '.[] | {id: .id, path: .path, line: .line, body: .body, user: .user.login}'
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
# post_inline_comment.sh
# Adds an inline comment to a specific line in a PR via the GitHub API.
# Usage: ./post_inline_comment.sh <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>
if [ "$#" -lt 4 ]; then
echo "Usage: $0 <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>"
exit 1
fi
PR_NUMBER="$1"
FILE_PATH="$2"
LINE="$3"
BODY="$4"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
echo "Staging inline comment for PR #${PR_NUMBER} on ${FILE_PATH}:${LINE}..."
COMMENT_FILE="/tmp/angular_pr_${PR_NUMBER}_comments.json"
if [ ! -f "$COMMENT_FILE" ]; then
echo "[]" > "$COMMENT_FILE"
fi
# Append the new comment to the JSON array
jq --arg path "${FILE_PATH}" --argjson line "${LINE}" --arg body "${BODY}" \
'. += [{"path": $path, "line": $line, "body": $body}]' "$COMMENT_FILE" > "${COMMENT_FILE}.tmp" && mv "${COMMENT_FILE}.tmp" "$COMMENT_FILE"
echo "Comment successfully staged locally. Remember to call submit_pr_review.sh when finished to publish all comments as a single review!"
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
# reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>
# Replies to an existing PR comment thread. Note: COMMENT_ID must be the ID of the top-level comment in the thread you are replying to.
if [ "$#" -lt 3 ]; then
echo "Usage: reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>"
exit 1
fi
PR_NUMBER="$1"
COMMENT_ID="$2"
BODY="$3"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Reply to the thread using the provided comment ID
gh api \
--silent \
--method POST \
-H "Accept: application/vnd.github+json" \
"/repos/${REPO}/pulls/${PR_NUMBER}/comments/${COMMENT_ID}/replies" \
-f body="$BODY"
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail
# submit_pr_review.sh
# Submits a batched PR review using comments previously staged by post_inline_comment.sh
# Usage: ./submit_pr_review.sh <PR_NUMBER> <EVENT_TYPE> [BODY]
# EVENT_TYPE must be COMMENT, APPROVE, or REQUEST_CHANGES
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <PR_NUMBER> <EVENT_TYPE> [BODY]"
echo "EVENT_TYPE must be COMMENT, APPROVE, or REQUEST_CHANGES"
exit 1
fi
PR_NUMBER="$1"
EVENT="$2"
BODY="${3:-}"
COMMENT_FILE="/tmp/angular_pr_${PR_NUMBER}_comments.json"
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Check if there are staged comments
COMMENTS="[]"
if [ -f "$COMMENT_FILE" ]; then
COMMENTS=$(cat "$COMMENT_FILE")
fi
echo "Submitting review for PR #${PR_NUMBER}..."
# Create the payload
PAYLOAD_FILE="/tmp/angular_pr_${PR_NUMBER}_payload.json"
jq -n --arg event "$EVENT" --arg body "$BODY" --argjson comments "$COMMENTS" \
'{event: $event, body: $body, comments: $comments}' > "$PAYLOAD_FILE"
# Post the review using the GitHub Pull Request Reviews API
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
--input "$PAYLOAD_FILE"
echo "Review submitted successfully!"
rm -f "$COMMENT_FILE"
rm -f "$PAYLOAD_FILE"
+1 -1
View File
@@ -1 +1 @@
8.5.1
8.6.0
+304 -34
View File
@@ -10271,7 +10271,7 @@ function isKeyOperator(operator) {
function getValues(context3, operator, key, modifier) {
var value = context3[key], result = [];
if (isDefined(value) && value !== "") {
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
value = value.toString();
if (modifier && modifier !== "*") {
value = value.substring(0, parseInt(modifier, 10));
@@ -10452,6 +10452,108 @@ var endpoint = withDefaults(null, DEFAULTS);
//
var import_fast_content_type_parse = __toESM(require_fast_content_type_parse());
//
var intRegex = /^-?\d+$/;
var noiseValue = /^-?\d+n+$/;
var originalStringify = JSON.stringify;
var originalParse = JSON.parse;
var customFormat = /^-?\d+n$/;
var bigIntsStringify = /([\[:])?"(-?\d+)n"($|([\\n]|\s)*(\s|[\\n])*[,\}\]])/g;
var noiseStringify = /([\[:])?("-?\d+n+)n("$|"([\\n]|\s)*(\s|[\\n])*[,\}\]])/g;
var JSONStringify = (value, replacer, space) => {
if ("rawJSON" in JSON) {
return originalStringify(
value,
(key, value2) => {
if (typeof value2 === "bigint")
return JSON.rawJSON(value2.toString());
if (typeof replacer === "function")
return replacer(key, value2);
if (Array.isArray(replacer) && replacer.includes(key))
return value2;
return value2;
},
space
);
}
if (!value)
return originalStringify(value, replacer, space);
const convertedToCustomJSON = originalStringify(
value,
(key, value2) => {
const isNoise = typeof value2 === "string" && Boolean(value2.match(noiseValue));
if (isNoise)
return value2.toString() + "n";
if (typeof value2 === "bigint")
return value2.toString() + "n";
if (typeof replacer === "function")
return replacer(key, value2);
if (Array.isArray(replacer) && replacer.includes(key))
return value2;
return value2;
},
space
);
const processedJSON = convertedToCustomJSON.replace(
bigIntsStringify,
"$1$2$3"
);
const denoisedJSON = processedJSON.replace(noiseStringify, "$1$2$3");
return denoisedJSON;
};
var isContextSourceSupported = () => JSON.parse("1", (_, __, context3) => !!context3 && context3.source === "1");
var convertMarkedBigIntsReviver = (key, value, context3, userReviver) => {
const isCustomFormatBigInt = typeof value === "string" && value.match(customFormat);
if (isCustomFormatBigInt)
return BigInt(value.slice(0, -1));
const isNoiseValue = typeof value === "string" && value.match(noiseValue);
if (isNoiseValue)
return value.slice(0, -1);
if (typeof userReviver !== "function")
return value;
return userReviver(key, value, context3);
};
var JSONParseV2 = (text, reviver) => {
return JSON.parse(text, (key, value, context3) => {
const isBigNumber = typeof value === "number" && (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER);
const isInt = context3 && intRegex.test(context3.source);
const isBigInt = isBigNumber && isInt;
if (isBigInt)
return BigInt(context3.source);
if (typeof reviver !== "function")
return value;
return reviver(key, value, context3);
});
};
var MAX_INT = Number.MAX_SAFE_INTEGER.toString();
var MAX_DIGITS = MAX_INT.length;
var stringsOrLargeNumbers = /"(?:\\.|[^"])*"|-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?/g;
var noiseValueWithQuotes = /^"-?\d+n+"$/;
var JSONParse = (text, reviver) => {
if (!text)
return originalParse(text, reviver);
if (isContextSourceSupported())
return JSONParseV2(text, reviver);
const serializedData = text.replace(
stringsOrLargeNumbers,
(text2, digits, fractional, exponential) => {
const isString = text2[0] === '"';
const isNoise = isString && Boolean(text2.match(noiseValueWithQuotes));
if (isNoise)
return text2.substring(0, text2.length - 1) + 'n"';
const isFractionalOrExponential = fractional || exponential;
const isLessThanMaxSafeInt = digits && (digits.length < MAX_DIGITS || digits.length === MAX_DIGITS && digits <= MAX_INT);
if (isString || isFractionalOrExponential || isLessThanMaxSafeInt)
return text2;
return '"' + text2 + 'n"';
}
);
return originalParse(
serializedData,
(key, value, context3) => convertMarkedBigIntsReviver(key, value, context3, reviver)
);
};
//
var RequestError = class extends Error {
name;
@@ -10492,7 +10594,7 @@ var RequestError = class extends Error {
};
//
var VERSION2 = "10.0.7";
var VERSION2 = "10.0.8";
var defaults_default = {
headers: {
"user-agent": `octokit-request.js/${VERSION2} ${getUserAgent()}`
@@ -10519,7 +10621,7 @@ async function fetchWrapper(requestOptions) {
}
const log = requestOptions.request?.log || console;
const parseSuccessResponseBody = requestOptions.request?.parseSuccessResponseBody !== false;
const body = isPlainObject2(requestOptions.body) || Array.isArray(requestOptions.body) ? JSON.stringify(requestOptions.body) : requestOptions.body;
const body = isPlainObject2(requestOptions.body) || Array.isArray(requestOptions.body) ? JSONStringify(requestOptions.body) : requestOptions.body;
const requestHeaders = Object.fromEntries(
Object.entries(requestOptions.headers).map(([name, value]) => [
name,
@@ -10618,7 +10720,7 @@ async function getResponseData(response) {
let text = "";
try {
text = await response.text();
return JSON.parse(text);
return JSONParse(text);
} catch (err) {
return text;
}
@@ -14135,17 +14237,81 @@ function stripAnsi(string) {
if (typeof string !== "string") {
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
}
if (!string.includes("\x1B") && !string.includes("\x9B")) {
return string;
}
return string.replace(regex, "");
}
function isAmbiguous(x) {
return x === 161 || x === 164 || x === 167 || x === 168 || x === 170 || x === 173 || x === 174 || x >= 176 && x <= 180 || x >= 182 && x <= 186 || x >= 188 && x <= 191 || x === 198 || x === 208 || x === 215 || x === 216 || x >= 222 && x <= 225 || x === 230 || x >= 232 && x <= 234 || x === 236 || x === 237 || x === 240 || x === 242 || x === 243 || x >= 247 && x <= 250 || x === 252 || x === 254 || x === 257 || x === 273 || x === 275 || x === 283 || x === 294 || x === 295 || x === 299 || x >= 305 && x <= 307 || x === 312 || x >= 319 && x <= 322 || x === 324 || x >= 328 && x <= 331 || x === 333 || x === 338 || x === 339 || x === 358 || x === 359 || x === 363 || x === 462 || x === 464 || x === 466 || x === 468 || x === 470 || x === 472 || x === 474 || x === 476 || x === 593 || x === 609 || x === 708 || x === 711 || x >= 713 && x <= 715 || x === 717 || x === 720 || x >= 728 && x <= 731 || x === 733 || x === 735 || x >= 768 && x <= 879 || x >= 913 && x <= 929 || x >= 931 && x <= 937 || x >= 945 && x <= 961 || x >= 963 && x <= 969 || x === 1025 || x >= 1040 && x <= 1103 || x === 1105 || x === 8208 || x >= 8211 && x <= 8214 || x === 8216 || x === 8217 || x === 8220 || x === 8221 || x >= 8224 && x <= 8226 || x >= 8228 && x <= 8231 || x === 8240 || x === 8242 || x === 8243 || x === 8245 || x === 8251 || x === 8254 || x === 8308 || x === 8319 || x >= 8321 && x <= 8324 || x === 8364 || x === 8451 || x === 8453 || x === 8457 || x === 8467 || x === 8470 || x === 8481 || x === 8482 || x === 8486 || x === 8491 || x === 8531 || x === 8532 || x >= 8539 && x <= 8542 || x >= 8544 && x <= 8555 || x >= 8560 && x <= 8569 || x === 8585 || x >= 8592 && x <= 8601 || x === 8632 || x === 8633 || x === 8658 || x === 8660 || x === 8679 || x === 8704 || x === 8706 || x === 8707 || x === 8711 || x === 8712 || x === 8715 || x === 8719 || x === 8721 || x === 8725 || x === 8730 || x >= 8733 && x <= 8736 || x === 8739 || x === 8741 || x >= 8743 && x <= 8748 || x === 8750 || x >= 8756 && x <= 8759 || x === 8764 || x === 8765 || x === 8776 || x === 8780 || x === 8786 || x === 8800 || x === 8801 || x >= 8804 && x <= 8807 || x === 8810 || x === 8811 || x === 8814 || x === 8815 || x === 8834 || x === 8835 || x === 8838 || x === 8839 || x === 8853 || x === 8857 || x === 8869 || x === 8895 || x === 8978 || x >= 9312 && x <= 9449 || x >= 9451 && x <= 9547 || x >= 9552 && x <= 9587 || x >= 9600 && x <= 9615 || x >= 9618 && x <= 9621 || x === 9632 || x === 9633 || x >= 9635 && x <= 9641 || x === 9650 || x === 9651 || x === 9654 || x === 9655 || x === 9660 || x === 9661 || x === 9664 || x === 9665 || x >= 9670 && x <= 9672 || x === 9675 || x >= 9678 && x <= 9681 || x >= 9698 && x <= 9701 || x === 9711 || x === 9733 || x === 9734 || x === 9737 || x === 9742 || x === 9743 || x === 9756 || x === 9758 || x === 9792 || x === 9794 || x === 9824 || x === 9825 || x >= 9827 && x <= 9829 || x >= 9831 && x <= 9834 || x === 9836 || x === 9837 || x === 9839 || x === 9886 || x === 9887 || x === 9919 || x >= 9926 && x <= 9933 || x >= 9935 && x <= 9939 || x >= 9941 && x <= 9953 || x === 9955 || x === 9960 || x === 9961 || x >= 9963 && x <= 9969 || x === 9972 || x >= 9974 && x <= 9977 || x === 9979 || x === 9980 || x === 9982 || x === 9983 || x === 10045 || x >= 10102 && x <= 10111 || x >= 11094 && x <= 11097 || x >= 12872 && x <= 12879 || x >= 57344 && x <= 63743 || x >= 65024 && x <= 65039 || x === 65533 || x >= 127232 && x <= 127242 || x >= 127248 && x <= 127277 || x >= 127280 && x <= 127337 || x >= 127344 && x <= 127373 || x === 127375 || x === 127376 || x >= 127387 && x <= 127404 || x >= 917760 && x <= 917999 || x >= 983040 && x <= 1048573 || x >= 1048576 && x <= 1114109;
}
function isFullWidth(x) {
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
}
function isWide(x) {
return x >= 4352 && x <= 4447 || x === 8986 || x === 8987 || x === 9001 || x === 9002 || x >= 9193 && x <= 9196 || x === 9200 || x === 9203 || x === 9725 || x === 9726 || x === 9748 || x === 9749 || x >= 9776 && x <= 9783 || x >= 9800 && x <= 9811 || x === 9855 || x >= 9866 && x <= 9871 || x === 9875 || x === 9889 || x === 9898 || x === 9899 || x === 9917 || x === 9918 || x === 9924 || x === 9925 || x === 9934 || x === 9940 || x === 9962 || x === 9970 || x === 9971 || x === 9973 || x === 9978 || x === 9981 || x === 9989 || x === 9994 || x === 9995 || x === 10024 || x === 10060 || x === 10062 || x >= 10067 && x <= 10069 || x === 10071 || x >= 10133 && x <= 10135 || x === 10160 || x === 10175 || x === 11035 || x === 11036 || x === 11088 || x === 11093 || x >= 11904 && x <= 11929 || x >= 11931 && x <= 12019 || x >= 12032 && x <= 12245 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12353 && x <= 12438 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12773 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 42124 || x >= 42128 && x <= 42182 || x >= 43360 && x <= 43388 || x >= 44032 && x <= 55203 || x >= 63744 && x <= 64255 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 94176 && x <= 94180 || x >= 94192 && x <= 94198 || x >= 94208 && x <= 101589 || x >= 101631 && x <= 101662 || x >= 101760 && x <= 101874 || x >= 110576 && x <= 110579 || x >= 110581 && x <= 110587 || x === 110589 || x === 110590 || x >= 110592 && x <= 110882 || x === 110898 || x >= 110928 && x <= 110930 || x === 110933 || x >= 110948 && x <= 110951 || x >= 110960 && x <= 111355 || x >= 119552 && x <= 119638 || x >= 119648 && x <= 119670 || x === 126980 || x === 127183 || x === 127374 || x >= 127377 && x <= 127386 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x === 127568 || x === 127569 || x >= 127584 && x <= 127589 || x >= 127744 && x <= 127776 || x >= 127789 && x <= 127797 || x >= 127799 && x <= 127868 || x >= 127870 && x <= 127891 || x >= 127904 && x <= 127946 || x >= 127951 && x <= 127955 || x >= 127968 && x <= 127984 || x === 127988 || x >= 127992 && x <= 128062 || x === 128064 || x >= 128066 && x <= 128252 || x >= 128255 && x <= 128317 || x >= 128331 && x <= 128334 || x >= 128336 && x <= 128359 || x === 128378 || x === 128405 || x === 128406 || x === 128420 || x >= 128507 && x <= 128591 || x >= 128640 && x <= 128709 || x === 128716 || x >= 128720 && x <= 128722 || x >= 128725 && x <= 128728 || x >= 128732 && x <= 128735 || x === 128747 || x === 128748 || x >= 128756 && x <= 128764 || x >= 128992 && x <= 129003 || x === 129008 || x >= 129292 && x <= 129338 || x >= 129340 && x <= 129349 || x >= 129351 && x <= 129535 || x >= 129648 && x <= 129660 || x >= 129664 && x <= 129674 || x >= 129678 && x <= 129734 || x === 129736 || x >= 129741 && x <= 129756 || x >= 129759 && x <= 129770 || x >= 129775 && x <= 129784 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
var ambiguousRanges = [161, 161, 164, 164, 167, 168, 170, 170, 173, 174, 176, 180, 182, 186, 188, 191, 198, 198, 208, 208, 215, 216, 222, 225, 230, 230, 232, 234, 236, 237, 240, 240, 242, 243, 247, 250, 252, 252, 254, 254, 257, 257, 273, 273, 275, 275, 283, 283, 294, 295, 299, 299, 305, 307, 312, 312, 319, 322, 324, 324, 328, 331, 333, 333, 338, 339, 358, 359, 363, 363, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 476, 593, 593, 609, 609, 708, 708, 711, 711, 713, 715, 717, 717, 720, 720, 728, 731, 733, 733, 735, 735, 768, 879, 913, 929, 931, 937, 945, 961, 963, 969, 1025, 1025, 1040, 1103, 1105, 1105, 8208, 8208, 8211, 8214, 8216, 8217, 8220, 8221, 8224, 8226, 8228, 8231, 8240, 8240, 8242, 8243, 8245, 8245, 8251, 8251, 8254, 8254, 8308, 8308, 8319, 8319, 8321, 8324, 8364, 8364, 8451, 8451, 8453, 8453, 8457, 8457, 8467, 8467, 8470, 8470, 8481, 8482, 8486, 8486, 8491, 8491, 8531, 8532, 8539, 8542, 8544, 8555, 8560, 8569, 8585, 8585, 8592, 8601, 8632, 8633, 8658, 8658, 8660, 8660, 8679, 8679, 8704, 8704, 8706, 8707, 8711, 8712, 8715, 8715, 8719, 8719, 8721, 8721, 8725, 8725, 8730, 8730, 8733, 8736, 8739, 8739, 8741, 8741, 8743, 8748, 8750, 8750, 8756, 8759, 8764, 8765, 8776, 8776, 8780, 8780, 8786, 8786, 8800, 8801, 8804, 8807, 8810, 8811, 8814, 8815, 8834, 8835, 8838, 8839, 8853, 8853, 8857, 8857, 8869, 8869, 8895, 8895, 8978, 8978, 9312, 9449, 9451, 9547, 9552, 9587, 9600, 9615, 9618, 9621, 9632, 9633, 9635, 9641, 9650, 9651, 9654, 9655, 9660, 9661, 9664, 9665, 9670, 9672, 9675, 9675, 9678, 9681, 9698, 9701, 9711, 9711, 9733, 9734, 9737, 9737, 9742, 9743, 9756, 9756, 9758, 9758, 9792, 9792, 9794, 9794, 9824, 9825, 9827, 9829, 9831, 9834, 9836, 9837, 9839, 9839, 9886, 9887, 9919, 9919, 9926, 9933, 9935, 9939, 9941, 9953, 9955, 9955, 9960, 9961, 9963, 9969, 9972, 9972, 9974, 9977, 9979, 9980, 9982, 9983, 10045, 10045, 10102, 10111, 11094, 11097, 12872, 12879, 57344, 63743, 65024, 65039, 65533, 65533, 127232, 127242, 127248, 127277, 127280, 127337, 127344, 127373, 127375, 127376, 127387, 127404, 917760, 917999, 983040, 1048573, 1048576, 1114109];
var fullwidthRanges = [12288, 12288, 65281, 65376, 65504, 65510];
var halfwidthRanges = [8361, 8361, 65377, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65512, 65518];
var narrowRanges = [32, 126, 162, 163, 165, 166, 172, 172, 175, 175, 10214, 10221, 10629, 10630];
var wideRanges = [4352, 4447, 8986, 8987, 9001, 9002, 9193, 9196, 9200, 9200, 9203, 9203, 9725, 9726, 9748, 9749, 9776, 9783, 9800, 9811, 9855, 9855, 9866, 9871, 9875, 9875, 9889, 9889, 9898, 9899, 9917, 9918, 9924, 9925, 9934, 9934, 9940, 9940, 9962, 9962, 9970, 9971, 9973, 9973, 9978, 9978, 9981, 9981, 9989, 9989, 9994, 9995, 10024, 10024, 10060, 10060, 10062, 10062, 10067, 10069, 10071, 10071, 10133, 10135, 10160, 10160, 10175, 10175, 11035, 11036, 11088, 11088, 11093, 11093, 11904, 11929, 11931, 12019, 12032, 12245, 12272, 12287, 12289, 12350, 12353, 12438, 12441, 12543, 12549, 12591, 12593, 12686, 12688, 12773, 12783, 12830, 12832, 12871, 12880, 42124, 42128, 42182, 43360, 43388, 44032, 55203, 63744, 64255, 65040, 65049, 65072, 65106, 65108, 65126, 65128, 65131, 94176, 94180, 94192, 94198, 94208, 101589, 101631, 101662, 101760, 101874, 110576, 110579, 110581, 110587, 110589, 110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951, 110960, 111355, 119552, 119638, 119648, 119670, 126980, 126980, 127183, 127183, 127374, 127374, 127377, 127386, 127488, 127490, 127504, 127547, 127552, 127560, 127568, 127569, 127584, 127589, 127744, 127776, 127789, 127797, 127799, 127868, 127870, 127891, 127904, 127946, 127951, 127955, 127968, 127984, 127988, 127988, 127992, 128062, 128064, 128064, 128066, 128252, 128255, 128317, 128331, 128334, 128336, 128359, 128378, 128378, 128405, 128406, 128420, 128420, 128507, 128591, 128640, 128709, 128716, 128716, 128720, 128722, 128725, 128728, 128732, 128735, 128747, 128748, 128756, 128764, 128992, 129003, 129008, 129008, 129292, 129338, 129340, 129349, 129351, 129535, 129648, 129660, 129664, 129674, 129678, 129734, 129736, 129736, 129741, 129756, 129759, 129770, 129775, 129784, 131072, 196605, 196608, 262141];
var isInRange = (ranges, codePoint) => {
let low = 0;
let high = Math.floor(ranges.length / 2) - 1;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
const i = mid * 2;
if (codePoint < ranges[i]) {
high = mid - 1;
} else if (codePoint > ranges[i + 1]) {
low = mid + 1;
} else {
return true;
}
}
return false;
};
var minimumAmbiguousCodePoint = ambiguousRanges[0];
var maximumAmbiguousCodePoint = ambiguousRanges.at(-1);
var minimumFullWidthCodePoint = fullwidthRanges[0];
var maximumFullWidthCodePoint = fullwidthRanges.at(-1);
var minimumHalfWidthCodePoint = halfwidthRanges[0];
var maximumHalfWidthCodePoint = halfwidthRanges.at(-1);
var minimumNarrowCodePoint = narrowRanges[0];
var maximumNarrowCodePoint = narrowRanges.at(-1);
var minimumWideCodePoint = wideRanges[0];
var maximumWideCodePoint = wideRanges.at(-1);
var commonCjkCodePoint = 19968;
var [wideFastPathStart, wideFastPathEnd] = findWideFastPathRange(wideRanges);
function findWideFastPathRange(ranges) {
let fastPathStart = ranges[0];
let fastPathEnd = ranges[1];
for (let index = 0; index < ranges.length; index += 2) {
const start = ranges[index];
const end = ranges[index + 1];
if (commonCjkCodePoint >= start && commonCjkCodePoint <= end) {
return [start, end];
}
if (end - start > fastPathEnd - fastPathStart) {
fastPathStart = start;
fastPathEnd = end;
}
}
return [fastPathStart, fastPathEnd];
}
var isAmbiguous = (codePoint) => {
if (codePoint < minimumAmbiguousCodePoint || codePoint > maximumAmbiguousCodePoint) {
return false;
}
return isInRange(ambiguousRanges, codePoint);
};
var isFullWidth = (codePoint) => {
if (codePoint < minimumFullWidthCodePoint || codePoint > maximumFullWidthCodePoint) {
return false;
}
return isInRange(fullwidthRanges, codePoint);
};
var isWide = (codePoint) => {
if (codePoint >= wideFastPathStart && codePoint <= wideFastPathEnd) {
return true;
}
if (codePoint < minimumWideCodePoint || codePoint > maximumWideCodePoint) {
return false;
}
return isInRange(wideRanges, codePoint);
};
function validate(codePoint) {
if (!Number.isSafeInteger(codePoint)) {
throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
@@ -28804,7 +28970,7 @@ function isKeyOperator2(operator) {
function getValues2(context3, operator, key, modifier) {
var value = context3[key], result = [];
if (isDefined2(value) && value !== "") {
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
value = value.toString();
if (modifier && modifier !== "*") {
value = value.substring(0, parseInt(modifier, 10));
@@ -28982,6 +29148,106 @@ function withDefaults4(oldDefaults, newDefaults) {
}
var endpoint2 = withDefaults4(null, DEFAULTS2);
var import_fast_content_type_parse2 = __toESM2(require_fast_content_type_parse2());
var intRegex2 = /^-?\d+$/;
var noiseValue2 = /^-?\d+n+$/;
var originalStringify2 = JSON.stringify;
var originalParse2 = JSON.parse;
var customFormat2 = /^-?\d+n$/;
var bigIntsStringify2 = /([\[:])?"(-?\d+)n"($|([\\n]|\s)*(\s|[\\n])*[,\}\]])/g;
var noiseStringify2 = /([\[:])?("-?\d+n+)n("$|"([\\n]|\s)*(\s|[\\n])*[,\}\]])/g;
var JSONStringify2 = (value, replacer, space) => {
if ("rawJSON" in JSON) {
return originalStringify2(
value,
(key, value2) => {
if (typeof value2 === "bigint")
return JSON.rawJSON(value2.toString());
if (typeof replacer === "function")
return replacer(key, value2);
if (Array.isArray(replacer) && replacer.includes(key))
return value2;
return value2;
},
space
);
}
if (!value)
return originalStringify2(value, replacer, space);
const convertedToCustomJSON = originalStringify2(
value,
(key, value2) => {
const isNoise = typeof value2 === "string" && Boolean(value2.match(noiseValue2));
if (isNoise)
return value2.toString() + "n";
if (typeof value2 === "bigint")
return value2.toString() + "n";
if (typeof replacer === "function")
return replacer(key, value2);
if (Array.isArray(replacer) && replacer.includes(key))
return value2;
return value2;
},
space
);
const processedJSON = convertedToCustomJSON.replace(
bigIntsStringify2,
"$1$2$3"
);
const denoisedJSON = processedJSON.replace(noiseStringify2, "$1$2$3");
return denoisedJSON;
};
var isContextSourceSupported2 = () => JSON.parse("1", (_, __, context3) => !!context3 && context3.source === "1");
var convertMarkedBigIntsReviver2 = (key, value, context3, userReviver) => {
const isCustomFormatBigInt = typeof value === "string" && value.match(customFormat2);
if (isCustomFormatBigInt)
return BigInt(value.slice(0, -1));
const isNoiseValue = typeof value === "string" && value.match(noiseValue2);
if (isNoiseValue)
return value.slice(0, -1);
if (typeof userReviver !== "function")
return value;
return userReviver(key, value, context3);
};
var JSONParseV22 = (text, reviver) => {
return JSON.parse(text, (key, value, context3) => {
const isBigNumber = typeof value === "number" && (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER);
const isInt = context3 && intRegex2.test(context3.source);
const isBigInt = isBigNumber && isInt;
if (isBigInt)
return BigInt(context3.source);
if (typeof reviver !== "function")
return value;
return reviver(key, value, context3);
});
};
var MAX_INT2 = Number.MAX_SAFE_INTEGER.toString();
var MAX_DIGITS2 = MAX_INT2.length;
var stringsOrLargeNumbers2 = /"(?:\\.|[^"])*"|-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?/g;
var noiseValueWithQuotes2 = /^"-?\d+n+"$/;
var JSONParse2 = (text, reviver) => {
if (!text)
return originalParse2(text, reviver);
if (isContextSourceSupported2())
return JSONParseV22(text, reviver);
const serializedData = text.replace(
stringsOrLargeNumbers2,
(text2, digits, fractional, exponential) => {
const isString = text2[0] === '"';
const isNoise = isString && Boolean(text2.match(noiseValueWithQuotes2));
if (isNoise)
return text2.substring(0, text2.length - 1) + 'n"';
const isFractionalOrExponential = fractional || exponential;
const isLessThanMaxSafeInt = digits && (digits.length < MAX_DIGITS2 || digits.length === MAX_DIGITS2 && digits <= MAX_INT2);
if (isString || isFractionalOrExponential || isLessThanMaxSafeInt)
return text2;
return '"' + text2 + 'n"';
}
);
return originalParse2(
serializedData,
(key, value, context3) => convertMarkedBigIntsReviver2(key, value, context3, reviver)
);
};
var RequestError2 = class extends Error {
name;
/**
@@ -29019,7 +29285,7 @@ var RequestError2 = class extends Error {
this.request = requestCopy;
}
};
var VERSION22 = "10.0.7";
var VERSION22 = "10.0.8";
var defaults_default2 = {
headers: {
"user-agent": `octokit-request.js/${VERSION22} ${getUserAgent2()}`
@@ -29046,7 +29312,7 @@ async function fetchWrapper2(requestOptions) {
}
const log = requestOptions.request?.log || console;
const parseSuccessResponseBody = requestOptions.request?.parseSuccessResponseBody !== false;
const body = isPlainObject22(requestOptions.body) || Array.isArray(requestOptions.body) ? JSON.stringify(requestOptions.body) : requestOptions.body;
const body = isPlainObject22(requestOptions.body) || Array.isArray(requestOptions.body) ? JSONStringify2(requestOptions.body) : requestOptions.body;
const requestHeaders = Object.fromEntries(
Object.entries(requestOptions.headers).map(([name, value]) => [
name,
@@ -29145,7 +29411,7 @@ async function getResponseData2(response) {
let text = "";
try {
text = await response.text();
return JSON.parse(text);
return JSONParse2(text);
} catch (err) {
return text;
}
@@ -33020,24 +33286,28 @@ var requiresLabels = createTypedObject(RequiresLabel)({
description: "This PR requires a passing TGP before merging is allowed"
}
});
var FeatureLabel = class extends Label {
var MiscLabel = class extends Label {
};
var featureLabels = createTypedObject(FeatureLabel)({
FEATURE_IN_BACKLOG: {
name: "feature: in backlog",
description: "Feature request for which voting has completed and is now in the backlog"
var miscLabels = createTypedObject(MiscLabel)({
FEATURE: {
name: "feature",
description: "Label used to distinguish feature request from other issues"
},
FEATURE_VOTES_REQUIRED: {
name: "feature: votes required",
description: "Feature request which is currently still in the voting phase"
GOOD_FIRST_ISSUE: {
name: "good first issue",
description: "Label noting a good first issue to be worked on by a community member"
},
FEATURE_UNDER_CONSIDERATION: {
name: "feature: under consideration",
description: "Feature request for which voting has completed and the request is now under consideration"
HELP_WANTED: {
name: "help wanted",
description: "Label noting an issue which the team is looking for contribution from the community to fix"
},
FEATURE_INSUFFICIENT_VOTES: {
name: "feature: insufficient votes",
description: "Label to add when the not a sufficient number of votes or comments from unique authors"
RENOVATE_MANAGED: {
name: "renovate managed",
description: "Label noting that a pull request will automatically be managed and rebased by renovate"
},
GEMINI_TRIAGED: {
name: "gemini-triaged",
description: "Label noting that an issue has been triaged by gemini"
}
});
var allLabels = {
@@ -33046,8 +33316,8 @@ var allLabels = {
...mergeLabels,
...targetLabels,
...priorityLabels,
...featureLabels,
...requiresLabels
...requiresLabels,
...miscLabels
};
var import_which = __toESM2(require_lib2());
var import_yaml = __toESM2(require_dist());
@@ -33225,7 +33495,7 @@ tmp/lib/tmp.js:
(* v8 ignore next -- @preserve *)
(* v8 ignore else -- @preserve *)
@angular/ng-dev/bundles/chunk-ZTI2LCA3.mjs:
@angular/ng-dev/bundles/chunk-YN3IWAKJ.mjs:
(*! Bundled license information:
yargs-parser/build/lib/string-utils.js:
@@ -33266,7 +33536,7 @@ tmp/lib/tmp.js:
*)
*)
@angular/ng-dev/bundles/chunk-BZKO77AS.mjs:
@angular/ng-dev/bundles/chunk-PZCO3UAP.mjs:
(*! Bundled license information:
@octokit/request-error/dist-src/index.js:
+2 -2
View File
@@ -5,9 +5,9 @@ runs:
using: 'composite'
steps:
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/saucelabs@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Starting Saucelabs tunnel service
shell: bash
run: ./tools/saucelabs/sauce-service.sh run &
+4 -4
View File
@@ -21,17 +21,17 @@ jobs:
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Build adev
# `snapshot-build` config is used to stamp the exact version with sha in the footer.
run: pnpm bazel build //adev:build.production --config=snapshot-build
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@9de194d77b66b6b3294e0f041e29985d2916e911
with:
workflow-artifact-name: 'adev-preview'
pull-number: '${{github.event.pull_request.number}}'
+1 -1
View File
@@ -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@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@9de194d77b66b6b3294e0f041e29985d2916e911
with:
github-token: '${{secrets.GITHUB_TOKEN}}'
workflow-artifact-name: 'adev-preview'
@@ -17,6 +17,6 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: angular/dev-infra/github-actions/branch-manager@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/branch-manager@9de194d77b66b6b3294e0f041e29985d2916e911
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
- run: pnpm install --frozen-lockfile
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
bazelrc: ./.bazelrc.user
+28 -26
View File
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Check code lint
@@ -32,6 +32,8 @@ jobs:
run: pnpm ng-dev pullapprove verify
- name: Validate angular robot configuration
run: pnpm ng-dev ngbot verify
- name: Validate agent skills
run: pnpm ng-dev ai skills validate
- name: Confirm code builds with typescript as expected
run: pnpm check-tooling-setup
@@ -39,13 +41,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
with:
disable-package-manager-cache: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -55,7 +57,7 @@ jobs:
- name: Test build
run: pnpm devtools:build:chrome
- name: Cypress run
uses: cypress-io/github-action@84d178e4bbce871e23f2ffa3085898cde0e4f0ec # v7.1.2
uses: cypress-io/github-action@bc22e01685c56e89e7813fd8e26f33dc47f87e15 # v7.1.5
with:
command: pnpm devtools:test:e2e
start: pnpm bazel run //devtools/src:devserver
@@ -67,11 +69,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -83,11 +85,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -100,11 +102,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -119,11 +121,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -136,11 +138,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
@@ -152,11 +154,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -206,11 +208,11 @@ jobs:
runs-on: ubuntu-latest-8core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Build adev
+16 -3
View File
@@ -3,23 +3,36 @@ name: DevInfra
on:
pull_request_target:
types: [opened, synchronize, reopened]
issues:
types: [opened, reopened]
# Declare default permissions as read only.
permissions:
contents: read
jobs:
labels:
pull_request_labels:
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/labeling/pull-request@9de194d77b66b6b3294e0f041e29985d2916e911
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
labels: '{"requires: TGP": ["packages/core/primitives/**/{*,.*}"]}'
post_approval_changes:
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/post-approval-changes@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/post-approval-changes@9de194d77b66b6b3294e0f041e29985d2916e911
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
issue_labels:
if: github.event_name == 'issues'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/labeling/issue@9de194d77b66b6b3294e0f041e29985d2916e911
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
google-generative-ai-key: ${{ secrets.GOOGLE_GENERATIVE_AI_KEY }}
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/google-internal-tests@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/google-internal-tests@9de194d77b66b6b3294e0f041e29985d2916e911
with:
run-tests-guide-url: http://go/angular-g3sync-start
github-token: ${{ secrets.GITHUB_TOKEN }}
+4 -4
View File
@@ -13,15 +13,15 @@ jobs:
JOBS: 2
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/saucelabs@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Set up Sauce Tunnel Daemon
run: pnpm bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
env:
+1 -1
View File
@@ -9,6 +9,6 @@ jobs:
status:
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/unified-status-check@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/unified-status-check@9de194d77b66b6b3294e0f041e29985d2916e911
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+3 -3
View File
@@ -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@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- id: workflows
@@ -36,9 +36,9 @@ jobs:
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- 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
+23 -21
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Check code lint
@@ -32,12 +32,14 @@ jobs:
run: pnpm ng-dev ngbot verify
- name: Confirm code builds with typescript as expected
run: pnpm check-tooling-setup
- name: Validate agent skills
run: pnpm ng-dev ai skills validate
- name: Check commit message
run: pnpm ng-dev commit-message validate-range ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
- 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@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/linting/licenses@9de194d77b66b6b3294e0f041e29985d2916e911
with:
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
@@ -45,13 +47,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
with:
disable-package-manager-cache: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run unit tests
@@ -59,7 +61,7 @@ jobs:
- name: Test build
run: pnpm devtools:build:chrome
- name: Cypress run
uses: cypress-io/github-action@84d178e4bbce871e23f2ffa3085898cde0e4f0ec # v7.1.2
uses: cypress-io/github-action@bc22e01685c56e89e7813fd8e26f33dc47f87e15 # v7.1.5
with:
command: pnpm devtools:test:e2e
start: pnpm bazel run //devtools/src:devserver
@@ -71,11 +73,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run CI tests for framework
@@ -95,11 +97,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run integration CI tests for framework
@@ -110,11 +112,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run tests
@@ -127,11 +129,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run tests
@@ -142,11 +144,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@9de194d77b66b6b3294e0f041e29985d2916e911
- name: Install node modules
run: pnpm install --frozen-lockfile
- run: |
+1 -1
View File
@@ -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@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
sarif_file: results.sarif
+1 -1
View File
@@ -9,5 +9,5 @@ export const github = {
name: 'angular',
mainBranchName: 'main',
mergeMode: 'caretaker-only',
requireReleaseModeForRelease: true,
requireReleaseModeForRelease: false,
};
+1 -1
View File
@@ -1 +1 @@
22.22.0
22.22.1
+3
View File
@@ -30,6 +30,9 @@ vscode-ng-language-service/syntaxes/test/data/*.html
# Ignore goldens MD files
goldens/**/*.api.md
# Ignore golden symbol json files
packages/**/*.golden_symbols.json
# adev generated files
adev/src/content/aria/**/*.json
adev/src/content/cli/**/*.json
+7 -15
View File
@@ -106,7 +106,6 @@ groups:
- thePunderWoman
- kirjs
- JoostK
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -153,7 +152,6 @@ groups:
- kirjs
- thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- JeanMeche
- ~amishne
- ~leonsenft
@@ -209,7 +207,6 @@ groups:
- kirjs
- thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -246,6 +243,8 @@ groups:
- >
contains_any_globs(files, [
'adev/**/{*,.*}',
'tools/manual_api_docs/blocks/*.md',
'tools/manual_api_docs/elements/*.md',
])
reviewers:
users:
@@ -263,7 +262,6 @@ groups:
- ~pkozlowski-opensource
- ~mgechev
- MarkTechson
- mmalerba
- ~hawkgs
- ~amishne
- ~leonsenft
@@ -299,7 +297,11 @@ groups:
<<: *defaults
conditions:
- >
contains_any_globs(files.exclude('.pullapprove.yml'), [
contains_any_globs(files
.exclude('.pullapprove.yml')
.exclude('tools/manual_api_docs/blocks/*.md')
.exclude('tools/manual_api_docs/elements/*.md'),
[
'{*,.*}',
'.agent/**/{*,.*}',
'.devcontainer/**/{*,.*}',
@@ -376,7 +378,6 @@ groups:
- thePunderWoman
- ~pkozlowski-opensource
- kirjs
- mmalerba
- crisbeto
- devversion
- JeanMeche
@@ -412,7 +413,6 @@ groups:
- kirjs
- thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -481,10 +481,6 @@ groups:
- thePunderWoman # Jessica Janiuk
- AndrewKushnir # Andrew Kushnir
- atscott # Andrew Scott
labels:
pending: 'requires: TGP'
approved: 'requires: TGP'
rejected: 'requires: TGP'
# External team required reviews
primitives-shared:
@@ -502,10 +498,6 @@ groups:
- tbondwilkinson # Tom Wilkinson
- rahatarmanahmed # Rahat Ahmed
- ENAML # Ethan Cline
labels:
pending: 'requires: TGP'
approved: 'requires: TGP'
rejected: 'requires: TGP'
####################################################################################
# Override managed result groups
+137 -108
View File
@@ -1,41 +1,168 @@
<a name="21.1.5"></a>
# 21.1.5 (2026-02-18)
<a name="21.2.5"></a>
# 21.2.5 (2026-03-18)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [334ae10168](https://github.com/angular/angular/commit/334ae10168fdad15cd1390180e2994b4eb65349b) | fix | ensure generated code compiles |
| [23ea431c4e](https://github.com/angular/angular/commit/23ea431c4ec45cbb4a7db9839969e7cb23b07f58) | fix | parse named HTML entities containing digits |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [26c43d14ba](https://github.com/angular/angular/commit/26c43d14baad1a6b3629a77825e702a97a4f8482) | fix | escape template literal in TCB |
| [67e0ba7e03](https://github.com/angular/angular/commit/67e0ba7e03bb940639f0eafb3af45015e9727eac) | fix | generic types not filled out correctly in type check block |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [1890c3008b](https://github.com/angular/angular/commit/1890c3008bbb41b7143b7ede09bed1f7704744fb) | fix | clean up dehydrated views during HMR component replacement |
| [bf948be4c2](https://github.com/angular/angular/commit/bf948be4c2c88c604e428cba35e3b9e532bfe5b0) | fix | run linked signal equality check without reactive consumer |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [076d41c3f6](https://github.com/angular/angular/commit/076d41c3f6496eb6c6f84b54e2d2ca85c1b35e64) | fix | prevent trailing comma syntax errors after removing NgStyle |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [e19150d2b5](https://github.com/angular/angular/commit/e19150d2b596e87c69bee61f478c3e9c7cbc8f67) | fix | preserve redirect policy on reconstructed asset requests |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.0-next.3"></a>
# 21.2.0-next.3 (2026-02-11)
<a name="21.2.4"></a>
# 21.2.4 (2026-03-12)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [ed2d324f9c](https://github.com/angular/angular/commit/ed2d324f9cc12aab6cfa0569ef10b73243a62c65) | fix | disallow translations of iframe src |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [abbd8797bb](https://github.com/angular/angular/commit/abbd8797bbd3ae53a10033c39bd895b5b85a4fae) | fix | reverts "feat(core): add support for nested animations" |
| [d1dcd16c5b](https://github.com/angular/angular/commit/d1dcd16c5b40291aa3fa2dc84d22842cd657b201) | fix | sanitize translated form attributes |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.3"></a>
# 21.2.3 (2026-03-11)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [62a97f7e4b](https://github.com/angular/angular/commit/62a97f7e4b896b4b03a1ef25764db387ffecebe1) | fix | ensure definitions compile |
| [21b1c3b2ee](https://github.com/angular/angular/commit/21b1c3b2ee2c8423782b111b93bd60eb6b453259) | fix | include signal debug names in their `toString()` representation |
| [224e60ecb1](https://github.com/angular/angular/commit/224e60ecb1b90115baa702f1c06edc1d64d86187) | fix | sanitize translated attribute bindings with interpolations |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.2"></a>
# 21.2.2 (2026-03-09)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [1df1697c6e](https://github.com/angular/angular/commit/1df1697c6e3a6b1d302f7692b495146943faa12f) | fix | prevent mutation of children array in RecursiveVisitor |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [c822bf8e76](https://github.com/angular/angular/commit/c822bf8e76611afde332b6625f5e7bae2fe9c3f3) | fix | always parenthesize object literals in TCB |
| [05d022d5e6](https://github.com/angular/angular/commit/05d022d5e61cca7ac90d5b2b2ba3fc738b364ad9) | fix | ignore generated ngDevMode signal branch for code coverage |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [670d1660c4](https://github.com/angular/angular/commit/670d1660c40504e3f55e094c3ebbcccad14163f3) | feat | add 'blur' option to debounce rule |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.1"></a>
# 21.2.1 (2026-03-04)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [e2e9a9a531](https://github.com/angular/angular/commit/e2e9a9a531c9e9a69701e549f28354cc5d5edd77) | fix | adds transfer cache to httpResource to fix hydration |
| [b4ec3cc4e4](https://github.com/angular/angular/commit/b4ec3cc4e41f2948ad0830eb14aa05d14fa3a9ed) | fix | prevent child animation elements from being orphaned |
| [e923d88398](https://github.com/angular/angular/commit/e923d8839868c79989502ab3503e13d93c78516a) | fix | Prevent removal of elements during drag and drop |
### http
| Commit | Type | Description |
| -- | -- | -- |
| [277ade97ac](https://github.com/angular/angular/commit/277ade97ac2a3a7f2a5b513acaa93e7663cdc55f) | fix | correctly cache blob responses in transfer cache ([#67002](https://github.com/angular/angular/pull/67002)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.0"></a>
# 21.2.0 (2026-02-25)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [18003a33bb](https://github.com/angular/angular/commit/18003a33bb0d6bb09def8a0e5939fa24069696eb) | feat | add an 'outlet' injector option for ngTemplateOutlet |
| [8bbe6dc46c](https://github.com/angular/angular/commit/8bbe6dc46c9dc13bafa81a60c7613b84b5ca3761) | feat | Add Location strategies to manage trailing slash on write |
| [51cc914807](https://github.com/angular/angular/commit/51cc91480761b7275c15b5600381207f8ca00ee5) | feat | support height in ImageLoaderConfig and built-in loaders |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [11834a4274](https://github.com/angular/angular/commit/11834a42745e62830a83a4c14eea9d203baec680) | fix | add geolocation element to schema |
| [72534e2a34](https://github.com/angular/angular/commit/72534e2a3458df4e1bb097973872f00bbb92be42) | feat | Add support for the `instanceof` binary operator |
| [95b3f37d4a](https://github.com/angular/angular/commit/95b3f37d4a7d9a38f616d56df746dfcda3c2139b) | feat | Exhaustive checks for switch blocks |
| [04ba09a8d9](https://github.com/angular/angular/commit/04ba09a8d9454013bebdd643eacb737642161952) | feat | support `AstVisitor.visitEmptyExpr()` |
| [ce80136e7b](https://github.com/angular/angular/commit/ce80136e7b9f0024d49fce835cffa024c4505855) | fix | optimize away unnecessary restore/reset view calls |
| [3242a61bae](https://github.com/angular/angular/commit/3242a61bae02253d13abb510b666376c665e61ac) | fix | variable counter visiting some expressions twice |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [473dd3e1cb](https://github.com/angular/angular/commit/473dd3e1cbd4fe3fa88ae4d5358eee35c11acb1b) | fix | attach source spans to object literal keys in TCB |
| [a904d9f77b](https://github.com/angular/angular/commit/a904d9f77b56feab407f75f8d0527fa512d5dafb) | fix | support nested component declaration |
| [2ea6dfc6c9](https://github.com/angular/angular/commit/2ea6dfc6c9ca11e96a2654510c980419899f8d04) | fix | update diagnostic to flag no-op arrow functions in listeners |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [8d5210c9fe](https://github.com/angular/angular/commit/8d5210c9fedd8abdd810d7a89ec7ee9a1234f5c1) | feat | add ChangeDetectionStrategy.Eager alias for Default |
| [92d2498910](https://github.com/angular/angular/commit/92d2498910caed06c182b67e39726e1441418698) | feat | add host node to DeferBlockData ([#66546](https://github.com/angular/angular/pull/66546)) |
| [ea2016a6dc](https://github.com/angular/angular/commit/ea2016a6dce58f95ecab7c773d5dcde274354e1a) | feat | add support for nested animations |
| [bd2868e915](https://github.com/angular/angular/commit/bd2868e915e78fb60583c00a11c778e3abf3ed8d) | fix | capture animation dependencies eagerly to avoid destroyed injector |
| [81cabc1477](https://github.com/angular/angular/commit/81cabc14777a3b4966c29d60e1505aca8c29b71c) | feat | add support for TypeScript 6 |
| [1ba9b7ac50](https://github.com/angular/angular/commit/1ba9b7ac5001b315cc9df78c518964dbf479d647) | feat | resource composition via snapshots |
| [d9923b72a2](https://github.com/angular/angular/commit/d9923b72a20972ba6bf728d78f1afac6936ade18) | feat | support arrow functions in expressions |
| [a7e8abbb7e](https://github.com/angular/angular/commit/a7e8abbb7e738ba338c3f50c76934c99925954e5) | fix | correctly handle SkipSelf when resolving from embedded view injector |
| [e53c8abaf9](https://github.com/angular/angular/commit/e53c8abaf9f09ca66b55f8169b9d723d1ffb640a) | fix | Fix flakey test due to document injection |
| [0806ee3826](https://github.com/angular/angular/commit/0806ee38269b664f535e10d4d501b88370d3b44c) | fix | prevent animated element duplication with dynamic components in zoneless mode |
| [ed78fa05c7](https://github.com/angular/angular/commit/ed78fa05c710ebafb355ae00a85b190a118b6cc4) | fix | Remove note to skip arrow functions in best practices |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [f56bb07d83](https://github.com/angular/angular/commit/f56bb07d83a015b0ac12e74fdb0cf1550ff36b97) | feat | add field param to submit action and onInvalid |
| [ba009b6031](https://github.com/angular/angular/commit/ba009b603119299a03f9d844f93882d42d47d150) | feat | add form directive |
| [24c0c5a180](https://github.com/angular/angular/commit/24c0c5a180fab31438b1939e501f01b75e2d2760) | feat | support signal-based schemas in validateStandardSchema |
| [22afbb2f36](https://github.com/angular/angular/commit/22afbb2f36be89c2ae575df343571a918dec5985) | feat | add parsing support to native inputs ([#66917](https://github.com/angular/angular/pull/66917)) |
| [95c386469c](https://github.com/angular/angular/commit/95c386469c7a2f09dd731601c2061bdb10d25717) | feat | Add passing focus options to form field |
| [95ecce8334](https://github.com/angular/angular/commit/95ecce8334299defe55fb2b74264e5258ffd137c) | feat | allow setting submit options at form-level |
| [ebae211add](https://github.com/angular/angular/commit/ebae211add37700858adeb8fc5d87bf503a59721) | feat | introduce parse errors in signal forms |
| [3937afc316](https://github.com/angular/angular/commit/3937afc3167ce409eebb06d91d5fb122eea4e33d) | feat | introduce SignalFormControl for Reactive Forms compatibility |
| [30f0914754](https://github.com/angular/angular/commit/30f09147545b67185f93efb9796e37c1db76733a) | feat | support binding null to number input ([#66917](https://github.com/angular/angular/pull/66917)) |
| [dd208ca259](https://github.com/angular/angular/commit/dd208ca2595258fcd1e289374f812ce0b56c7011) | feat | update submit function to accept options object |
| [27397b3f4f](https://github.com/angular/angular/commit/27397b3f4f3182ce00d6e2f8690285c316e2a274) | fix | clear parse errors when model updates ([#66917](https://github.com/angular/angular/pull/66917)) |
| [63d8005703](https://github.com/angular/angular/commit/63d80057039928b3e878b59c1fe6b93ef1c6b701) | fix | preserve custom-control focus context in signal forms |
| [631f60d1f9](https://github.com/angular/angular/commit/631f60d1f9be72cb68330308a6ff18cc195babb8) | fix | preserve parse errors when parse returns value |
| [adfb83146b](https://github.com/angular/angular/commit/adfb83146b0c149734f43961563b389e00cc1d85) | fix | simplify design of parse errors |
### http
| [fb05fc86d0](https://github.com/angular/angular/commit/fb05fc86d0f12ffafd94c7c1420118d8a79f7e59) | fix | sort error summary by DOM order |
| [567f292e8e](https://github.com/angular/angular/commit/567f292e8e0f9d2b5ddebadfa1c6d6dd6c456f39) | fix | support custom controls as host directives |
| [bdfb60f3e3](https://github.com/angular/angular/commit/bdfb60f3e33065e047183dc1890c36e527e2b304) | fix | use consistent error format returned from parse |
| [d75046bc09](https://github.com/angular/angular/commit/d75046bc091699bbadcb5f2032be627e983ee6fa) | fix | warn when showing hidden field state |
### language-server
| Commit | Type | Description |
| -- | -- | -- |
| [cb1163e5e5](https://github.com/angular/angular/commit/cb1163e5e5434d5d96897180f6f0eb86d3992964) | fix | correctly parse ArrayBuffer and Blob in transfer cache |
| [ebc90c26f5](https://github.com/angular/angular/commit/ebc90c26f5ff1ba1e0ca9b775a44e301ebfb9473) | feat | Add completions and hover info for inline styles |
| [26fd0839c3](https://github.com/angular/angular/commit/26fd0839c32d2ebeaa5e3ecc10ed70ab9ca17749) | feat | Add folding range support for inline styles |
| [573aadef7e](https://github.com/angular/angular/commit/573aadef7eb8b6b5e83b82a16f95d2a556f27c01) | feat | Add quick info for inline styles |
| [6fb39d9b62](https://github.com/angular/angular/commit/6fb39d9b62cbb634e95ec00fe5ef85d84da3bdbd) | feat | Support client-side file watching via `onDidChangeWatchedFiles` |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [496967e7b1](https://github.com/angular/angular/commit/496967e7b13dfe1ebdde69724cd62880914beb60) | feat | add JSON schema for angularCompilerOptions |
| [8c21866f49](https://github.com/angular/angular/commit/8c21866f49ff74344551395ae0a5df1841d54c0d) | feat | add linked editing ranges for HTML tag synchronization |
| [d2137928e8](https://github.com/angular/angular/commit/d2137928e8f075527016a3c011dd8efc4d4e1ebd) | perf | use lightweight project warmup for Angular analysis |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [b51bab583d](https://github.com/angular/angular/commit/b51bab583d84e38f16dea489e4119edc34e2a491) | feat | Add partial ActivatedRouteSnapshot information to `canMatch` params |
| [cf9620f7d0](https://github.com/angular/angular/commit/cf9620f7d072897f13b7f281b7bca6f51f69cfd0) | feat | Make match options optional in isActive |
| [907a94dcec](https://github.com/angular/angular/commit/907a94dcec2926a5c7d0c4d36249bd62e31a2ae3) | feat | Update `IsActiveMatchOptions` APIs to accept a Partial |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.1.5"></a>
# 21.1.5 (2026-02-18)
No user facing changes in this release
<!-- CHANGELOG SPLIT MARKER -->
@@ -61,42 +188,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.0-next.2"></a>
# 21.2.0-next.2 (2026-02-04)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [8d5210c9fe](https://github.com/angular/angular/commit/8d5210c9fedd8abdd810d7a89ec7ee9a1234f5c1) | feat | add ChangeDetectionStrategy.Eager alias for Default |
| [aff9e36a98](https://github.com/angular/angular/commit/aff9e36a988ad7f11bc7a1ca903f75140d14c02c) | fix | `linkedSignal.update` should propagate errors |
| [8ab433abdd](https://github.com/angular/angular/commit/8ab433abdd4c8984b6f9a16219b10af0c54b31f7) | fix | export DirectiveWithBindings |
| [cab5ddd526](https://github.com/angular/angular/commit/cab5ddd526f5a6ba44b042ba0391f0526877cde6) | fix | hold constructors weakly in DepsTracker cache |
| [c66a19f0de](https://github.com/angular/angular/commit/c66a19f0de1a4f8d0f50079b26f8bb52852be6e1) | fix | prevent element duplication with dynamic components |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [95ecce8334](https://github.com/angular/angular/commit/95ecce8334299defe55fb2b74264e5258ffd137c) | feat | allow setting submit options at form-level |
| [3937afc316](https://github.com/angular/angular/commit/3937afc3167ce409eebb06d91d5fb122eea4e33d) | feat | introduce SignalFormControl for Reactive Forms compatibility |
| [dd208ca259](https://github.com/angular/angular/commit/dd208ca2595258fcd1e289374f812ce0b56c7011) | feat | update submit function to accept options object |
| [b1bf535f8e](https://github.com/angular/angular/commit/b1bf535f8e5cbeaec23e9dbb98c1a1bb99deb62a) | fix | Resolves debounce promise on abort in debounceForDuration |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [496967e7b1](https://github.com/angular/angular/commit/496967e7b13dfe1ebdde69724cd62880914beb60) | feat | add JSON schema for angularCompilerOptions |
| [8c21866f49](https://github.com/angular/angular/commit/8c21866f49ff74344551395ae0a5df1841d54c0d) | feat | add linked editing ranges for HTML tag synchronization |
### localize
| Commit | Type | Description |
| -- | -- | -- |
| [1c3b1cf18d](https://github.com/angular/angular/commit/1c3b1cf18d14eb795f949ed05c4a6741dc582485) | fix | add support for unit-test builder in ng-add schematic |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [cf9620f7d0](https://github.com/angular/angular/commit/cf9620f7d072897f13b7f281b7bca6f51f69cfd0) | feat | Make match options optional in isActive |
| [907a94dcec](https://github.com/angular/angular/commit/907a94dcec2926a5c7d0c4d36249bd62e31a2ae3) | feat | Update `IsActiveMatchOptions` APIs to accept a Partial |
| [458bc4a2c8](https://github.com/angular/angular/commit/458bc4a2c88aa6f9f955c8f2bd58dd73ae35b0ad) | fix | limit UrlParser recursion depth to prevent stack overflow |
| [3867cd8554](https://github.com/angular/angular/commit/3867cd85545bfb5bde9e92d46467651337b2b7ae) | perf | Use .bind to avoid holding other closures in memory |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.1.3"></a>
# 21.1.3 (2026-02-04)
### core
@@ -122,34 +213,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.0-next.1"></a>
# 21.2.0-next.1 (2026-01-28)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [8bbe6dc46c](https://github.com/angular/angular/commit/8bbe6dc46c9dc13bafa81a60c7613b84b5ca3761) | feat | Add Location strategies to manage trailing slash on write |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [ebae211add](https://github.com/angular/angular/commit/ebae211add37700858adeb8fc5d87bf503a59721) | feat | introduce parse errors in signal forms |
| [e682e53113](https://github.com/angular/angular/commit/e682e53113601b967881cf3d19ba8cffff637c0f) | fix | only touch visible, interactive fields on submit |
| [fb05fc86d0](https://github.com/angular/angular/commit/fb05fc86d0f12ffafd94c7c1420118d8a79f7e59) | fix | sort error summary by DOM order |
### language-server
| Commit | Type | Description |
| -- | -- | -- |
| [6fb39d9b62](https://github.com/angular/angular/commit/6fb39d9b62cbb634e95ec00fe5ef85d84da3bdbd) | feat | Support client-side file watching via `onDidChangeWatchedFiles` |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [8a7cbd4668](https://github.com/angular/angular/commit/8a7cbd46685874f4500c52629d09c5f7fd309080) | fix | Detect local project version on creation |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [b51bab583d](https://github.com/angular/angular/commit/b51bab583d84e38f16dea489e4119edc34e2a491) | feat | Add partial ActivatedRouteSnapshot information to `canMatch` params |
| [dbd50be7f7](https://github.com/angular/angular/commit/dbd50be7f7151c567b3caa72c3f21083e7022b74) | fix | Do not intercept reload events with Navigation integration |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.1.2"></a>
# 21.1.2 (2026-01-28)
### forms
@@ -167,40 +230,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.2.0-next.0"></a>
# 21.2.0-next.0 (2026-01-22)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [72534e2a34](https://github.com/angular/angular/commit/72534e2a3458df4e1bb097973872f00bbb92be42) | feat | Add support for the `instanceof` binary operator |
| [04ba09a8d9](https://github.com/angular/angular/commit/04ba09a8d9454013bebdd643eacb737642161952) | feat | support `AstVisitor.visitEmptyExpr()` |
| [ce80136e7b](https://github.com/angular/angular/commit/ce80136e7b9f0024d49fce835cffa024c4505855) | fix | optimize away unnecessary restore/reset view calls |
| [3242a61bae](https://github.com/angular/angular/commit/3242a61bae02253d13abb510b666376c665e61ac) | fix | variable counter visiting some expressions twice |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [473dd3e1cb](https://github.com/angular/angular/commit/473dd3e1cbd4fe3fa88ae4d5358eee35c11acb1b) | fix | attach source spans to object literal keys in TCB |
| [a904d9f77b](https://github.com/angular/angular/commit/a904d9f77b56feab407f75f8d0527fa512d5dafb) | fix | support nested component declaration |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [92d2498910](https://github.com/angular/angular/commit/92d2498910caed06c182b67e39726e1441418698) | feat | add host node to DeferBlockData ([#66546](https://github.com/angular/angular/pull/66546)) |
| [1ba9b7ac50](https://github.com/angular/angular/commit/1ba9b7ac5001b315cc9df78c518964dbf479d647) | feat | resource composition via snapshots |
| [d9923b72a2](https://github.com/angular/angular/commit/d9923b72a20972ba6bf728d78f1afac6936ade18) | feat | support arrow functions in expressions |
| [ed78fa05c7](https://github.com/angular/angular/commit/ed78fa05c710ebafb355ae00a85b190a118b6cc4) | fix | Remove note to skip arrow functions in best practices |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [95c386469c](https://github.com/angular/angular/commit/95c386469c7a2f09dd731601c2061bdb10d25717) | feat | Add passing focus options to form field |
### language-server
| Commit | Type | Description |
| -- | -- | -- |
| [ebc90c26f5](https://github.com/angular/angular/commit/ebc90c26f5ff1ba1e0ca9b775a44e301ebfb9473) | feat | Add completions and hover info for inline styles |
| [26fd0839c3](https://github.com/angular/angular/commit/26fd0839c32d2ebeaa5e3ecc10ed70ab9ca17749) | feat | Add folding range support for inline styles |
| [573aadef7e](https://github.com/angular/angular/commit/573aadef7eb8b6b5e83b82a16f95d2a556f27c01) | feat | Add quick info for inline styles |
<!-- CHANGELOG SPLIT MARKER -->
<a name="21.1.1"></a>
# 21.1.1 (2026-01-21)
### compiler-cli
+27 -27
View File
@@ -6,41 +6,41 @@ module(
bazel_dep(name = "rules_pkg", version = "1.2.0")
bazel_dep(name = "rules_nodejs", version = "6.7.3")
bazel_dep(name = "aspect_rules_ts", version = "3.8.4")
bazel_dep(name = "aspect_rules_js", version = "2.9.2")
bazel_dep(name = "aspect_rules_esbuild", version = "0.25.0")
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.2")
bazel_dep(name = "aspect_rules_ts", version = "3.8.6")
bazel_dep(name = "aspect_rules_js", version = "3.0.3")
bazel_dep(name = "aspect_rules_esbuild", version = "0.25.1")
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4")
bazel_dep(name = "aspect_rules_rollup", version = "2.0.1")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.22.5")
bazel_dep(name = "tar.bzl", version = "0.8.1")
bazel_dep(name = "yq.bzl", version = "0.3.4")
bazel_dep(name = "bazel_lib", version = "3.2.2")
bazel_dep(name = "tar.bzl", version = "0.9.0")
bazel_dep(name = "yq.bzl", version = "0.3.5")
bazel_dep(name = "rules_angular")
git_override(
module_name = "rules_angular",
commit = "d746c4f75e42cffe389d1ab077f4639be2bc78d1",
remote = "https://github.com/devversion/rules_angular.git",
commit = "cc27b644546c1b8f680f3e5a1000f7a127eef13b",
remote = "https://github.com/angular/rules_angular.git",
)
bazel_dep(name = "devinfra")
git_override(
module_name = "devinfra",
commit = "7c08ac2a4f396bad752829fba09dbaefbcded9fc",
commit = "9de194d77b66b6b3294e0f041e29985d2916e911",
remote = "https://github.com/angular/dev-infra.git",
)
bazel_dep(name = "rules_sass")
git_override(
module_name = "rules_sass",
commit = "1184a80751a21af8348f308abc5b38a41f26850e",
remote = "https://github.com/devversion/rules_sass.git",
commit = "6c5490b4da59c283f7d4a48f68615a513a352b10",
remote = "https://github.com/angular/rules_sass.git",
)
bazel_dep(name = "rules_browsers")
git_override(
module_name = "rules_browsers",
commit = "e08ae33c679d07b3b2fcc136658b787a81995bc5",
remote = "https://github.com/devversion/rules_browsers.git",
commit = "79771c96882a2aa5ad8a2311e858e1c9eddf786a",
remote = "https://github.com/angular/rules_browsers.git",
)
yq = use_extension("@yq.bzl//yq:extensions.bzl", "yq")
@@ -49,15 +49,15 @@ use_repo(yq, "yq_toolchains")
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(
node_repositories = {
"22.22.0-darwin_arm64": ("node-v22.22.0-darwin-arm64.tar.gz", "node-v22.22.0-darwin-arm64", "5ed4db0fcf1eaf84d91ad12462631d73bf4576c1377e192d222e48026a902640"),
"22.22.0-darwin_amd64": ("node-v22.22.0-darwin-x64.tar.gz", "node-v22.22.0-darwin-x64", "5ea50c9d6dea3dfa3abb66b2656f7a4e1c8cef23432b558d45fb538c7b5dedce"),
"22.22.0-linux_arm64": ("node-v22.22.0-linux-arm64.tar.xz", "node-v22.22.0-linux-arm64", "1bf1eb9ee63ffc4e5d324c0b9b62cf4a289f44332dfef9607cea1a0d9596ba6f"),
"22.22.0-linux_ppc64le": ("node-v22.22.0-linux-ppc64le.tar.xz", "node-v22.22.0-linux-ppc64le", "d83b9957431cc18e1fc143a4b99f89cde7b8a18f53ef392231b4336afd058865"),
"22.22.0-linux_s390x": ("node-v22.22.0-linux-s390x.tar.xz", "node-v22.22.0-linux-s390x", "5aa0e520689448c4233e8d73f284e8e0634fdcd32b479735698494be5641f3e4"),
"22.22.0-linux_amd64": ("node-v22.22.0-linux-x64.tar.xz", "node-v22.22.0-linux-x64", "9aa8e9d2298ab68c600bd6fb86a6c13bce11a4eca1ba9b39d79fa021755d7c37"),
"22.22.0-windows_amd64": ("node-v22.22.0-win-x64.zip", "node-v22.22.0-win-x64", "c97fa376d2becdc8863fcd3ca2dd9a83a9f3468ee7ccf7a6d076ec66a645c77a"),
"22.22.1-darwin_arm64": ("node-v22.22.1-darwin-arm64.tar.gz", "node-v22.22.1-darwin-arm64", "679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"),
"22.22.1-darwin_amd64": ("node-v22.22.1-darwin-x64.tar.gz", "node-v22.22.1-darwin-x64", "07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"),
"22.22.1-linux_arm64": ("node-v22.22.1-linux-arm64.tar.xz", "node-v22.22.1-linux-arm64", "0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"),
"22.22.1-linux_ppc64le": ("node-v22.22.1-linux-ppc64le.tar.xz", "node-v22.22.1-linux-ppc64le", "a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"),
"22.22.1-linux_s390x": ("node-v22.22.1-linux-s390x.tar.xz", "node-v22.22.1-linux-s390x", "e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"),
"22.22.1-linux_amd64": ("node-v22.22.1-linux-x64.tar.xz", "node-v22.22.1-linux-x64", "9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"),
"22.22.1-windows_amd64": ("node-v22.22.1-win-x64.zip", "node-v22.22.1-win-x64", "877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"),
},
node_version = "22.22.0",
node_version = "22.22.1",
)
use_repo(node, "nodejs_toolchains")
use_repo(node, "nodejs_darwin_amd64")
@@ -71,8 +71,8 @@ use_repo(node, "nodejs_windows_amd64")
pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm")
pnpm.pnpm(
name = "pnpm",
pnpm_version = "10.30.0",
pnpm_version_integrity = "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==",
pnpm_version = "10.32.1",
pnpm_version_integrity = "sha512-pwaTjw6JrBRWtlY+q07fHR+vM2jRGR/FxZeQ6W3JGORFarLmfWE94QQ9LoyB+HMD5rQNT/7KnfFe8a1Wc0jyvg==",
)
use_repo(pnpm, "pnpm")
@@ -117,9 +117,9 @@ use_repo(npm, "npm")
rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext")
rules_ts_ext.deps(
name = "angular_npm_typescript",
# Obtained by: curl --silent https://registry.npmjs.org/typescript/6.0.0-beta | jq -r '.dist.integrity'
ts_integrity = "sha512-CldZdztDpQRLM1HC6WDQjQkQN5Ub5zRau737a1diGh3lPmb9oRsaWHk1y5iqK0o7+1bNJ0oXfEGRkAogFZBL+Q==",
ts_version = "6.0.0-beta",
# Obtained by: curl --silent https://registry.npmjs.org/typescript/6.0.1-rc | jq -r '.dist.integrity'
ts_integrity = "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
ts_version = "5.9.3",
)
use_repo(rules_ts_ext, **{"npm_typescript": "angular_npm_typescript"})
+341 -485
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -5,21 +5,21 @@
"@algolia/requester-browser-xhr": "5.48.0",
"@algolia/requester-node-http": "5.48.0",
"@angular/animations": "workspace:*",
"@angular/aria": "21.2.0-rc.0",
"@angular/build": "21.2.0-next.2",
"@angular/cdk": "21.2.0-rc.0",
"@angular/cli": "21.2.0-next.2",
"@angular/aria": "21.2.2",
"@angular/build": "21.2.2",
"@angular/cdk": "21.2.2",
"@angular/cli": "21.2.2",
"@angular/common": "workspace:*",
"@angular/compiler": "workspace:*",
"@angular/compiler-cli": "workspace:*",
"@angular/core": "workspace:*",
"@angular/docs": "workspace:*",
"@angular/forms": "workspace:*",
"@angular/material": "21.2.0-rc.0",
"@angular/material": "21.2.2",
"@angular/platform-browser": "workspace:*",
"@angular/platform-server": "workspace:*",
"@angular/router": "workspace:*",
"@angular/ssr": "21.2.0-next.2",
"@angular/ssr": "21.2.2",
"@codemirror/autocomplete": "6.20.0",
"@codemirror/commands": "6.10.1",
"@codemirror/lang-angular": "0.1.4",
@@ -70,7 +70,7 @@
"hast-util-whitespace": "^3.0.0",
"html-void-elements": "^3.0.0",
"jsdom": "28.0.0",
"jasmine-core": "6.0.0",
"jasmine-core": "6.1.0",
"karma-chrome-launcher": "3.2.0",
"karma-coverage": "2.2.1",
"karma-jasmine": "5.1.0",
@@ -81,7 +81,7 @@
"open-in-idx": "0.1.1",
"playwright-core": "1.58.1",
"preact": "10.28.3",
"preact-render-to-string": "6.6.5",
"preact-render-to-string": "6.6.6",
"prettier": "3.8.1",
"property-information": "^7.1.0",
"rxjs": "7.8.2",
@@ -91,7 +91,7 @@
"style-mod": "4.1.3",
"tinyglobby": "0.2.15",
"tslib": "2.8.1",
"typescript": "6.0.0-beta",
"typescript": "5.9.3",
"w3c-keyname": "2.2.8",
"zwitch": "^2.0.4"
},
+1
View File
@@ -29,6 +29,7 @@ ts_project(
deps = [
"//adev:node_modules/@angular/docs",
"//adev:node_modules/@types/node",
"//adev/shared-docs/pipeline/shared:heading",
"//adev/src/app/routing/navigation-entries",
"//adev/src/content/reference/errors:route-nav-items",
"//adev/src/content/reference/extended-diagnostics:route-nav-items",
+1 -8
View File
@@ -7,6 +7,7 @@
*/
import {ALL_ITEMS} from '../../src/app/routing/navigation-entries/index.js';
import {getIdFromHeading} from '../../shared-docs/pipeline/shared/heading.mjs';
import {NavigationItem} from '@angular/docs';
import {writeFileSync, readFileSync} from 'fs';
import {join, resolve} from 'path';
@@ -72,11 +73,3 @@ function main() {
}
main();
// TODO: refactor so this function is shared with the generation pipeline (adev/shared-docs/pipeline/shared/marked/transformations/heading.mts)
function getIdFromHeading(heading: string): string {
return heading
.toLowerCase()
.replace(/\s|\//g, '-') // replace spaces and slashes with dashes
.replace(/[^\p{L}\d\-]/gu, ''); // only keep letters, digits & dashes
}
@@ -137,14 +137,14 @@ dialog {
.docs-search-results__start-typing,
.docs-search-results__no-results {
padding: 0.75rem;
color: var(--gray-400);
color: var(--quaternary-contrast);
}
.docs-search-footer {
display: flex;
align-items: center;
justify-content: space-between;
color: var(--gray-400);
color: var(--quaternary-contrast);
padding: 1rem;
font-size: 0.75rem;
font-weight: 500;
@@ -143,7 +143,7 @@
height: fit-content;
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
transition: color 0.3s ease;
}
@@ -87,7 +87,7 @@
fill="none"
>
<path
fill="var(--gray-400)"
fill="var(--quaternary-contrast)"
d="M3.4 22 2 20.6 8.6 14H4v-2h8v8h-2v-4.6L3.4 22ZM12 12V4h2v4.6L20.6 2 22 3.4 15.4 10H20v2h-8Z"
/>
</svg>
@@ -2,11 +2,11 @@
.docs-example-viewer-preview {
.docs-dark-mode & {
color: var(--primary-contrast);
background: var(--gray-900);
background: var(--primary-constrast);
}
@media screen and (prefers-color-scheme: dark) {
color: var(--primary-contrast);
background: var(--gray-900);
background: var(--primary-constrast);
}
.docs-light-mode & {
background: var(--page-background);
@@ -70,7 +70,7 @@
cursor: pointer;
height: 24px;
width: 24px;
color: var(--gray-400);
color: var(--quaternary-contrast);
path {
transition: fill 0.3s ease;
+2 -2
View File
@@ -1,6 +1,6 @@
load("@aspect_bazel_lib//lib:copy_to_bin.bzl", _copy_to_bin = "copy_to_bin")
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", _copy_to_directory = "copy_to_directory")
load("@aspect_rules_esbuild//esbuild:defs.bzl", _esbuild = "esbuild")
load("@bazel_lib//lib:copy_to_bin.bzl", _copy_to_bin = "copy_to_bin")
load("@bazel_lib//lib:copy_to_directory.bzl", _copy_to_directory = "copy_to_directory")
load("@devinfra//bazel/private:path_relative_to_label.bzl", _path_relative_to_label = "path_relative_to_label")
load(
"//tools:defaults.bzl",
@@ -43,15 +43,6 @@ describe('ClickOutside', () => {
expect(clickedOutsideSpy).not.toHaveBeenCalled();
});
it('should not docsClickOutside be emitted when user click inside `content` element', () => {
const clickedOutsideSpy = spyOn(component, 'clickedOutside');
const button = fixture.debugElement.query(By.css('button[id="ignoreThisButton"]'));
button.nativeElement.click();
expect(clickedOutsideSpy).not.toHaveBeenCalled();
});
});
@Component({
@@ -10,6 +10,15 @@ ts_project(
],
)
ts_project(
name = "heading",
srcs = ["heading.mts"],
visibility = [
"//adev/scripts/routes:__subpackages__",
"//adev/shared-docs/pipeline:__subpackages__",
],
)
ts_project(
name = "shiki",
srcs = ["shiki.mts"],
@@ -36,3 +45,17 @@ zoneless_jasmine_test(
name = "linking_test",
data = [":linking_test_lib"],
)
ts_project(
name = "heading_test_lib",
testonly = True,
srcs = ["test/heading.spec.mts"],
deps = [
":heading",
],
)
zoneless_jasmine_test(
name = "heading_test",
data = [":heading_test_lib"],
)
@@ -0,0 +1,29 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
/**
* Extracts the ID from a heading text.
* Supports custom ID syntax: `## My Heading {#custom-id}`
*/
export function getIdFromHeading(heading: string): string {
// extract the extended markdown heading id
// ex: ## MyHeading {# myId}
// This is recommended in case we end up having duplicate Ids but we still want the same heading text.
// We don't want to make Id generation stateful/too complex to handle duplicates automatically.
const customIdRegex = /{#\s*([\w-]+)\s*}/g;
const customId = customIdRegex.exec(heading)?.[1];
if (customId) {
return customId;
}
return heading
.toLowerCase()
.replace(/\s|\//g, '-') // replace spaces and slashes with dashes
.replace(/[^\p{L}\d\-]/gu, ''); // only keep letters, digits & dashes
}
@@ -30,6 +30,8 @@ const LINK_EXEMPT = new Set([
'Event',
'form',
'type',
'Host',
'filter',
]);
export function shouldLinkSymbol(symbol: string): boolean {
@@ -18,6 +18,7 @@ ts_project(
"//adev:node_modules/mermaid",
"//adev:node_modules/playwright-core",
"//adev:node_modules/shiki",
"//adev/shared-docs/pipeline/shared:heading",
"//adev/shared-docs/pipeline/shared:linking",
"//adev/shared-docs/pipeline/shared:shiki",
"//adev/shared-docs/pipeline/shared/regions",
@@ -21,7 +21,7 @@ interface DocsCardContainerToken extends Tokens.Generic {
// Capture group 1: all attributes on the opening tag
// Capture group 2: all content between the open and close tags
const cardContainerRule =
/^[^<]*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
/^\s*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
const headerTitleRule = /headerTitle="([^"]*)"/;
const headerImgSrcRule = /headerImgSrc="([^"]*)"/;
@@ -23,7 +23,7 @@ interface DocsCardToken extends Tokens.Generic {
// Capture group 1: all attributes on the opening tag
// Capture group 2: all content between the open and close tags
const cardRule = /^[^<]*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
const cardRule = /^\s*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
const titleRule = /title="([^"]*)"/;
const linkRule = /link="([^"]*)"/;
@@ -41,6 +41,7 @@ export const docsCodeBlockExtension = {
const headerRule = /header\s*:\s*(['"`])([^'"`]+)\1/; // The 2nd capture matters here
const highlightRule = /highlight\s*:\s*(.*)([^,])/;
const hideCopyRule = /hideCopy/;
const hideDollarRule = /hideDollar/;
const preferRule = /\b(prefer|avoid)\b/;
const linenumsRule = /linenums/;
@@ -52,6 +53,7 @@ export const docsCodeBlockExtension = {
header: headerRule.exec(metadataStr)?.[2],
highlight: highlightRule.exec(metadataStr)?.[1],
hideCopy: hideCopyRule.test(metadataStr),
hideDollar: hideDollarRule.test(metadataStr),
style: preferRule.exec(metadataStr)?.[1] as 'prefer' | 'avoid' | undefined,
linenums: linenumsRule.test(metadataStr),
};
@@ -32,6 +32,7 @@ const visibleLinesRule = /visibleLines="([^"]*)"/;
const regionRule = /region="([^"]*)"/;
const previewRule = /preview/;
const hideCodeRule = /hideCode/;
const hideDollarRule = /hideDollar/;
const preferRule = /\b(prefer|avoid)\b/;
export const docsCodeExtension = {
@@ -52,8 +53,9 @@ export const docsCodeExtension = {
const language = languageRule.exec(attr);
const visibleLines = visibleLinesRule.exec(attr);
const region = regionRule.exec(attr);
const preview = previewRule.exec(attr) ? true : false;
const hideCode = hideCodeRule.exec(attr) ? true : false;
const preview = previewRule.test(attr);
const hideCode = hideCodeRule.test(attr);
const hideDollar = hideDollarRule.test(attr);
const classes = classRule.exec(attr);
const style = preferRule.exec(attr);
@@ -78,6 +80,7 @@ export const docsCodeExtension = {
region: region?.[1],
preview: preview,
hideCode,
hideDollar,
style: style?.[1] as 'prefer' | 'avoid' | undefined,
classes: classes?.[1]?.split(' '),
};
@@ -39,6 +39,8 @@ export interface CodeToken extends Tokens.Generic {
highlight?: string;
/** Whether to hide the copy button */
hideCopy?: boolean;
/** Whether to hide the dollar sign in the shell code */
hideDollar?: boolean;
// additional classes for the element
classes?: string[];
@@ -132,6 +134,10 @@ function applyContainerAttributesAndClasses(el: Element, token: CodeToken) {
if (token.hideCopy) {
el.setAttribute('hideCopy', 'true');
}
if (token.hideDollar) {
el.setAttribute('hideDollar', 'true');
}
const language = token.language;
if (language === 'mermaid') {
@@ -11,7 +11,7 @@ import {chromium} from 'playwright-core';
import {Mermaid, MermaidConfig} from 'mermaid';
import {resolve, join} from 'path';
const runfilesDir = process.env['RUNFILES']!;
const runfilesDir = process.env['JS_BINARY__RUNFILES']!;
// Declare mermarid in the context of this file so that typescript doesn't get upset when we
// access it within the `page.evaluate` function. At runtime the context in with the method
// is run difference than this file, but this makes typescript happy.
@@ -1,4 +1,39 @@
Introductory paragraph that should be preserved before any card containers.
## First Section
This section contains important information about the feature status.
### Available features
- Feature one
- Feature two
- Feature three
### In progress
The following items are currently being developed:
1. Item A with description
2. Item B with description
<docs-card-container>
<docs-card></docs-card>
<docs-card></docs-card>
<docs-card title="Card One"></docs-card>
<docs-card title="Card Two"></docs-card>
</docs-card-container>
### Additional context
More text after the first card container that should also be preserved.
## Second Section
Another paragraph before the second card container.
<docs-card-container>
<docs-card title="Card Three"></docs-card>
</docs-card-container>
## Final Section
Concluding remarks at the end of the document.
@@ -20,10 +20,60 @@ describe('markdown to html', () => {
markdownDocument = JSDOM.fragment(await parseMarkdown(markdownContent, rendererContext));
});
it('creates card containers containing multiple cards', () => {
const containerEl = markdownDocument.querySelector('.docs-card-grid');
it('creates multiple card containers with correct card counts', () => {
const containers = markdownDocument.querySelectorAll('.docs-card-grid');
expect(containerEl!.children.length).toBe(2);
expect(containerEl!.classList.contains('docs-card-grid')).toBeTrue();
expect(containers.length).toBe(2);
expect(containers[0].children.length).toBe(2);
expect(containers[1].children.length).toBe(1);
});
it('preserves all h2 section headings', () => {
const h2Elements = markdownDocument.querySelectorAll('h2');
expect(h2Elements.length).toBe(3);
expect(h2Elements[0].textContent).toContain('First Section');
expect(h2Elements[1].textContent).toContain('Second Section');
expect(h2Elements[2].textContent).toContain('Final Section');
});
it('preserves all h3 subsection headings outside card containers', () => {
// Card titles also render as h3, so we filter to only h3s not inside card containers
const allH3s = Array.from(markdownDocument.querySelectorAll('h3'));
const sectionH3s = allH3s.filter((h3) => !h3.closest('.docs-card-grid'));
expect(sectionH3s.length).toBe(3);
expect(sectionH3s[0].textContent).toContain('Available features');
expect(sectionH3s[1].textContent).toContain('In progress');
expect(sectionH3s[2].textContent).toContain('Additional context');
});
it('preserves unordered lists before card containers', () => {
const ulElements = markdownDocument.querySelectorAll('ul');
expect(ulElements.length).toBeGreaterThanOrEqual(1);
expect(ulElements[0].children.length).toBe(3);
expect(ulElements[0].textContent).toContain('Feature one');
});
it('preserves ordered lists before card containers', () => {
const olElements = markdownDocument.querySelectorAll('ol');
expect(olElements.length).toBe(1);
expect(olElements[0].children.length).toBe(2);
expect(olElements[0].textContent).toContain('Item A');
});
it('preserves paragraphs throughout the document', () => {
const paragraphs = markdownDocument.querySelectorAll('p');
expect(paragraphs.length).toBeGreaterThanOrEqual(5);
const paragraphTexts = Array.from(paragraphs).map((p) => p.textContent);
expect(paragraphTexts.some((t) => t?.includes('Introductory paragraph'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('important information'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('More text after'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('Another paragraph'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('Concluding remarks'))).toBeTrue();
});
});
@@ -11,3 +11,7 @@ this is a code block
```
code block without language
```
```shell {hideDollar}
echo "hello"
```
@@ -27,10 +27,10 @@ describe('markdown to html', () => {
expect(codeBlock?.textContent?.trim()).toBe('this is a code block');
});
it('should parse all 3 code blocks', () => {
it('should parse all 4 code blocks', () => {
const codeBlocks = markdownDocument.querySelectorAll('.docs-code');
expect(codeBlocks.length).toBe(3);
expect(codeBlocks.length).toBe(4);
});
it('should deindent code blocks correctly', () => {
@@ -42,4 +42,9 @@ describe('markdown to html', () => {
const codeBlock = markdownDocument.querySelectorAll('.docs-code')[2];
expect(codeBlock).toBeDefined();
});
it('should parse the hideDollar attribute', () => {
const codeBlock = markdownDocument.querySelectorAll('.docs-code')[3];
expect(codeBlock.getAttribute('hideDollar')).toBe('true');
});
});
@@ -12,3 +12,5 @@ const form = {
state: ['']
};
</docs-code>
<docs-code hideDollar code="echo 'hello world'" />
@@ -52,4 +52,9 @@ describe('markdown to html', () => {
const codeBlock = markdownDocument.querySelectorAll('code')[4];
expect(codeBlock?.innerHTML).not.toContain('<a href="/api/animations/state">state</a>');
});
it('should parse the hideDollar attribute', () => {
const codeBlock = markdownDocument.querySelectorAll('.docs-code')[5];
expect(codeBlock.getAttribute('hideDollar')).toBe('true');
});
});
@@ -8,6 +8,7 @@
import {Tokens} from 'marked';
import {AdevDocsRenderer} from '../renderer.mjs';
import {getIdFromHeading} from '../../heading.mjs';
export function headingRender(
this: AdevDocsRenderer,
@@ -25,14 +26,7 @@ export function headingRender(
`;
}
// extract the extended markdown heading id
// ex: ## MyHeading {# myId}
// This is recommended in case we end up having duplicate Ids but we still want the same heading text.
// We don't want to make Id generation stateful/too complex to handle duplicates automatically.
const customIdRegex = /{#\s*([\w-]+)\s*}/g;
const customId = customIdRegex.exec(headingText)?.[1];
const link = customId ?? getIdFromHeading(headingText);
const link = getIdFromHeading(headingText);
// Replace code backticks and remove custom ID syntax from the displayed label
let label = parsedText.replace(/`(.*?)`/g, '<code>$1</code>');
@@ -67,10 +61,3 @@ export function getPageTitle(text: string, filePath?: string): string {
}
</div>`;
}
function getIdFromHeading(heading: string): string {
return heading
.toLowerCase()
.replace(/\s|\//g, '-') // replace spaces and slashes with dashes
.replace(/[^\p{L}\d\-]/gu, ''); // only keep letters, digits & dashes
}
@@ -0,0 +1,31 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {getIdFromHeading} from '../heading.mjs';
describe('getIdFromHeading', () => {
it('should generate id from simple text', () => {
expect(getIdFromHeading('My Heading')).toBe('my-heading');
});
it('should generate id from text with special characters', () => {
expect(getIdFromHeading('Step 2 - Add component')).toBe('step-2---add-component');
});
it('should extract custom id when present', () => {
expect(getIdFromHeading('My Heading {#custom-id}')).toBe('custom-id');
});
it('should extract custom id ignoring surrounding spaces', () => {
expect(getIdFromHeading('My Heading {# custom-id }')).toBe('custom-id');
});
it('should prioritize custom id over text content', () => {
expect(getIdFromHeading('Duplicate Heading {#unique-id}')).toBe('unique-id');
});
});
+9 -1
View File
@@ -51,7 +51,7 @@
}
.docs-reference-category {
color: var(--gray-400);
color: var(--quaternary-contrast);
font-size: 0.875rem;
font-weight: 500;
line-height: 1.4rem;
@@ -426,6 +426,14 @@
.docs-ref-content {
padding: 1rem 0;
.docs-ref-option-and-description {
.docs-reference-option {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
}
&:not(:first-child) {
border-block-start: 1px solid var(--senary-contrast);
}
+62 -61
View File
@@ -6,68 +6,66 @@
border-radius: 0.25rem;
margin: 1rem 0;
.docs-card-container-header {
align-items: flex-end;
border-bottom: 1px solid var(--senary-contrast);
display: flex;
justify-content: space-between;
.docs-card-container-header {
align-items: flex-end;
border-bottom: 1px solid var(--senary-contrast);
display: flex;
justify-content: space-between;
h2 {
padding: 2.5rem 1rem 2.5rem 2.5rem;
min-width: 350px;
h2 {
padding: 2.5rem 1rem 2.5rem 2.5rem;
min-width: 350px;
}
.theme-fill-bg {
fill: var(--page-background);
stroke: var(--primary-contrast);
}
.theme-fill-accent-bg {
fill: var(--septenary-contrast);
stroke: var(--primary-contrast);
}
.theme-stroke-primary {
stroke: var(--primary-contrast);
}
.theme-fill-primary {
fill: var(--primary-contrast);
}
.theme-fill-secondary {
fill: var(--octonary-contrast);
}
.theme-stroke-accent {
stroke: var(--vivid-pink);
}
.theme-fill-accent {
fill: var(--vivid-pink);
stroke: var(--primary-contrast);
}
.theme-stroke-secondary {
stroke: var(--senary-contrast);
}
.theme-fill-secondary {
fill: var(--senary-contrast);
}
.header-img {
margin-top: 5px;
overflow: hidden;
margin-bottom: -5px;
}
svg {
fill-opacity: 1;
@container header (max-width: 550px) {
display: none;
}
.theme-fill-bg {
fill: var(--page-background);
stroke: var(--primary-contrast);
}
.theme-fill-accent-bg {
fill: var(--septenary-contrast);
stroke: var(--primary-contrast);
}
.theme-stroke-primary {
stroke: var(--primary-contrast);
}
.theme-fill-primary {
fill: var(--primary-contrast);
}
.theme-fill-secondary {
fill: var(--octonary-contrast);
}
.theme-stroke-accent {
stroke: var(--vivid-pink);
}
.theme-fill-accent {
fill: var(--vivid-pink);
stroke: var(--primary-contrast);
}
.theme-stroke-secondary {
stroke: var(--senary-contrast);
}
.theme-fill-secondary {
fill: var(--senary-contrast);
}
.header-img {
margin-top: 5px;
overflow: hidden;
margin-bottom: -5px;
}
svg {
fill-opacity: 1;
@container header (max-width: 550px) {
display: none;
}
rect {
fill: transparent;
}
rect {
fill: transparent;
}
}
}
.docs-card-container-content {
margin: 1rem;
@@ -214,7 +212,10 @@
&:before {
content: '';
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
margin: -1px;
border-radius: inherit;
@@ -223,7 +224,7 @@
.docs-nav-card-title {
background: var(--pink-to-highlight-to-purple-to-blue-horizontal-gradient);
padding: 1.5rem 1.5rem .5rem;
padding: 1.5rem 1.5rem 0.5rem;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
@@ -264,11 +265,11 @@
gap: 8px;
h3 {
margin-block-end: .5rem;
margin-block-end: 0.5rem;
}
svg path {
fill: var(--gray-400);
fill: var(--quaternary-contrast);
}
}
+17 -8
View File
@@ -204,15 +204,24 @@ $code-font-size: 0.875rem;
white-space: nowrap;
}
.shiki .line {
&::before {
content: '$';
padding-inline-end: 0.5rem;
&:not([hideDollar]) {
.shiki {
.line {
&::before {
content: '$';
padding-inline-end: 0.5rem;
}
}
}
display: block;
}
&.hidden {
display: none;
.shiki {
.line {
display: block;
&.hidden {
display: none;
}
}
}
}
@@ -239,7 +248,7 @@ $code-font-size: 0.875rem;
opacity: 1;
path {
transition: fill 0.3s ease;
fill: var(--gray-400);
fill: var(--quaternary-contrast);
}
}
.docs-check {
@@ -41,3 +41,6 @@ export const setCookieConsent = (state: 'denied' | 'granted'): void => {
}
}
};
// This fixes the RollupError: Exported variable "global" is not defined.
export {};
+1 -1
View File
@@ -91,7 +91,7 @@
width: 100vw;
height: 100vh;
backdrop-filter: blur(2px);
background-color: color-mix(in srgb, var(--gray-1000) 5%, transparent);
background-color: color-mix(in srgb, var(--page-background) 5%, transparent);
z-index: 50;
visibility: hidden;
opacity: 0;
@@ -95,20 +95,27 @@
<div>
<h2>Community translations</h2>
<ul>
<!-- Sorted using Unicode Collation Algorithm (UCA) -->
<li>
<a href="https://angular.cn/" title="简体中文版">简体中文版</a>
<a href="https://angular.az/" title="Azərbaycanca">Azərbaycanca</a>
</li>
<li>
<a href="https://dev.angular.tw/" title="正體中文版">正體中文版</a>
<a href="https://angular-docs.tr/" title="Türkçe">Türkçe</a>
</li>
<li>
<a href="https://angular.jp/" title="日本語版">日本語版</a>
<a href="https://angular-docs.ru/" title="Русский">Русский</a>
</li>
<li>
<a href="https://angular.kr/" title="한국어">한국어</a>
</li>
<li>
<a href="https://angular-docs.ru/" title="Русский">Русский</a>
<a href="https://angular.jp/" title="日本語版">日本語版</a>
</li>
<li>
<a href="https://angular.cn/" title="简体中文版">简体中文版</a>
</li>
<li>
<a href="https://dev.angular.tw/" title="正體中文版">正體中文版</a>
</li>
</ul>
</div>
@@ -76,7 +76,6 @@
background-color 0.3s ease,
border-color 0.3s ease;
height: 100dvh;
padding-block-start: 1rem;
padding-block-end: 2rem;
box-sizing: border-box;
// Add a subtle border for the home page
@@ -108,6 +107,19 @@
color-mix(in srgb, var(--electric-violet), transparent 70%) 25%,
color-mix(in srgb, var(--bright-blue), transparent 60%) 90%
);
&::before {
content: '';
position: absolute;
opacity: 0.8;
width: 100%;
height: 100%;
background-color: var(--octonary-contrast);
z-index: -1;
}
.adev-version-button {
border: 1px solid var(--quinary-contrast);
}
}
&.adev-nav-primary--deprecated {
@@ -153,6 +165,7 @@
list-style: none;
display: flex;
flex-direction: column;
padding-block-start: 1rem;
@include mq.for-tablet {
flex-direction: row;
@@ -159,7 +159,7 @@
.docs-delete-file,
.docs-rename-file {
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
transition: color 0.3s ease;
font-size: 1.2rem;
}
@@ -270,7 +270,7 @@
border-inline-start: 1px solid var(--senary-contrast);
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
transition: color 0.3s ease;
font-size: 1.3rem;
}
@@ -106,7 +106,7 @@ $width-breakpoint: 950px;
z-index: var(--z-index-content);
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
margin: auto;
font-size: 1.3rem;
transition: color 0.3s ease;
@@ -120,7 +120,7 @@ $width-breakpoint: 950px;
&:disabled {
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
}
}
}
@@ -3,7 +3,7 @@
.docs-dark-mode & {
.adev-embedded-editor-preview-container {
background: var(--gray-100);
background: var(--primary-constrast);
}
}
@@ -19,6 +19,10 @@
gap: 2rem;
padding: 1.5rem;
}
@include mq.for-phone-only {
padding: 1rem;
}
}
.step-description {
@@ -42,6 +46,7 @@
display: flex;
flex-direction: column;
gap: 1.5rem;
min-width: 0;
.code-block {
background: var(--card-background);
@@ -19,6 +19,10 @@
gap: 2rem;
padding: 1.5rem;
}
@include mq.for-phone-only {
padding: 1rem;
}
}
.step-description {
@@ -10,7 +10,7 @@
<div class="demo-display">
<input
[value]="searchTerm()"
(input)="onSearch($event)"
(input)="onSearch($event.target.value)"
placeholder="Search for fruit..."
class="demo-input"
/>
@@ -19,6 +19,10 @@
gap: 2rem;
padding: 1.5rem;
}
@include mq.for-phone-only {
padding: 1rem;
}
}
.step-description {
@@ -35,12 +35,13 @@ export class SignalsDemo {
// A computed signal that derives the filtered list.
// It automatically re-runs when a dependency changes.
filteredItems = computed(() =>
this.items().filter((item) => item.toLowerCase().includes(this.searchTerm().toLowerCase())),
);
filteredItems = computed(() => {
const lowerCaseSearchTerm = this.searchTerm().toLowerCase();
return this.items().filter((item) => item.toLowerCase().includes(lowerCaseSearchTerm));
});
onSearch(event: Event) {
this.searchTerm.set((event.target as HTMLInputElement).value);
onSearch(searchTerm: string) {
this.searchTerm.set(searchTerm);
}
}
@@ -50,20 +51,19 @@ items = signal(['Apple', 'Banana', /*...*/ ]);
searchTerm = signal('');
// A computed signal that derives the filtered list.
// It automatically re-runs when a dependency changes.
filteredItems = computed(() =>
this.items.filter(item =>
item.toLowerCase().includes (
this.searchTerm().toLowerCase()
)
)
) ;
filteredItems = computed(() => {
const lowerCaseSearchTerm = this.searchTerm().toLowerCase();
return this.items().filter(item =>
item.toLowerCase().includes(lowerCaseSearchTerm)
);
});
`.trim();
const htmlExample = `
<input [valuel="searchTerm()" (input)="searchTerm.set($event)" />
<input [value]="searchTerm()" (input)="searchTerm.set($event.target.value)" />
<ul>
@for (item of filteredItems (); track item) {
<li>{{ item }}</Li>
@for (item of filteredItems(); track $index) {
<li>{{ item }}</li>
}
</ul>
`.trim();
@@ -345,6 +345,10 @@ section {
min-height: 100px;
width: 25%;
box-sizing: border-box;
@include mq.for-phone-only {
padding: 0.5rem;
}
}
}
@@ -110,7 +110,7 @@
var(--symbolic-yellow) var(--item-attr-base-mix),
var(--octonary-contrast)
);
color: var(--gray-1000);
color: var(--page-background);
}
&.adev-experimental {
@@ -119,7 +119,7 @@
var(--symbolic-green) var(--item-attr-base-mix),
var(--octonary-contrast)
);
color: var(--gray-1000);
color: var(--page-background);
}
&.adev-deprecated {
@@ -25,6 +25,7 @@
border-block-end: 1px solid var(--senary-contrast);
padding-block-end: 2rem;
margin-block-end: 1rem;
-webkit-tap-highlight-color: transparent;
.adev-reference-list-type-filter-label {
margin-block: 2.5rem 1rem;
@@ -25,7 +25,7 @@
display: flex;
align-items: center;
justify-content: flex-end;
color: var(--gray-400);
color: var(--quaternary-contrast);
background-color: var(--page-background);
border-block-start: 1px solid var(--senary-contrast);
border-radius: 0 0 0.25rem 0.25rem;
@@ -1,4 +1,4 @@
<div class="page docs-viewer">
<main class="page docs-viewer">
<h1 class="page-header" tabindex="-1">Update Guide</h1>
<div class="wizard">
<div>
@@ -205,4 +205,4 @@
}
</div>
}
</div>
</main>
@@ -46,8 +46,6 @@ h4 {
}
.wizard {
padding-inline: 1rem;
.show-button {
display: block;
margin-block-start: 2rem;
@@ -163,9 +161,15 @@ h4 {
}
}
.adev-complexity-1 { --badge-color: var(--super-green); }
.adev-complexity-2 { --badge-color: var(--bright-blue); }
.adev-complexity-3 { --badge-color: var(--symbolic-orange); }
.adev-complexity-1 {
--badge-color: var(--super-green);
}
.adev-complexity-2 {
--badge-color: var(--bright-blue);
}
.adev-complexity-3 {
--badge-color: var(--symbolic-orange);
}
// Code blocks are generable from the markdown, we need to opt-out of the scoping
::ng-deep code {
@@ -341,6 +341,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
path: 'guide/di/di-in-action',
contentPath: 'guide/di/di-in-action',
},
{
label: 'Debugging and troubleshooting DI',
path: 'guide/di/debugging-and-troubleshooting-di',
contentPath: 'guide/di/debugging-and-troubleshooting-di',
status: 'new',
},
],
},
{
@@ -357,6 +363,11 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
path: 'guide/routing/define-routes',
contentPath: 'guide/routing/define-routes',
},
{
label: 'Route Loading Strategies',
path: 'guide/routing/loading-strategies',
contentPath: 'guide/routing/loading-strategies',
},
{
label: 'Show routes with Outlets',
path: 'guide/routing/show-routes-with-outlets',
@@ -1080,6 +1091,12 @@ export const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
},
// Loading Performance
{
label: 'Lazy-loaded routes',
path: 'best-practices/performance/lazy-loaded-routes',
contentPath: 'guide/routing/loading-strategies',
category: 'Loading Performance',
},
{
label: 'Deferred loading with @defer',
path: 'best-practices/performance/defer',
+2 -2
View File
@@ -1,4 +1,4 @@
{
"branchName": "refs/heads/main",
"sha": "a68740532edcf94dafd4a6862a8985f506718016"
"branchName": "refs/heads/21.2.x",
"sha": "0707c69d63e9962bab077dbc45770c25c8d26b7c"
}
+87 -48
View File
@@ -44,16 +44,6 @@
"description": "A global unique identifier for the panel.",
"jsdocTags": []
},
{
"name": "panelId",
"type": "InputSignal<string>",
"memberType": "property",
"memberTags": [
"readonly"
],
"description": "A local unique identifier for the panel, used to match with its trigger's `panelId`.",
"jsdocTags": []
},
{
"name": "visible",
"type": "Signal<boolean>",
@@ -165,7 +155,7 @@
}
],
"generics": [],
"description": "The content panel of an accordion item that is conditionally visible.\n\nThis directive is a container for the content that is shown or hidden. It requires\na `panelId` that must match the `panelId` of its corresponding `ngAccordionTrigger`.\nThe content within the panel should be provided using an `ng-template` with the\n`ngAccordionContent` directive so that the content is not rendered on the page until the trigger\nis expanded. It applies `role=\"region\"` for accessibility and uses the `inert` attribute to hide\nits content from assistive technologies when not visible.\n\n```html\n<div ngAccordionPanel panelId=\"unique-id-1\">\n <ng-template ngAccordionContent>\n <p>This content is lazily rendered and will be shown when the panel is expanded.</p>\n </ng-template>\n</div>\n```",
"description": "The content panel of an accordion item that is conditionally visible.\n\nThis directive is a container for the content that is shown or hidden. It should\nexpose a template reference that will be used by the corresponding `ngAccordionTrigger`.\nThe content within the panel should be provided using an `ng-template` with the\n`ngAccordionContent` directive so that the content is not rendered on the page until the trigger\nis expanded. It applies `role=\"region\"` for accessibility and uses the `inert` attribute to hide\nits content from assistive technologies when not visible.\n\n```html\n<div ngAccordionPanel #panel=\"ngAccordionPanel\">\n <ng-template ngAccordionContent>\n <p>This content is lazily rendered and will be shown when the panel is expanded.</p>\n </ng-template>\n</div>\n```",
"jsdocTags": [
{
"name": "developerPreview",
@@ -176,12 +166,12 @@
"comment": "[Accordion](guide/aria/accordion)"
}
],
"rawComment": "/**\n * The content panel of an accordion item that is conditionally visible.\n *\n * This directive is a container for the content that is shown or hidden. It requires\n * a `panelId` that must match the `panelId` of its corresponding `ngAccordionTrigger`.\n * The content within the panel should be provided using an `ng-template` with the\n * `ngAccordionContent` directive so that the content is not rendered on the page until the trigger\n * is expanded. It applies `role=\"region\"` for accessibility and uses the `inert` attribute to hide\n * its content from assistive technologies when not visible.\n *\n * ```html\n * <div ngAccordionPanel panelId=\"unique-id-1\">\n * <ng-template ngAccordionContent>\n * <p>This content is lazily rendered and will be shown when the panel is expanded.</p>\n * </ng-template>\n * </div>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"rawComment": "/**\n * The content panel of an accordion item that is conditionally visible.\n *\n * This directive is a container for the content that is shown or hidden. It should\n * expose a template reference that will be used by the corresponding `ngAccordionTrigger`.\n * The content within the panel should be provided using an `ng-template` with the\n * `ngAccordionContent` directive so that the content is not rendered on the page until the trigger\n * is expanded. It applies `role=\"region\"` for accessibility and uses the `inert` attribute to hide\n * its content from assistive technologies when not visible.\n *\n * ```html\n * <div ngAccordionPanel #panel=\"ngAccordionPanel\">\n * <ng-template ngAccordionContent>\n * <p>This content is lazily rendered and will be shown when the panel is expanded.</p>\n * </ng-template>\n * </div>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"implements": [],
"source": {
"filePath": "/src/aria/accordion/accordion-panel.ts",
"startLine": 42,
"endLine": 103
"startLine": 34,
"endLine": 88
}
},
{
@@ -199,6 +189,19 @@
"description": "A reference to the trigger element.",
"jsdocTags": []
},
{
"name": "panel",
"type": "InputSignal<AccordionPanel>",
"memberType": "property",
"memberTags": [
"readonly",
"input"
],
"description": "The associated AccordionPanel.",
"jsdocTags": [],
"inputAlias": "panel",
"isRequiredInput": true
},
{
"name": "id",
"type": "InputSignal<any>",
@@ -207,23 +210,20 @@
"readonly",
"input"
],
"description": "A unique identifier for the widget.",
"description": "The unique identifier for the trigger.",
"jsdocTags": [],
"inputAlias": "id",
"isRequiredInput": false
},
{
"name": "panelId",
"type": "InputSignal<string>",
"type": "Signal<any>",
"memberType": "property",
"memberTags": [
"readonly",
"input"
"readonly"
],
"description": "A local unique identifier for the trigger, used to match with its panel's `panelId`.",
"jsdocTags": [],
"inputAlias": "panelId",
"isRequiredInput": true
"description": "The unique identifier for the correspondingtrigger panel.",
"jsdocTags": []
},
{
"name": "disabled",
@@ -263,6 +263,39 @@
"description": "Whether the trigger is active.",
"jsdocTags": []
},
{
"name": "ngOnInit",
"signatures": [
{
"name": "ngOnInit",
"entryType": "function",
"description": "",
"generics": [],
"isNewType": false,
"jsdocTags": [],
"params": [],
"rawComment": "",
"returnType": "void"
}
],
"implementation": {
"params": [],
"isNewType": false,
"returnType": "void",
"generics": [],
"name": "ngOnInit",
"description": "",
"entryType": "function",
"jsdocTags": [],
"rawComment": ""
},
"entryType": "function",
"description": "",
"jsdocTags": [],
"rawComment": "",
"memberType": "method",
"memberTags": []
},
{
"name": "expand",
"signatures": [
@@ -364,7 +397,7 @@
}
],
"generics": [],
"description": "The trigger that toggles the visibility of its associated `ngAccordionPanel`.\n\nThis directive requires a `panelId` that must match the `panelId` of the `ngAccordionPanel` it\ncontrols. When clicked, it will expand or collapse the panel. It also handles keyboard\ninteractions for navigation within the `ngAccordionGroup`. It applies `role=\"button\"` and manages\n`aria-expanded`, `aria-controls`, and `aria-disabled` attributes for accessibility.\nThe `disabled` input can be used to disable the trigger.\n\n```html\n<button ngAccordionTrigger panelId=\"unique-id-1\">\n Accordion Trigger Text\n</button>\n```",
"description": "The trigger that toggles the visibility of its associated `ngAccordionPanel`.\n\nThis directive requires the `panel` input be set to the template reference of the `ngAccordionPanel`\nit controls. When clicked, it will expand or collapse the panel. It also handles keyboard\ninteractions for navigation within the `ngAccordionGroup`. It applies `role=\"button\"` and manages\n`aria-expanded`, `aria-controls`, and `aria-disabled` attributes for accessibility.\nThe `disabled` input can be used to disable the trigger.\n\n```html\n<button ngAccordionTrigger [panel]=\"panel\">\n Accordion Trigger Text\n</button>\n```",
"jsdocTags": [
{
"name": "developerPreview",
@@ -375,8 +408,10 @@
"comment": "[Accordion](guide/aria/accordion)"
}
],
"rawComment": "/**\n * The trigger that toggles the visibility of its associated `ngAccordionPanel`.\n *\n * This directive requires a `panelId` that must match the `panelId` of the `ngAccordionPanel` it\n * controls. When clicked, it will expand or collapse the panel. It also handles keyboard\n * interactions for navigation within the `ngAccordionGroup`. It applies `role=\"button\"` and manages\n * `aria-expanded`, `aria-controls`, and `aria-disabled` attributes for accessibility.\n * The `disabled` input can be used to disable the trigger.\n *\n * ```html\n * <button ngAccordionTrigger panelId=\"unique-id-1\">\n * Accordion Trigger Text\n * </button>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"implements": [],
"rawComment": "/**\n * The trigger that toggles the visibility of its associated `ngAccordionPanel`.\n *\n * This directive requires the `panel` input be set to the template reference of the `ngAccordionPanel`\n * it controls. When clicked, it will expand or collapse the panel. It also handles keyboard\n * interactions for navigation within the `ngAccordionGroup`. It applies `role=\"button\"` and manages\n * `aria-expanded`, `aria-controls`, and `aria-disabled` attributes for accessibility.\n * The `disabled` input can be used to disable the trigger.\n *\n * ```html\n * <button ngAccordionTrigger [panel]=\"panel\">\n * Accordion Trigger Text\n * </button>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"implements": [
"OnInit"
],
"isStandalone": true,
"selector": "[ngAccordionTrigger]",
"exportAs": [
@@ -388,7 +423,7 @@
"source": {
"filePath": "/src/aria/accordion/accordion-trigger.ts",
"startLine": 42,
"endLine": 107
"endLine": 112
}
},
{
@@ -536,7 +571,7 @@
}
],
"generics": [],
"description": "A container for a group of accordion items. It manages the overall state and\ninteractions of the accordion, such as keyboard navigation and expansion mode.\n\nThe `ngAccordionGroup` serves as the root of a group of accordion triggers and panels,\ncoordinating the behavior of the `ngAccordionTrigger` and `ngAccordionPanel` elements within it.\nIt supports both single and multiple expansion modes.\n\n```html\n<div ngAccordionGroup [multiExpandable]=\"true\" [(expandedPanels)]=\"expandedItems\">\n <div class=\"accordion-item\">\n <h3>\n <button ngAccordionTrigger panelId=\"item-1\">Item 1</button>\n </h3>\n <div ngAccordionPanel panelId=\"item-1\">\n <ng-template ngAccordionContent>\n <p>Content for Item 1.</p>\n </ng-template>\n </div>\n </div>\n <div class=\"accordion-item\">\n <h3>\n <button ngAccordionTrigger panelId=\"item-2\">Item 2</button>\n </h3>\n <div ngAccordionPanel panelId=\"item-2\">\n <ng-template ngAccordionContent>\n <p>Content for Item 2.</p>\n </ng-template>\n </div>\n </div>\n</div>\n```",
"description": "A container for a group of accordion items. It manages the overall state and\ninteractions of the accordion, such as keyboard navigation and expansion mode.\n\nThe `ngAccordionGroup` serves as the root of a group of accordion triggers and panels,\ncoordinating the behavior of the `ngAccordionTrigger` and `ngAccordionPanel` elements within it.\nIt supports both single and multiple expansion modes.\n\n```html\n<div ngAccordionGroup [multiExpandable]=\"true\">\n <div class=\"accordion-item\">\n <h3>\n <button ngAccordionTrigger [panel]=\"panel1\">Item 1</button>\n </h3>\n <div ngAccordionPanel #panel1=\"ngAccordionPanel\">\n <ng-template ngAccordionContent>\n <p>Content for Item 1.</p>\n </ng-template>\n </div>\n </div>\n <div class=\"accordion-item\">\n <h3>\n <button ngAccordionTrigger [panel]=\"panel2\">Item 2</button>\n </h3>\n <div ngAccordionPanel #panel2=\"ngAccordionPanel\">\n <ng-template ngAccordionContent>\n <p>Content for Item 2.</p>\n </ng-template>\n </div>\n </div>\n</div>\n```",
"jsdocTags": [
{
"name": "developerPreview",
@@ -547,7 +582,7 @@
"comment": "[Accordion](guide/aria/accordion)"
}
],
"rawComment": "/**\n * A container for a group of accordion items. It manages the overall state and\n * interactions of the accordion, such as keyboard navigation and expansion mode.\n *\n * The `ngAccordionGroup` serves as the root of a group of accordion triggers and panels,\n * coordinating the behavior of the `ngAccordionTrigger` and `ngAccordionPanel` elements within it.\n * It supports both single and multiple expansion modes.\n *\n * ```html\n * <div ngAccordionGroup [multiExpandable]=\"true\" [(expandedPanels)]=\"expandedItems\">\n * <div class=\"accordion-item\">\n * <h3>\n * <button ngAccordionTrigger panelId=\"item-1\">Item 1</button>\n * </h3>\n * <div ngAccordionPanel panelId=\"item-1\">\n * <ng-template ngAccordionContent>\n * <p>Content for Item 1.</p>\n * </ng-template>\n * </div>\n * </div>\n * <div class=\"accordion-item\">\n * <h3>\n * <button ngAccordionTrigger panelId=\"item-2\">Item 2</button>\n * </h3>\n * <div ngAccordionPanel panelId=\"item-2\">\n * <ng-template ngAccordionContent>\n * <p>Content for Item 2.</p>\n * </ng-template>\n * </div>\n * </div>\n * </div>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"rawComment": "/**\n * A container for a group of accordion items. It manages the overall state and\n * interactions of the accordion, such as keyboard navigation and expansion mode.\n *\n * The `ngAccordionGroup` serves as the root of a group of accordion triggers and panels,\n * coordinating the behavior of the `ngAccordionTrigger` and `ngAccordionPanel` elements within it.\n * It supports both single and multiple expansion modes.\n *\n * ```html\n * <div ngAccordionGroup [multiExpandable]=\"true\">\n * <div class=\"accordion-item\">\n * <h3>\n * <button ngAccordionTrigger [panel]=\"panel1\">Item 1</button>\n * </h3>\n * <div ngAccordionPanel #panel1=\"ngAccordionPanel\">\n * <ng-template ngAccordionContent>\n * <p>Content for Item 1.</p>\n * </ng-template>\n * </div>\n * </div>\n * <div class=\"accordion-item\">\n * <h3>\n * <button ngAccordionTrigger [panel]=\"panel2\">Item 2</button>\n * </h3>\n * <div ngAccordionPanel #panel2=\"ngAccordionPanel\">\n * <ng-template ngAccordionContent>\n * <p>Content for Item 2.</p>\n * </ng-template>\n * </div>\n * </div>\n * </div>\n * ```\n *\n * @developerPreview 21.0\n * @see [Accordion](guide/aria/accordion)\n */",
"implements": [],
"isStandalone": true,
"selector": "[ngAccordionGroup]",
@@ -559,8 +594,8 @@
],
"source": {
"filePath": "src/aria/accordion/accordion-group.ts",
"startLine": 62,
"endLine": 158
"startLine": 60,
"endLine": 120
}
}
],
@@ -569,28 +604,20 @@
"Directive",
"@angular/core"
],
[
"input",
"@angular/core"
],
[
"inject",
"@angular/core"
],
[
"afterRenderEffect",
"@angular/core"
],
[
"signal",
"@angular/core"
],
[
"computed",
"@angular/core"
],
[
"WritableSignal",
"inject",
"@angular/core"
],
[
"input",
"@angular/core"
],
[
@@ -602,17 +629,25 @@
"@angular/core"
],
[
"model",
"OnInit",
"@angular/core"
],
[
"booleanAttribute",
"@angular/core"
],
[
"model",
"@angular/core"
],
[
"contentChildren",
"@angular/core"
],
[
"signal",
"@angular/core"
],
[
"Directionality",
"@angular/cdk/bidi"
@@ -645,10 +680,6 @@
"AccordionPanel.id",
"@angular/aria/accordion"
],
[
"AccordionPanel.panelId",
"@angular/aria/accordion"
],
[
"AccordionPanel.visible",
"@angular/aria/accordion"
@@ -673,6 +704,10 @@
"AccordionTrigger.element",
"@angular/aria/accordion"
],
[
"AccordionTrigger.panel",
"@angular/aria/accordion"
],
[
"AccordionTrigger.id",
"@angular/aria/accordion"
@@ -693,6 +728,10 @@
"AccordionTrigger.active",
"@angular/aria/accordion"
],
[
"AccordionTrigger.ngOnInit",
"@angular/aria/accordion"
],
[
"AccordionTrigger.expand",
"@angular/aria/accordion"
+2 -2
View File
@@ -275,7 +275,7 @@
"source": {
"filePath": "src/aria/grid/grid-cell-widget.ts",
"startLine": 42,
"endLine": 134
"endLine": 135
}
},
{
@@ -446,7 +446,7 @@
"source": {
"filePath": "/src/aria/grid/grid.ts",
"startLine": 48,
"endLine": 177
"endLine": 178
}
},
{
@@ -6,12 +6,12 @@ Angular includes many optimizations out of the box, but as applications grow, yo
Loading performance determines how quickly your application becomes visible and interactive. Slow loading directly impacts [Core Web Vitals](https://web.dev/vitals/) like Largest Contentful Paint (LCP) and Time to First Byte (TTFB).
| Technique | What it does | When to use it |
| :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- |
| [Lazy-loaded routes](guide/routing/define-routes#lazily-loaded-components-and-routes) | Defers loading route components until navigation, reducing the initial bundle size | Applications with multiple routes where not all are needed on initial load |
| [Deferred loading with `@defer`](best-practices/performance/defer) | Splits components into separate bundles that load on demand | Components not visible on initial render, heavy third-party libraries, below-the-fold content |
| [Image optimization](best-practices/performance/image-optimization) | Prioritizes LCP images, lazy loads others, generates responsive `srcset` attributes | Any application that displays images |
| [Server-side rendering](best-practices/performance/ssr) | Renders pages on the server for faster first paint and better SEO, with [hydration](guide/hydration) to restore interactivity and [incremental hydration](guide/incremental-hydration) to defer hydrating sections until needed | Content-heavy applications, pages that need search engine indexing |
| Technique | What it does | When to use it |
| :------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- |
| [Lazy-loaded routes](best-practices/performance/lazy-loaded-routes#lazily-loaded-components-and-routes) | Defers loading route components until navigation, reducing the initial bundle size | Applications with multiple routes where not all are needed on initial load |
| [Deferred loading with `@defer`](best-practices/performance/defer) | Splits components into separate bundles that load on demand | Components not visible on initial render, heavy third-party libraries, below-the-fold content |
| [Image optimization](best-practices/performance/image-optimization) | Prioritizes LCP images, lazy loads others, generates responsive `srcset` attributes | Any application that displays images |
| [Server-side rendering](best-practices/performance/ssr) | Renders pages on the server for faster first paint and better SEO, with [hydration](guide/hydration) to restore interactivity and [incremental hydration](guide/incremental-hydration) to defer hydrating sections until needed | Content-heavy applications, pages that need search engine indexing |
## Runtime performance
+1 -1
View File
@@ -1,4 +1,4 @@
{
"branchName": "refs/heads/main",
"branchName": "refs/heads/21.2.x",
"sha": "fc8b94d631a5d105a87abc2a008a6e8f76d7f3f5"
}
+2 -2
View File
@@ -1,4 +1,4 @@
{
"branchName": "refs/heads/main",
"sha": "8e9555870edb3275b35d299613ef3cf9d3bfb73a"
"branchName": "refs/heads/21.2.x",
"sha": "5bf3b735e2f5c6d63b124917c60d32374215fd0d"
}
+2 -2
View File
@@ -109,7 +109,7 @@
"aliases": [
"s"
],
"description": "Include the styles for the root component directly within the `app.component.ts` file. Only CSS styles can be included inline. By default, a separate stylesheet file (e.g., `app.component.css`) is created."
"description": "Include the styles for the root component directly within the `app.ts` file. Only CSS styles can be included inline. By default, a separate stylesheet file (e.g., `app.css`) is created."
},
{
"name": "inline-template",
@@ -117,7 +117,7 @@
"aliases": [
"t"
],
"description": "Include the HTML template for the root component directly within the `app.component.ts` file. By default, a separate template file (e.g., `app.component.html`) is created."
"description": "Include the HTML template for the root component directly within the `app.ts` file. By default, a separate template file (e.g., `app.html`) is created."
},
{
"name": "minimal",
+2 -2
View File
@@ -91,7 +91,7 @@
"aliases": [
"s"
],
"description": "Include the styles for the initial application's root component directly within the `app.component.ts` file. By default, a separate stylesheet file (e.g., `app.component.css`) is created."
"description": "Include the styles for the initial application's root component directly within the `app.ts` file. By default, a separate stylesheet file (e.g., `app.css`) is created."
},
{
"name": "inline-template",
@@ -99,7 +99,7 @@
"aliases": [
"t"
],
"description": "Include the HTML template for the initial application's root component directly within the `app.component.ts` file. By default, a separate template file (e.g., `app.component.html`) is created."
"description": "Include the HTML template for the initial application's root component directly within the `app.ts` file. By default, a separate template file (e.g., `app.html`) is created."
},
{
"name": "interactive",
+1 -1
View File
@@ -3,7 +3,7 @@
"command": "ng update [packages..]",
"shortDescription": "Updates your workspace and its dependencies. See https://update.angular.dev/.",
"longDescriptionRelativePath": "@angular/cli/src/commands/update/long-description.md",
"longDescription": "Perform a basic update to the current stable release of the core framework and CLI by running the following command.\n\n```\nng update @angular/cli @angular/core\n```\n\nTo update to the next beta or pre-release version, use the `--next` option.\n\nTo update from one major version to another, use the format\n\n```\nng update @angular/cli@^<major_version> @angular/core@^<major_version>\n```\n\nWe recommend that you always update to the latest patch version, as it contains fixes we released since the initial major release.\nFor example, use the following command to take the latest 10.x.x version and use that to update.\n\n```\nng update @angular/cli@^10 @angular/core@^10\n```\n\nFor detailed information and guidance on updating your application, see the interactive [Angular Update Guide](https://update.angular.dev/).\n",
"longDescription": "Perform a basic update to the current stable release of the core framework and CLI by running the following command.\n\n```\nng update @angular/cli @angular/core\n```\n\nTo update to the next beta or pre-release version, use the `--next` option.\n\nTo update from one major version to another, use the format\n\n```\nng update @angular/cli@^<major_version> @angular/core@^<major_version>\n```\n\nWe recommend that you always update to the latest patch version, as it contains fixes we released since the initial major release.\nFor example, use the following command to take the latest 21.x.x version and use that to update.\n\n```\nng update @angular/cli@^21 @angular/core@^21\n```\n\nFor detailed information and guidance on updating your application, see the interactive [Angular Update Guide](/update-guide).\n",
"aliases": [],
"deprecated": false,
"options": [
@@ -10,7 +10,7 @@ There are some niche use cases when you may want to maintain a custom build pipe
- You have an existing app using a different toolchain and you’d like to add Angular to it
- You’re strongly coupled to [module federation](https://module-federation.io/) and unable to adopt bundler-agnostic [native federation](https://www.npmjs.com/package/@angular-architects/native-federation)
- You’d like to create an short-lived experiment using your favorite build tool
- You’d like to create a short-lived experiment using your favorite build tool
## What are the options?
@@ -47,7 +47,7 @@ If you don't provide an `initialValue`, the resulting signal will return `undefi
Some Observables are guaranteed to emit synchronously, such as `BehaviorSubject`. In those cases, you can specify the `requireSync: true` option.
When `requiredSync` is `true`, `toSignal` enforces that the Observable emits synchronously on subscription. This guarantees that the signal always has a value, and no `undefined` type or initial value is required.
When `requireSync` is `true`, `toSignal` enforces that the Observable emits synchronously on subscription. This guarantees that the signal always has a value, and no `undefined` type or initial value is required.
### `manualCleanup`
@@ -1,13 +1,12 @@
<!-- #docplaster -->
<h2><code>animate.leave</code> Parent Sub-tree No Animation Example</h2>
<h2><code>animate.leave</code> Parent Sub-tree Animation Example</h2>
<button type="button" class="toggle-btn" (click)="toggle()">Toggle Element</button>
@if (isShown()) {
<!-- the child node with `animate.leave` will not animate out because the
parent node removal happens first and will take the child dom tree
with it. -->
<div class="leave-parent">
<!-- the child node with `animate.leave` will animate first
before the parent node is removed from the DOM. -->
<div class="leave-container" animate.leave="leaving">
<p>Goodbye</p>
</div>
@@ -6,28 +6,28 @@
justify-content: center;
font-family: 'Press Start 2P';
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000));
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--page-background));
--retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white);
--retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
--retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
--retro-elevated-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--quaternary-contrast),
0px 4px 0px 0px var(--quaternary-contrast), -4px 0px 0px 0px var(--quaternary-contrast),
0px -4px 0px 0px var(--quaternary-contrast);
--retro-flat-shadow:
4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700),
-4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700);
4px 0px 0px 0px var(--quaternary-contrast), 0px 4px 0px 0px var(--quaternary-contrast),
-4px 0px 0px 0px var(--quaternary-contrast), 0px -4px 0px 0px var(--quaternary-contrast);
--retro-clickable-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--quaternary-contrast),
0px 4px 0px 0px var(--quaternary-contrast), -4px 0px 0px 0px var(--quaternary-contrast),
0px -4px 0px 0px var(--quaternary-contrast), 8px 8px 0px 0px var(--quaternary-contrast);
--retro-pressed-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-dark),
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--quaternary-contrast),
0px 4px 0px 0px var(--quaternary-contrast), -4px 0px 0px 0px var(--quaternary-contrast),
0px -4px 0px 0px var(--quaternary-contrast), 0px 0px 0px 0px var(--quaternary-contrast);
}
[ngAccordionGroup] {
@@ -6,28 +6,28 @@
justify-content: center;
font-family: 'Press Start 2P';
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000));
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--page-background));
--retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white);
--retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
--retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
--retro-elevated-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast);
--retro-flat-shadow:
4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700),
-4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700);
4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
-4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
--retro-clickable-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
--retro-pressed-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-dark),
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}
[ngAccordionGroup] {
@@ -6,28 +6,28 @@
justify-content: center;
font-family: 'Press Start 2P';
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000));
--retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--page-background));
--retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white);
--retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
--retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
--retro-elevated-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast);
--retro-flat-shadow:
4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700),
-4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700);
4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
-4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
--retro-clickable-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
--retro-pressed-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-dark),
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}
[ngAccordionGroup] {
@@ -12,17 +12,17 @@
--retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
--retro-elevated-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-light),
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast);
--retro-flat-shadow:
4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700),
-4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700);
4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
-4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
--retro-pressed-shadow:
inset 4px 4px 0px 0px var(--retro-shadow-dark),
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700),
0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700),
0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700);
inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}
.retro-autocomplete {

Some files were not shown because too many files have changed in this diff Show More