Compare commits

...

285 Commits

Author SHA1 Message Date
kirjs a8a35343bc release: cut the v19.1.8 release 2025-02-26 14:11:04 -05:00
Matthieu Riegler 41ef1cbd80 docs(docs-infra): remove explicit dectectChanges() (#60098)
PR Close #60098
2025-02-26 12:00:59 -05:00
arturovt 567d48f2a1 refactor(core): tree-shake REF_EXTRACTOR_REGEXP (#60081)
The `REF_EXTRACTOR_REGEXP` is a `new` expression that has side effects and is not dropped in production, even if it is unused.

PR Close #60081
2025-02-26 11:17:50 -05:00
arturovt adf4987185 refactor(core): inline depPath in throwCyclicDependencyError to be dropped (#60084)
Inlines the `depPath` within the `throwCyclicDependencyError`, because it's not being tree-shaken in production.

PR Close #60084
2025-02-26 11:10:37 -05:00
Jens Kuehlers 4f38429cea docs: move release date for v20 by one week (#60111)
PR Close #60111
2025-02-26 11:00:42 -05:00
arturovt 33769c234f refactor(forms): tree-shake _checkParentType in production (#60041)
In this commit, we move `_checkParentType` to a separate function to avoid a redundant prototype method in production.

PR Close #60041
2025-02-25 14:12:43 -05:00
Andrew Scott 4c9d09c643 fix(language-service): provide correct rename info for elements (#60088)
This commit ensures we do not block element rename if it is supported by
other rename providers.

fixes https://github.com/angular/vscode-ng-language-service/issues/2077

PR Close #60088
2025-02-25 14:10:54 -05:00
Kristiyan Kostadinov 1fbaeab37d fix(common): make types for HttpClient more readable (#59901)
`HttpClient` has a lot of overloads to achieve proper type checking, however each overload is also very long which makes it hard to read on adev. These changes replace the object literal types with `Record` to make them a bit more concise.

PR Close #59901
2025-02-25 13:01:10 -05:00
Pawel Kozlowski 69b6d6547e refactor(core): remove performance mark feature for signals (#59991)
Remove the performance mark feature from the Angular signal impl
so more code can be shared between primitives and other frameworks.

PR Close #59991
2025-02-25 11:10:08 -05:00
Angular Robot 94117f1cfc build: update all non-major dependencies (#60093)
See associated pull request for more information.

PR Close #60093
2025-02-25 10:49:24 -05:00
Angular Robot d0c5fe9886 build: update io_bazel_rules_sass digest to 3b3667f (#60092)
See associated pull request for more information.

PR Close #60092
2025-02-25 10:45:35 -05:00
Angular Robot 790bdbfc48 build: update scorecard action dependencies (#60094)
See associated pull request for more information.

PR Close #60094
2025-02-25 10:43:27 -05:00
mgechev d36dbce309 docs: add a page for custom build pipeline (#60058)
Add a documentation page for creating a custom build pipeline
with community plugins.

PR Close #60058
2025-02-25 10:40:35 -05:00
Aristeidis Bampakos 7a88ce5ef3 docs: update security guide (#59885)
PR Close #59885
2025-02-25 10:24:27 -05:00
Kristiyan Kostadinov c611c8d212 fix(core): capture stack for HMR errors (#60067)
Currently we send the `message` of an error thrown during HMR. That's usually not enough so now we also capture the stack trace.

Relates to https://github.com/angular/angular-cli/issues/29695.

PR Close #60067
2025-02-24 11:56:16 -05:00
hawkgs 3b0b4936c6 refactor(devtools): drop @ from inputs and outputs label (#60053)
Drop '@' from inputs and outputs label to fit in with the new signal-based API.

PR Close #60053
2025-02-24 10:49:12 -05:00
Evgeniy Aksyonov 5ecceda5cb docs: fix typo in outputs.md for migrations section (#60055)
PR Close #60055
2025-02-24 10:46:22 -05:00
hawkgs 3edc494ea2 docs(docs-infra): fix the top position of the search dialog (#60012)
Instead of centering the dialog, fix the top position in such way that when the results container is full, the dialog looks centered. This prevents the dialog from "jumping" when you type and the results change.

PR Close #60012
2025-02-24 10:44:19 -05:00
Jessica Janiuk 91149b5cdb refactor(core): clean up when blocks fail to fetch or hydrate (#59740)
There are cases where resources fail to fetch or the DOM has changed due to an if block. This should clean up the remaining promises and any registry references to those blocks in that case.

PR Close #59740
2025-02-21 11:08:03 -05:00
Matthieu Riegler 51caec89ed ci: disable adev tests. (#60043)
Due toe #54858 and in the introduction of the new `FakeNavigation` by #59857, adev tests now fails to build.
We have to disable them until the next 19.1 release is out.

PR Close #60043
2025-02-20 19:18:49 -05:00
arturovt 20f806a658 refactor(core): drop platform check in ImagePerformanceWarning (#59809)
Replaces `PLATFORM_ID` checks with `ngServerMode`.

PR Close #59809
2025-02-20 12:32:23 -05:00
hawkgs 1dc5c39086 refactor(devtools): fix component inspector highlighting (#59995)
Use `position: absolute` instead of `position: fixed`. This fixes the odd behavior that can be reproduced when scrolling.

PR Close #59995
2025-02-20 11:56:08 -05:00
Trevor Florence f0990c67e6 fix(benchpress): Ensure future-proof correct initialization order (#60025)
Future changes to initialization order can cause this previously OK code to start having compiler erroring like: `TS2729: Property 'foo' is used before its initialization.`

PR Close #60025
2025-02-20 11:21:54 -05:00
muhammadali1658 da25071c11 docs: Fix typo ')' in banner-initial.component.spec.ts (#60032)
PR Close #60032
2025-02-20 11:03:10 -05:00
Andrew Scott c2102c545b refactor(core): Add fake navigation to primitives for code sharing (#59857)
This moves the `FakeNavigation` implementation to the primitives folder
so its implementation can be shared with Wiz. This class was initially
copied directly from the Wiz implementation, with some small modifications.
There will still need to be some work done to align the implementations
and fix anything internally that needs adjusting.

PR Close #59857
2025-02-19 20:09:10 +00:00
Jessica Janiuk 5a66f6072d release: cut the v19.1.7 release 2025-02-19 13:43:00 -05:00
Matthieu Riegler 164facb6ba docs(docs-infra): disable CodeEditor tests (#60015)
The test are only broken on `19.1.x` but not on main. We'll disable them on this branch to allow the CI to go back to green.

PR Close #60015
2025-02-19 17:01:27 +00:00
arturovt e16394a1c9 refactor(common): inline supports check in slice pipe (#59684)
The refactored version improves the original code by removing the `supports` method from the prototype and inlining the logic directly into the `transform` method. This reduces indirection and simplifies the class, especially since `supports` is not reused elsewhere. ESBuild can directly inline the condition into the `if` statement by removing the variable: `if (!("string" == typeof e || Array.isArray(e))) throw i(s, e);`.

PR Close #59684
2025-02-19 15:22:49 +00:00
arturovt b323e2db2b refactor(forms): remove _checkFormPresent and move directly to ngOnChanges (#59741)
In this commit, we remove `_checkFormPresent` because it is a no-op in production. We move its body directly into `ngOnChanges` to eliminate the redundant method from the prototype. Previously, `_checkFormPresent` was being called with no body in production each time `ngOnChanges` was executed.

PR Close #59741
2025-02-19 15:22:13 +00:00
arturovt 354b1fa22f refactor(core): improve stringify (#59745)
In this commit, we improve branching in the `stringify` function, which is widely used by the framework, and add additional comments for clarification. Benchmark results of the old and new implementations (using `slice` makes it slightly faster) are as follows:
```
stringify (old version) x 117,945,419 ops/sec ±5.25% (55 runs sampled)
stringify (new version) x 136,692,820 ops/sec ±4.82% (56 runs sampled)
```

PR Close #59745
2025-02-19 15:21:37 +00:00
arturovt 236a623294 refactor(common): simplify stripTrailingSlash (#59746)
The new version of the function is smaller, eliminating extra bytes. The refactor improves both code size and readability while optimizing the implementation. Benchmark results for the old and new implementations are as follows:

```
stripTrailingSlash_old x 15,446,602 ops/sec ±0.89% (66 runs sampled)
stripTrailingSlash_new x 19,694,523 ops/sec ±1.10% (61 runs sampled)
```

Thus, the new implementation is both smaller and faster.

PR Close #59746
2025-02-19 15:20:53 +00:00
Vlad Boisa 066c52e0a3 docs: add serve section to Service-worker (#59972)
Add the section which mention way to enable service-worker during local development

Fixes #59949

PR Close #59972
2025-02-19 15:19:19 +00:00
Matthieu Riegler 538895b5f5 docs(docs-infra): remove unused examples (#59252)
PR Close #59252
2025-02-19 15:18:47 +00:00
Miles Malerba 265739544e ci: add mmalerba to pullapprove (#60005)
Add mmalerba to pullapprove config

PR Close #60005
2025-02-19 15:18:08 +00:00
Angular Robot 4ec0e66cc1 build: update actions/cache digest to 0c907a7 (#60002)
See associated pull request for more information.

PR Close #60002
2025-02-18 20:23:09 +00:00
Matthieu Riegler ec1e4c3d94 fix(forms): Fix typing on FormRecord. (#59993)
Priori to this change, `ɵRawValue` of a `FormRecord` returned a `Partial`. This commit fixes it.

fixes #59985

PR Close #59993
2025-02-18 19:28:36 +00:00
Kristiyan Kostadinov da1426b3fe refactor(core): simplify serialization of inputs and outputs (#59980)
Simplifies the functions that serialize inputs/outputs for the `ComponentFactory` type.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov a29c2e0f25 build: update bundle goldens (#59980)
Updates the bundle goldens to account for the latest changes.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov fa260a9862 refactor(core): add assertion to avoid writes to directive factories (#59980)
Attempting to write to directive inputs before the directive is created can lead to subtle issues that won't necessarily trigger errors. These changes add an assertion to catch such issues earlier.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov a1b45799eb refactor(core): avoid unnecessary lookup when writing inputs (#59980)
Currently we resolve the DOM node when writing inputs up-front, because it's necessary for the `ng-reflect-` attributes. Since the attributes are dev-mode-only, we can move the resolution into the function that writes them so we can avoid the resolution when it's not used.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov d359650273 refactor(core): simplify InitialInputs data structure (#59980)
Reworks the `InitialInputs` data structure to only store a public name and initial value, resulting in less memory usage and making it easier to work with.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov e7834767f6 refactor(core): remove flags from TNode.inputs (#59980)
The input flags are already available on the definition so we don't need to store them on `TNode.inputs`.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov 798752b423 refactor(compiler): remove input transforms feature (#59980)
An earlier refactor made the `InputTransformsFeature` a no-op so these changes remove the code that was generating it.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov 951178233d refactor(core): remove inputTransforms from definition (#59980)
Removes the `inputTransform` from the directive definition since this information is already available on the `inputs`.

PR Close #59980
2025-02-18 19:28:01 +00:00
Kristiyan Kostadinov b8d1b070b2 refactor(core): simplify how inputs are stored in the directive definition (#59980)
Currently the values in `DirectiveDef.inputs` are either strings or arrays, depending if there are flags. This makes it a bit hard to work with, because each time it's read, the consumer needs to account for both cases.

These changes rework it so the values are always an arrays.

PR Close #59980
2025-02-18 19:28:00 +00:00
Pawel Kozlowski 6d8c2e2162 refactor(core): move LContainer manipulation logic to its own file (#59989)
All the view in a container logic is in the
packages/core/src/render3/view/container.ts file
plus some other associated refactorings.

PR Close #59989
2025-02-18 15:42:28 +00:00
arturovt e9f10eb4c9 fix(common): clean up urlChanges subscribers when root scope is destroyed (#59703)
In this commit, the `urlChanges` subject is completed to release all active observers when the root scope is destroyed. Previously, subscribing to the `urlChanges` subject caused the subscriber to capture `this`, resulting in a memory leak after the root scope was destroyed.

PR Close #59703
2025-02-18 15:40:20 +00:00
hawkgs 26c64a8554 docs(docs-infra): fix card highlighting in the API reference details page (#59965)
Drop `pointer-events: none` and update the member card highlighting mechanism.

PR Close #59965
2025-02-18 14:56:49 +00:00
Matthieu Riegler 28551a82b4 docs(docs-infra): attemp to fix flaky mermaid test (#59994)
This test has 2 async parts, loading the markdown file and the marked parsing.
First attempt to fix the flakiness is by inline the markdown file.

If this test timeouts again in the future it means the timeout is related to marked itself (and the dynamic import of mermaid).

PR Close #59994
2025-02-18 14:55:50 +00:00
Doug Parker 8d40876900 docs: update zip command and link to recent DevTools commits (#59792)
`-x dist/` never worked for reasons I don't really understand. Historically I've just deleted `dist/` before zipping. I tried a few different approaches, but all of them lead to some form of "Name not matched" error in `zip` of the `dist/` directory. Instead I just opted to delete `dist/` as part of the zipping command.

The link to recent DevTools commits seems good enough to manually write a changelog. All relevant commits should be using `refactor(devtools)`, so the string "devtools" should definitely be in there.

PR Close #59792
2025-02-14 19:32:00 +00:00
Andrew Scott d46dd77742 refactor(benchpress): move initializer to constructor (#59960)
Move the initializer into the constructor for instance members that reference identifiers declared in the constructor.

When TypeScript outputs modern language features, the below case throws an TS error.

PR Close #59960
2025-02-14 18:39:58 +00:00
Angular Robot 387eb043a7 build: update all non-major dependencies (#59641)
See associated pull request for more information.

PR Close #59641
2025-02-14 18:39:10 +00:00
Angular Robot e141893836 build: update dependency jsdom to v26 (#59958)
See associated pull request for more information.

PR Close #59958
2025-02-14 18:01:26 +00:00
Alan Agius 82eba1d44b ci: update nvm node.js verson to 18.20.5 (#59957)
This is needed due to some deps.

PR Close #59957
2025-02-14 17:24:55 +00:00
Angular Robot 37d4fa883b build: update io_bazel_rules_sass digest to c01e884 (#59948)
See associated pull request for more information.

PR Close #59948
2025-02-14 16:34:24 +00:00
Doug Parker f76adcc33c release: bump Angular DevTools version to 1.0.23 (#59931)
PR Close #59931
2025-02-14 16:31:37 +00:00
Alan Agius 6b2685de65 build: update bazel node.js version to 18.20.5 (#59943)
This is needed as selenium-webdriver requires at least this version.

PR Close #59943
2025-02-14 16:31:05 +00:00
Jessica Janiuk 1b4fc8e20b ci: fix flakey incremental hydration test (#59945)
This extends the test timeout for the two timer tests while shortening the actual hydrate on timer. This hopefully should result in more reliable CI.

PR Close #59945
2025-02-13 22:35:04 +00:00
iteriani 3fd69d7ab4 refactor(core): Check in some interfaces for the DI package (#59921)
This will be the starting point of the DI package. We will first check in some interfaces and then make sure the existing DI package implements that interface. Afterwards, we'll slowly start moving injector implementation.

PR Close #59921
2025-02-13 20:19:29 +00:00
Jessica Janiuk 419e67faf4 build: update zone.js pullapprove rule (#59942)
This fixes the broken pullapprove config due to a missing array.

PR Close #59942
2025-02-13 20:16:50 +00:00
Jessica Janiuk defe672084 build: update zone.js pullapprove rule (#59941)
This excludes lock and package files from requiring zones approval.

PR Close #59941
2025-02-13 19:17:14 +00:00
JoostK 16fc074689 fix(compiler-cli): avoid crash in isolated transform operations (#59869)
The CLI uses the `ts.transform` API to apply the Angular compiler's transformers
on the source files when `isolatedModules` is true (and various other constraints)
instead of going through a full `ts.Program.emit` operation. This results in the
transformers to operate in an environment where no emit resolver is available, which
was not previously accounted for. This commit reflects the possibility for the emit
resolver to be missing and handles this scenario accordingly.

Fixes #59837

PR Close #59869
2025-02-13 16:39:05 +00:00
arturovt 04851c748b refactor(common): remove redundant transferCacheInterceptorFn dependencies (#59819)
The `transferCacheInterceptorFn` injects dependencies in itself; the `TransferCache` and cache options are redundant in the `deps` list.

PR Close #59819
2025-02-13 15:11:19 +00:00
arturovt 6d1ebc52a2 refactor(core): simplify concatStringsWithSpace (#59820)
The new version of the function is smaller, eliminating extra bytes. The refactor improves both code size and readability while optimizing the implementation. Benchmark results for the old and new implementations are as follows:

```
concatStringsWithSpace_old x 149,225,311 ops/sec ±8.54% (50 runs sampled)
concatStringsWithSpace_new x 160,206,834 ops/sec ±5.72% (54 runs sampled)
```

Thus, the new implementation is both smaller and faster.

PR Close #59820
2025-02-13 15:10:43 +00:00
Doug Parker adbf013cea docs: link to Tailwind docs about Angular CLI integration (#59765)
We should probably have our own authoritative documentation here, but Tailwind's doc is pretty decent, so this is a good starting point.

PR Close #59765
2025-02-13 15:00:56 +00:00
rysavy-dudrtools 0131c703ab docs(localize): added link to add-package.md (#59937)
PR Close #59937
2025-02-13 14:59:37 +00:00
hawkgs f01d827a05 docs(docs-infra): drop tabs layout from the API reference details page (#59068)
Drop the tabs in favor of a single page separated by sections.

PR Close #59068
2025-02-13 14:58:33 +00:00
Angular Robot df03cfd731 build: update github/codeql-action action to v3.28.9 (#59914)
See associated pull request for more information.

PR Close #59914
2025-02-13 14:56:39 +00:00
Doug Parker 22c2dfa756 release: bump Angular DevTools version to 1.0.22 (#59791)
PR Close #59791
2025-02-13 14:50:39 +00:00
Andrew Scott 20df2cd108 release: cut the v19.1.6 release 2025-02-12 12:02:25 -08:00
Kristiyan Kostadinov 01f669a274 fix(compiler): handle tracking expressions requiring temporary variables (#58520)
Currently when we generate the tracking expression for a `@for` block, we process its expression in the context of the creation block. This is incorrect, because the expression may require ops of its own for cases like nullish coalescing or safe reads. The result is that while we do generate the correct variable, they're added to the creation block rather than the tracking function which causes an error at runtime.

These changes address the issue by keeping track of a separate set of ops for the `track` expression that are prepended to the generated function, similarly to how we handle event listeners.

Fixes #56256.

PR Close #58520
2025-02-12 09:56:09 -08:00
Angular Robot b41a263508 build: update io_bazel_rules_sass digest to d829b6a (#59862)
See associated pull request for more information.

PR Close #59862
2025-02-12 09:47:53 -08:00
Bobokhuja bc6e11160e docs: fix tabs in example code in creating injectable services (#59911)
PR Close #59911
2025-02-12 09:46:52 -08:00
Kristiyan Kostadinov 710759ddcc fix(migrations): account for let declarations in control flow migration (#59861)
Fixes that the control flow migration wasn't accounting for `@let` when determining which symbols are used.

PR Close #59861
2025-02-12 09:45:15 -08:00
Kristiyan Kostadinov 46f36a58bf fix(migrations): count used dependencies inside existing control flow (#59861)
Fixes that the control flow migration wasn't checking the content of pre-existing control flow nodes for dependencies.

Fixes #59846.

PR Close #59861
2025-02-12 09:45:15 -08:00
Angular Robot 9366e842b2 build: update dependency saucelabs to v9 (#59801)
See associated pull request for more information.

PR Close #59801
2025-02-12 09:39:29 -08:00
AleksanderBodurri f9e59007ce fix(devtools): regressions in component tree (#59873)
This commit solves two cases

Bug: When a directive of the same name is selected, the property view tab would not update properly. This was caused by a signals refactor that changed the behaviour of a string input property to not re-render because the underlying signal did not change (string equality). This is fixed by converting this input into an object.

Bug: When a selected element is removed from the component tree, DevTools would not rerender the component tree properly and deselect that component. Now if DevTools detects that a component is removed, it re-renders the tree and deselects the component.

PR Close #59873
2025-02-12 09:22:30 -08:00
Matthieu Riegler 544fb89709 docs(docs-infra): inline example in description (#59908)
fixes #59905

PR Close #59908
2025-02-12 09:21:50 -08:00
Hendra Arfiansyah ce216723a5 docs: remove trailing parentheses in example code in linked signal (#59917)
PR Close #59917
2025-02-12 09:20:32 -08:00
Kristiyan Kostadinov dcfb9f1959 fix(compiler-cli): handle deferred blocks with shared dependencies correctly (#59926)
When the compiler analyzes the defer blocks in a component, it generates two sets of dependencies: ones specific for each block and others from all the deferred blocks within the component. The logic that combines all the defer block dependencies wasn't de-duplicating them which resulted in us producing `setClassMetadataAsync` calls where the callback can have multiple parameters with the same name. This was a problem both in full and partial compilation, but the latter was more visible, because Babel throws an error in such cases.

These changes add some logic to de-duplicate the dependencies so that we produce valid code.

Fixes #59922.

PR Close #59926
2025-02-12 09:15:54 -08:00
Kristiyan Kostadinov cab7a9b69c fix(core): invalidate HMR component if replacement throws an error (#59854)
Integrates https://github.com/angular/angular-cli/pull/29510 which allows us to invalidate the data in the dev server for a component if a replacement threw an error.

PR Close #59854
2025-02-12 09:05:31 -08:00
Kristiyan Kostadinov 6e999300a7 refactor(compiler): pass more information to HMR replacement function (#59854)
Adjusts the code we generate for HMR so that it passes in the HMR ID and `import.meta` to the `replaceMetadata` call. This is necessary so we can do better logging of errors.

PR Close #59854
2025-02-12 09:05:31 -08:00
Alex Rickabaugh 27c39f5a8a release: cut the v19.1.5 release 2025-02-06 12:32:16 -08:00
Wadie 6217e45cc5 fix(docs-infra): reset sandbox runtime on template change (#59844)
Ensure the sandbox runtime is properly reset when the template changes to prevent any unexpected behavior during development.

PR Close #59844
2025-02-05 15:01:34 -08:00
Andrew Scott 87588ecd2b build: remove self from unavailable list (#59858)
remove self from unavailable list

PR Close #59858
2025-02-05 12:18:57 -08:00
Jeevan Mahesha dbbd0d3536 docs: Add v18 Angular version link to versions configuration (#58933)
PR Close #58933
2025-02-05 09:02:02 -08:00
muhammadali1658 d09bb7e8b0 docs: fix broken link of FID (#59848)
PR Close #59848
2025-02-05 09:01:31 -08:00
hyperlife1119 d2c6d0c443 docs(service-worker): corrected default values ​​for navigation URLs (#58156)
The default value described in the documentation is inconsistent with the actual default value.

PR Close #58156
2025-02-05 09:00:23 -08:00
Pawel Kozlowski 2137f80702 refactor(core): minor code cleanups (#59843)
Some minor code cleanups after code changes in
previous commits.

PR Close #59843
2025-02-05 08:56:28 -08:00
Pawel Kozlowski 802397d997 refactor(core): reuse element end first creation pass (#59843)
Reuse element end first creation pass in ComponentRef impl.

PR Close #59843
2025-02-05 08:56:28 -08:00
Pawel Kozlowski 724885bbc6 refactor(core): reuse element first create pass in ComponentRef (#59843)
Reuse element first create pass in ComponentRef.

PR Close #59843
2025-02-05 08:56:28 -08:00
Pawel Kozlowski ad01b6a788 refactor(core): move directive matching logic to a separate file (#59843)
Move directive matching logic to a separate file.

PR Close #59843
2025-02-05 08:56:28 -08:00
Angular Robot 2115cca958 build: update dependency angular-split to v19 (#59827)
See associated pull request for more information.

PR Close #59827
2025-02-03 14:00:11 -08:00
Ole Martin Sørli 09e309da6f docs(migrations): fix misspelled link text in overview.md (#59816)
I assume that the link text should read "Try it now" instead of "Try it not". The latter is funnier, but also implies that this migration is not a recommended one.
PR Close #59816
2025-02-03 13:59:16 -08:00
Kristiyan Kostadinov d7b5c597ff fix(compiler-cli): gracefully fall back if const enum cannot be passed through (#59815)
Adds some logic so that if we can't produce a runtime representation of an enum, the dev server can fall back to refreshing the page.

PR Close #59815
2025-02-03 13:58:32 -08:00
Kristiyan Kostadinov 53a4668b58 fix(compiler-cli): handle const enums used inside HMR data (#59815)
When we generate an HMR replacement function, we determine which locals from the file are used and we pass them by reference. This works fine in most cases, but breaks down for const enums which don't have a runtime representation.

These changes work around the issue by passing in all the values as an object literal.

Fixes #59800.

PR Close #59815
2025-02-03 13:58:32 -08:00
Kristiyan Kostadinov 976125e0b4 fix(compiler-cli): handle enum members without initializers in partial evaluator (#59815)
Fixes that the partial evaluator was interpreting initializer-less enum members as undefined. In this case the value is the same as the index.

PR Close #59815
2025-02-03 13:58:32 -08:00
arturovt 8eef6b7d1f refactor(platform-browser): remove redundant DomEventsPlugin dependencies (#59811)
The `DomEventsPlugin` only injects the `DOCUMENT`; the platform ID and `NgZone` are redundant.

PR Close #59811
2025-02-03 13:57:45 -08:00
Pawel Kozlowski 2a0731f9c7 refactor(core): reuse existing logic in ComponentRef impl (#59806)
This change removes some code and logic duplication by
re-using the existing functionality. It also pulls some
code into separate methods for clarity.

PR Close #59806
2025-02-03 13:57:11 -08:00
Luan Gong 419634c391 docs: Fix wording for Angular CLI end-to-end testing (#59808)
PR Close #59808
2025-02-03 13:56:40 -08:00
Andrew Scott cde83e99bc refactor(core): move callAndReportToErrorHandler to bootstrap file (#59793)
This function is only used in the bootstrap file and does not need to be in application_ref

PR Close #59793
2025-02-03 13:54:40 -08:00
Angular Robot 3f6ccfc173 build: update github/codeql-action action to v3.28.8 (#59786)
See associated pull request for more information.

PR Close #59786
2025-02-03 13:54:02 -08:00
Gerard Esteve 29a2924d5a docs: add clarification for sourceLocale location in angular.json (#59783)
PR Close #59783
2025-02-03 13:53:35 -08:00
Alan Agius 29d412d31a docs: replace provideServerRoutesConfig with provideServerRouting (#59777)
The `provideServerRoutesConfig` is replaced with `provideServerRouting`

PR Close #59777
2025-02-03 13:53:04 -08:00
arturovt 0558b38283 refactor(docs-infra): allow home animation to be cleaned up properly (#59732)
In this commit, we wrap `initCanvas` in an observable to prevent executing any code, such as `getViews()`, if the view is destroyed before the canvas becomes ready.

PR Close #59732
2025-02-03 13:52:17 -08:00
arturovt e77391f51c refactor(docs-infra): extract NodeRuntimeSandbox lazy-loading into separate function (#59344)
In this commit, we extract `NodeRuntimeSandbox` lazy-loading into a separate function (because it's duplicated).

PR Close #59344
2025-02-03 13:51:52 -08:00
BreadInvasion 1ca8491b46 docs: use inject() in dependency injection guide (#59079)
PR Close #59079
2025-02-03 13:51:23 -08:00
Sam Knutson 6efcbe8f7a docs: fix spelling of "set up" (#58362)
Fix spelling of the word "set up" in docs. "Setup" (one word) is a noun
whereas "set up" (two words) is a verb.

Fixes #58361

PR Close #58362
2025-02-03 13:50:49 -08:00
Alex Rickabaugh 5d89ffc959 release: cut the v19.1.4 release 2025-01-29 15:08:33 -08:00
Dmitry Ivanitskiy 67db7f7147 docs: fix programmatic-rendering example (#59768)
Fixes example of programmatically rendering of components using dynamic import, as calling dynamic import returns module namespace object rather than component instance

PR Close #59768
2025-01-29 10:54:10 -08:00
Doug Parker f179dc5cef docs: updates versioning docs to recommend that fixes in an RC period be released as a -next release prior to hitting stable (#59766)
PR Close #59766
2025-01-29 10:52:45 -08:00
Kristiyan Kostadinov 4418064599 fix(elements): not setting initial value on signal-based input (#59773)
Fixes that `createCustomElement` was incorrectly excluding signal-based inputs when setting the initial values.

Fixes #59757.

PR Close #59773
2025-01-29 08:50:26 -08:00
muhammadali1658 79f0736089 docs: fix spelling of 'static-site' (#59780)
PR Close #59780
2025-01-29 08:45:20 -08:00
Alan Agius 1828a84062 fix(platform-browser): prepend baseHref to sourceMappingURL in CSS content (#59730)
Implemented functionality to prepend the baseHref to `sourceMappingURL` in CSS content. Added handling to ensure external sourcemaps are loaded relative to the baseHref. Corrected sourcemap URL behavior when accessing pages with multi-segment URLs (e.g., `/foo/bar`). Ensured that when the baseHref is set to `/`, maps are requested from the correct path (e.g., `http://localhost/comp.css.map` instead of `http://localhost/foo/bar/comp.css.map`).

Closes #59729

PR Close #59730
2025-01-29 08:44:20 -08:00
arturovt 544b9ee7ca fix(core): check whether application is destroyed before printing hydration stats (#59716)
In this commit, we check whether the application is destroyed before printing hydration stats. The application may be destroyed before it becomes stable, so when the `whenStableWithTimeout` resolves, the injector might already be in a destroyed state. As a result, calling `injector.get` would throw an error indicating that the injector has already been destroyed.

PR Close #59716
2025-01-29 08:43:34 -08:00
Matthieu Riegler 68dbaf5548 docs(docs-infra): remove non-necessary files from playground zip. (#59728)
fixes #56739

PR Close #59728
2025-01-28 20:34:23 +01:00
Matthieu Riegler c3f1c7aecc docs(docs-infra): Check for files without using / as root. (#59726)
In certain circonstances, a leading slash in the file paths created a incorrect unarchived project.

fixes #57075

PR Close #59726
2025-01-28 20:33:23 +01:00
Matthieu Riegler f6029bc126 docs(docs-infra): Remove leading path from zipped files. (#59726)
In certain circonstances, a leading slash in the file paths created a incorrect unarchived project.

fixes #57075

PR Close #59726
2025-01-28 20:33:23 +01:00
Joey Perrott 1a06eb2e46 ci: prevent renovate from updating @bazel/ibazel (#59761)
Add @bazel/ibazel to the ignored deps list for renovate to prevent us from updating to a version that
is incompatible with our repository.

PR Close #59761
2025-01-28 19:17:34 +01:00
Luan Gong fb909446e4 docs(core): Fix typo in documentation of linkedSignal (#59752)
PR Close #59752
2025-01-28 19:14:21 +01:00
Angular Robot 07e5136b61 build: update cross-repo angular dependencies (#59669)
See associated pull request for more information.

PR Close #59669
2025-01-28 18:51:00 +01:00
Tyler Luckewicz 70a71187f2 docs(docs-infra): fix gammatical error in two way binding with plain properties section (#59755)
PR Close #59755
2025-01-28 18:48:09 +01:00
Alan Agius 522acbf3d7 fix(service-worker): add missing rxjs peer dependency (#59747)
The `@angular/service-worker` package now explicitly declares `rxjs` as a peer dependency.

PR Close #59747
2025-01-28 13:09:50 +01:00
Alan Agius 0fdc4cd795 build: remove @angular/common from Service Worker dependencies (#59747)
The `@angular/service-worker` package no longer directly depends on `@angular/common`.

PR Close #59747
2025-01-28 13:09:50 +01:00
Paul Gschwendtner f3d6c49b1e ci: configure merge tool to enforce mandatory PR statuses (#59749)
The merge tool is currently hard-coded to only check `lint` as a
required status. This was added because at some point the old GitHub
robot was replaced with a so-called `unified-statuses` check GitHub
action; but that one never worked/impacted productivity of the team.

I've added support to the merge tool to require specific jobs/checks to
run, before allowing merge (can be forcibly ignored). We are using this
ability now to enforce a few "common" required jobs, as a safety measure
when GitHub didn't trigger CI runs (e.g. for new contributors).

This recently became a more prominent issue as the GitHub org enforces
that CI doesn't run for e.g. first time contributors.

PR Close #59749
2025-01-28 12:53:33 +01:00
hawkgs 3c28301085 build: revert back to @bazel/ibazel v0.16 (#59748)
v0.25 is causing issues with adev and devtools – file changes do not trigger a rebuild.

PR Close #59748
2025-01-28 12:42:38 +01:00
Pawel Kozlowski cb1cb0cf9a refactor(core): reuse host directive resolution logic (#59685)
Reuse host directive resolution logic in ComponentRef

PR Close #59685
2025-01-28 11:31:29 +01:00
arturovt 873870f60f refactor(common): drop error messages in production (#59545)
Switches to using `RuntimeError` and drops error messages in production by replacing it with an error code.

PR Close #59545
2025-01-28 09:39:42 +01:00
arturovt 82528492eb refactor(router): remove unused code (#59704)
This code is never used.

PR Close #59704
2025-01-28 09:38:34 +01:00
Angular Robot d0dc8f76a5 build: update github/codeql-action action to v3.28.6 (#59744)
See associated pull request for more information.

PR Close #59744
2025-01-28 09:08:47 +01:00
arturovt 2c770a251a refactor(common): drop platform check in PreconnectLinkChecker (#59714)
Replaces platform check within the `PreconnectLinkChecker` with the `ngServerMode` global.

PR Close #59714
2025-01-27 17:22:44 +01:00
hawkgs e7d0ca1bd5 docs(docs-infra): fix header layout for tablets (#59734)
The version picker and the theme and socials buttons were not properly styled.

PR Close #59734
2025-01-27 17:07:54 +01:00
Pawel Kozlowski 068cf2966d refactor(core): remove unused LifecycleHooksFeature (#59678) (#59735)
LifecycleHooksFeature seems to be unused and can be deleted.

PR Close #59678

PR Close #59735
2025-01-27 16:49:51 +01:00
Pawel Kozlowski 557ca8dd9d refactor(core): simplify ComponentRef creation (#59678) (#59735)
Move more logic to a constructor of a ComponentRef.

PR Close #59678

PR Close #59735
2025-01-27 16:49:51 +01:00
Pawel Kozlowski caaa7ca6b8 refactor(core): simplify attributes extraction logic for ComponentRef (#59678) (#59735)
Make extractAttrsAndClassesFromSelector to return TAttributes directly to
simplify the overall logic and remove unecessary code.

PR Close #59678

PR Close #59735
2025-01-27 16:49:51 +01:00
arturovt 0a9c03c7b1 refactor(service-worker): drop platform checks (#59475)
In this commit, we drop `isPlatformBrowser` checks in favor of `ngServerMode` compile-time variable.

PR Close #59475
2025-01-27 16:41:10 +01:00
Sebastian Ochoa 1c84cbca30 fix(platform-browser): Update pseudoevent created by createMouseSpecialEvent to populate _originalEvent property (#59690)
This fixes an internal bug

PR Close #59690
2025-01-27 10:28:59 +01:00
Sebastian Ochoa 1225657462 fix(platform-browser): Update pseudoevent created by createMouseSpecialEvent to populate _originalEvent property (#59690)
This fixes an internal bug

PR Close #59690
2025-01-27 10:28:59 +01:00
Sebastian Ochoa 3f4d5f636a fix(platform-browser): Update pseudoevent created by createMouseSpecialEvent to populate _originalEvent property (#59690)
This fixes an internal bug.

PR Close #59690
2025-01-27 10:28:59 +01:00
arturovt 093ba4b5c7 refactor(docs-infra): allow home to be cleaned up (#59683)
In this commit, we're using the `from()` in the `adev-home` component, which allows us to invert a dependency and avoid memory leaks. Because an `async` function would be executed even if the component is already destroyed.

PR Close #59683
2025-01-27 10:27:20 +01:00
arturovt 7613bb46cd refactor(docs-infra): prevent leak in tutorial component (#59675)
In this commit, we're using the `from()` in the `adev-tutorial` component, which allows us to invert a dependency and avoid memory leaks. Because `then()` would be executed even if the component is already destroyed.

PR Close #59675
2025-01-27 10:26:36 +01:00
Aaditree Jaisswal f668440eca docs: Add link to Language Service page from the Installation page (#59654)
PR Close #59654
2025-01-27 10:25:21 +01:00
Andrew Seguin 6338257202 docs: fix broken material.angular.io test harness links (#59709)
PR Close #59709
2025-01-27 10:22:50 +01:00
waify 170c052141 docs: fix typo in signals-interop.md (#59724)
PR Close #59724
2025-01-27 09:55:42 +01:00
Angular Robot 7a328ba13e docs: update Angular CLI help [19.1.x] (#59706)
Updated Angular CLI help contents.

PR Close #59706
2025-01-24 20:42:31 +01:00
arturovt b4b36ed9e3 refactor(common): tree-shake PreloadLinkCreator for client bundles (#59431)
In this commit, we tree-shake the `PreloadLinkCreator` for client bundles because it's targeting only server code. We use the pending tasks service to contribute to app stability by waiting for the module to load.

PR Close #59431
2025-01-24 17:17:58 +01:00
Kristiyan Kostadinov d6e78c072d fix(core): ensure type is preserved during HMR (#59700)
Fixes an internal HMR issue where the type might be replaced when swapping out the definition. Externally this is a no-op.

PR Close #59700
2025-01-24 17:16:58 +01:00
arturovt 15cc74fe82 refactor(common): simplify joinWithSlash (#59484)
The new version is 2x smaller in the reduced code size; as thus this eliminates extra bytes. Refactors `joinWithSlash` function to reduce code size and improve readability. Added checks to handle leading and trailing slashes more concisely and provided comments for clarity.

PR Close #59484
2025-01-24 17:16:12 +01:00
arturovt 6a92b80ae6 refactor(core): re-use isDetachedByI18n (#59668)
We already have a function called `isDetachedByI18n` which checks whether a `tNode` is in `isDetached` state; as thus, there's no reason to apply those checks manually.

PR Close #59668
2025-01-24 17:15:08 +01:00
arturovt b7b8da5b5a refactor(common): simplify null/undefined check in keyvalue pipe (#59696)
In this commit, we remove the separate `a === undefined` and `a === null` checks and replace them with `a == null`. Using `a == null` is better and more concise because it checks for both `null` and `undefined` in a single operation. The loose equality `==` is specifically designed to treat `null` and `undefined` as equivalent. This change only reduces some bytes in the code and simplifies it, with no performance impact, as modern JavaScript engines handle `a == null` efficiently. Additionally, comments have been added for clarification.

PR Close #59696
2025-01-24 12:45:04 +01:00
arturovt f8b8a3e7c0 refactor(forms): wrap _checkParentType with ngDevMode (#59489)
The `_checkParentType` bodies are wrapped with `ngDevMode`, meaning they act as no-ops in production. We can wrap the actual calls to `_checkParentType` with `ngDevMode` to prevent calling no-op functions in production

PR Close #59489
2025-01-24 11:51:37 +01:00
Ezequiel Cicala 4574ece590 docs: replace word in using-component-harnesses.md (#59687)
PR Close #59687
2025-01-24 11:29:19 +01:00
Pawel Kozlowski 9ea6337653 refactor(core): reuse directive instantiate logic (#59633) (#59695)
This refactor reuses the existing directive instantiation
logic for a given component.

This is 19.1.x version of the PR #59633

PR Close #59695
2025-01-24 11:00:52 +01:00
Pawel Kozlowski 4867b64050 test: update golden files (#59693)
Update a missing entry in a golden file that breaks
a build on the 19.1 branch.

PR Close #59693
2025-01-24 09:27:57 +01:00
Doug Parker cdb439b809 docs: sort application and browser-esbuild builders first (#59686)
This emphasizes these as the default/preferred options over `browser` builder.

PR Close #59686
2025-01-23 14:27:53 -08:00
Ezequiel Cicala 8070353d22 docs: add missing word on components-scenarios.md (#59681)
PR Close #59681
2025-01-23 14:26:23 -08:00
Ezequiel Cicala 455ae44393 docs: add another missing word on components-scenarios.md (#59680)
PR Close #59680
2025-01-23 14:25:51 -08:00
arturovt 9ee4e42283 refactor(core): prevent duplicating componentOffset checks (#59611)
The `type_checks` module already exposes a utility function that checks whether `TNode.componentOffset` is greater than -1. There is no need to check that property manually in other places, as we can reuse the helper function.

PR Close #59611
2025-01-23 14:23:29 -08:00
arturovt 60094d3853 refactor(common): prevent duplicating Accept header name (#59546)
Drops some bytes by moving `Accept` into a variable, which is then minified to something like `var a="Accept"` and reused in all the places.

PR Close #59546
2025-01-23 14:21:51 -08:00
arturovt e3da35ec74 fix(router): prevent error handling when injector is destroyed (#59457)
In this commit, we prevent error handling when the root injector is already destroyed. This may happen when the observable completes before emitting a value, which would trigger a `catchError` block that attempts to call `runInInjectionContext` on a destroyed injector.

PR Close #59457
2025-01-23 14:21:07 -08:00
hawkgs 1de822c561 refactor(devtools): select the root element by default (#59626)
Select the application root element when you start Angular DevTools.

PR Close #59626
2025-01-22 13:34:40 -08:00
Jessica Janiuk c2436702df fix(core): fixes test timer-based test flakiness in CI (#59674)
This converts two tests that rely on timers to use fakeAsync. This resolves the flakiness.

PR Close #59674
2025-01-22 13:27:06 -08:00
arturovt 7dc5116f62 refactor(core): prevent duplicating isRootView checks (#59614)
The `type_checks` module already exposes a utility function that checks whether `LView` is marked as a root view. There is no need to check flags in other places, as we can reuse the helper function.

PR Close #59614
2025-01-22 12:30:27 -08:00
Pawel Kozlowski 597a33c482 refactor(core): use linkedSignal primitives (#59599)
This change refactors the linkedSignal to use implementation
from the shared primitives package.

PR Close #59599
2025-01-22 12:29:38 -08:00
Pawel Kozlowski cb6272199b test(core): additional linkedSignal tests (#59599)
Adds a test veryfing that downstream dependencies are
not recomputed when the source of the linkedSignal is
equal to its current value.

PR Close #59599
2025-01-22 12:29:37 -08:00
Andrew Kushnir 66d07e7baf release: cut the v19.1.3 release 2025-01-22 11:41:16 -08:00
Jens Kuehlers 38c8868223 docs: add Bluesky links (#59661)
PR Close #59661
2025-01-22 07:58:15 -08:00
Kristiyan Kostadinov a62c84bc18 fix(migrations): avoid applying the same replacements twice when cleaning up unused imports (#59656)
If a file ends up in multiple programs, the unused imports migration was counting it twice. This was fine since the string replacements were handling it correctly, but it was printing out incorrect data.

These changes rework the migration to de-duplicate the replacements and produce the data from the de-duplicated results.

PR Close #59656
2025-01-22 07:57:38 -08:00
Andrew Kushnir 89b391c245 test(zone.js): reduce flakiness of a timer-related test (#59653)
This commit updates a flaky test to increase the amount of work (more `for` loop iterations) to minimize the chance of getting the same timestamp after that work.

PR Close #59653
2025-01-21 13:20:24 -08:00
Pawel Kozlowski 0de5049daa refactor(core): move TNode manipulation logic to its own file (#59601)
Move TNode manipulation logic to its own file and update existing refereces.

PR Close #59601
2025-01-21 10:48:44 -08:00
Charles Lyding 78af7a5059 fix(compiler-cli): handle new expressions when extracting dependencies (#59637)
Updates the HMR dependencies extraction logic to handle new expressions.
For example, `deps: [[new Optional(), dep]]`.

PR Close #59637
2025-01-21 10:47:44 -08:00
Charles Lyding 39690969af fix(compiler-cli): handle conditional expressions when extracting dependencies (#59637)
Updates the HMR dependencies extraction logic to handle conditional expressions.
For example, `providers: [condition ? providersA : providersB]`.

PR Close #59637
2025-01-21 10:47:43 -08:00
Kristiyan Kostadinov 26f6d4c485 fix(core): skip component ID collision warning during SSR (#59625)
The component ID collision check tries to account for components being replaced by checking for the `type`, however that might not work during SSR.

These changes disable the warning since it's primarily useful on the browser anyways.

PR Close #59625
2025-01-21 09:56:53 -08:00
Kristiyan Kostadinov 53160e504d fix(compiler-cli): extract parenthesized dependencies during HMR (#59644)
Fixes that the HMR dependency extraction logic wasn't accounting for parenthesized identifiers correctly.

PR Close #59644
2025-01-21 09:50:28 -08:00
Kristiyan Kostadinov b2b3816cb1 fix(platform-browser): clear renderer cache during HMR when using async animations (#59644)
Fixes that the async animations renderer didn't have the logic to clean up its style cache during HMR. This is identical to #59393.

Fixes #59640.

PR Close #59644
2025-01-21 09:50:28 -08:00
Kristiyan Kostadinov 408af24ff3 fix(core): capture self-referencing component during HMR (#59644)
Fixes that we were filtering out the component itself from the set of dependencies when HMR is enabled, breaking self-referencing components.

Fixes #59632.

PR Close #59644
2025-01-21 09:50:27 -08:00
Kristiyan Kostadinov d7575c201c fix(core): replace metadata in place during HMR (#59644)
Currently during HMR we swap out the entire module definition (e.g. `MyComp.ɵcmp = newDef`). In standalone components and most module-based ones this works fine, however in some cases (e.g. circular dependencies) the compiler can produce a `setComponentScope` call for a module-based component. This call doesn't make it into the HMR replacement function, because it is defined in the module's file, not the component's. As a result, the dependencies of these components are cleared out upon replacement.

A secondary problem is that the `directiveDefs` and `pipeDefs` fields can save references to definitions that later become stale as a result of HMR.

These changes resolve both issues by:
1. Performing the replacement by copying the properties from the new definition onto the old one, while keeping it in place.
2. Preserving the initial `directiveDefs`, `pipeDefs` and `setInput`.

Fixes #59639.

PR Close #59644
2025-01-21 09:50:27 -08:00
Angular Robot 67fe0b94c7 build: update dependency shiki to v2 (#59623)
See associated pull request for more information.

PR Close #59623
2025-01-21 09:12:02 -08:00
Kristiyan Kostadinov ecfb74d287 fix(compiler): handle :host-context with comma-separated child selector (#59276)
Both `:host` and `:host-context` work by looking for a specific character sequence that is terminated by `,` or `{` and replacing selectors inside of it with scoped versions. This is implemented as a regex which isn't aware of things like nested selectors. Normally this is fine for `:host`, because each `:host` produces one scoped selector which doesn't affect any child selectors, however it breaks down with `:host-context` which replaces each instance with two selectors. For example, if we have a selector in the form of `:host-context(.foo) a:not(.a, .b)`, the compiler ends up determining that `.a,` is the end selector and produces `.foo[a-host] a[contenta]:not(.a, .foo [a-host] a[contenta]:not(.a, .b) {}`.

These changes resolve the issue by splitting the CSS alogn top-level commas, processing the `:host-context` in them individually, and stiching the CSS back together.

PR Close #59276
2025-01-21 09:11:16 -08:00
Pawel Kozlowski 64836215c6 refactor(core): move linkedSignal implementation to primitives (#59501)
This change refactors the Angular-specific linkedSignal implementation
such that its core logic can be shared with other frameworks.

PR Close #59501
2025-01-21 07:58:09 -08:00
Pawel Kozlowski 2ec826dfdc release: cut the v19.1.2 release 2025-01-20 15:10:32 +01:00
Kristiyan Kostadinov 266a8f2f2e fix(core): handle shadow DOM encapsulated component with HMR (#59597)
When a component is created with shadow DOM encapsulation, we attach a shadow root to it. When the component is re-created during HMR, it was throwing an error because only one shadow root can be attached to a node at a time.

Since there's no way to detach a shadow root from a node, these changes resolve the issue by making a shallow clone of the element, replacing it and using the clone for any future updates.

Fixes #59588.

PR Close #59597
2025-01-20 09:54:00 +01:00
Alan Agius 8dcd889987 fix(compiler): update @ng/component URL to be relative (#59620)
This change is required to resolve https://github.com/angular/angular-cli/pull/29248 and works in conjunction with https://github.com/angular/angular-cli/pull/29386. It ensures that HMR (Hot Module Replacement) functions correctly with `base href`, proxies, and other advanced development setups.

PR Close #59620
2025-01-20 09:10:13 +01:00
Kristiyan Kostadinov 95a05bb202 fix(compiler-cli): disable tree shaking during HMR (#59595)
When HMR is enabled, we need to capture the dependencies used in a template and forward them to the HMR replacement function. One half of this process is static, meaning that we can't change it after the initial compilation. Tree shaking becomes a problem in such a case, because the user can change the template in a way that changes the set of dependencies which will start matching with the static part of the HMR code.

These changes disable the tree shaking when HMR is enabled to ensure that the dependencies stay stable.

Fixes #59581.

PR Close #59595
2025-01-20 08:59:30 +01:00
Kristiyan Kostadinov 6f7716268a fix(core): HMR not matching component that injects ViewContainerRef (#59596)
If a component injects `ViewContainerRef`, its `LView` gets wrapped in an empty `LContainer` and the container's host becomes the `LView`. The HMR logic wasn't accounting for this which meant that such components wouldn't be replaced.

Fixes #59592.

PR Close #59596
2025-01-20 08:57:17 +01:00
Matt Janssen 70c4b83509 docs(router): Fix small grammatical errors (#59568)
Improves readability.
PR Close #59568
2025-01-17 13:21:27 -08:00
arturovt 5497102769 fix(core): cleanup stash listener when app is destroyed (#59598)
In this commit, we clean up the reference to the function set by the environment initializer, as the function closure may capture injected elements and prevent them from being properly garbage collected.

PR Close #59598
2025-01-17 10:00:56 -08:00
Pawel Kozlowski b88f81da19 refactor(core): reuse setupStaticAttributes in ComponentRef (#59572)
This change refactor how the dynamically created component
deals with attributes in order to reuse the existing
setupStaticAttributes logic (instead of having specific
and similar code).

PR Close #59572
2025-01-17 09:59:59 -08:00
Andrew Kushnir 2e72ec7e1c test(platform-server): fix flaky incremental hydration test (#59584)
This commit updates a test setup to define a global `ngServerMode` correctly for a test that was emulating client-only behavior. The flag could've been set by prior tests and depending on its state, the test was acting differently.

PR Close #59584
2025-01-17 10:45:37 +01:00
Andrew Kushnir 55837de2a9 test(platform-server): fix flaky hydration test (#59579)
This commit updates testing setup logic to apply correct `document` reference, which should be used by the runtime. Previously, the timing of that operation was less predictable and in some cases led to reusing document state from previous tests.

PR Close #59579
2025-01-17 10:30:51 +01:00
arturovt 4eb541837c fix(core): cleanup _ejsa when app is destroyed (#59492)
In this commit, we delete `_ejsa` when the app is destroyed, ensuring that no elements are still captured in the global list and are not prevented from being garbage collected.

PR Close #59492
2025-01-16 13:56:29 -08:00
arturovt 4507109ac7 refactor(router): drop forRoot guard in production (#59458)
In this commit, we switch from decorators (which also produce redundant metadata, such as in the `declareFactory`
instruction) to the `inject` function to drop the `ROUTER_FORROOT_GUARD` token in production. This token factory function is only in development mode but is still referenced in the constructor due to the `@Inject(ROUTER_FORROOT_GUARD)` decorator.

PR Close #59458
2025-01-16 13:55:49 -08:00
Kristiyan Kostadinov a4eb74c79c fix(core): animation sometimes renderer not being destroyed during HMR (#59574)
These changes aim to resolve the issue that prompted #59514. The animations module is a bit tricky for HMR, because it schedules the destruction of its renderer after the currently-running animations are done. If there are no running animations, the renderer gets destroyed next time around. This is a problem, because it means that the styles can stay around for a long time.

These changes resolve the issue by:
1. Moving the cleanup of the renderer to after the destruction of the old view. This ensures that the usual clean up flow has been kicked off.
2. Flushing the animations when a component is replaced to ensure that the renderer is cleaned up in a timely manner.

PR Close #59574
2025-01-16 11:36:43 -08:00
Angular Robot 612f11616b build: update cross-repo angular dependencies to v19.2.0-next.0 (#59571)
See associated pull request for more information.

PR Close #59571
2025-01-16 10:40:01 -08:00
Pawel Kozlowski 8b08a25f6b refactor(core): move DOM manipulation logic to its own file (#59462)
This refactoring takes a step toward breaking down the
node_manipulation file into smaller, more focused files.

PR Close #59462
2025-01-16 10:38:45 -08:00
Alex Rickabaugh 81f8fe63bd refactor(core): port resource() to linkedSignal() (#59024)
When the reactive `request` of a resource() notifies, it transitions to the
Loading state, fires the loader, and eventually transitions to Resolved.
With the prior implementation, a change of the `request` will queue the
effect, but the state remains unchanged until the effect actually runs. For
a brief period, the resource is in a state where the request has changed,
but the state has yet to update.

This is problematic if we want to use resources in certain contexts where we
care about the state of the resource in a synchronous way. For example, an
async validator backed by a resource might be checked after an update:

```
value.set(123);

if (validator.value()) {
  // value is still valid, even though the resource is dirty and will soon
  // flip to loading state (returning value(): undefined) while revalidating
}
```

To address this timing concern, `linkedSignal()` is used within the
`resource()` to synchronously transition the state in response to the
request changing. This ensures any followup reads see a consistent view of
the resource regardless of whether the effect has run.

This also addresses a race condition where `.set()` behaves differently on a
`resource()` depending on whether or not the effect has run.

PR Close #59024
2025-01-16 09:22:47 -08:00
Alex Rickabaugh 906413aba3 fix(core): change Resource to use explicit undefined in its typings (#59024)
Originally the `T` in `Resource<T>` represented the resolved type of the
resource, and `undefined` was explicitly added to this type in the `.value`
signal. This turned out to be problematic, as it wasn't possible to write a
type for a resource which didn't return `undefined` values. Such a type is
useful for 2 reasons:

1. to support narrowing of the resource type when `Resource.hasValue()`
   returns `true`.

2. for resources which use a different value instead of `undefined` to
   represent not having a value (for example, array resources which want to
   use `[]` as their default).

Instead, this commit changes `resource()` and `rxResource()` to return an
explicit `ResourceRef<T|undefined>`, and removes the union with `undefined`
from all types related to the resource's value. This way, it's trivially
possible to write `Resource<T>` to represent resources where `.value` only
returns `T`.

`hasValue()` then actually works to perform narrowing, by narrowing the
resource type to `Exclude<T, undefined>`.

PR Close #59024
2025-01-16 09:22:46 -08:00
Leon Senft d12a186d53 fix(core): treat exceptions in equal as part of computation (#55818)
Prevent leaking signal reads and exceptions from a custom `equal`
function of a producer `computed()` to a consumer.

Upstream https://github.com/tc39/proposal-signals/pull/90 with a notable
change: Angular does **not** track reactive reads in custom `equal`
implementations.

PR Close #55818
2025-01-16 08:10:10 -08:00
Pawel Kozlowski 797800ce0a docs: update linkedSignal documentation (#59532)
This commit updates the linkedSignal documentation around
the quality function option.

Fixes #59094

PR Close #59532
2025-01-16 08:09:23 -08:00
Matthieu Riegler 126c80c39b docs: update examples to the application builder (#59539)
fixes #59538

PR Close #59539
2025-01-16 08:08:36 -08:00
Pawel Kozlowski 5c9d739a05 release: cut the v19.1.1 release 2025-01-16 13:16:48 +01:00
Kristiyan Kostadinov 357795cb96 fix(core): run HMR replacement in the zone (#59562)
Fixes that in some cases the HMR replacement function was being run outside the zone which meant that change detection would break down after a replacement.

Fixes #59559.

PR Close #59562
2025-01-16 12:36:58 +01:00
Kristiyan Kostadinov eb0b1851f4 fix(platform-browser): roll back HMR fix (#59557)
Rolls back the changes from #59514 because they ended up being breaking in 1P. We can revisit the internal fix in a different way.

Fixes #59558.

PR Close #59557
2025-01-16 12:27:51 +01:00
Pawel Kozlowski 326248ce85 test(devtools): disable flaky highlighter test (#59561)
The test in question was very flaky on CI, example run:
https://github.com/angular/angular/actions/runs/12805645683/job/35702462974?pr=59557

Disabling as it is causing productivity loose for the team.

PR Close #59561
2025-01-16 12:19:39 +01:00
Pawel Kozlowski 74daef1ca2 refactor(core): move logic out of shared instructions code (#59453)
This is first of a series of refactorings that moves code
around such that logic from the shared instruction file
is dispatched to the relevant functional parts.

PR Close #59453
2025-01-16 11:12:05 +01:00
Doug Parker 0d019e9e2b release: bump Angular DevTools version to 1.0.21 (#59548)
PR Close #59548
2025-01-15 16:48:00 -08:00
arturovt 810ed6aad5 refactor(common): prevent duplicating Content-Type header (#59518)
Drops some bytes by moving `Content-Type` into a variable, which is then minified to something like `var b="Content-Type"` and reused in all the places.

PR Close #59518
2025-01-15 12:22:29 -08:00
kirjs e36e812fd0 release: cut the v19.1.0 release 2025-01-15 14:57:40 -05:00
arturovt e2b7359498 refactor(common): drop error message in production (#59471)
Switches to using `RuntimeError` and drops the error message in production by replacing it with an error code.

PR Close #59471
2025-01-15 12:28:30 -05:00
Matthieu Riegler 95c0e51b6e docs: update class & style binding recommendation (#59240)
This commit introduces an update to the official recommendations when it comes to class & styles bindings.

`[class]` & `[style]` bindings are now recommended for basic uses cases.

`[ngClass]` and `[ngStyle]` allow more advanced bindings (like space separated keys) or keys with units (for `ngStyle`) which are not supported by the native bindings. They still require the dedicated directives.

PR Close #59240
2025-01-15 12:27:13 -05:00
Angular Robot f8e1f8508c docs: update Angular CLI help [19.1.x] (#59536)
Updated Angular CLI help contents.

PR Close #59536
2025-01-15 12:17:49 -05:00
Jeremy Elbourn cfdf5ee0f5 docs: clarify that @for doesn't support break/continue (#59533)
We recently saw some confusion around this, so it's worth adding a
sentence to clarify

PR Close #59533
2025-01-15 12:00:22 -05:00
carimatics d0fc0d2da1 docs(forms): escape inequality signs of input tags in flowchart (#59517)
The input tags written within the flowcharts in the document were not being escaped, so we did that.
This change will ensure that the flowcharts in the document are properly displayed.

PR Close #59517
2025-01-15 10:17:23 -05:00
Sandeep Salwan 1fba8d1e51 docs: fix typos in let.md (#59526)
PR Close #59526
2025-01-15 09:44:26 -05:00
Andrew Kushnir 6a0dd9639a Revert "refactor: initialize headers map directly in HttpHeaders class (#59268)" (#59523)
This reverts commit e15226a444.

PR Close #59523
2025-01-14 17:48:36 -05:00
Abdul Wahab b44c0203c5 docs: fix property wrong usage inside afterNextRender in lifecycle.md (#59521)
PR Close #59521
2025-01-14 16:27:40 -05:00
Angular Robot 0130298328 build: update cross-repo angular dependencies (#59520)
See associated pull request for more information.

PR Close #59520
2025-01-14 16:05:15 -05:00
hawkgs 3e7ba3d014 docs: set syntax highlighting to the remaining Markdown code examples blocks (#59088)
There are some code blocks that slipped through the initial Regex-es.

Related to #59026

PR Close #59088
2025-01-14 15:14:03 -05:00
hawkgs 99c542a19b docs(docs-infra): fix scrolling issues in the API reference (#59207)
Fix issues related to scrolling in the API reference:
- Scroll to the top of the page when navigating to the API details page
- Preserve scroll position when navigating back from the API details page

PR Close #59207
2025-01-14 14:56:43 -05:00
arturovt 51a4839e86 refactor(common): tree-shake lcpObserver in NgOptimizedImage (#59481)
Prior to this commit, the `this.lcpObserver?.updateImage` expression was still preserved in the production code because it wasn't wrapped with `ngDevMode`. The observer is injected only in development mode. Additionally, we moved the logic from `ngOnDestroy` to avoid having an empty method in production.

PR Close #59481
2025-01-14 14:54:17 -05:00
Angular Robot 3913893ef4 build: lock file maintenance (#59519)
See associated pull request for more information.

Closes #59494 as a takeover pull request

PR Close #59519
2025-01-14 14:44:30 -05:00
arturovt f6e7516747 refactor(common): tree-shake transfer cache interceptor stuff (#59439)
In this commit, we replace `isPlatformServer` runtime call with the `ngServerMode` in the `transferCacheInterceptorFn` in order to make the functionality tree-shakable between client and server bundles.

PR Close #59439
2025-01-14 14:40:07 -05:00
Kristiyan Kostadinov a7f824a7ec fix(core): destroy renderer when replacing styles during HMR (#59514)
Currently when we swap out the component during HMR, we remove the renderer from the cache, but we never destroy it which means that its styles are still in the DOM. This can cause the old styles to leak into the component after they're replaced. These changes add a `destroy` call to ensure that they're removed.

PR Close #59514
2025-01-14 11:22:07 -05:00
hawkgs 2b85ddc916 docs(docs-infra): change API reference list items order to top-down (#58655)
Change the order from left-right to top-down (columns) and additionally make columns equal width.

PR Close #58655
2025-01-14 11:10:53 -05:00
hawkgs a0756e45c0 docs(docs-infra): fix SCSS build-time warnings (#59115)
Fix SCSS "declarations after nested rules" and `@import` warnings.

PR Close #59115
2025-01-14 11:09:25 -05:00
Matthieu Riegler 4efb1918ee refactor(compiler): remove unused AstVisitors (#59297)
Those 2 clases weren't imported anywhere.

PR Close #59297
2025-01-14 11:08:26 -05:00
Andrew Kushnir e33e673ff9 refactor(core): do not serialize parent block id for top level blocks (#59190)
This commit updates incremental hydration-related annotation logic to avoid serializing parent block id when it's `null` (for top-level blocks).

PR Close #59190
2025-01-14 11:06:59 -05:00
Angular Robot 69cd6f0884 build: update io_bazel_rules_sass digest to adeaf81 (#59508)
See associated pull request for more information.

PR Close #59508
2025-01-14 11:03:22 -05:00
hawkgs 53c3f8538c docs(docs-infra): generate errors and extended-diagnostics route NavigationItem-s (#59355)
Generate the `NavigationItem`-s as part of adev/shared-docs pipeline and use the output JSON files instead of the hardcoded objects in the `sub-navigation-data.ts`.

PR Close #59355
2025-01-14 11:00:08 -05:00
Angular Robot 2a8a8f02f2 build: update all non-major dependencies (#59510)
See associated pull request for more information.

PR Close #59510
2025-01-14 10:57:24 -05:00
Angular Robot d78de38f4c build: update dependency @babel/generator to v7.26.5 (#59511)
See associated pull request for more information.

PR Close #59511
2025-01-14 10:55:25 -05:00
Angular Robot 983b21bcd2 build: update scorecard action dependencies (#59513)
See associated pull request for more information.

PR Close #59513
2025-01-14 10:53:22 -05:00
Pawel Kozlowski 3a9d084b3d ci: update Ethan Cline GitHub user name (#59516)
Use case-sensitive user name.

PR Close #59516
2025-01-14 10:52:05 -05:00
RafaelJCamara f73f39cb96 refactor: initialize headers map directly in HttpHeaders class (#59268)
Improved the initialization of the headers map to enhance performance
and code readability.

No breaking changes.

PR Close #59268
2025-01-14 10:50:16 -05:00
arturovt c67af8b66d refactor(docs-infra): lazy-load EmbeddedTutorialManager in editor UI state (#59509)
In this commit, we lazy-load the `EmbeddedTutorialManager` in the editor UI state as done in other parts of the code.

PR Close #59509
2025-01-14 10:15:13 -05:00
Charles Lyding f68e9cd2e8 docs: update component HMR to fully stable (#59503)
As of 19.1, component HMR for both styles and templates is considered
stable and enabled by default. This includes support for both inline
and file-based component styles/templates.

PR Close #59503
2025-01-14 09:49:15 -05:00
arturovt f1aba5320f refactor(docs-infra): lazy-load EmbeddedTutorialManager in code editor (#59505)
In this commit, we lazy-load the `EmbeddedTutorialManager` in the code editor component as done in other parts of the code.

PR Close #59505
2025-01-13 15:00:27 -05:00
AleksanderBodurri f5e8693701 fix(devtools): remove property tab css that is hiding directive metadata (#59493)
It looks like this height property was redundant prior to upgrading to angular/material 19.1.0-rc.0. An interaction between this property and that update caused elements inside of material expansion panels to be hidden.

This PR removes this unnecessary height assignment entirely.

PR Close #59493
2025-01-13 14:48:02 -05:00
Angular Robot a1cbfa377a build: update cross-repo angular dependencies (#59474)
See associated pull request for more information.

PR Close #59474
2025-01-13 12:52:12 -05:00
arturovt 411b4f54bb refactor(common): prevent duplicating Accept header (#59467)
In this commit, we extract content types into a variable to eliminate extra bytes, as these values are duplicated in multiple places.

PR Close #59467
2025-01-13 12:38:47 -05:00
arturovt de12b524e9 refactor(common): drop enums by changing to const enum (#59468)
Note: this enums are not a part of the public API.

Prior to this commit, the compiler produced:

```js
var DateType;
(function (DateType) {
    DateType[DateType["FullYear"] = 0] = "FullYear";
    DateType[DateType["Month"] = 1] = "Month";
    DateType[DateType["Date"] = 2] = "Date";
    DateType[DateType["Hours"] = 3] = "Hours";
    DateType[DateType["Minutes"] = 4] = "Minutes";
    DateType[DateType["Seconds"] = 5] = "Seconds";
    DateType[DateType["FractionalSeconds"] = 6] = "FractionalSeconds";
    DateType[DateType["Day"] = 7] = "Day";
})(DateType || (DateType = {}));
```

With these changes, we allow objects to be dropped entirely and inlined.

PR Close #59468
2025-01-13 11:14:28 -05:00
arturovt 03339d5f94 refactor(core): change node navigation step to plain const (#59469)
We change the `enum` to a plain `const` to eliminate extra bytes, as `enum` is not really required. We might not be able to switch to `const enum` due to single-file compilation restrictions.

PR Close #59469
2025-01-13 11:12:47 -05:00
Kristiyan Kostadinov 6fc5f182cd test(migrations): add test for earlier fix (#59497)
Adds a test for the fix from #59452 now that we know what caused the issue.

PR Close #59497
2025-01-13 11:10:18 -05:00
Kristiyan Kostadinov ff386718f7 refactor(compiler): fix typo in method name (#59479)
Fixes a typo in the `AstVisitor.visitTypeofExpresion` method's name.

PR Close #59479
2025-01-13 10:57:53 -05:00
Amy Sorto 8091a4afe0 docs: add component harnesses guides (#59078)
PR Close #59078
2025-01-13 10:46:44 -05:00
arturovt c0ffd81efa refactor(docs-infra): lazy-load EmbeddedTutorialManager in home editor (#59491)
In this commit, we lazy-load `EmbeddedTutorialManager` in the home editor component via `injectAsync` as done in other parts of the code.

PR Close #59491
2025-01-13 10:45:44 -05:00
Bobokhuja b745d8ddf9 docs: fix typo example code in pipes documentation (#59312)
PR Close #59312
2025-01-13 10:38:08 -05:00
RafaelJCamara 9146c68733 docs: add $default to path (#59383)
Closes: #59378

PR Close #59383
2025-01-13 10:36:19 -05:00
Matthieu Riegler ee63b0bafa docs(docs-infra): remove sorting from API manager (#59427)
fixes #59423

PR Close #59427
2025-01-13 10:33:39 -05:00
PhilippMDoerner e4efc67222 docs: Adjust lines of server.ts example in server-side-rendering docs (#59490)
docs: Adjust lines of server.ts example in ssr docs

The server.ts excerpt used in the server-side-rendering docs
(https://angular.dev/guide/ssr#configure-server-side-rendering)
does not fully encapsulate the commonEngine code-block.

It begins too early in line 31, leading to the inclusions of lines
from another codeblock that is not intended to be shown here:
```
 );  

// All regular routes use the Angular engine
```
It should be beginning with the line
`// All regular routes use the Angular engine`.

It also ends too soon, cutting off these parts of the code-block:
```
      .catch((err) => next(err));
  });
```
PR Close #59490
2025-01-13 10:32:16 -05:00
Matthieu Riegler c2b77b52fe docs(docs-infra): prevent the host class from being replaced (#59460)
When removing the binding, the class defined on the host element is being replaced

fixes #59442

PR Close #59460
2025-01-10 14:03:39 -05:00
Angular Robot f90dc4ca27 build: update cross-repo angular dependencies (#59473)
See associated pull request for more information.

PR Close #59473
2025-01-10 13:36:51 -05:00
Jessica Janiuk 574cfaf530 fix(dev-infra): remove no longer necessary scope (#59472)
We no longer have need for the view engine scope.

PR Close #59472
2025-01-10 13:28:29 -05:00
Angular Robot c8bbade542 build: update cross-repo angular dependencies (#59470)
See associated pull request for more information.

PR Close #59470
2025-01-10 12:27:22 -05:00
Paul Gschwendtner 59a1d68ce7 fix(migrations): incorrect stats when migrating queries with best effort mode (#59463)
We previously did count forcibly ignored queries as incompatible. This
resulted in incorrect migration stats that are printed upon migration
completion.

See: #58657

PR Close #59463
2025-01-10 11:52:14 -05:00
Paul Gschwendtner ca1d392210 test: add test to verify extending tsconfig works in signal input migration (#59463)
Related to https://github.com/angular/angular/issues/59348

PR Close #59463
2025-01-10 11:52:14 -05:00
Paul Gschwendtner 7debf0f74c test: improve typescript version coverage for signal input migration (#59463)
This ensures the migration works for these TypeScript versions. The
migration is very sensitive to the TS version and its internals; so it
makes sense to test all of these.

PR Close #59463
2025-01-10 11:52:14 -05:00
arturovt ce28bffcb7 refactor(platform-browser): drop BROWSER_MODULE_PROVIDERS_MARKER in production (#59412)
In this commit, we switch from decorators (which also produce redundant metadata, such as in the
`declareFactory` instruction) to the `inject` function to drop the `BROWSER_MODULE_PROVIDERS_MARKER`
token in production. This token is actually provided only in development mode but is still
referenced in the constructor due to the `@Inject(BROWSER_MODULE_PROVIDERS_MARKER)` decorator.

PR Close #59412
2025-01-10 11:47:32 -05:00
Aristeidis Bampakos dec8f91a90 docs: update component scenarios guide (#59461)
PR Close #59461
2025-01-10 10:55:41 -05:00
Kristiyan Kostadinov 14fb8ce4c0 fix(migrations): resolve text replacement issue (#59452)
Based on https://github.com/angular/angular/pull/59353#issuecomment-2580320424, fixes a text replacement issue that seems to cause code to be duplicated in some setups.

PR Close #59452
2025-01-10 10:47:54 -05:00
Matthieu Riegler 53c8dc6d70 docs: update linkedSignal. (#59221)
The commit adds the mention that it is intentionnal that the computation is reactive even if there is an explicit `source`.

fixes #59094

PR Close #59221
2025-01-10 10:41:19 -05:00
Angular Robot 3b1fbceed9 build: update cross-repo angular dependencies (#59464)
See associated pull request for more information.

PR Close #59464
2025-01-10 10:38:11 -05:00
Charles Lyding aed49ddaaa fix(compiler): use chunk origin in template HMR request URL (#59459)
The URL that is dynamically imported to fetch a potential component update
for HMR is now based on the value of `import.meta.url`. This ensures that
the request is sent to the same location that was used to retrieve the
application code. For some development server setups the HTML base HREF
may not be the location of the Angular development server. By using the
application code location which was generated by the development server,
HMR requests can continue to work as expected in these scenarios. In
most common cases, this change will not have any effect as the HTML base
HREF aligns with the location of the application code files.

PR Close #59459
2025-01-09 18:21:48 -05:00
arturovt 4d9bfab807 refactor(common): prevent duplicating X-Request-URL (#59420)
The `X-Request-URL` string is duplicated in multiple places. It is worth moving it to a shared constant that would be minified to something like `const a = "X-Request-URL"` and referenced in all the used places.

PR Close #59420
2025-01-09 18:18:26 -05:00
Doug Parker 2ec76641f5 release: bump Angular DevTools version to 1.0.20 (#59454)
PR Close #59454
2025-01-09 15:41:55 -05:00
Andrew Kushnir 679d4d1ae8 Revert "fix(core): Defer afterRender until after first CD (#58250)" (#59455)
This reverts commit 9870b643bf.

PR Close #59455
2025-01-09 14:30:02 -05:00
Andrew Kushnir 213d1b3a82 Revert "fix(core): Don't run effects in check no changes pass (#58250)" (#59455)
This reverts commit a5fc962094.

PR Close #59455
2025-01-09 14:30:02 -05:00
arturovt bfaeefe302 refactor(animations): drop warning functions in production (#59408)
Prior to this commit, functions that issued warnings were not wrapped with `ngDevMode` at the point
of invocation but had the `ngDevMode` check inside. This meant they acted as no-ops in production.
In this commit, we wrap them externally with `ngDevMode`, so they are entirely removed.

PR Close #59408
2025-01-09 13:15:07 -05:00
arturovt 988a6b2aaf refactor(platform-browser): remove Console from Hammer gestures (#59409)
Injecting the `Console` is redundant because it directly calls the global `console` object.
There is no reason to reference this class in Hammer gestures, as it is only used in development
mode. We can safely call the `console` object directly.

PR Close #59409
2025-01-09 13:09:52 -05:00
arturovt fedee14090 refactor(common): tree-shake fetch backend (#59418)
This commit updates the code of the HTTP code to make the `FetchBackend` class tree-shakable. The class is only needed with `withFetch()` is called and it should not be included into bundles that do not use that feature.

PR Close #59418
2025-01-09 13:05:58 -05:00
arturovt 4491b5bf24 refactor(platform-browser): drop Hammer token names in production (#59438)
In this commit, we drop `HAMMER_GESTURE_CONFIG` and `HAMMER_LOADER` injection token names in production.

PR Close #59438
2025-01-09 12:38:07 -05:00
arturovt 3502039bff refactor(common): drop NullViewportScroller for client bundles (#59440)
In this commit, we replace the `isPlatformBrowser` runtime call with the `ngServerMode` in order to drop the `NullViewportScroller` for client bundles.

PR Close #59440
2025-01-09 12:33:06 -05:00
arturovt c281807e92 refactor(core): drop platform injection token names in production (#59400)
In this commit, we tree-shake the injection token names in production.

PR Close #59400
2025-01-09 12:28:19 -05:00
Kristiyan Kostadinov c6b66e5aba fix(compiler-cli): handle more node types when extracting dependencies (#59445)
Fixes that the HMR dependency extraction logic wasn't handling some node types. Most of these are a bit edge-case-ey in component definitions, but variable initializers and arrow functions can realistically happen in factories.

PR Close #59445
2025-01-09 12:22:47 -05:00
Angular Robot d7cce1c78b build: update cross-repo angular dependencies (#59249)
See associated pull request for more information.

PR Close #59249
2025-01-09 12:18:45 -05:00
arturovt 8ca298dc9c refactor(core): change LContainerFlags to const enum (#59416)
Prior to this commit, the compiler produced:

```js
No = (function (e) {
  return (
    (e[(e.None = 0)] = "None"),
    (e[(e.HasTransplantedViews = 2)] = "HasTransplantedViews"),
    e
  );
})(No || {});
```

Changing to `const enum` allows it to be entirely dropped and inline values.

PR Close #59416
2025-01-09 10:38:28 -05:00
Sumit Arora ac0a655ad5 fix(devtools): fixing dark mode colors for devtools and router tree (#59329)
added dark mode colors for devtools and router tree  and fixed the router tree legend rerendering issue

PR Close #59329
2025-01-09 10:32:42 -05:00
Ethan Cline 5ec4997ac8 ci: Add self (Ethan Cline) as primitives-shared reviewer. (#59437)
Add self (Ethan Cline) as primitives-shared reviewer.

PR Close #59437
2025-01-09 10:31:31 -05:00
Angular Robot 86a3260ba7 build: update dependency @bazel/buildifier to v8 (#59446)
See associated pull request for more information.

PR Close #59446
2025-01-09 10:30:42 -05:00
zhangenming 621a5d1f59 docs(router): update link to development guide in README.md (#59388)
PR Close #59388
2025-01-09 10:29:40 -05:00
Kristiyan Kostadinov 5906bb07ac docs: add doc page about unused imports schematic (#59449)
Adds a docs for the new `ng generate @angular/core:cleanup-unused-imports` schematic.

PR Close #59449
2025-01-09 10:28:40 -05:00
RafaelJCamara 1223324b26 docs: update license URL from angular.io to angular.dev and year of license to 2025 (#59407)
PR Close #59407
2025-01-09 10:27:54 -05:00
Kristiyan Kostadinov a6a43477bb build: clean up pipeline-specific tests (#59450)
Now that we only have the template pipeline, we can remove the `.pipeline` extension from the files.

PR Close #59450
2025-01-09 09:56:07 -05:00
arturovt 13a51b6b05 refactor(forms): drop CALL_SET_DISABLED_STATE name in production (#59430)
In this commit, we drop the `CALL_SET_DISABLED_STATE` injection token name in production.

PR Close #59430
2025-01-09 09:21:02 -05:00
Jessica Janiuk 77b24cd575 release: cut the v19.1.0-rc.0 release 2025-01-08 10:24:19 -08:00
749 changed files with 29562 additions and 14641 deletions
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -5,9 +5,9 @@ runs:
using: 'composite'
steps:
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/saucelabs@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Starting Saucelabs tunnel service
shell: bash
run: ./tools/saucelabs/sauce-service.sh run &
+1 -1
View File
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
runs:
using: 'composite'
steps:
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4
- uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4
with:
path: |
./node_modules/
+4 -4
View File
@@ -21,16 +21,16 @@ jobs:
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev to ensure it continues to work
run: yarn bazel build //adev:build --full_build_adev --config=release
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@2670abf637fa155971cdd1f7e570a7f234922a65
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@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@2670abf637fa155971cdd1f7e570a7f234922a65
with:
github-token: '${{secrets.GITHUB_TOKEN}}'
workflow-artifact-name: 'adev-preview'
@@ -16,6 +16,6 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: angular/dev-infra/github-actions/branch-manager@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/branch-manager@2670abf637fa155971cdd1f7e570a7f234922a65
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
- uses: ./.github/actions/yarn-install
- uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
with:
bazelrc: ./.bazelrc.user
+24 -22
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@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Install node modules
@@ -41,13 +41,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Run unit tests
@@ -59,13 +59,13 @@ jobs:
runs-on: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile --network-timeout 100000
- name: Run CI tests for framework
@@ -76,30 +76,32 @@ jobs:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev in fast mode to ensure it continues to work
run: yarn bazel build //adev:build --config=release
- name: Run tests
run: yarn bazel test //adev/...
# TODO: re-enable tests once the next release is shipped
# Tests are broken because of https://github.com/angular/angular/issues/54858
# - name: Run tests
# run: yarn bazel test //adev/...
publish-snapshots:
runs-on:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
@@ -111,7 +113,7 @@ jobs:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
node-module-directories: |
@@ -119,9 +121,9 @@ jobs:
./packages/zone.js/node_modules
./packages/zone.js/test/typings/node_modules
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- run: |
@@ -158,7 +160,7 @@ jobs:
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Install node modules
@@ -171,11 +173,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev to ensure it continues to work
+2 -2
View File
@@ -13,13 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: angular/dev-infra/github-actions/commit-message-based-labels@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/commit-message-based-labels@2670abf637fa155971cdd1f7e570a7f234922a65
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
post_approval_changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: angular/dev-infra/github-actions/post-approval-changes@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/post-approval-changes@2670abf637fa155971cdd1f7e570a7f234922a65
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: angular/dev-infra/github-actions/google-internal-tests@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/google-internal-tests@2670abf637fa155971cdd1f7e570a7f234922a65
with:
run-tests-guide-url: http://go/angular-g3sync-start
github-token: ${{ secrets.GITHUB_TOKEN }}
+4 -4
View File
@@ -13,17 +13,17 @@ jobs:
JOBS: 2
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/saucelabs@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Set up Sauce Tunnel Daemon
run: yarn 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@289aa644e65a557bcb21adcf75ad60605a9c9859
- uses: angular/dev-infra/github-actions/unified-status-check@2670abf637fa155971cdd1f7e570a7f234922a65
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@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn -s 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@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn -s install --frozen-lockfile
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
+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@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Install node modules
@@ -39,7 +39,7 @@ jobs:
- name: Check code format
run: yarn ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
- name: Check Package Licenses
uses: angular/dev-infra/github-actions/linting/licenses@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/linting/licenses@2670abf637fa155971cdd1f7e570a7f234922a65
with:
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
@@ -47,13 +47,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Run unit tests
@@ -65,13 +65,13 @@ jobs:
runs-on: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile --network-timeout 100000
- name: Run CI tests for framework
@@ -83,19 +83,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile --network-timeout 100000
- name: Run CI tests for framework
run: yarn tsx ./scripts/build/build-packages-dist.mts
- name: Archive build artifacts
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: pr-artifacts-${{ github.event.number }}
path: dist/packages-dist/
@@ -105,24 +105,26 @@ jobs:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- name: Build adev in fast mode to ensure it continues to work
run: yarn bazel build //adev:build --config=release
- name: Run tests
run: yarn bazel test //adev/...
# TODO: re-enable tests once the next release is shipped
# Tests are broken because of https://github.com/angular/angular/issues/54858
# - name: Run tests
# run: yarn bazel test //adev/...
zone-js:
runs-on:
labels: ubuntu-latest-4core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
node-module-directories: |
@@ -130,9 +132,9 @@ jobs:
./packages/zone.js/node_modules
./packages/zone.js/test/typings/node_modules
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/setup@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/bazel/configure-remote@2670abf637fa155971cdd1f7e570a7f234922a65
- name: Install node modules
run: yarn install --frozen-lockfile
- run: |
@@ -169,7 +171,7 @@ jobs:
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2670abf637fa155971cdd1f7e570a7f234922a65
with:
cache-node-modules: true
- name: Install node modules
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
with:
results_file: results.sarif
results_format: sarif
@@ -39,7 +39,7 @@ jobs:
# Upload the results as artifacts.
- name: 'Upload artifact'
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: SARIF file
path: results.sarif
@@ -47,6 +47,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
with:
sarif_file: results.sarif
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
env:
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
- name: Create a PR (if necessary)
uses: angular/dev-infra/github-actions/create-pr-for-changes@289aa644e65a557bcb21adcf75ad60605a9c9859
uses: angular/dev-infra/github-actions/create-pr-for-changes@2670abf637fa155971cdd1f7e570a7f234922a65
with:
branch-prefix: update-cli-help
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
-1
View File
@@ -32,7 +32,6 @@ export const commitMessage: CommitMessageConfig = {
'router',
'service-worker',
'upgrade',
've',
'zone.js',
],
};
+8
View File
@@ -22,4 +22,12 @@ export const pullRequest: PullRequestConfig = {
assertEnforceTested: true,
assertIsolatedSeparateFiles: true,
},
requiredStatuses: [
{type: 'check', name: 'test'},
{type: 'check', name: 'lint'},
{type: 'check', name: 'adev'},
{type: 'check', name: 'zone-js'},
{type: 'status', name: 'google-internal-tests'},
],
};
+1 -1
View File
@@ -1 +1 @@
18.20.0
18.20.5
+10 -4
View File
@@ -56,8 +56,8 @@
version: 3
availability:
users_unavailable: ['atscott']
# availability:
# users_unavailable: ['atscott']
# Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config.
@@ -133,6 +133,7 @@ groups:
- devversion
- kirjs
- JoostK
- mmalerba
# =========================================================
# Framework: General (most code in our packages)
@@ -175,6 +176,7 @@ groups:
- ~jelbourn
- thePunderWoman
- pkozlowski-opensource
- mmalerba
# =========================================================
# Framework: Security-sensitive files which require extra review
@@ -227,9 +229,9 @@ groups:
<<: *defaults
conditions:
- >
contains_any_globs(files, [
contains_any_globs(files.exclude('yarn.lock'), [
'packages/zone.js/**/{*,.*}',
])
])
reviewers:
users:
- JiaLiPassion
@@ -285,6 +287,7 @@ groups:
- mgechev
- MarkTechson
- kirjs
- mmalerba
# =========================================================
# Angular DevTools
@@ -391,6 +394,7 @@ groups:
- thePunderWoman
- pkozlowski-opensource
- kirjs
- mmalerba
- ~iteriani
- ~tbondwilkinson
- ~rahatarmanahmed
@@ -420,6 +424,7 @@ groups:
- ~jelbourn
- thePunderWoman
- pkozlowski-opensource
- mmalerba
reviews:
request: 2 # Request reviews from 2 people
required: 1 # Require that 1 person approve
@@ -516,6 +521,7 @@ groups:
- iteriani # Thomas Nguyen
- tbondwilkinson # Tom Wilkinson
- rahatarmanahmed # Rahat Ahmed
- ENAML # Ethan Cline
labels:
pending: 'requires: TGP'
approved: 'requires: TGP'
+207 -81
View File
@@ -1,3 +1,210 @@
<a name="19.1.8"></a>
# 19.1.8 (2025-02-26)
### benchpress
| Commit | Type | Description |
| -- | -- | -- |
| [f0990c67e6](https://github.com/angular/angular/commit/f0990c67e660c61109fa910885da6aa4beaf576a) | fix | Ensure future-proof correct initialization order ([#60025](https://github.com/angular/angular/pull/60025)) |
### common
| Commit | Type | Description |
| -- | -- | -- |
| [1fbaeab37d](https://github.com/angular/angular/commit/1fbaeab37d5c65436938b6e14e21bc4d57bb517b) | fix | make types for HttpClient more readable ([#59901](https://github.com/angular/angular/pull/59901)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [c611c8d212](https://github.com/angular/angular/commit/c611c8d212b0134365954726c2fd6c98c28e5424) | fix | capture stack for HMR errors ([#60067](https://github.com/angular/angular/pull/60067)) |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [4c9d09c643](https://github.com/angular/angular/commit/4c9d09c643cf1232d1f502ff7d6bd25709ba1c6a) | fix | provide correct rename info for elements ([#60088](https://github.com/angular/angular/pull/60088)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.7"></a>
# 19.1.7 (2025-02-19)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [e9f10eb4c9](https://github.com/angular/angular/commit/e9f10eb4c950692992098619b9628ecefd1b36ce) | fix | clean up `urlChanges` subscribers when root scope is destroyed ([#59703](https://github.com/angular/angular/pull/59703)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [16fc074689](https://github.com/angular/angular/commit/16fc074689d31ef6886c49525b020bc6c1529d0e) | fix | avoid crash in isolated transform operations ([#59869](https://github.com/angular/angular/pull/59869)) |
### forms
| Commit | Type | Description |
| -- | -- | -- |
| [ec1e4c3d94](https://github.com/angular/angular/commit/ec1e4c3d9430f5ea4380252098d2b4b71d8a950f) | fix | Fix typing on `FormRecord`. ([#59993](https://github.com/angular/angular/pull/59993)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.6"></a>
# 19.1.6 (2025-02-12)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [01f669a274](https://github.com/angular/angular/commit/01f669a27425c5034a04274763cc60801f961aa2) | fix | handle tracking expressions requiring temporary variables ([#58520](https://github.com/angular/angular/pull/58520)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [dcfb9f1959](https://github.com/angular/angular/commit/dcfb9f1959164baf45f5f954b4bf681d650d8a2d) | fix | handle deferred blocks with shared dependencies correctly ([#59926](https://github.com/angular/angular/pull/59926)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [cab7a9b69c](https://github.com/angular/angular/commit/cab7a9b69c3a5d789432a87a554e8489c78a0f15) | fix | invalidate HMR component if replacement throws an error ([#59854](https://github.com/angular/angular/pull/59854)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [710759ddcc](https://github.com/angular/angular/commit/710759ddcc0ecbad68deb20821b535fd5deb69c6) | fix | account for let declarations in control flow migration ([#59861](https://github.com/angular/angular/pull/59861)) |
| [46f36a58bf](https://github.com/angular/angular/commit/46f36a58bf3a7b9131b6330e84d4adb3e73f3601) | fix | count used dependencies inside existing control flow ([#59861](https://github.com/angular/angular/pull/59861)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.5"></a>
# 19.1.5 (2025-02-06)
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [d7b5c597ffc](https://github.com/angular/angular/commit/d7b5c597ffcb6469ae3f08a97e7790599d569cc4) | fix | gracefully fall back if const enum cannot be passed through ([#59815](https://github.com/angular/angular/pull/59815)) |
| [53a4668b58b](https://github.com/angular/angular/commit/53a4668b58b645e41baddc5b67d52ede21c8e945) | fix | handle const enums used inside HMR data ([#59815](https://github.com/angular/angular/pull/59815)) |
| [976125e0b4c](https://github.com/angular/angular/commit/976125e0b4cf4e7fb4621a7203e3f43b009885f0) | fix | handle enum members without initializers in partial evaluator ([#59815](https://github.com/angular/angular/pull/59815)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.4"></a>
# 19.1.4 (2025-01-29)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [544b9ee7ca0](https://github.com/angular/angular/commit/544b9ee7ca00925e62b7c74cf7930777a10aaf76) | fix | check whether application is destroyed before printing hydration stats ([#59716](https://github.com/angular/angular/pull/59716)) |
| [d6e78c072dc](https://github.com/angular/angular/commit/d6e78c072dcb5b0b6efc2b098fdb911ccddf6e81) | fix | ensure type is preserved during HMR ([#59700](https://github.com/angular/angular/pull/59700)) |
| [c2436702df9](https://github.com/angular/angular/commit/c2436702df980bbf2db0fe3bee4c72860edb4e63) | fix | fixes test timer-based test flakiness in CI ([#59674](https://github.com/angular/angular/pull/59674)) |
### elements
| Commit | Type | Description |
| -- | -- | -- |
| [44180645992](https://github.com/angular/angular/commit/44180645992f7d9018ccb2d7663530b3cffde36b) | fix | not setting initial value on signal-based input ([#59773](https://github.com/angular/angular/pull/59773)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [1828a840620](https://github.com/angular/angular/commit/1828a8406201827e52549c8afa487bf6364a70c3) | fix | prepend `baseHref` to `sourceMappingURL` in CSS content ([#59730](https://github.com/angular/angular/pull/59730)) |
| [1c84cbca30e](https://github.com/angular/angular/commit/1c84cbca30e6606e6df3f40346989d9434d89bc6) | fix | Update pseudoevent created by createMouseSpecialEvent to populate `_originalEvent` property ([#59690](https://github.com/angular/angular/pull/59690)) |
| [12256574626](https://github.com/angular/angular/commit/12256574626f04f5fe2b41e805f7bdc93d62df0a) | fix | Update pseudoevent created by createMouseSpecialEvent to populate `_originalEvent` property ([#59690](https://github.com/angular/angular/pull/59690)) |
| [3f4d5f636aa](https://github.com/angular/angular/commit/3f4d5f636aac90cabe32ff6c4d75180ced99eb97) | fix | Update pseudoevent created by createMouseSpecialEvent to populate `_originalEvent` property ([#59690](https://github.com/angular/angular/pull/59690)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [e3da35ec749](https://github.com/angular/angular/commit/e3da35ec749395239731158f89e29d47e7a9ef36) | fix | prevent error handling when injector is destroyed ([#59457](https://github.com/angular/angular/pull/59457)) |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [522acbf3d7e](https://github.com/angular/angular/commit/522acbf3d7ed502e7802117776acda3529a9a2b4) | fix | add missing `rxjs` peer dependency ([#59747](https://github.com/angular/angular/pull/59747)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.3"></a>
# 19.1.3 (2025-01-22)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [ecfb74d287](https://github.com/angular/angular/commit/ecfb74d287bec7bec37d0b476b321b047bef2c43) | fix | handle :host-context with comma-separated child selector ([#59276](https://github.com/angular/angular/pull/59276)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [53160e504d](https://github.com/angular/angular/commit/53160e504df44b05f59cacd9afeb40a0e627b744) | fix | extract parenthesized dependencies during HMR ([#59644](https://github.com/angular/angular/pull/59644)) |
| [39690969af](https://github.com/angular/angular/commit/39690969af14914df0c9b5a009b2df920f5c03e7) | fix | handle conditional expressions when extracting dependencies ([#59637](https://github.com/angular/angular/pull/59637)) |
| [78af7a5059](https://github.com/angular/angular/commit/78af7a5059cc3e03704ba63f8512351a40470557) | fix | handle new expressions when extracting dependencies ([#59637](https://github.com/angular/angular/pull/59637)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [408af24ff3](https://github.com/angular/angular/commit/408af24ff3490926e9992cb4f1f71914d71ad6ad) | fix | capture self-referencing component during HMR ([#59644](https://github.com/angular/angular/pull/59644)) |
| [d7575c201c](https://github.com/angular/angular/commit/d7575c201cfd61010952b3a633eec03e32f58220) | fix | replace metadata in place during HMR ([#59644](https://github.com/angular/angular/pull/59644)) |
| [26f6d4c485](https://github.com/angular/angular/commit/26f6d4c485b566d7bc127c78cc163c376d0fe6b5) | fix | skip component ID collision warning during SSR ([#59625](https://github.com/angular/angular/pull/59625)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [a62c84bc18](https://github.com/angular/angular/commit/a62c84bc188d41ea24cf0eca14ac18c4b917ccd0) | fix | avoid applying the same replacements twice when cleaning up unused imports ([#59656](https://github.com/angular/angular/pull/59656)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [b2b3816cb1](https://github.com/angular/angular/commit/b2b3816cb1c5c573dc9368f05fd2971671d7159f) | fix | clear renderer cache during HMR when using async animations ([#59644](https://github.com/angular/angular/pull/59644)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.2"></a>
# 19.1.2 (2025-01-20)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [8dcd889987](https://github.com/angular/angular/commit/8dcd88998700a94115a542462e6ae6beedbfbd9d) | fix | update `@ng/component` URL to be relative ([#59620](https://github.com/angular/angular/pull/59620)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [95a05bb202](https://github.com/angular/angular/commit/95a05bb2021acab02df3468212adf023d331a688) | fix | disable tree shaking during HMR ([#59595](https://github.com/angular/angular/pull/59595)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [a4eb74c79c](https://github.com/angular/angular/commit/a4eb74c79cca802d8179118cf4d53c73285baadb) | fix | animation sometimes renderer not being destroyed during HMR ([#59574](https://github.com/angular/angular/pull/59574)) |
| [906413aba3](https://github.com/angular/angular/commit/906413aba31459e6499420ed14519d1280e182ad) | fix | change `Resource` to use explicit `undefined` in its typings ([#59024](https://github.com/angular/angular/pull/59024)) |
| [4eb541837c](https://github.com/angular/angular/commit/4eb541837cf28ce1950d782213291165a2436410) | fix | cleanup `_ejsa` when app is destroyed ([#59492](https://github.com/angular/angular/pull/59492)) |
| [5497102769](https://github.com/angular/angular/commit/549710276969ec4cf8c1e3d2f19d1fe9f755976e) | fix | cleanup stash listener when app is destroyed ([#59598](https://github.com/angular/angular/pull/59598)) |
| [266a8f2f2e](https://github.com/angular/angular/commit/266a8f2f2ebf9f5e310ba5de695be5072790e1e5) | fix | handle shadow DOM encapsulated component with HMR ([#59597](https://github.com/angular/angular/pull/59597)) |
| [6f7716268a](https://github.com/angular/angular/commit/6f7716268afa5146f2b2d0dbbea146defa9acfef) | fix | HMR not matching component that injects ViewContainerRef ([#59596](https://github.com/angular/angular/pull/59596)) |
| [d12a186d53](https://github.com/angular/angular/commit/d12a186d531b41e6a16f84446a1d54eaed010fc4) | fix | treat exceptions in `equal` as part of computation ([#55818](https://github.com/angular/angular/pull/55818)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.1"></a>
# 19.1.1 (2025-01-16)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [357795cb96](https://github.com/angular/angular/commit/357795cb96a1cd138ec263c468c9de8ca8b2af9c) | fix | run HMR replacement in the zone ([#59562](https://github.com/angular/angular/pull/59562)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [eb0b1851f4](https://github.com/angular/angular/commit/eb0b1851f494adfe72f583763a44bd2528a5956c) | fix | roll back HMR fix ([#59557](https://github.com/angular/angular/pull/59557)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0"></a>
# 19.1.0 (2025-01-15)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [e4c50b3bea](https://github.com/angular/angular/commit/e4c50b3bea22ca2afba74465893c36730952f4b9) | feat | expose component instance in NgComponentOutlet ([#58698](https://github.com/angular/angular/pull/58698)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [ceadd28ea1](https://github.com/angular/angular/commit/ceadd28ea12140e8e78cdb706aff0487f5a87a3c) | fix | allow $any in two-way bindings ([#59362](https://github.com/angular/angular/pull/59362)) |
| [aed49ddaaa](https://github.com/angular/angular/commit/aed49ddaaa40d6e6816198b47ceada4e98cd636c) | fix | use chunk origin in template HMR request URL ([#59459](https://github.com/angular/angular/pull/59459)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [c5c20e9d86](https://github.com/angular/angular/commit/c5c20e9d86d72b33840dcf0adea02876437a589f) | fix | check event side of two-way bindings ([#59002](https://github.com/angular/angular/pull/59002)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [d010e11b73](https://github.com/angular/angular/commit/d010e11b735562ded439989ddb84cc83c6c00e81) | feat | add event listener options to renderer ([#59092](https://github.com/angular/angular/pull/59092)) |
| [57f3550219](https://github.com/angular/angular/commit/57f3550219f2a57c7c26c9183e48ee66845e0439) | feat | add utility for resolving defer block information to ng global ([#59184](https://github.com/angular/angular/pull/59184)) |
| [22f191f763](https://github.com/angular/angular/commit/22f191f76339a08bb8f0f2dfbc60dde0f2e38e73) | feat | extend the set of profiler events ([#59183](https://github.com/angular/angular/pull/59183)) |
| [e894a5daea](https://github.com/angular/angular/commit/e894a5daea401b4e1173b0e66557ae40140eb9a0) | feat | set kind field on template and effect nodes ([#58865](https://github.com/angular/angular/pull/58865)) |
| [bd1f1294ae](https://github.com/angular/angular/commit/bd1f1294aeb0d47b24421b7b7a608988689a459f) | feat | support TypeScript 5.7 ([#58609](https://github.com/angular/angular/pull/58609)) |
| [9870b643bf](https://github.com/angular/angular/commit/9870b643bff46f089a3f0a30514fb7e062a66d56) | fix | Defer afterRender until after first CD ([#58250](https://github.com/angular/angular/pull/58250)) |
| [a5fc962094](https://github.com/angular/angular/commit/a5fc9620948c59da2146d46d27de388839b93254) | fix | Don't run effects in check no changes pass ([#58250](https://github.com/angular/angular/pull/58250)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [d298d25426](https://github.com/angular/angular/commit/d298d254269ff759111fbdef7736bc8b713638bc) | feat | add schematic to clean up unused imports ([#59353](https://github.com/angular/angular/pull/59353)) |
| [14fb8ce4c0](https://github.com/angular/angular/commit/14fb8ce4c00fc458cfbe1d7f2c85638c6165b636) | fix | resolve text replacement issue ([#59452](https://github.com/angular/angular/pull/59452)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [8c5db3cfb7](https://github.com/angular/angular/commit/8c5db3cfb75700dd64f4c8c073554c7086835950) | fix | avoid circular DI error in async renderer ([#59256](https://github.com/angular/angular/pull/59256)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [52a6710f54](https://github.com/angular/angular/commit/52a6710f54bcec81f4cde23a78b9f78d038156c5) | fix | complete router `events` on dispose ([#59327](https://github.com/angular/angular/pull/59327)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.6"></a>
# 19.0.6 (2025-01-08)
### compiler-cli
@@ -21,22 +228,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0-next.4"></a>
# 19.1.0-next.4 (2024-12-18)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [57f3550219](https://github.com/angular/angular/commit/57f3550219f2a57c7c26c9183e48ee66845e0439) | feat | add utility for resolving defer block information to ng global ([#59184](https://github.com/angular/angular/pull/59184)) |
| [22f191f763](https://github.com/angular/angular/commit/22f191f76339a08bb8f0f2dfbc60dde0f2e38e73) | feat | extend the set of profiler events ([#59183](https://github.com/angular/angular/pull/59183)) |
| [1f4ff2fa36](https://github.com/angular/angular/commit/1f4ff2fa36f5d6240cbc4a40839d3d89501519d8) | fix | avoid triggering `on timer` and `on idle` on the server ([#59177](https://github.com/angular/angular/pull/59177)) |
| [cf89f14766](https://github.com/angular/angular/commit/cf89f14766b0ed0204f7012d44a4732fccb35398) | fix | Fix nested timer serialization ([#59173](https://github.com/angular/angular/pull/59173)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [300b141cc8](https://github.com/angular/angular/commit/300b141cc8652fd714b02f05c943cb79167ea844) | fix | Warn user when transfer state happens more than once ([#58935](https://github.com/angular/angular/pull/58935)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.5"></a>
# 19.0.5 (2024-12-18)
### core
@@ -51,26 +242,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0-next.3"></a>
# 19.1.0-next.3 (2024-12-12)
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [c5c20e9d86](https://github.com/angular/angular/commit/c5c20e9d86d72b33840dcf0adea02876437a589f) | fix | check event side of two-way bindings ([#59002](https://github.com/angular/angular/pull/59002)) |
| [0dee2681f7](https://github.com/angular/angular/commit/0dee2681f782106fdb0fdcf9bc6ad1bca562751d) | fix | consider pre-release versions when detecting feature support ([#59061](https://github.com/angular/angular/pull/59061)) |
| [1b9492edf8](https://github.com/angular/angular/commit/1b9492edf88f8a217c0fd1a8203df489d91b623b) | fix | error in unused standalone imports diagnostic ([#59064](https://github.com/angular/angular/pull/59064)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [d010e11b73](https://github.com/angular/angular/commit/d010e11b735562ded439989ddb84cc83c6c00e81) | feat | add event listener options to renderer ([#59092](https://github.com/angular/angular/pull/59092)) |
| [30e676098d](https://github.com/angular/angular/commit/30e676098d72e9e11a6628b9716668df08f18c62) | fix | Fix a bug where snapshotted functions are being run twice if they return a nullish/falsey value. ([#59073](https://github.com/angular/angular/pull/59073)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [52be35118f](https://github.com/angular/angular/commit/52be35118feee587d2efe5a6c55502c171caaa97) | fix | collect external component styles from server rendering ([#59031](https://github.com/angular/angular/pull/59031)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.4"></a>
# 19.0.4 (2024-12-12)
### compiler-cli
@@ -89,43 +260,11 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0-next.2"></a>
# 19.1.0-next.2 (2024-12-04)
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.3"></a>
# 19.0.3 (2024-12-04)
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0-next.1"></a>
# 19.1.0-next.1 (2024-12-04)
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [f280467398](https://github.com/angular/angular/commit/f280467398c6980878b5e755a78606251814447b) | fix | account for multiple generated namespace imports in HMR ([#58924](https://github.com/angular/angular/pull/58924)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [e894a5daea](https://github.com/angular/angular/commit/e894a5daea401b4e1173b0e66557ae40140eb9a0) | feat | set kind field on template and effect nodes ([#58865](https://github.com/angular/angular/pull/58865)) |
| [3b765367f3](https://github.com/angular/angular/commit/3b765367f31b6d1bb32406505f18151acdf1f2b2) | fix | Explicitly manage TracingSnapshot lifecycle and dispose of it once it's been used. ([#58929](https://github.com/angular/angular/pull/58929)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [e31e52e177](https://github.com/angular/angular/commit/e31e52e1771ea565a6869b4ed252d6ff7097d4ad) | fix | class content being deleted in some edge cases ([#58959](https://github.com/angular/angular/pull/58959)) |
| [508d3a1b3b](https://github.com/angular/angular/commit/508d3a1b3bc5770f18e3e46e2105bf0ba6178a87) | fix | correctly strip away parameters surrounded by comments in inject migration ([#58959](https://github.com/angular/angular/pull/58959)) |
| [7191aa6e09](https://github.com/angular/angular/commit/7191aa6e09ca3b85efd3fd14a18944eac4384763) | fix | don't migrate classes with parameters that can't be injected ([#58959](https://github.com/angular/angular/pull/58959)) |
| [a4924af6d5](https://github.com/angular/angular/commit/a4924af6d580c5bdaa185c4c97277c4effb55af9) | fix | inject migration aggressively removing imports ([#58959](https://github.com/angular/angular/pull/58959)) |
| [35165d152d](https://github.com/angular/angular/commit/35165d152d7f9c3c8789ebdf792037aafdc1cc66) | fix | inject migration dropping code if everything except super is removed ([#58959](https://github.com/angular/angular/pull/58959)) |
| [68e5ba7a3a](https://github.com/angular/angular/commit/68e5ba7a3a44c2f1647c4c6cc7ed66b010f85d15) | fix | preserve type literals and tuples in inject migrations ([#58959](https://github.com/angular/angular/pull/58959)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [1cfbfc66d3](https://github.com/angular/angular/commit/1cfbfc66d3a24b6c41abf13550e7c2911e20b550) | fix | remove peer dependency on animations ([#58997](https://github.com/angular/angular/pull/58997)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.2"></a>
# 19.0.2 (2024-12-04)
### compiler-cli
@@ -161,19 +300,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.1.0-next.0"></a>
# 19.1.0-next.0 (2024-11-26)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [e4c50b3bea](https://github.com/angular/angular/commit/e4c50b3bea22ca2afba74465893c36730952f4b9) | feat | expose component instance in NgComponentOutlet ([#58698](https://github.com/angular/angular/pull/58698)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [bd1f1294ae](https://github.com/angular/angular/commit/bd1f1294aeb0d47b24421b7b7a608988689a459f) | feat | support TypeScript 5.7 ([#58609](https://github.com/angular/angular/pull/58609)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="19.0.1"></a>
# 19.0.1 (2024-11-26)
### compiler-cli
+2
View File
@@ -125,6 +125,7 @@ Help us keep Angular open and inclusive. Please read and follow our [Code of Con
Join the conversation and help the community.
- [X (formerly Twitter)][X (formerly Twitter)]
- [Bluesky][bluesky]
- [Discord][discord]
- [Gitter][gitter]
- [YouTube][youtube]
@@ -154,6 +155,7 @@ Join the conversation and help the community.
[npm]: https://www.npmjs.com/get-npm
[codeofconduct]: CODE_OF_CONDUCT.md
[X (formerly Twitter)]: https://www.twitter.com/angular
[bluesky]: https://bsky.app/profile/angular.dev
[discord]: https://discord.gg/angular
[gitter]: https://gitter.im/angular/angular
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular
+12 -12
View File
@@ -50,16 +50,16 @@ load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
nodejs_register_toolchains(
name = "nodejs",
node_repositories = {
"18.20.0-darwin_arm64": ("node-v18.20.0-darwin-arm64.tar.gz", "node-v18.20.0-darwin-arm64", "10066ad4dd9e03ea5c4c45ef8775420ff37b860de09bbdf87b97e0c07b1ea036"),
"18.20.0-darwin_amd64": ("node-v18.20.0-darwin-x64.tar.gz", "node-v18.20.0-darwin-x64", "062ba71618e88e06321de5caa038843c350aababa2d315f3ca7b8551f8e66c1c"),
"18.20.0-linux_arm64": ("node-v18.20.0-linux-arm64.tar.xz", "node-v18.20.0-linux-arm64", "afe51da9ffb38ac1e3a20d9a06efd403ced4bf8831ab554a02a088dd8392fd79"),
"18.20.0-linux_ppc64le": ("node-v18.20.0-linux-ppc64le.tar.xz", "node-v18.20.0-linux-ppc64le", "9e652bbf53a3e37285b11dfb9d6a9bb8b02010c3b50e5c8229d4cc10e72681da"),
"18.20.0-linux_s390x": ("node-v18.20.0-linux-s390x.tar.xz", "node-v18.20.0-linux-s390x", "a6c2a5796b9d9e9bf21da62ec89ff30b41a8108880b9eaa3c912f1ce795a7743"),
"18.20.0-linux_amd64": ("node-v18.20.0-linux-x64.tar.xz", "node-v18.20.0-linux-x64", "03eea148e56785babb27930b05ed6bf311aaa3bc573c0399dd63cad2fe5713c7"),
"18.20.0-windows_amd64": ("node-v18.20.0-win-x64.zip", "node-v18.20.0-win-x64", "1c0aab05cc6836a8f5148cca345b92ebc948a4a2013f18d117b7ade6ff05aca6"),
"18.20.5-darwin_arm64": ("node-v18.20.5-darwin-arm64.tar.gz", "node-v18.20.5-darwin-arm64", "bdfeaf59dbf29aec08c0c66130edf0a8a17014b4f2997727641dfd0b58b51f48"),
"18.20.5-darwin_amd64": ("node-v18.20.5-darwin-x64.tar.gz", "node-v18.20.5-darwin-x64", "dff01068da7d3fe7b515f72a3903dca96a34dc377f6f426b6a813901274b6441"),
"18.20.5-linux_arm64": ("node-v18.20.5-linux-arm64.tar.xz", "node-v18.20.5-linux-arm64", "a77db6ab34267f3bc80e02ed68abf51b7065eb5c82fcd69adc4b40e390d9b116"),
"18.20.5-linux_ppc64le": ("node-v18.20.5-linux-ppc64le.tar.xz", "node-v18.20.5-linux-ppc64le", "63b4c6801c96fb452e3bd8125e8b5b195ecacc4fa2505e47a128e94587999aeb"),
"18.20.5-linux_s390x": ("node-v18.20.5-linux-s390x.tar.xz", "node-v18.20.5-linux-s390x", "617d7456e16534a4b4e03f5285cc8d13581f39cdad9196efff2516d6588de319"),
"18.20.5-linux_amd64": ("node-v18.20.5-linux-x64.tar.xz", "node-v18.20.5-linux-x64", "e4a3a21e5ac7e074ed50d2533dd0087d8460647ab567464867141a2b643f3fb3"),
"18.20.5-windows_amd64": ("node-v18.20.5-win-x64.zip", "node-v18.20.5-win-x64", "910237449895b4de61026568dc076fa6c3ffcd667563ed03112a4a77e1f1556b"),
},
# We need at least Node 18.17 due to some transitive dependencies.
node_version = "18.20.0",
# We need at least Node 18.20.5 due to some transitive dependencies.
node_version = "18.20.5",
)
# Download npm dependencies.
@@ -143,10 +143,10 @@ cldr_xml_data_repository(
# sass rules
http_archive(
name = "io_bazel_rules_sass",
sha256 = "0eae9a0c840e1e0d0b9ace056f8bde06384315315c4e2ebdb5cec722d1d4134b",
strip_prefix = "rules_sass-aff53ca13ff2af82d323adb02a83c45a301e9ae8",
sha256 = "e8b863f6be5609c6ed15664d12512ee36d93e8bcb2c1a331f85d9e8758a82ee7",
strip_prefix = "rules_sass-3b3667fd5861b06a03bea1f1946b55ac7100d4ea",
urls = [
"https://github.com/bazelbuild/rules_sass/archive/aff53ca13ff2af82d323adb02a83c45a301e9ae8.zip",
"https://github.com/bazelbuild/rules_sass/archive/3b3667fd5861b06a03bea1f1946b55ac7100d4ea.zip",
],
)
+1 -1
View File
@@ -6,7 +6,7 @@ The content is written primarily in Markdown format located in `src/content`. Fo
## Local Development
For local development, [yarn](https://yarnpkg.com/) is the preferred package manager. You can setup a local environment with the following commands
For local development, [yarn](https://yarnpkg.com/) is the preferred package manager. You can set up a local environment with the following commands
:
```bash
@@ -24,13 +24,13 @@
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
transition: background-color 0.3s ease;
background-color: var(--septenary-contrast);
@include mq.for-tablet-landscape-down {
background-color: var(--quinary-contrast);
}
border-radius: 10px;
transition: background-color 0.3s ease;
}
&::-webkit-scrollbar-thumb:hover {
@@ -2,6 +2,8 @@ dialog {
background-color: transparent;
border: none;
padding-block-end: 3rem;
margin: 0 auto;
top: 15vh;
&::backdrop {
backdrop-filter: blur(5px);
@@ -6,26 +6,26 @@
<ul class="docs-faceted-list">
<!-- TODO: Hide li elements with class docs-toc-item-h3 for laptop, table and phone screen resolutions -->
@for (item of tableOfContentItems(); track item.id) {
<li
class="docs-faceted-list-item"
[class.docs-toc-item-h2]="item.level === TableOfContentsLevel.H2"
[class.docs-toc-item-h3]="item.level === TableOfContentsLevel.H3"
>
<a
routerLink="."
[fragment]="item.id"
[class.docs-faceted-list-item-active]="item.id === activeItemId()"
<li
class="docs-faceted-list-item"
[class.docs-toc-item-h2]="item.level === TableOfContentsLevel.H2"
[class.docs-toc-item-h3]="item.level === TableOfContentsLevel.H3"
>
{{ item.title }}
</a>
</li>
<!-- Not using routerLink + fragment because of: https://github.com/angular/angular/issues/30139 -->
<a
[href]="location.path() + '#' + item.id"
[class.docs-faceted-list-item-active]="item.id === activeItemId()"
>
{{ item.title }}
</a>
</li>
}
</ul>
</nav>
@if (shouldDisplayScrollToTop()) {
<button type="button" (click)="scrollToTop()">
<docs-icon role="presentation">arrow_upward_alt</docs-icon>
Back to the top
</button>
<button type="button" (click)="scrollToTop()">
<docs-icon role="presentation">arrow_upward_alt</docs-icon>
Back to the top
</button>
}
</aside>
@@ -14,7 +14,7 @@ import {
computed,
inject,
} from '@angular/core';
import {RouterLink} from '@angular/router';
import {Location} from '@angular/common';
import {TableOfContentsLevel} from '../../interfaces/index';
import {TableOfContentsLoader} from '../../services/table-of-contents-loader.service';
import {TableOfContentsScrollSpy} from '../../services/table-of-contents-scroll-spy.service';
@@ -25,11 +25,12 @@ import {IconComponent} from '../icon/icon.component';
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './table-of-contents.component.html',
styleUrls: ['./table-of-contents.component.scss'],
imports: [RouterLink, IconComponent],
imports: [IconComponent],
})
export class TableOfContents {
// Element that contains the content from which the Table of Contents is built
readonly contentSourceElement = input.required<HTMLElement>();
readonly location = inject(Location);
private readonly scrollSpy = inject(TableOfContentsScrollSpy);
private readonly tableOfContentsLoader = inject(TableOfContentsLoader);
@@ -112,6 +112,13 @@ describe('DocViewer', () => {
expect(exampleViewer).not.toBeNull();
expect(exampleViewer.componentInstance.view()).toBe(CodeExampleViewMode.SNIPPET);
const checkIcon = fixture.debugElement.query(By.directive(IconComponent));
expect((checkIcon.nativeElement as HTMLElement).classList).toContain(
`material-symbols-outlined`,
);
expect((checkIcon.nativeElement as HTMLElement).classList).toContain(`docs-check`);
expect(checkIcon.nativeElement.innerHTML).toBe('check');
});
it('should display example viewer in multi file mode when user clicks expand', async () => {
@@ -265,9 +265,12 @@ export class DocViewer implements OnChanges {
}
private loadIcons(element: HTMLElement): void {
element.querySelectorAll('docs-icon').forEach((iconsPlaceholder) => {
this.renderComponent(IconComponent, iconsPlaceholder as HTMLElement);
});
// We need to make sure that we don't reload the icons in loadCopySourceCodeButtons
element
.querySelectorAll('docs-icon:not([docs-copy-source-code] docs-icon)')
.forEach((iconsPlaceholder) => {
this.renderComponent(IconComponent, iconsPlaceholder as HTMLElement);
});
}
/**
@@ -290,9 +293,6 @@ export class DocViewer implements OnChanges {
}
}
// Trigger change detection after setting inputs.
componentRef.changeDetectorRef.detectChanges();
// Attach a view to the ApplicationRef for change detection
// purposes and for hydration serialization to pick it up
// during SSG.
@@ -340,7 +340,12 @@ export class DocViewer implements OnChanges {
relativeUrl = hrefAttr;
}
handleHrefClickEventWithRouter(e, this.router, relativeUrl);
// Unless this is a link to an element within the same page, use the Angular router.
// https://github.com/angular/angular/issues/30139
const scrollToElementExists = relativeUrl.startsWith(this.location.path() + '#');
if (!scrollToElementExists) {
handleHrefClickEventWithRouter(e, this.router, relativeUrl);
}
});
});
}
@@ -103,8 +103,6 @@ export class ExampleViewer {
this.snippetCode.set(this.exampleMetadata()?.files[0]);
this.changeDetector.detectChanges();
this.setCodeLinesVisibility();
this.elementRef.nativeElement.setAttribute(
+3 -1
View File
@@ -1,9 +1,11 @@
load("//adev/shared-docs/pipeline:_guides.bzl", _generate_guides = "generate_guides")
load("//adev/shared-docs/pipeline:_stackblitz.bzl", _generate_stackblitz = "generate_stackblitz")
load("//adev/shared-docs/pipeline:_navigation.bzl", _generate_nav_items = "generate_nav_items")
load("//adev/shared-docs/pipeline:_playground.bzl", _generate_playground = "generate_playground")
load("//adev/shared-docs/pipeline:_stackblitz.bzl", _generate_stackblitz = "generate_stackblitz")
load("//adev/shared-docs/pipeline:_tutorial.bzl", _generate_tutorial = "generate_tutorial")
generate_guides = _generate_guides
generate_stackblitz = _generate_stackblitz
generate_playground = _generate_playground
generate_tutorial = _generate_tutorial
generate_nav_items = _generate_nav_items
+10 -10
View File
@@ -2,14 +2,14 @@
"name": "@angular/docs",
"version": "0.0.0-PLACEHOLDER",
"peerDependencies": {
"@angular/cdk": "^19.1.0-next",
"@angular/common": "^19.1.0-next",
"@angular/core": "^19.1.0-next",
"@angular/forms": "^19.1.0-next",
"@angular/material": "^19.1.0-next",
"@angular/platform-browser": "^19.1.0-next",
"@angular/router": "^19.1.0-next",
"@angular/ssr": "^19.1.0-next",
"@angular/cdk": "^19.2.0-next",
"@angular/common": "^19.2.0-next",
"@angular/core": "^19.2.0-next",
"@angular/forms": "^19.2.0-next",
"@angular/material": "^19.2.0-next",
"@angular/platform-browser": "^19.2.0-next",
"@angular/router": "^19.2.0-next",
"@angular/ssr": "^19.2.0-next",
"algoliasearch": "^5.0.0",
"rxjs": "^7.8.1"
},
@@ -20,10 +20,10 @@
"fast-glob": "~3.3.2",
"fflate": "^0.8.2",
"html-entities": "~2.5.2",
"jsdom": "~25.0.0",
"jsdom": "~26.0.0",
"marked": "~15.0.0",
"mermaid": "^11.0.0",
"shiki": "^1.10.3"
"shiki": "^2.0.0"
},
"exports": {
"./styles/*": {
+19
View File
@@ -97,11 +97,24 @@ esbuild_esm_bundle(
],
)
esbuild_esm_bundle(
name = "navigation-bundle",
entry_point = "//adev/shared-docs/pipeline/navigation:index.ts",
output = "navigation.mjs",
platform = "node",
target = "es2022",
visibility = ["//visibility:public"],
deps = [
"//adev/shared-docs/pipeline/navigation",
],
)
exports_files([
"_guides.bzl",
"_stackblitz.bzl",
"_playground.bzl",
"_tutorial.bzl",
"_navigation.bzl",
"BUILD.bazel",
])
@@ -160,3 +173,9 @@ nodejs_binary(
entry_point = "//adev/shared-docs/pipeline:tutorial.mjs",
visibility = ["//visibility:public"],
)
nodejs_binary(
name = "navigation",
entry_point = "//adev/shared-docs/pipeline:navigation.mjs",
visibility = ["//visibility:public"],
)
+61
View File
@@ -0,0 +1,61 @@
load("@build_bazel_rules_nodejs//:providers.bzl", "run_node")
def _generate_nav_items(ctx):
"""Implementation of the navigation items data generator rule"""
# Set the arguments for the actions inputs and output location.
args = ctx.actions.args()
# Use a param file because we may have a large number of inputs.
args.set_param_file_format("multiline")
args.use_param_file("%s", use_always = True)
# Pass the set of source files.
args.add_joined(ctx.files.srcs, join_with = ",")
# Add BUILD file path to the arguments.
args.add(ctx.label.package)
# Add the nav item generation strategy to thte arguments.
args.add(ctx.attr.strategy)
# File declaration of the generated JSON file.
json_output = ctx.actions.declare_file("routes.json")
# Add the path to the output file to the arguments.
args.add(json_output.path)
run_node(
ctx = ctx,
inputs = depset(ctx.files.srcs),
executable = "_generate_nav_items",
outputs = [json_output],
arguments = [args],
)
# The return value describes what the rule is producing. In this case we need to specify
# the "DefaultInfo" with the output json file.
return [DefaultInfo(files = depset([json_output]))]
generate_nav_items = rule(
# Point to the starlark function that will execute for this rule.
implementation = _generate_nav_items,
doc = """Rule that generates navigation items data.""",
# The attributes that can be set to this rule.
attrs = {
"srcs": attr.label_list(
doc = """Markdown files that represent the page contents.""",
allow_empty = False,
allow_files = True,
),
"strategy": attr.string(
doc = """Represents the navigation items generation strategy.""",
),
"_generate_nav_items": attr.label(
default = Label("//adev/shared-docs/pipeline:navigation"),
executable = True,
cfg = "exec",
),
},
)
@@ -43,6 +43,7 @@ const MD_CTYPE_MAP: {[key in FileType]: string} = {
export function interpolateCodeExamples(entries: DocEntry[]): void {
for (const entry of entries) {
entry.rawComment = replaceExample(entry.rawComment);
entry.description = replaceExample(entry.description);
for (const jsdocTag of entry.jsdocTags) {
jsdocTag.comment = replaceExample(jsdocTag.comment);
@@ -15,7 +15,7 @@ const tsMdBlock = (code: string) => '```angular-ts\n' + code + '\n```';
const htmlMdBlock = (code: string) => '```angular-html\n' + code + '\n```';
const entriesBuilder = (comment: string): DocEntry[] => [
{jsdocTags: [], rawComment: comment} as unknown as DocEntry,
{jsdocTags: [], rawComment: comment, description: ''} as unknown as DocEntry,
];
const getComment = (entries: DocEntry[]) => entries[0].rawComment;
@@ -35,6 +35,7 @@ describe('interpolate_code_examples', () => {
},
],
rawComment: `{@example dummy/jsdocs_raw.ts region='function'}`,
description: `{@example dummy/jsdocs_raw.ts region='function'}`,
},
];
@@ -8,13 +8,13 @@
// TODO(jelbourn): all of these CSS classes should use the `docs-` prefix.
export const API_REFERENCE_CONTAINER = 'docs-api';
export const PARAM_KEYWORD_CLASS_NAME = 'docs-param-keyword';
export const PARAM_GROUP_CLASS_NAME = 'docs-param-group';
export const REFERENCE_HEADER = 'docs-reference-header';
export const REFERENCE_MEMBERS = 'docs-reference-members';
export const REFERENCE_DEPRECATED = 'docs-reference-deprecated';
export const REFERENCE_MEMBERS_CONTAINER = 'docs-reference-members-container';
export const REFERENCE_MEMBER_CARD = 'docs-reference-member-card';
export const REFERENCE_MEMBER_CARD_HEADER = 'docs-reference-card-header';
export const REFERENCE_MEMBER_CARD_BODY = 'docs-reference-card-body';
@@ -24,3 +24,6 @@ export const HEADER_CLASS_NAME = 'docs-reference-header';
export const HEADER_ENTRY_CATEGORY = 'docs-reference-category';
export const HEADER_ENTRY_TITLE = 'docs-reference-title';
export const HEADER_ENTRY_LABEL = 'docs-api-item-label';
export const SECTION_CONTAINER = 'docs-reference-section';
export const SECTION_HEADING = 'docs-reference-section-heading';
@@ -13,7 +13,7 @@ import {
isPropertyEntry,
isSetterEntry,
} from '../entities/categorization';
import {MemberEntryRenderable} from '../entities/renderables';
import {MemberEntryRenderable, MethodEntryRenderable} from '../entities/renderables';
import {
REFERENCE_MEMBER_CARD,
REFERENCE_MEMBER_CARD_BODY,
@@ -27,20 +27,24 @@ import {getFunctionMetadataRenderable} from '../transforms/function-transforms';
import {CodeSymbol} from './code-symbols';
export function ClassMember(props: {member: MemberEntryRenderable}) {
const member = props.member;
const renderMethod = (method: MethodEntryRenderable) => {
const signature = method.signatures.length ? method.signatures : [method.implementation];
return signature.map((sig) => {
const renderableMember = getFunctionMetadataRenderable(sig);
return <ClassMethodInfo entry={renderableMember} options={{showUsageNotes: true}} />;
});
};
const body = (
<div className={REFERENCE_MEMBER_CARD_BODY}>
{isClassMethodEntry(props.member) ? (
(props.member.signatures.length
? props.member.signatures
: [props.member.implementation]
).map((sig) => {
const renderableMember = getFunctionMetadataRenderable(sig);
return <ClassMethodInfo entry={renderableMember} options={{showUsageNotes: true}} />;
})
) : props.member.htmlDescription || props.member.deprecationMessage ? (
{isClassMethodEntry(member) ? (
renderMethod(member)
) : member.htmlDescription || member.deprecationMessage ? (
<div className={REFERENCE_MEMBER_CARD_ITEM}>
<DeprecatedLabel entry={props.member} />
<RawHtml value={props.member.htmlDescription} />
<DeprecatedLabel entry={member} />
<RawHtml value={member.htmlDescription} />
</div>
) : (
<></>
@@ -48,23 +52,19 @@ export function ClassMember(props: {member: MemberEntryRenderable}) {
</div>
);
const memberName = props.member.name;
const returnType = getMemberType(props.member);
const memberName = member.name;
const returnType = getMemberType(member);
return (
<div id={memberName} className={REFERENCE_MEMBER_CARD} tabIndex={-1}>
<header>
<div className={REFERENCE_MEMBER_CARD_HEADER}>
<h3>{memberName}</h3>
<div>
{isClassMethodEntry(props.member) && props.member.signatures.length > 1 ? (
<span>{props.member.signatures.length} overloads</span>
) : returnType ? (
<CodeSymbol code={returnType} />
) : (
<></>
)}
</div>
</div>
<div id={memberName} className={REFERENCE_MEMBER_CARD}>
<header className={REFERENCE_MEMBER_CARD_HEADER}>
<h3>{memberName}</h3>
{isClassMethodEntry(member) && member.signatures.length > 1 ? (
<span>{member.signatures.length} overloads</span>
) : returnType ? (
<CodeSymbol code={returnType} />
) : (
<></>
)}
</header>
{body}
</div>
@@ -10,26 +10,26 @@ import {Fragment, h} from 'preact';
import {ClassEntryRenderable, DecoratorEntryRenderable} from '../entities/renderables';
import {ClassMemberList} from './class-member-list';
import {HeaderApi} from './header-api';
import {REFERENCE_MEMBERS_CONTAINER} from '../styling/css-classes';
import {TabDescription} from './tab-description';
import {TabUsageNotes} from './tab-usage-notes';
import {TabApi} from './tab-api';
import {API_REFERENCE_CONTAINER, REFERENCE_MEMBERS} from '../styling/css-classes';
import {SectionDescription} from './section-description';
import {SectionUsageNotes} from './section-usage-notes';
import {SectionApi} from './section-api';
/** Component to render a class API reference document. */
export function ClassReference(entry: ClassEntryRenderable | DecoratorEntryRenderable) {
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabApi entry={entry} />
<TabDescription entry={entry} />
<TabUsageNotes entry={entry} />
<SectionApi entry={entry} />
{entry.members.length > 0 ? (
<div class={REFERENCE_MEMBERS_CONTAINER}>
<div class={REFERENCE_MEMBERS}>
<ClassMemberList members={entry.members} />
</div>
) : (
<></>
)}
<SectionDescription entry={entry} />
<SectionUsageNotes entry={entry} />
</div>
);
}
@@ -9,17 +9,12 @@
import {Fragment, h} from 'preact';
import {CliCardRenderable} from '../entities/renderables';
import {DeprecatedLabel} from './deprecated-label';
import { REFERENCE_MEMBER_CARD, REFERENCE_MEMBER_CARD_HEADER } from '../styling/css-classes';
import {REFERENCE_MEMBER_CARD, REFERENCE_MEMBER_CARD_BODY} from '../styling/css-classes';
export function CliCard(props: {card: CliCardRenderable}) {
return (
<div id={props.card.type} class={REFERENCE_MEMBER_CARD} tabIndex={-1}>
<header>
<div class={REFERENCE_MEMBER_CARD_HEADER}>
<h3>{props.card.type}</h3>
</div>
</header>
<div class="docs-reference-card-body">
<div class={REFERENCE_MEMBER_CARD}>
<div className={REFERENCE_MEMBER_CARD_BODY}>
{props.card.items.map((item) => (
<div class="docs-ref-content">
{item.deprecated ? <DeprecatedLabel entry={item} /> : <></>}
@@ -6,55 +6,74 @@
* found in the LICENSE file at https://angular.dev/license
*/
import { Fragment, h } from 'preact';
import { CliCommandRenderable } from '../entities/renderables';
import { REFERENCE_MEMBERS, REFERENCE_MEMBERS_CONTAINER } from '../styling/css-classes';
import { CliCard } from './cli-card';
import { HeaderCli } from './header-cli';
import { RawHtml } from './raw-html';
import {Fragment, h} from 'preact';
import {CliCommandRenderable} from '../entities/renderables';
import {REFERENCE_MEMBERS} from '../styling/css-classes';
import {CliCard} from './cli-card';
import {HeaderCli} from './header-cli';
import {RawHtml} from './raw-html';
import {SectionHeading} from './section-heading';
/** Component to render a CLI command reference document. */
export function CliCommandReference(entry: CliCommandRenderable) {
return (
<div className="cli">
<div className="docs-cli">
<div className="docs-reference-cli-content">
<HeaderCli command={entry} />
{[entry.name, ...entry.aliases].map((command) =>
{[entry.name, ...entry.aliases].map((command) => (
<div class="docs-code docs-reference-cli-toc">
<pre class="docs-mini-scroll-track">
<code>
<div className={'shiki line cli'}>
ng {commandName(entry, command)}
{entry.argumentsLabel ? <button member-id={'Arguments'} className="shiki-ln-line-argument">{entry.argumentsLabel}</button> : <></>}
{entry.hasOptions ? <button member-id={'Options'} className="shiki-ln-line-option">[options]</button> : <></>}
{entry.argumentsLabel ? (
<button member-id={'Arguments'} className="shiki-ln-line-argument">
{entry.argumentsLabel}
</button>
) : (
<></>
)}
{entry.hasOptions ? (
<button member-id={'Options'} className="shiki-ln-line-option">
[options]
</button>
) : (
<></>
)}
</div>
</code>
</pre>
</div>
))}
<RawHtml value={entry.htmlDescription} />
{entry.subcommands && entry.subcommands?.length > 0 ? (
<>
<h3>Sub-commands</h3>
<p>This command has the following sub-commands</p>
<ul>
{entry.subcommands.map((subcommand) => (
<li>
<a href={`cli/${entry.name}/${subcommand.name}`}>{subcommand.name}</a>
</li>
))}
</ul>
</>
) : (
<></>
)}
<RawHtml value={entry.htmlDescription}/>
{entry.subcommands && entry.subcommands?.length > 0 ? <>
<h3>Sub-commands</h3>
<p>This command has the following sub-commands</p>
<ul>
{entry.subcommands.map((subcommand) =>
<li>
<a href={`cli/${entry.name}/${subcommand.name}`}>{subcommand.name}</a>
</li>
)}
</ul>
</> : <></>}
</div>
<div className={REFERENCE_MEMBERS_CONTAINER}>
<div className={REFERENCE_MEMBERS}>
{entry.cards.map((card) => <CliCard card={card} />)}
</div>
<div className={REFERENCE_MEMBERS}>
{entry.cards.map((card) => (
<>
<SectionHeading name={card.type} />
<CliCard card={card} />
</>
))}
</div>
</div>
);
}
function commandName(entry: CliCommandRenderable, command: string) {
if (entry.parentCommand?.name) {
return `${entry.parentCommand?.name} ${command}`;
@@ -9,18 +9,19 @@
import {h} from 'preact';
import {ConstantEntryRenderable} from '../entities/renderables';
import {HeaderApi} from './header-api';
import {TabDescription} from './tab-description';
import {TabUsageNotes} from './tab-usage-notes';
import {TabApi} from './tab-api';
import {SectionDescription} from './section-description';
import {SectionUsageNotes} from './section-usage-notes';
import {SectionApi} from './section-api';
import {API_REFERENCE_CONTAINER} from '../styling/css-classes';
/** Component to render a constant API reference document. */
export function ConstantReference(entry: ConstantEntryRenderable) {
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabApi entry={entry} />
<TabDescription entry={entry} />
<TabUsageNotes entry={entry} />
<SectionApi entry={entry} />
<SectionDescription entry={entry} />
<SectionUsageNotes entry={entry} />
</div>
);
}
@@ -9,14 +9,15 @@
import {h} from 'preact';
import {DocEntryRenderable} from '../entities/renderables';
import {HeaderApi} from './header-api';
import {TabDescription} from './tab-description';
import {SectionDescription} from './section-description';
import {API_REFERENCE_CONTAINER} from '../styling/css-classes';
/** Component to render a block or element API reference document. */
export function DocsReference(entry: DocEntryRenderable) {
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabDescription entry={entry} />
<SectionDescription entry={entry} />
</div>
);
}
@@ -9,29 +9,27 @@
import {h, Fragment} from 'preact';
import {EnumEntryRenderable, MemberEntryRenderable} from '../entities/renderables';
import {HeaderApi} from './header-api';
import {TabDescription} from './tab-description';
import {TabApi} from './tab-api';
import {REFERENCE_MEMBERS, REFERENCE_MEMBERS_CONTAINER} from '../styling/css-classes';
import {SectionDescription} from './section-description';
import {SectionApi} from './section-api';
import {API_REFERENCE_CONTAINER, REFERENCE_MEMBERS} from '../styling/css-classes';
import {ClassMember} from './class-member';
/** Component to render a enum API reference document. */
export function EnumReference(entry: EnumEntryRenderable) {
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabApi entry={entry} />
<TabDescription entry={entry} />
{
entry.members.length > 0
? (
<div class={REFERENCE_MEMBERS_CONTAINER}>
<div class={REFERENCE_MEMBERS}>
{entry.members.map((member: MemberEntryRenderable) => (<ClassMember member={member}/>))}
</div>
</div>
)
: (<></>)
}
<SectionApi entry={entry} />
{entry.members.length > 0 ? (
<div class={REFERENCE_MEMBERS}>
{entry.members.map((member: MemberEntryRenderable) => (
<ClassMember member={member} />
))}
</div>
) : (
<></>
)}
<SectionDescription entry={entry} />
</div>
);
}
@@ -6,20 +6,23 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {h} from 'preact';
import {FunctionEntryRenderable, FunctionSignatureMetadataRenderable} from '../entities/renderables';
import {h, Fragment} from 'preact';
import {
FunctionEntryRenderable,
FunctionSignatureMetadataRenderable,
} from '../entities/renderables';
import {
API_REFERENCE_CONTAINER,
REFERENCE_MEMBERS,
REFERENCE_MEMBERS_CONTAINER,
REFERENCE_MEMBER_CARD,
REFERENCE_MEMBER_CARD_BODY,
REFERENCE_MEMBER_CARD_HEADER,
} from '../styling/css-classes';
import {ClassMethodInfo} from './class-method-info';
import {HeaderApi} from './header-api';
import {TabApi} from './tab-api';
import {TabDescription} from './tab-description';
import {TabUsageNotes} from './tab-usage-notes';
import {SectionApi} from './section-api';
import {SectionDescription} from './section-description';
import {SectionUsageNotes} from './section-usage-notes';
import {HighlightTypeScript} from './highlight-ts';
import {printInitializerFunctionSignatureLine} from '../transforms/code-transforms';
import {getFunctionMetadataRenderable} from '../transforms/function-transforms';
@@ -32,8 +35,8 @@ export const signatureCard = (
printSignaturesAsHeader: boolean,
) => {
return (
<div class={REFERENCE_MEMBER_CARD} id={opts.id} tabIndex={-1}>
<header>
<div id={opts.id} class={REFERENCE_MEMBER_CARD}>
<header class={REFERENCE_MEMBER_CARD_HEADER}>
{printSignaturesAsHeader ? (
<code>
<HighlightTypeScript
@@ -46,12 +49,12 @@ export const signatureCard = (
/>
</code>
) : (
<div className={REFERENCE_MEMBER_CARD_HEADER}>
<>
<h3>{name}</h3>
<div>
<CodeSymbol code={signature.returnType} />
</div>
</div>
</>
)}
</header>
<div class={REFERENCE_MEMBER_CARD_BODY}>
@@ -67,25 +70,24 @@ export function FunctionReference(entry: FunctionEntryRenderable) {
const printSignaturesAsHeader = entry.signatures.length > 1;
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabApi entry={entry} />
<TabDescription entry={entry} />
<TabUsageNotes entry={entry} />
<div className={REFERENCE_MEMBERS_CONTAINER}>
<div className={REFERENCE_MEMBERS}>
{entry.signatures.map((s, i) =>
signatureCard(
s.name,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${s.name}_${i}`,
},
printSignaturesAsHeader,
),
)}
</div>
<SectionApi entry={entry} />
<div className={REFERENCE_MEMBERS}>
{entry.signatures.map((s, i) =>
signatureCard(
s.name,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${s.name}_${i}`,
},
printSignaturesAsHeader,
),
)}
</div>
<SectionDescription entry={entry} />
<SectionUsageNotes entry={entry} />
</div>
);
}
@@ -9,9 +9,9 @@
import {h, JSX} from 'preact';
import {InitializerApiFunctionRenderable} from '../entities/renderables';
import {HeaderApi} from './header-api';
import {TabApi} from './tab-api';
import {TabUsageNotes} from './tab-usage-notes';
import {REFERENCE_MEMBERS, REFERENCE_MEMBERS_CONTAINER} from '../styling/css-classes';
import {SectionApi} from './section-api';
import {SectionUsageNotes} from './section-usage-notes';
import {API_REFERENCE_CONTAINER, REFERENCE_MEMBERS} from '../styling/css-classes';
import {getFunctionMetadataRenderable} from '../transforms/function-transforms';
import {signatureCard} from './function-reference';
@@ -34,42 +34,41 @@ export function InitializerApiFunction(entry: InitializerApiFunctionRenderable)
}
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} showFullDescription={true} />
<TabApi entry={entry} />
<TabUsageNotes entry={entry} />
<SectionApi entry={entry} />
<div class={REFERENCE_MEMBERS_CONTAINER}>
<div class={REFERENCE_MEMBERS}>
{entry.callFunction.signatures.map((s, i) =>
signatureCard(
s.name,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${s.name}_${i}`,
},
printSignaturesAsHeader,
),
)}
<div class={REFERENCE_MEMBERS}>
{entry.callFunction.signatures.map((s, i) =>
signatureCard(
s.name,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${s.name}_${i}`,
},
printSignaturesAsHeader,
),
)}
{entry.subFunctions.reduce(
(elements, subFunction) => [
...elements,
...subFunction.signatures.map((s, i) =>
signatureCard(
`${entry.name}.${s.name}`,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${entry.name}_${s.name}_${i}`,
},
printSignaturesAsHeader,
),
{entry.subFunctions.reduce(
(elements, subFunction) => [
...elements,
...subFunction.signatures.map((s, i) =>
signatureCard(
`${entry.name}.${s.name}`,
getFunctionMetadataRenderable(s, entry.moduleName),
{
id: `${entry.name}_${s.name}_${i}`,
},
printSignaturesAsHeader,
),
],
[] as JSX.Element[],
)}
</div>
),
],
[] as JSX.Element[],
)}
</div>
<SectionUsageNotes entry={entry} />
</div>
);
}
@@ -0,0 +1,26 @@
/*!
* @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 {h} from 'preact';
import {DocEntryRenderable} from '../entities/renderables';
import {HasRenderableToc} from '../entities/traits';
import {CodeTableOfContents} from './code-table-of-contents';
import {SECTION_CONTAINER} from '../styling/css-classes';
import {SectionHeading} from './section-heading';
const API_SECTION_NAME = 'API';
/** Component to render the API section. */
export function SectionApi(props: {entry: DocEntryRenderable & HasRenderableToc}) {
return (
<div className={SECTION_CONTAINER + ' docs-reference-api-section'}>
<SectionHeading name={API_SECTION_NAME} />
<CodeTableOfContents entry={props.entry} />
</div>
);
}
@@ -8,14 +8,15 @@
import {Fragment, h} from 'preact';
import {DocEntryRenderable} from '../entities/renderables';
import {normalizeTabUrl} from '../transforms/url-transforms';
import {RawHtml} from './raw-html';
import {CodeSymbol} from './code-symbols';
import {SECTION_CONTAINER} from '../styling/css-classes';
import {SectionHeading} from './section-heading';
const DESCRIPTION_TAB_NAME = 'Description';
const DESCRIPTION_SECTION_NAME = 'Description';
/** Component to render the description tab. */
export function TabDescription(props: {entry: DocEntryRenderable}) {
/** Component to render the description section. */
export function SectionDescription(props: {entry: DocEntryRenderable}) {
const exportedBy = props.entry.jsdocTags.filter((t) => t.name === 'ngModule');
if (
(!props.entry.htmlDescription ||
@@ -26,7 +27,8 @@ export function TabDescription(props: {entry: DocEntryRenderable}) {
}
return (
<div data-tab={DESCRIPTION_TAB_NAME} data-tab-url={normalizeTabUrl(DESCRIPTION_TAB_NAME)}>
<div className={SECTION_CONTAINER}>
<SectionHeading name={DESCRIPTION_SECTION_NAME} />
<RawHtml value={props.entry.htmlDescription} />
{exportedBy.length ? (
@@ -0,0 +1,25 @@
/*!
* @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 {h} from 'preact';
import {convertSectionNameToId} from '../transforms/reference-section-id';
import {SECTION_HEADING} from '../styling/css-classes';
/** Component to render the API section. */
export function SectionHeading(props: {name: string}) {
const id = convertSectionNameToId(props.name);
const label = 'Link to ' + props.name + ' section';
return (
<h2 id={id} class={SECTION_HEADING}>
<a href={'#' + id} aria-label={label} tabIndex={-1}>
{props.name}
</a>
</h2>
);
}
@@ -8,19 +8,21 @@
import {Fragment, h} from 'preact';
import {DocEntryRenderable} from '../entities/renderables';
import {normalizeTabUrl} from '../transforms/url-transforms';
import {RawHtml} from './raw-html';
import {SECTION_CONTAINER} from '../styling/css-classes';
import {SectionHeading} from './section-heading';
const USAGE_NOTES_TAB_NAME = 'Usage Notes';
const USAGE_NOTES_SECTION_NAME = 'Usage Notes';
/** Component to render the usage notes tab. */
export function TabUsageNotes(props: {entry: DocEntryRenderable}) {
/** Component to render the usage notes section. */
export function SectionUsageNotes(props: {entry: DocEntryRenderable}) {
if (!props.entry.htmlUsageNotes) {
return (<></>);
return <></>;
}
return (
<div data-tab={USAGE_NOTES_TAB_NAME} data-tab-url={normalizeTabUrl(USAGE_NOTES_TAB_NAME)}>
<div className={SECTION_CONTAINER}>
<SectionHeading name={USAGE_NOTES_SECTION_NAME} />
<RawHtml value={props.entry.htmlUsageNotes} />
</div>
);
@@ -1,26 +0,0 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {h} from 'preact';
import {DocEntryRenderable} from '../entities/renderables';
import {HasRenderableToc} from '../entities/traits';
import {normalizeTabUrl} from '../transforms/url-transforms';
import {CodeTableOfContents} from './code-table-of-contents';
const API_TAB_NAME = 'API';
/** Component to render the API tab. */
export function TabApi(props: {entry: DocEntryRenderable & HasRenderableToc}) {
return (
<div data-tab={API_TAB_NAME} data-tab-url={normalizeTabUrl(API_TAB_NAME)}>
<div class={'docs-reference-api-tab'}>
<CodeTableOfContents entry={props.entry} />
</div>
</div>
);
}
@@ -9,18 +9,19 @@
import {h} from 'preact';
import {TypeAliasEntryRenderable} from '../entities/renderables';
import {HeaderApi} from './header-api';
import {TabDescription} from './tab-description';
import {TabUsageNotes} from './tab-usage-notes';
import {TabApi} from './tab-api';
import {SectionDescription} from './section-description';
import {SectionUsageNotes} from './section-usage-notes';
import {SectionApi} from './section-api';
import {API_REFERENCE_CONTAINER} from '../styling/css-classes';
/** Component to render a type alias API reference document. */
export function TypeAliasReference(entry: TypeAliasEntryRenderable) {
return (
<div class="api">
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<TabApi entry={entry} />
<TabDescription entry={entry} />
<TabUsageNotes entry={entry} />
<SectionApi entry={entry} />
<SectionDescription entry={entry} />
<SectionUsageNotes entry={entry} />
</div>
);
}
@@ -0,0 +1,14 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
export const convertSectionNameToId = (sectionName: string): string => {
return sectionName
.toLowerCase()
.replace(/\s|\//g, '-') // remove spaces and slashes
.replace(/[^0-9a-z\-]/g, ''); // only keep letters, digits & dashes
};
@@ -19,15 +19,3 @@ export const normalizePath = (path: string): string => {
}
return path;
};
export const normalizeTabUrl = (tabName: string): string => {
return tabName
.toLowerCase()
.replace(/<code>(.*?)<\/code>/g, '$1') // remove <code>
.replace(/<strong>(.*?)<\/strong>/g, '$1') // remove <strong>
.replace(/<em>(.*?)<\/em>/g, '$1') // remove <em>
.replace(/\s|\//g, '-') // remove spaces and slashes
.replace(/gt;|lt;/g, '') // remove escaped < and >
.replace(/&#\d+;/g, '') // remove HTML entities
.replace(/[^0-9a-zA-Z\-]/g, ''); // only keep letters, digits & dashes
};
@@ -21,14 +21,13 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/example-app",
"index": "src/index.html",
"main": "src/main.ts",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "css",
"assets": ["src/assets"],
"styles": ["src/styles.css"],
"stylePreprocessorOptions": {
@@ -59,12 +58,9 @@
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
"sourceMap": true
}
},
"defaultConfiguration": "production"
@@ -7,7 +7,7 @@
*/
import {Token, Tokens, RendererThis, TokenizerThis} from 'marked';
import {formatHeading, headingRender} from '../../tranformations/heading';
import {formatHeading} from '../../tranformations/heading';
interface DocsStepToken extends Tokens.Generic {
type: 'docs-step';
@@ -1,14 +0,0 @@
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
```mermaid
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
```
@@ -20,9 +20,24 @@ describe('markdown to html', () => {
// Extend the timeout interval tyo 15 seconds because we were seeing issues with not being able to run marked
// within the default timeframe.
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;
const markdownContent = await readFile(runfiles.resolvePackageRelative('./mermaid.md'), {
encoding: 'utf-8',
});
// This test was flaky, 1st attemp to fix it is by inlining the markdown content
const markdownContent = `
\`\`\`mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
\`\`\`
\`\`\`mermaid
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
\`\`\`
`;
marked.use({
async: true,
@@ -0,0 +1,36 @@
load("//tools:defaults.bzl", "ts_library")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "lib",
srcs = glob(
[
"*.ts",
],
exclude = [
"index.ts",
],
),
deps = [
"//adev/shared-docs/interfaces",
"@npm//@types/node",
"@npm//@webcontainer/api",
"@npm//fast-glob",
],
)
ts_library(
name = "navigation",
srcs = [
"index.ts",
],
visibility = [
"//adev/shared-docs:__subpackages__",
],
deps = [
":lib",
"//adev/shared-docs/interfaces",
"@npm//@types/node",
],
)
@@ -0,0 +1,26 @@
/*!
* @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 {readFileSync, writeFileSync} from 'fs';
import {generateNavItems} from './nav-items-gen';
import {getNavItemGenStrategy} from './strategies';
async function main() {
const [paramFilePath] = process.argv.slice(2);
const rawParamLines = readFileSync(paramFilePath, {encoding: 'utf8'}).split('\n');
const [joinedSrcs, packageDir, strategy, outputFilePath] = rawParamLines;
const srcs = joinedSrcs.split(',');
// Generate navigation data
const navData = await generateNavItems(srcs, getNavItemGenStrategy(strategy, packageDir));
writeFileSync(outputFilePath, JSON.stringify(navData));
}
await main();
@@ -0,0 +1,59 @@
/*!
* @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 fs from 'fs';
import readline from 'readline';
import {basename, dirname, resolve} from 'path';
import {NavigationItem} from '../../interfaces';
import {NavigationItemGenerationStrategy} from './types';
/**
* Generate navigations items by a provided strategy.
*
* @param mdFilesPaths Paths to the Markdown files that represent the page contents
* @param strategy Strategy
* @returns An array with navigation items
*/
export async function generateNavItems(
mdFilesPaths: string[],
strategy: NavigationItemGenerationStrategy,
): Promise<NavigationItem[]> {
const navItems: NavigationItem[] = [];
const {labelGeneratorFn, pathPrefix, contentPath} = strategy;
for (const path of mdFilesPaths) {
const fullPath = resolve(dirname(path), basename(path));
const name = path.split('/').pop()?.replace('.md', '')!;
const firstLine = await getMdFileHeading(fullPath);
navItems.push({
label: labelGeneratorFn(name, firstLine),
path: `${pathPrefix}/${name}`,
contentPath: `${contentPath}/${name}`,
});
}
return navItems;
}
/** Extract the first heading from a Markdown file. */
async function getMdFileHeading(filePath: string): Promise<string> {
const readStream = fs.createReadStream(filePath);
const rl = readline.createInterface({input: readStream});
for await (const line of rl) {
if (line.trim().startsWith('#')) {
rl.close();
readStream.destroy();
return line.replace(/^#+[ \t]+/, '');
}
}
return '';
}
@@ -0,0 +1,54 @@
/*!
* @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 {NavigationItemGenerationStrategy, Strategy} from './types';
// Should point to the website content.
// Update, if the location is updated or shared-docs is extracted from `adev/`.
const CONTENT_FOLDER_PATH = 'adev/src/content/';
// Ensure that all Strategy-ies are part of SUPPORTED_STRATEGIES by using a key-typed object.
const strategiesObj: {[key in Strategy]: null} = {errors: null, 'extended-diagnostics': null};
const SUPPORTED_STRATEGIES = Object.keys(strategiesObj);
/** Get navigation item generation strategy by a provided strategy string. */
export function getNavItemGenStrategy(
strategy: string,
packageDir: string,
): NavigationItemGenerationStrategy {
if (SUPPORTED_STRATEGIES.indexOf(strategy) === -1) {
throw new Error(
`Unsupported NavigationItem generation strategy "${strategy}". Supported: ${SUPPORTED_STRATEGIES.join(', ')}`,
);
}
switch (strategy as Strategy) {
case 'errors':
return errorsStrategy(packageDir);
case 'extended-diagnostics':
return extendedDiagnosticsStrategy(packageDir);
}
}
// "Errors" navigation items generation strategy
function errorsStrategy(packageDir: string): NavigationItemGenerationStrategy {
return {
pathPrefix: 'errors',
contentPath: packageDir.replace(CONTENT_FOLDER_PATH, ''),
labelGeneratorFn: (fileName, firstLine) => fileName + ': ' + firstLine,
};
}
// "Extended diagnostics" items generation strategy
function extendedDiagnosticsStrategy(packageDir: string): NavigationItemGenerationStrategy {
return {
pathPrefix: 'extended-diagnostics',
contentPath: packageDir.replace(CONTENT_FOLDER_PATH, ''),
labelGeneratorFn: (fileName, firstLine) => fileName + ': ' + firstLine,
};
}
@@ -0,0 +1,17 @@
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
package(default_visibility = ["//adev/shared-docs/pipeline/navigation:__subpackages__"])
ts_library(
name = "unit_test_lib",
testonly = True,
srcs = glob(["*.spec.ts"]),
deps = [
"//adev/shared-docs/pipeline/navigation:lib",
],
)
jasmine_node_test(
name = "unit_tests",
deps = [":unit_test_lib"],
)
@@ -0,0 +1,50 @@
/**
* @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 {generateNavItems} from '../nav-items-gen';
import {NavigationItemGenerationStrategy} from '../types';
import fs from 'fs';
import readline from 'readline';
const readlineInterfaceMock = {
close: () => {},
async *[Symbol.asyncIterator]() {
yield '<!-- Comment -->';
yield 'Some random text';
yield '## Heading';
yield 'Some text';
},
};
describe('generateNavItems', () => {
it('should test the default case', async () => {
spyOn(fs, 'createReadStream').and.returnValue({destroy: () => null} as any);
spyOn(readline, 'createInterface').and.returnValue(readlineInterfaceMock as any);
const strategy: NavigationItemGenerationStrategy = {
pathPrefix: 'page',
contentPath: 'content/directory',
labelGeneratorFn: (fileName, firstLine) => fileName + ' // ' + firstLine,
};
const navItems = await generateNavItems(['directory/home.md', 'directory/about.md'], strategy);
expect(navItems).toEqual([
{
label: 'home // Heading',
path: 'page/home',
contentPath: 'content/directory/home',
},
{
label: 'about // Heading',
path: 'page/about',
contentPath: 'content/directory/about',
},
]);
});
});
@@ -0,0 +1,22 @@
/*!
* @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
*/
/**
* `NavigationItem` generation strategy
*/
export type NavigationItemGenerationStrategy = {
/** App route path prefix. */
pathPrefix: string;
/** Content path where the source files are kept. */
contentPath: string;
/** Page/route label generator function. */
labelGeneratorFn: (fileName: string, firstLine: string) => string;
};
/** Strategy for navigation item generation. */
export type Strategy = 'errors' | 'extended-diagnostics';
@@ -33,7 +33,6 @@ ts_library(
":editor",
"//adev/shared-docs/interfaces",
"@npm//@types/node",
"@npm//fast-glob",
],
)
@@ -49,9 +49,7 @@ export class TableOfContentsLoader {
const updatedTopValues = new Map<string, number>();
for (const heading of headings) {
const parentTop = heading.parentElement?.offsetTop ?? 0;
const top = Math.floor(parentTop + heading.offsetTop - this.toleranceThreshold);
updatedTopValues.set(heading.id, top);
updatedTopValues.set(heading.id, this.calculateTop(heading));
}
this.tableOfContentItems.update((oldItems) => {
@@ -17,6 +17,7 @@
&:not(.full) {
height: 22px;
width: 22px;
flex: 0 0 22px;
}
&.full {
+404
View File
@@ -0,0 +1,404 @@
@use './anchor' as anchor;
/* Common styles for the API & CLI references */
@mixin reference-common() {
.docs-code {
pre {
margin-block: 0;
}
}
.docs-reference-header {
// deprecated markers beside header
& ~ .docs-deprecated {
margin-block-start: 0.5rem;
}
& > p {
color: var(--secondary-contrast);
margin-block-start: 0;
margin-block-end: 1.5rem;
}
.docs-reference-title {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
padding-block-end: 0;
gap: 0.5rem;
> div {
margin-block: 0.67em;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
h1 {
margin-block: 0;
}
}
a {
fill: var(--quinary-contrast);
transition: fill 0.3s ease;
&:hover {
fill: var(--primary-contrast);
}
}
}
.docs-reference-category {
color: var(--gray-400);
font-size: 0.875rem;
font-weight: 500;
line-height: 1.4rem;
letter-spacing: -0.00875rem;
}
.docs-code {
margin-block-end: 1.5rem;
}
}
.docs-reference-section-heading {
padding-block-start: 3rem;
a {
@include anchor.docs-anchor();
color: inherit;
}
}
.docs-reference-members {
box-sizing: border-box;
width: 100%;
display: flex;
flex-direction: column;
gap: 20px;
&:not(:first-child) {
margin-top: 1rem;
}
.docs-reference-member-card {
border: 1px solid var(--senary-contrast);
border-radius: 0.25rem;
position: relative;
transition: border 0.3s ease;
&::before {
content: '';
inset: -1px;
position: absolute;
background: transparent;
border-radius: 0.35rem;
z-index: 0;
}
&.highlighted {
box-shadow: 10px 4px 40px 0 rgba(0, 0, 0, 0.01);
&::before {
background: var(--red-to-pink-to-purple-horizontal-gradient);
}
}
> p {
padding-inline: 1.25rem;
margin-block-end: 0;
}
.docs-reference-card-header {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 0.25rem 0.25rem 0 0;
background-color: var(--octonary-contrast);
position: relative;
z-index: 10;
padding: 0.7rem 1rem;
gap: 0.5rem;
flex-wrap: wrap;
transition:
background-color 0.3s ease,
border 0.3s ease;
&:focus {
outline: none;
}
&:has(+ .docs-reference-card-body:empty) {
border-radius: 0.25rem;
}
code {
font-size: 0.875rem;
&:has(pre) {
padding: 0;
}
&:not(pre *) {
padding: 0 0.3rem;
}
}
pre {
margin: 0;
/* Do we have a better alternative ? */
overflow: auto;
}
h3 {
display: inline-block;
font-family: var(--code-font);
font-size: 1rem;
letter-spacing: -0.025rem;
margin: 0;
}
span {
font-size: 0.875rem;
}
}
.docs-reference-card-body {
padding: 0.25rem 1.25rem;
background: var(--septenary-contrast);
transition: background-color 0.3s ease;
color: var(--quaternary-contrast);
border-radius: 0 0 0.25rem 0.25rem;
position: relative;
z-index: 10;
&:empty {
display: none;
}
&:first-child {
border-radius: 0.25rem;
}
hr {
margin-block: 2rem;
}
.docs-code {
margin-block-end: 1rem;
}
.docs-deprecation-message {
border-block-end: 1px solid var(--senary-contrast);
.docs-deprecated {
color: var(--page-background);
background-color: var(--quaternary-contrast);
width: max-content;
border-radius: 0.25rem;
padding: 0.1rem 0.25rem;
margin-block-start: 1rem;
}
}
}
}
}
}
/* API reference styles */
@mixin api-reference {
// API section styles
.docs-reference-api-section {
.docs-code {
box-sizing: border-box;
width: 100%;
overflow: hidden;
padding: 0;
button {
transition: background-color 0.3s ease;
&.shiki-ln-line-highlighted {
background-color: var(--senary-contrast);
}
&:hover {
background-color: var(--septenary-contrast);
}
&:focus {
background-color: var(--senary-contrast);
span {
background-color: inherit;
}
}
}
// Hide copy source code button
button[docs-copy-source-code] {
display: none;
}
}
code {
margin-block: 0;
}
pre {
white-space: pre;
overflow-x: auto;
margin: 0;
}
}
// "API member card"-specific styles
.docs-reference-member-card {
.docs-reference-card-item {
// When it's not the only card ...
&:has(~ .docs-reference-card-item) {
border: 1px solid var(--senary-contrast);
margin-block: 1rem;
border-radius: 0.25rem;
padding-inline: 1rem;
}
// & the last card
&:last-child:not(:first-of-type) {
border: 1px solid var(--senary-contrast);
margin-block: 1rem;
border-radius: 0.25rem;
padding-inline: 1rem;
}
span {
display: inline-block;
font-size: 0.875rem;
}
code {
font-size: 0.875rem;
}
.docs-function-definition:has(*) {
border-block-end: 1px solid var(--senary-contrast);
}
.docs-param-group {
margin-block-start: 1rem;
// If it's the only param group...
&:not(:has(~ .docs-param-group)) {
margin-block: 1rem;
}
.docs-param-name {
color: var(--vivid-pink);
font-family: var(--code-font);
margin-inline-end: 0.25rem;
&::after {
content: ':';
}
}
.docs-parameter-description {
p:first-child {
margin-block-start: 0;
}
}
}
.docs-param-keyword {
color: var(--primary-contrast);
font-family: var(--code-font);
margin-inline-end: 0.5rem;
}
.docs-return-type {
padding-block: 1rem;
// & does not follow a function definition
&:not(.docs-function-definition + .docs-return-type) {
border-block-start: 1px solid var(--senary-contrast);
}
}
}
}
}
/* CLI reference styles */
@mixin cli-reference {
// CLI TOC
.docs-reference-cli-toc {
margin-bottom: 1rem;
.shiki-ln-line-argument,
.shiki-ln-line-option {
padding: 0.1rem 0.2rem 0.2rem;
margin-inline: 0.1rem;
color: var(--quaternary-contrast);
background: transparent;
border-radius: 0.25rem;
position: relative;
transition:
color 0.3s ease,
background 0.3s ease,
border 0.3s ease;
&:hover {
color: var(--primary-contrast);
background: var(--septenary-contrast);
}
&.shiki-ln-line-highlighted {
color: var(--primary-contrast);
background: var(--senary-contrast);
}
}
.shiki-ln-line-argument {
margin-inline-start: 0.2rem;
}
}
.docs-reference-members {
.docs-reference-section-heading {
margin: 0;
}
// "CLI member card"-specific styles
.docs-reference-member-card {
.docs-ref-content {
padding: 1rem 0;
&:not(:first-child) {
border-block-start: 1px solid var(--senary-contrast);
}
.docs-reference-type-and-default {
width: 4.375rem;
flex-shrink: 0;
span {
display: block;
font-size: 0.875rem;
margin-block-end: 0.2rem;
white-space: nowrap;
&:not(:first-child) {
margin-block-start: 1rem;
}
}
code {
font-size: 0.775rem;
}
}
}
}
}
}
+6 -3
View File
@@ -21,7 +21,9 @@
border: 1px solid var(--senary-contrast);
border-radius: 0.25rem;
overflow: hidden;
transition: border-color 0.3s ease, background-color 0.3s ease;
transition:
border-color 0.3s ease,
background-color 0.3s ease;
p:first-of-type {
margin-block-start: 1.5rem;
@@ -54,6 +56,7 @@
flex-direction: column;
justify-content: space-between;
border-block-start: 1px solid var(--senary-contrast);
h3 {
margin-bottom: 0;
margin-block-start: 1rem;
@@ -79,7 +82,6 @@
color: transparent;
font-size: 0.875rem;
margin-block: 0;
transition: background-position 1.8s ease-out;
background-size: 200% 100%;
background-position: 100% 0%;
@@ -87,10 +89,11 @@
}
&:hover {
background: var(--subtle-purple);
span {
background-position: 0% 0%;
}
background: var(--subtle-purple);
}
}
+5 -1
View File
@@ -144,12 +144,16 @@ class FakeFileSystemAPI implements FileSystemAPI {
): Promise<DirEnt<string>[]>;
readdir(
path: unknown,
options?: unknown,
options?: {encoding?: string | null | undefined; withFileTypes?: boolean} | string | null,
):
| Promise<Uint8Array[]>
| Promise<string[]>
| Promise<DirEnt<Uint8Array>[]>
| Promise<DirEnt<string>[]> {
if (typeof options === 'object' && options?.withFileTypes === true) {
return Promise.resolve([{name: 'fake-file', isFile: () => true, isDirectory: () => false}]);
}
return Promise.resolve(['/fake-dirname']);
}
-2
View File
@@ -29,8 +29,6 @@ ts_library(
"//adev/shared-docs/providers",
"//packages/core",
"//packages/router",
"@npm//@types/node",
"@npm//@webcontainer/api",
"@npm//fflate",
],
)
+7 -3
View File
@@ -41,7 +41,7 @@ interface FileSystemAPI {
export const checkFilesInDirectory = async (
dir: string,
fs: FileSystemAPI,
filterFoldersPredicate: (path?: string) => boolean = () => true,
filterFromRootPredicate: ((path: string) => boolean) | null,
files: FileAndContent[] = [],
) => {
const entries = (await fs.readdir(dir, {withFileTypes: true})) ?? [];
@@ -49,11 +49,15 @@ export const checkFilesInDirectory = async (
for (const entry of entries) {
const fullPath = normalizePath(`${dir}/${entry.name}`);
if (filterFromRootPredicate && !filterFromRootPredicate?.(entry.name)) {
continue;
}
if (entry.isFile()) {
const content = await fs.readFile(fullPath, 'utf-8');
files.push({content, path: fullPath});
} else if (entry.isDirectory() && filterFoldersPredicate(entry.name)) {
await checkFilesInDirectory(fullPath, fs, filterFoldersPredicate, files);
} else if (entry.isDirectory()) {
await checkFilesInDirectory(fullPath, fs, null, files);
}
}
+2 -2
View File
@@ -23,10 +23,11 @@ export class AppScroller {
private readonly viewportScroller = inject(ViewportScroller);
private readonly appRef = inject(ApplicationRef);
private readonly injector = inject(EnvironmentInjector);
disableScrolling = false;
private _lastScrollEvent?: Scroll;
private canScroll = false;
private cancelScroll?: () => void;
get lastScrollEvent(): Scroll | undefined {
return this._lastScrollEvent;
}
@@ -41,7 +42,6 @@ export class AppScroller {
this.canScroll = true;
this._lastScrollEvent = e;
}),
filter(() => !this.disableScrolling),
filter(() => {
const info = this.router.lastSuccessfulNavigation?.extras.info as Record<
'disableScrolling',
+2 -2
View File
@@ -8,13 +8,13 @@
import {mergeApplicationConfig, ApplicationConfig} from '@angular/core';
import {provideServerRendering} from '@angular/platform-server';
import {provideServerRoutesConfig, RenderMode} from '@angular/ssr';
import {provideServerRouting, RenderMode} from '@angular/ssr';
import {appConfig} from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering(),
provideServerRoutesConfig([{path: '**', renderMode: RenderMode.Prerender}]),
provideServerRouting([{path: '**', renderMode: RenderMode.Prerender}]),
],
};
+1
View File
@@ -11,3 +11,4 @@ export const X = 'https://x.com/angular';
export const MEDIUM = 'https://blog.angular.dev';
export const YOUTUBE = 'https://www.youtube.com/angular';
export const DISCORD = 'https://discord.gg/angular';
export const BLUESKY = 'https://bsky.app/profile/angular.dev';
+4
View File
@@ -9,6 +9,10 @@
export const VERSIONS_CONFIG = {
aDevVersionsLinkPattern: 'https://{{prefix}}{{version}}angular.dev',
aioVersions: [
{
version: 'v18',
url: 'https://v18.angular.dev/overview',
},
{
version: 'v17',
url: 'https://v17.angular.io/docs',
@@ -9,6 +9,9 @@
<li>
<a [href]="X" title="X (formerly Twitter)">X (formerly Twitter)</a>
</li>
<li>
<a [href]="BLUESKY" title="Bluesky">Bluesky</a>
</li>
<li>
<a [href]="YOUTUBE" title="YouTube">YouTube</a>
</li>
@@ -9,7 +9,7 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {ExternalLink} from '@angular/docs';
import {RouterLink} from '@angular/router';
import {GITHUB, X, MEDIUM, YOUTUBE} from './../../constants/links';
import {GITHUB, X, MEDIUM, YOUTUBE, BLUESKY} from './../../constants/links';
@Component({
selector: 'footer[adev-footer]',
@@ -23,4 +23,5 @@ export class Footer {
readonly X = X;
readonly YOUTUBE = YOUTUBE;
readonly MEDIUM = MEDIUM;
readonly BLUESKY = BLUESKY;
}
@@ -346,6 +346,27 @@
</svg>
</a>
</li>
<li>
<a
[href]="BLUESKY"
cdkMenuItem
title="Angular Bluesky profile"
target="_blank"
rel="noopener"
>
<!-- Bluesky Icon -->
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3.468 1.948C5.303 3.325 7.276 6.118 8 7.616c.725-1.498 2.697-4.29 4.532-5.668C13.855.955 16 .186 16 2.632c0 .489-.28 4.105-.444 4.692-.572 2.04-2.653 2.561-4.504 2.246 3.236.551 4.06 2.375 2.281 4.2-3.376 3.464-4.852-.87-5.23-1.98-.07-.204-.103-.3-.103-.218 0-.081-.033.014-.102.218-.379 1.11-1.855 5.444-5.231 1.98-1.778-1.825-.955-3.65 2.28-4.2-1.85.315-3.932-.205-4.503-2.246C.28 6.737 0 3.12 0 2.632 0 .186 2.145.955 3.468 1.948Z"></path>
</svg>
</a>
</li>
<li>
<a
[href]="MEDIUM"
@@ -64,7 +64,9 @@
// render primary nav / mini menu above tablet secondary bar
z-index: 250;
position: relative;
transition: background-color 0.3s ease, border-color 0.3s ease;
transition:
background-color 0.3s ease,
border-color 0.3s ease;
height: 100dvh;
padding-block-start: 1rem;
padding-block-end: 2rem;
@@ -96,8 +98,8 @@
color-mix(in srgb, var(--orange-red), transparent 60%) 0%,
color-mix(in srgb, var(--vivid-pink), transparent 40%) 15%,
color-mix(in srgb, var(--electric-violet), transparent 70%) 25%,
color-mix(in srgb, var(--bright-blue), transparent 60%) 90%,
);
color-mix(in srgb, var(--bright-blue), transparent 60%) 90%
);
}
&.adev-nav-primary--deprecated {
@@ -195,7 +197,7 @@
}
li {
padding-inline: 1rem;
padding-inline: 0.875rem;
}
}
}
@@ -209,8 +211,9 @@
gap: 1rem;
@include mq.for-tablet {
flex-direction: row;
flex-direction: row !important;
margin-inline-end: 1.25rem;
gap: 0.75rem;
}
.adev-nav-item--active {
@@ -249,8 +252,14 @@
}
}
.adev-nav-item--logo a {
height: 34px;
.adev-nav-item--logo {
a {
height: 34px;
}
@include mq.for-tablet {
gap: 0.75rem;
}
}
.adev-close-nav {
@@ -281,7 +290,9 @@
border-block-end: 1px solid var(--septenary-contrast);
padding-block: 1rem;
padding-inline: var(--layout-padding);
transition: background-color 0.3s ease, border-color 0.3s ease;
transition:
background-color 0.3s ease,
border-color 0.3s ease;
button {
display: flex;
gap: 0.5rem;
@@ -28,7 +28,7 @@ import {
import {NavigationEnd, Router, RouterLink} from '@angular/router';
import {filter, map, startWith} from 'rxjs/operators';
import {DOCS_ROUTES, REFERENCE_ROUTES, TUTORIALS_ROUTES} from '../../../routes';
import {GITHUB, MEDIUM, X, YOUTUBE, DISCORD} from '../../constants/links';
import {GITHUB, MEDIUM, X, YOUTUBE, DISCORD, BLUESKY} from '../../constants/links';
import {PagePrefix} from '../../enums/pages';
import {Theme, ThemeManager} from '../../services/theme-manager.service';
import {VersionManager} from '../../services/version-manager.service';
@@ -67,6 +67,7 @@ export class Navigation implements OnInit {
readonly MEDIUM = MEDIUM;
readonly YOUTUBE = YOUTUBE;
readonly DISCORD = DISCORD;
readonly BLUESKY = BLUESKY;
readonly PRIMARY_NAV_ID = PRIMARY_NAV_ID;
readonly SECONDARY_NAV_ID = SECONDARY_NAV_ID;
@@ -39,8 +39,8 @@ describe('VersionManager', () => {
});
it('should contain correct number of Angular Docs versions', () => {
// Note: From v2 to v17 (inclusive), there were no v3
const expectedAioDocsVersionsCount = 15;
// Note: From v2 to v18 (inclusive), there were no v3
const expectedAioDocsVersionsCount = 16;
// Last stable version and next
const expectedRecentDocsVersionCount = 2;
@@ -44,7 +44,8 @@ class FakeCodeMirrorEditor implements Partial<CodeMirrorEditor> {
const codeMirrorEditorService = new FakeCodeMirrorEditor();
const fakeChangeDetectorRef = new FakeChangeDetectorRef();
describe('CodeEditor', () => {
// Disabled because broken (like because of package mismatch)
xdescribe('CodeEditor', () => {
let component: CodeEditor;
let fixture: ComponentFixture<CodeEditor>;
let loader: HarnessLoader;
@@ -148,6 +149,9 @@ describe('CodeEditor', () => {
});
it('should focused on a new tab when adding a new file', async () => {
// Wait until the asynchronous injection stuff is done.
await fixture.whenStable();
const button = fixture.debugElement.query(By.css('button.adev-add-file')).nativeElement;
button.click();
@@ -13,6 +13,7 @@ import {
Component,
DestroyRef,
ElementRef,
EnvironmentInjector,
OnDestroy,
ViewChild,
inject,
@@ -21,10 +22,9 @@ import {
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
import {Title} from '@angular/platform-browser';
import {debounceTime, map} from 'rxjs';
import {debounceTime, from, map, switchMap} from 'rxjs';
import {TerminalType} from '../terminal/terminal-handler.service';
import {EmbeddedTutorialManager} from '../embedded-tutorial-manager.service';
import {CodeMirrorEditor} from './code-mirror-editor.service';
import {DiagnosticWithLocation, DiagnosticsState} from './services/diagnostics-state.service';
@@ -34,6 +34,7 @@ import {ClickOutside, IconComponent} from '@angular/docs';
import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu';
import {IDXLauncher} from '../idx-launcher.service';
import {MatTooltip} from '@angular/material/tooltip';
import {injectEmbeddedTutorialManager} from '../inject-embedded-tutorial-manager';
export const REQUIRED_FILES = new Set([
'src/main.ts',
@@ -91,7 +92,7 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
private readonly idxLauncher = inject(IDXLauncher);
private readonly title = inject(Title);
private readonly location = inject(Location);
private readonly embeddedTutorialManager = inject(EmbeddedTutorialManager);
private readonly environmentInjector = inject(EnvironmentInjector);
private readonly errors$ = this.diagnosticsState.diagnostics$.pipe(
// Display errors one second after code update
@@ -142,7 +143,8 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
}
async downloadCurrentCodeEditorState(): Promise<void> {
const name = this.embeddedTutorialManager.tutorialId();
const embeddedTutorialManager = await injectEmbeddedTutorialManager(this.environmentInjector);
const name = embeddedTutorialManager.tutorialId();
await this.downloadManager.downloadCurrentStateOfTheSolution(name);
}
@@ -236,8 +238,14 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
}
private setSelectedTabOnTutorialChange() {
this.embeddedTutorialManager.tutorialChanged$
.pipe(takeUntilDestroyed(this.destroyRef))
// Using `from` to prevent injecting the embedded tutorial manager once the
// injector is destroyed (this may happen in unit tests when the test ends
// before `injectAsync` runs, causing an error).
from(injectEmbeddedTutorialManager(this.environmentInjector))
.pipe(
switchMap((embeddedTutorialManager) => embeddedTutorialManager.tutorialChanged$),
takeUntilDestroyed(this.destroyRef),
)
.subscribe(() => {
// selected file on project change is always the first
this.matTabGroup.selectedIndex = 0;
@@ -9,7 +9,8 @@
import {DOCUMENT, isPlatformBrowser} from '@angular/common';
import {EnvironmentInjector, Injectable, PLATFORM_ID, inject} from '@angular/core';
import {generateZip} from '@angular/docs';
import {injectAsync} from '../core/services/inject-async';
import {injectNodeRuntimeSandbox} from './inject-node-runtime-sandbox';
@Injectable({
providedIn: 'root',
@@ -23,9 +24,7 @@ export class DownloadManager {
* Generate ZIP with the current state of the solution in the EmbeddedEditor
*/
async downloadCurrentStateOfTheSolution(name: string) {
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
);
const nodeRuntimeSandbox = await injectNodeRuntimeSandbox(this.environmentInjector);
const files = await nodeRuntimeSandbox.getSolutionFiles();
const content = await generateZip(files);
@@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {DestroyRef, inject, Injectable, signal} from '@angular/core';
import {EnvironmentInjector, inject, Injectable, signal} from '@angular/core';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {filter, map, Subject} from 'rxjs';
import {filter, from, map, Subject, switchMap} from 'rxjs';
import {TutorialMetadata, TutorialType} from '@angular/docs';
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
import {injectEmbeddedTutorialManager} from './inject-embedded-tutorial-manager';
export interface EditorUiStateConfig {
displayOnlyInteractiveTerminal: boolean;
@@ -23,8 +23,7 @@ export const DEFAULT_EDITOR_UI_STATE: EditorUiStateConfig = {
@Injectable()
export class EditorUiState {
private readonly embeddedTutorialManager = inject(EmbeddedTutorialManager);
private readonly destroyRef = inject(DestroyRef);
private readonly environmentInjector = inject(EnvironmentInjector);
private readonly stateChanged = new Subject<void>();
@@ -41,11 +40,13 @@ export class EditorUiState {
}
private handleTutorialChange() {
this.embeddedTutorialManager.tutorialChanged$
from(injectEmbeddedTutorialManager(this.environmentInjector))
.pipe(
map(() => this.embeddedTutorialManager.type()),
switchMap((embeddedTutorialManager) =>
embeddedTutorialManager.tutorialChanged$.pipe(map(() => embeddedTutorialManager.type())),
),
filter((tutorialType): tutorialType is TutorialMetadata['type'] => Boolean(tutorialType)),
takeUntilDestroyed(this.destroyRef),
takeUntilDestroyed(),
)
.subscribe((tutorialType) => {
if (tutorialType === TutorialType.CLI) {
+3 -4
View File
@@ -7,9 +7,10 @@
*/
import {EnvironmentInjector, Injectable, inject} from '@angular/core';
import {injectAsync} from '../core/services/inject-async';
import * as IDX from 'open-in-idx';
import {injectNodeRuntimeSandbox} from './inject-node-runtime-sandbox';
@Injectable({
providedIn: 'root',
})
@@ -17,9 +18,7 @@ export class IDXLauncher {
private readonly environmentInjector = inject(EnvironmentInjector);
async openCurrentSolutionInIDX(): Promise<void> {
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
);
const nodeRuntimeSandbox = await injectNodeRuntimeSandbox(this.environmentInjector);
const runtimeFiles = await nodeRuntimeSandbox.getSolutionFiles();
const workspaceFiles: Record<string, string> = {};
+3 -2
View File
@@ -9,7 +9,8 @@
export {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
export {LoadingStep} from './enums/loading-steps';
export {NodeRuntimeState} from './node-runtime-state.service';
export {NodeRuntimeSandbox} from './node-runtime-sandbox.service';
export {injectNodeRuntimeSandbox} from './inject-node-runtime-sandbox';
export {EmbeddedEditor, EMBEDDED_EDITOR_SELECTOR} from './embedded-editor.component';
export {injectEmbeddedTutorialManager} from './inject-embedded-tutorial-manager';
@@ -0,0 +1,17 @@
/*!
* @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 {EnvironmentInjector} from '@angular/core';
import {injectAsync} from '../core/services/inject-async';
export function injectEmbeddedTutorialManager(injector: EnvironmentInjector) {
return injectAsync(injector, () =>
import('./embedded-tutorial-manager.service').then((c) => c.EmbeddedTutorialManager),
);
}
@@ -0,0 +1,17 @@
/*!
* @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 {EnvironmentInjector} from '@angular/core';
import {injectAsync} from '../core/services/inject-async';
export function injectNodeRuntimeSandbox(injector: EnvironmentInjector) {
return injectAsync(injector, () =>
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
);
}
@@ -300,4 +300,18 @@ describe('NodeRuntimeSandbox', () => {
expect(deleteFileSpy).toHaveBeenCalledWith(fileToDelete);
}
});
it('should not have any filePath starting with "/" in solutions files', async () => {
service['webContainerPromise'] = Promise.resolve(
new FakeWebContainer() as unknown as WebContainer,
);
setValuesToInitializeProject();
await service.init();
const files = await service.getSolutionFiles();
expect(files.length).toBe(1);
expect(files[0].path).toBe('fake-file');
});
});
@@ -143,12 +143,20 @@ export class NodeRuntimeSandbox {
async getSolutionFiles(): Promise<FileAndContent[]> {
const webContainer = await this.webContainerPromise!;
const excludeFolders = ['node_modules', '.angular', 'dist'];
const excludeFromRoot = [
'node_modules',
'.angular',
'dist',
'BUILD.bazel',
'idx',
'package.json.template',
'config.json',
];
return await checkFilesInDirectory(
'/',
'',
webContainer.fs,
(path?: string) => !!path && !excludeFolders.includes(path),
(path: string) => !excludeFromRoot.includes(path),
);
}
@@ -6,13 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
inject,
computed,
} from '@angular/core';
import {ChangeDetectionStrategy, Component, inject, computed} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {toSignal} from '@angular/core/rxjs-interop';
@@ -30,7 +24,6 @@ import {PreviewError} from './preview-error.component';
imports: [PreviewError],
})
export class Preview {
private readonly changeDetectorRef = inject(ChangeDetectorRef);
private readonly domSanitizer = inject(DomSanitizer);
private readonly nodeRuntimeSandbox = inject(NodeRuntimeSandbox);
private readonly nodeRuntimeState = inject(NodeRuntimeState);
@@ -8,7 +8,8 @@
import {EnvironmentInjector, Injectable, inject} from '@angular/core';
import sdk, {Project, ProjectFiles} from '@stackblitz/sdk';
import {injectAsync} from '../core/services/inject-async';
import {injectNodeRuntimeSandbox} from './inject-node-runtime-sandbox';
@Injectable({
providedIn: 'root',
@@ -22,9 +23,7 @@ export class StackBlitzOpener {
async openCurrentSolutionInStackBlitz(
projectMetadata: Pick<Project, 'title' | 'description'>,
): Promise<void> {
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
);
const nodeRuntimeSandbox = await injectNodeRuntimeSandbox(this.environmentInjector);
const runtimeFiles = await nodeRuntimeSandbox.getSolutionFiles();
@@ -17,10 +17,13 @@ import {
OnInit,
} from '@angular/core';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {forkJoin} from 'rxjs';
import {forkJoin, switchMap} from 'rxjs';
import {injectAsync} from '../../../core/services/inject-async';
import {EmbeddedEditor, EmbeddedTutorialManager} from '../../../editor';
import {
EmbeddedEditor,
injectEmbeddedTutorialManager,
injectNodeRuntimeSandbox,
} from '../../../editor';
@Component({
selector: 'adev-code-editor',
@@ -32,7 +35,6 @@ import {EmbeddedEditor, EmbeddedTutorialManager} from '../../../editor';
})
export class CodeEditorComponent implements OnInit {
private readonly cdRef = inject(ChangeDetectorRef);
private readonly embeddedTutorialManager = inject(EmbeddedTutorialManager);
private readonly environmentInjector = inject(EnvironmentInjector);
private readonly destroyRef = inject(DestroyRef);
@@ -47,13 +49,18 @@ export class CodeEditorComponent implements OnInit {
// and completed, which can lead to a memory leak if the user navigates away from
// this component to another page.
forkJoin([
injectAsync(this.environmentInjector, () =>
import('../../../editor/index').then((c) => c.NodeRuntimeSandbox),
),
this.embeddedTutorialManager.fetchAndSetTutorialFiles(this.tutorialFiles),
injectNodeRuntimeSandbox(this.environmentInjector),
injectEmbeddedTutorialManager(this.environmentInjector),
])
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(([nodeRuntimeSandbox]) => {
.pipe(
switchMap(([nodeRuntimeSandbox, embeddedTutorialManager]) =>
embeddedTutorialManager
.fetchAndSetTutorialFiles(this.tutorialFiles)
.then(() => nodeRuntimeSandbox),
),
takeUntilDestroyed(this.destroyRef),
)
.subscribe((nodeRuntimeSandbox) => {
this.cdRef.markForCheck();
nodeRuntimeSandbox.init();
});
+27 -36
View File
@@ -6,21 +6,21 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {DOCUMENT, isPlatformBrowser} from '@angular/common';
import {DOCUMENT} from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
DestroyRef,
ElementRef,
Injector,
OnDestroy,
OnInit,
PLATFORM_ID,
ViewChild,
afterNextRender,
inject,
} from '@angular/core';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {WINDOW, shouldReduceMotion, isIos} from '@angular/docs';
import {ActivatedRoute, RouterLink} from '@angular/router';
import {from} from 'rxjs';
import {injectAsync} from '../../core/services/inject-async';
@@ -38,14 +38,14 @@ export const TUTORIALS_HOMEPAGE_DIRECTORY = 'homepage';
styleUrls: ['./home.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export default class Home implements OnInit, AfterViewInit, OnDestroy {
export default class Home {
@ViewChild('home') home!: ElementRef<HTMLDivElement>;
private readonly document = inject(DOCUMENT);
private readonly injector = inject(Injector);
private readonly platformId = inject(PLATFORM_ID);
private readonly window = inject(WINDOW);
private readonly activatedRoute = inject(ActivatedRoute);
private readonly destroyRef = inject(DestroyRef);
protected readonly tutorialFiles = TUTORIALS_HOMEPAGE_DIRECTORY;
protected readonly isUwu = 'uwu' in this.activatedRoute.snapshot.queryParams;
@@ -53,19 +53,12 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
private homeAnimation?: HomeAnimation;
private intersectionObserver: IntersectionObserver | undefined;
ctaLink = 'tutorials/learn-angular';
ctaIosLink = 'overview';
readonly ctaLink = isIos ? 'overview' : 'tutorials/learn-angular';
ngOnInit(): void {
if (isIos) {
this.ctaLink = this.ctaIosLink;
}
}
constructor() {
afterNextRender(() => {
this.element = this.home.nativeElement;
ngAfterViewInit() {
this.element = this.home.nativeElement;
if (isPlatformBrowser(this.platformId)) {
// Always scroll to top on home page (even for navigating back)
this.window.scrollTo({top: 0, left: 0, behavior: 'instant'});
@@ -76,18 +69,13 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
if (this.isWebGLAvailable() && !shouldReduceMotion() && !this.isUwu) {
this.loadHomeAnimation();
}
}
}
});
ngOnDestroy(): void {
if (isPlatformBrowser(this.platformId)) {
this.destroyRef.onDestroy(() => {
// Stop observing and disconnect
this.intersectionObserver?.disconnect();
if (this.homeAnimation) {
this.homeAnimation.destroy();
}
}
this.homeAnimation?.destroy();
});
}
private initIntersectionObserver(): void {
@@ -102,9 +90,7 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
this.headerTop(headerEntry);
// Disable animation at end of page
if (this.homeAnimation) {
this.homeAnimation.disableEnd(footerEntry);
}
this.homeAnimation?.disableEnd(footerEntry);
});
// Start observing
@@ -124,12 +110,17 @@ export default class Home implements OnInit, AfterViewInit, OnDestroy {
}
}
private async loadHomeAnimation() {
this.homeAnimation = await injectAsync(this.injector, () =>
import('./services/home-animation.service').then((c) => c.HomeAnimation),
);
await this.homeAnimation.init(this.element);
private loadHomeAnimation() {
from(
injectAsync(this.injector, () =>
import('./services/home-animation.service').then((c) => c.HomeAnimation),
),
)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((homeAnimation) => {
this.homeAnimation = homeAnimation;
this.homeAnimation.init(this.element);
});
}
private isWebGLAvailable() {
@@ -12,7 +12,7 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {RESIZE_EVENT_DELAY, WEBGL_LOADED_DELAY, WINDOW} from '@angular/docs';
import {gsap} from 'gsap';
import {ScrollTrigger} from 'gsap/ScrollTrigger';
import {fromEvent} from 'rxjs';
import {from, fromEvent} from 'rxjs';
import {debounceTime} from 'rxjs/operators';
import {ThemeManager} from '../../../core/services/theme-manager.service';
import {Canvas} from '../components/canvas';
@@ -80,7 +80,7 @@ export class HomeAnimation {
/**
* Initialize CSS styles, GSAP, the WebGL canvas and animations.
*/
async init(element: HTMLDivElement): Promise<void> {
init(element: HTMLDivElement): void {
this.element = element;
// CSS styles needed for the animation
@@ -93,32 +93,40 @@ export class HomeAnimation {
ignoreMobileResize: true,
});
await this.initCanvas();
this.getViews();
// Wrap `initCanvas` in an observable to prevent executing any code,
// such as `getViews()`, if the view is destroyed before the canvas becomes ready.
from(this.initCanvas())
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.getViews();
// Call theme and resize handlers once before setting the animations
this.onTheme();
this.onResize();
this.setAnimations();
// Call theme and resize handlers once before setting the animations
this.onTheme();
this.onResize();
this.setAnimations();
// Call update handler once before starting the animation
this.onUpdate(0, 0, 0, 0);
this.enable();
// Call update handler once before starting the animation
this.onUpdate(0, 0, 0, 0);
this.enable();
// Workaround for the flash of white before the programs are ready
setTimeout(() => {
// Show the canvas
this.element.classList.add(LOADED_CLASS_NAME);
}, WEBGL_LOADED_DELAY);
// Workaround for the flash of white before the programs are ready
const timeoutId = setTimeout(() => {
// Show the canvas
this.element.classList.add(LOADED_CLASS_NAME);
}, WEBGL_LOADED_DELAY);
// If the view is destroyed before the timer fires, we clean up the handle.
// This will be a no-op if the timer has already fired.
this.destroyRef.onDestroy(() => clearTimeout(timeoutId));
});
}
/**
* Initialize the canvas controller.
*/
private async initCanvas(): Promise<void> {
private initCanvas(): Promise<void[]> {
this.canvas = new Canvas(this.document.querySelector(CANVAS)!, this.document, this.window);
await this.canvas.ready();
return this.canvas.ready();
}
/**
@@ -9,7 +9,8 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {WINDOW} from '@angular/docs';
import {NodeRuntimeSandbox, EmbeddedTutorialManager} from '../../editor';
import {EmbeddedTutorialManager} from '../../editor';
import {NodeRuntimeSandbox} from '../../editor/node-runtime-sandbox.service';
import TutorialPlayground from './playground.component';

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