mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
606 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7593653be | |||
| 21b1c3b2ee | |||
| 6c73aaca30 | |||
| c98eab794c | |||
| d45fced21b | |||
| ed48c41f65 | |||
| 75135586d6 | |||
| ff697707ba | |||
| 7d76103999 | |||
| 575f3023c1 | |||
| 4c86ed382d | |||
| 224e60ecb1 | |||
| 492e7560e6 | |||
| 09638ec7c3 | |||
| ab35383285 | |||
| 934e2732b3 | |||
| c20dabda2a | |||
| 62a97f7e4b | |||
| 106cf4ee90 | |||
| 024e307ab0 | |||
| 77b035eca6 | |||
| 4a9b715b3a | |||
| 420aa725ae | |||
| c499c578c9 | |||
| 0588133210 | |||
| 6416a31c1b | |||
| b2b903957a | |||
| bd72571583 | |||
| 628f3f99db | |||
| 79ac570c26 | |||
| 276c12a349 | |||
| 104ac117ea | |||
| c2a74548d9 | |||
| e7d1d8def3 | |||
| 4a390b6c73 | |||
| 5a486a65cf | |||
| c822bf8e76 | |||
| 31e2c99007 | |||
| f8b6bd0cbe | |||
| 5349b027b8 | |||
| 8f8d67dc57 | |||
| 23153a06dd | |||
| fd3b4413f3 | |||
| 670d1660c4 | |||
| 8ca0237d99 | |||
| 3576019c0f | |||
| 05d022d5e6 | |||
| 1df1697c6e | |||
| 05476ea21b | |||
| f38169d0a7 | |||
| 6d7446bc6c | |||
| c25c84d7dc | |||
| f4160c2073 | |||
| 93c6dc6395 | |||
| 76431ed3e3 | |||
| b4ec3cc4e4 | |||
| 84e79f5add | |||
| 2eecf0d9a2 | |||
| da57d1af73 | |||
| 58ea4d2ee8 | |||
| 277ade97ac | |||
| aeb9b819d2 | |||
| 657d532ad1 | |||
| 8dafd2413a | |||
| 796b9a714a | |||
| dd551b1ff3 | |||
| 84adb2fb3b | |||
| 98343ea35e | |||
| c4226a10d0 | |||
| 5e545069ac | |||
| ecf0bb4668 | |||
| 0d54c5f0e2 | |||
| 8f6ca1d9f9 | |||
| 1f51c61372 | |||
| f5e9a862c2 | |||
| 0c8a2858b9 | |||
| a79e8afbad | |||
| 7b7faef739 | |||
| 95afc09206 | |||
| 23cb9a4291 | |||
| 0a863ba03f | |||
| e923d88398 | |||
| 150f0b3c30 | |||
| fc5f9d03cf | |||
| 498d9cdda4 | |||
| fd8d29a157 | |||
| e2e9a9a531 | |||
| 35fd8b567a | |||
| 4e9648d184 | |||
| 54a0541013 | |||
| 9c0587f755 | |||
| ac06941bcf | |||
| 907415c801 | |||
| 225a56677e | |||
| 944181869d | |||
| 3d3e6cbf20 | |||
| 2158bf8bb8 | |||
| 1b46b6db18 | |||
| f23f3e7f5f | |||
| 9414da5b7e | |||
| 8078abe893 | |||
| 661e800302 | |||
| c960a6e492 | |||
| 2eeb4b5666 | |||
| 8f19cf8d84 | |||
| 50a9ed190d | |||
| e437980659 | |||
| d3ab1ea5f2 | |||
| fe7b26e403 | |||
| 70e4c7fbab | |||
| a25f74238e | |||
| 61ad0f8b90 | |||
| a86c3214c2 | |||
| 706cfecaee | |||
| 63cb3f4fa8 | |||
| 787cd875b0 | |||
| 1a151f2dae | |||
| 6b112e6c6c | |||
| 7d58b798c6 | |||
| ab1c84eed9 | |||
| 103a44f690 | |||
| de9092eb23 | |||
| 0b0b34565a | |||
| b17a7e062f | |||
| 7c976c3453 | |||
| eb6bce0ff5 | |||
| 30e486a41c | |||
| a73d5435d8 | |||
| b9d3fe3b44 | |||
| c9ecf9e40b | |||
| 2f213de593 | |||
| ec32591dd7 | |||
| 02b7f5e4f7 | |||
| 31bf694599 | |||
| bdfb60f3e3 | |||
| e99b92a1f0 | |||
| 5c24de5ee8 | |||
| fad5def327 | |||
| de2eab6820 | |||
| ea1aeb3d45 | |||
| 35f0663ce8 | |||
| 2eeeabb760 | |||
| 87372893ea | |||
| 631f60d1f9 | |||
| 390efd51e7 | |||
| c2cedd1954 | |||
| 3c4deaa52b | |||
| b5eea233df | |||
| c0cb6040f8 | |||
| fb901f7eda | |||
| 17da2c392e | |||
| 6cf0100fe4 | |||
| d2137928e8 | |||
| 1d4783c01c | |||
| 9ee99c7cc0 | |||
| 5b8a403220 | |||
| 9c8f2dab7d | |||
| 9f1a78ca74 | |||
| d45440eda4 | |||
| eb7c593fda | |||
| 48802fd7ed | |||
| 5cea3576cf | |||
| 913bb6ad14 | |||
| 79f1cd462e | |||
| 4ea3cafdc8 | |||
| 94b9a3ef70 | |||
| c5afb88d9a | |||
| f58f9c892e | |||
| 7f33cbeb6c | |||
| dd630ef955 | |||
| 13fd2b1aa3 | |||
| cb8e974de0 | |||
| 567f292e8e | |||
| dcb9af6dfa | |||
| 9a9f4e7f93 | |||
| b8811b45d8 | |||
| 47486f8c49 | |||
| c36385c691 | |||
| 22a209055c | |||
| eaf72d456a | |||
| 5a3cacaaac | |||
| 98610aabaf | |||
| d99e336a03 | |||
| c2f7eaa833 | |||
| 680e1c05c6 | |||
| fd956f675a | |||
| bd1cdac54d | |||
| 8de0d25ffa | |||
| 2931ca1fca | |||
| 064749e010 | |||
| b481294047 | |||
| e45a7fe734 | |||
| dea0819aa9 | |||
| 084f7dc08d | |||
| fc557f0276 | |||
| 95b3f37d4a | |||
| a8aab64809 | |||
| 81cabc1477 | |||
| 9f4c025531 | |||
| 9c5658adb1 | |||
| b8d1164e0f | |||
| ee7b4eb24d | |||
| 815e1a03a9 | |||
| a37b6c55a8 | |||
| a6a0347998 | |||
| 30f0914754 | |||
| 22afbb2f36 | |||
| 27397b3f4f | |||
| 2d9987869b | |||
| 29a17ed791 | |||
| e10a63453d | |||
| 5f6088da3a | |||
| 6e0d783e5b | |||
| 08ea105aa3 | |||
| 63d8005703 | |||
| 0806ee3826 | |||
| 83da928206 | |||
| dfd5e3a90a | |||
| d0038235d5 | |||
| 3cad0d644e | |||
| d5b35b1826 | |||
| ddfc833df9 | |||
| 5b59dbd36f | |||
| 06d94ac0ca | |||
| 097208454b | |||
| b386f95bd0 | |||
| 9b69e29603 | |||
| 62453330f5 | |||
| d75046bc09 | |||
| 17f19272c1 | |||
| 302ea2ee46 | |||
| ece827e269 | |||
| f67818a0ea | |||
| 4937d162f5 | |||
| 7b5bcbf401 | |||
| a4fceda35b | |||
| 50e74add52 | |||
| 4999868d8d | |||
| 3606902b33 | |||
| 39cff9c235 | |||
| ad815106dd | |||
| ba009b6031 | |||
| bd2868e915 | |||
| c6ca1cd725 | |||
| e229328b39 | |||
| 8b4eec6683 | |||
| 18003a33bb | |||
| a7e8abbb7e | |||
| 4f8d3995f0 | |||
| 387793fe29 | |||
| 15fc190556 | |||
| 0f47fda51b | |||
| 19d0ceede3 | |||
| 0c6eb60c86 | |||
| 8b3b069be7 | |||
| e7fa177923 | |||
| 760910ecf1 | |||
| 51cc914807 | |||
| f56bb07d83 | |||
| c6d7500203 | |||
| e53c8abaf9 | |||
| cb1163e5e5 | |||
| b772f518f1 | |||
| adfb83146b | |||
| f50ec42f15 | |||
| 66e8385b6a | |||
| 11834a4274 | |||
| d940885c5b | |||
| c32e732d3d | |||
| d019ee3c0b | |||
| 20a24631a4 | |||
| dd15efb7c3 | |||
| fd293d3397 | |||
| 0b9d1cfb7b | |||
| 11767cabe4 | |||
| 85d6a2bc6e | |||
| 7ddd10bb44 | |||
| 4b3b149ba1 | |||
| ec26d38778 | |||
| a1441a432d | |||
| c4abadb528 | |||
| 14f16226aa | |||
| 0c6604f478 | |||
| 63d828aa33 | |||
| ce0f0febe2 | |||
| 460dbbb8e9 | |||
| 15c71fba43 | |||
| ea2016a6dc | |||
| 24c0c5a180 | |||
| 2ea6dfc6c9 | |||
| 108252bf67 | |||
| 6550b9d776 | |||
| 64d34da0b2 | |||
| fd5ff5c1a9 | |||
| 8a3f312115 | |||
| e79e7994d4 | |||
| 12afc1d164 | |||
| 6fa227031e | |||
| 2a0241a665 | |||
| 6883889123 | |||
| 407ab1a92f | |||
| ec6334da85 | |||
| 85dd096c11 | |||
| 3e2ed305d1 | |||
| ff2c0053c8 | |||
| 91ed22c241 | |||
| c3229b3136 | |||
| 8fe34e146b | |||
| 8c21866f49 | |||
| 01ed57f297 | |||
| 03e1a95c26 | |||
| 7dfbacbcf8 | |||
| d6585fe837 | |||
| 81876c2583 | |||
| 38428945ac | |||
| da1f61cfbd | |||
| 680d99b1c3 | |||
| cab5ddd526 | |||
| 95ecce8334 | |||
| dd208ca259 | |||
| 43d61ecbb2 | |||
| cfa7664361 | |||
| 9c032972a8 | |||
| 3867cd8554 | |||
| 5a0f272519 | |||
| 68ba9c45cb | |||
| c750b3cf11 | |||
| 80f08838b0 | |||
| fdae63c11f | |||
| e4eeb3adc0 | |||
| b3b5611096 | |||
| df32f957f9 | |||
| 0df5442f4e | |||
| dabe34ad06 | |||
| 8e80575ff4 | |||
| 05d5087252 | |||
| bbbdf0a6ed | |||
| a2950805df | |||
| 35d02f228c | |||
| d6b49f12ef | |||
| c2e0be7600 | |||
| b63496853d | |||
| 1e3462db00 | |||
| ab3f4367f4 | |||
| bb5e75a5a1 | |||
| 3937afc316 | |||
| f29fcd882a | |||
| 50af8cbd15 | |||
| aff9e36a98 | |||
| 8ab433abdd | |||
| 9505541d32 | |||
| 70615117a2 | |||
| 1fa7879cfd | |||
| 35046d3dba | |||
| cdbb957334 | |||
| a64a90dbbe | |||
| bd27aa2cf3 | |||
| 4aae3379c2 | |||
| 825122b6d2 | |||
| 19aa1eb95e | |||
| a8d0155303 | |||
| 9306abe883 | |||
| 522c5ba868 | |||
| 3d09d8e831 | |||
| 8d5210c9fe | |||
| 496967e7b1 | |||
| 424ecf840d | |||
| 9a3d5b36c2 | |||
| 346ceb7dc0 | |||
| b1bf535f8e | |||
| 26d12158e1 | |||
| af76b9dd4d | |||
| b327d72ed2 | |||
| 74e7681142 | |||
| a67e00741c | |||
| 88e6ebec01 | |||
| f9bcccc2b9 | |||
| 72dfb4d92a | |||
| 6990f88d97 | |||
| df3258cfc4 | |||
| 528ce58222 | |||
| c66a19f0de | |||
| 1c3b1cf18d | |||
| 458bc4a2c8 | |||
| 907a94dcec | |||
| cf9620f7d0 | |||
| 0c2efc0d46 | |||
| 0e04233a7c | |||
| d072791f13 | |||
| 5a6fefb687 | |||
| 571747d5cc | |||
| 7bb241f7b6 | |||
| d7672cfceb | |||
| e682e53113 | |||
| 042471044d | |||
| 1b324a2ca6 | |||
| a4f6d407c2 | |||
| 611f6a49d1 | |||
| 177234a6f7 | |||
| bea4cb72d1 | |||
| 4123ebf61e | |||
| 01bfb83fc9 | |||
| 4448356313 | |||
| 960de629ed | |||
| 160a8b4be7 | |||
| 8a7cbd4668 | |||
| 3e7808b39f | |||
| b51bab583d | |||
| 57e80a5737 | |||
| 042e6d2616 | |||
| 899df39c7c | |||
| ceefceb004 | |||
| c921786260 | |||
| 6e9da70b35 | |||
| 8efee1c71d | |||
| 87a72f3dd0 | |||
| 9625780259 | |||
| dbd50be7f7 | |||
| fb05fc86d0 | |||
| 1df564b9f9 | |||
| ca9b5bd658 | |||
| b3f2bad593 | |||
| aeb4b419af | |||
| ffe40f4bfa | |||
| 19b59df2dc | |||
| 8feb541060 | |||
| 105274fe32 | |||
| 1d1777931e | |||
| d306737e54 | |||
| 8bbe6dc46c | |||
| 6fb39d9b62 | |||
| 85122cb12d | |||
| ddd3198dc2 | |||
| d1135f5840 | |||
| 30b50e7142 | |||
| ebae211add | |||
| 085784e4f1 | |||
| 145e77d09d | |||
| dbc1452de3 | |||
| 5d6e534d8b | |||
| 405fa59375 | |||
| bfc2afdb5b | |||
| e35eea6e92 | |||
| 2c53243f00 | |||
| 4ca2722d6f | |||
| f0b1061791 | |||
| b885851cbe | |||
| d94b19a92f | |||
| 0fa8099d50 | |||
| 1f86de019f | |||
| 4df3a8bb36 | |||
| cb7ace96a4 | |||
| 6bda88d203 | |||
| b275206a49 | |||
| 6284126da5 | |||
| 94a8f797e5 | |||
| 508d9c34d5 | |||
| e4c09776b0 | |||
| 094cdfe0b5 | |||
| ed78fa05c7 | |||
| 75c40e7ac7 | |||
| ce80136e7b | |||
| 1cf1370568 | |||
| d0ba332292 | |||
| adae4c7ab0 | |||
| 2d4262cfbd | |||
| 92d2498910 | |||
| 5dd17d7b81 | |||
| 00455105cf | |||
| 6f48b4f5ed | |||
| 4adbc4fa19 | |||
| fc73252287 | |||
| a88f353a45 | |||
| 30b78bdc71 | |||
| 6dff1cf85d | |||
| 2080dd1fec | |||
| 8b9bdd0a63 | |||
| d50e971e98 | |||
| 5d46554e3f | |||
| 95c386469c | |||
| e55260f693 | |||
| 9989c5fb78 | |||
| 4bb5774f3b | |||
| 52bc0208f9 | |||
| e7b2dde6d1 | |||
| 54fc393d27 | |||
| d9c980a958 | |||
| 4831a9f676 | |||
| 417c385ddc | |||
| 87f4797321 | |||
| 721094788a | |||
| c7eee8300f | |||
| 5974cd0afc | |||
| f2cf96b519 | |||
| 849b8401a0 | |||
| 22fefe7880 | |||
| ebc52ff434 | |||
| a792315f09 | |||
| 61614f6caa | |||
| fa4bcf12cd | |||
| 0159268971 | |||
| d12e6f0986 | |||
| 3f13db87e2 | |||
| 724e917f7a | |||
| 230e16d3a5 | |||
| c9f584b918 | |||
| a904d9f77b | |||
| e673eb6df2 | |||
| 074666b2e8 | |||
| 4c2d860c5f | |||
| 551f120530 | |||
| 710a4bf02b | |||
| 95e8c2fdee | |||
| 227acddd3a | |||
| cb5879f566 | |||
| 029685bd93 | |||
| b95753eb7d | |||
| c70a6a6ecc | |||
| e45f8afdab | |||
| 871fa1b2dd | |||
| 6e6a02206c | |||
| 951671ab09 | |||
| e8f8ac20d6 | |||
| 72534e2a34 | |||
| 9273f1c3c2 | |||
| 910768f5cc | |||
| 6e82167481 | |||
| 69da6390b1 | |||
| 78755771e1 | |||
| 36c2f4b6f9 | |||
| a39e3fdabe | |||
| e8c44a00f9 | |||
| e34365cfd5 | |||
| 1ba9b7ac50 | |||
| 65fa5b5439 | |||
| 7fd076bdd3 | |||
| 1b4dcc01ff | |||
| ebc90c26f5 | |||
| 573aadef7e | |||
| 26fd0839c3 | |||
| 27276374ab | |||
| f53f878e0f | |||
| c09f5352f6 | |||
| 8bdd98ef41 | |||
| 933ca9e5dc | |||
| 4d6a6aafee | |||
| 4a76058baf | |||
| 4d983e9904 | |||
| 511d9ca9d2 | |||
| c63bc58e0f | |||
| e38c1bf743 | |||
| fa6e82b569 | |||
| 10e9022a07 | |||
| b22835579e | |||
| a056413520 | |||
| 33b2d9905d | |||
| ad699cebb5 | |||
| 89d47d814d | |||
| 460c1c7e71 | |||
| 405b05607c | |||
| 66b40d4fb3 | |||
| 783f20edbc | |||
| 7f1b790f84 | |||
| f0dba6deb9 | |||
| e7f24014cf | |||
| 9333751525 | |||
| f34eb65f89 | |||
| 0aaadafc50 | |||
| f4469ad583 | |||
| 5671f2cc07 | |||
| 008e20ca56 | |||
| 5c16caa95e | |||
| 99db2e9065 | |||
| 7b5625e72a | |||
| 4cf1a92288 | |||
| d9923b72a2 | |||
| 3242a61bae | |||
| 17733b70a3 | |||
| 87a422358b | |||
| f05d08f432 | |||
| ab536f8f32 | |||
| d01e54dea4 | |||
| da364d2635 | |||
| 4fb24cadee | |||
| ac865b51f7 | |||
| 94b707957a | |||
| e3b3290998 | |||
| 09234753e1 | |||
| e6a8bb81f9 | |||
| 7d985ce08e | |||
| a7e470a1b3 | |||
| 4d19408e9b | |||
| 07a08ab9f8 | |||
| 04ba09a8d9 | |||
| e66aeac8d0 | |||
| bea5840864 | |||
| 3a65814f53 | |||
| 0d35088b56 | |||
| 3ccd5a4354 | |||
| c963f35d2c | |||
| 80a7419a16 | |||
| 49295778bc | |||
| 473dd3e1cb | |||
| 00905c1c03 | |||
| 9529362617 | |||
| e005eb4e66 |
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../AGENTS.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../.gemini/skills
|
||||
+1
-1
@@ -1 +1 @@
|
||||
8.5.0
|
||||
8.6.0
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
# Image metadata and config.
|
||||
# Ideally, the Node.js version should match what we use on CI.
|
||||
FROM cimg/node:18.13.0@sha256:45d0ee279f522c4562a464df71108104cc9b2187205333ffd0707d4f05589731
|
||||
|
||||
FROM cimg/node:22.21.1-browsers@sha256:eee8ed828d5a54196456a86ac6872c43325acad54e59632261e23b486c458992
|
||||
|
||||
LABEL name="Angular dev environment" \
|
||||
description="This image can be used to create a dev environment for building Angular." \
|
||||
vendor="angular" \
|
||||
version="1.0"
|
||||
|
||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||
description="This image can be used to create a dev environment for building Angular." \
|
||||
vendor="angular" \
|
||||
version="1.0"
|
||||
|
||||
EXPOSE 4200 4201 4205 4206 9876
|
||||
|
||||
# Switch to `root`.
|
||||
USER root
|
||||
|
||||
|
||||
# Configure `Node.js`/`npm`.
|
||||
RUN npm config --global set user root
|
||||
|
||||
|
||||
# Go! (And keep going.)
|
||||
CMD ["tail", "--follow", "/dev/null"]
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
{
|
||||
"name": "Angular dev container",
|
||||
"dockerFile": "Dockerfile",
|
||||
"appPort": [4000, 4200, 4433, 5000, 8080, 9876],
|
||||
"forwardPorts": [4200, 4201, 4205, 4206, 9876],
|
||||
"postCreateCommand": "pnpm install",
|
||||
"extensions": [
|
||||
"devondcarew.bazel-code",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||
],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["BazelBuild.vscode-bazel", "ms-vscode.vscode-typescript-tslint-plugin"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
description = "Researches part of the codebase and creates a skill for it"
|
||||
prompt="""
|
||||
## Role
|
||||
|
||||
You are an experienced senior developer specializing in reverse engineering and understanding
|
||||
complex code, prompt engineering, and context engineering.
|
||||
|
||||
Your task is to build a complete understanding of the mental model and architecture of the code,
|
||||
and to create an efficient context file that allows a coding agent to understand and work with the
|
||||
code.
|
||||
|
||||
## Guiding Principles
|
||||
|
||||
1. **Deep Analysis:** Understand the _why_ behind the code. Not just a surface level listing of
|
||||
files and classes.
|
||||
|
||||
2. **Curiosity:** Be curious. If something is unclear, confusing, or unexpected you _MUST_
|
||||
investigate further until you fully understand.
|
||||
|
||||
3. **Efficient Token Use:** The final output will be directly included into the context of the
|
||||
coding assistant, so be sure to make efficient use of tokens. Think deeply, but only capture the
|
||||
most important information for the coding agent in the final output
|
||||
|
||||
## Procedure
|
||||
|
||||
1. Fully explore the code before first, with a focus on understanding the architecture and how all
|
||||
of the pieces fit together.
|
||||
|
||||
2. Develop an understanding of the mental model behind the architecture. _Why_ is the code is
|
||||
architected this way? How should developers think about the system?
|
||||
|
||||
3. Document your findings using the given output format described in the next section.
|
||||
|
||||
## Output Format
|
||||
|
||||
Note the following placeholders below:
|
||||
|
||||
- `[package]`: is a unique identifier for the current code package (for example if you're looking at
|
||||
code under `packages/forms/signals` you might use `signal-forms` as the `[package]`)
|
||||
- `[code-location]`: is the location of the current code within the larger repository
|
||||
- `[context]`: is the context to add to the coding agent when it is working with this code.
|
||||
|
||||
With those placeholders in mind, write a file create a new directory under `.gemini/skills` with the
|
||||
name `reference-[package]/`, and under that directory add a `SKILL.md` file with the following
|
||||
content:
|
||||
|
||||
```md
|
||||
---
|
||||
name: reference-[package]
|
||||
description: Explains the mental model and architecture of the code under `[code-location]`. You MUST use this skill any time you plan to work with code in `[code-location]`
|
||||
---
|
||||
|
||||
[context]
|
||||
```
|
||||
|
||||
## Additional User Instructions
|
||||
|
||||
The user may have additional instructions.
|
||||
|
||||
- The user should indicate what package to research
|
||||
- The user may indicate that they want to update a package that has already been researched. In this
|
||||
case, read the existing skill and make any required updates based on your research
|
||||
- The user may request supplemental information be added to the skill (if so, add this to the
|
||||
existing skill in a new markdown file under a `references` directory within the skill. Add a
|
||||
section to the main `SKILL.md` that mentions what supplemental information is available)
|
||||
|
||||
Here are the user's additional instructions:
|
||||
|
||||
{{args}}
|
||||
"""
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"context": {
|
||||
"fileName": ["AGENTS.md", "GEMINI.md"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
---
|
||||
name: adev-writing-guide
|
||||
description: Comprehensive writing guide for Angular documentation (adev). Covers Google Technical Writing standards, Angular-specific markdown extensions, code blocks, and components. Use when authoring or reviewing content in adev/src/content.
|
||||
---
|
||||
|
||||
# Angular Documentation (adev) Writing Guide
|
||||
|
||||
This skill provides comprehensive guidelines for authoring content in `adev/src/content`. It combines Google's technical writing standards with Angular-specific markdown conventions, components, and best practices.
|
||||
|
||||
## I. Google Technical Writing Guidelines
|
||||
|
||||
### Tone and Content
|
||||
|
||||
- **Be conversational and friendly:** Maintain a helpful yet professional tone. Avoid being overly casual.
|
||||
- **Write accessibly:** Ensure documentation is understandable to a diverse global audience, including non-native English speakers.
|
||||
- **Audience-first:** Focus on what the user needs to do, not just what the system does.
|
||||
- **Avoid pre-announcing:** Do not mention unreleased features or make unsupported claims.
|
||||
- **Use descriptive link text:** Link text should clearly indicate the destination (e.g., avoid "click here").
|
||||
|
||||
### Language and Grammar
|
||||
|
||||
- **Use second person ("you"):** Address the reader directly.
|
||||
- **Prefer active voice:** Clearly state who or what is performing the action (e.g., "The system generates a token" vs "A token is generated").
|
||||
- **Standard American English:** Use standard American spelling and punctuation.
|
||||
- **Conditional clauses first:** Place "if" or "when" clauses before the instruction (e.g., "If you encounter an error, check the logs").
|
||||
- **Define terms:** Introduce new or unfamiliar terms/acronyms upon first use.
|
||||
- **Consistent terminology:** Use the same term for the same concept throughout the document.
|
||||
- **Conciseness:** Aim for one idea per sentence. Keep sentences short.
|
||||
|
||||
### Formatting and Organization
|
||||
|
||||
- **Sentence case for headings:** Capitalize only the first word and proper nouns in titles and headings.
|
||||
- **Lists:**
|
||||
- **Numbered lists:** Use for sequential steps or prioritized items.
|
||||
- **Bulleted lists:** Use for unordered collections of items.
|
||||
- **Description lists:** Use for term-definition pairs.
|
||||
- **Serial commas:** Use the Oxford comma (comma before the last item in a list of three or more).
|
||||
- **Code formatting:** Use code font for code-related text (filenames, variables, commands).
|
||||
- **UI Elements:** formatting user interface elements in **bold**.
|
||||
- **Date formatting:** Use unambiguous formats (e.g., "September 4, 2024" rather than "9/4/2024").
|
||||
- **Structure:** Use logical hierarchy with clear introductions and navigation. Headings should be task-based where possible.
|
||||
|
||||
### Images and Code Samples
|
||||
|
||||
- **Images:** Use simple, clear illustrations to enhance understanding.
|
||||
- **Captions:** Write captions that support the image.
|
||||
- **Code Samples:**
|
||||
- Ensure code is correct and builds without errors.
|
||||
- Follow language-specific conventions.
|
||||
- **Comments:** Focus on _why_, not _what_. Avoid commenting on obvious code.
|
||||
|
||||
### Reference Hierarchy
|
||||
|
||||
1. Project-specific style guidelines (if any exist in `CONTRIBUTING.md` or similar).
|
||||
2. Google Developer Documentation Style Guide.
|
||||
3. Merriam-Webster (spelling).
|
||||
4. Chicago Manual of Style (non-technical).
|
||||
5. Microsoft Writing Style Guide (technical).
|
||||
|
||||
---
|
||||
|
||||
## II. Angular Documentation Specifics
|
||||
|
||||
### Code Blocks
|
||||
|
||||
Use the appropriate language identifier for syntax highlighting:
|
||||
|
||||
- **TypeScript (Angular):** Use `angular-ts` when TypeScript code examples contain inline templates.
|
||||
- **HTML (Angular):** Use `angular-html` for Angular templates.
|
||||
- **TypeScript (Generic):** Use `ts` for plain TypeScript.
|
||||
- **HTML (Generic):** Use `html` for plain HTML.
|
||||
- **Shell/Terminal:** Use `shell` or `bash`.
|
||||
- **Mermaid Diagrams:** Use `mermaid`.
|
||||
|
||||
#### Attributes
|
||||
|
||||
You can enhance code blocks with attributes in curly braces `{}` after the language identifier:
|
||||
|
||||
- `header="Title"`: Adds a title to the code block.
|
||||
- `linenums`: Enables line numbering.
|
||||
- `highlight="[1, 3-5]"`: Highlights specific lines.
|
||||
- `hideCopy`: Hides the copy button.
|
||||
- `prefer`: Marks code as a preferred example (green border/check).
|
||||
- `avoid`: Marks code as an example to avoid (red border/cross).
|
||||
|
||||
**Example:**
|
||||
|
||||
````markdown
|
||||
```angular-ts {header:"My Component", linenums, highlight="[2]"}
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: '<h1>Hello</h1>',
|
||||
})
|
||||
export class App {}
|
||||
```
|
||||
````
|
||||
|
||||
#### `<docs-code>` Component
|
||||
|
||||
For more advanced code block features, use the `<docs-code>` component:
|
||||
|
||||
- `path`: Path to a source file (e.g., `adev/src/content/examples/...`).
|
||||
- `header`: Custom header text.
|
||||
- `language`: Language identifier (e.g., `angular-ts`).
|
||||
- `linenums`: Boolean attribute.
|
||||
- `highlight`: Array of line numbers/ranges (e.g., `[[3,7], 9]`).
|
||||
- `diff`: Path to diff file.
|
||||
- `visibleLines`: Range of lines to show initially (collapsible).
|
||||
- `region`: Region to extract from source file.
|
||||
- `preview`: Boolean. Renders a live preview (StackBlitz). _Only works with standalone examples._
|
||||
- `hideCode`: Boolean. Collapses code by default.
|
||||
|
||||
**Multifile Example:**
|
||||
|
||||
```html
|
||||
<docs-code-multifile path="..." preview>
|
||||
<docs-code path="..." />
|
||||
<docs-code path="..." />
|
||||
</docs-code-multifile>
|
||||
```
|
||||
|
||||
### Alerts / Admonitions
|
||||
|
||||
Use specific keywords followed by a colon for alerts. These render as styled blocks.
|
||||
|
||||
- `NOTE:` For ancillary information.
|
||||
- `TIP:` For helpful hints or shortcuts.
|
||||
- `IMPORTANT:` For crucial information.
|
||||
- `CRITICAL:` For warnings about potential data loss or severe issues.
|
||||
- `TODO`: For incomplete documentation.
|
||||
- `QUESTION:` To pose a question to the reader.
|
||||
- `SUMMARY:` For section summaries.
|
||||
- `TLDR:` For concise summaries.
|
||||
- `HELPFUL:` For best practices.
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||
TIP: Use `ng serve` to run your application locally.
|
||||
```
|
||||
|
||||
### Custom Components
|
||||
|
||||
- **Cards (`<docs-card>`):**
|
||||
- Must be inside `<docs-card-container>`.
|
||||
- Attributes: `title`, `link`, `href`.
|
||||
- **Callouts (`<docs-callout>`):**
|
||||
- Attributes: `title`, `important`, `critical`.
|
||||
- **Pills (`<docs-pill>`):**
|
||||
- Must be inside `<docs-pill-row>`.
|
||||
- Attributes: `title`, `href`.
|
||||
- **Steps / Workflow (`<docs-step>`):**
|
||||
- Must be inside `<docs-workflow>`.
|
||||
- Attributes: `title`.
|
||||
- **Tabs (`<docs-tab>`):**
|
||||
- Must be inside `<docs-tab-group>`.
|
||||
- Attributes: `label`.
|
||||
- **Videos (`<docs-video>`):**
|
||||
- Attributes: `src` (YouTube embed URL), `alt`.
|
||||
|
||||
### Images
|
||||
|
||||
Use standard markdown syntax with optional attributes for sizing and loading behavior.
|
||||
|
||||
- `#small`, `#medium`: Append to image URL for sizing.
|
||||
- `{loading: 'lazy'}`: Add attribute for lazy loading.
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
### Headers
|
||||
|
||||
- Use markdown headers (`#`, `##`, `###`).
|
||||
- Ensure a logical hierarchy (don't skip levels).
|
||||
- `h2` and `h3` are most common for content structure.
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
name: reference-compiler-cli
|
||||
description: Explains the mental model and architecture of the code under `packages/compiler-cli`. You MUST use this skill any time you plan to work with code in `packages/compiler-cli`
|
||||
---
|
||||
|
||||
# Angular Compiler CLI (`ngtsc`) Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
The `packages/compiler-cli` package contains the Angular Compiler (Ivy), often referred to as `ngtsc`. It is a wrapper around the TypeScript compiler (`tsc`) that extends it with Angular-specific capabilities.
|
||||
|
||||
The core goal of `ngtsc` is to compile Angular decorators (like `@Component`, `@Directive`, `@Pipe`) into static properties on the class (Ivy instructions, e.g., `static ɵcmp = ...`). It also performs template type checking and ahead-of-time (AOT) compilation.
|
||||
|
||||
## Mental Model
|
||||
|
||||
The compiler is designed as a **lazy, incremental, and partial** compilation pipeline.
|
||||
|
||||
1. **Wrapper Pattern**: `NgtscProgram` wraps the standard `ts.Program`. It intercepts calls to act as a drop-in replacement for standard tooling.
|
||||
2. **Traits System**: Every class with an Angular decorator is considered a "Trait". The compiler manages the state of these traits through a state machine:
|
||||
- **Pending**: Detected but not processed.
|
||||
- **Analyzed**: Metadata extracted, template parsed (but dependencies not yet linked).
|
||||
- **Resolved**: Dependencies (directives/pipes in template) resolved, import cycles handled.
|
||||
- **Skipped**: Not an Angular class.
|
||||
3. **Lazy Analysis**: Analysis only happens when necessary (e.g., when diagnostics are requested or emit is prepared).
|
||||
4. **Output AST**: The compiler generates an intermediate "Output AST" (`o.Expression`) for the generated code, which is then translated into TypeScript AST nodes during the emit phase.
|
||||
|
||||
## Key Subsystems
|
||||
|
||||
### 1. Core Orchestration (`ngtsc/core`)
|
||||
|
||||
- **`NgtscProgram`**: The public API implementing `api.Program`. It manages the `ts.Program` and the `NgCompiler`.
|
||||
- **`NgCompiler`**: The brain of the compiler. It orchestrates the compilation phases (Analysis, Resolution, Type Checking, Emit). It holds the `TraitCompiler`.
|
||||
|
||||
### 2. Trait Compilation (`ngtsc/transform`)
|
||||
|
||||
- **`TraitCompiler`**: Manages the lifecycle of "Traits". It iterates over source files, identifies decorated classes, and delegates to the appropriate `DecoratorHandler`.
|
||||
- **`Trait`**: A state container for a class, holding its handler, analysis results, and resolution results.
|
||||
|
||||
### 3. Decorator Handlers (`ngtsc/annotations`)
|
||||
|
||||
- **`DecoratorHandler`**: An interface for handling specific decorators.
|
||||
- **`ComponentDecoratorHandler`**: The most complex handler. It:
|
||||
- Extracts metadata (selector, inputs, outputs).
|
||||
- Parses the template.
|
||||
- Resolves used directives and pipes (`R3TargetBinder`).
|
||||
- Generates the `ɵcmp` instruction.
|
||||
- **`DirectiveDecoratorHandler`**, **`PipeDecoratorHandler`**, **`NgModuleDecoratorHandler`**: Handle their respective decorators.
|
||||
|
||||
### 4. Template Type Checking (`ngtsc/typecheck`)
|
||||
|
||||
- **`TemplateTypeChecker`**: Generates "Type Check Blocks" (TCBs). A TCB is a block of TypeScript code that represents the template's logic in a way `tsc` can understand and check for errors.
|
||||
- **`TypeCheckBlock`**: The actual generated code that validates bindings, events, and structural directives.
|
||||
|
||||
### 5. Metadata & Scope (`ngtsc/metadata`, `ngtsc/scope`)
|
||||
|
||||
- **`MetadataReader`**: Reads Angular metadata from source files (using `LocalMetadataRegistry`) and `.d.ts` files (using `DtsMetadataReader`).
|
||||
- **`ScopeRegistry`**: Determines the "compilation scope" of a component (which directives/pipes are available to it), handling `NgModule` transitive exports and Standalone Component imports.
|
||||
|
||||
### 6. Emit & Transformation (`ngtsc/transform`)
|
||||
|
||||
- **`ivyTransformFactory`**: A TypeScript transformer factory.
|
||||
- **`IvyCompilationVisitor`**: Visits classes, triggers compilation via `TraitCompiler`, and collects the Output AST.
|
||||
- **`IvyTransformationVisitor`**: Translates the Output AST into TypeScript AST, injects the `static ɵ...` fields, and removes the original decorators.
|
||||
|
||||
## Compilation Phases
|
||||
|
||||
1. **Construction**: `NgtscProgram` creates `NgCompiler`, which sets up all registries and the `TraitCompiler`.
|
||||
2. **Analysis** (`analyzeSync`):
|
||||
- The `TraitCompiler` scans files.
|
||||
- `DecoratorHandler`s extract metadata and parse templates.
|
||||
- No cross-file resolution happens here (allowing for parallelism and caching).
|
||||
3. **Resolution** (`resolve`):
|
||||
- `TraitCompiler` resolves traits.
|
||||
- Components link their templates to specific Directives and Pipes (found via `ScopeRegistry`).
|
||||
- Import cycles are detected and handled (e.g., via "remote scoping").
|
||||
4. **Type Checking**:
|
||||
- `TemplateTypeChecker` creates TCBs for all components.
|
||||
- TypeScript diagnostics are retrieved for these TCBs.
|
||||
5. **Emit** (`prepareEmit`):
|
||||
- `ivyTransformFactory` is created.
|
||||
- TS `emit` is called.
|
||||
- The transformers run, injecting the compiled Ivy instructions into the JS/DTS output.
|
||||
|
||||
## Important File Locations
|
||||
|
||||
- `packages/compiler-cli/src/ngtsc/program.ts`: Entry point (`NgtscProgram`).
|
||||
- `packages/compiler-cli/src/ngtsc/core/src/compiler.ts`: Core logic (`NgCompiler`).
|
||||
- `packages/compiler-cli/src/ngtsc/transform/src/trait.ts`: Trait state machine.
|
||||
- `packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts`: Component compilation logic.
|
||||
- `packages/compiler-cli/src/ngtsc/typecheck/src/template_type_checker.ts`: Type checking logic.
|
||||
- `packages/compiler-cli/src/ngtsc/transform/src/transform.ts`: AST transformation logic.
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
name: reference-core
|
||||
description: Explains the mental model and architecture of the code under `packages/core`. You MUST use this skill any time you plan to work with code in `packages/core`
|
||||
---
|
||||
|
||||
# Angular Core (`packages/core`) Mental Model
|
||||
|
||||
This document outlines the architecture and mental model for `packages/core`, the heart of the Angular framework.
|
||||
|
||||
## 1. High-Level Architecture
|
||||
|
||||
`packages/core` contains the runtime logic for Angular. Its primary responsibilities are:
|
||||
|
||||
1. **Rendering (Ivy/Render3)**: Transforming templates into DOM updates.
|
||||
2. **Dependency Injection (DI)**: Managing object creation and lifetime.
|
||||
3. **Change Detection**: Synchronizing the model with the view.
|
||||
4. **Reactivity**: Signals and Zone.js integration.
|
||||
|
||||
## 2. Rendering Engine (Ivy / Render3)
|
||||
|
||||
The rendering engine (located in `packages/core/src/render3`) uses an **instruction-based** approach.
|
||||
|
||||
### Key Concepts
|
||||
|
||||
- **Instructions**: The Angular compiler transforms templates into a sequence of instruction calls (e.g., `ɵɵelementStart`, `ɵɵtext`, `ɵɵproperty`). These instructions are executed at runtime to create and update the view.
|
||||
- _Location_: `packages/core/src/render3/instructions`
|
||||
|
||||
- **LView (Logical View)**: An array containing the _state_ of a specific view instance. It holds:
|
||||
- DOM nodes (`RElement`, `RText`).
|
||||
- Binding values (for change detection).
|
||||
- Directive/Component instances.
|
||||
- _Context_: `packages/core/src/render3/interfaces/view.ts`
|
||||
|
||||
- **TView (Template View)**: An array containing the _static structure_ of a view. It is shared across all instances (`LView`s) of the same component/template. It holds:
|
||||
- Property names for bindings.
|
||||
- Node relationship information.
|
||||
- Compiled directive definitions.
|
||||
- _Context_: `packages/core/src/render3/interfaces/view.ts`
|
||||
|
||||
- **Memory Layout**: `LView` and `TView` are parallel arrays. Index `i` in `LView` corresponds to metadata at index `i` in `TView`.
|
||||
- `HEADER`: Fixed size, contains context (Parent, Host, etc.).
|
||||
- `DECLS`: Static nodes (elements, text, pipes).
|
||||
- `VARS`: Binding values.
|
||||
- `EXPANDO`: Dynamic data (host bindings, injectors).
|
||||
|
||||
### The Render Cycle
|
||||
|
||||
1. **Creation Mode**: Instructions create DOM nodes and store them in `LView`.
|
||||
2. **Update Mode**: Instructions check current values against previous values stored in `LView`. If changed, they update the DOM.
|
||||
|
||||
## 3. Dependency Injection (DI)
|
||||
|
||||
DI in Angular is hierarchical and split into two systems that interact:
|
||||
|
||||
### Module Injector (`R3Injector`)
|
||||
|
||||
- Configured via `@NgModule.providers` or `providedIn: 'root'`.
|
||||
- Stored in a hierarchy of `R3Injector` instances.
|
||||
- _Location_: `packages/core/src/di/r3_injector.ts`
|
||||
|
||||
### Node Injector
|
||||
|
||||
- Configured via `@Component.providers` or `@Directive.providers`.
|
||||
- **Not a class**, but a data structure embedded in the `LView` ("Expando" section).
|
||||
- Uses **Bloom Filters** (`TView.data`) to quickly check if a token is present at a specific node index before traversing up the tree.
|
||||
- Resolves tokens starting from the current node, walking up the view tree (Element Injector hierarchy), and falling back to the Module Injector if not found.
|
||||
|
||||
## 4. Change Detection
|
||||
|
||||
- **Dirty Checking**: Angular checks if values bound in templates have changed.
|
||||
- **Strategies**:
|
||||
- `Default`: Checks everything.
|
||||
- `OnPush`: Checks only if inputs change, events fire, or signals update.
|
||||
- **Signals**: The new reactivity primitive. Signals notify the scheduler when they change, potentially allowing for fine-grained updates (Zoneless).
|
||||
|
||||
## 5. Key Directories to Know
|
||||
|
||||
- `src/render3`: The Ivy rendering engine.
|
||||
- `instructions`: The runtime instructions called by compiled code.
|
||||
- `interfaces`: `LView`, `TView`, `TNode` definitions.
|
||||
- `src/di`: Dependency injection system.
|
||||
- `src/change_detection`: Change detection logic.
|
||||
- `src/zone`: Zone.js integration.
|
||||
- `src/signal`: Signals implementation (if present in this version, otherwise likely in `primitives`).
|
||||
|
||||
## 6. Conventions & Gotchas
|
||||
|
||||
- **Prefixes**: Private/Internal exports often start with `ɵ`.
|
||||
- **Global State**: Ivy relies heavily on global state (e.g., `getLView()`) during instruction execution to avoid passing context arguments everywhere. This is for performance and code size.
|
||||
- **Performance**: The code is highly optimized for performance and memory. You will see arrays used instead of objects, bitmasks, and manual memory management patterns. **Respect these patterns.**
|
||||
|
||||
## 7. How to Modify Core
|
||||
|
||||
1. **Understand the Instruction**: If modifying runtime behavior, find the corresponding instruction in `src/render3/instructions`.
|
||||
2. **Check `LView`/`TView` Impact**: If adding state, understand where it fits in the `LView` array.
|
||||
3. **Tests**: Core has extensive tests. Run them using Bazel.
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
name: reference-signal-forms
|
||||
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
|
||||
---
|
||||
|
||||
# Signal Forms Architecture
|
||||
|
||||
The `packages/forms/signals` directory contains an experimental, signal-based forms API for Angular.
|
||||
This system differs significantly from the existing Reactive and Template-driven forms.
|
||||
|
||||
## Mental Model
|
||||
|
||||
1. **Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
|
||||
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
|
||||
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).
|
||||
|
||||
2. **Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
|
||||
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
|
||||
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.
|
||||
|
||||
3. **Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
|
||||
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
|
||||
This separates the _structure_ of the data from the _rules_ governing it.
|
||||
|
||||
4. **Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
|
||||
It handles:
|
||||
- Syncing the value between the DOM and the Signal.
|
||||
- Reflecting state (valid, touched, etc.) to the UI.
|
||||
- Handling user interaction events (blur, input).
|
||||
|
||||
## Key Components
|
||||
|
||||
### 1. `FieldNode` (`src/field/node.ts`)
|
||||
|
||||
The central internal class representing a single field in the form graph. It aggregates several state managers:
|
||||
|
||||
- `structure`: Manages parent/child relationships and signal slicing.
|
||||
- `validationState`: Computes `valid`, `invalid`, `errors` signals.
|
||||
- `nodeState`: Tracks `touched`, `dirty`, `pristine`.
|
||||
- `metadataState`: Stores metadata like `min`, `max`, `required`.
|
||||
- `submitState`: Tracks submission status and server errors.
|
||||
|
||||
### 2. `ValidationState` (`src/field/validation.ts`)
|
||||
|
||||
Manages the complexity of validation:
|
||||
|
||||
- **Synchronous Errors**: Derived from schema rules.
|
||||
- **Asynchronous Errors**: Handled via signals, including 'pending' states.
|
||||
- **Tree Errors**: Errors that bubble up or are targeted at specific fields.
|
||||
- **Submission Errors**: Server-side errors injected imperatively via `submit()`.
|
||||
|
||||
### 3. `FormField` Directive (`src/directive/form_field_directive.ts`)
|
||||
|
||||
The bridge between the `FieldNode` and the DOM.
|
||||
|
||||
- Selector: `[formField]`
|
||||
- It supports:
|
||||
- **Native Elements**: `<input>`, `<select>`, `<textarea>`.
|
||||
- **Custom Controls**: Components implementing `FormUiControl` or `FormValueControl`.
|
||||
- **Legacy Interop**: Components implementing `ControlValueAccessor` (via `InteropNgControl`).
|
||||
|
||||
### 4. `Schema` (`src/api/structure.ts` & `src/api/rules`)
|
||||
|
||||
Defines the behavior.
|
||||
|
||||
- Created via `schema(fn)`.
|
||||
- Applied via `apply(path, schema)`.
|
||||
- Rules include validators (`required`, `pattern`, `min`, `max`) and state modifiers (`disabled`, `hidden`).
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. **Read**: `form.field.value()` reads directly from the underlying signal (projected to the specific path).
|
||||
2. **Write**: Writing to the form (e.g., via UI) updates the underlying signal.
|
||||
3. **Validation**: A computed effect observes the value signal and runs validators defined in the schema.
|
||||
|
||||
## Usage Example (Conceptual)
|
||||
|
||||
```typescript
|
||||
// 1. Define Model
|
||||
const user = signal({name: '', age: 0});
|
||||
|
||||
// 2. Define Schema
|
||||
const userRules = schema((u) => {
|
||||
required(u.name);
|
||||
min(u.age, 18);
|
||||
});
|
||||
|
||||
// 3. Create Form
|
||||
const userForm = form(user, userRules); // OR apply(userForm, userRules)
|
||||
|
||||
// 4. Bind in Template
|
||||
// <input [formField]="userForm.name">
|
||||
```
|
||||
|
||||
## Important Files
|
||||
|
||||
- `packages/forms/signals/src/api/structure.ts`: Public API entry points (`form`, `apply`).
|
||||
- `packages/forms/signals/src/api/control.ts`: Interfaces for custom controls (`FormUiControl`).
|
||||
- `packages/forms/signals/src/field/node.ts`: The `FieldNode` implementation.
|
||||
- `packages/forms/signals/src/directive/form_field_directive.ts`: The `[formField]` directive.
|
||||
|
||||
## Supplemental Information
|
||||
|
||||
- [Compiler & Core Integration](references/integration.md): Details how `[formField]` hooks into type-checking and the runtime.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Signal Forms Integration: Compiler & Core
|
||||
|
||||
This document explains how the Signal Forms system hooks into the Angular compiler and runtime to provide seamless type-checking and efficient updates.
|
||||
|
||||
## 1. Compiler-CLI Integration (Type Checking)
|
||||
|
||||
The `packages/compiler-cli` package contains specific logic to support `[formField]`. This is primarily handled in `src/ngtsc/typecheck/src/ops/signal_forms.ts`.
|
||||
|
||||
### Key Mechanisms:
|
||||
|
||||
- **Detection**: The compiler identifies a directive as a "Field Directive" if it has the `ɵNgFieldDirective` property or comes from `@angular/forms/signals`.
|
||||
- **Synthetic Binding Expansion**: When you write `<input [formField]="mySignal" />`, the type checker doesn't just check `formField`. It synthetically expands this into a set of bindings for validation:
|
||||
- `[value]="mySignal()"` (or `checked` for checkboxes)
|
||||
- `[disabled]="mySignal.disabled()"`
|
||||
- `[required]="mySignal.required()"`
|
||||
- ...and so on.
|
||||
- This ensures that `mySignal` (the `FieldNode`) has all the necessary properties to drive the form control.
|
||||
- **Conflict Detection**: It actively prevents "double binding". If you bind `[formField]`, you are _banned_ from also binding `[value]`, `[disabled]`, `[required]`, etc., as the signal form should be the single source of truth.
|
||||
- **Element Type Validation**:
|
||||
- **Native Elements**: Checks that the signal's value type matches the element type (e.g., `<input type="checkbox">` requires a `boolean` signal).
|
||||
- **Custom Controls**: Detects if a custom component is a "Form Value Control" (has a `value` input/output) or "Form Checkbox Control" (has a `checked` input/output) and validates against that.
|
||||
|
||||
### Relevant Files:
|
||||
|
||||
- `packages/compiler-cli/src/ngtsc/typecheck/src/ops/signal_forms.ts`: The core logic for `TcbNativeFieldOp` and `SignalFormFieldOp`.
|
||||
|
||||
## 2. Core Runtime Integration
|
||||
|
||||
The `packages/core` package provides the low-level instructions that power the `FormField` directive. This allows it to do things normal directives cannot, like efficiently syncing state without change detection overhead for every property.
|
||||
|
||||
### Key Mechanisms:
|
||||
|
||||
- **`ɵngControlCreate` Hook**: The `FormField` directive defines a special method `ɵngControlCreate`.
|
||||
- **`ɵɵcontrol` Instructions**: When the compiler sees `ɵngControlCreate`, it emits:
|
||||
- `ɵɵcontrolCreate`: Called during the creation phase.
|
||||
- `ɵɵcontrol`: Called during the update phase.
|
||||
- **`ControlDirectiveHost`**: These instructions provide the directive with a `ControlDirectiveHost`. This is a privileged interface that allows the `FormField` directive to:
|
||||
- **Access the Element**: Get direct access to the native element or component instance.
|
||||
- **Set Inputs**: Write directly to inputs of _other directives_ on the same node (e.g., setting the `value` input of a custom control).
|
||||
- **Listen to Outputs**: Subscribe to outputs of other directives (e.g., `valueChange`).
|
||||
- **Bypass Templates**: It effectively acts as a "meta-directive" that manages the bindings for you, bypassing the need for explicit template syntax for every property.
|
||||
|
||||
### Relevant Files:
|
||||
|
||||
- `packages/core/src/render3/instructions/control.ts`: Implementation of `ɵɵcontrol` instructions.
|
||||
- `packages/forms/signals/src/directive/form_field_directive.ts`: The directive that implements the hook.
|
||||
@@ -0,0 +1,48 @@
|
||||
name: 'VSCode Angular Language Service extension'
|
||||
description: Report an issue or suggest a feature for the VSCode Angular Language Service extension
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: bug-report-or-feature-request
|
||||
attributes:
|
||||
label: Is this a bug report or a feature request?
|
||||
description: Select one.
|
||||
options:
|
||||
- label: Bug Report
|
||||
- label: Feature Request
|
||||
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Please provide the steps to reproduce the issue [Bug Report only]
|
||||
|
||||
- type: textarea
|
||||
id: expected-vs-actual-behavior
|
||||
attributes:
|
||||
label: Please provide the expected behavior vs the actual behavior you encountered [Bug Report only]
|
||||
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: Please provide a screenshot if possible [Bug Report only]
|
||||
|
||||
- type: textarea
|
||||
id: exception-or-error
|
||||
attributes:
|
||||
label: Please provide the exception or error you saw [Bug Report only]
|
||||
render: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description [Feature Request only]
|
||||
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: Proposed solution [Feature Request only]
|
||||
|
||||
- type: textarea
|
||||
id: alternatives-considered
|
||||
attributes:
|
||||
label: Alternatives considered [Feature Request only]
|
||||
@@ -1,33 +1,53 @@
|
||||
import {Deployment} from './deployments.mjs';
|
||||
import {join} from 'path';
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
|
||||
export async function generateSitemap(deployment: Deployment, distDir: string) {
|
||||
const servingUrlWithoutEndingSlash = deployment.servingUrl.endsWith('/')
|
||||
? deployment.servingUrl.slice(0, -1)
|
||||
: deployment.servingUrl;
|
||||
import {join} from 'node:path';
|
||||
import {readFile, writeFile} from 'node:fs/promises';
|
||||
|
||||
export async function generateSitemap(deployment: Deployment, distDir: string): Promise<void> {
|
||||
/** Timestamp string used to of the last file update. */
|
||||
const lastModifiedTimestamp = new Date().toISOString();
|
||||
/** An object containing all of the routes available within the application. */
|
||||
const routes = JSON.parse(readFileSync(join(distDir, 'prerendered-routes.json'), 'utf-8'));
|
||||
const {routes} = JSON.parse(await readFile(join(distDir, 'prerendered-routes.json'), 'utf-8'));
|
||||
const routePaths = Object.keys(routes);
|
||||
|
||||
/** The generated sitemap string. */
|
||||
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${Object.keys(routes.routes)
|
||||
.map((route) => {
|
||||
const routeWithoutLeadingSlash = route.startsWith('/') ? route.slice(1) : route;
|
||||
return `
|
||||
<url>
|
||||
<loc>${servingUrlWithoutEndingSlash}/${routeWithoutLeadingSlash}</loc>
|
||||
${routePaths
|
||||
.map(
|
||||
(route) => `<url>
|
||||
<loc>${joinUrlParts(deployment.servingUrl, route)}</loc>
|
||||
<lastmod>${lastModifiedTimestamp}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
`;
|
||||
})
|
||||
</url>`,
|
||||
)
|
||||
.join('')}
|
||||
</urlset>`;
|
||||
writeFileSync(join(distDir, 'browser', 'sitemap.xml'), sitemap, 'utf-8');
|
||||
console.log(`Generated sitemap with ${Object.keys(routes.routes).length} entries.`);
|
||||
|
||||
await writeFile(join(distDir, 'browser', 'sitemap.xml'), sitemap, 'utf-8');
|
||||
|
||||
console.log(`Generated sitemap with ${routePaths.length} entries.`);
|
||||
}
|
||||
|
||||
function joinUrlParts(...parts: string[]): string {
|
||||
const normalizeParts: string[] = [];
|
||||
for (const part of parts) {
|
||||
if (part === '') {
|
||||
// Skip any empty parts
|
||||
continue;
|
||||
}
|
||||
|
||||
let normalizedPart = part;
|
||||
if (part[0] === '/') {
|
||||
normalizedPart = normalizedPart.slice(1);
|
||||
}
|
||||
if (part.at(-1) === '/') {
|
||||
normalizedPart = normalizedPart.slice(0, -1);
|
||||
}
|
||||
if (normalizedPart !== '') {
|
||||
normalizeParts.push(normalizedPart);
|
||||
}
|
||||
}
|
||||
|
||||
return normalizeParts.join('/');
|
||||
}
|
||||
|
||||
+20227
-22773
File diff suppressed because one or more lines are too long
@@ -5,9 +5,9 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/saucelabs@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Starting Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
|
||||
@@ -21,17 +21,17 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Build adev
|
||||
# `snapshot-build` config is used to stamp the exact version with sha in the footer.
|
||||
run: pnpm bazel build //adev:build.production --config=snapshot-build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -14,9 +14,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.repository.fork == false
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
|
||||
id: comment-branch
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# Specify repository as the PR branch might be from a fork.
|
||||
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
+29
-27
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check code lint
|
||||
@@ -32,6 +32,8 @@ jobs:
|
||||
run: pnpm ng-dev pullapprove verify
|
||||
- name: Validate angular robot configuration
|
||||
run: pnpm ng-dev ngbot verify
|
||||
- name: Validate agent skills
|
||||
run: pnpm ng-dev ai skills validate
|
||||
- name: Confirm code builds with typescript as expected
|
||||
run: pnpm check-tooling-setup
|
||||
|
||||
@@ -39,13 +41,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
disable-package-manager-cache: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -55,7 +57,7 @@ jobs:
|
||||
- name: Test build
|
||||
run: pnpm devtools:build:chrome
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@2ad32e649e4db26c07674ebae31a297601dbcbaf # v6.10.8
|
||||
uses: cypress-io/github-action@bc22e01685c56e89e7813fd8e26f33dc47f87e15 # v7.1.5
|
||||
with:
|
||||
command: pnpm devtools:test:e2e
|
||||
start: pnpm bazel run //devtools/src:devserver
|
||||
@@ -67,11 +69,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -83,11 +85,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -100,11 +102,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -119,11 +121,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -136,11 +138,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -152,11 +154,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
|
||||
- name: Install node modules
|
||||
@@ -206,11 +208,11 @@ jobs:
|
||||
runs-on: ubuntu-latest-8core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Build adev
|
||||
@@ -224,6 +226,6 @@ jobs:
|
||||
configPath: 'adev/firebase.json'
|
||||
distDir: 'dist/bin/adev/dist'
|
||||
- name: Update Algolia synonym record
|
||||
run: pnpm tsx adev/scripts/synonyms/update-synonyms.mts
|
||||
run: node adev/scripts/synonyms/update-synonyms.mts
|
||||
env:
|
||||
ALGOLIA_KEY: ${{ secrets.ALGOLIA_SYNONYM_MANAGER }}
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# Setting `persist-credentials: false` prevents the github-action account from being the
|
||||
# account that is attempted to be used for authentication, instead the remote is set to
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
ANGULAR_READONLY_GITHUB_TOKEN: ${{ secrets.READONLY_GITHUB_TOKEN }}
|
||||
|
||||
- name: Create a PR (if necessary)
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
token: ${{ secrets.ANGULAR_ROBOT_ACCESS_TOKEN }}
|
||||
push-to-fork: 'angular-robot/angular'
|
||||
|
||||
@@ -3,23 +3,36 @@ name: DevInfra
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
labels:
|
||||
pull_request_labels:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: angular/dev-infra/github-actions/pull-request-labeling@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: angular/dev-infra/github-actions/labeling/pull-request@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
labels: '{"requires: TGP": ["packages/core/primitives/**/{*,.*}"]}'
|
||||
post_approval_changes:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
issue_labels:
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/labeling/issue@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
google-generative-ai-key: ${{ secrets.GOOGLE_GENERATIVE_AI_KEY }}
|
||||
|
||||
@@ -13,8 +13,8 @@ jobs:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -13,15 +13,15 @@ jobs:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/saucelabs@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: pnpm bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
workflows: ${{ steps.workflows.outputs.workflows }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- id: workflows
|
||||
@@ -36,9 +36,9 @@ jobs:
|
||||
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
|
||||
|
||||
+23
-21
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check code lint
|
||||
@@ -32,12 +32,14 @@ jobs:
|
||||
run: pnpm ng-dev ngbot verify
|
||||
- name: Confirm code builds with typescript as expected
|
||||
run: pnpm check-tooling-setup
|
||||
- name: Validate agent skills
|
||||
run: pnpm ng-dev ai skills validate
|
||||
- name: Check commit message
|
||||
run: pnpm ng-dev commit-message validate-range ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
|
||||
- name: Check code format
|
||||
run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
|
||||
- name: Check Package Licenses
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
|
||||
|
||||
@@ -45,13 +47,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
with:
|
||||
disable-package-manager-cache: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -59,7 +61,7 @@ jobs:
|
||||
- name: Test build
|
||||
run: pnpm devtools:build:chrome
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@2ad32e649e4db26c07674ebae31a297601dbcbaf # v6.10.8
|
||||
uses: cypress-io/github-action@bc22e01685c56e89e7813fd8e26f33dc47f87e15 # v7.1.5
|
||||
with:
|
||||
command: pnpm devtools:test:e2e
|
||||
start: pnpm bazel run //devtools/src:devserver
|
||||
@@ -71,11 +73,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run CI tests for framework
|
||||
@@ -95,11 +97,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run integration CI tests for framework
|
||||
@@ -110,11 +112,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run tests
|
||||
@@ -127,11 +129,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Run tests
|
||||
@@ -142,11 +144,11 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@2ff164a0ca60e692f3d7e1a982bde9bf3379365e
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e4dcda13e469f50a6bd92667e2ded8b98173bf2c
|
||||
- name: Install node modules
|
||||
run: pnpm install --frozen-lockfile
|
||||
- run: |
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -54,3 +54,6 @@ baseline.json
|
||||
|
||||
# Ignore cache created with the Angular CLI.
|
||||
.angular/
|
||||
|
||||
# pnpm store
|
||||
.pnpm-store
|
||||
|
||||
@@ -9,4 +9,5 @@ export const github = {
|
||||
name: 'angular',
|
||||
mainBranchName: 'main',
|
||||
mergeMode: 'caretaker-only',
|
||||
requireReleaseModeForRelease: false,
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"packages/docs/**",
|
||||
"packages/elements/schematics/**",
|
||||
"packages/examples/**",
|
||||
"packages/forms/signals/src/api/rules/validation/standard_schema.ts",
|
||||
"packages/localize/**",
|
||||
"packages/private/**",
|
||||
"packages/service-worker/**",
|
||||
|
||||
+7
-1
@@ -30,10 +30,16 @@ vscode-ng-language-service/syntaxes/test/data/*.html
|
||||
# Ignore goldens MD files
|
||||
goldens/**/*.api.md
|
||||
|
||||
# Ignore golden symbol json files
|
||||
packages/**/*.golden_symbols.json
|
||||
|
||||
# adev generated files
|
||||
adev/src/content/aria/**/*.json
|
||||
adev/src/content/cli/**/*.json
|
||||
adev/src/content/cdk/**/*.json
|
||||
|
||||
# Antigravity rules
|
||||
.agent/rules/agents.md
|
||||
|
||||
CHANGELOG.md
|
||||
CHANGELOG_ARCHIVE.md
|
||||
CHANGELOG_ARCHIVE.md
|
||||
|
||||
+28
-23
@@ -106,7 +106,6 @@ groups:
|
||||
- thePunderWoman
|
||||
- kirjs
|
||||
- JoostK
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
@@ -151,10 +150,8 @@ groups:
|
||||
- crisbeto
|
||||
- devversion
|
||||
- kirjs
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- JeanMeche
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
@@ -181,9 +178,9 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- ~alxhub
|
||||
- jelbourn
|
||||
- josephperrott
|
||||
- ~pkozlowski-opensource
|
||||
- alan-agius4
|
||||
reviews:
|
||||
request: -1 # request reviews from everyone
|
||||
required: 2 # require at least 2 approvals
|
||||
@@ -202,7 +199,6 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- ~JiaLiPassion
|
||||
- ~jelbourn
|
||||
- ~alxhub
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
@@ -211,7 +207,6 @@ groups:
|
||||
- kirjs
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
@@ -248,6 +243,8 @@ groups:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'adev/**/{*,.*}',
|
||||
'tools/manual_api_docs/blocks/*.md',
|
||||
'tools/manual_api_docs/elements/*.md',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
@@ -259,14 +256,12 @@ groups:
|
||||
- crisbeto
|
||||
- kirjs
|
||||
- JeanMeche
|
||||
- jelbourn
|
||||
- thePunderWoman
|
||||
- devversion
|
||||
- josephperrott
|
||||
- ~pkozlowski-opensource
|
||||
- ~mgechev
|
||||
- MarkTechson
|
||||
- mmalerba
|
||||
- ~hawkgs
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
@@ -302,8 +297,13 @@ groups:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files.exclude('.pullapprove.yml'), [
|
||||
contains_any_globs(files
|
||||
.exclude('.pullapprove.yml')
|
||||
.exclude('tools/manual_api_docs/blocks/*.md')
|
||||
.exclude('tools/manual_api_docs/elements/*.md'),
|
||||
[
|
||||
'{*,.*}',
|
||||
'.agent/**/{*,.*}',
|
||||
'.devcontainer/**/{*,.*}',
|
||||
'.github/**/{*,.*}',
|
||||
'.husky/**/{*,.*}',
|
||||
@@ -340,6 +340,7 @@ groups:
|
||||
- author not in ["angular-robot"]
|
||||
reviewers:
|
||||
users:
|
||||
- alan-agius4
|
||||
- devversion
|
||||
- josephperrott
|
||||
|
||||
@@ -374,11 +375,9 @@ groups:
|
||||
- AndrewKushnir
|
||||
- ~alxhub
|
||||
- atscott
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- kirjs
|
||||
- mmalerba
|
||||
- crisbeto
|
||||
- devversion
|
||||
- JeanMeche
|
||||
@@ -412,10 +411,8 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- kirjs
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- ~pkozlowski-opensource
|
||||
- mmalerba
|
||||
- ~amishne
|
||||
- ~leonsenft
|
||||
- ~mattrbeck
|
||||
@@ -424,6 +421,24 @@ groups:
|
||||
required: 1 # Require that 1 person approve
|
||||
reviewed_for: required
|
||||
|
||||
# =========================================================
|
||||
# Agent Skills
|
||||
# =========================================================
|
||||
agent-skills:
|
||||
<<: *defaults
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'skills/{*,.*}',
|
||||
'skills/**/{*,.*}',
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- marktechson
|
||||
- kirjs
|
||||
- ~JeanMeche
|
||||
- ~dgp1130
|
||||
|
||||
####################################################################################
|
||||
# Special Cases
|
||||
####################################################################################
|
||||
@@ -444,7 +459,6 @@ groups:
|
||||
- AndrewKushnir
|
||||
- andrewseguin
|
||||
- dgp1130
|
||||
- ~jelbourn
|
||||
- thePunderWoman
|
||||
- josephperrott
|
||||
|
||||
@@ -467,10 +481,6 @@ groups:
|
||||
- thePunderWoman # Jessica Janiuk
|
||||
- AndrewKushnir # Andrew Kushnir
|
||||
- atscott # Andrew Scott
|
||||
labels:
|
||||
pending: 'requires: TGP'
|
||||
approved: 'requires: TGP'
|
||||
rejected: 'requires: TGP'
|
||||
|
||||
# External team required reviews
|
||||
primitives-shared:
|
||||
@@ -488,10 +498,6 @@ groups:
|
||||
- tbondwilkinson # Tom Wilkinson
|
||||
- rahatarmanahmed # Rahat Ahmed
|
||||
- ENAML # Ethan Cline
|
||||
labels:
|
||||
pending: 'requires: TGP'
|
||||
approved: 'requires: TGP'
|
||||
rejected: 'requires: TGP'
|
||||
|
||||
####################################################################################
|
||||
# Override managed result groups
|
||||
@@ -514,7 +520,6 @@ groups:
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- jelbourn
|
||||
- josephperrott
|
||||
reviews:
|
||||
request: 0
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
trigger: always_on
|
||||
---
|
||||
|
||||
This is the source code for the Angular framework. This guide outlines standard practices for AI agents working in this repository.
|
||||
|
||||
## Environment
|
||||
|
||||
- Use `pnpm` for package management.
|
||||
- Use `pnpm bazel test //target` to run tests.
|
||||
|
||||
## Key Documentation
|
||||
|
||||
- [Building and Testing](contributing-docs/building-and-testing-angular.md): definitive guide for running targets.
|
||||
- [Coding Standards](contributing-docs/coding-standards.md): style guide for TypeScript and other files.
|
||||
- [Commit Guidelines](contributing-docs/commit-message-guidelines.md): format for commit messages and PR titles.
|
||||
|
||||
## Testing
|
||||
|
||||
- **Zoneless & Async-First:** Assume a zoneless environment where state changes schedule updates asynchronously.
|
||||
- **Do NOT** use `fixture.detectChanges()` to manually trigger updates.
|
||||
- **ALWAYS** use the "Act, Wait, Assert" pattern:
|
||||
1. **Act:** Update state or perform an action.
|
||||
2. **Wait:** `await fixture.whenStable()` to allow the framework to process the scheduled update.
|
||||
3. **Assert:** Verify the output.
|
||||
- To keep tests fast, minimize the need for waiting:
|
||||
- Use `useAutoTick()` (from `packages/private/testing/src/utils.ts`) to fast-forward time via the mock clock.
|
||||
- When waiting is necessary, use real async tests (`it('...', async () => { ... })`) along with:
|
||||
- `await timeout(ms)` (from `packages/private/testing/src/utils.ts`) to wait a specific number of milliseconds.
|
||||
- `await fixture.whenStable()` to wait for framework stability.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- Use the `gh` CLI (GitHub CLI) for creating and managing pull requests.
|
||||
+272
-173
@@ -1,3 +1,275 @@
|
||||
<a name="21.2.3"></a>
|
||||
# 21.2.3 (2026-03-11)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [62a97f7e4b](https://github.com/angular/angular/commit/62a97f7e4b896b4b03a1ef25764db387ffecebe1) | fix | ensure definitions compile |
|
||||
| [21b1c3b2ee](https://github.com/angular/angular/commit/21b1c3b2ee2c8423782b111b93bd60eb6b453259) | fix | include signal debug names in their `toString()` representation |
|
||||
| [224e60ecb1](https://github.com/angular/angular/commit/224e60ecb1b90115baa702f1c06edc1d64d86187) | fix | sanitize translated attribute bindings with interpolations |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.2.2"></a>
|
||||
# 21.2.2 (2026-03-09)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1df1697c6e](https://github.com/angular/angular/commit/1df1697c6e3a6b1d302f7692b495146943faa12f) | fix | prevent mutation of children array in RecursiveVisitor |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c822bf8e76](https://github.com/angular/angular/commit/c822bf8e76611afde332b6625f5e7bae2fe9c3f3) | fix | always parenthesize object literals in TCB |
|
||||
| [05d022d5e6](https://github.com/angular/angular/commit/05d022d5e61cca7ac90d5b2b2ba3fc738b364ad9) | fix | ignore generated ngDevMode signal branch for code coverage |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [670d1660c4](https://github.com/angular/angular/commit/670d1660c40504e3f55e094c3ebbcccad14163f3) | feat | add 'blur' option to debounce rule |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.2.1"></a>
|
||||
# 21.2.1 (2026-03-04)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e2e9a9a531](https://github.com/angular/angular/commit/e2e9a9a531c9e9a69701e549f28354cc5d5edd77) | fix | adds transfer cache to httpResource to fix hydration |
|
||||
| [b4ec3cc4e4](https://github.com/angular/angular/commit/b4ec3cc4e41f2948ad0830eb14aa05d14fa3a9ed) | fix | prevent child animation elements from being orphaned |
|
||||
| [e923d88398](https://github.com/angular/angular/commit/e923d8839868c79989502ab3503e13d93c78516a) | fix | Prevent removal of elements during drag and drop |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [277ade97ac](https://github.com/angular/angular/commit/277ade97ac2a3a7f2a5b513acaa93e7663cdc55f) | fix | correctly cache blob responses in transfer cache ([#67002](https://github.com/angular/angular/pull/67002)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.2.0"></a>
|
||||
# 21.2.0 (2026-02-25)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [18003a33bb](https://github.com/angular/angular/commit/18003a33bb0d6bb09def8a0e5939fa24069696eb) | feat | add an 'outlet' injector option for ngTemplateOutlet |
|
||||
| [8bbe6dc46c](https://github.com/angular/angular/commit/8bbe6dc46c9dc13bafa81a60c7613b84b5ca3761) | feat | Add Location strategies to manage trailing slash on write |
|
||||
| [51cc914807](https://github.com/angular/angular/commit/51cc91480761b7275c15b5600381207f8ca00ee5) | feat | support height in ImageLoaderConfig and built-in loaders |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [72534e2a34](https://github.com/angular/angular/commit/72534e2a3458df4e1bb097973872f00bbb92be42) | feat | Add support for the `instanceof` binary operator |
|
||||
| [95b3f37d4a](https://github.com/angular/angular/commit/95b3f37d4a7d9a38f616d56df746dfcda3c2139b) | feat | Exhaustive checks for switch blocks |
|
||||
| [04ba09a8d9](https://github.com/angular/angular/commit/04ba09a8d9454013bebdd643eacb737642161952) | feat | support `AstVisitor.visitEmptyExpr()` |
|
||||
| [ce80136e7b](https://github.com/angular/angular/commit/ce80136e7b9f0024d49fce835cffa024c4505855) | fix | optimize away unnecessary restore/reset view calls |
|
||||
| [3242a61bae](https://github.com/angular/angular/commit/3242a61bae02253d13abb510b666376c665e61ac) | fix | variable counter visiting some expressions twice |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [473dd3e1cb](https://github.com/angular/angular/commit/473dd3e1cbd4fe3fa88ae4d5358eee35c11acb1b) | fix | attach source spans to object literal keys in TCB |
|
||||
| [a904d9f77b](https://github.com/angular/angular/commit/a904d9f77b56feab407f75f8d0527fa512d5dafb) | fix | support nested component declaration |
|
||||
| [2ea6dfc6c9](https://github.com/angular/angular/commit/2ea6dfc6c9ca11e96a2654510c980419899f8d04) | fix | update diagnostic to flag no-op arrow functions in listeners |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8d5210c9fe](https://github.com/angular/angular/commit/8d5210c9fedd8abdd810d7a89ec7ee9a1234f5c1) | feat | add ChangeDetectionStrategy.Eager alias for Default |
|
||||
| [92d2498910](https://github.com/angular/angular/commit/92d2498910caed06c182b67e39726e1441418698) | feat | add host node to DeferBlockData ([#66546](https://github.com/angular/angular/pull/66546)) |
|
||||
| [ea2016a6dc](https://github.com/angular/angular/commit/ea2016a6dce58f95ecab7c773d5dcde274354e1a) | feat | add support for nested animations |
|
||||
| [81cabc1477](https://github.com/angular/angular/commit/81cabc14777a3b4966c29d60e1505aca8c29b71c) | feat | add support for TypeScript 6 |
|
||||
| [1ba9b7ac50](https://github.com/angular/angular/commit/1ba9b7ac5001b315cc9df78c518964dbf479d647) | feat | resource composition via snapshots |
|
||||
| [d9923b72a2](https://github.com/angular/angular/commit/d9923b72a20972ba6bf728d78f1afac6936ade18) | feat | support arrow functions in expressions |
|
||||
| [a7e8abbb7e](https://github.com/angular/angular/commit/a7e8abbb7e738ba338c3f50c76934c99925954e5) | fix | correctly handle SkipSelf when resolving from embedded view injector |
|
||||
| [0806ee3826](https://github.com/angular/angular/commit/0806ee38269b664f535e10d4d501b88370d3b44c) | fix | prevent animated element duplication with dynamic components in zoneless mode |
|
||||
| [ed78fa05c7](https://github.com/angular/angular/commit/ed78fa05c710ebafb355ae00a85b190a118b6cc4) | fix | Remove note to skip arrow functions in best practices |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f56bb07d83](https://github.com/angular/angular/commit/f56bb07d83a015b0ac12e74fdb0cf1550ff36b97) | feat | add field param to submit action and onInvalid |
|
||||
| [ba009b6031](https://github.com/angular/angular/commit/ba009b603119299a03f9d844f93882d42d47d150) | feat | add form directive |
|
||||
| [22afbb2f36](https://github.com/angular/angular/commit/22afbb2f36be89c2ae575df343571a918dec5985) | feat | add parsing support to native inputs ([#66917](https://github.com/angular/angular/pull/66917)) |
|
||||
| [95c386469c](https://github.com/angular/angular/commit/95c386469c7a2f09dd731601c2061bdb10d25717) | feat | Add passing focus options to form field |
|
||||
| [95ecce8334](https://github.com/angular/angular/commit/95ecce8334299defe55fb2b74264e5258ffd137c) | feat | allow setting submit options at form-level |
|
||||
| [ebae211add](https://github.com/angular/angular/commit/ebae211add37700858adeb8fc5d87bf503a59721) | feat | introduce parse errors in signal forms |
|
||||
| [3937afc316](https://github.com/angular/angular/commit/3937afc3167ce409eebb06d91d5fb122eea4e33d) | feat | introduce SignalFormControl for Reactive Forms compatibility |
|
||||
| [30f0914754](https://github.com/angular/angular/commit/30f09147545b67185f93efb9796e37c1db76733a) | feat | support binding null to number input ([#66917](https://github.com/angular/angular/pull/66917)) |
|
||||
| [dd208ca259](https://github.com/angular/angular/commit/dd208ca2595258fcd1e289374f812ce0b56c7011) | feat | update submit function to accept options object |
|
||||
| [27397b3f4f](https://github.com/angular/angular/commit/27397b3f4f3182ce00d6e2f8690285c316e2a274) | fix | clear parse errors when model updates ([#66917](https://github.com/angular/angular/pull/66917)) |
|
||||
| [63d8005703](https://github.com/angular/angular/commit/63d80057039928b3e878b59c1fe6b93ef1c6b701) | fix | preserve custom-control focus context in signal forms |
|
||||
| [631f60d1f9](https://github.com/angular/angular/commit/631f60d1f9be72cb68330308a6ff18cc195babb8) | fix | preserve parse errors when parse returns value |
|
||||
| [adfb83146b](https://github.com/angular/angular/commit/adfb83146b0c149734f43961563b389e00cc1d85) | fix | simplify design of parse errors |
|
||||
| [fb05fc86d0](https://github.com/angular/angular/commit/fb05fc86d0f12ffafd94c7c1420118d8a79f7e59) | fix | sort error summary by DOM order |
|
||||
| [567f292e8e](https://github.com/angular/angular/commit/567f292e8e0f9d2b5ddebadfa1c6d6dd6c456f39) | fix | support custom controls as host directives |
|
||||
| [bdfb60f3e3](https://github.com/angular/angular/commit/bdfb60f3e33065e047183dc1890c36e527e2b304) | fix | use consistent error format returned from parse |
|
||||
| [d75046bc09](https://github.com/angular/angular/commit/d75046bc091699bbadcb5f2032be627e983ee6fa) | fix | warn when showing hidden field state |
|
||||
### language-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ebc90c26f5](https://github.com/angular/angular/commit/ebc90c26f5ff1ba1e0ca9b775a44e301ebfb9473) | feat | Add completions and hover info for inline styles |
|
||||
| [26fd0839c3](https://github.com/angular/angular/commit/26fd0839c32d2ebeaa5e3ecc10ed70ab9ca17749) | feat | Add folding range support for inline styles |
|
||||
| [573aadef7e](https://github.com/angular/angular/commit/573aadef7eb8b6b5e83b82a16f95d2a556f27c01) | feat | Add quick info for inline styles |
|
||||
| [6fb39d9b62](https://github.com/angular/angular/commit/6fb39d9b62cbb634e95ec00fe5ef85d84da3bdbd) | feat | Support client-side file watching via `onDidChangeWatchedFiles` |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [496967e7b1](https://github.com/angular/angular/commit/496967e7b13dfe1ebdde69724cd62880914beb60) | feat | add JSON schema for angularCompilerOptions |
|
||||
| [8c21866f49](https://github.com/angular/angular/commit/8c21866f49ff74344551395ae0a5df1841d54c0d) | feat | add linked editing ranges for HTML tag synchronization |
|
||||
| [d2137928e8](https://github.com/angular/angular/commit/d2137928e8f075527016a3c011dd8efc4d4e1ebd) | perf | use lightweight project warmup for Angular analysis |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b51bab583d](https://github.com/angular/angular/commit/b51bab583d84e38f16dea489e4119edc34e2a491) | feat | Add partial ActivatedRouteSnapshot information to `canMatch` params |
|
||||
| [cf9620f7d0](https://github.com/angular/angular/commit/cf9620f7d072897f13b7f281b7bca6f51f69cfd0) | feat | Make match options optional in isActive |
|
||||
| [907a94dcec](https://github.com/angular/angular/commit/907a94dcec2926a5c7d0c4d36249bd62e31a2ae3) | feat | Update `IsActiveMatchOptions` APIs to accept a Partial |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.5"></a>
|
||||
# 21.1.5 (2026-02-18)
|
||||
No user facing changes in this release
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.4"></a>
|
||||
# 21.1.4 (2026-02-11)
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [caab23dfe6](https://github.com/angular/angular/commit/caab23dfe6acf06c3b859af091f5e078b08f1c4c) | fix | add geolocation element to schema |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2b99eaa019](https://github.com/angular/angular/commit/2b99eaa019b5551a2e2fcf9ff8cd0a796e1e857b) | fix | capture animation dependencies eagerly to avoid destroyed injector |
|
||||
| [d6aeac504c](https://github.com/angular/angular/commit/d6aeac504c6181f15e5d8afdca3d9c3e3b32652c) | fix | Fix flakey test due to document injection |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0d1acd0165](https://github.com/angular/angular/commit/0d1acd0165511b57ce853f29486d9b92d0215959) | feat | support signal-based schemas in validateStandardSchema |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3905015ccc](https://github.com/angular/angular/commit/3905015ccc53399a606dd8e4f3c4d0cce628a08e) | fix | correctly parse ArrayBuffer and Blob in transfer cache |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.3"></a>
|
||||
# 21.1.3 (2026-02-04)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2b254bc050](https://github.com/angular/angular/commit/2b254bc0508b73aab8991c3b1a9a703c339cb735) | fix | `linkedSignal.update` should propagate errors |
|
||||
| [e5110b4fa1](https://github.com/angular/angular/commit/e5110b4fa155e4669ed507f3460d2d29026a28ab) | fix | export DirectiveWithBindings |
|
||||
| [2cf4da0ea1](https://github.com/angular/angular/commit/2cf4da0ea11f5746eb7ae4dfd775f757576e4d98) | fix | hold constructors weakly in DepsTracker cache |
|
||||
| [70a5b651be](https://github.com/angular/angular/commit/70a5b651be29f1421eb25150b560bfe154aad6bc) | fix | prevent element duplication with dynamic components |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6f75b6e3f6](https://github.com/angular/angular/commit/6f75b6e3f60dc2a4f33e13562649931dc95eb52b) | fix | Resolves debounce promise on abort in debounceForDuration |
|
||||
### localize
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4c7126d23b](https://github.com/angular/angular/commit/4c7126d23be3e43b1d5bd6f2fb13119d185c3682) | fix | add support for unit-test builder in ng-add schematic |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d6268c0bbb](https://github.com/angular/angular/commit/d6268c0bbbdc92abaaaeb8eebee3bc45decab9c9) | fix | limit UrlParser recursion depth to prevent stack overflow |
|
||||
| [49a36f4cc7](https://github.com/angular/angular/commit/49a36f4cc7254420bc34fff4e0f0242e00970280) | perf | Use .bind to avoid holding other closures in memory |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.2"></a>
|
||||
# 21.1.2 (2026-01-28)
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9f99b14882](https://github.com/angular/angular/commit/9f99b14882bc4f883aa33295856010a8bca900fa) | fix | only touch visible, interactive fields on submit |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c57b0355b5](https://github.com/angular/angular/commit/c57b0355b51f5aee5abd822f203fc3bcc3e85acd) | fix | Detect local project version on creation |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [21ecdc036a](https://github.com/angular/angular/commit/21ecdc036a46c487d6c5b6bd25c2bbc3e53a60f9) | fix | Do not intercept reload events with Navigation integration |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.1"></a>
|
||||
# 21.1.1 (2026-01-21)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0e1f1ed573](https://github.com/angular/angular/commit/0e1f1ed5732f3bb4d5dfbd1f0ee5a5be840594e4) | fix | drop .tsx extension for generated relative imports |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [05adfcf8f2](https://github.com/angular/angular/commit/05adfcf8f26013ac20c38f2b08847b5142e4fd85) | fix | handle Set in class bindings |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d89a80a970](https://github.com/angular/angular/commit/d89a80a970d9590df0509d8b94090904a99b7aca) | feat | Ability to manually register a form field binding in signal forms |
|
||||
| [cb75f9ce85](https://github.com/angular/angular/commit/cb75f9ce85160b2e4359610c06294929ac1169c0) | fix | fix control value syncing on touch |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0"></a>
|
||||
# 21.1.0 (2026-01-14)
|
||||
## Deprecations
|
||||
### upgrade
|
||||
- `VERSION` from `@angular/upgrade` is deprecated. Please use the entry from `@angular/upgrade/static` instead.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d8790972be](https://github.com/angular/angular/commit/d8790972bea4c59a208219dd36d158b5d7e4fdde) | feat | Add custom transformations for Cloudflare and Cloudinary image loaders |
|
||||
| [a6b8cb68af](https://github.com/angular/angular/commit/a6b8cb68afaded6999ee68f495512be1a9932ae4) | feat | support custom transformations in ImageKit and Imgix loaders |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [640693da8e](https://github.com/angular/angular/commit/640693da8e667c015662246152236585d9b24e7f) | feat | Add support for multiple swich cases matching |
|
||||
| [0ad3adc7c6](https://github.com/angular/angular/commit/0ad3adc7c6d4094f1e3432a3f2e3bdc9862cb4fa) | fix | Support empty cases |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [99ad18a4ee](https://github.com/angular/angular/commit/99ad18a4ee82ecc5524106d1d403ccfa9bae2304) | feat | Add stability debugging utility |
|
||||
| [a0dfa5fa86](https://github.com/angular/angular/commit/a0dfa5fa86f40520b0e368a021b3c72009a45e8e) | feat | support rest arguments in function calls |
|
||||
| [6e18fa8bc9](https://github.com/angular/angular/commit/6e18fa8bc9d7e6801e2e89e635c2f759dc422317) | feat | support spread elements in array literals |
|
||||
| [e407280ab5](https://github.com/angular/angular/commit/e407280ab53cde5f93c3a643457c848845c6ec8b) | feat | support spread expressions in object literals |
|
||||
| [06be8034bb](https://github.com/angular/angular/commit/06be8034bb9b9adfc07ab0d40cd87c6ae5de02de) | fix | Microtask scheduling should be used after any application synchronization |
|
||||
| [b4f584cf42](https://github.com/angular/angular/commit/b4f584cf42235c94bb8389fa55bc634e23d7b010) | fix | return `StaticProvider` for `providePlatformInitializer` |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1ea5c97703](https://github.com/angular/angular/commit/1ea5c97703ad3c6d8e4cb1b4297eec57629ce117) | feat | allow focusing bound control from field state |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ec9dc94cee](https://github.com/angular/angular/commit/ec9dc94ceeb3c026c64e01c6889b7f5c6fd25a66) | feat | add `context` to `createApplication` |
|
||||
| [ab67988d2e](https://github.com/angular/angular/commit/ab67988d2e5242eff0034483f984428d684acd02) | feat | resolve JIT resources in `createApplication` |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5edceffd04](https://github.com/angular/angular/commit/5edceffd0431f5a25e111a731db521e966b91f86) | feat | add controls for route cleanup |
|
||||
| [a03c82564d](https://github.com/angular/angular/commit/a03c82564da6824e199ff48d5249ea8708040951) | feat | Add scroll behavior controls on router navigation |
|
||||
| [e44839b016](https://github.com/angular/angular/commit/e44839b01640505e554fff16f24e08f282a557c0) | feat | Add standalone function to create a comptued for isActive |
|
||||
| [c25d749d85](https://github.com/angular/angular/commit/c25d749d85374fff7745980cd9bb2673c661105a) | feat | Execute RunGuardsAndResolvers function in injection context |
|
||||
| [1c00ab42f8](https://github.com/angular/angular/commit/1c00ab42f8714f2775ed75bbf3cdf0fd44ee32c3) | feat | extend paramters of RedirectFunction to include paramMap and queryParamMap |
|
||||
| [7003e8d241](https://github.com/angular/angular/commit/7003e8d2417660f71b3a2a017aff3e650c8d9646) | feat | Publish Router's integration with platform Navigation API as experimental |
|
||||
| [c84d372778](https://github.com/angular/angular/commit/c84d37277874cf7cbd7582a295d796ff113b9cc1) | feat | Support wildcard params with segments trailing ([#64737](https://github.com/angular/angular/pull/64737)) |
|
||||
### upgrade
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [75fe8f8af9](https://github.com/angular/angular/commit/75fe8f8af9488bae6f7068b64d44500643c5d63f) | refactor | deprecate `VERSION` export |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.9"></a>
|
||||
# 21.0.9 (2026-01-14)
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [82d556a8fb](https://github.com/angular/angular/commit/82d556a8fb38cd2024e3d098c55254305ba12b6b) | fix | Ensure the control instruction comes after the other bindings |
|
||||
| [0055f3cc79](https://github.com/angular/angular/commit/0055f3cc79f387b8dec6ce5e1a33fad5486f9341) | fix | Rename signal form [field] to [formField] |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e4bfa5c9e7](https://github.com/angular/angular/commit/e4bfa5c9e7feec48d3c4e9425a21a2ccf6532bdb) | fix | prevent duplicate imports in common-to-standalone migration |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.8"></a>
|
||||
# 21.0.8 (2026-01-08)
|
||||
### core
|
||||
@@ -65,53 +337,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0-next.4"></a>
|
||||
# 21.1.0-next.4 (2025-12-17)
|
||||
## Breaking Changes
|
||||
### forms
|
||||
- The shape of `SignalFormsConfig.classes` has changed
|
||||
|
||||
Previously each function in the `classes` map took a `FieldState`. Now
|
||||
it takes a `Field` directive.
|
||||
|
||||
For example if you previously had:
|
||||
```
|
||||
provideSignalFormsConfig({
|
||||
classes: {
|
||||
'my-valid': (state) => state.valid()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You would need to update to:
|
||||
```
|
||||
provideSignalFormsConfig({
|
||||
classes: {
|
||||
'my-valid': ({state}) => state().valid()
|
||||
}
|
||||
})
|
||||
```
|
||||
-
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [06be8034bb](https://github.com/angular/angular/commit/06be8034bb9b9adfc07ab0d40cd87c6ae5de02de) | fix | Microtask scheduling should be used after any application synchronization |
|
||||
| [b4f584cf42](https://github.com/angular/angular/commit/b4f584cf42235c94bb8389fa55bc634e23d7b010) | fix | return `StaticProvider` for `providePlatformInitializer` |
|
||||
| [7be4ddef1c](https://github.com/angular/angular/commit/7be4ddef1ccb9a6b330b52b9bbdd174089755503) | fix | throw better errors for potential circular references |
|
||||
| [f516370c8e](https://github.com/angular/angular/commit/f516370c8e8e96806bad757d43c857ab5f2051ed) | fix | use mutable ResponseInit type for RESPONSE_INIT token |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [348f149e8b](https://github.com/angular/angular/commit/348f149e8b06d6885f54bac4cf03a9481a8b19b7) | feat | pass field directive to class config |
|
||||
| [ae0c59028a](https://github.com/angular/angular/commit/ae0c59028a2f393ea5716bf222db2c38e7a3989f) | refactor | rename field to fieldTree in FieldContext and ValidationError |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9f5744a92d](https://github.com/angular/angular/commit/9f5744a92dda4219e93bf7e6236d32a93bc167e6) | fix | avoid interpolation highlighting inside @let |
|
||||
| [ce1a4769f9](https://github.com/angular/angular/commit/ce1a4769f987e96e2a1b1cbc7654ed5bac9ce91d) | fix | Prevent language service from crashing on suggestion diagnostic errors |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.6"></a>
|
||||
# 21.0.6 (2025-12-17)
|
||||
## Breaking Changes (affecting only experimental features)
|
||||
@@ -159,24 +384,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0-next.3"></a>
|
||||
|
||||
# 21.1.0-next.3 (2025-12-11)
|
||||
|
||||
### core
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------ |
|
||||
| [4f6014a756a](https://github.com/angular/angular/commit/4f6014a756a95ff9cb55e91deb27039b7eb079ee) | fix | avoid false-positive deprecation when using `InjectionToken` with factory only |
|
||||
|
||||
### forms
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | ---- | --------------------------- |
|
||||
| [d0097f7d0c2](https://github.com/angular/angular/commit/d0097f7d0c214c5c3d715e7f1dfa3723b31f4065) | fix | fix signal forms type error |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.5"></a>
|
||||
|
||||
# 21.0.5 (2025-12-11)
|
||||
@@ -195,47 +402,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0-next.2"></a>
|
||||
|
||||
# 21.1.0-next.2 (2025-12-10)
|
||||
|
||||
## Deprecations
|
||||
|
||||
### upgrade
|
||||
|
||||
- `VERSION` from `@angular/upgrade` is deprecated. Please use the entry from `@angular/upgrade/static` instead.
|
||||
|
||||
### compiler
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | ---- | --------------------------------- |
|
||||
| [ae1c0dc4900](https://github.com/angular/angular/commit/ae1c0dc49002665c10d4e44f530f4cb8d1e35b8d) | perf | chain query creation instructions |
|
||||
|
||||
### compiler-cli
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | ---- | --------------------------------------------------- |
|
||||
| [8a3f3a91cf6](https://github.com/angular/angular/commit/8a3f3a91cf6919f11c1583afeb71b65488f8cba4) | fix | expand type for native controls with a dynamic type |
|
||||
|
||||
### forms
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------- |
|
||||
| [aff8b248b35](https://github.com/angular/angular/commit/aff8b248b35931cbe7d644ad2594144b75064ca6) | feat | expose element on signal forms `Field` directive |
|
||||
| [ebc5c2b083a](https://github.com/angular/angular/commit/ebc5c2b083a90fde6fced3521be434a414ef29dd) | feat | redo the signal forms metadata API |
|
||||
| [9fe95665813](https://github.com/angular/angular/commit/9fe95665813e24544d00dcf463658067da745ac2) | fix | add signals for dirty, hidden, and pending states in custom controls |
|
||||
| [14713d09923](https://github.com/angular/angular/commit/14713d09923b5315ac7c6f20acc06fc69ff0ed79) | fix | allow resetting with empty string |
|
||||
| [b96f65a963f](https://github.com/angular/angular/commit/b96f65a963febab376f2a783cf4313a8b8140efe) | fix | memoize reads of child fields in signal forms ([#65802](https://github.com/angular/angular/pull/65802)) |
|
||||
| [179b4cba67b](https://github.com/angular/angular/commit/179b4cba67b95563da27fd5f12dd2acc910a1a52) | fix | Reuse key in parent in compat structure |
|
||||
|
||||
### upgrade
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------- | -------- | -------------------------- |
|
||||
| [75fe8f8af94](https://github.com/angular/angular/commit/75fe8f8af9488bae6f7068b64d44500643c5d63f) | refactor | deprecate `VERSION` export |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.4"></a>
|
||||
|
||||
# 21.0.4 (2025-12-10)
|
||||
@@ -265,52 +431,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0-next.1"></a>
|
||||
|
||||
# 21.1.0-next.1 (2025-12-03)
|
||||
|
||||
### compiler
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | ----------------------------------------------------------------- |
|
||||
| [1c6b0704fb](https://github.com/angular/angular/commit/1c6b0704fb63d051fab8acff84d076abfbc4893a) | fix | prevent XSS via SVG animation `attributeName` and MathML/SVG URLs |
|
||||
|
||||
### compiler-cli
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | --------------------------------------------------------- |
|
||||
| [e30e61b789](https://github.com/angular/angular/commit/e30e61b7893a9b04ada54ab184c24e652dcd114e) | fix | avoid allocating an object for signals in production mode |
|
||||
| [6773d3b97d](https://github.com/angular/angular/commit/6773d3b97d07dcbf7760c0c12d9384fa60f7082e) | fix | check that field radio button values are strings |
|
||||
|
||||
### core
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| [d8ab83ca82](https://github.com/angular/angular/commit/d8ab83ca82c36faacae9fc1a01e9eb9762e679fc) | fix | run animation queue in environment injector context |
|
||||
| [886cf6c452](https://github.com/angular/angular/commit/886cf6c452abcf85b70058caeb080ff3a5c51cb9) | fix | unable to inject viewProviders when host directive with providers is present |
|
||||
| [e6d5632a30](https://github.com/angular/angular/commit/e6d5632a3059a4920f19eb6b193ec7edb11645d4) | perf | tree shake unused dynamic `[field]` binding instructions ([#65599](https://github.com/angular/angular/pull/65599)) |
|
||||
|
||||
### forms
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | -------------------------------------------------------------------------------------------- |
|
||||
| [7d1e502345](https://github.com/angular/angular/commit/7d1e50234515185ee73c8bdd39f7af2a26635ca2) | feat | Allows transforms on `FormUiControl` signals |
|
||||
| [cd7ae7e2ce](https://github.com/angular/angular/commit/cd7ae7e2ce4648edf62c047b3e453c8b32539d4a) | fix | support dynamic `[field]` bindings ([#65599](https://github.com/angular/angular/pull/65599)) |
|
||||
|
||||
### http
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | ---------------------------------------------------- |
|
||||
| [0659d11c85](https://github.com/angular/angular/commit/0659d11c854c9c6b886a2e925afef98d70bb005f) | fix | enable XSRF protection for same-origin absolute URLs |
|
||||
|
||||
### router
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | --------------------------------------------------- |
|
||||
| [b74a0693f2](https://github.com/angular/angular/commit/b74a0693f2409812ad1ab02f19eb3fbe7ce1b83e) | fix | handle errors from view transition finished promise |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.0.3"></a>
|
||||
|
||||
# 21.0.3 (2025-12-03)
|
||||
@@ -399,27 +519,6 @@
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="21.1.0-next.0"></a>
|
||||
|
||||
# 21.1.0-next.0 (2025-11-25)
|
||||
|
||||
### platform-browser
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | -------------------------------------------- |
|
||||
| [ec9dc94cee](https://github.com/angular/angular/commit/ec9dc94ceeb3c026c64e01c6889b7f5c6fd25a66) | feat | add `context` to `createApplication` |
|
||||
| [ab67988d2e](https://github.com/angular/angular/commit/ab67988d2e5242eff0034483f984428d684acd02) | feat | resolve JIT resources in `createApplication` |
|
||||
|
||||
### router
|
||||
|
||||
| Commit | Type | Description |
|
||||
| ------------------------------------------------------------------------------------------------ | ---- | -------------------------------------------------------------------------------------------------------- |
|
||||
| [a03c82564d](https://github.com/angular/angular/commit/a03c82564da6824e199ff48d5249ea8708040951) | feat | Add scroll behavior controls on router navigation |
|
||||
| [c25d749d85](https://github.com/angular/angular/commit/c25d749d85374fff7745980cd9bb2673c661105a) | feat | Execute RunGuardsAndResolvers function in injection context |
|
||||
| [c84d372778](https://github.com/angular/angular/commit/c84d37277874cf7cbd7582a295d796ff113b9cc1) | feat | Support wildcard params with segments trailing ([#64737](https://github.com/angular/angular/pull/64737)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="20.3.14"></a>
|
||||
|
||||
# 20.3.14 (2025-11-25)
|
||||
|
||||
+27
-16
@@ -5,27 +5,27 @@ module(
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_pkg", version = "1.2.0")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.6.2")
|
||||
bazel_dep(name = "aspect_rules_ts", version = "3.8.1")
|
||||
bazel_dep(name = "aspect_rules_js", version = "2.8.3")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.7.3")
|
||||
bazel_dep(name = "aspect_rules_ts", version = "3.8.5")
|
||||
bazel_dep(name = "aspect_rules_js", version = "2.9.2")
|
||||
bazel_dep(name = "aspect_rules_esbuild", version = "0.25.0")
|
||||
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.2")
|
||||
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4")
|
||||
bazel_dep(name = "aspect_rules_rollup", version = "2.0.1")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.9.0")
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.22.2")
|
||||
bazel_dep(name = "tar.bzl", version = "0.7.0")
|
||||
bazel_dep(name = "yq.bzl", version = "0.3.4")
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.22.5")
|
||||
bazel_dep(name = "tar.bzl", version = "0.9.0")
|
||||
bazel_dep(name = "yq.bzl", version = "0.3.5")
|
||||
bazel_dep(name = "rules_angular")
|
||||
git_override(
|
||||
module_name = "rules_angular",
|
||||
commit = "7133b97252508f8528e5c5818a9a73cacc2e2a0e",
|
||||
remote = "https://github.com/devversion/rules_angular.git",
|
||||
commit = "d746c4f75e42cffe389d1ab077f4639be2bc78d1",
|
||||
remote = "https://github.com/angular/rules_angular.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "devinfra")
|
||||
git_override(
|
||||
module_name = "devinfra",
|
||||
commit = "2ff164a0ca60e692f3d7e1a982bde9bf3379365e",
|
||||
commit = "e4dcda13e469f50a6bd92667e2ded8b98173bf2c",
|
||||
remote = "https://github.com/angular/dev-infra.git",
|
||||
)
|
||||
|
||||
@@ -33,21 +33,32 @@ bazel_dep(name = "rules_sass")
|
||||
git_override(
|
||||
module_name = "rules_sass",
|
||||
commit = "1184a80751a21af8348f308abc5b38a41f26850e",
|
||||
remote = "https://github.com/devversion/rules_sass.git",
|
||||
remote = "https://github.com/angular/rules_sass.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_browsers")
|
||||
git_override(
|
||||
module_name = "rules_browsers",
|
||||
commit = "5f0e50d17d15c70e6ab5546f1659338ae94c4072",
|
||||
remote = "https://github.com/devversion/rules_browsers.git",
|
||||
commit = "8231142fc5516323b040883bf774ba8362645387",
|
||||
remote = "https://github.com/angular/rules_browsers.git",
|
||||
)
|
||||
|
||||
yq = use_extension("@yq.bzl//yq:extensions.bzl", "yq")
|
||||
use_repo(yq, "yq_toolchains")
|
||||
|
||||
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
|
||||
node.toolchain(node_version_from_nvmrc = "//:.nvmrc")
|
||||
node.toolchain(
|
||||
node_repositories = {
|
||||
"22.22.1-darwin_arm64": ("node-v22.22.1-darwin-arm64.tar.gz", "node-v22.22.1-darwin-arm64", "679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"),
|
||||
"22.22.1-darwin_amd64": ("node-v22.22.1-darwin-x64.tar.gz", "node-v22.22.1-darwin-x64", "07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"),
|
||||
"22.22.1-linux_arm64": ("node-v22.22.1-linux-arm64.tar.xz", "node-v22.22.1-linux-arm64", "0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"),
|
||||
"22.22.1-linux_ppc64le": ("node-v22.22.1-linux-ppc64le.tar.xz", "node-v22.22.1-linux-ppc64le", "a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"),
|
||||
"22.22.1-linux_s390x": ("node-v22.22.1-linux-s390x.tar.xz", "node-v22.22.1-linux-s390x", "e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"),
|
||||
"22.22.1-linux_amd64": ("node-v22.22.1-linux-x64.tar.xz", "node-v22.22.1-linux-x64", "9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"),
|
||||
"22.22.1-windows_amd64": ("node-v22.22.1-win-x64.zip", "node-v22.22.1-win-x64", "877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"),
|
||||
},
|
||||
node_version = "22.22.1",
|
||||
)
|
||||
use_repo(node, "nodejs_toolchains")
|
||||
use_repo(node, "nodejs_darwin_amd64")
|
||||
use_repo(node, "nodejs_darwin_arm64")
|
||||
@@ -60,7 +71,8 @@ use_repo(node, "nodejs_windows_amd64")
|
||||
pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm")
|
||||
pnpm.pnpm(
|
||||
name = "pnpm",
|
||||
pnpm_version = "10.16.1",
|
||||
pnpm_version = "10.32.0",
|
||||
pnpm_version_integrity = "sha512-myY0uz/tVgHDNjPy2SWT9QYnCjljuMUdKy1qgo2mFc5One6++WFMzrvBOsjTwPnJzM61g8achXhDb6R327INcA==",
|
||||
)
|
||||
use_repo(pnpm, "pnpm")
|
||||
|
||||
@@ -71,7 +83,6 @@ npm.npm_translate_lock(
|
||||
"//:.pnpmfile.cjs",
|
||||
"//:package.json",
|
||||
"//:pnpm-workspace.yaml",
|
||||
"//:tools/pnpm-patches/dagre-d3-es+7.0.11.patch",
|
||||
"//adev:package.json",
|
||||
"//adev/shared-docs:package.json",
|
||||
"//adev/shared-docs/pipeline/api-gen:package.json",
|
||||
|
||||
Generated
+375
-89
@@ -13,28 +13,28 @@
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.0.0/MODULE.bazel": "e118477db5c49419a88d78ebc7a2c2cea9d49600fe0f490c1903324a2c16ecd9",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.11.0/MODULE.bazel": "cb1ba9f9999ed0bc08600c221f532c1ddd8d217686b32ba7d45b0713b5131452",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.14.0/MODULE.bazel": "2b31ffcc9bdc8295b2167e07a757dbbc9ac8906e7028e5170a3708cecaac119f",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.17.1/MODULE.bazel": "9b027af55f619c7c444cead71061578fab6587e5e1303fa4ed61d49d2b1a7262",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.2/MODULE.bazel": "30dfabbfae0139b1f0036e01c201dd4c0167da3017f0b7ef3820d78e07622989",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.3/MODULE.bazel": "253d739ba126f62a5767d832765b12b59e9f8d2bc88cc1572f4a73e46eb298ca",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.2/MODULE.bazel": "6b735f3fdd64978e217c9725f4ff0d84bf606554c8e77d20e90977841d7ff2ed",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.2/source.json": "58fffa2d722cff47cb8d921c8bbed7701c53f233009d9ca82beb4a0fb8fb9418",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.5/MODULE.bazel": "004ba890363d05372a97248c37205ae64b6fa31047629cd2c0895a9d0c7779e8",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.5/source.json": "ac2c3213df8f985785f1d0aeb7f0f73d5324e6e67d593d9b9470fb74a25d4a9b",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.7.7/MODULE.bazel": "491f8681205e31bb57892d67442ce448cda4f472a8e6b3dc062865e29a64f89c",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "812d2dd42f65dca362152101fbec418029cc8fd34cbad1a2fde905383d705838",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.9.3/MODULE.bazel": "66baf724dbae7aff4787bf2245cc188d50cb08e07789769730151c0943587c14",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_esbuild/0.25.0/MODULE.bazel": "5fef5ec709c837312823f9bcf0f276661e2cb48ad52f17c4e01176bbf1e9bf58",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_esbuild/0.25.0/source.json": "5e42968c6d23ab8bd95c02634b16864d866334347827cb6a8425b86c11cc4363",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.2/MODULE.bazel": "45f054400ff242c4433f6d7f20f6123a9a72739cb7a1f44247d738db1644f46c",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.2/source.json": "3ed399a5654259a822448f9cdbf21f6c738f16ccd7f89249c7507e374cbdd1e3",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/MODULE.bazel": "fbb819eb8b7e5d7f67fdd38f7cecb413e287594cd666ce192c72c8828527775a",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/source.json": "81ffb708333cd98ec3c0b4cc004f4d5cf92a16914b5196a2892c45141bba7cff",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.0.0/MODULE.bazel": "b45b507574aa60a92796e3e13c195cd5744b3b8aff516a9c0cb5ae6a048161c5",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.4.2/MODULE.bazel": "0d01db38b96d25df7ed952a5e96eac4b3802723d146961974bf020f6dd07591d",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.6.2/MODULE.bazel": "ed2a871f4ab8fbde0cab67c425745069d84ea64b64313fa1a2954017326511f5",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.8.3/MODULE.bazel": "807ce5f624124a8bc586c743394d174e85f0f9c6c4e0e2410b4088aebe790ac8",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.8.3/source.json": "c35cb4e04f61a09c17f8c569894b80de884b1e3dee2d33829704786e3f778037",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.9.2/MODULE.bazel": "93fd5b85e6e912fb0712cbab453c43271d4ea33a093f84fd587638fbc9f8c145",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_js/2.9.2/source.json": "4bff7c03ab387b60deb15649ba575688e62f2a71a7544cbc7a660b19ec473808",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_rollup/2.0.1/MODULE.bazel": "296e3a053658c2af989ba9bd62a205e6d1fa84bdd6dd5249196546e6b84770ec",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_rollup/2.0.1/source.json": "2fe8ac1ccb4de74bf884761e070010280b272d94e3997205b361b91c75409726",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.6.3/MODULE.bazel": "d09db394970f076176ce7bab5b5fa7f0d560fd4f30b8432ea5e2c2570505b130",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.7.0/MODULE.bazel": "5aace216caf88638950ef061245d23c36f57c8359e56e97f02a36f70bb09c50f",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.8.1/MODULE.bazel": "796622c65ae3008374fc2d77c32ddb4ef6da9fe891826ce648f70033a48b3667",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.8.1/source.json": "a7c4f332f5c21f4e63d073f8dda40bf278d5307499fb307b35058dba558f417a",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.8.5/MODULE.bazel": "bcf8f0b6b9375f0f74451e2f70671efae9bb366acef8fdc04675305eaf137f06",
|
||||
"https://bcr.bazel.build/modules/aspect_rules_ts/3.8.5/source.json": "fa35e43f6359f654e4b70ce55efdf280d0b06c0b3ef9fc0b06ba52327a0e6311",
|
||||
"https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.3/MODULE.bazel": "20f53b145f40957a51077ae90b37b7ce83582a1daf9350349f0f86179e19dd0d",
|
||||
"https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.6/MODULE.bazel": "cafb8781ad591bc57cc765dca5fefab08cf9f65af363d162b79d49205c7f8af7",
|
||||
"https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.8/MODULE.bazel": "aa975a83e72bcaac62ee61ab12b788ea324a1d05c4aab28aadb202f647881679",
|
||||
@@ -47,9 +47,11 @@
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.34.0/MODULE.bazel": "e8475ad7c8965542e0c7aac8af68eb48c4af904be3d614b6aa6274c092c2ea1e",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.34.0/source.json": "dfa5c4b01110313153b484a735764d247fee5624bbab63d25289e43b151a657a",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.39.0/MODULE.bazel": "28739425c1fc283c91931619749c832b555e60bcd1010b40d8441ce0a5cf726d",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.39.0/source.json": "f63cbeb4c602098484d57001e5a07d31cb02bbccde9b5e2c9bf0b29d05283e93",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
|
||||
@@ -75,7 +77,8 @@
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||
"https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8",
|
||||
"https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/source.json": "fa7b512dfcb5eafd90ce3959cf42a2a6fe96144ebbb4b3b3928054895f2afac2",
|
||||
"https://bcr.bazel.build/modules/gawk/5.3.2.bcr.3/MODULE.bazel": "f1b7bb2dd53e8f2ef984b39485ec8a44e9076dda5c4b8efd2fb4c6a6e856a31d",
|
||||
"https://bcr.bazel.build/modules/gawk/5.3.2.bcr.3/source.json": "ebe931bfe362e4b41e59ee00a528db6074157ff2ced92eb9e970acab2e1089c9",
|
||||
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
|
||||
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
|
||||
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
|
||||
@@ -122,7 +125,9 @@
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.16/source.json": "d03d5cde49376d87e14ec14b666c56075e5e3926930327fd5d0484a1ff2ac1cc",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc",
|
||||
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
|
||||
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
|
||||
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
|
||||
@@ -157,10 +162,11 @@
|
||||
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.2.0/MODULE.bazel": "ec27907f55eb34705adb4e8257952162a2d4c3ed0f0b3b4c3c1aad1fac7be35e",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.3.0/MODULE.bazel": "45345e4aba35dd6e4701c1eebf5a4e67af4ed708def9ebcdc6027585b34ee52d",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.3.3/MODULE.bazel": "b66eadebd10f1f1b25f52f95ab5213a57e82c37c3f656fcd9a57ad04d2264ce7",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.0/MODULE.bazel": "546d0cf79f36f9f6e080816045f97234b071c205f4542e3351bd4424282a8810",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.5.2/MODULE.bazel": "7f9ea68a0ce6d82905ce9f74e76ab8a8b4531ed4c747018c9d76424ad0b3370d",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.6.2/MODULE.bazel": "9fdb5e1d50246a25761f150fcc820dc47e4052330a8408451e628804f9ca64a6",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.6.2/source.json": "6e8c1ecc64ff8da147c1620f862ad77d7b19c5d1b52b3aa5e847d5b3d0de4cc3",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.7.3/MODULE.bazel": "c22a48b2a0dbf05a9dc5f83837bbc24c226c1f6e618de3c3a610044c9f336056",
|
||||
"https://bcr.bazel.build/modules/rules_nodejs/6.7.3/source.json": "a3f966f4415a8a6545e560ee5449eac95cc633f96429d08e87c87775c72f5e09",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/1.2.0/MODULE.bazel": "c7db3c2b407e673c7a39e3625dc05dc9f12d6682cbd82a3a5924a13b491eda7e",
|
||||
@@ -194,14 +200,14 @@
|
||||
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.7.0/MODULE.bazel": "cc1acd85da33c80e430b65219a620d54d114628df24a618c3a5fa0b65e988da9",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.7.0/source.json": "9becb80306f42d4810bfa16379fb48aad0b01ce5342bc12fe47dcd6af3ac4d7a",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.9.0/MODULE.bazel": "452a22d7f02b1c9d7a22ab25edf20f46f3e1101f0f67dc4bfbf9a474ddf02445",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.9.0/source.json": "c732760a374831a2cf5b08839e4be75017196b4d796a5aa55235272ee17cd839",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.2.0/MODULE.bazel": "6f3a675677db8885be4d607fde14cc51829715e3a879fb016eb9bf336786ce6d",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.2/MODULE.bazel": "0384efa70e8033d842ea73aa4b7199fa099709e236a7264345c03937166670b6",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.4/MODULE.bazel": "d3a270662f5d766cd7229732d65a5a5bc485240c3007343dd279edfb60c9ae27",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.4/source.json": "786dafdc2843722da3416e4343ee1a05237227f068590779a6e8496a2064c0f9",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.5/MODULE.bazel": "130c603e54be717bdf84100210f06598a0d2b4b4e01888fb01b70f50f41767ec",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.3.5/source.json": "1ae7bdc03cb26aaa8bd2bceadf65e90d90f0b2d03008ba9a0564da2e21396c39",
|
||||
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
|
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
|
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
|
||||
@@ -211,7 +217,7 @@
|
||||
"moduleExtensions": {
|
||||
"@@aspect_rules_esbuild+//esbuild:extensions.bzl%esbuild": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "9odiC0alKLq5PUYv/CZiw2yiMHsGpxvEhPsqt//fRRk=",
|
||||
"bzlTransitiveDigest": "fzdwsWU1Px4bYL57Cw1rvU/mgOqB7f0AF51JxT5kAs8=",
|
||||
"usagesDigest": "ToTaCONCN/E05krnHXLM1kpV1zrHNxHrGpUip973II4=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -412,8 +418,8 @@
|
||||
},
|
||||
"@@aspect_rules_js+//npm:extensions.bzl%pnpm": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "zVV86HvMwDBJ8IsFt27k/Sjq0vCMPr8b8X9OAuprQ6w=",
|
||||
"usagesDigest": "3ECQVM1bdy/C4w7vxglaG1gt0S98v0T14gP5wNiDgwY=",
|
||||
"bzlTransitiveDigest": "9Zmqluz9ltvCoc6pskOslTkQpkH6CIINjWVkgam9aa4=",
|
||||
"usagesDigest": "pLuUB7Fmb40xWdK1ynAXIWXeucWkJ0R9x2nDjqKhbq4=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -422,11 +428,11 @@
|
||||
"repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule",
|
||||
"attributes": {
|
||||
"package": "pnpm",
|
||||
"version": "10.16.1",
|
||||
"version": "10.32.0",
|
||||
"root_package": "",
|
||||
"link_workspace": "",
|
||||
"link_packages": {},
|
||||
"integrity": "sha512-DhVaomKduGcrSehHXaYiaqS96oX9zf3BU1CHSUbU88kfqvZMvcSl0auAAvRz1cP87c0ZeYnPA5D5ut08BGeHBg==",
|
||||
"integrity": "sha512-myY0uz/tVgHDNjPy2SWT9QYnCjljuMUdKy1qgo2mFc5One6++WFMzrvBOsjTwPnJzM61g8achXhDb6R327INcA==",
|
||||
"url": "",
|
||||
"commit": "",
|
||||
"patch_args": [
|
||||
@@ -449,7 +455,7 @@
|
||||
"repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links",
|
||||
"attributes": {
|
||||
"package": "pnpm",
|
||||
"version": "10.16.1",
|
||||
"version": "10.32.0",
|
||||
"dev": false,
|
||||
"root_package": "",
|
||||
"link_packages": {},
|
||||
@@ -566,10 +572,10 @@
|
||||
},
|
||||
"@@aspect_rules_ts+//ts:extensions.bzl%ext": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "7k3bewVApw4Kc6Rpho1Rrs1nrW/5jphUA5Mh1iHE2U4=",
|
||||
"usagesDigest": "BIPOUwqzuuYqLOw/0p3h5GwHIDeBVXvNcxNoG5YlsHQ=",
|
||||
"bzlTransitiveDigest": "6NyLUdrb79stFKm8oWIBK2q65cT5Upbr8IR2Qwsywu8=",
|
||||
"usagesDigest": "ZXlhH7TrNEERA0ibuRRxAjYv2fVuXoFGNd3v+0UK1/g=",
|
||||
"recordedFileInputs": {
|
||||
"@@rules_browsers+//package.json": "84dc1ba9b1c667a25894e97218bd8f247d54f24bb694efb397a881be3c06a4c5"
|
||||
"@@rules_browsers+//package.json": "772d873d450a539e2133635aeb5e63744cf1cec86e6b37aeecd9267a147fb0d7"
|
||||
},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -633,7 +639,7 @@
|
||||
"@@aspect_tools_telemetry+//:extension.bzl%telemetry": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "cl5A2O84vDL6Tt+Qga8FCj1DUDGqn+e7ly5rZ+4xvcc=",
|
||||
"usagesDigest": "c8kIEi+rX5/1OpfMZW0mHrM7sAvw+nu7pOep2xSjFb4=",
|
||||
"usagesDigest": "fkarigrHiiNAt/BwClRuO51QOEo6226baK6LoK/IWdU=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -642,10 +648,10 @@
|
||||
"repoRuleId": "@@aspect_tools_telemetry+//:extension.bzl%tel_repository",
|
||||
"attributes": {
|
||||
"deps": {
|
||||
"aspect_rules_ts": "3.8.1",
|
||||
"aspect_rules_js": "2.8.3",
|
||||
"aspect_rules_ts": "3.8.5",
|
||||
"aspect_rules_js": "2.9.2",
|
||||
"aspect_rules_esbuild": "0.25.0",
|
||||
"aspect_rules_jasmine": "2.0.2",
|
||||
"aspect_rules_jasmine": "2.0.4",
|
||||
"aspect_tools_telemetry": "0.3.3"
|
||||
}
|
||||
}
|
||||
@@ -667,7 +673,7 @@
|
||||
},
|
||||
"@@pybind11_bazel+//:python_configure.bzl%extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "c9ZWWeXeu6bctL4/SsY2otFWyeFN0JJ20+ymGyJZtWk=",
|
||||
"bzlTransitiveDigest": "D2/qWHU6yQFwRG7Bb+caqrYMha5avsASao2vERrxK24=",
|
||||
"usagesDigest": "fycyB39YnXIJkfWCIXLUKJMZzANcuLy9ZE73hRucjFk=",
|
||||
"recordedFileInputs": {
|
||||
"@@pybind11_bazel+//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e"
|
||||
@@ -727,8 +733,8 @@
|
||||
},
|
||||
"@@rules_browsers+//browsers:extensions.bzl%browsers": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "agkaLQ8wE1r/5IX6pkERzFxI/z0M42Em+ICNO6TXsVo=",
|
||||
"usagesDigest": "FS7q5WaIwg3KirS3njhuPFkTIBYvDaTInVGrlzu0XL8=",
|
||||
"bzlTransitiveDigest": "Bm6fiKpWy96aLohOlLCP36ARVxRLZm/R+smhsb2HzmI=",
|
||||
"usagesDigest": "FmXYJVoVJlnfUU8x8gObSvu4qWcco/9Faw61aC/wBF0=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -736,9 +742,9 @@
|
||||
"rules_browsers_chrome_linux": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "0a2ff0fc9eb5958b7b420f20e3968f424be7423fef89739e71565a48aa073a57",
|
||||
"sha256": "1ac33f89306327af43be159c03ca4a26486de0858f42fe52394acdef50364143",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/linux64/chrome-headless-shell-linux64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/linux64/chrome-headless-shell-linux64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-linux64/chrome-headless-shell"
|
||||
@@ -754,9 +760,9 @@
|
||||
"rules_browsers_chrome_mac": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "e6076b1201d86f74c5eab982a239d5af83e66b1aa4d780bcb792698790e01d87",
|
||||
"sha256": "169ff49c465cfda52931395e61861e146dfc5013e92c01ca792db5acea858d0b",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/mac-x64/chrome-headless-shell-mac-x64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/mac-x64/chrome-headless-shell-mac-x64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-x64/chrome-headless-shell"
|
||||
@@ -772,9 +778,9 @@
|
||||
"rules_browsers_chrome_mac_arm": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "b74dbcf5543d916b02d0a133e2e7c6a4de251f06733f72c2c15ea8c42213f63b",
|
||||
"sha256": "aeaaaaa4d68193a21bed04c44ddeb1230232707b4ea1d845a92925787509cd8e",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/mac-arm64/chrome-headless-shell-mac-arm64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/mac-arm64/chrome-headless-shell-mac-arm64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-mac-arm64/chrome-headless-shell"
|
||||
@@ -790,9 +796,9 @@
|
||||
"rules_browsers_chrome_win64": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "df1e612dc3b1615e182a1f11821052995913c39df37caa52699de21a68d030d2",
|
||||
"sha256": "4d6d79bcbcb22084df6e3a3d3a2caff67d6c0fa488d63f0c7ec1526f9553db8c",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/win64/chrome-headless-shell-win64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/win64/chrome-headless-shell-win64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROME-HEADLESS-SHELL": "chrome-headless-shell-win64/chrome-headless-shell.exe"
|
||||
@@ -808,9 +814,9 @@
|
||||
"rules_browsers_chromedriver_linux": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "69c504306399d979a2766fea603c3fb9d3d87d46c75bddc9f2a049b4f636d57c",
|
||||
"sha256": "0607ccf6810a07ae08cac6443beac8b23f88dd53c7f1e0299e22d65f7cd2d020",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/linux64/chromedriver-linux64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/linux64/chromedriver-linux64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROMEDRIVER": "chromedriver-linux64/chromedriver"
|
||||
@@ -824,9 +830,9 @@
|
||||
"rules_browsers_chromedriver_mac": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "5fc9d6f594fc5f2568a15145f25116dd8e9c9a60baa8da4bb21a17650fb00e7e",
|
||||
"sha256": "0f512a9dd683ed4c41e609d8d02c07807497dbad3ab2f95f0d583486be7b8cff",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/mac-x64/chromedriver-mac-x64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/mac-x64/chromedriver-mac-x64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROMEDRIVER": "chromedriver-mac-x64/chromedriver"
|
||||
@@ -840,9 +846,9 @@
|
||||
"rules_browsers_chromedriver_mac_arm": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "14e92294c2c3639ca4e7d27e850588b619d698e2f8905cee368f07db2e1bf1e9",
|
||||
"sha256": "7d6fc6d17de1733eb6739d1ea16d085c8df1568bcf9fa0d130c2784b27f38268",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/mac-arm64/chromedriver-mac-arm64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/mac-arm64/chromedriver-mac-arm64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROMEDRIVER": "chromedriver-mac-arm64/chromedriver"
|
||||
@@ -856,9 +862,9 @@
|
||||
"rules_browsers_chromedriver_win64": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "cf641d2e176db95bcc158cd90eafd347ad4928fa0458a5f3bfd56c6d983e70db",
|
||||
"sha256": "f4e9fb7bbf692fde7979b24e8d737b3cef4baafbc7a370e5d0abc4a8450fd830",
|
||||
"urls": [
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/145.0.7586.0/win64/chromedriver-win64.zip"
|
||||
"https://storage.googleapis.com/chrome-for-testing-public/147.0.7687.0/win64/chromedriver-win64.zip"
|
||||
],
|
||||
"named_files": {
|
||||
"CHROMEDRIVER": "chromedriver-win64/chromedriver.exe"
|
||||
@@ -872,9 +878,9 @@
|
||||
"rules_browsers_firefox_linux": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "8d56f479cc398a537a60a3fa20dca92d8a41925113d3a67f534881a4e4d7e344",
|
||||
"sha256": "f055b9c0d7346a10d22edc7f10e08679af2ea495367381ab2be9cab3ec6add97",
|
||||
"urls": [
|
||||
"https://archive.mozilla.org/pub/firefox/releases/146.0/linux-x86_64/en-US/firefox-146.0.tar.xz"
|
||||
"https://archive.mozilla.org/pub/firefox/releases/147.0/linux-x86_64/en-US/firefox-147.0.tar.xz"
|
||||
],
|
||||
"named_files": {
|
||||
"FIREFOX": "firefox/firefox"
|
||||
@@ -888,9 +894,9 @@
|
||||
"rules_browsers_firefox_mac": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "4b1645313887972d466cd82166ea571485c2c40a167f84624e3f3ca739993cc9",
|
||||
"sha256": "48485e2068bc726e2f30cf5855fc2da1fc75c1272bc243a5394f428ffae3ba35",
|
||||
"urls": [
|
||||
"https://archive.mozilla.org/pub/firefox/releases/146.0/mac/en-US/Firefox%20146.0.dmg"
|
||||
"https://archive.mozilla.org/pub/firefox/releases/147.0/mac/en-US/Firefox%20147.0.dmg"
|
||||
],
|
||||
"named_files": {
|
||||
"FIREFOX": "Firefox.app/Contents/MacOS/firefox"
|
||||
@@ -904,9 +910,9 @@
|
||||
"rules_browsers_firefox_mac_arm": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "4b1645313887972d466cd82166ea571485c2c40a167f84624e3f3ca739993cc9",
|
||||
"sha256": "48485e2068bc726e2f30cf5855fc2da1fc75c1272bc243a5394f428ffae3ba35",
|
||||
"urls": [
|
||||
"https://archive.mozilla.org/pub/firefox/releases/146.0/mac/en-US/Firefox%20146.0.dmg"
|
||||
"https://archive.mozilla.org/pub/firefox/releases/147.0/mac/en-US/Firefox%20147.0.dmg"
|
||||
],
|
||||
"named_files": {
|
||||
"FIREFOX": "Firefox.app/Contents/MacOS/firefox"
|
||||
@@ -920,9 +926,9 @@
|
||||
"rules_browsers_firefox_win64": {
|
||||
"repoRuleId": "@@rules_browsers+//browsers/private:browser_repo.bzl%browser_repo",
|
||||
"attributes": {
|
||||
"sha256": "216870c89648f32450cfefb5cec417fcd66d480d5dc83f894bf99f5fd7f38dbb",
|
||||
"sha256": "36ff9e150875aa48a0af9eec3eb67f66dddd8efac5c743265371a72ae3e796c4",
|
||||
"urls": [
|
||||
"https://archive.mozilla.org/pub/firefox/releases/146.0/win64/en-US/Firefox%20Setup%20146.0.exe"
|
||||
"https://archive.mozilla.org/pub/firefox/releases/147.0/win64/en-US/Firefox%20Setup%20147.0.exe"
|
||||
],
|
||||
"named_files": {
|
||||
"FIREFOX": "core/firefox.exe"
|
||||
@@ -939,7 +945,7 @@
|
||||
},
|
||||
"@@rules_fuzzing+//fuzzing/private:extensions.bzl%non_module_dependencies": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "WHRlQQnxW7e7XMRBhq7SARkDarLDOAbg6iLaJpk5QYM=",
|
||||
"bzlTransitiveDigest": "4LouzhF/yT117s7peGnNs9ROomiJXC6Zl5R0oI21jho=",
|
||||
"usagesDigest": "wy6ISK6UOcBEjj/mvJ/S3WeXoO67X+1llb9yPyFtPgc=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -1022,7 +1028,7 @@
|
||||
},
|
||||
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=",
|
||||
"bzlTransitiveDigest": "nvW/NrBXlAmiQw99EMGKkLaD2KbNp2mQDlxdfpr+0Ls=",
|
||||
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -1086,8 +1092,8 @@
|
||||
},
|
||||
"@@rules_nodejs+//nodejs:extensions.bzl%node": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "NwcLXHrbh2hoorA/Ybmcpjxsn/6avQmewDglodkDrgo=",
|
||||
"usagesDigest": "QbHTNODxV2P0w/Zs/oELuqv6ovXgi81f6SUYmX7dNhc=",
|
||||
"bzlTransitiveDigest": "4pUxCNc22K4I+6+4Nxu52Hur12tFRfa1JMsN5mdDv60=",
|
||||
"usagesDigest": "pjXeuItYQffkhMcQv+aU/G0SB0QAmyOC9W7iq63eW08=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -1096,12 +1102,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "linux_amd64"
|
||||
}
|
||||
@@ -1110,12 +1151,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "linux_arm64"
|
||||
}
|
||||
@@ -1124,12 +1200,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "linux_s390x"
|
||||
}
|
||||
@@ -1138,12 +1249,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "linux_ppc64le"
|
||||
}
|
||||
@@ -1152,12 +1298,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "darwin_amd64"
|
||||
}
|
||||
@@ -1166,12 +1347,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "darwin_arm64"
|
||||
}
|
||||
@@ -1180,12 +1396,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "windows_amd64"
|
||||
}
|
||||
@@ -1194,12 +1445,47 @@
|
||||
"repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
|
||||
"attributes": {
|
||||
"node_download_auth": {},
|
||||
"node_repositories": {},
|
||||
"node_repositories": {
|
||||
"22.22.1-darwin_arm64": [
|
||||
"node-v22.22.1-darwin-arm64.tar.gz",
|
||||
"node-v22.22.1-darwin-arm64",
|
||||
"679ad4966339e4ef4900f57996714864e4211b898825bb840c3086c419fbcef2"
|
||||
],
|
||||
"22.22.1-darwin_amd64": [
|
||||
"node-v22.22.1-darwin-x64.tar.gz",
|
||||
"node-v22.22.1-darwin-x64",
|
||||
"07b13722d558790fca20bb1ecf61bde24b7a4863111f7be77fc57251a407359a"
|
||||
],
|
||||
"22.22.1-linux_arm64": [
|
||||
"node-v22.22.1-linux-arm64.tar.xz",
|
||||
"node-v22.22.1-linux-arm64",
|
||||
"0f3550d58d45e5d3cf7103d9e3f69937f09fe82fb5dd474c66a5d816fa58c9ee"
|
||||
],
|
||||
"22.22.1-linux_ppc64le": [
|
||||
"node-v22.22.1-linux-ppc64le.tar.xz",
|
||||
"node-v22.22.1-linux-ppc64le",
|
||||
"a65a44cf0224505f052b90357b763dbc1ea9148f4f5f2284f0596cf2000f819b"
|
||||
],
|
||||
"22.22.1-linux_s390x": [
|
||||
"node-v22.22.1-linux-s390x.tar.xz",
|
||||
"node-v22.22.1-linux-s390x",
|
||||
"e08b3a73d0bd840e008f589e4be4a2ef3d4a0c59015f4f20a04ed7fc968042a2"
|
||||
],
|
||||
"22.22.1-linux_amd64": [
|
||||
"node-v22.22.1-linux-x64.tar.xz",
|
||||
"node-v22.22.1-linux-x64",
|
||||
"9a6bc82f9b491279147219f6a18add1e18424dce90d41d2a5fcd69d4924ba3aa"
|
||||
],
|
||||
"22.22.1-windows_amd64": [
|
||||
"node-v22.22.1-win-x64.zip",
|
||||
"node-v22.22.1-win-x64",
|
||||
"877cb93829e14fffbbc7903e7d8037336c9a79f3ea43c5d0b8c2379b79da56de"
|
||||
]
|
||||
},
|
||||
"node_urls": [
|
||||
"https://nodejs.org/dist/v{version}/{filename}"
|
||||
],
|
||||
"node_version": "20.19.5",
|
||||
"node_version_from_nvmrc": "@@//:.nvmrc",
|
||||
"node_version": "22.22.1",
|
||||
"include_headers": false,
|
||||
"platform": "windows_arm64"
|
||||
}
|
||||
@@ -1228,7 +1514,7 @@
|
||||
},
|
||||
"@@rules_python+//python/extensions:pip.bzl%pip": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "39J6fxZx6VyebAMZs6LDsQSGw91SROMECqQx77bSJqE=",
|
||||
"bzlTransitiveDigest": "LFkevJ0u48WgTVCyU07LkRD8iYwsRUs2M7uSFHkQAW0=",
|
||||
"usagesDigest": "/9NP3RV6/DWuNdYAsIU/8UCgCX0TdPUJr0X6O+0lrtk=",
|
||||
"recordedFileInputs": {
|
||||
"@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5",
|
||||
@@ -4022,8 +4308,8 @@
|
||||
},
|
||||
"@@yq.bzl+//yq:extensions.bzl%yq": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "tDqk+ntWTdxNAWPDjRY1uITgHbti2jcXR5ZdinltBs0=",
|
||||
"usagesDigest": "fKeGl7m4X6ZwRQS4Up/5Bzx+9laXzZyKEn6s9ODJQTc=",
|
||||
"bzlTransitiveDigest": "UfFMy8CWK4/dVo/tfaSAIYUiDGNAPes5eRllx9O9Q9Q=",
|
||||
"usagesDigest": "LPHUB1lzZAsPKLeNh6HnzS3+5eXDr8A5CKmoD+VBOA4=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
|
||||
@@ -25,6 +25,19 @@ APPLICATION_FILES = [
|
||||
"//adev/src/assets:context",
|
||||
"//adev/src/content/examples:embeddable",
|
||||
"tailwind.config.js",
|
||||
|
||||
# For the routes that are generated at build time
|
||||
"//adev/src/assets:docs_api_manifest",
|
||||
"//adev/scripts/routes:generate_route",
|
||||
"//adev/src/app/routing/navigation-entries",
|
||||
"//adev/src/app/routing/navigation-entries:navigation_types",
|
||||
"//adev/src/content/reference/errors:route-nav-items",
|
||||
"//adev/src/content/reference/extended-diagnostics:route-nav-items",
|
||||
"//adev/src/content/tutorials/deferrable-views",
|
||||
"//adev/src/content/tutorials/first-app",
|
||||
"//adev/src/content/tutorials/learn-angular",
|
||||
"//adev/src/content/tutorials/signal-forms",
|
||||
"//adev/src/content/tutorials/signals",
|
||||
] + glob(
|
||||
["src/**/*"],
|
||||
exclude = ["src/**/*.spec.ts"],
|
||||
@@ -47,6 +60,7 @@ APPLICATION_DEPS = [
|
||||
":node_modules/@lezer/highlight",
|
||||
":node_modules/@lezer/javascript",
|
||||
":node_modules/@stackblitz/sdk",
|
||||
":node_modules/shiki",
|
||||
":node_modules/@typescript/vfs",
|
||||
":node_modules/@webcontainer/api",
|
||||
":node_modules/@xterm/addon-fit",
|
||||
@@ -78,6 +92,30 @@ APPLICATION_DEPS = [
|
||||
":node_modules/crelt",
|
||||
":node_modules/style-mod",
|
||||
":node_modules/w3c-keyname",
|
||||
#
|
||||
":node_modules/@shikijs/themes",
|
||||
":node_modules/@shikijs/langs",
|
||||
":node_modules/@shikijs/engine-oniguruma",
|
||||
":node_modules/@shikijs/core",
|
||||
":node_modules/@shikijs/engine-javascript",
|
||||
":node_modules/@shikijs/types",
|
||||
":node_modules/@shikijs/vscode-textmate",
|
||||
":node_modules/hast-util-to-html",
|
||||
# ":node_modules/oniguruma-to-es",
|
||||
":node_modules/ccount",
|
||||
":node_modules/comma-separated-tokens",
|
||||
":node_modules/hast-util-whitespace",
|
||||
":node_modules/html-void-elements",
|
||||
# ":node_modules/oniguruma-parser",
|
||||
":node_modules/property-information",
|
||||
# ":node_modules/regex-recursion",
|
||||
# ":node_modules/regex",
|
||||
":node_modules/space-separated-tokens",
|
||||
":node_modules/stringify-entities",
|
||||
":node_modules/zwitch",
|
||||
":node_modules/character-entities-html4",
|
||||
":node_modules/character-entities-legacy",
|
||||
# ":node_modules/regex-utilities",
|
||||
]
|
||||
|
||||
TEST_FILES = APPLICATION_FILES + glob(["src/app/**/*.spec.ts"])
|
||||
|
||||
+49
-31
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.46.2",
|
||||
"@algolia/client-search": "5.46.2",
|
||||
"@algolia/requester-browser-xhr": "5.46.2",
|
||||
"@algolia/requester-node-http": "5.46.2",
|
||||
"@algolia/client-common": "5.48.0",
|
||||
"@algolia/client-search": "5.48.0",
|
||||
"@algolia/requester-browser-xhr": "5.48.0",
|
||||
"@algolia/requester-node-http": "5.48.0",
|
||||
"@angular/animations": "workspace:*",
|
||||
"@angular/aria": "21.1.0-next.3",
|
||||
"@angular/build": "21.1.0-next.3",
|
||||
"@angular/cdk": "21.1.0-next.3",
|
||||
"@angular/cli": "21.1.0-next.3",
|
||||
"@angular/aria": "21.2.0",
|
||||
"@angular/build": "21.2.0",
|
||||
"@angular/cdk": "21.2.0",
|
||||
"@angular/cli": "21.2.0",
|
||||
"@angular/common": "workspace:*",
|
||||
"@angular/compiler": "workspace:*",
|
||||
"@angular/compiler-cli": "workspace:*",
|
||||
"@angular/core": "workspace:*",
|
||||
"@angular/docs": "workspace:*",
|
||||
"@angular/forms": "workspace:*",
|
||||
"@angular/material": "21.1.0-next.3",
|
||||
"@angular/material": "21.2.0",
|
||||
"@angular/platform-browser": "workspace:*",
|
||||
"@angular/platform-server": "workspace:*",
|
||||
"@angular/router": "workspace:*",
|
||||
"@angular/ssr": "21.1.0-next.3",
|
||||
"@angular/ssr": "21.2.0",
|
||||
"@codemirror/autocomplete": "6.20.0",
|
||||
"@codemirror/commands": "6.10.1",
|
||||
"@codemirror/lang-angular": "0.1.4",
|
||||
@@ -28,57 +28,75 @@
|
||||
"@codemirror/lang-javascript": "6.2.4",
|
||||
"@codemirror/lang-sass": "6.0.2",
|
||||
"@codemirror/language": "6.12.1",
|
||||
"@codemirror/lint": "6.9.2",
|
||||
"@codemirror/search": "6.5.11",
|
||||
"@codemirror/state": "6.5.3",
|
||||
"@codemirror/view": "6.39.9",
|
||||
"@lezer/common": "1.5.0",
|
||||
"@codemirror/lint": "6.9.3",
|
||||
"@codemirror/search": "6.6.0",
|
||||
"@codemirror/state": "6.5.4",
|
||||
"@codemirror/view": "6.39.12",
|
||||
"@lezer/common": "1.5.1",
|
||||
"@lezer/css": "1.3.0",
|
||||
"@lezer/highlight": "1.2.3",
|
||||
"@lezer/html": "1.3.13",
|
||||
"@lezer/javascript": "1.5.4",
|
||||
"@lezer/lr": "1.4.7",
|
||||
"@lezer/lr": "1.4.8",
|
||||
"@lezer/sass": "1.1.0",
|
||||
"@marijn/find-cluster-break": "1.0.2",
|
||||
"@shikijs/core": "^3.21.0",
|
||||
"@shikijs/engine-javascript": "^3.21.0",
|
||||
"@shikijs/engine-oniguruma": "^3.21.0",
|
||||
"@shikijs/langs": "^3.21.0",
|
||||
"@shikijs/themes": "^3.21.0",
|
||||
"@shikijs/types": "^3.21.0",
|
||||
"@shikijs/vscode-textmate": "^10.0.2",
|
||||
"@stackblitz/sdk": "1.11.0",
|
||||
"@types/dom-navigation": "1.0.6",
|
||||
"@types/jasmine": "5.1.13",
|
||||
"@types/jasmine": "6.0.0",
|
||||
"@types/jsdom": "27.0.0",
|
||||
"@types/node": "24.10.4",
|
||||
"@types/node": "24.10.11",
|
||||
"@typescript/vfs": "1.6.2",
|
||||
"@webcontainer/api": "1.6.1",
|
||||
"@xterm/addon-fit": "0.11.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"algoliasearch": "5.46.2",
|
||||
"@xterm/xterm": "6.0.0",
|
||||
"algoliasearch": "5.48.0",
|
||||
"angular-split": "20.0.0",
|
||||
"ccount": "^2.0.1",
|
||||
"character-entities-html4": "^2.1.0",
|
||||
"character-entities-legacy": "^3.0.0",
|
||||
"comma-separated-tokens": "^2.0.3",
|
||||
"crelt": "1.0.6",
|
||||
"diff": "8.0.2",
|
||||
"diff": "8.0.3",
|
||||
"emoji-regex": "10.6.0",
|
||||
"fflate": "0.8.2",
|
||||
"jasmine-core": "5.13.0",
|
||||
"jsdom": "27.4.0",
|
||||
"hast-util-to-html": "^9.0.5",
|
||||
"hast-util-whitespace": "^3.0.0",
|
||||
"html-void-elements": "^3.0.0",
|
||||
"jsdom": "28.0.0",
|
||||
"jasmine-core": "6.1.0",
|
||||
"karma-chrome-launcher": "3.2.0",
|
||||
"karma-coverage": "2.2.1",
|
||||
"karma-jasmine": "5.1.0",
|
||||
"karma-jasmine-html-reporter": "2.1.0",
|
||||
"karma-jasmine-html-reporter": "2.2.0",
|
||||
"marked": "17.0.1",
|
||||
"mermaid": "11.12.2",
|
||||
"ngx-progressbar": "14.0.0",
|
||||
"open-in-idx": "0.1.1",
|
||||
"playwright-core": "1.57.0",
|
||||
"preact": "10.28.2",
|
||||
"preact-render-to-string": "6.6.5",
|
||||
"prettier": "3.7.4",
|
||||
"playwright-core": "1.58.1",
|
||||
"preact": "10.28.3",
|
||||
"preact-render-to-string": "6.6.6",
|
||||
"prettier": "3.8.1",
|
||||
"property-information": "^7.1.0",
|
||||
"rxjs": "7.8.2",
|
||||
"shiki": "3.21.0",
|
||||
"shiki": "3.22.0",
|
||||
"space-separated-tokens": "^2.0.2",
|
||||
"stringify-entities": "^4.0.4",
|
||||
"style-mod": "4.1.3",
|
||||
"tinyglobby": "0.2.15",
|
||||
"tslib": "2.8.1",
|
||||
"typescript": "5.9.3",
|
||||
"w3c-keyname": "2.2.8"
|
||||
"w3c-keyname": "2.2.8",
|
||||
"zwitch": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "10.4.23",
|
||||
"autoprefixer": "10.4.24",
|
||||
"karma": "~6.4.4",
|
||||
"postcss": "8.5.6",
|
||||
"tailwindcss": "3.4.19"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
|
||||
load("//adev/shared-docs:defaults.bzl", "js_binary", "js_run_binary")
|
||||
|
||||
package(default_visibility = ["//adev:__subpackages__"])
|
||||
|
||||
ts_project(
|
||||
name = "generate_routes_lib",
|
||||
srcs = [
|
||||
"generate-routes.mts",
|
||||
],
|
||||
data = [
|
||||
"//adev/src/assets:docs_api_manifest",
|
||||
"//adev/src/content/tutorials/deferrable-views",
|
||||
"//adev/src/content/tutorials/first-app",
|
||||
"//adev/src/content/tutorials/learn-angular",
|
||||
"//adev/src/content/tutorials/signal-forms",
|
||||
"//adev/src/content/tutorials/signals",
|
||||
],
|
||||
tsconfig = {
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"types": ["node"],
|
||||
"rootDir": ".",
|
||||
"skipLibCheck": True,
|
||||
},
|
||||
},
|
||||
deps = [
|
||||
"//adev:node_modules/@angular/docs",
|
||||
"//adev:node_modules/@types/node",
|
||||
"//adev/shared-docs/pipeline/shared:heading",
|
||||
"//adev/src/app/routing/navigation-entries",
|
||||
"//adev/src/content/reference/errors:route-nav-items",
|
||||
"//adev/src/content/reference/extended-diagnostics:route-nav-items",
|
||||
],
|
||||
)
|
||||
|
||||
js_binary(
|
||||
name = "generate_route",
|
||||
data = [
|
||||
"generate-routes.mjs",
|
||||
":generate_routes_lib",
|
||||
"//adev/src/content:guide_files",
|
||||
],
|
||||
entry_point = ":generate-routes.mjs",
|
||||
)
|
||||
|
||||
js_run_binary(
|
||||
name = "run_generate_route",
|
||||
outs = ["defined-routes.json"],
|
||||
chdir = package_name(),
|
||||
tool = ":generate_route",
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
/*!
|
||||
* @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 {ALL_ITEMS} from '../../src/app/routing/navigation-entries/index.js';
|
||||
import {getIdFromHeading} from '../../shared-docs/pipeline/shared/heading.mjs';
|
||||
import {NavigationItem} from '@angular/docs';
|
||||
import {writeFileSync, readFileSync} from 'fs';
|
||||
import {join, resolve} from 'path';
|
||||
|
||||
const outputFile = 'defined-routes.json';
|
||||
const contentRoot = resolve(process.cwd(), '../../src/content');
|
||||
|
||||
/**
|
||||
* The scripts generates a list of all defined routes in the guides section and stores them
|
||||
* in a JSON file. This file then used by other bazel targets to know which routes are valid.
|
||||
*/
|
||||
|
||||
function extractRoutes(items: NavigationItem[]): string[] {
|
||||
const routes: string[] = [];
|
||||
for (const item of items) {
|
||||
if (item.path && !item.path.startsWith('http')) {
|
||||
routes.push(item.path);
|
||||
if (item.contentPath) {
|
||||
const content = readFileSync(join(contentRoot, `${item.contentPath}.md`), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
const headings = extractHeadings(content);
|
||||
routes.push(
|
||||
...headings.map(
|
||||
(heading) => `${item.path}#${heading.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (item.children) {
|
||||
routes.push(...extractRoutes(item.children));
|
||||
}
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
|
||||
function extractHeadings(content: string): string[] {
|
||||
const headings = content
|
||||
.split('\n')
|
||||
// Top level heading (H1) are used for the page title only
|
||||
// and yes, headings can have leading spaces
|
||||
.filter((line) => line.trim().startsWith('##'))
|
||||
.map((line) => line.replace(/^#+\s*/, '').trim());
|
||||
|
||||
const stepRegex = /<docs-step[^>]*title="([^"]*)"/g;
|
||||
let match;
|
||||
while ((match = stepRegex.exec(content)) !== null) {
|
||||
headings.push(match[1]);
|
||||
}
|
||||
|
||||
return headings.map((heading: string) => getIdFromHeading(heading));
|
||||
}
|
||||
|
||||
function main() {
|
||||
const allRoutes: string[] = [];
|
||||
|
||||
allRoutes.push(...extractRoutes(ALL_ITEMS));
|
||||
|
||||
const uniqueRoutes = Array.from(new Set(allRoutes.filter((r) => !!r)));
|
||||
|
||||
console.warn('Generated routes:', JSON.stringify(uniqueRoutes, null, 2));
|
||||
writeFileSync(outputFile, JSON.stringify(uniqueRoutes, null, 2));
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {SynonymHit} from 'algoliasearch';
|
||||
import {type SynonymHit} from 'algoliasearch';
|
||||
|
||||
/**
|
||||
* List of synonyms to upload to algolia.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "bundler",
|
||||
"preserveSymlinks": true,
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"allowImportingTsExtensions": true,
|
||||
"lib": ["ES2022"],
|
||||
"types": [],
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {algoliasearch} from 'algoliasearch';
|
||||
import synonyms from './algolia-synonyms.mjs';
|
||||
import synonyms from './algolia-synonyms.mts';
|
||||
|
||||
/** The name of the index being updated. */
|
||||
const INDEX_NAME = 'angular_v17';
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
import {ChangeDetectionStrategy, Component, inject, input, output} from '@angular/core';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
import {MatTooltip} from '@angular/material/tooltip';
|
||||
import {RouterLink, RouterLinkActive} from '@angular/router';
|
||||
import {NavigationItem} from '../../interfaces/index';
|
||||
import {IsActiveNavigationItem} from '../../pipes';
|
||||
@@ -23,7 +23,7 @@ import {IconComponent} from '../icon/icon.component';
|
||||
IconComponent,
|
||||
IsActiveNavigationItem,
|
||||
NgTemplateOutlet,
|
||||
MatTooltipModule,
|
||||
MatTooltip,
|
||||
],
|
||||
templateUrl: './navigation-list.component.html',
|
||||
styleUrls: ['./navigation-list.component.scss'],
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<docs-text-field
|
||||
[autofocus]="true"
|
||||
[hideIcon]="true"
|
||||
[field]="searchForm"
|
||||
[formField]="searchForm"
|
||||
[resetLabel]="'Clear the search'"
|
||||
class="docs-search-input"
|
||||
placeholder="Search docs"
|
||||
|
||||
@@ -137,14 +137,14 @@ dialog {
|
||||
.docs-search-results__start-typing,
|
||||
.docs-search-results__no-results {
|
||||
padding: 0.75rem;
|
||||
color: var(--gray-400);
|
||||
color: var(--quaternary-contrast);
|
||||
}
|
||||
|
||||
.docs-search-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: var(--gray-400);
|
||||
color: var(--quaternary-contrast);
|
||||
padding: 1rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
DestroyRef,
|
||||
ElementRef,
|
||||
Injector,
|
||||
afterNextRender,
|
||||
effect,
|
||||
ElementRef,
|
||||
inject,
|
||||
Injector,
|
||||
output,
|
||||
viewChild,
|
||||
viewChildren,
|
||||
@@ -26,7 +26,7 @@ import {Search, SearchHistory} from '../../services';
|
||||
|
||||
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {Field, form} from '@angular/forms/signals';
|
||||
import {form, FormField} from '@angular/forms/signals';
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {fromEvent} from 'rxjs';
|
||||
import {RelativeLink} from '../../pipes';
|
||||
@@ -40,7 +40,7 @@ import {TextField} from '../text-field/text-field.component';
|
||||
imports: [
|
||||
ClickOutside,
|
||||
TextField,
|
||||
Field,
|
||||
FormField,
|
||||
SearchItem,
|
||||
AlgoliaIcon,
|
||||
RelativeLink,
|
||||
@@ -54,7 +54,6 @@ export class SearchDialog {
|
||||
readonly onClose = output();
|
||||
readonly dialog = viewChild.required<ElementRef<HTMLDialogElement>>('searchDialog');
|
||||
readonly items = viewChildren(SearchItem);
|
||||
readonly textField = viewChild(TextField);
|
||||
|
||||
readonly history = inject(SearchHistory);
|
||||
private readonly search = inject(Search);
|
||||
@@ -96,9 +95,6 @@ export class SearchDialog {
|
||||
if (!this.dialog().nativeElement.open) {
|
||||
this.dialog().nativeElement.showModal?.();
|
||||
}
|
||||
// We want to select the pre-existing text on opening
|
||||
// In order to change the search input with minimal user interaction.
|
||||
this.textField()?.input().nativeElement.select();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ ng_project(
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev:node_modules/@angular/aria",
|
||||
"//adev:node_modules/@angular/common",
|
||||
"//adev:node_modules/@angular/core",
|
||||
"//adev:node_modules/@angular/forms",
|
||||
|
||||
@@ -1,10 +1,61 @@
|
||||
<select
|
||||
[attr.id]="id()"
|
||||
[attr.name]="name()"
|
||||
[value]="value()"
|
||||
(change)="setOption($any($event.target).value)"
|
||||
>
|
||||
@for (item of options(); track item) {
|
||||
<option [value]="item.value" [selected]="value() === item.value">{{ item.label }}</option>
|
||||
}
|
||||
</select>
|
||||
<div ngCombobox #outerCombobox="ngCombobox" [readonly]="true" [disabled]="disabled()">
|
||||
<div class="docs-select-input-container">
|
||||
<input
|
||||
ngComboboxInput
|
||||
[attr.id]="id()"
|
||||
[attr.name]="name()"
|
||||
[value]="displayValue()"
|
||||
placeholder="Select an option..."
|
||||
readonly
|
||||
/>
|
||||
<span class="material-symbols-outlined docs-select-arrow" translate="no" aria-hidden="true"
|
||||
>arrow_drop_down</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<ng-template ngComboboxPopupContainer>
|
||||
<dialog ngComboboxDialog class="docs-select-dialog">
|
||||
<div ngCombobox #innerCombobox="ngCombobox" filterMode="manual" [alwaysExpanded]="true">
|
||||
<div class="docs-select-search-container">
|
||||
<span
|
||||
class="material-symbols-outlined docs-select-search-icon"
|
||||
translate="no"
|
||||
aria-hidden="true"
|
||||
>search</span
|
||||
>
|
||||
<input
|
||||
ngComboboxInput
|
||||
class="docs-select-search-input"
|
||||
placeholder="Search..."
|
||||
[(value)]="searchString"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ng-template ngComboboxPopupContainer>
|
||||
@if (filteredOptions().length === 0) {
|
||||
<div class="docs-select-no-results">No results found</div>
|
||||
}
|
||||
|
||||
<div ngListbox [(values)]="selectedValues" class="docs-select-listbox">
|
||||
@for (option of filteredOptions(); track option.value) {
|
||||
<div
|
||||
ngOption
|
||||
[value]="option.value"
|
||||
[label]="option.label"
|
||||
class="docs-select-option"
|
||||
>
|
||||
<span class="docs-select-option-label">{{ option.label }}</span>
|
||||
<span
|
||||
class="material-symbols-outlined docs-select-check-icon"
|
||||
translate="no"
|
||||
aria-hidden="true"
|
||||
>check</span
|
||||
>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</dialog>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
:host {
|
||||
--border-color: color-mix(in srgb, var(--full-contrast) 20%, var(--page-background));
|
||||
}
|
||||
|
||||
[ngCombobox] {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.docs-select-input-container {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
[ngComboboxInput] {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
[ngComboboxInput][readonly='true'] {
|
||||
cursor: pointer;
|
||||
padding: 0.7rem 1rem;
|
||||
}
|
||||
|
||||
[ngCombobox]:focus-within [ngComboboxInput]:not(.docs-select-search-input) {
|
||||
outline: 1.5px solid var(--vivid-pink);
|
||||
box-shadow: 0 0 0 4px color-mix(in srgb, var(--vivid-pink) 25%, transparent);
|
||||
}
|
||||
|
||||
.docs-select-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 20px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
pointer-events: none;
|
||||
padding: 0 0.5rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
opacity: 0.8;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
[ngComboboxInput][aria-expanded='true'] + .docs-select-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
[ngComboboxInput] {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
padding: 0.7rem 1rem 0.7rem 2.5rem;
|
||||
background-color: var(--septenary-contrast);
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
|
||||
.docs-select-dialog {
|
||||
position: absolute;
|
||||
left: auto;
|
||||
right: auto;
|
||||
top: auto;
|
||||
bottom: auto;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--septenary-contrast);
|
||||
color: inherit;
|
||||
|
||||
.docs-select-input-container {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[ngCombobox],
|
||||
.docs-select-input-container {
|
||||
border: none;
|
||||
}
|
||||
|
||||
[ngComboboxInput] {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
[ngCombobox]:focus-within [ngComboboxInput] {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.docs-select-search-input:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.docs-select-search-container {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
&::backdrop {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-select-search-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.docs-select-search-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 20px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.docs-select-search-input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 0.875rem;
|
||||
padding: 0.5rem 0.75rem 0.5rem 2rem;
|
||||
background-color: var(--septenary-contrast);
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
|
||||
.docs-select-no-results {
|
||||
padding: 0.75rem;
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
color: var(--primary-contrast);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.docs-select-listbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 12rem;
|
||||
overflow: auto;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.docs-select-option {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in srgb, var(--primary-contrast) 5%, transparent);
|
||||
}
|
||||
|
||||
&[data-active='true'] {
|
||||
outline-offset: -2px;
|
||||
outline: 2px solid var(--vivid-pink);
|
||||
}
|
||||
|
||||
&[aria-selected='true'] {
|
||||
color: var(--vivid-pink);
|
||||
background-color: color-mix(in srgb, var(--vivid-pink) 5%, transparent);
|
||||
}
|
||||
|
||||
&:not([aria-selected='true']) .docs-select-check-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-select-option-label {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.docs-select-check-icon {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,26 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, input, model} from '@angular/core';
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxDialog,
|
||||
ComboboxInput,
|
||||
ComboboxPopupContainer,
|
||||
} from '@angular/aria/combobox';
|
||||
import {Listbox, Option} from '@angular/aria/listbox';
|
||||
import {
|
||||
afterRenderEffect,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
input,
|
||||
model,
|
||||
signal,
|
||||
untracked,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import {FormValueControl} from '@angular/forms/signals';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
type SelectOptionValue = string | number | boolean;
|
||||
|
||||
@@ -19,11 +37,17 @@ export interface SelectOption {
|
||||
@Component({
|
||||
selector: 'docs-select',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
Combobox,
|
||||
ComboboxDialog,
|
||||
ComboboxInput,
|
||||
ComboboxPopupContainer,
|
||||
FormsModule,
|
||||
Listbox,
|
||||
Option,
|
||||
],
|
||||
templateUrl: './select.component.html',
|
||||
styleUrls: ['./select.component.scss'],
|
||||
host: {
|
||||
class: 'docs-form-element',
|
||||
},
|
||||
})
|
||||
export class Select implements FormValueControl<string | null> {
|
||||
readonly value = model<string | null>(null);
|
||||
@@ -33,11 +57,66 @@ export class Select implements FormValueControl<string | null> {
|
||||
readonly options = input.required<SelectOption[]>();
|
||||
readonly disabled = input(false);
|
||||
|
||||
setOption($event: SelectOptionValue): void {
|
||||
if (this.disabled()) {
|
||||
readonly dialog = viewChild(ComboboxDialog);
|
||||
readonly listbox = viewChild<Listbox<SelectOptionValue>>(Listbox);
|
||||
readonly combobox = viewChild<Combobox<SelectOptionValue>>(Combobox);
|
||||
|
||||
readonly searchString = signal('');
|
||||
|
||||
readonly filteredOptions = computed(() => {
|
||||
const search = this.searchString().toLowerCase();
|
||||
if (!search) {
|
||||
return this.options();
|
||||
}
|
||||
return this.options().filter((option) => option.label.toLowerCase().includes(search));
|
||||
});
|
||||
|
||||
readonly displayValue = computed(() => {
|
||||
const currentValue = this.value();
|
||||
if (currentValue === null) {
|
||||
return '';
|
||||
}
|
||||
const option = this.options().find((opt) => opt.value === currentValue);
|
||||
return option ? option.label : '';
|
||||
});
|
||||
|
||||
readonly selectedValues = signal<SelectOptionValue[]>([]);
|
||||
|
||||
constructor() {
|
||||
afterRenderEffect(() => {
|
||||
if (this.dialog() && this.combobox()?.expanded()) {
|
||||
untracked(() => this.listbox()?.gotoFirst());
|
||||
this.positionDialog();
|
||||
}
|
||||
});
|
||||
|
||||
afterRenderEffect(() => {
|
||||
const selected = this.selectedValues();
|
||||
if (selected.length > 0) {
|
||||
untracked(() => this.dialog()?.close());
|
||||
this.value.set(selected[0] as string);
|
||||
this.searchString.set('');
|
||||
}
|
||||
});
|
||||
|
||||
afterRenderEffect(() => this.listbox()?.scrollActiveItemIntoView());
|
||||
}
|
||||
// TODO: Improve once CDK overlay is fixed https://github.com/angular/components/issues/32504
|
||||
private positionDialog(): void {
|
||||
const dialog = this.dialog();
|
||||
const combobox = this.combobox();
|
||||
|
||||
if (!dialog || !combobox) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.value.set($event as string);
|
||||
const comboboxRect = combobox.inputElement()?.getBoundingClientRect();
|
||||
const scrollY = window.scrollY;
|
||||
|
||||
if (comboboxRect) {
|
||||
dialog.element.style.width = `${comboboxRect.width}px`;
|
||||
dialog.element.style.top = `${comboboxRect.bottom + scrollY + 4}px`;
|
||||
dialog.element.style.left = `${comboboxRect.left}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,32 @@ describe('TabGroup', () => {
|
||||
expect(tabs[0].textContent.trim()).toBe('tab 1');
|
||||
expect(tabpanels[0].textContent.trim()).toBe('panel 1');
|
||||
});
|
||||
|
||||
it('should generate unique ids for tabs and tabpanels', async () => {
|
||||
const testPanel1 = document.createElement('div');
|
||||
testPanel1.textContent = 'panel 1';
|
||||
const testPanel2 = document.createElement('div');
|
||||
testPanel2.textContent = 'panel 2';
|
||||
fixture.componentRef.setInput('tabs', [
|
||||
{label: 'tab 1', panel: testPanel1},
|
||||
{label: 'tab 2', panel: testPanel2},
|
||||
]);
|
||||
await fixture.whenStable();
|
||||
|
||||
const tabs = fixture.nativeElement.querySelectorAll('.docs-tab');
|
||||
const tabpanels = fixture.nativeElement.querySelectorAll('.docs-tab-panel');
|
||||
expect(tabs[0].id).not.toBe(tabs[1].id);
|
||||
expect(tabpanels[0].id).not.toBe(tabpanels[1].id);
|
||||
|
||||
const fixture2 = TestBed.createComponent(TabGroup);
|
||||
fixture2.componentRef.setInput('tabs', [
|
||||
{label: 'tab 1', panel: testPanel1},
|
||||
{label: 'tab 2', panel: testPanel2},
|
||||
]);
|
||||
await fixture2.whenStable();
|
||||
const tabs2 = fixture2.nativeElement.querySelectorAll('.docs-tab');
|
||||
const tabpanels2 = fixture2.nativeElement.querySelectorAll('.docs-tab-panel');
|
||||
expect(tabs[0].id).not.toBe(tabs2[0].id);
|
||||
expect(tabpanels[0].id).not.toBe(tabpanels2[0].id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,18 +7,19 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
input,
|
||||
inject,
|
||||
computed,
|
||||
linkedSignal,
|
||||
viewChildren,
|
||||
afterRenderEffect,
|
||||
Renderer2,
|
||||
ElementRef,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
ElementRef,
|
||||
inject,
|
||||
input,
|
||||
linkedSignal,
|
||||
Renderer2,
|
||||
viewChildren,
|
||||
} from '@angular/core';
|
||||
import {_IdGenerator} from '@angular/cdk/a11y';
|
||||
|
||||
let idCounter = 0;
|
||||
|
||||
/**
|
||||
* A simple tabs implementation with proper aria roles.
|
||||
@@ -36,20 +37,24 @@ import {_IdGenerator} from '@angular/cdk/a11y';
|
||||
})
|
||||
export class TabGroup {
|
||||
private readonly _renderer = inject(Renderer2);
|
||||
private readonly _idGenerator = inject(_IdGenerator);
|
||||
private readonly _tabpanels = viewChildren<ElementRef<HTMLDivElement>>('tabpanel');
|
||||
|
||||
readonly tabs = input<{label: string; panel: HTMLElement}[]>();
|
||||
|
||||
readonly computedTabs = computed(
|
||||
() =>
|
||||
this.tabs()?.map((tab) => ({
|
||||
tabId: this._idGenerator.getId('docs-tab-'),
|
||||
tabPanelId: this._idGenerator.getId('docs-tab-panel-'),
|
||||
label: tab.label,
|
||||
panel: tab.panel,
|
||||
})) ?? [],
|
||||
);
|
||||
readonly computedTabs = computed(() => {
|
||||
return (
|
||||
this.tabs()?.map((tab) => {
|
||||
const id = idCounter++;
|
||||
|
||||
return {
|
||||
tabId: `docs-tab-${id}`,
|
||||
tabPanelId: `docs-tab-panel-${id}`,
|
||||
label: tab.label,
|
||||
panel: tab.panel,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
});
|
||||
|
||||
readonly selectedTab = linkedSignal(() => this.computedTabs()[0]?.tabId);
|
||||
|
||||
|
||||
@@ -8,11 +8,19 @@
|
||||
top: 0;
|
||||
height: fit-content;
|
||||
width: 14rem;
|
||||
padding-right: 2rem;
|
||||
padding-right: 1rem;
|
||||
max-height: 100vh;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include mq.for-large-desktop-up {
|
||||
width: 16rem;
|
||||
}
|
||||
|
||||
@include mq.for-extra-large-desktop-up {
|
||||
width: 25rem;
|
||||
}
|
||||
|
||||
aside {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import {IconComponent} from '../icon/icon.component';
|
||||
class: 'docs-form-element',
|
||||
},
|
||||
})
|
||||
export class TextField implements FormValueControl<string | null> {
|
||||
export class TextField implements FormValueControl<string> {
|
||||
readonly input = viewChild.required<ElementRef<HTMLInputElement>>('inputRef');
|
||||
readonly name = input<string>('');
|
||||
readonly value = model<string | null>(null);
|
||||
readonly value = model<string>('');
|
||||
readonly placeholder = input<string | null>(null);
|
||||
readonly disabled = model<boolean>(false);
|
||||
readonly hideIcon = input<boolean>(false);
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
height: fit-content;
|
||||
|
||||
docs-icon {
|
||||
color: var(--gray-400);
|
||||
color: var(--quaternary-contrast);
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
fill="var(--gray-400)"
|
||||
fill="var(--quaternary-contrast)"
|
||||
d="M3.4 22 2 20.6 8.6 14H4v-2h8v8h-2v-4.6L3.4 22ZM12 12V4h2v4.6L20.6 2 22 3.4 15.4 10H20v2h-8Z"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
.docs-example-viewer-preview {
|
||||
.docs-dark-mode & {
|
||||
color: var(--primary-contrast);
|
||||
background: var(--gray-900);
|
||||
background: var(--primary-constrast);
|
||||
}
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
color: var(--primary-contrast);
|
||||
background: var(--gray-900);
|
||||
background: var(--primary-constrast);
|
||||
}
|
||||
.docs-light-mode & {
|
||||
background: var(--page-background);
|
||||
@@ -70,7 +70,7 @@
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
color: var(--gray-400);
|
||||
color: var(--quaternary-contrast);
|
||||
|
||||
path {
|
||||
transition: fill 0.3s ease;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import {
|
||||
afterNextRender,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
computed,
|
||||
ElementRef,
|
||||
@@ -20,13 +19,13 @@ import {
|
||||
Type,
|
||||
} from '@angular/core';
|
||||
import {DOCUMENT, NgComponentOutlet, NgTemplateOutlet} from '@angular/common';
|
||||
import {MatTabsModule} from '@angular/material/tabs';
|
||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {CopySourceCodeButton} from '../../copy-source-code-button/copy-source-code-button.component';
|
||||
import {IconComponent} from '../../icon/icon.component';
|
||||
import {ExampleMetadata, Snippet} from '../../../interfaces/index';
|
||||
import {EXAMPLE_VIEWER_CONTENT_LOADER} from '../../../providers/index';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
import {MatTooltip} from '@angular/material/tooltip';
|
||||
|
||||
export const CODE_LINE_NUMBER_CLASS_NAME = 'shiki-ln-number';
|
||||
export const CODE_LINE_CLASS_NAME = 'line';
|
||||
@@ -37,8 +36,9 @@ export const HIDDEN_CLASS_NAME = 'hidden';
|
||||
selector: 'docs-example-viewer',
|
||||
imports: [
|
||||
CopySourceCodeButton,
|
||||
MatTabsModule,
|
||||
MatTooltipModule,
|
||||
MatTabGroup,
|
||||
MatTab,
|
||||
MatTooltip,
|
||||
IconComponent,
|
||||
NgTemplateOutlet,
|
||||
NgComponentOutlet,
|
||||
|
||||
@@ -5,9 +5,15 @@ load("//adev/shared-docs/pipeline:_previews.bzl", _generate_previews = "generate
|
||||
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_previews = _generate_previews
|
||||
generate_playground = _generate_playground
|
||||
generate_tutorial = _generate_tutorial
|
||||
generate_nav_items = _generate_nav_items
|
||||
|
||||
def generate_guides(**kwargs):
|
||||
_generate_guides(
|
||||
api_manifest = "//adev/src/assets:docs_api_manifest",
|
||||
defined_routes = "//adev/scripts/routes:defined-routes.json",
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
"name": "@angular/docs",
|
||||
"version": "0.0.0-PLACEHOLDER",
|
||||
"peerDependencies": {
|
||||
"@angular/cdk": "^21.1.0-next",
|
||||
"@angular/common": "^21.1.0-next",
|
||||
"@angular/core": "^21.1.0-next",
|
||||
"@angular/forms": "^21.1.0-next",
|
||||
"@angular/material": "^21.1.0-next",
|
||||
"@angular/platform-browser": "^21.1.0-next",
|
||||
"@angular/router": "^21.1.0-next",
|
||||
"@angular/ssr": "^21.1.0-next",
|
||||
"@angular/cdk": "^21.2.0-next",
|
||||
"@angular/common": "^21.2.0-next",
|
||||
"@angular/core": "^21.2.0-next",
|
||||
"@angular/forms": "^21.2.0-next",
|
||||
"@angular/material": "^21.2.0-next",
|
||||
"@angular/platform-browser": "^21.2.0-next",
|
||||
"@angular/router": "^21.2.0-next",
|
||||
"@angular/ssr": "^21.2.0-next",
|
||||
"algoliasearch": "^5.0.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
@@ -18,7 +18,7 @@
|
||||
"diff": "~8.0.0",
|
||||
"emoji-regex": "~10.6.0",
|
||||
"fflate": "^0.8.2",
|
||||
"jsdom": "~27.4.0",
|
||||
"jsdom": "~28.0.0",
|
||||
"marked": "~17.0.0",
|
||||
"mermaid": "^11.0.0",
|
||||
"shiki": "^3.0.0",
|
||||
|
||||
@@ -47,6 +47,7 @@ js_binary(
|
||||
"//adev:node_modules/jsdom",
|
||||
"//adev:node_modules/mermaid",
|
||||
"//adev:node_modules/playwright-core",
|
||||
"//adev:node_modules/typescript",
|
||||
"@rules_browsers//browsers/chromium",
|
||||
],
|
||||
entry_point = "//adev/shared-docs/pipeline/guides:guides.mjs",
|
||||
@@ -61,6 +62,7 @@ js_binary(
|
||||
name = "markdown_no_mermaid",
|
||||
data = [
|
||||
"//adev:node_modules/jsdom",
|
||||
"//adev:node_modules/typescript",
|
||||
],
|
||||
entry_point = "//adev/shared-docs/pipeline/guides:guides-no-mermaid.mjs",
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
@@ -22,6 +22,11 @@ def _generate_guides(ctx):
|
||||
else:
|
||||
args.add("")
|
||||
|
||||
if ctx.attr.defined_routes:
|
||||
args.add(ctx.file.defined_routes.path)
|
||||
else:
|
||||
args.add("")
|
||||
|
||||
# Determine the set of html output files. For each input markdown file, produce an html
|
||||
# file with the same name (replacing the markdown extension with `.html`).
|
||||
html_outputs = []
|
||||
@@ -39,6 +44,8 @@ def _generate_guides(ctx):
|
||||
inputs = ctx.files.srcs + ctx.files.data
|
||||
if ctx.attr.api_manifest:
|
||||
inputs.append(ctx.file.api_manifest)
|
||||
if ctx.attr.defined_routes:
|
||||
inputs.append(ctx.file.defined_routes)
|
||||
|
||||
if (ctx.attr.mermaid_blocks):
|
||||
ctx.actions.run(
|
||||
@@ -85,6 +92,10 @@ generate_guides = rule(
|
||||
doc = """A file containing API entries to be used in the markdown.""",
|
||||
allow_single_file = True,
|
||||
),
|
||||
"defined_routes": attr.label(
|
||||
doc = """List of defined routes.""",
|
||||
allow_single_file = [".json"],
|
||||
),
|
||||
"mermaid_blocks": attr.bool(
|
||||
doc = """Whether to transform mermaid blocks.""",
|
||||
default = False,
|
||||
|
||||
@@ -7,6 +7,7 @@ esbuild(
|
||||
entry_point = ":index.mts",
|
||||
external = [
|
||||
"@angular/compiler-cli",
|
||||
"typescript",
|
||||
],
|
||||
format = "esm",
|
||||
output = "bin.mjs",
|
||||
|
||||
@@ -8,6 +8,7 @@ esbuild(
|
||||
external = [
|
||||
"jsdom",
|
||||
"playwright-core",
|
||||
"typescript",
|
||||
],
|
||||
format = "esm",
|
||||
output = "bin.mjs",
|
||||
|
||||
@@ -126,11 +126,11 @@ export interface EnumEntry extends DocEntry {
|
||||
/** Documentation entity for an Angular decorator. */
|
||||
export interface DecoratorEntry extends DocEntry {
|
||||
decoratorType: DecoratorType;
|
||||
members: PropertyEntry[] | null;
|
||||
signatures?: {
|
||||
parameters: ParameterEntry[];
|
||||
jsdocTags: JsDocTagEntry[];
|
||||
}[];
|
||||
members: MemberEntry[];
|
||||
}
|
||||
|
||||
/** Documentation entity for an Angular directives and components. */
|
||||
@@ -161,6 +161,9 @@ export type FunctionEntry = FunctionDefinitionEntry &
|
||||
implementation: FunctionSignatureMetadata;
|
||||
};
|
||||
|
||||
/** Documentation entity for a block. */
|
||||
export interface BlockEntry extends DocEntry {}
|
||||
|
||||
/** Interface describing a function with overload signatures. */
|
||||
export interface FunctionDefinitionEntry {
|
||||
name: string;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
BlockEntry,
|
||||
ClassEntry,
|
||||
ConstantEntry,
|
||||
DecoratorEntry,
|
||||
@@ -27,6 +28,7 @@ import {
|
||||
import {CliCommand} from '../cli-entities.mjs';
|
||||
|
||||
import {
|
||||
BlockEntryRenderable,
|
||||
ClassEntryRenderable,
|
||||
ConstantEntryRenderable,
|
||||
DecoratorEntryRenderable,
|
||||
@@ -107,6 +109,13 @@ export function isFunctionEntry(entry: DocEntry): entry is FunctionEntry {
|
||||
return entry.entryType === EntryType.Function;
|
||||
}
|
||||
|
||||
/** Gets whether the given entry represents a block */
|
||||
export function isBlockEntry(entry: DocEntryRenderable): entry is BlockEntryRenderable;
|
||||
export function isBlockEntry(entry: DocEntry): entry is BlockEntry;
|
||||
export function isBlockEntry(entry: DocEntry): entry is BlockEntry {
|
||||
return entry.entryType === EntryType.Block;
|
||||
}
|
||||
|
||||
export function isInitializerApiFunctionEntry(
|
||||
entry: DocEntryRenderable,
|
||||
): entry is InitializerApiFunctionRenderable;
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
ParameterEntry,
|
||||
PipeEntry,
|
||||
TypeAliasEntry,
|
||||
EntryType,
|
||||
} from '../entities.mjs';
|
||||
|
||||
import {CliCommand, CliOption} from '../cli-entities.mjs';
|
||||
@@ -75,7 +76,11 @@ export type PipeEntryRenderable = PipeEntry &
|
||||
members: MemberEntryRenderable[];
|
||||
};
|
||||
|
||||
export type DecoratorEntryRenderable = DecoratorEntry & DocEntryRenderable & HasRenderableToc;
|
||||
export type DecoratorEntryRenderable = Omit<DecoratorEntry, 'members'> &
|
||||
DocEntryRenderable &
|
||||
HasRenderableToc & {
|
||||
members: PropertyEntryRenderable[];
|
||||
};
|
||||
|
||||
/** Documentation entity for a TypeScript enum augmented transformed content for rendering. */
|
||||
export type EnumEntryRenderable = EnumEntry &
|
||||
@@ -102,6 +107,9 @@ export type FunctionSignatureMetadataRenderable = FunctionSignatureMetadata &
|
||||
params: ParameterEntryRenderable[];
|
||||
};
|
||||
|
||||
/** Documentation entity for a block augmented with transformed content for rendering. */
|
||||
export type BlockEntryRenderable = DocEntry & DocEntryRenderable;
|
||||
|
||||
/** Sub-entry for a single class or enum member augmented with transformed content for rendering. */
|
||||
export interface MemberEntryRenderable extends MemberEntry {
|
||||
htmlDescription: string;
|
||||
@@ -116,6 +124,10 @@ export interface MemberEntryRenderable extends MemberEntry {
|
||||
experimental: {version: string | undefined} | undefined;
|
||||
}
|
||||
|
||||
export interface PropertyEntryRenderable extends MemberEntryRenderable {
|
||||
type: string;
|
||||
}
|
||||
|
||||
/** Sub-entry for a class method augmented transformed content for rendering. */
|
||||
export type MethodEntryRenderable = MemberEntryRenderable &
|
||||
FunctionEntryRenderable & {
|
||||
@@ -155,11 +167,9 @@ export type CliCommandRenderable = CliCommand & {
|
||||
htmlDescription: string;
|
||||
cards: CliCardRenderable[];
|
||||
argumentsLabel: string;
|
||||
hasOptions: boolean;
|
||||
optionsLabel: string;
|
||||
subcommands?: CliCommandRenderable[];
|
||||
};
|
||||
|
||||
export interface InitializerApiFunctionRenderable
|
||||
extends Omit<InitializerApiFunctionEntry, 'jsdocTags'>,
|
||||
DocEntryRenderable,
|
||||
HasRenderableToc {}
|
||||
extends Omit<InitializerApiFunctionEntry, 'jsdocTags'>, DocEntryRenderable, HasRenderableToc {}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {JsDocTagEntry, MemberEntry, ParameterEntry} from '../entities.mjs';
|
||||
import {JsDocTagEntry, MemberEntry, ParameterEntry, PropertyEntry} from '../entities.mjs';
|
||||
|
||||
import {
|
||||
CodeLineRenderable,
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
LinkEntryRenderable,
|
||||
MemberEntryRenderable,
|
||||
ParameterEntryRenderable,
|
||||
PropertyEntryRenderable,
|
||||
} from './renderables.mjs';
|
||||
|
||||
/** A doc entry that has jsdoc tags. */
|
||||
@@ -21,6 +22,10 @@ export interface HasJsDocTags {
|
||||
jsdocTags: JsDocTagEntry[];
|
||||
}
|
||||
|
||||
export interface MaybeJsDocTags {
|
||||
jsdocTags?: JsDocTagEntry[];
|
||||
}
|
||||
|
||||
export interface HasAdditionalLinks {
|
||||
additionalLinks: LinkEntryRenderable[];
|
||||
}
|
||||
@@ -56,6 +61,10 @@ export interface HasMembers {
|
||||
members: MemberEntry[];
|
||||
}
|
||||
|
||||
export interface HasPropertyMembers {
|
||||
members: PropertyEntry[];
|
||||
}
|
||||
|
||||
/** A doc entry that has members groups transformed for rendering. */
|
||||
export interface HasRenderableMembersGroups {
|
||||
membersGroups: Map<string, MemberEntryRenderable[]>;
|
||||
@@ -66,6 +75,10 @@ export interface HasRenderableMembers {
|
||||
members: MemberEntryRenderable[];
|
||||
}
|
||||
|
||||
export interface HasRenderablePropertyMembers {
|
||||
members: PropertyEntryRenderable[];
|
||||
}
|
||||
|
||||
/** A doc entry that has an associated JS module name. */
|
||||
export interface HasModuleName {
|
||||
moduleName: string;
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
isInitializerApiFunctionEntry,
|
||||
isInterfaceEntry,
|
||||
isTypeAliasEntry,
|
||||
isBlockEntry,
|
||||
} from './entities/categorization.mjs';
|
||||
import {CliCommandRenderable, DocEntryRenderable} from './entities/renderables.mjs';
|
||||
import {getClassRenderable} from './transforms/class-transforms.mjs';
|
||||
@@ -39,6 +40,7 @@ import {
|
||||
import {addModuleName} from './transforms/module-name.mjs';
|
||||
import {addRepo} from './transforms/repo.mjs';
|
||||
import {getTypeAliasRenderable} from './transforms/type-alias-transforms.mjs';
|
||||
import {getBlockRenderable} from './transforms/block-transforms.mjs';
|
||||
|
||||
export async function getRenderable(
|
||||
entry: DocEntry | CliCommand,
|
||||
@@ -73,6 +75,9 @@ export async function getRenderable(
|
||||
if (isInitializerApiFunctionEntry(entry)) {
|
||||
return getInitializerApiFunctionRenderable(entry, moduleName, repo);
|
||||
}
|
||||
if (isBlockEntry(entry)) {
|
||||
return getBlockRenderable(entry, moduleName, repo);
|
||||
}
|
||||
|
||||
// Fallback to an uncategorized renderable.
|
||||
return setEntryFlags(
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
isInitializerApiFunctionEntry,
|
||||
isInterfaceEntry,
|
||||
isTypeAliasEntry,
|
||||
isBlockEntry,
|
||||
} from './entities/categorization.mjs';
|
||||
import {CliCommandRenderable, DocEntryRenderable} from './entities/renderables.mjs';
|
||||
import {ClassReference} from './templates/class-reference';
|
||||
@@ -30,6 +31,7 @@ import {InitializerApiFunction} from './templates/initializer-api-function';
|
||||
import {TypeAliasReference} from './templates/type-alias-reference';
|
||||
import {DecoratorReference} from './templates/decorator-reference';
|
||||
import {setCurrentSymbol} from './symbol-context.mjs';
|
||||
import {BlockReference} from './templates/block-reference';
|
||||
|
||||
/** Given a doc entry, get the transformed version of the entry for rendering. */
|
||||
export function renderEntry(renderable: DocEntryRenderable | CliCommandRenderable): string {
|
||||
@@ -59,6 +61,9 @@ export function renderEntry(renderable: DocEntryRenderable | CliCommandRenderabl
|
||||
if (isInitializerApiFunctionEntry(renderable)) {
|
||||
return render(InitializerApiFunction(renderable));
|
||||
}
|
||||
if (isBlockEntry(renderable)) {
|
||||
return render(BlockReference(renderable));
|
||||
}
|
||||
|
||||
// Fall back rendering nothing while in development.
|
||||
return render(DocsReference(renderable));
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*!
|
||||
* @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 {BlockEntryRenderable} from '../entities/renderables.mjs';
|
||||
import {HeaderApi} from './header-api';
|
||||
import {RawHtml} from './raw-html';
|
||||
import {API_REFERENCE_CONTAINER} from '../styling/css-classes.mjs';
|
||||
|
||||
/** Component to render a block API reference document. */
|
||||
export function BlockReference(entry: BlockEntryRenderable) {
|
||||
return (
|
||||
<div className={API_REFERENCE_CONTAINER}>
|
||||
<HeaderApi entry={entry} hideDescription={true} />
|
||||
<RawHtml value={entry.htmlDescription} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -12,15 +12,18 @@ import {
|
||||
ParameterEntryRenderable,
|
||||
} from '../entities/renderables.mjs';
|
||||
import {PARAM_KEYWORD_CLASS_NAME, REFERENCE_MEMBER_CARD_ITEM} from '../styling/css-classes.mjs';
|
||||
import {CodeSymbol} from './code-symbols';
|
||||
import {DeprecatedLabel} from './deprecated-label';
|
||||
import {Parameter} from './parameter';
|
||||
import {RawHtml} from './raw-html';
|
||||
import {CodeSymbol} from './code-symbols';
|
||||
|
||||
/**
|
||||
* Component to render the method-specific parts of a class's API reference.
|
||||
*/
|
||||
export function ClassMethodInfo(props: {entry: FunctionSignatureMetadataRenderable}) {
|
||||
export function ClassMethodInfo(props: {
|
||||
entry: FunctionSignatureMetadataRenderable;
|
||||
hideUsageNotes?: boolean;
|
||||
}) {
|
||||
const entry = props.entry;
|
||||
|
||||
return (
|
||||
@@ -43,7 +46,7 @@ export function ClassMethodInfo(props: {entry: FunctionSignatureMetadataRenderab
|
||||
<span className={PARAM_KEYWORD_CLASS_NAME}>@returns</span>
|
||||
<CodeSymbol code={entry.returnType} />
|
||||
</div>
|
||||
{entry.htmlUsageNotes ? (
|
||||
{entry.htmlUsageNotes && !props.hideUsageNotes ? (
|
||||
<div className={'docs-usage-notes'}>
|
||||
<span className={'docs-usage-notes-heading'}>Usage notes</span>
|
||||
<RawHtml value={entry.htmlUsageNotes} />
|
||||
|
||||
@@ -28,6 +28,7 @@ import {RawHtml} from './raw-html';
|
||||
import {DeprecationWarning} from './deprecation-warning';
|
||||
import {codeToHtml} from '../../../shared/shiki.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {getSymbolsAsApiEntries} from '../symbol-context.mjs';
|
||||
|
||||
/** Component to render a class API reference document. */
|
||||
export function ClassReference(
|
||||
@@ -43,6 +44,7 @@ export function ClassReference(
|
||||
<RawHtml
|
||||
value={codeToHtml(getHighlighterInstance(), (entry as PipeEntry).usage, {
|
||||
language: 'angular-html',
|
||||
apiEntries: getSymbolsAsApiEntries(),
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -26,19 +26,15 @@ export function CliCommandReference(entry: CliCommandRenderable) {
|
||||
<code>
|
||||
<div className={'shiki line cli'}>
|
||||
ng {commandName(entry, command)}
|
||||
{entry.argumentsLabel ? (
|
||||
{entry.argumentsLabel && (
|
||||
<button member-id={'Arguments'} className="shiki-ln-line-argument">
|
||||
{entry.argumentsLabel}
|
||||
</button>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{entry.hasOptions ? (
|
||||
{entry.optionsLabel && (
|
||||
<button member-id={'Options'} className="shiki-ln-line-option">
|
||||
[options]
|
||||
{entry.optionsLabel}
|
||||
</button>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</code>
|
||||
|
||||
@@ -7,12 +7,45 @@
|
||||
*/
|
||||
|
||||
import {h} from 'preact';
|
||||
import {DecoratorEntryRenderable, PropertyEntryRenderable} from '../entities/renderables.mjs';
|
||||
import {
|
||||
API_REFERENCE_CONTAINER,
|
||||
REFERENCE_MEMBER_CARD,
|
||||
REFERENCE_MEMBER_CARD_BODY,
|
||||
REFERENCE_MEMBER_CARD_HEADER,
|
||||
REFERENCE_MEMBER_CARD_ITEM,
|
||||
REFERENCE_MEMBERS,
|
||||
} from '../styling/css-classes.mjs';
|
||||
import {CodeSymbol} from './code-symbols';
|
||||
import {HeaderApi} from './header-api';
|
||||
import {RawHtml} from './raw-html';
|
||||
import {SectionApi} from './section-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.mjs';
|
||||
import {DecoratorEntryRenderable} from '../entities/renderables.mjs';
|
||||
|
||||
export const signatureCard = (
|
||||
name: string,
|
||||
member: PropertyEntryRenderable,
|
||||
opts: {id: string},
|
||||
) => {
|
||||
return (
|
||||
<div id={opts.id} class={REFERENCE_MEMBER_CARD}>
|
||||
<header class={REFERENCE_MEMBER_CARD_HEADER}>
|
||||
<h3>{name}</h3>
|
||||
<div>
|
||||
<CodeSymbol code={member.type} />
|
||||
</div>
|
||||
</header>
|
||||
<div class={REFERENCE_MEMBER_CARD_BODY}>
|
||||
<div className={`${REFERENCE_MEMBER_CARD_ITEM}`}>
|
||||
<p>
|
||||
<RawHtml value={member.htmlDescription} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/** Component to render a decorator API reference document. */
|
||||
export function DecoratorReference(entry: DecoratorEntryRenderable) {
|
||||
@@ -20,6 +53,13 @@ export function DecoratorReference(entry: DecoratorEntryRenderable) {
|
||||
<div className={API_REFERENCE_CONTAINER}>
|
||||
<HeaderApi entry={entry} />
|
||||
<SectionApi entry={entry} />
|
||||
<div className={REFERENCE_MEMBERS}>
|
||||
{entry.members.map((member, index) =>
|
||||
signatureCard(member.name, member, {
|
||||
id: `${member.name}_${index}`,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
<SectionDescription entry={entry} />
|
||||
<SectionUsageNotes entry={entry} />
|
||||
</div>
|
||||
|
||||
@@ -22,23 +22,22 @@ import {printInitializerFunctionSignatureLine} from '../transforms/code-transfor
|
||||
import {getFunctionMetadataRenderable} from '../transforms/function-transforms.mjs';
|
||||
import {ClassMethodInfo} from './class-method-info';
|
||||
import {CodeSymbol} from './code-symbols';
|
||||
import {DeprecationWarning} from './deprecation-warning';
|
||||
import {HeaderApi} from './header-api';
|
||||
import {HighlightTypeScript} from './highlight-ts';
|
||||
import {SectionApi} from './section-api';
|
||||
import {SectionDescription} from './section-description';
|
||||
import {SectionUsageNotes} from './section-usage-notes';
|
||||
import {DeprecationWarning} from './deprecation-warning';
|
||||
|
||||
export const signatureCard = (
|
||||
name: string,
|
||||
signature: FunctionSignatureMetadataRenderable,
|
||||
opts: {id: string},
|
||||
printSignaturesAsHeader: boolean,
|
||||
opts: {id: string; printSignaturesAsHeader: boolean; hideUsageNotes?: boolean},
|
||||
) => {
|
||||
return (
|
||||
<div id={opts.id} class={REFERENCE_MEMBER_CARD}>
|
||||
<header class={REFERENCE_MEMBER_CARD_HEADER}>
|
||||
{printSignaturesAsHeader ? (
|
||||
{opts.printSignaturesAsHeader ? (
|
||||
<HighlightTypeScript
|
||||
code={printInitializerFunctionSignatureLine(
|
||||
name,
|
||||
@@ -57,7 +56,7 @@ export const signatureCard = (
|
||||
)}
|
||||
</header>
|
||||
<div class={REFERENCE_MEMBER_CARD_BODY}>
|
||||
<ClassMethodInfo entry={signature} />
|
||||
<ClassMethodInfo entry={signature} hideUsageNotes={opts.hideUsageNotes} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -74,16 +73,14 @@ export function FunctionReference(entry: FunctionEntryRenderable) {
|
||||
<DeprecationWarning entry={entry} />
|
||||
<SectionApi entry={entry} />
|
||||
<div className={REFERENCE_MEMBERS}>
|
||||
{entry.signatures.map((s, i) =>
|
||||
signatureCard(
|
||||
s.name,
|
||||
getFunctionMetadataRenderable(s, entry.moduleName, entry.repo),
|
||||
{
|
||||
{entry.signatures.length > 1 &&
|
||||
entry.signatures.map((s, i) =>
|
||||
signatureCard(s.name, getFunctionMetadataRenderable(s, entry.moduleName, entry.repo), {
|
||||
id: `${s.name}_${i}`,
|
||||
},
|
||||
printSignaturesAsHeader,
|
||||
),
|
||||
)}
|
||||
printSignaturesAsHeader,
|
||||
hideUsageNotes: true,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
|
||||
<SectionDescription entry={entry} />
|
||||
|
||||
@@ -21,6 +21,7 @@ import {DocsPillRow} from './docs-pill-row';
|
||||
export function HeaderApi(props: {
|
||||
entry: DocEntryRenderable | PipeEntryRenderable;
|
||||
showFullDescription?: boolean;
|
||||
hideDescription?: boolean;
|
||||
}) {
|
||||
const entry = props.entry;
|
||||
|
||||
@@ -60,12 +61,14 @@ export function HeaderApi(props: {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<section
|
||||
className={'docs-reference-description'}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: props.showFullDescription ? entry.htmlDescription : entry.shortHtmlDescription,
|
||||
}}
|
||||
></section>
|
||||
{!props.hideDescription && (
|
||||
<section
|
||||
className={'docs-reference-description'}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: props.showFullDescription ? entry.htmlDescription : entry.shortHtmlDescription,
|
||||
}}
|
||||
></section>
|
||||
)}
|
||||
|
||||
<DocsPillRow links={entry.additionalLinks} />
|
||||
</header>
|
||||
|
||||
@@ -10,10 +10,14 @@ import {h} from 'preact';
|
||||
import {RawHtml} from './raw-html';
|
||||
import {codeToHtml} from '../../../shared/shiki.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {getSymbolsAsApiEntries} from '../symbol-context.mjs';
|
||||
|
||||
/** Component to render a header of the CLI page. */
|
||||
export function HighlightTypeScript(props: {code: string}) {
|
||||
const result = codeToHtml(getHighlighterInstance(), props.code, {language: 'typescript'});
|
||||
const result = codeToHtml(getHighlighterInstance(), props.code, {
|
||||
language: 'typescript',
|
||||
apiEntries: getSymbolsAsApiEntries(),
|
||||
});
|
||||
const withScrollTrack = result.replace(/^(<pre class="shiki)/, '$1 docs-mini-scroll-track');
|
||||
|
||||
return <RawHtml value={withScrollTrack} className="docs-code" />;
|
||||
|
||||
@@ -40,14 +40,10 @@ export function InitializerApiFunction(entry: InitializerApiFunctionRenderable)
|
||||
|
||||
<div class={REFERENCE_MEMBERS}>
|
||||
{entry.callFunction.signatures.map((s, i) =>
|
||||
signatureCard(
|
||||
s.name,
|
||||
getFunctionMetadataRenderable(s, entry.moduleName, entry.repo),
|
||||
{
|
||||
id: `${s.name}_${i}`,
|
||||
},
|
||||
signatureCard(s.name, getFunctionMetadataRenderable(s, entry.moduleName, entry.repo), {
|
||||
id: `${s.name}_${i}`,
|
||||
printSignaturesAsHeader,
|
||||
),
|
||||
}),
|
||||
)}
|
||||
|
||||
{entry.subFunctions.reduce(
|
||||
@@ -59,8 +55,8 @@ export function InitializerApiFunction(entry: InitializerApiFunctionRenderable)
|
||||
getFunctionMetadataRenderable(s, entry.moduleName, entry.repo),
|
||||
{
|
||||
id: `${entry.name}_${s.name}_${i}`,
|
||||
printSignaturesAsHeader,
|
||||
},
|
||||
printSignaturesAsHeader,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('CLI docs to html', () => {
|
||||
const cliTocs = fragment.querySelectorAll('.docs-reference-cli-toc')!;
|
||||
expect(cliTocs.length).toBe(2);
|
||||
|
||||
expect(cliTocs[0].textContent).toContain('ng component[name][options]');
|
||||
expect(cliTocs[1].textContent).toContain('ng c[name][options]');
|
||||
expect(cliTocs[0].textContent).toContain('ng component [name] [options]');
|
||||
expect(cliTocs[1].textContent).toContain('ng c [name] [options]');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
import {readFile} from 'fs/promises';
|
||||
import {JSDOM} from 'jsdom';
|
||||
import {getRenderable} from '../processing.mjs';
|
||||
import {renderEntry} from '../rendering.mjs';
|
||||
import {setSymbols} from '../symbol-context.mjs';
|
||||
import {resolve} from 'path';
|
||||
import {initHighlighter} from '../../../shared/shiki.mjs';
|
||||
import {getRenderable} from '../processing.mjs';
|
||||
import {renderEntry} from '../rendering.mjs';
|
||||
import {setHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {setSymbols} from '../symbol-context.mjs';
|
||||
|
||||
// Note: The tests will probably break if the schema of the api extraction changes.
|
||||
// All entries in the fake-entries are extracted from Angular's api.
|
||||
@@ -69,7 +69,7 @@ describe('markdown to html', () => {
|
||||
it('should render multiple {@link} blocks', () => {
|
||||
const provideClientHydrationEntry = entries.get('provideClientHydration')!;
|
||||
expect(provideClientHydrationEntry).toBeDefined();
|
||||
const cardItem = provideClientHydrationEntry.querySelector('.docs-reference-card-item')!;
|
||||
const cardItem = provideClientHydrationEntry.querySelector('.docs-api')!;
|
||||
expect(cardItem.innerHTML).not.toContain('@link');
|
||||
});
|
||||
|
||||
|
||||
+215
-192
@@ -17,204 +17,207 @@ import {
|
||||
|
||||
// @ts-ignore This compiles fine, but Webstorm doesn't like the ESM import in a CJS context.
|
||||
describe('jsdoc transforms', () => {
|
||||
it('should transform links', () => {
|
||||
setCurrentSymbol('Router');
|
||||
setSymbols(
|
||||
Object.fromEntries([
|
||||
['Route', 'test'],
|
||||
['Router', 'test'],
|
||||
['Router.someMethod', 'test'],
|
||||
['Router.someMethodWithParenthesis', 'test'],
|
||||
['FormGroup', 'test'],
|
||||
['FormGroup.someMethod', 'test'],
|
||||
]),
|
||||
);
|
||||
describe('addHtmlAdditionalLinks', () => {
|
||||
it('should transform links', () => {
|
||||
setCurrentSymbol('Router');
|
||||
setSymbols(
|
||||
Object.fromEntries([
|
||||
['Route', 'test'],
|
||||
['Router', 'test'],
|
||||
['Router.someMethod', 'test'],
|
||||
['Router.someMethodWithParenthesis', 'test'],
|
||||
['FormGroup', 'test'],
|
||||
['FormGroup.someMethod', 'test'],
|
||||
]),
|
||||
);
|
||||
|
||||
const entry = addHtmlAdditionalLinks({
|
||||
jsdocTags: [
|
||||
{
|
||||
name: 'see',
|
||||
comment: '[Angular](https://angular.io)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '[Angular](https://angular.io "Angular")',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link Route}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link Route Something else}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link #someMethod}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link #someMethodWithParenthesis()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link someMethod()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link FormGroup.someMethod()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link https://angular.dev/api/core/ApplicationRef}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link https://angular.dev}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link /cli/build ng build}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link /ecosystem/rxjs-interop/output-interop Output Interop}',
|
||||
},
|
||||
],
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[0]).toEqual({
|
||||
label: 'Angular',
|
||||
url: 'https://angular.io',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[1]).toEqual({
|
||||
label: 'Angular',
|
||||
url: 'https://angular.io',
|
||||
title: 'Angular',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[2]).toEqual({
|
||||
label: 'Route',
|
||||
url: '/api/test/Route',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[3]).toEqual({
|
||||
label: 'Something else',
|
||||
url: '/api/test/Route',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[4]).toEqual({
|
||||
label: 'someMethod',
|
||||
url: '/api/test/Router#someMethod',
|
||||
});
|
||||
expect(entry.additionalLinks[5]).toEqual({
|
||||
label: 'someMethodWithParenthesis()',
|
||||
url: '/api/test/Router#someMethodWithParenthesis',
|
||||
});
|
||||
expect(entry.additionalLinks[6]).toEqual({
|
||||
label: 'someMethod()',
|
||||
url: '/api/test/Router#someMethod',
|
||||
});
|
||||
expect(entry.additionalLinks[7]).toEqual({
|
||||
label: 'FormGroup.someMethod()',
|
||||
url: '/api/test/FormGroup#someMethod',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[8]).toEqual({
|
||||
label: 'ApplicationRef',
|
||||
url: 'https://angular.dev/api/core/ApplicationRef',
|
||||
});
|
||||
expect(entry.additionalLinks[9]).toEqual({
|
||||
label: 'angular.dev',
|
||||
url: 'https://angular.dev',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[10]).toEqual({
|
||||
label: 'ng build',
|
||||
url: '/cli/build',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[11]).toEqual({
|
||||
label: 'Output Interop',
|
||||
url: '/ecosystem/rxjs-interop/output-interop',
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert backticks to code tags in markdown links', () => {
|
||||
const entry = addHtmlAdditionalLinks({
|
||||
jsdocTags: [
|
||||
{
|
||||
name: 'see',
|
||||
comment:
|
||||
'[Host view using `ViewContainerRef.createComponent`](guide/components/programmatic-rendering#host-view-using-viewcontainerrefcreatecomponent)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment:
|
||||
'[Popup attached to `document.body` with `createComponent` + `hostElement`](guide/components/programmatic-rendering#popup-attached-to-documentbody-with-createcomponent--hostelement)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '[Method with `backticks` in title](https://example.com "Title with `code`")',
|
||||
},
|
||||
],
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[0]).toEqual({
|
||||
label: 'Host view using <code>ViewContainerRef.createComponent</code>',
|
||||
url: 'guide/components/programmatic-rendering#host-view-using-viewcontainerrefcreatecomponent',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[1]).toEqual({
|
||||
label:
|
||||
'Popup attached to <code>document.body</code> with <code>createComponent</code> + <code>hostElement</code>',
|
||||
url: 'guide/components/programmatic-rendering#popup-attached-to-documentbody-with-createcomponent--hostelement',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[2]).toEqual({
|
||||
label: 'Method with <code>backticks</code> in title',
|
||||
url: 'https://example.com',
|
||||
title: 'Title with `code`',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw on invalid relatie @link', () => {
|
||||
const entryFn = () =>
|
||||
addHtmlAdditionalLinks({
|
||||
const entry = addHtmlAdditionalLinks({
|
||||
jsdocTags: [
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link cli/build ng build}',
|
||||
comment: '[Angular](https://angular.io)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '[Angular](https://angular.io "Angular")',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link Route}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link Route Something else}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link #someMethod}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link #someMethodWithParenthesis()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link someMethod()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link FormGroup.someMethod()}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link https://angular.dev/api/core/ApplicationRef}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link https://angular.dev}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link /cli/build ng build}',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link /ecosystem/rxjs-interop/output-interop Output Interop}',
|
||||
},
|
||||
],
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
expect(entryFn).toThrowError(/Forbidden relative link: cli\/build ng build/);
|
||||
expect(entry.additionalLinks[0]).toEqual({
|
||||
label: 'Angular',
|
||||
url: 'https://angular.io',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[1]).toEqual({
|
||||
label: 'Angular',
|
||||
url: 'https://angular.io',
|
||||
title: 'Angular',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[2]).toEqual({
|
||||
label: 'Route',
|
||||
url: '/api/test/Route',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[3]).toEqual({
|
||||
label: 'Something else',
|
||||
url: '/api/test/Route',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[4]).toEqual({
|
||||
label: 'someMethod',
|
||||
url: '/api/test/Router#someMethod',
|
||||
});
|
||||
expect(entry.additionalLinks[5]).toEqual({
|
||||
label: 'someMethodWithParenthesis()',
|
||||
url: '/api/test/Router#someMethodWithParenthesis',
|
||||
});
|
||||
expect(entry.additionalLinks[6]).toEqual({
|
||||
label: 'someMethod()',
|
||||
url: '/api/test/Router#someMethod',
|
||||
});
|
||||
expect(entry.additionalLinks[7]).toEqual({
|
||||
label: 'FormGroup.someMethod()',
|
||||
url: '/api/test/FormGroup#someMethod',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[8]).toEqual({
|
||||
label: 'ApplicationRef',
|
||||
url: 'https://angular.dev/api/core/ApplicationRef',
|
||||
});
|
||||
expect(entry.additionalLinks[9]).toEqual({
|
||||
label: 'angular.dev',
|
||||
url: 'https://angular.dev',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[10]).toEqual({
|
||||
label: 'ng build',
|
||||
url: '/cli/build',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[11]).toEqual({
|
||||
label: 'Output Interop',
|
||||
url: '/ecosystem/rxjs-interop/output-interop',
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert backticks to code tags in markdown links', () => {
|
||||
const entry = addHtmlAdditionalLinks({
|
||||
jsdocTags: [
|
||||
{
|
||||
name: 'see',
|
||||
comment:
|
||||
'[Host view using `ViewContainerRef.createComponent`](guide/components/programmatic-rendering#host-view-using-viewcontainerrefcreatecomponent)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment:
|
||||
'[Popup attached to `document.body` with `createComponent` + `hostElement`](guide/components/programmatic-rendering#popup-attached-to-documentbody-with-createcomponent--hostelement)',
|
||||
},
|
||||
{
|
||||
name: 'see',
|
||||
comment: '[Method with `backticks` in title](https://example.com "Title with `code`")',
|
||||
},
|
||||
],
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[0]).toEqual({
|
||||
label: 'Host view using <code>ViewContainerRef.createComponent</code>',
|
||||
url: 'guide/components/programmatic-rendering#host-view-using-viewcontainerrefcreatecomponent',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[1]).toEqual({
|
||||
label:
|
||||
'Popup attached to <code>document.body</code> with <code>createComponent</code> + <code>hostElement</code>',
|
||||
url: 'guide/components/programmatic-rendering#popup-attached-to-documentbody-with-createcomponent--hostelement',
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
expect(entry.additionalLinks[2]).toEqual({
|
||||
label: 'Method with <code>backticks</code> in title',
|
||||
url: 'https://example.com',
|
||||
title: 'Title with `code`',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw on invalid relatie @link', () => {
|
||||
const entryFn = () =>
|
||||
addHtmlAdditionalLinks({
|
||||
jsdocTags: [
|
||||
{
|
||||
name: 'see',
|
||||
comment: '{@link cli/build ng build}',
|
||||
},
|
||||
],
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
expect(entryFn).toThrowError(/Forbidden relative link: cli\/build ng build/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse markdown in descriptions', async () => {
|
||||
setHighlighterInstance(await initHighlighter());
|
||||
describe('addHtmlDescription', () => {
|
||||
it('should parse markdown in descriptions', async () => {
|
||||
setHighlighterInstance(await initHighlighter());
|
||||
|
||||
setSymbols(
|
||||
Object.fromEntries([
|
||||
['Route', 'test'],
|
||||
['Router', 'angular/router'],
|
||||
['Router.someMethod', 'test'],
|
||||
['Router.someMethodWithParenthesis', 'test'],
|
||||
['FormGroup', 'test'],
|
||||
['FormGroup.someMethod', 'test'],
|
||||
]),
|
||||
);
|
||||
setSymbols(
|
||||
Object.fromEntries([
|
||||
['Route', 'test'],
|
||||
['Router', 'angular/router'],
|
||||
['Router.someMethod', 'test'],
|
||||
['Router.someMethodWithParenthesis', 'test'],
|
||||
['FormGroup', 'test'],
|
||||
['FormGroup.someMethod', 'test'],
|
||||
]),
|
||||
);
|
||||
|
||||
const entry = addHtmlDescription({
|
||||
description: `
|
||||
const entry = addHtmlDescription({
|
||||
description: `
|
||||
\`\`\`angular-ts
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@@ -223,16 +226,36 @@ function setupRouter() {
|
||||
}
|
||||
\`\`\`
|
||||
`,
|
||||
moduleName: 'test',
|
||||
moduleName: 'test',
|
||||
});
|
||||
|
||||
// Should have some shiki variables (meaning the description was highlighted).
|
||||
expect(entry.htmlDescription).toContain('--shiki');
|
||||
|
||||
// Having docs-code means that the description was parsed and formatted correctly (by the shared marked renderer)
|
||||
expect(entry.htmlDescription).toContain('class="docs-code"');
|
||||
|
||||
expect(entry.htmlDescription).toContain('/api/angular/router/Router');
|
||||
});
|
||||
|
||||
// Should have some shiki variables (meaning the description was highlighted).
|
||||
expect(entry.htmlDescription).toContain('--shiki');
|
||||
it('should transform entry with different description & description tag', () => {
|
||||
const entry = addHtmlDescription({
|
||||
'description':
|
||||
"Enables interop with the browser's `Navigation` API for router navigations.",
|
||||
'jsdocTags': [
|
||||
{
|
||||
'name': 'description',
|
||||
'comment': 'This feature is _highly_ experimental ...',
|
||||
},
|
||||
],
|
||||
'moduleName': 'platform-browser',
|
||||
});
|
||||
|
||||
// Having docs-code means that the description was parsed and formatted correctly (by the shared marked renderer)
|
||||
expect(entry.htmlDescription).toContain('class="docs-code"');
|
||||
|
||||
expect(entry.htmlDescription).toContain('/api/angular/router/Router');
|
||||
expect(entry.htmlDescription).toBe(`<p>This feature is <em>highly</em> experimental ...</p>`);
|
||||
expect(entry.shortHtmlDescription).toBe(
|
||||
`<p>Enables interop with the browser's <code>Navigation</code> API for router navigations.</p>`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should only mark as deprecated if all overloads are deprecated', () => {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* @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 {DocEntry} from '../entities.mjs';
|
||||
import {BlockEntryRenderable} from '../entities/renderables.mjs';
|
||||
import {
|
||||
addHtmlAdditionalLinks,
|
||||
addHtmlDescription,
|
||||
addHtmlJsDocTagComments,
|
||||
addHtmlUsageNotes,
|
||||
setEntryFlags,
|
||||
} from './jsdoc-transforms.mjs';
|
||||
import {addModuleName} from './module-name.mjs';
|
||||
import {addRepo} from './repo.mjs';
|
||||
|
||||
/** Given an unprocessed block entry, get the fully renderable block entry. */
|
||||
export function getBlockRenderable(
|
||||
blockEntry: DocEntry,
|
||||
moduleName: string,
|
||||
repo: string,
|
||||
): BlockEntryRenderable {
|
||||
return setEntryFlags(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlDescription(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(addRepo(addModuleName(blockEntry, moduleName), repo)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export function getCliRenderable(command: CliCommand): CliCommandRenderable {
|
||||
}),
|
||||
cards: getCliCardsRenderable(command),
|
||||
argumentsLabel: getArgumentsLabel(command),
|
||||
hasOptions: getOptions(command).length > 0,
|
||||
optionsLabel: getOptionsLabel(command),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,7 +66,12 @@ function getArgumentsLabel(command: CliCommand): string {
|
||||
if (args.length === 0) {
|
||||
return '';
|
||||
}
|
||||
return command.command.replace(`${command.name} `, '');
|
||||
const label = command.command.replace(/^ng\s+/, '').replace(`${command.name} `, '');
|
||||
return ` ${label}`;
|
||||
}
|
||||
|
||||
function getOptionsLabel(command: CliCommand): string {
|
||||
return getOptions(command).length > 0 ? ' [options]' : '';
|
||||
}
|
||||
|
||||
function getArgs(command: CliCommand): CliOption[] {
|
||||
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
insertParenthesesForDecoratorInShikiHtml,
|
||||
replaceKeywordFromShikiHtml,
|
||||
} from '../shiki/shiki.mjs';
|
||||
import {getSymbolUrl} from '../symbol-context.mjs';
|
||||
import {getSymbolsAsApiEntries, getSymbolUrl} from '../symbol-context.mjs';
|
||||
|
||||
import {codeToHtml} from '../../../shared/shiki.mjs';
|
||||
import {formatJs} from './format-code.mjs';
|
||||
@@ -92,7 +92,10 @@ export async function addRenderableCodeToc<T extends DocEntry & HasModuleName>(
|
||||
let codeWithSyntaxHighlighting = codeToHtml(
|
||||
getHighlighterInstance(),
|
||||
formattedCode ?? metadata?.contents,
|
||||
{language: 'typescript'},
|
||||
{
|
||||
language: 'typescript',
|
||||
apiEntries: getSymbolsAsApiEntries(),
|
||||
},
|
||||
);
|
||||
|
||||
if (isDecoratorEntry(entry)) {
|
||||
@@ -111,11 +114,6 @@ export async function addRenderableCodeToc<T extends DocEntry & HasModuleName>(
|
||||
// }
|
||||
}
|
||||
|
||||
// Note: Don't expect enum value in signatures to be linked correctly
|
||||
// as shiki already splits them into separate span blocks.
|
||||
// Only the enum itself will recieve a link
|
||||
codeWithSyntaxHighlighting = addApiLinksToHtml(codeWithSyntaxHighlighting);
|
||||
|
||||
// shiki returns the lines wrapped by 2 node : 1 pre node, 1 code node.
|
||||
// As leveraging jsdom isn't trivial here, we rely on a regex to extract the line nodes
|
||||
const pattern = /(.*?)<code.*?>(.*?)<\/code>(.*)/s;
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
addHtmlUsageNotes,
|
||||
setEntryFlags,
|
||||
} from './jsdoc-transforms.mjs';
|
||||
import {addRenderablePropertyMembers} from './member-transforms.mjs';
|
||||
import {addModuleName} from './module-name.mjs';
|
||||
import {addRepo} from './repo.mjs';
|
||||
|
||||
@@ -25,14 +26,24 @@ export async function getDecoratorRenderable(
|
||||
moduleName: string,
|
||||
repo: string,
|
||||
): Promise<DecoratorEntryRenderable> {
|
||||
const decoratorEntryWithMembers = {
|
||||
...decoratorEntry,
|
||||
members: decoratorEntry.members ?? [],
|
||||
};
|
||||
|
||||
return setEntryFlags(
|
||||
await addRenderableCodeToc(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
addHtmlDescription(addRepo(addModuleName(decoratorEntry, moduleName), repo)),
|
||||
await addRenderablePropertyMembers(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
addHtmlDescription(
|
||||
addRepo(addModuleName(decoratorEntryWithMembers, moduleName), repo),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
decoratorEntry.name,
|
||||
),
|
||||
),
|
||||
) as DecoratorEntryRenderable;
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
HasModuleName,
|
||||
HasRenderableJsDocTags,
|
||||
HasStableFlag,
|
||||
MaybeJsDocTags,
|
||||
} from '../entities/traits.mjs';
|
||||
|
||||
import {parseMarkdown} from '../../../shared/marked/parse.mjs';
|
||||
@@ -43,7 +44,7 @@ const jsDoclinkRegex = /\{\s*@link\s+([^}]+)\s*\}/;
|
||||
const jsDoclinkRegexGlobal = new RegExp(jsDoclinkRegex.source, 'g');
|
||||
|
||||
/** Given an entity with a description, gets the entity augmented with an `htmlDescription`. */
|
||||
export function addHtmlDescription<T extends HasDescription & HasModuleName>(
|
||||
export function addHtmlDescription<T extends HasDescription & HasModuleName & MaybeJsDocTags>(
|
||||
entry: T,
|
||||
): T & HasHtmlDescription {
|
||||
const firstParagraphRule = /(.*?)(?:\n\n|$)/s;
|
||||
@@ -56,10 +57,17 @@ export function addHtmlDescription<T extends HasDescription & HasModuleName>(
|
||||
?.comment ?? '';
|
||||
}
|
||||
|
||||
const description = !!entry.description ? entry.description : jsDocDescription;
|
||||
const shortTextMatch = description.match(firstParagraphRule);
|
||||
let description = entry.description || jsDocDescription;
|
||||
let shortDescription = description.match(firstParagraphRule)?.[0] ?? '';
|
||||
|
||||
// For the cases where the @description tag is after a short description
|
||||
if (jsDocDescription && description !== jsDocDescription) {
|
||||
shortDescription = entry.description;
|
||||
description = jsDocDescription;
|
||||
}
|
||||
|
||||
const htmlDescription = getHtmlForJsDocText(description).trim();
|
||||
const shortHtmlDescription = getHtmlForJsDocText(shortTextMatch ? shortTextMatch[0] : '').trim();
|
||||
const shortHtmlDescription = getHtmlForJsDocText(shortDescription).trim();
|
||||
|
||||
return {...entry, htmlDescription, shortHtmlDescription};
|
||||
}
|
||||
@@ -109,6 +117,7 @@ function getHtmlForJsDocText(text: string): string {
|
||||
const parsed = parseMarkdown(mdToParse, {
|
||||
apiEntries: getSymbolsAsApiEntries(),
|
||||
highlighter: getHighlighterInstance(),
|
||||
definedRoutes: [],
|
||||
});
|
||||
return addApiLinksToHtml(parsed);
|
||||
}
|
||||
@@ -136,6 +145,9 @@ function getHtmlAdditionalLinks<T extends HasJsDocTags>(entry: T): LinkEntryRend
|
||||
.filter((tag) => tag.name === JS_DOC_SEE_TAG)
|
||||
.map((tag) => tag.comment)
|
||||
.map((comment) => {
|
||||
// TODO: Throw when the comment is an absolute link.
|
||||
// With TS 5.9 this is not possible as the ts api that extracts comments from tags strips the "http" part of links.
|
||||
|
||||
const markdownLinkMatch = comment.match(markdownLinkRule);
|
||||
|
||||
if (markdownLinkMatch) {
|
||||
@@ -201,10 +213,6 @@ function convertLinks(text: string) {
|
||||
}
|
||||
|
||||
function parseAtLink(link: string): {label: string; url: string} | undefined {
|
||||
// Because of microsoft/TypeScript/issues/59679
|
||||
// getTextOfJSDocComment introduces an extra space between the symbol and a trailing ()
|
||||
link = link.replace(/ \(\)$/, '');
|
||||
|
||||
let [rawSymbol, description] = link.split(/\s(.+)/);
|
||||
if (rawSymbol.startsWith('#')) {
|
||||
rawSymbol = rawSymbol.substring(1);
|
||||
|
||||
@@ -10,7 +10,14 @@ import {MemberEntry, MemberTags, MemberType, type DocEntry} from '../entities.mj
|
||||
import {isHiddenEntry} from '../entities/categorization.mjs';
|
||||
import type {MemberEntryRenderable} from '../entities/renderables.mjs';
|
||||
|
||||
import {HasMembers, HasModuleName, HasRenderableMembers, HasRepo} from '../entities/traits.mjs';
|
||||
import {
|
||||
HasMembers,
|
||||
HasModuleName,
|
||||
HasPropertyMembers,
|
||||
HasRenderableMembers,
|
||||
HasRenderablePropertyMembers,
|
||||
HasRepo,
|
||||
} from '../entities/traits.mjs';
|
||||
import {addRenderableCodeToc} from './code-transforms.mjs';
|
||||
|
||||
import {
|
||||
@@ -85,8 +92,7 @@ export async function addRenderableMembers<T extends HasMembers & HasModuleName
|
||||
): Promise<T & HasRenderableMembers> {
|
||||
const members = (
|
||||
await Promise.all(
|
||||
// TODO: remove `?? []` when components repo is updated to include members array on type aliases.
|
||||
(entry.members ?? [])
|
||||
entry.members
|
||||
.filter((member) => !isHiddenEntry(member))
|
||||
.map((member) => {
|
||||
if (member.memberType === MemberType.Interface) {
|
||||
@@ -112,3 +118,11 @@ export async function addRenderableMembers<T extends HasMembers & HasModuleName
|
||||
members,
|
||||
};
|
||||
}
|
||||
|
||||
export async function addRenderablePropertyMembers<
|
||||
T extends HasPropertyMembers & HasModuleName & HasRepo,
|
||||
>(entry: T, parentName: string): Promise<T & HasRenderablePropertyMembers> {
|
||||
return {
|
||||
...((await addRenderableMembers(entry, parentName)) as T & HasRenderablePropertyMembers),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ esbuild(
|
||||
external = [
|
||||
"jsdom",
|
||||
"playwright-core",
|
||||
"typescript",
|
||||
],
|
||||
format = "esm",
|
||||
output = "guides.mjs",
|
||||
@@ -38,6 +39,7 @@ esbuild(
|
||||
entry_point = ":index.mts",
|
||||
external = [
|
||||
"jsdom",
|
||||
"typescript",
|
||||
],
|
||||
output = "guides-no-mermaid.mjs",
|
||||
platform = "node",
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
import {readFile, writeFile} from 'fs/promises';
|
||||
import path from 'path';
|
||||
import {initHighlighter} from '../shared/shiki.mjs';
|
||||
import {parseMarkdownAsync} from '../shared/marked/parse.mjs';
|
||||
import {initHighlighter} from '../shared/shiki.mjs';
|
||||
import {hasUnknownAnchors} from './helpers.mjs';
|
||||
|
||||
type ApiManifest = ApiManifestPackage[];
|
||||
@@ -21,33 +21,45 @@ interface ApiManifestPackage {
|
||||
async function main() {
|
||||
const [paramFilePath] = process.argv.slice(2);
|
||||
const rawParamLines = (await readFile(paramFilePath, {encoding: 'utf8'})).split('\n');
|
||||
const [srcs, outputFilenameExecRootRelativePath, apiManifestPath] = rawParamLines;
|
||||
const [srcs, outputFilenameExecRootRelativePath, apiManifestPath, definedRoutesAsStr] =
|
||||
rawParamLines;
|
||||
|
||||
// The highlighter needs to be setup asynchronously
|
||||
// so we're doing it at the start of the pipeline
|
||||
const highlighter = await initHighlighter();
|
||||
|
||||
let apiManifest: ApiManifest = [];
|
||||
if (!apiManifestPath) {
|
||||
throw new Error(
|
||||
'No API manifest path provided to the markdown parser. Check the failing generate_guides target.',
|
||||
);
|
||||
}
|
||||
|
||||
const apiManifestStr = await readFile(apiManifestPath, {encoding: 'utf8'});
|
||||
apiManifest = JSON.parse(apiManifestStr);
|
||||
|
||||
let definedRoutes: string[] = [];
|
||||
if (!definedRoutesAsStr) {
|
||||
throw new Error(
|
||||
'No defined routes path provided to the markdown parser. Check the failing generate_guides target.',
|
||||
);
|
||||
}
|
||||
|
||||
const definedGuideRoutes = await readFile(definedRoutesAsStr, {encoding: 'utf8'});
|
||||
definedRoutes = JSON.parse(definedGuideRoutes) as string[];
|
||||
|
||||
await Promise.all(
|
||||
srcs.split(',').map(async (filePath) => {
|
||||
if (!filePath.endsWith('.md')) {
|
||||
throw new Error(`Input file "${filePath}" does not end in a ".md" file extension.`);
|
||||
}
|
||||
|
||||
let apiManifest: ApiManifest = [];
|
||||
if (apiManifestPath) {
|
||||
try {
|
||||
const apiManifestStr = await readFile(apiManifestPath, {encoding: 'utf8'});
|
||||
apiManifest = JSON.parse(apiManifestStr);
|
||||
} catch (error) {
|
||||
console.warn('Failed to load API entries:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const markdownContent = await readFile(filePath, {encoding: 'utf8'});
|
||||
const htmlOutputContent = await parseMarkdownAsync(markdownContent, {
|
||||
markdownFilePath: filePath,
|
||||
apiEntries: mapManifestToEntries(apiManifest),
|
||||
highlighter,
|
||||
definedRoutes,
|
||||
});
|
||||
|
||||
// The expected file name structure is the [name of the file].md.html.
|
||||
|
||||
@@ -10,6 +10,15 @@ ts_project(
|
||||
],
|
||||
)
|
||||
|
||||
ts_project(
|
||||
name = "heading",
|
||||
srcs = ["heading.mts"],
|
||||
visibility = [
|
||||
"//adev/scripts/routes:__subpackages__",
|
||||
"//adev/shared-docs/pipeline:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
ts_project(
|
||||
name = "shiki",
|
||||
srcs = ["shiki.mts"],
|
||||
@@ -17,7 +26,9 @@ ts_project(
|
||||
"//adev/shared-docs/pipeline:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":linking",
|
||||
"//adev:node_modules/shiki",
|
||||
"//adev:node_modules/typescript",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -34,3 +45,17 @@ zoneless_jasmine_test(
|
||||
name = "linking_test",
|
||||
data = [":linking_test_lib"],
|
||||
)
|
||||
|
||||
ts_project(
|
||||
name = "heading_test_lib",
|
||||
testonly = True,
|
||||
srcs = ["test/heading.spec.mts"],
|
||||
deps = [
|
||||
":heading",
|
||||
],
|
||||
)
|
||||
|
||||
zoneless_jasmine_test(
|
||||
name = "heading_test",
|
||||
data = [":heading_test_lib"],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extracts the ID from a heading text.
|
||||
* Supports custom ID syntax: `## My Heading {#custom-id}`
|
||||
*/
|
||||
export function getIdFromHeading(heading: string): string {
|
||||
// extract the extended markdown heading id
|
||||
// ex: ## MyHeading {# myId}
|
||||
// This is recommended in case we end up having duplicate Ids but we still want the same heading text.
|
||||
// We don't want to make Id generation stateful/too complex to handle duplicates automatically.
|
||||
const customIdRegex = /{#\s*([\w-]+)\s*}/g;
|
||||
const customId = customIdRegex.exec(heading)?.[1];
|
||||
|
||||
if (customId) {
|
||||
return customId;
|
||||
}
|
||||
|
||||
return heading
|
||||
.toLowerCase()
|
||||
.replace(/\s|\//g, '-') // replace spaces and slashes with dashes
|
||||
.replace(/[^\p{L}\d\-]/gu, ''); // only keep letters, digits & dashes
|
||||
}
|
||||
@@ -20,6 +20,18 @@ const LINK_EXEMPT = new Set([
|
||||
'hidden',
|
||||
'state',
|
||||
'group',
|
||||
'animation',
|
||||
'transition',
|
||||
'trigger',
|
||||
'group()',
|
||||
'keyframes',
|
||||
'@keyframes',
|
||||
'input',
|
||||
'Event',
|
||||
'form',
|
||||
'type',
|
||||
'Host',
|
||||
'filter',
|
||||
]);
|
||||
|
||||
export function shouldLinkSymbol(symbol: string): boolean {
|
||||
|
||||
@@ -18,6 +18,7 @@ ts_project(
|
||||
"//adev:node_modules/mermaid",
|
||||
"//adev:node_modules/playwright-core",
|
||||
"//adev:node_modules/shiki",
|
||||
"//adev/shared-docs/pipeline/shared:heading",
|
||||
"//adev/shared-docs/pipeline/shared:linking",
|
||||
"//adev/shared-docs/pipeline/shared:shiki",
|
||||
"//adev/shared-docs/pipeline/shared/regions",
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ interface DocsCardContainerToken extends Tokens.Generic {
|
||||
// Capture group 1: all attributes on the opening tag
|
||||
// Capture group 2: all content between the open and close tags
|
||||
const cardContainerRule =
|
||||
/^[^<]*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
|
||||
/^\s*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
|
||||
const headerTitleRule = /headerTitle="([^"]*)"/;
|
||||
const headerImgSrcRule = /headerImgSrc="([^"]*)"/;
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {Tokens, Token, RendererThis, TokenizerThis} from 'marked';
|
||||
import {loadWorkspaceRelativeFile, anchorTarget} from '../../helpers.mjs';
|
||||
import {setInsideLink} from '../../transformations/link.mjs';
|
||||
import {RendererThis, Token, TokenizerThis, Tokens} from 'marked';
|
||||
import {anchorTarget, loadWorkspaceRelativeFile} from '../../helpers.mjs';
|
||||
import {AdevDocsRenderer} from '../../renderer.mjs';
|
||||
|
||||
interface DocsCardToken extends Tokens.Generic {
|
||||
type: 'docs-card';
|
||||
@@ -23,7 +23,7 @@ interface DocsCardToken extends Tokens.Generic {
|
||||
|
||||
// Capture group 1: all attributes on the opening tag
|
||||
// Capture group 2: all content between the open and close tags
|
||||
const cardRule = /^[^<]*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
|
||||
const cardRule = /^\s*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
|
||||
|
||||
const titleRule = /title="([^"]*)"/;
|
||||
const linkRule = /link="([^"]*)"/;
|
||||
@@ -67,11 +67,13 @@ export const docsCardExtension = {
|
||||
return undefined;
|
||||
},
|
||||
renderer(this: RendererThis, token: DocsCardToken) {
|
||||
return token.imgSrc ? getCardWithSvgIllustration(this, token) : getStandardCard(this, token);
|
||||
return token.imgSrc
|
||||
? getCardWithSvgIllustration(this, token)
|
||||
: getStandardCard(this.parser.renderer as AdevDocsRenderer, token);
|
||||
},
|
||||
};
|
||||
|
||||
function getStandardCard(renderer: RendererThis, token: DocsCardToken) {
|
||||
function getStandardCard(renderer: AdevDocsRenderer, token: DocsCardToken) {
|
||||
if (token.iconImgSrc && token.href) {
|
||||
// We can assume that all icons are svg files since they are custom.
|
||||
// We need to read svg content, instead of renering svg with `img`,
|
||||
@@ -110,13 +112,11 @@ function getStandardCard(renderer: RendererThis, token: DocsCardToken) {
|
||||
`;
|
||||
}
|
||||
|
||||
function parseWithoutCreatingLinks(renderer: RendererThis, token: DocsCardToken) {
|
||||
setInsideLink(true);
|
||||
try {
|
||||
return renderer.parser.parse(token.tokens);
|
||||
} finally {
|
||||
setInsideLink(false);
|
||||
}
|
||||
function parseWithoutCreatingLinks(renderer: AdevDocsRenderer, token: DocsCardToken) {
|
||||
renderer.context.disableAutoLinking = true;
|
||||
const parsed = renderer.parser.parse(token.tokens);
|
||||
renderer.context.disableAutoLinking = false;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function getCardWithSvgIllustration(renderer: RendererThis, token: DocsCardToken) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user