Compare commits
629 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8df9d50061 | |||
| 2917b3e545 | |||
| 0f2c2c4ff8 | |||
| 6c2c49cd03 | |||
| 0acce33d4e | |||
| db1b8f5a3a | |||
| 620f6ea0ad | |||
| c4af67343f | |||
| 4147b62a16 | |||
| 6cdbeb6e1a | |||
| be035dce59 | |||
| 0d7ecb937b | |||
| 72d91de8c4 | |||
| 04bd4dfdab | |||
| 33c3adaa15 | |||
| b2219f2cd0 | |||
| eb6712e738 | |||
| e4b9e5822d | |||
| 8da37b04f3 | |||
| 691a64532b | |||
| cc369a3e11 | |||
| badc998c65 | |||
| 58a69f99b1 | |||
| 6feae2e1fb | |||
| bff97e01cb | |||
| 029df7a649 | |||
| 7342e603b3 | |||
| 60920310c0 | |||
| 22c0f002fd | |||
| cb5510d277 | |||
| 68783a9c78 | |||
| 52e2995917 | |||
| 5d597ee55c | |||
| e6a5a7ed84 | |||
| 300493ec0b | |||
| c6b2a26156 | |||
| 60d019e0c7 | |||
| 6c2c50d84c | |||
| f70a9c1cc7 | |||
| 3cd1c73d3d | |||
| 19e6404eb5 | |||
| f0252323f8 | |||
| 71bfd7eb7e | |||
| 2fdf5b278d | |||
| 0f45aaff8a | |||
| 4627345d4e | |||
| e807320d74 | |||
| 0f24bf559d | |||
| aba0eb280d | |||
| ba2c982ae8 | |||
| d2e85ba720 | |||
| c5e9489f2f | |||
| 1a877efc98 | |||
| 8352d40df5 | |||
| 77692feae4 | |||
| 3ca68887de | |||
| 2e442d56b4 | |||
| 7792d80258 | |||
| e6eed35426 | |||
| 5895c9acf6 | |||
| 2ee5d69ca3 | |||
| b740baf57a | |||
| b314dd187b | |||
| 30acb10c89 | |||
| adc6d0757e | |||
| 804d4c2e0c | |||
| 5f8540488b | |||
| 4923c15e7e | |||
| 8207c94617 | |||
| a4c13212ab | |||
| 02c01e5daf | |||
| a5015d3992 | |||
| c888ac72c6 | |||
| 731aba377a | |||
| 8ff2768aaa | |||
| 637daf5343 | |||
| 6df1d8891a | |||
| ba5b78e910 | |||
| f8f05b4086 | |||
| 7ff4f19529 | |||
| f161603d37 | |||
| 191e492c05 | |||
| 9ffe2fd715 | |||
| 3ca0e475ab | |||
| 2c1bfa30b1 | |||
| 2cfb746272 | |||
| 363457c2a8 | |||
| 49fc6d54ff | |||
| 5071217c30 | |||
| 21783402b7 | |||
| c08e83c73d | |||
| 9fecf1416a | |||
| a0581d717f | |||
| f87e20fe75 | |||
| 25b8550adc | |||
| 3558a4cdfe | |||
| e3a4233cfe | |||
| 1ecbd8082c | |||
| b6958b3e88 | |||
| 00e4c0c69a | |||
| 017ad93d35 | |||
| 081bec53cf | |||
| 67059ccf10 | |||
| 098d3ed9c9 | |||
| 9eb254c964 | |||
| 7e00ec431f | |||
| 80322f921f | |||
| 71470480bb | |||
| 7e51d85b1b | |||
| 1eea5edb50 | |||
| cac7f6c3e8 | |||
| 3c5e40be68 | |||
| 6c2b3ee37d | |||
| d70c888a93 | |||
| f31bef701a | |||
| 12f42ca798 | |||
| 70bbbe9ff6 | |||
| b7cfee16e2 | |||
| 8fcef1e81a | |||
| 5fd57badb9 | |||
| 626fb0873e | |||
| 68eee382dc | |||
| 8750521b32 | |||
| 9a6c7adddf | |||
| 57f28bac5e | |||
| 1c8796a4d7 | |||
| 1eecf46e4a | |||
| 239a4dbb2d | |||
| 9f7414e32a | |||
| 236177b8a3 | |||
| 0e500dc64f | |||
| aa38b256a7 | |||
| 618c3344af | |||
| 05bd3a4c16 | |||
| 3401c7ec78 | |||
| 7b9970f499 | |||
| 219e82d4cd | |||
| f5c876b82e | |||
| 6b56665857 | |||
| f5915fa165 | |||
| e418217dde | |||
| 3206c35fb2 | |||
| 40b99940f9 | |||
| 0d84a6788f | |||
| 6b3b0c679b | |||
| 2dc4cb53ac | |||
| 41dec8ee78 | |||
| 02e5c4af8e | |||
| ed3ddebde5 | |||
| e8576a8bb2 | |||
| 4bfc1e8e29 | |||
| 961e2379fe | |||
| de8a0205fd | |||
| d86fb5d244 | |||
| b96b8e32e3 | |||
| f54364eb67 | |||
| c1b942fd1c | |||
| a9def426a1 | |||
| a1dcd09172 | |||
| b3e6b03d82 | |||
| 9471207767 | |||
| 7fd2cb4e3b | |||
| 2088eaaf22 | |||
| 001e2ba4bb | |||
| 1ef2614519 | |||
| 54f6206f1b | |||
| 20653ab15a | |||
| 0014ae66d8 | |||
| 4e3f475f63 | |||
| 76c030a82e | |||
| 50cf84f758 | |||
| 37cbdee1a2 | |||
| 455891eaf5 | |||
| 1997d950af | |||
| 26df170c54 | |||
| 36b9f7ab32 | |||
| 5c565ad37f | |||
| ba893a13b0 | |||
| 19dbf55206 | |||
| 3d48b75202 | |||
| 26a7e4fca7 | |||
| 7ca6680e03 | |||
| 5fa1c18dea | |||
| 647d75116b | |||
| 12422ae3ea | |||
| db09e106e9 | |||
| ab7db78b04 | |||
| 6121a12368 | |||
| 8f3b0b22a7 | |||
| 3c85af93af | |||
| 00a247be3f | |||
| 6d0523e326 | |||
| 3439ff10e7 | |||
| 806e9a83af | |||
| 4509d95b3b | |||
| 9513a1f89c | |||
| 843c041396 | |||
| 93e0b21d97 | |||
| 98b2ab42e6 | |||
| 6b54d6acf6 | |||
| 73ecb30491 | |||
| e581c3c437 | |||
| 685e497c4f | |||
| 7a3179241e | |||
| 22618b6be9 | |||
| 60089cc998 | |||
| a0a3289112 | |||
| 373066a379 | |||
| 7458b52b4e | |||
| 4170c2f82b | |||
| 2182cea451 | |||
| 777217618e | |||
| 746b89a901 | |||
| b395cec4cd | |||
| a6948665e6 | |||
| 790358af91 | |||
| e9146c7862 | |||
| 62d0ad7f25 | |||
| e470b2c64a | |||
| 28e778a1f9 | |||
| 61442118cf | |||
| 9b5768e7fe | |||
| cde5ee8c83 | |||
| f2072f01f2 | |||
| 2e5844c61b | |||
| 58cbbf20bd | |||
| 603e7c0bb6 | |||
| f5d97e3047 | |||
| a032099138 | |||
| f549ef290f | |||
| a020954987 | |||
| cfcf109450 | |||
| ba6ca6c5ae | |||
| a98b524f06 | |||
| f6bc122c0b | |||
| b97f666a4e | |||
| 1b7d0955a2 | |||
| bc47ab8ce9 | |||
| 26aca9e5ec | |||
| 18557f8af4 | |||
| c933660b88 | |||
| c2fba1f6fc | |||
| 83051c5c62 | |||
| 2d78f571b4 | |||
| 4017b61ede | |||
| 0acc8b0988 | |||
| a084f205f9 | |||
| 8cc052f351 | |||
| d64f45879b | |||
| 8f7c635894 | |||
| 7e0f66dbf3 | |||
| b401e6e348 | |||
| a5d34fd9f9 | |||
| 4507b5a03b | |||
| d7c8f6e772 | |||
| 4fcdc9542e | |||
| 29a61429a5 | |||
| b28366395f | |||
| 4ec3a99544 | |||
| 9c326bb8e9 | |||
| 0347e67334 | |||
| ad0b44f05f | |||
| ac8b58191a | |||
| 56633a7b1b | |||
| 2f3b7d09b5 | |||
| 4a07faf15c | |||
| 84b0debba8 | |||
| b876ced24f | |||
| f52d58675a | |||
| e56abcf517 | |||
| 6b95de3ede | |||
| 3e6e0681d0 | |||
| e97b3fa0e3 | |||
| 221ad580d8 | |||
| eb4281d7dd | |||
| f76f1ce3df | |||
| 54a4eb4da7 | |||
| d1653eca05 | |||
| 160b4cce34 | |||
| 1089ffc41b | |||
| f2649cbaa6 | |||
| 43a5e163ce | |||
| 39df8c9b76 | |||
| 29467dac05 | |||
| 18b3c52a3c | |||
| f36c61f530 | |||
| 98e510b47e | |||
| 514005a7c9 | |||
| a52e7b0f6e | |||
| 3f7119a821 | |||
| a082693838 | |||
| 630d227a5f | |||
| 66a437a42a | |||
| 7712d2a656 | |||
| 215876c398 | |||
| 7021056fae | |||
| 442f745b23 | |||
| 7c978ed8c9 | |||
| e57c8a71b2 | |||
| 4a4b780685 | |||
| 1cf2c6665f | |||
| 2f1712f894 | |||
| 81fd8b4170 | |||
| 3047fbda9e | |||
| 09fb0b693a | |||
| 6788fccbd6 | |||
| f1fe6c0e24 | |||
| 54bd3c498f | |||
| fa45d79e55 | |||
| b1a33ee608 | |||
| b9af6a74b8 | |||
| c4f1f53b70 | |||
| a4d9ad9c66 | |||
| d3058a726f | |||
| 97d38f75ee | |||
| d717414ec2 | |||
| b59fb033b9 | |||
| 4073537270 | |||
| 59cf495fe1 | |||
| 0a8272d7e7 | |||
| 500a4c92ee | |||
| b2ba8c2770 | |||
| 87c8d49b7e | |||
| 516db5c43d | |||
| 44187bde41 | |||
| a8d6b0ad65 | |||
| 1002ad5198 | |||
| b3c3e40490 | |||
| ab82c7b1be | |||
| 7c2f3511e2 | |||
| 2402ecb576 | |||
| 3847528d44 | |||
| b92df85b97 | |||
| 083b97255a | |||
| b9a0f36d5f | |||
| 4fcd1d22b2 | |||
| 681825e6be | |||
| 1c3434fc32 | |||
| ce2586aed8 | |||
| 420091d9df | |||
| cddb2ef2d0 | |||
| 28e681b99c | |||
| c9d20c78f1 | |||
| da88c80a7f | |||
| 585a8ef1a9 | |||
| 03cde99faa | |||
| 8819dccb94 | |||
| bbfd0a3c12 | |||
| 3d8658cbcd | |||
| 8dacb26ea1 | |||
| 042915418c | |||
| c4b063d403 | |||
| 10c64c804d | |||
| 6934445fd9 | |||
| 81da1e0ec4 | |||
| 5cf5186ec9 | |||
| 9eace13cee | |||
| 8b88f61df6 | |||
| 86d1b39ba4 | |||
| 4b4ad66a01 | |||
| 390343c16b | |||
| 893ac599d2 | |||
| eaec2aaa2a | |||
| 7c87157340 | |||
| 3d7e59a072 | |||
| 2f2bbb4cf6 | |||
| 6dd80b9578 | |||
| 767aafa951 | |||
| 64fefe2d8f | |||
| 84813dca53 | |||
| 6c03f624ff | |||
| 823758f22e | |||
| 135019b443 | |||
| 998fb98da8 | |||
| 16c4b2bd8c | |||
| a61bef75bf | |||
| ed1a03468b | |||
| d17b7d1aab | |||
| 23aabf78b4 | |||
| d01bcb4dd0 | |||
| 3f7e152685 | |||
| 6549d2a2d8 | |||
| 678619f4a8 | |||
| 6d8694560d | |||
| d8e2a6b8f0 | |||
| 2e4d5d3167 | |||
| deb10f2818 | |||
| ace274d58b | |||
| 5f72bf3f36 | |||
| c327a00b29 | |||
| 7d61470c15 | |||
| 3b69f0fccf | |||
| c4a32560a0 | |||
| dce77c164d | |||
| ebc46e3a7b | |||
| 6bd1a1835f | |||
| ea63c79b52 | |||
| 8c52f626bc | |||
| 849f356e65 | |||
| a20bbd5533 | |||
| 4f31a03c52 | |||
| 449e396962 | |||
| c031db1721 | |||
| 8aa2874452 | |||
| fd3c08724f | |||
| 42b553cd2e | |||
| 45e420c55b | |||
| 698e51b0d5 | |||
| e8bd83e3e0 | |||
| 3d1177fe06 | |||
| f37c13b5a8 | |||
| fde5908aa7 | |||
| 762685ce88 | |||
| ffe85e9a56 | |||
| 9cefa648f2 | |||
| 82acc84b3c | |||
| 60b353a54f | |||
| 807e2d2c24 | |||
| 8881e4233c | |||
| 6a104c520e | |||
| 61b2796257 | |||
| aac830971d | |||
| a150d9fd4c | |||
| c802c6f1e5 | |||
| 14efeffb9d | |||
| ddccfaa549 | |||
| af74f824ff | |||
| f425526fd2 | |||
| d37d8252e4 | |||
| 31765c6995 | |||
| bfaa91bbc3 | |||
| f85fdff1a9 | |||
| f35cfc1c82 | |||
| 0ba5f2d9de | |||
| 6c024a2207 | |||
| 0050a811ab | |||
| a8c266f5b8 | |||
| 451572afd3 | |||
| e2eb44ca40 | |||
| d6a4caa9b5 | |||
| 475e7277f6 | |||
| 4a62cbecd2 | |||
| 3417e78460 | |||
| 05ab516eb7 | |||
| 412a55d012 | |||
| ea1f1cb4d0 | |||
| c24a76bc3e | |||
| 6cf618efaf | |||
| b7a291f8c1 | |||
| 82b26adb8a | |||
| 55c0ce2685 | |||
| 897e2ea6f6 | |||
| fd0a1f65af | |||
| 58b666aa55 | |||
| 90f908579e | |||
| 8f8f804823 | |||
| 95fee9f718 | |||
| 895d7da162 | |||
| 48f24566c2 | |||
| bcaeed7b3a | |||
| 01d5f3fe42 | |||
| b96cfd325a | |||
| 91f517e819 | |||
| 756a538775 | |||
| ef563d80a6 | |||
| 24a703e4b8 | |||
| 08b0dfd9c1 | |||
| 7ed71e58bc | |||
| ff4426205f | |||
| 7d19ba7027 | |||
| 738b06b30a | |||
| e642155ac5 | |||
| 8f2220036d | |||
| 975c4c387c | |||
| 0149fac877 | |||
| 1e0bfc698e | |||
| e77293876b | |||
| 6e137262ea | |||
| 48e17bc53c | |||
| a09bb0020e | |||
| 9ca711fb85 | |||
| 8670f2df97 | |||
| 844bbb213d | |||
| 1d687c4994 | |||
| 6f1086f1ec | |||
| 836034172c | |||
| a520306949 | |||
| fcf01c9579 | |||
| edec724e5d | |||
| c7e9941b4f | |||
| 57d9ca98c7 | |||
| c99ac81d39 | |||
| 2f55bcb70b | |||
| 3bac12451e | |||
| 07e3166ab6 | |||
| 15e3ed53f5 | |||
| f198e9218a | |||
| 359f08d6af | |||
| f303577805 | |||
| 385a62a918 | |||
| e28a97aaeb | |||
| 58231a5a1a | |||
| f04ac29215 | |||
| e5ac4a8024 | |||
| ac711feeaa | |||
| b863bc1686 | |||
| c7400eb08c | |||
| ecfc503532 | |||
| 443b714095 | |||
| a9b7ea5cd5 | |||
| 783380c801 | |||
| ae37f0bc39 | |||
| 0ef9be8295 | |||
| 54dc25978d | |||
| 22c57e465c | |||
| 1bea9138b7 | |||
| e14440857a | |||
| 726594c286 | |||
| 6b86c33c30 | |||
| d651d17a06 | |||
| 9a038e9b8e | |||
| 9660df4352 | |||
| bcfdd01e85 | |||
| a24f4167b7 | |||
| a9a17be0e0 | |||
| 264593b46b | |||
| 4f9eeb4fb1 | |||
| 92ab08882c | |||
| 45681f30ba | |||
| 29707d6e79 | |||
| 1b4b64d1d3 | |||
| ccd33ba5c7 | |||
| 856d7d2b46 | |||
| 5f4a0fe852 | |||
| 405d91d977 | |||
| a8373f1a74 | |||
| 2e9b5430bb | |||
| 8887ae0e08 | |||
| cd32388903 | |||
| d09b519d7a | |||
| 5be7b38619 | |||
| 7f4a8eaf86 | |||
| ad032add38 | |||
| 5d953a42c2 | |||
| e2a79862a6 | |||
| c54727dd53 | |||
| 05227d73c5 | |||
| 65a216bfe2 | |||
| 65fab5bb4c | |||
| 3bcf014cb3 | |||
| 6c109d2c20 | |||
| 5ea2e47acf | |||
| b6d5f38691 | |||
| 6480d3d6d1 | |||
| a6755caff8 | |||
| 2a6bb23701 | |||
| c0ad4843d1 | |||
| 5856e01a2c | |||
| bd1b689b06 | |||
| c9aa288d11 | |||
| 72dd9fe0b6 | |||
| a0e0e1ce1f | |||
| c915527eee | |||
| 57c5c6acd2 | |||
| 146f57748c | |||
| 19fff53cd2 | |||
| 9e47fed9c9 | |||
| 5e0bcae9ef | |||
| 7fa83cd416 | |||
| e4ec3b3c97 | |||
| 79ac44d078 | |||
| ec07bfb843 | |||
| dbcafa0e8b | |||
| 4c17346bdb | |||
| 5964b4a04c | |||
| ee6de8fae7 | |||
| f1b00ca610 | |||
| 6cf1d7a34d | |||
| e3df4d2d86 | |||
| 816fa2b9a9 | |||
| bd6d5c8e66 | |||
| 369f162474 | |||
| 133730b276 | |||
| 4d57e62ce8 | |||
| 55a16e625f | |||
| 575e6a0534 | |||
| af7ebee21e | |||
| fa5a1bf781 | |||
| af12d6c1ee | |||
| c8ae15f08c | |||
| befc6243b8 | |||
| 1542d9c822 | |||
| dd5daeae0c | |||
| c73b2aada9 | |||
| 14e2bec60a | |||
| 9d004a2783 | |||
| 36741d08d2 | |||
| 63b5baae3a | |||
| 6eab2d0c71 | |||
| 93fcc48344 | |||
| e5a7460e65 | |||
| e4f1d267fb | |||
| d345362bd6 | |||
| 3334c9aa60 | |||
| 88f192827a | |||
| a429972481 | |||
| 08dcd682b8 | |||
| 688ff139dd | |||
| f87001cb66 | |||
| 5d7ba935d6 | |||
| 040d7d7746 | |||
| 7ba9a24809 | |||
| 98c47f004f | |||
| afe5d17c9f | |||
| 86b3285b02 | |||
| 81010ac16a | |||
| 27b14a75c3 | |||
| 537bb4258c | |||
| 910ea7cc44 | |||
| e574baf2aa | |||
| 44fdc7ae6e | |||
| e3fcad3f30 | |||
| 99d3d2aebf | |||
| 67f60e729f | |||
| c193928f41 | |||
| bb6f60b7c5 | |||
| 459dc88b4e | |||
| e1fb42327d | |||
| d02b7f46b0 |
@@ -0,0 +1,87 @@
|
||||
---
|
||||
name: run-nx-generator
|
||||
description: Run Nx generators with prioritization for workspace-plugin generators. Use this when generating code, scaffolding new features, or automating repetitive tasks in the monorepo.
|
||||
allowed-tools: Bash, Read, Glob, Grep, mcp__nx-mcp__nx_generators, mcp__nx-mcp__nx_generator_schema
|
||||
---
|
||||
|
||||
# Run Nx Generator
|
||||
|
||||
This skill helps you execute Nx generators efficiently, with special focus on workspace-plugin generators from your internal tooling.
|
||||
|
||||
## Generator Priority List
|
||||
|
||||
Use the `mcp__nx-mcp__nx_generator_schema` tool to get more information about how to use the generator
|
||||
|
||||
Choose which generators to run in this priority order:
|
||||
|
||||
### 🔥 Workspace-Plugin Generators (High Priority)
|
||||
|
||||
These are your custom internal tools in `tools/workspace-plugin/`
|
||||
|
||||
### 📦 Core Nx Generators (Standard)
|
||||
|
||||
Only use these if workspace-plugin generators don't fit:
|
||||
|
||||
- `nx generate @nx/devkit:...` - DevKit utilities
|
||||
- `nx generate @nx/node:...` - Node.js libraries
|
||||
- `nx generate @nx/react:...` - React components and apps
|
||||
- Framework-specific generators
|
||||
|
||||
## How to Run Generators
|
||||
|
||||
1. **List available generators**:
|
||||
|
||||
2. **Get generator schema** (to see available options):
|
||||
Use the `mcp__nx-mcp__nx_generator_schema` tool to get more information about how to use the generator
|
||||
|
||||
3. **Run the generator**:
|
||||
|
||||
```bash
|
||||
nx generate [generator-path] [options]
|
||||
```
|
||||
|
||||
4. **Verify the changes**:
|
||||
- Review generated files
|
||||
- Run tests: `nx affected -t test`
|
||||
- Format code: `npx prettier --write [files]`
|
||||
|
||||
## Best Practices
|
||||
|
||||
- ✅ Always check workspace-plugin first - it has your custom solutions
|
||||
- ✅ Use `--dry-run` flag to preview changes before applying
|
||||
- ✅ Format generated code immediately with Prettier
|
||||
- ✅ Test affected projects after generation
|
||||
- ✅ Commit generator changes separately from manual edits
|
||||
|
||||
## Examples
|
||||
|
||||
### Bumping Maven Version
|
||||
|
||||
When updating the Maven plugin version, use the workspace-plugin generator:
|
||||
|
||||
```bash
|
||||
nx generate @nx/workspace-plugin:bump-maven-version \
|
||||
--newVersion 0.0.10 \
|
||||
--nxVersion 22.1.0-beta.7
|
||||
```
|
||||
|
||||
This automates all the version bumping instead of manual file edits.
|
||||
|
||||
### Creating a New Plugin
|
||||
|
||||
For creating a new create-nodes plugin:
|
||||
|
||||
```bash
|
||||
nx generate @nx/workspace-plugin:create-nodes-plugin \
|
||||
--name my-custom-plugin
|
||||
```
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when you need to:
|
||||
|
||||
- Generate new code or projects
|
||||
- Scaffold new features or libraries
|
||||
- Automate repetitive setup tasks
|
||||
- Update internal tools and configurations
|
||||
- Create migrations or version updates
|
||||
@@ -8,11 +8,11 @@
|
||||
// Try a more recent distribution, if your are having build issues related to GLIBC version
|
||||
// Here we use 'bookworm', which is based on `Debian-12`, which comes with `GLIBC v2.36`
|
||||
// (Nx tools currenlty requires `GLIBC v2.33` or higher)
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:20-bookworm",
|
||||
// Note: Using base debian image instead of typescript-node since mise will manage all tools
|
||||
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
|
||||
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/rust:1": {}
|
||||
},
|
||||
// All tools (Node, Java, Rust, Dotnet) are managed by mise via mise.toml
|
||||
"features": {},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// 4211 = nx graph port
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
# Update the underlying (Debian) OS, to make sure we have the latest security patches and libraries like 'GLIBC'
|
||||
# Update the underlying (Debian) OS, to make sure we have the latest security patches and libraries like 'GLIBC'
|
||||
echo "⚙️ Updating the underlying OS..."
|
||||
sudo apt-get update && sudo apt-get -y upgrade
|
||||
|
||||
# Uninstall globally installed PNPM (required version will be reinstalled through corepack)
|
||||
echo "❌ Uninstalling globally installed PNPM..."
|
||||
npm uninstall -g pnpm
|
||||
# Install mise for managing development tools (Node, Java, Rust, Dotnet)
|
||||
echo "⚙️ Installing mise..."
|
||||
curl https://mise.run | sh
|
||||
|
||||
# Add mise to PATH
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
# Trust the mise.toml configuration file
|
||||
echo "⚙️ Trusting mise.toml configuration..."
|
||||
mise trust
|
||||
|
||||
# Install all tools from mise.toml (node, java, rust, dotnet)
|
||||
echo "⚙️ Installing tools via mise (node, java, rust, dotnet)..."
|
||||
mise install
|
||||
|
||||
# Activate mise to make tools available in current shell
|
||||
eval "$(mise activate bash)"
|
||||
|
||||
# Add mise activation to bashrc for future shell sessions
|
||||
echo "⚙️ Configuring mise activation in shell..."
|
||||
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
|
||||
|
||||
# Prevent corepack from prompting user before downloading PNPM
|
||||
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||
|
||||
@@ -9,7 +9,7 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# 4 space indentation
|
||||
[*.{js,ts,jsx,tsx}]
|
||||
[*.{kts,kt,js,ts,jsx,tsx}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"nx-mcp": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["nx", "mcp"]
|
||||
}
|
||||
},
|
||||
"contextFileName": "AGENTS.md"
|
||||
}
|
||||
@@ -28,12 +28,12 @@ Note: We reserve the right to remove unmaintained plugins from the registry. If
|
||||
|
||||
## Steps to Submit Your Plugin
|
||||
- Use the following commit message template: `chore(core): nx plugin submission [PLUGIN_NAME]`
|
||||
- Update the `community/approved-plugins.json` file with a new entry for your plugin that includes `name`, `url`, `description`:
|
||||
- Update the `astro-docs/src/content/approved-community-plugins.json` file with a new entry for your plugin that includes `name`, `url`, `description`:
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
// community/approved-plugins.json
|
||||
// astro-docs/src/content/approved-community-plugins.json
|
||||
|
||||
[{
|
||||
"name": "@community/plugin",
|
||||
@@ -42,7 +42,7 @@ Example:
|
||||
}]
|
||||
```
|
||||
|
||||
Once merged, your plugin will be available when running the `nx list` command, and will also be available in the Plugin Registry on [nx.dev](https://nx.dev/plugin-registry)
|
||||
Once merged, your plugin will be available when running the `nx list` command, and will also be available in the Plugin Registry on [nx.dev](https://nx.dev/docs/plugin-registry)
|
||||
-->
|
||||
|
||||
# Community Plugin Submission
|
||||
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
|
||||
env:
|
||||
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
|
||||
NX_CLOUD_ENABLE_METRICS_COLLECTION: 'true'
|
||||
PNPM_HOME: ~/.pnpm
|
||||
|
||||
jobs:
|
||||
@@ -46,7 +47,7 @@ jobs:
|
||||
main-branch-name: 'master'
|
||||
|
||||
- name: Start CI Run
|
||||
run: npx nx-cloud@next start-ci-run --distribute-on="./.nx/workflows/dynamic-changesets.yaml" --stop-agents-after="e2e"
|
||||
run: npx nx-cloud@next start-ci-run --auto-apply-fixes="*format:check*,*sync:check*,*conformance:check*,*format-native*,*lint-native*,*lint*,*astro-docs:validate-links*" --distribute-on="./.nx/workflows/dynamic-changesets.yaml" --stop-agents-after="e2e"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -56,27 +57,13 @@ jobs:
|
||||
- name: Install Chrome
|
||||
uses: browser-actions/setup-chrome@2dbff04819ebbfd5c974947148805a825b8a07fd # v2.1.0
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 10.11.1
|
||||
run_install: false
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
|
||||
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
|
||||
with:
|
||||
rustflags: ''
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@48b5f213c81028ace310571dc5ec0fbbca0b2947 # v4.4.3
|
||||
@@ -86,9 +73,9 @@ jobs:
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm playwright install --with-deps
|
||||
|
||||
- name: Check Documentation
|
||||
run: pnpm nx documentation
|
||||
timeout-minutes: 20
|
||||
- name: Nx Report
|
||||
run:
|
||||
pnpm nx report
|
||||
|
||||
- name: Run Checks/Lint/Test/Build
|
||||
run: |
|
||||
@@ -103,10 +90,10 @@ jobs:
|
||||
pnpm nx-cloud record -- nx-cloud conformance:check
|
||||
pids+=($!)
|
||||
|
||||
pnpm nx run-many -t check-imports check-commit check-lock-files check-codeowners --parallel=1 --no-dte &
|
||||
pnpm nx run-many -t check-imports check-lock-files check-codeowners --parallel=1 --no-dte &
|
||||
pids+=($!)
|
||||
|
||||
pnpm nx affected --targets=lint,test,build,e2e,e2e-ci,format-native,lint-native &
|
||||
pnpm nx affected --targets=lint,test,test-kt,build,e2e,e2e-ci,format-native,lint-native &
|
||||
pids+=($!)
|
||||
|
||||
for pid in "${pids[@]}"; do
|
||||
@@ -148,7 +135,33 @@ jobs:
|
||||
run: git fetch origin master:master
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Set SHAs
|
||||
uses: nrwl/nx-set-shas@1859e66a83ac9be0dceecbd9a023702e27ac47f4 # v4.3.3
|
||||
with:
|
||||
main-branch-name: 'master'
|
||||
|
||||
- name: Check for React Native changes
|
||||
id: check-changes
|
||||
run: |
|
||||
HAS_CHANGED=$(node ./scripts/check-react-native-changes.js $NX_BASE $NX_HEAD);
|
||||
if $HAS_CHANGED; then
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "React Native projects are affected, will run macOS tests"
|
||||
else
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No React Native projects affected, skipping macOS tests"
|
||||
fi
|
||||
|
||||
- name: Restore Homebrew packages
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: |
|
||||
@@ -157,11 +170,12 @@ jobs:
|
||||
key: nrwl-nx-homebrew-packages
|
||||
|
||||
- name: Configure Detox Environment, Install applesimutils
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
# Ensure Xcode command line tools are installed and configured
|
||||
xcode-select --print-path || sudo xcode-select --reset
|
||||
sudo xcode-select -s /Applications/Xcode.app
|
||||
|
||||
|
||||
# Install or update applesimutils with error handling
|
||||
if ! brew list applesimutils &>/dev/null; then
|
||||
echo "Installing applesimutils..."
|
||||
@@ -175,44 +189,45 @@ jobs:
|
||||
echo "Updating applesimutils..."
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade applesimutils || true
|
||||
fi
|
||||
|
||||
|
||||
# Verify applesimutils installation
|
||||
applesimutils --version || (echo "applesimutils installation failed" && exit 1)
|
||||
|
||||
|
||||
# Configure environment for M-series Mac
|
||||
echo "DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer" >> $GITHUB_ENV
|
||||
echo "PLATFORM_NAME=iOS Simulator" >> $GITHUB_ENV
|
||||
|
||||
|
||||
# Set additional environment variables for better debugging
|
||||
echo "DETOX_DISABLE_TELEMETRY=1" >> $GITHUB_ENV
|
||||
echo "DETOX_LOG_LEVEL=trace" >> $GITHUB_ENV
|
||||
|
||||
|
||||
# Verify Xcode installation
|
||||
xcodebuild -version
|
||||
|
||||
|
||||
# List available simulators
|
||||
xcrun simctl list devices available
|
||||
timeout-minutes: 10
|
||||
continue-on-error: false
|
||||
|
||||
|
||||
- name: Reset iOS Simulators
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: reset-simulators
|
||||
run: |
|
||||
echo "Resetting iOS Simulators..."
|
||||
|
||||
|
||||
# Kill simulator processes
|
||||
sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
|
||||
killall "Simulator" 2>/dev/null || true
|
||||
killall "iOS Simulator" 2>/dev/null || true
|
||||
|
||||
|
||||
# Wait for processes to terminate
|
||||
sleep 3
|
||||
|
||||
|
||||
# Shutdown and erase all simulators (ignore failures)
|
||||
xcrun simctl shutdown all 2>/dev/null || true
|
||||
sleep 5
|
||||
xcrun simctl erase all 2>/dev/null || true
|
||||
|
||||
|
||||
# If erase failed, try the nuclear option
|
||||
if xcrun simctl list devices | grep -q "Booted" 2>/dev/null; then
|
||||
echo "Standard reset failed, using nuclear option..."
|
||||
@@ -220,25 +235,25 @@ jobs:
|
||||
launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
|
||||
# Clean up additional directories
|
||||
rm -rf ~/Library/Developer/CoreSimulator/Caches/* 2>/dev/null || true
|
||||
rm -rf ~/Library/Logs/CoreSimulator/* 2>/dev/null || true
|
||||
rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null || true
|
||||
|
||||
|
||||
echo "Simulator reset completed"
|
||||
timeout-minutes: 5
|
||||
continue-on-error: true
|
||||
|
||||
- name: Verify Simulator Reset
|
||||
if: ${{ steps.reset-simulators.outcome == 'success' }}
|
||||
if: steps.check-changes.outputs.has_changes == 'true' && steps.reset-simulators.outcome == 'success'
|
||||
run: |
|
||||
# Verify CoreSimulator service restarted
|
||||
pgrep -fl "CoreSimulator" || (echo "CoreSimulator service not running" && exit 1)
|
||||
|
||||
|
||||
# Check simulator list is clean
|
||||
xcrun simctl list devices
|
||||
|
||||
|
||||
# Verify simulator runtime paths exist and are writable
|
||||
test -d ~/Library/Developer/CoreSimulator/Devices || (echo "Simulator devices directory missing" && exit 1)
|
||||
touch ~/Library/Developer/CoreSimulator/Devices/test || (echo "Simulator devices directory not writable" && exit 1)
|
||||
@@ -246,7 +261,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: Diagnose Simulator Reset Failure
|
||||
if: ${{ steps.reset-simulators.outcome == 'failure' }}
|
||||
if: steps.check-changes.outputs.has_changes == 'true' && steps.reset-simulators.outcome == 'failure'
|
||||
run: |
|
||||
echo "Simulator reset failed. Collecting diagnostic information..."
|
||||
xcrun simctl list
|
||||
@@ -254,6 +269,7 @@ jobs:
|
||||
ls -la ~/Library/Logs/CoreSimulator/ || echo "No simulator logs found"
|
||||
|
||||
- name: Save Homebrew Cache
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: |
|
||||
@@ -261,37 +277,13 @@ jobs:
|
||||
~/Library/Caches/Homebrew
|
||||
key: nrwl-nx-homebrew-packages
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 10.11.1
|
||||
run_install: false
|
||||
|
||||
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
|
||||
with:
|
||||
rustflags: ''
|
||||
|
||||
- name: Install project dependencies
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm playwright install --with-deps
|
||||
|
||||
- name: Set SHAs
|
||||
uses: nrwl/nx-set-shas@1859e66a83ac9be0dceecbd9a023702e27ac47f4 # v4.3.3
|
||||
with:
|
||||
main-branch-name: 'master'
|
||||
|
||||
- name: Run E2E Tests for macOS
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
HAS_CHANGED=$(node ./scripts/check-react-native-changes.js $NX_BASE $NX_HEAD);
|
||||
if $HAS_CHANGED; then
|
||||
pnpm nx affected -t e2e-macos-local --parallel=1 --base=$NX_BASE --head=$NX_HEAD
|
||||
else
|
||||
echo "Skip E2E tests for macOS as there are no changes in React Native projects."
|
||||
fi
|
||||
pnpm nx affected -t e2e-macos-local --parallel=1 --base=$NX_BASE --head=$NX_HEAD
|
||||
|
||||
@@ -51,6 +51,8 @@ jobs:
|
||||
build-mode: none
|
||||
- language: rust
|
||||
build-mode: none
|
||||
- language: csharp
|
||||
build-mode: autobuild
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
@@ -63,6 +65,14 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Setup Language Tooling
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
|
||||
@@ -46,6 +46,8 @@ jobs:
|
||||
build-mode: none
|
||||
- language: rust
|
||||
build-mode: none
|
||||
- language: csharp
|
||||
build-mode: autobuild
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
@@ -58,6 +60,14 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Setup Language Tooling
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
|
||||
@@ -2,7 +2,7 @@ name: E2E matrix
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 5 * * *"
|
||||
- cron: '0 5 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
debug_enabled:
|
||||
@@ -14,7 +14,7 @@ on:
|
||||
env:
|
||||
CYPRESS_CACHE_FOLDER: ${{ github.workspace }}/.cypress
|
||||
|
||||
permissions: { }
|
||||
permissions: {}
|
||||
jobs:
|
||||
preinstall:
|
||||
if: ${{ github.repository_owner == 'nrwl' }}
|
||||
@@ -28,19 +28,20 @@ jobs:
|
||||
# - windows-latest Windows fails to build gradle wrapper which always runs when we build nx.
|
||||
## https://staging.nx.app/runs/LgD4vxGn8w?utm_source=pull-request&utm_medium=comment
|
||||
node_version:
|
||||
# TODO(v23): remove node 20 - EOL April 2026
|
||||
- 20
|
||||
- 22
|
||||
# - 23
|
||||
- 24
|
||||
exclude:
|
||||
# run just node v20 on macos and windows
|
||||
# run just node v24 on macos and windows
|
||||
- os: macos-latest
|
||||
node_version: 20
|
||||
- os: macos-latest
|
||||
node_version: 22
|
||||
# - os: macos-latest
|
||||
# node_version: 23
|
||||
# - os: windows-latest TODO (emily): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
|
||||
# node_version: 22
|
||||
# - os: windows-latest TODO (emily): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
|
||||
# node_version: 23
|
||||
# - os: windows-latest TODO(Jack): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
|
||||
# node_version: 20
|
||||
# - os: windows-latest TODO (Jack): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
|
||||
# node_version: 22
|
||||
|
||||
name: Cache install (${{ matrix.os }}, node v${{ matrix.node_version }})
|
||||
steps:
|
||||
@@ -50,17 +51,15 @@ jobs:
|
||||
fetch-depth: 0
|
||||
filter: tree:0
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 10.11.1
|
||||
run_install: false
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
env:
|
||||
NODE_VERSION: ${{ matrix.node_version }}
|
||||
|
||||
- name: Set node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'pnpm'
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
@@ -127,8 +126,7 @@ jobs:
|
||||
|
||||
- name: Process matrix data
|
||||
id: process-json
|
||||
run:
|
||||
echo "MATRIX=$(npx tsx .github/workflows/nightly/process-matrix.ts | jq -c .)" >> $GITHUB_OUTPUT
|
||||
run: echo "MATRIX=$(npx tsx .github/workflows/nightly/process-matrix.ts | jq -c .)" >> $GITHUB_OUTPUT
|
||||
|
||||
e2e:
|
||||
if: ${{ github.repository_owner == 'nrwl' }}
|
||||
@@ -138,7 +136,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 200 # <- cap each job to 200 minutes
|
||||
timeout-minutes: 200 # <- cap each job to 200 minutes
|
||||
strategy:
|
||||
matrix: ${{fromJson(needs.prepare-matrix.outputs.matrix)}} # Load matrix from previous job
|
||||
fail-fast: false
|
||||
@@ -154,34 +152,15 @@ jobs:
|
||||
- name: Prepare dir for output
|
||||
run: mkdir -p outputs
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 10.11.1
|
||||
run_install: false
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
env:
|
||||
NODE_VERSION: ${{ matrix.node_version }}
|
||||
|
||||
- name: Use Node.js ${{ matrix.node_version }}
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install Rust
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
rustup toolchain install 1.70.0
|
||||
|
||||
- name: Load Cargo Env
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
run: echo "PATH=$HOME/.cargo/bin:$PATH" >> $GITHUB_ENV
|
||||
|
||||
- name: Install bun
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
|
||||
with:
|
||||
bun-version: latest
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
@@ -195,7 +174,7 @@ jobs:
|
||||
# https://github.com/actions/virtual-environments/issues/2840
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf '/usr/local/share/boost'
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
sudo apt-get install lsof
|
||||
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
@@ -231,35 +210,35 @@ jobs:
|
||||
# Ensure Xcode command line tools are installed and configured
|
||||
xcode-select --print-path || sudo xcode-select --reset
|
||||
sudo xcode-select -s /Applications/Xcode.app
|
||||
|
||||
|
||||
# Install or update applesimutils with error handling
|
||||
if ! brew list applesimutils &>/dev/null; then
|
||||
echo "Installing applesimutils..."
|
||||
echo 'Installing applesimutils...'
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null || {
|
||||
echo "Failed to install applesimutils, retrying with update..."
|
||||
echo 'Failed to install applesimutils, retrying with update...'
|
||||
brew update
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils
|
||||
}
|
||||
else
|
||||
echo "Updating applesimutils..."
|
||||
echo 'Updating applesimutils...'
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade applesimutils || true
|
||||
fi
|
||||
|
||||
|
||||
# Verify applesimutils installation
|
||||
applesimutils --version || (echo "applesimutils installation failed" && exit 1)
|
||||
|
||||
applesimutils --version || (echo 'applesimutils installation failed' && exit 1)
|
||||
|
||||
# Configure environment for M-series Mac
|
||||
echo "DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer" >> $GITHUB_ENV
|
||||
echo "PLATFORM_NAME=iOS Simulator" >> $GITHUB_ENV
|
||||
|
||||
echo 'DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer' >> $GITHUB_ENV
|
||||
echo 'PLATFORM_NAME=iOS Simulator' >> $GITHUB_ENV
|
||||
|
||||
# Set additional environment variables for better debugging
|
||||
echo "DETOX_DISABLE_TELEMETRY=1" >> $GITHUB_ENV
|
||||
echo "DETOX_LOG_LEVEL=trace" >> $GITHUB_ENV
|
||||
|
||||
echo 'DETOX_DISABLE_TELEMETRY=1' >> $GITHUB_ENV
|
||||
echo 'DETOX_LOG_LEVEL=trace' >> $GITHUB_ENV
|
||||
|
||||
# Verify Xcode installation
|
||||
xcodebuild -version
|
||||
|
||||
|
||||
timeout-minutes: 10
|
||||
continue-on-error: false
|
||||
|
||||
@@ -267,35 +246,35 @@ jobs:
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
id: reset-simulators
|
||||
run: |
|
||||
echo "Resetting iOS Simulators..."
|
||||
|
||||
echo 'Resetting iOS Simulators...'
|
||||
|
||||
# Kill simulator processes
|
||||
sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
|
||||
killall "Simulator" 2>/dev/null || true
|
||||
killall "iOS Simulator" 2>/dev/null || true
|
||||
|
||||
killall 'Simulator' 2>/dev/null || true
|
||||
killall 'iOS Simulator' 2>/dev/null || true
|
||||
|
||||
# Wait for processes to terminate
|
||||
sleep 3
|
||||
|
||||
|
||||
# Shutdown and erase all simulators (ignore failures)
|
||||
xcrun simctl shutdown all 2>/dev/null || true
|
||||
sleep 5
|
||||
xcrun simctl erase all 2>/dev/null || true
|
||||
|
||||
|
||||
# If erase failed, try the nuclear option
|
||||
if xcrun simctl list devices | grep -q "Booted" 2>/dev/null; then
|
||||
echo "Standard reset failed, using nuclear option..."
|
||||
if xcrun simctl list devices | grep -q 'Booted' 2>/dev/null; then
|
||||
echo 'Standard reset failed, using nuclear option...'
|
||||
rm -rf ~/Library/Developer/CoreSimulator/Devices/* 2>/dev/null || true
|
||||
launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
|
||||
# Clean up additional directories
|
||||
rm -rf ~/Library/Developer/CoreSimulator/Caches/* 2>/dev/null || true
|
||||
rm -rf ~/Library/Logs/CoreSimulator/* 2>/dev/null || true
|
||||
rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null || true
|
||||
|
||||
echo "Simulator reset completed"
|
||||
|
||||
echo 'Simulator reset completed'
|
||||
timeout-minutes: 5
|
||||
continue-on-error: true
|
||||
|
||||
@@ -303,27 +282,27 @@ jobs:
|
||||
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success' }}
|
||||
run: |
|
||||
# Verify CoreSimulator service restarted
|
||||
pgrep -fl "CoreSimulator" || (echo "CoreSimulator service not running" && exit 1)
|
||||
|
||||
pgrep -fl 'CoreSimulator' || (echo 'CoreSimulator service not running' && exit 1)
|
||||
|
||||
# Verify simulator runtime paths exist and are writable
|
||||
test -d ~/Library/Developer/CoreSimulator/Devices || (echo "Simulator devices directory missing" && exit 1)
|
||||
touch ~/Library/Developer/CoreSimulator/Devices/test || (echo "Simulator devices directory not writable" && exit 1)
|
||||
test -d ~/Library/Developer/CoreSimulator/Devices || (echo 'Simulator devices directory missing' && exit 1)
|
||||
touch ~/Library/Developer/CoreSimulator/Devices/test || (echo 'Simulator devices directory not writable' && exit 1)
|
||||
rm ~/Library/Developer/CoreSimulator/Devices/test
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: Diagnose Simulator Reset Failure
|
||||
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'failure' }}
|
||||
run: |
|
||||
echo "Simulator reset failed. Collecting diagnostic information..."
|
||||
echo 'Simulator reset failed. Collecting diagnostic information...'
|
||||
xcrun simctl list
|
||||
echo "Checking simulator logs..."
|
||||
ls -la ~/Library/Logs/CoreSimulator/ || echo "No simulator logs found"
|
||||
echo 'Checking simulator logs...'
|
||||
ls -la ~/Library/Logs/CoreSimulator/ || echo 'No simulator logs found'
|
||||
|
||||
- name: Configure git metadata (needed for lerna smoke tests)
|
||||
if: ${{ (matrix.os != 'macos-latest') || (matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success') }}
|
||||
run: |
|
||||
git config --global user.email test@test.com
|
||||
git config --global user.name "Test Test"
|
||||
git config --global user.name 'Test Test'
|
||||
|
||||
- name: Set starting timestamp
|
||||
if: ${{ (matrix.os != 'macos-latest') || (matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success') }}
|
||||
@@ -352,18 +331,18 @@ jobs:
|
||||
npm_config_registry: http://localhost:4872
|
||||
YARN_REGISTRY: http://localhost:4872
|
||||
CI: true
|
||||
|
||||
|
||||
- name: Run e2e tests with npm (macOS)
|
||||
id: e2e-run-npm
|
||||
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success' }}
|
||||
run: |
|
||||
# Run the tests
|
||||
if [[ "${{ matrix.project }}" == "e2e-detox" ]] || [[ "${{ matrix.project }}" == "e2e-react-native" ]] || [[ "${{ matrix.project }}" == "e2e-expo" ]]; then
|
||||
if [[ '${{ matrix.project }}' == 'e2e-detox' ]] || [[ '${{ matrix.project }}' == 'e2e-react-native' ]] || [[ '${{ matrix.project }}' == 'e2e-expo' ]]; then
|
||||
NX_E2E_VERBOSE_DEBUG=1 pnpm nx run ${{ matrix.project }}:e2e-macos-local
|
||||
else
|
||||
NX_E2E_VERBOSE_DEBUG=1 pnpm nx run ${{ matrix.project }}:e2e-local
|
||||
fi
|
||||
|
||||
|
||||
env:
|
||||
NX_E2E_CI_CACHE_KEY: e2e-gha-${{ matrix.os }}-${{ matrix.node_version }}-${{ matrix.package_manager }}
|
||||
NX_PERF_LOGGING: 'false'
|
||||
@@ -387,10 +366,10 @@ jobs:
|
||||
before=${{ steps.before-e2e.outputs.timestamp }}
|
||||
now=$(date +%s)
|
||||
delta=$(($now - $before))
|
||||
|
||||
|
||||
# Determine the outcome based on which step ran
|
||||
outcome="${{ matrix.os == 'macos-latest' && steps.e2e-run-npm.outcome || steps.e2e-run-pnpm.outcome }}"
|
||||
|
||||
outcome='${{ matrix.os == 'macos-latest' && steps.e2e-run-npm.outcome || steps.e2e-run-pnpm.outcome }}'
|
||||
|
||||
matrix=$((
|
||||
echo '${{ toJSON(matrix) }}'
|
||||
) | jq --argjson delta $delta -c '. + { "status": "'"$outcome"'", "duration": $delta }')
|
||||
|
||||
@@ -3,14 +3,14 @@ name: Generate embeddings
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 5 * * 0,4" # sunday, thursday 5AM
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cache-and-install:
|
||||
if: github.repository == 'nrwl/nx'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ['20.19.0']
|
||||
node-version: ['24']
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -19,7 +19,8 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: '20.19.0'
|
||||
node-version: '24'
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
@@ -45,8 +46,11 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --no-frozen-lockfile
|
||||
|
||||
- name: Build docs
|
||||
run: npx nx build astro-docs
|
||||
|
||||
- name: Run embeddings script
|
||||
run: pnpm exec nx run tools-documentation-create-embeddings:run-node
|
||||
run: node --import tsx tools/documentation/create-embeddings/src/main.mts --mode=astro
|
||||
env:
|
||||
NX_NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NX_NEXT_PUBLIC_SUPABASE_URL }}
|
||||
NX_SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.NX_SUPABASE_SERVICE_ROLE_KEY }}
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: Use Node.js ${{ matrix.node_version }}
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: '20.19.0'
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Cache node_modules
|
||||
|
||||
@@ -67,6 +67,7 @@ const matrixData: MatrixData = {
|
||||
{ name: 'e2e-storybook', codeowners: 'S04SVQ8H0G5' },
|
||||
{ name: 'e2e-nuxt', codeowners: 'S04SJ6PL98X' }
|
||||
],
|
||||
// TODO(v23): remove node 20 - EOL April 2026
|
||||
nodeTLS: 20,
|
||||
setup: [
|
||||
{
|
||||
@@ -74,12 +75,15 @@ const matrixData: MatrixData = {
|
||||
os_name: 'Linux',
|
||||
os_timeout: 60,
|
||||
package_managers: ['npm', 'pnpm', 'yarn'],
|
||||
node_versions: ['20.19.0', '22.12.0'],
|
||||
node_versions: ['20.19.0', '22.12.0', '24.0.0'],
|
||||
excluded: ['e2e-detox', 'e2e-react-native', 'e2e-expo']
|
||||
},
|
||||
{ os: 'macos-latest', os_name: 'MacOS', os_timeout: 90, package_managers: ['npm'], node_versions: ['20.19.0'] }
|
||||
// TODO (emily): Fix Windows support as gradle fails when running nx build https://staging.nx.app/runs/LgD4vxGn8w?utm_source=pull-request&utm_medium=comment
|
||||
// { os: 'windows-latest', os_name: 'WinOS', os_timeout: 180, package_managers: ['npm'], node_versions: ['20.19.0'], excluded: ['e2e-detox', 'e2e-react-native', 'e2e-expo'] }
|
||||
// Docker is not supported on ARM-based macOS runners (no nested virtualization)
|
||||
// See: https://github.com/docker/setup-docker-action and https://github.com/douglascamata/setup-docker-macos-action
|
||||
// We may want to look into adding intel only for this docker case, at least until vm-in-vm works on latest macos
|
||||
{ os: 'macos-latest', os_name: 'MacOS', os_timeout: 90, package_managers: ['npm'], node_versions: ['24.0.0'], excluded: ['e2e-docker'] }
|
||||
// TODO (Jack): Fix Windows support as gradle fails when running nx build https://staging.nx.app/runs/LgD4vxGn8w?utm_source=pull-request&utm_medium=comment
|
||||
// { os: 'windows-latest', os_name: 'WinOS', os_timeout: 180, package_managers: ['npm'], node_versions: ['24.0.0'], excluded: ['e2e-detox', 'e2e-react-native', 'e2e-expo'] }
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Validate PR title
|
||||
|
||||
@@ -3,7 +3,14 @@ name: publish
|
||||
on:
|
||||
# Automated schedule - canary releases from master
|
||||
schedule:
|
||||
- cron: "0 20 * * 1-5" # Monday - Friday, at 20:00 UTC (8pm UTC)
|
||||
- cron: "0 19 * * 1-5" # Monday - Friday, at 19:00 UTC (7pm UTC)
|
||||
# Manual trigger - PR releases or dry-runs (based on workflow inputs)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr:
|
||||
description: "PR Number - If set, a real release will be created for the branch associated with the given PR number. If blank, a dry-run of the currently selected branch will be performed."
|
||||
required: false
|
||||
type: number
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
@@ -28,6 +35,11 @@ jobs:
|
||||
# - release:
|
||||
# - We are running a full release which is based on the tag that triggered the release event, we can use default
|
||||
# ref resolution in actions/checkout. The exact version will be generated within scripts/nx-release.ts.
|
||||
#
|
||||
# - workflow_dispatch:
|
||||
# - We are either running a dry-run on the current branch, in which case the version will be static and we can use
|
||||
# default ref resolution in actions/checkout, or we are creating a PR release for the given PR number, in which case
|
||||
# we should generate an applicable version number within publish-resolve-data.js and use a custom ref of the PR branch name.
|
||||
resolve-required-data:
|
||||
name: Resolve Required Data
|
||||
if: ${{ github.repository_owner == 'nrwl' }}
|
||||
@@ -35,21 +47,23 @@ jobs:
|
||||
outputs:
|
||||
version: ${{ steps.script.outputs.version }}
|
||||
dry_run_flag: ${{ steps.script.outputs.dry_run_flag }}
|
||||
success_comment: ${{ steps.script.outputs.success_comment }}
|
||||
publish_branch: ${{ steps.script.outputs.publish_branch }}
|
||||
ref: ${{ steps.script.outputs.ref }}
|
||||
repo: ${{ steps.script.outputs.repo }}
|
||||
pr_number: ${{ steps.script.outputs.pr_number }}
|
||||
pr_author: ${{ steps.script.outputs.pr_author }}
|
||||
steps:
|
||||
# Default checkout on the triggering branch so that the latest publish-resolve-data.js script is available
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
check-latest: true
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Resolve and set checkout and version data to use for release
|
||||
id: script
|
||||
@@ -62,6 +76,43 @@ jobs:
|
||||
const script = require('${{ github.workspace }}/scripts/publish-resolve-data.js');
|
||||
await script({ github, context, core });
|
||||
|
||||
- name: (PR Release Only) Check out latest master
|
||||
if: ${{ steps.script.outputs.ref != '' }}
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
# Check out the latest master branch to get its copy of nx-release.ts
|
||||
repository: nrwl/nx
|
||||
ref: master
|
||||
path: latest-master-checkout
|
||||
|
||||
- name: (PR Release Only) Check out PR branch
|
||||
if: ${{ steps.script.outputs.ref != '' }}
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
# Check out the PR branch to get its copy of nx-release.ts
|
||||
repository: ${{ steps.script.outputs.repo }}
|
||||
ref: ${{ steps.script.outputs.ref }}
|
||||
path: pr-branch-checkout
|
||||
|
||||
- name: (PR Release Only) Ensure that release scripts have not changed in the PR being released
|
||||
if: ${{ steps.script.outputs.ref != '' }}
|
||||
run: |
|
||||
# List of files that must not change in PR releases
|
||||
FILES_TO_CHECK=(
|
||||
"scripts/nx-release.ts"
|
||||
"scripts/publish-resolve-data.js"
|
||||
)
|
||||
|
||||
for FILE in "${FILES_TO_CHECK[@]}"; do
|
||||
if ! cmp -s "latest-master-checkout/$FILE" "pr-branch-checkout/$FILE"; then
|
||||
echo "🛑 Error: The file $FILE is different on the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} vs latest master on nrwl/nx, cancelling workflow."
|
||||
echo "If you did not modify the file, then you likely just need to rebase/merge latest master."
|
||||
exit 1
|
||||
else
|
||||
echo "✅ The file $FILE is identical between the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} and latest master on nrwl/nx."
|
||||
fi
|
||||
done
|
||||
|
||||
build:
|
||||
needs: [ resolve-required-data ]
|
||||
if: ${{ github.repository_owner == 'nrwl' }}
|
||||
@@ -69,7 +120,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
settings:
|
||||
- host: macos-13
|
||||
- host: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
setup: |-
|
||||
rustup target add aarch64-apple-darwin
|
||||
@@ -77,8 +128,13 @@ jobs:
|
||||
pnpm nx run-many --target=build-native -- --target=x86_64-apple-darwin
|
||||
- host: windows-latest
|
||||
setup: |-
|
||||
choco install openjdk --version=21.0.0 -y
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
build: pnpm nx run-many --target=build-native -- --target=x86_64-pc-windows-msvc
|
||||
build: |
|
||||
export JAVA_HOME="C:\Program Files\OpenJDK\jdk-21"
|
||||
export PATH="$JAVA_HOME\bin:$PATH"
|
||||
java -version
|
||||
pnpm nx run-many --target=build-native -- --target=x86_64-pc-windows-msvc
|
||||
target: x86_64-pc-windows-msvc
|
||||
# Windows 32bit (not needed)
|
||||
# - host: windows-latest
|
||||
@@ -92,16 +148,22 @@ jobs:
|
||||
set -e
|
||||
apt-get update
|
||||
|
||||
# Install Java 21
|
||||
apt-get install -y openjdk-21-jdk
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
java --version
|
||||
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs=22.16.0-1nodesource1
|
||||
|
||||
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
node --version
|
||||
npm --version
|
||||
|
||||
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add x86_64-unknown-linux-gnu
|
||||
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-gnu
|
||||
@@ -112,27 +174,32 @@ jobs:
|
||||
bash -c "
|
||||
set -e
|
||||
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
|
||||
apk add --no-cache curl xz
|
||||
apk add --no-cache curl xz openjdk21
|
||||
|
||||
# Set up Java 21
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
|
||||
export PATH=\"\$JAVA_HOME/bin:\$PATH\"
|
||||
java --version
|
||||
|
||||
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
|
||||
tar -xJf node.tar.xz
|
||||
mv node-v22.16.0-linux-x64-musl /usr/local/node
|
||||
|
||||
|
||||
export PATH=\"/usr/local/node/bin:\$PATH\"
|
||||
|
||||
|
||||
echo Node: \$(node -v)
|
||||
echo NPM: \$(npm -v)
|
||||
|
||||
|
||||
# Install PNPM
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
|
||||
# Install deps and run native build
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add x86_64-unknown-linux-musl
|
||||
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-musl
|
||||
"
|
||||
- host: macos-13
|
||||
- host: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
setup: |-
|
||||
rustup target add aarch64-apple-darwin
|
||||
@@ -149,17 +216,23 @@ jobs:
|
||||
build: |
|
||||
set -e
|
||||
apt-get update
|
||||
|
||||
|
||||
# Install Java 21
|
||||
apt-get install -y openjdk-21-jdk
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
java --version
|
||||
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs=22.16.0-1nodesource1
|
||||
|
||||
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
node --version
|
||||
npm --version
|
||||
|
||||
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add aarch64-unknown-linux-gnu
|
||||
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-gnu
|
||||
@@ -187,54 +260,58 @@ jobs:
|
||||
bash -c "
|
||||
set -e
|
||||
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
|
||||
apk add --no-cache curl xz
|
||||
|
||||
apk add --no-cache curl xz openjdk21
|
||||
|
||||
# Set up Java 21
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
|
||||
export PATH=\"\$JAVA_HOME/bin:\$PATH\"
|
||||
java --version
|
||||
|
||||
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
|
||||
tar -xJf node.tar.xz
|
||||
mv node-v22.16.0-linux-x64-musl /usr/local/node
|
||||
|
||||
|
||||
export PATH=\"/usr/local/node/bin:\$PATH\"
|
||||
|
||||
|
||||
echo Node: \$(node -v)
|
||||
echo NPM: \$(npm -v)
|
||||
|
||||
|
||||
# Install PNPM
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
|
||||
# Install deps and run native build
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add aarch64-unknown-linux-musl
|
||||
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-musl
|
||||
rustup target add aarch64-unknown-linux-musl
|
||||
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-musl
|
||||
"
|
||||
- host: windows-latest
|
||||
target: aarch64-pc-windows-msvc
|
||||
setup: |-
|
||||
choco install openjdk --version=21.0.0 -y
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
build: pnpm nx run-many --target=build-native -- --target=aarch64-pc-windows-msvc
|
||||
build: |
|
||||
export JAVA_HOME="C:\Program Files\OpenJDK\jdk-21"
|
||||
export PATH="$JAVA_HOME\bin:$PATH"
|
||||
java -version
|
||||
pnpm nx run-many --target=build-native -- --target=aarch64-pc-windows-msvc
|
||||
name: stable - ${{ matrix.settings.target }} - node@22.16.0
|
||||
runs-on: ${{ matrix.settings.host }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
|
||||
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
if: ${{ !matrix.settings.docker }}
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
check-latest: true
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install
|
||||
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
|
||||
- name: Enable corepack and install pnpm
|
||||
if: ${{ !matrix.settings.docker }}
|
||||
with:
|
||||
target: ${{ matrix.settings.target }}
|
||||
rustflags: ''
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
@@ -306,6 +383,9 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
|
||||
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
@@ -325,8 +405,12 @@ jobs:
|
||||
run: |
|
||||
env
|
||||
whoami
|
||||
sudo pkg install -y -f node libnghttp2 www/npm git
|
||||
sudo pkg install -y -f node libnghttp2 www/npm git openjdk17
|
||||
sudo npm install --location=global --ignore-scripts pnpm@10.11.1
|
||||
# Set up Java 17
|
||||
export JAVA_HOME=/usr/local/openjdk17
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
java --version
|
||||
curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
sh rustup.sh -y --profile minimal --default-toolchain stable
|
||||
source "$HOME/.cargo/env"
|
||||
@@ -343,6 +427,54 @@ jobs:
|
||||
freebsd-version
|
||||
echo "Installing dependencies"
|
||||
pnpm install --frozen-lockfile --ignore-scripts
|
||||
|
||||
echo "Checking disk space before cleanup"
|
||||
df -h
|
||||
echo "Removing unnecessary preinstalled packages"
|
||||
# List all packages first to see what's installed
|
||||
sudo pkg info -a
|
||||
echo "Cleaning up to free disk space"
|
||||
# Clean package caches
|
||||
sudo pkg clean -a -y
|
||||
sudo pkg autoremove -y
|
||||
# Remove unnecessary system files
|
||||
sudo rm -rf /usr/local/lib/*.a
|
||||
sudo rm -rf /usr/local/share/doc/*
|
||||
sudo rm -rf /usr/local/share/man/*
|
||||
sudo rm -rf /usr/local/share/examples/*
|
||||
sudo rm -rf /usr/local/share/locale/*
|
||||
sudo rm -rf /usr/local/share/gtk-doc/*
|
||||
sudo rm -rf /usr/local/share/info/*
|
||||
sudo rm -rf /usr/src/*
|
||||
sudo rm -rf /usr/obj/*
|
||||
sudo rm -rf /usr/tests/*
|
||||
sudo rm -rf /usr/lib/debug/*
|
||||
# Clean var directories
|
||||
sudo rm -rf /var/cache/pkg/*
|
||||
sudo rm -rf /var/db/pkg/*.tbz
|
||||
sudo rm -rf /var/log/*.log
|
||||
sudo rm -rf /var/log/*.old
|
||||
# Clean temporary files
|
||||
sudo rm -rf /tmp/*
|
||||
sudo rm -rf /var/tmp/*
|
||||
# Remove Python cache if present
|
||||
sudo find /usr/local -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
sudo find /usr/local -name "*.pyc" -delete 2>/dev/null || true
|
||||
sudo find /usr/local -name "*.pyo" -delete 2>/dev/null || true
|
||||
# Clean npm/pnpm caches
|
||||
npm cache clean --force || true
|
||||
pnpm store prune || true
|
||||
rm -rf ~/.npm || true
|
||||
rm -rf ~/.pnpm-store || true
|
||||
# Remove Rust build artifacts if any
|
||||
rm -rf ~/.cargo/registry || true
|
||||
rm -rf ~/.cargo/git || true
|
||||
rm -rf ~/.rustup/toolchains/*/share || true
|
||||
# Remove other development tool caches
|
||||
rm -rf ~/.cache/* || true
|
||||
echo "Checking disk space after cleanup"
|
||||
df -h
|
||||
|
||||
echo "Building FreeBSD bindings"
|
||||
pnpm nx run-many --verbose --outputStyle stream --target=build-native -- --target=x86_64-unknown-freebsd
|
||||
echo "Cleaning up"
|
||||
@@ -378,19 +510,18 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
|
||||
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
|
||||
|
||||
- name: Setup dev tools with mise
|
||||
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3
|
||||
|
||||
- name: Enable corepack and install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare --activate
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
check-latest: true
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Use npm 11.5.2
|
||||
run: npm install -g npm@11.5.2
|
||||
|
||||
@@ -410,6 +541,7 @@ jobs:
|
||||
run: |
|
||||
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz
|
||||
tar -xvf wasi-sdk-23.0-x86_64-linux.tar.gz
|
||||
rustup toolchain install nightly-2025-05-09
|
||||
pnpm build:wasm
|
||||
- name: Publish
|
||||
env:
|
||||
@@ -432,6 +564,22 @@ jobs:
|
||||
if: ${{ !github.event.release.prerelease && github.event_name == 'release' }}
|
||||
run: npx ts-node -P ./scripts/tsconfig.scripts.json ./scripts/release-docs.ts
|
||||
|
||||
- name: (PR Release Only) Create comment for successful PR release
|
||||
if: success() && github.event.inputs.pr
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
SUCCESS_COMMENT: ${{ needs.resolve-required-data.outputs.success_comment }}
|
||||
with:
|
||||
# github-token defaults to ${{ github.token }} so we don't need to specify it
|
||||
script: |
|
||||
const successComment = JSON.parse(process.env.SUCCESS_COMMENT);
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: ${{ github.event.inputs.pr }},
|
||||
body: successComment
|
||||
});
|
||||
|
||||
report-pending-publish:
|
||||
name: Report Pending Publish to Slack
|
||||
if: ${{ github.repository_owner == 'nrwl' }}
|
||||
@@ -447,10 +595,20 @@ jobs:
|
||||
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
notification_title: '📦 Publish Pending Review'
|
||||
message_format: ${{ format('Version `{0}` is being published to NPM - manual review is required', needs.resolve-required-data.outputs.version) }}
|
||||
notification_title: >-
|
||||
${{ needs.resolve-required-data.outputs.pr_number &&
|
||||
format('📦 PR #{0} Publish Pending Review', needs.resolve-required-data.outputs.pr_number) ||
|
||||
'📦 Publish Pending Review' }}
|
||||
message_format: >-
|
||||
${{ needs.resolve-required-data.outputs.pr_number &&
|
||||
format('Version {0} from PR #{1} by @{2} is being published to NPM - manual review is required',
|
||||
needs.resolve-required-data.outputs.version,
|
||||
needs.resolve-required-data.outputs.pr_number,
|
||||
needs.resolve-required-data.outputs.pr_author) ||
|
||||
format('Version {0} is being published to NPM - manual review is required',
|
||||
needs.resolve-required-data.outputs.version) }}
|
||||
footer: '<{run_url}|View Workflow Run>'
|
||||
mention_groups: 'U9NPA6C90' # Jason
|
||||
mention_users: 'U9NPA6C90' # Jason
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
|
||||
|
||||
@@ -460,16 +618,17 @@ jobs:
|
||||
needs: [ resolve-required-data, build, build-freebsd, publish ]
|
||||
name: (PR Release Failure Only) Create comment for failed PR release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Create comment for failed PR release
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This script is intentionally kept inline (and e.g. not generated in publish-resolve-data.js)
|
||||
# to ensure that an error within the data generation itself is not missed.
|
||||
script: |
|
||||
const message = `
|
||||
Failed to publish a PR release of this pull request, triggered by @${{ github.triggering_actor }}.
|
||||
Failed to publish a PR release of this pull request, triggered by @${{ github.triggering_actor }}.
|
||||
See the failed workflow run at: https://github.com/nrwl/nx/actions/runs/${{ github.run_id }}
|
||||
`;
|
||||
await github.rest.issues.createComment({
|
||||
@@ -478,3 +637,4 @@ jobs:
|
||||
issue_number: ${{ github.event.inputs.pr }},
|
||||
body: message
|
||||
});
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ out
|
||||
.profile
|
||||
.rustup/
|
||||
target
|
||||
.flattened-pom.xml
|
||||
*.wasm
|
||||
/wasi-sdk*
|
||||
|
||||
@@ -75,9 +76,7 @@ storybook-static
|
||||
|
||||
.claude/settings.local.json
|
||||
|
||||
.cursor/rules/nx-rules.mdc
|
||||
.cursor/mcp.json
|
||||
.github/instructions/nx.instructions.md
|
||||
|
||||
# Added by Claude Task Master
|
||||
# Logs
|
||||
@@ -90,6 +89,7 @@ dev-debug.log
|
||||
node_modules/
|
||||
# Environment variables
|
||||
.env
|
||||
!e2e/dotnet/.env
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
@@ -110,12 +110,24 @@ node_modules/
|
||||
|
||||
astro-docs/.netlify
|
||||
|
||||
coverage
|
||||
|
||||
# Angular Rspack Specific Options
|
||||
packages/angular-rspack/coverage
|
||||
packages/angular-rspack-compiler/coverage
|
||||
|
||||
# Angular Rspack Packages use a template to generate the correct README
|
||||
# Some Packages use a template to generate the correct README
|
||||
packages/angular-rspack/README.md
|
||||
packages/angular-rspack-compiler/README.md
|
||||
packages/dotnet/README.md
|
||||
packages/maven/README.md
|
||||
|
||||
test-output
|
||||
test-results
|
||||
|
||||
# TypeScript build info files
|
||||
*.tsbuildinfo
|
||||
|
||||
# .NET build output
|
||||
/packages/dotnet/analyzer/bin
|
||||
/packages/dotnet/analyzer/obj
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
NX_USE_V8_SERIALIZER=false
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"nx": {
|
||||
"command": "pnpm",
|
||||
"args": ["nx-mcp"],
|
||||
"env": {}
|
||||
"nx-mcp": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["nx", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
wrapperVersion=3.3.4
|
||||
distributionType=only-script
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
@@ -1,163 +1,76 @@
|
||||
common-env-vars: &common-env-vars
|
||||
GIT_AUTHOR_EMAIL: test@test.com
|
||||
GIT_AUTHOR_NAME: Test
|
||||
GIT_COMMITTER_EMAIL: test@test.com
|
||||
GIT_COMMITTER_NAME: Test
|
||||
SELECTED_PM: 'pnpm'
|
||||
NX_NATIVE_LOGGING: 'nx::native::db'
|
||||
# These are need for build and link validation for next.js and astro apps
|
||||
NEXT_PUBLIC_ASTRO_URL: 'https://master--nx-docs.netlify.app'
|
||||
NX_DEV_URL: 'https://canary.nx.dev'
|
||||
|
||||
common-init-steps: &common-init-steps
|
||||
- name: Checkout
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/checkout/main.yaml'
|
||||
|
||||
- name: Cache restore
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/cache/main.yaml'
|
||||
inputs:
|
||||
key: 'pnpm-lock.yaml'
|
||||
paths: ~/.local/share/pnpm/store
|
||||
base-branch: 'master'
|
||||
|
||||
# reads mise.toml and installs toolchains needed for repo
|
||||
- name: Setup toolchains
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/install-mise/main.yaml'
|
||||
|
||||
- name: Verify toolchain versions
|
||||
script: |
|
||||
echo "mise: $(mise --version)"
|
||||
echo "node: $(node --version)"
|
||||
echo "pnpm: $(pnpm --version)"
|
||||
echo "bun: $(bun --version)"
|
||||
echo "rust: $(rustc --version) - $(cargo --version)"
|
||||
echo "dotnet: $(dotnet --version)"
|
||||
echo "java: $(javac --version)"
|
||||
|
||||
- name: Install system deps
|
||||
script: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev zip unzip
|
||||
|
||||
- name: Pnpm Install from lockfile
|
||||
script: |
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Install browsers
|
||||
script: |
|
||||
pnpm exec cypress install
|
||||
pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Install rust deps
|
||||
script: |
|
||||
cargo fetch
|
||||
|
||||
- name: Setup gradle
|
||||
script: |
|
||||
./gradlew wrapper
|
||||
./gradlew --version
|
||||
|
||||
- name: Configure git metadata (needed for lerna smoke tests)
|
||||
script: |
|
||||
git config --global user.email test@test.com
|
||||
git config --global user.name "Test Test"
|
||||
|
||||
launch-templates:
|
||||
linux-large:
|
||||
resource-class: 'docker_linux_amd64/large'
|
||||
image: 'us-east1-docker.pkg.dev/nxcloudoperations/nx-cloud/nx-agents-base-images:ubuntu22.04-node20.19-v1'
|
||||
env:
|
||||
GIT_AUTHOR_EMAIL: test@test.com
|
||||
GIT_AUTHOR_NAME: Test
|
||||
GIT_COMMITTER_EMAIL: test@test.com
|
||||
GIT_COMMITTER_NAME: Test
|
||||
SELECTED_PM: 'pnpm'
|
||||
|
||||
NX_NATIVE_LOGGING: 'nx::native::db'
|
||||
init-steps:
|
||||
- name: Checkout
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/checkout/main.yaml'
|
||||
|
||||
- name: Check Node Version
|
||||
script: node --version
|
||||
|
||||
- name: Cache restore
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/cache/main.yaml'
|
||||
inputs:
|
||||
key: 'pnpm-lock.yaml'
|
||||
paths: .pnpm-store
|
||||
base-branch: 'master'
|
||||
|
||||
- name: Install zip and unzip
|
||||
script: sudo apt-get -yqq install zip unzip
|
||||
|
||||
- name: Install bun
|
||||
script: |
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
echo "BUN_INSTALL=$HOME/.bun" >> $NX_CLOUD_ENV
|
||||
echo "PATH=$HOME/.bun/bin:$PATH" >> $NX_CLOUD_ENV
|
||||
|
||||
- name: Check bun
|
||||
script: |
|
||||
bun --version
|
||||
|
||||
- name: Install e2e deps
|
||||
script: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev
|
||||
|
||||
- name: Pnpm Install from lockfile
|
||||
script: |
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Install Browsers
|
||||
script: |
|
||||
pnpm exec cypress install
|
||||
pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Install Rust
|
||||
script: |
|
||||
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
rustup toolchain install 1.70.0
|
||||
|
||||
- name: Configure git metadata (needed for lerna smoke tests)
|
||||
script: |
|
||||
git config --global user.email test@test.com
|
||||
git config --global user.name "Test Test"
|
||||
|
||||
- name: Load Cargo Env
|
||||
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
||||
|
||||
- name: Install Rust Dependencies
|
||||
script: |
|
||||
cargo fetch
|
||||
|
||||
- name: Setup Java 21
|
||||
script: |
|
||||
sudo apt update
|
||||
sudo apt install -y openjdk-21-jdk
|
||||
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
|
||||
java -version
|
||||
|
||||
- name: Setup Gradle
|
||||
script: |
|
||||
./gradlew wrapper
|
||||
./gradlew --version
|
||||
env: *common-env-vars
|
||||
init-steps: *common-init-steps
|
||||
|
||||
linux-extra-large:
|
||||
resource-class: 'docker_linux_amd64/extra_large'
|
||||
image: 'us-east1-docker.pkg.dev/nxcloudoperations/nx-cloud/nx-agents-base-images:ubuntu22.04-node20.19-v1'
|
||||
env:
|
||||
GIT_AUTHOR_EMAIL: test@test.com
|
||||
GIT_AUTHOR_NAME: Test
|
||||
GIT_COMMITTER_EMAIL: test@test.com
|
||||
GIT_COMMITTER_NAME: Test
|
||||
SELECTED_PM: 'pnpm'
|
||||
NX_NATIVE_LOGGING: 'nx::native::db'
|
||||
init-steps:
|
||||
- name: Checkout
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/checkout/main.yaml'
|
||||
|
||||
- name: Check Node Version
|
||||
script: node --version
|
||||
|
||||
- name: Cache restore
|
||||
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/cache/main.yaml'
|
||||
inputs:
|
||||
key: 'pnpm-lock.yaml'
|
||||
paths: .pnpm-store
|
||||
base-branch: 'master'
|
||||
|
||||
- name: Install zip and unzip
|
||||
script: sudo apt-get -yqq install zip unzip
|
||||
|
||||
- name: Install bun
|
||||
script: |
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
echo "BUN_INSTALL=$HOME/.bun" >> $NX_CLOUD_ENV
|
||||
echo "PATH=$HOME/.bun/bin:$PATH" >> $NX_CLOUD_ENV
|
||||
|
||||
- name: Check bun
|
||||
script: |
|
||||
bun --version
|
||||
|
||||
- name: Install e2e deps
|
||||
script: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev
|
||||
|
||||
- name: Pnpm Install from lockfile
|
||||
script: |
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Install Browsers
|
||||
script: |
|
||||
pnpm exec cypress install
|
||||
pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Install Rust
|
||||
script: |
|
||||
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
rustup toolchain install 1.70.0
|
||||
|
||||
- name: Configure git metadata (needed for lerna smoke tests)
|
||||
script: |
|
||||
git config --global user.email test@test.com
|
||||
git config --global user.name "Test Test"
|
||||
|
||||
- name: Load Cargo Env
|
||||
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
||||
|
||||
- name: Install Rust Dependencies
|
||||
script: |
|
||||
cargo fetch
|
||||
|
||||
- name: Setup Java 21
|
||||
script: |
|
||||
sudo apt update
|
||||
sudo apt install -y openjdk-21-jdk
|
||||
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
|
||||
java -version
|
||||
|
||||
- name: Setup Gradle
|
||||
script: |
|
||||
./gradlew wrapper
|
||||
./gradlew --version
|
||||
env: *common-env-vars
|
||||
init-steps: *common-init-steps
|
||||
|
||||
@@ -1,24 +1,50 @@
|
||||
distribute-on:
|
||||
default: auto linux-large, 1 linux-extra-large
|
||||
default: auto linux-large, 3 linux-extra-large
|
||||
assignment-rules:
|
||||
# e2e-release tests must run sequentially due to shared git state and publishing operations
|
||||
- projects:
|
||||
- e2e-release
|
||||
targets:
|
||||
- e2e-ci**
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 1
|
||||
|
||||
- projects:
|
||||
- e2e-gradle
|
||||
targets:
|
||||
- e2e-ci**
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 1
|
||||
- agent: linux-extra-large
|
||||
parallelism: 1
|
||||
- agent: linux-extra-large
|
||||
parallelism: 1
|
||||
|
||||
- projects:
|
||||
- nx
|
||||
- workspace
|
||||
- remix
|
||||
- nx-maven-plugin
|
||||
targets:
|
||||
- install
|
||||
- test
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 1
|
||||
- agent: linux-extra-large
|
||||
parallelism: 1
|
||||
|
||||
- projects:
|
||||
- e2e-release
|
||||
- e2e-angular
|
||||
- e2e-react
|
||||
- e2e-next
|
||||
- e2e-web
|
||||
- e2e-eslint
|
||||
- e2e-remix
|
||||
- e2e-cypress
|
||||
- e2e-docker
|
||||
- e2e-js
|
||||
- e2e-nx-init
|
||||
- e2e-dotnet
|
||||
- e2e-workspace-create
|
||||
- e2e-rollup
|
||||
targets:
|
||||
- e2e-ci**
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 1
|
||||
- agent: linux-extra-large
|
||||
parallelism: 1
|
||||
|
||||
# All other e2e tests can run in parallel
|
||||
- targets:
|
||||
@@ -51,9 +77,11 @@ assignment-rules:
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 6
|
||||
- agent: linux-extra-large
|
||||
parallelism: 6
|
||||
|
||||
- targets:
|
||||
- '*'
|
||||
- "*"
|
||||
run-on:
|
||||
- agent: linux-large
|
||||
parallelism: 3
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"endOfLine": "lf",
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.mdoc",
|
||||
"options": {
|
||||
"parser": "markdown"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
When responding to queries about this repository:
|
||||
|
||||
1. Suggest relevant commands from the "Essential Commands" section when applicable
|
||||
2. Highlight Nx's focus on monorepos and its key features like smart task execution, code generation, and project graph
|
||||
analysis
|
||||
3. Mention the plugin ecosystem and support for various frameworks when relevant
|
||||
4. Emphasize the importance of running the full validation suite before committing changes
|
||||
|
||||
Always strive to provide accurate, helpful responses that align with the best practices and workflows described in this
|
||||
file.
|
||||
|
||||
## GitHub Issue Response Mode
|
||||
|
||||
When responding to GitHub issues, determine your approach based on how the request is phrased:
|
||||
|
||||
### Plan-First Mode (Default)
|
||||
|
||||
Use this approach when users ask you to:
|
||||
|
||||
- "analyze", "investigate", "assess", "review", "examine", or "plan"
|
||||
- Or when the request is ambiguous
|
||||
|
||||
In this mode:
|
||||
|
||||
1. Provide a detailed analysis of the issue
|
||||
2. Create a comprehensive implementation plan
|
||||
3. Break down the solution into clear steps
|
||||
4. Then please post the plan as a comment on the issue
|
||||
|
||||
### Immediate Implementation Mode
|
||||
|
||||
Use this approach when users ask you to:
|
||||
|
||||
- "fix", "implement", "solve", "build", "create", "update", or "add"
|
||||
- Or when they explicitly request immediate action
|
||||
|
||||
In this mode:
|
||||
|
||||
1. Analyze the issue quickly
|
||||
2. Implement the complete solution immediately
|
||||
3. Make all necessary code changes. Please make multiple commits so that the changes are easier to review.
|
||||
4. Run appropriate tests and validation
|
||||
5. If the tests, are not passing, please fix the issues and continue doing this up to 3 more times until the tests pass
|
||||
6. Once the tests pass, push a branch and then suggest opening a PR which has a description of the changes made, and
|
||||
that
|
||||
it make sure that it explicitly says "Fixes #ISSUE_NUMBER" to automatically close the issue when the PR is merged.
|
||||
|
||||
## Avoid making changes to generated files
|
||||
|
||||
Files under `generated` directories are generated based on a different source file and should not be modified directly.
|
||||
Find the underlying source and modify that instead.
|
||||
|
||||
## Essential Commands
|
||||
|
||||
### Code Formatting
|
||||
|
||||
After code changes are made, please make sure to format the files with prettier via `npx prettier -- FILE_NAME`
|
||||
|
||||
### Pre-push Validation
|
||||
|
||||
```bash
|
||||
# Full validation suite - run before committing
|
||||
nx prepush
|
||||
```
|
||||
|
||||
If the prepush validation suite fails, please fix the issues before proceeding with your work. This ensures that all
|
||||
code adheres to the project's standards and passes all tests. DO NOT make a new commit to fix these issues. Instead,
|
||||
amend the current commit.
|
||||
|
||||
### Testing Changes
|
||||
|
||||
After code changes are made, first test the specific project where the changes were made:
|
||||
|
||||
```bash
|
||||
nx run-many -t test,build,lint -p PROJECT_NAME
|
||||
```
|
||||
|
||||
After verifying the individual project, validate that the changes in projects which have been affected:
|
||||
|
||||
```bash
|
||||
# Test only affected projects (recommended for development)
|
||||
nx affected -t build,test,lint
|
||||
```
|
||||
|
||||
As the last step, run the e2e tests to fully ensure that changes are valid:
|
||||
|
||||
```bash
|
||||
# Run affected e2e tests (recommended for development)
|
||||
nx affected -t e2e-local
|
||||
```
|
||||
|
||||
## Fixing GitHub Issues
|
||||
|
||||
When working on a GitHub issue, follow this systematic approach:
|
||||
|
||||
### 1. Get Issue Details
|
||||
|
||||
```bash
|
||||
# Get issue details using GitHub CLI (replace ISSUE_NUMBER with actual number)
|
||||
gh issue view ISSUE_NUMBER
|
||||
|
||||
# View multiple issues efficiently in one command
|
||||
gh issue list --limit 50 --json number,title,state,labels,assignees,updatedAt,body --jq '.[] | select(.number == 123 or .number == 456 or .number == 789)'
|
||||
|
||||
# Or filter by specific criteria to get multiple related issues
|
||||
gh issue list --label "bug" --state "open" --json number,title,body,labels --jq '.[]'
|
||||
gh issue list --assignee "@me" --json number,title,body,state --jq '.[]'
|
||||
```
|
||||
|
||||
**Tip**: Instead of running `gh issue view` multiple times, use `gh issue list` with JSON output and filtering to gather
|
||||
information about multiple issues in a single command. This is much more efficient than viewing issues one at a time.
|
||||
|
||||
**Always provide clickable links**: When discussing GitHub issues or PRs, always include the full GitHub URL so the user
|
||||
can easily open them in their browser. For example:
|
||||
|
||||
- Issue #12345: https://github.com/nrwl/nx/issues/12345
|
||||
- PR #67890: https://github.com/nrwl/nx/pull/67890
|
||||
|
||||
When cloning reproduction repos, please clone within `./tmp/claude/repro-ISSUE_NUMBER`
|
||||
|
||||
### 2. Analyze the Plan
|
||||
|
||||
- Look for a plan or implementation details in the issue description
|
||||
- Check comments for additional context or clarification
|
||||
- Identify affected projects and components
|
||||
|
||||
### 3. Implement the Solution
|
||||
|
||||
- Follow the plan outlined in the issue
|
||||
- Make focused changes that address the specific problem
|
||||
- Ensure code follows existing patterns and conventions
|
||||
|
||||
### 4. Run Full Validation
|
||||
|
||||
Use the testing workflow from the "Essential Commands" section.
|
||||
|
||||
### 5. Submit Pull Request
|
||||
|
||||
- Create a descriptive PR title that references the issue
|
||||
- **Always fill in the PR template** - don't leave it empty
|
||||
- Include "Fixes #ISSUE_NUMBER" in the PR description
|
||||
- Provide a clear summary of changes made
|
||||
- Request appropriate reviewers
|
||||
|
||||
## Pull Request Template
|
||||
|
||||
**IMPORTANT**: When creating a pull request, you MUST fill in the template found in `.github/PULL_REQUEST_TEMPLATE.md`.
|
||||
Do not leave the template sections empty. The template includes:
|
||||
|
||||
### Required Sections
|
||||
|
||||
1. **Current Behavior**: Describe the behavior we have today
|
||||
2. **Expected Behavior**: Describe the behavior we should expect with the changes in this PR
|
||||
3. **Related Issue(s)**: Link the issue being fixed so it gets closed when the PR is merged
|
||||
|
||||
### Template Format
|
||||
|
||||
```markdown
|
||||
## Current Behavior
|
||||
|
||||
<!-- This is the behavior we have today -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
<!-- This is the behavior we should expect with the changes in this PR -->
|
||||
|
||||
## Related Issue(s)
|
||||
|
||||
<!-- Please link the issue being fixed so it gets closed when this is merged. -->
|
||||
|
||||
Fixes #ISSUE_NUMBER
|
||||
```
|
||||
|
||||
### Guidelines
|
||||
|
||||
- Ensure your commit message follows the conventional commit format (use `pnpm commit`)
|
||||
- Use `fix:`, `feat:`, `chore:`, etc. as appropriate types.
|
||||
- Scope is **required** for all commits. Possible scopes are listed in `scripts/commitizen.js`.
|
||||
- Read the submission guidelines in CONTRIBUTING.md before posting
|
||||
- For complex changes, you can request a dedicated Nx release by mentioning the Nx team
|
||||
- Always link the related issue using "Fixes #ISSUE_NUMBER" to automatically close it when merged
|
||||
|
||||
<!-- nx configuration start-->
|
||||
<!-- Leave the start & end comments to automatically receive updates. -->
|
||||
|
||||
# General Guidelines for working with Nx
|
||||
|
||||
- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly
|
||||
- You have access to the Nx MCP server and its tools, use them to help the user
|
||||
- When answering questions about the repository, use the `nx_workspace` tool first to gain an understanding of the workspace architecture where applicable.
|
||||
- When working in individual projects, use the `nx_project_details` mcp tool to analyze and understand the specific project structure and dependencies
|
||||
- For questions around nx configuration, best practices or if you're unsure, use the `nx_docs` tool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration
|
||||
- If the user needs help with an Nx configuration or project graph error, use the `nx_workspace` tool to get any errors
|
||||
|
||||
# CI Error Guidelines
|
||||
|
||||
If the user wants help with fixing an error in their CI pipeline, use the following flow:
|
||||
|
||||
- Retrieve the list of current CI Pipeline Executions (CIPEs) using the `nx_cloud_cipe_details` tool
|
||||
- If there are any errors, use the `nx_cloud_fix_cipe_failure` tool to retrieve the logs for a specific task
|
||||
- Use the task logs to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
|
||||
- Make sure that the problem is fixed by running the task that you passed into the `nx_cloud_fix_cipe_failure` tool
|
||||
|
||||
<!-- nx configuration end-->
|
||||
@@ -1,13 +1,10 @@
|
||||
When responding to queries about this repository:
|
||||
|
||||
1. Use the `nx_workspace` mcp tool for understanding the workspace architecture when appropriate
|
||||
2. When working in projects, use the `nx_project` mcp tool to analyze and understand the specific project structure and
|
||||
dependencies
|
||||
3. Suggest relevant commands from the "Essential Commands" section when applicable
|
||||
4. Highlight Nx's focus on monorepos and its key features like smart task execution, code generation, and project graph
|
||||
1. Suggest relevant commands from the "Essential Commands" section when applicable
|
||||
2. Highlight Nx's focus on monorepos and its key features like smart task execution, code generation, and project graph
|
||||
analysis
|
||||
5. Mention the plugin ecosystem and support for various frameworks when relevant
|
||||
6. Emphasize the importance of running the full validation suite before committing changes
|
||||
3. Mention the plugin ecosystem and support for various frameworks when relevant
|
||||
4. Emphasize the importance of running the full validation suite before committing changes
|
||||
|
||||
Always strive to provide accurate, helpful responses that align with the best practices and workflows described in this
|
||||
file.
|
||||
@@ -182,3 +179,26 @@ Fixes #ISSUE_NUMBER
|
||||
- Read the submission guidelines in CONTRIBUTING.md before posting
|
||||
- For complex changes, you can request a dedicated Nx release by mentioning the Nx team
|
||||
- Always link the related issue using "Fixes #ISSUE_NUMBER" to automatically close it when merged
|
||||
|
||||
<!-- nx configuration start-->
|
||||
<!-- Leave the start & end comments to automatically receive updates. -->
|
||||
|
||||
# General Guidelines for working with Nx
|
||||
|
||||
- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly
|
||||
- You have access to the Nx MCP server and its tools, use them to help the user
|
||||
- When answering questions about the repository, use the `nx_workspace` tool first to gain an understanding of the workspace architecture where applicable.
|
||||
- When working in individual projects, use the `nx_project_details` mcp tool to analyze and understand the specific project structure and dependencies
|
||||
- For questions around nx configuration, best practices or if you're unsure, use the `nx_docs` tool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration
|
||||
- If the user needs help with an Nx configuration or project graph error, use the `nx_workspace` tool to get any errors
|
||||
|
||||
# CI Error Guidelines
|
||||
|
||||
If the user wants help with fixing an error in their CI pipeline, use the following flow:
|
||||
|
||||
- Retrieve the list of current CI Pipeline Executions (CIPEs) using the `nx_cloud_cipe_details` tool
|
||||
- If there are any errors, use the `nx_cloud_fix_cipe_failure` tool to retrieve the logs for a specific task
|
||||
- Use the task logs to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
|
||||
- Make sure that the problem is fixed by running the task that you passed into the `nx_cloud_fix_cipe_failure` tool
|
||||
|
||||
<!-- nx configuration end-->
|
||||
|
||||
@@ -11,17 +11,13 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
# Docs Site + Graph
|
||||
/astro-docs @nrwl/nx-docs-reviewers
|
||||
/docs @nrwl/nx-docs-reviewers
|
||||
/docs/nx-cloud @StalkAltan @rarmatei @nixallover @nrwl/nx-docs-reviewers
|
||||
/graph/** @philipjfulcher @FrozenPandaz @bcabanes @MaxKless @Coly010 @jaysoo @nartc
|
||||
/images @nrwl/nx-docs-reviewers
|
||||
/nx-dev/** @nrwl/nx-docs-reviewers
|
||||
/typedoc-theme @nrwl/nx-docs-reviewers
|
||||
|
||||
# Plugin Verticals
|
||||
|
||||
## Angular
|
||||
/docs/generated/packages/angular/** @nrwl/nx-angular-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/angular/** @nrwl/nx-angular-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/angular/** @nrwl/nx-angular-reviewers
|
||||
/packages/angular-rspack/** @nrwl/nx-angular-reviewers
|
||||
/packages/angular-rspack-compiler/** @nrwl/nx-angular-reviewers
|
||||
@@ -32,10 +28,6 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/packages/angular/src/generators/component-test/** @nrwl/nx-angular-reviewers @nrwl/nx-testing-tools-reviewers
|
||||
|
||||
## React
|
||||
/docs/generated/packages/react/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/next/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/react/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/next/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/react/** @nrwl/nx-react-reviewers
|
||||
/e2e/react/** @nrwl/nx-react-reviewers
|
||||
/packages/next/** @nrwl/nx-react-reviewers
|
||||
@@ -45,10 +37,6 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/packages/react/src/generators/component-test/** @nrwl/nx-react-reviewers @nrwl/nx-testing-tools-reviewers
|
||||
|
||||
# React Native
|
||||
/docs/generated/packages/detox/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/expo/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/react-native/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/react-native/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/detox/** @nrwl/nx-react-reviewers
|
||||
/e2e/detox/** @nrwl/nx-react-reviewers
|
||||
/packages/expo/** @nrwl/nx-react-reviewers
|
||||
@@ -57,7 +45,6 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/e2e/react-native/** @nrwl/nx-react-reviewers
|
||||
|
||||
## remix
|
||||
/docs/generated/packages/remix/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers @Coly010
|
||||
/packages/remix/** @nrwl/nx-react-reviewers @Coly010
|
||||
/e2e/remix/** @nrwl/nx-react-reviewers @Coly010
|
||||
|
||||
@@ -68,31 +55,12 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/e2e/nuxt/** @nrwl/nx-vue-reviewers
|
||||
|
||||
## Node
|
||||
/docs/generated/packages/node/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/nest/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/express/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/node/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/express/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/nest/** @nrwl/nx-node-reviewers @FrozenPandaz @nrwl/nx-docs-reviewers
|
||||
/packages/node/** @nrwl/nx-node-reviewers
|
||||
/packages/express/** @nrwl/nx-node-reviewers
|
||||
/packages/nest/** @nrwl/nx-node-reviewers
|
||||
/e2e/node/** @nrwl/nx-node-reviewers
|
||||
|
||||
## JS
|
||||
/docs/generated/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/rollup/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/js/** @nrwl/nx-js-reviewers
|
||||
/e2e/js/** @nrwl/nx-js-reviewers
|
||||
/packages/web/** @nrwl/nx-js-reviewers
|
||||
@@ -108,17 +76,12 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/e2e/rollup/** @nrwl/nx-js-reviewers
|
||||
/packages/vite/** @nrwl/nx-js-reviewers
|
||||
/e2e/vite/** @nrwl/nx-js-reviewers
|
||||
/packages/vitest/** @nrwl/nx-js-reviewers
|
||||
|
||||
## Module Federation
|
||||
/packages/module-federation/** @nrwl/nx-js-reviewers
|
||||
|
||||
## Tools
|
||||
/docs/generated/packages/cypress/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/cypress/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/jest/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/jest/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/playwright/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/playwright/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/cypress/** @nrwl/nx-testing-tools-reviewers
|
||||
/e2e/cypress/** @nrwl/nx-testing-tools-reviewers
|
||||
/packages/jest/** @nrwl/nx-testing-tools-reviewers
|
||||
@@ -127,26 +90,19 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/e2e/playwright/** @nrwl/nx-testing-tools-reviewers
|
||||
|
||||
# Linter
|
||||
/docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/eslint/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/eslint/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/eslint-plugin/** @nrwl/nx-linter-reviewers
|
||||
/packages/eslint/** @nrwl/nx-linter-reviewers
|
||||
/e2e/eslint/** @nrwl/nx-linter-reviewers
|
||||
.eslint* @nrwl/nx-linter-reviewers
|
||||
|
||||
# Storybook
|
||||
/docs/generated/packages/storybook/** @nrwl/nx-storybook-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/storybook/** @nrwl/nx-storybook-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/storybook/** @nrwl/nx-storybook-reviewers
|
||||
/e2e/storybook/** @nrwl/nx-storybook-reviewers
|
||||
|
||||
# Docker
|
||||
/packages/docker/** @nrwl/nx-core-reviewers @Coly010
|
||||
/packages/docker/** @nrwl/nx-core-reviewers @Coly010 @jaysoo
|
||||
|
||||
## Devkit
|
||||
/docs/generated/devkit/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/devkit/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/devkit/** @nrwl/nx-devkit-reviewers
|
||||
/packages/devkit/index.ts @FrozenPandaz @vsavkin
|
||||
/packages/devkit/public-api.ts @FrozenPandaz @vsavkin
|
||||
@@ -155,16 +111,15 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/packages/gradle/** @FrozenPandaz @MaxKless @lourw
|
||||
/e2e/gradle/** @FrozenPandaz @MaxKless @lourw
|
||||
|
||||
# Maven
|
||||
/packages/maven/** @FrozenPandaz @MaxKless @lourw
|
||||
/e2e/maven/** @FrozenPandaz @MaxKless @lourw
|
||||
|
||||
# Nx-Plugin
|
||||
/docs/generated/packages/plugin/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/shared/packages/plugin/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/plugin/** @nrwl/nx-devkit-reviewers
|
||||
/e2e/plugin/** @nrwl/nx-devkit-reviewers
|
||||
|
||||
## Core
|
||||
/docs/generated/cli/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/nx/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
|
||||
/docs/generated/packages/workspace/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
|
||||
/packages/nx/** @nrwl/nx-core-reviewers
|
||||
/packages/nx/src/adapter @nrwl/nx-core-reviewers @leosvelperez
|
||||
/packages/nx/src/native @nrwl/nx-core-reviewers @nrwl/nx-native-reviewers
|
||||
@@ -179,6 +134,10 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
/e2e/workspace-create/** @nrwl/nx-core-reviewers
|
||||
/e2e/release/** @nrwl/nx-core-reviewers
|
||||
|
||||
# .NET
|
||||
/packages/dotnet/** @FrozenPandaz @AgentEnder
|
||||
/e2e/dotnet/** @FrozenPandaz @AgentEnder
|
||||
|
||||
# Misc
|
||||
/e2e/lerna-smoke-tests/** @vsavkin @JamesHenry
|
||||
/e2e/utils/** @meeroslav @nrwl/nx-testing-tools-reviewers @vsavkin
|
||||
@@ -194,6 +153,7 @@ rust-toolchain.toml @nrwl/nx-native-reviewers
|
||||
|
||||
# CI
|
||||
/.nx/workflows/** @nrwl/nx-pipelines-reviewers
|
||||
mise.toml @nrwl/nx-pipelines-reviewers @FrozenPandaz
|
||||
/.github/** @nrwl/nx-pipelines-reviewers
|
||||
/.husky/** @nrwl/nx-pipelines-reviewers
|
||||
/packages/workspace/src/generators/ci-workflow/** @nrwl/nx-pipelines-reviewers
|
||||
@@ -208,6 +168,3 @@ project.json @FrozenPandaz @vsavkin
|
||||
jest.config.ts @nrwl/nx-testing-tools-reviewers @FrozenPandaz
|
||||
jest.preset.js @nrwl/nx-testing-tools-reviewers @FrozenPandaz
|
||||
|
||||
# Overrides - These are applied last, so override any matches above.
|
||||
docs/generated/manifests/* @nrwl/nrwlians
|
||||
docs/generated/packages-metadata.json @FrozenPandaz @jaysoo @AgentEnder @nrwl/nx-docs-reviewers
|
||||
|
||||
@@ -7,7 +7,7 @@ We would love for you to contribute to Nx! Read this document to see how to do i
|
||||
Watch this 5-minute video:
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=8LCA_4qxc08" target="_blank" rel="noreferrer">
|
||||
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600" alt="Nx - How to contribute"></p>
|
||||
<p style="text-align: center;"><img src="./images/how-to-contribute.png" width="600" alt="Nx - How to contribute"></p>
|
||||
</a>
|
||||
|
||||
## Got a Question?
|
||||
@@ -194,76 +194,73 @@ To build Nx on Windows, you need to use WSL.
|
||||
## Documentation Contributions
|
||||
|
||||
We would love for you to contribute to our documentation as well! Please feel welcome to submit fixes or enhancements to
|
||||
our existing documentation pages and the `nx-dev` application in this repo.
|
||||
our existing documentation pages, `astro-docs` and the `nx-dev` application in this repo.
|
||||
|
||||
### Documentation Structure
|
||||
|
||||
#### Documentation Pages
|
||||
|
||||
Our documentation pages can be found within this repo under the `docs` directory.
|
||||
Our documentation pages can be found within this repo under the `astro-docs/src/content/docs` directory.
|
||||
|
||||
The `docs/map.json` file is considered our source of truth for our site's structure, and should be updated when adding a
|
||||
new page to our documentation to ensure that it is included in the documentation site. We also run automated scripts
|
||||
based on this `map.json` data to safeguard against common human errors that could break our site.
|
||||
Documentation is written in `.mdoc` (Markdoc) or `.mdx` (MDX) format and supports custom Markdoc tags for rich content
|
||||
such as videos, graphs, interactive components, and more. See the `astro-docs/README.md` for a full list of available
|
||||
custom tags and their usage.
|
||||
|
||||
When you make a change to the `map.json` file, make sure to run `pnpm documentation` to propagate your changes to the `nx-dev` application.
|
||||
The sidebar structure is defined in `astro-docs/sidebar.mts` and should be updated when adding new sections or pages
|
||||
to ensure proper navigation.
|
||||
|
||||
#### Astro-Docs Application
|
||||
|
||||
Our public `nx.dev/docs` documentation site is built with [Astro](https://astro.build) and [Starlight](https://starlight.astro.build),
|
||||
and can be found in the `astro-docs` directory of this repo. See [docs README for more details](./astro-docs/README.md)
|
||||
|
||||
#### Nx-Dev Application
|
||||
|
||||
Our public `nx.dev` documentation site is a [Next.js](https://nextjs.org/) application, that can be found in
|
||||
the `nx-dev` directory of this repo.
|
||||
The documentation site is consuming the `docs/` directly by copy-ing its content while deploying, so the website is
|
||||
always in sync and reflects the latest version of `docs/`.
|
||||
The `nx-dev` directory contains a [Next.js](https://nextjs.org/) application used for blog posts and landing pages.
|
||||
|
||||
Jump to [Running the Documentation Site Locally](#running-the-documentation-site-locally) to see how to preview your
|
||||
changes while serving.
|
||||
|
||||
### Changing Generated API documentation
|
||||
|
||||
`.md` files documenting the API for our CLI (including executor and generator API docs) are generated via the
|
||||
corresponding `schema.json` file for the given command.
|
||||
API documentation for CLI commands, executors, and generators is automatically generated during the build process from
|
||||
the corresponding `schema.json` files in each package.
|
||||
|
||||
After adjusting the `schema.json` file, `.md` files for these commands can be generated by running:
|
||||
The documentation is generated using content loaders in the `astro-docs` application and requires a rebuild to reflect
|
||||
changes. After adjusting a `schema.json` file:
|
||||
|
||||
```bash
|
||||
pnpm documentation
|
||||
```
|
||||
|
||||
This will update the corresponding contents of the `docs` directory. These are generated automatically on push (via
|
||||
husky) as well.
|
||||
1. Restart the development server with `nx serve astro-docs` to see the changes
|
||||
2. Or run `nx preview astro-docs` to view the built site locally
|
||||
|
||||
Note that adjusting the `schema.json` files will also affect the CLI manuals and Nx Console behavior, in addition to
|
||||
adjusting the docs.
|
||||
the generated documentation.
|
||||
|
||||
### Running the Documentation Site Locally
|
||||
|
||||
To run `nx-dev` locally, run the command:
|
||||
To run the documentation site locally, run the command:
|
||||
|
||||
```bash
|
||||
npx nx serve-docs nx-dev
|
||||
```shell
|
||||
nx serve astro-docs
|
||||
```
|
||||
|
||||
You can then access the application locally at `localhost:4200`. Changes to markdown documentation files will be automatically applied to the site when you refresh the browser.
|
||||
You can then access the application locally at `localhost:4321`. Changes to markdoc files should reflect automatically in the browser on save.
|
||||
|
||||
#### Troubleshooting: `JavaScript heap out of memory`
|
||||
#### Working with Plugin Registry
|
||||
|
||||
If you see an error that states: `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`,
|
||||
you need
|
||||
to [increase the max memory size of V8's old memory section](https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes):
|
||||
To view plugin registry statistics (GitHub stars, npm downloads, etc.) during local development:
|
||||
|
||||
```bash
|
||||
export NODE_OPTIONS="--max-old-space-size=4096"
|
||||
NX_DOCS_PLUGIN_STATS=true nx serve astro-docs
|
||||
```
|
||||
|
||||
After configuring this, try to run `npx nx serve nx-dev` again.
|
||||
Note: Plugin stats are disabled by default in development to improve performance.
|
||||
|
||||
### PR Preview
|
||||
|
||||
When submitting a PR, this repo will automatically generate a preview of the `nx-dev` application based on the contents
|
||||
When submitting a PR, this repo will automatically generate a preview of the documentation site based on the contents
|
||||
of your pull request.
|
||||
|
||||
Once the preview site is launched, a comment will automatically be added to your PR with the link your PR's preview. To
|
||||
check your docs changes, make sure to select `Preview` from the version selection box of the site.
|
||||
Once the preview site is launched, a comment will automatically be added to your PR with the link to your PR's preview.
|
||||
|
||||
## Submission Guidelines
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ dependencies = [
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.59.0",
|
||||
"wl-clipboard-rs",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
@@ -395,7 +396,7 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"nom 7.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -914,6 +915,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.1"
|
||||
@@ -2271,6 +2278,15 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "normalize-path"
|
||||
version = "0.2.1"
|
||||
@@ -2391,7 +2407,7 @@ dependencies = [
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
"nix 0.30.0",
|
||||
"nom",
|
||||
"nom 7.1.3",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"portable-pty",
|
||||
@@ -2524,6 +2540,16 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@@ -2571,6 +2597,17 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"hashbrown 0.15.2",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.10.0"
|
||||
@@ -2780,6 +2817,15 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.5"
|
||||
@@ -4200,6 +4246,17 @@ dependencies = [
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree_magic_mini"
|
||||
version = "3.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"nom 8.0.0",
|
||||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triomphe"
|
||||
version = "0.1.11"
|
||||
@@ -4588,6 +4645,76 @@ dependencies = [
|
||||
"watchexec-signals",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-backend"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
"rustix 1.0.5",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.31.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"rustix 1.0.5",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.32.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols-wlr"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.31.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.31.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
@@ -4990,6 +5117,25 @@ dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wl-clipboard-rs"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a083daad7e8a4b8805ad73947ccadabe62afe37ce0e9787a56ff373d34762c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"os_pipe",
|
||||
"rustix 0.38.38",
|
||||
"tempfile",
|
||||
"thiserror 1.0.58",
|
||||
"tree_magic_mini",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-wlr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<p style="text-align: center;">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
|
||||
<img alt="Nx - Smart Repos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="./images/nx-dark.svg">
|
||||
<img alt="Nx - Smart Repos · Fast Builds" src="./images/nx-light.svg" width="100%">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
@@ -67,7 +67,7 @@ our [guidelines for contributing](https://github.com/nrwl/nx/blob/master/CONTRIB
|
||||
help you get started.
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=8LCA_4qxc08" target="_blank" rel="noreferrer">
|
||||
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600" alt="Nx - How to contribute video"></p>
|
||||
<p style="text-align: center;"><img src="./images/how-to-contribute.png" width="600" alt="Nx - How to contribute video"></p>
|
||||
</a>
|
||||
|
||||
## Core Team
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.spec.ts", "**/*.test.ts", "**/*.spec.js", "**/*.test.js"],
|
||||
"rules": {
|
||||
"playwright/no-standalone-expect": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { sidebar } from './sidebar.mts';
|
||||
|
||||
const BASE = '/docs';
|
||||
|
||||
// This is exposed as window.__CONFIG
|
||||
const PUBLIC_CONFIG = {
|
||||
cookiebotDisabled: process.env.COOKIEBOT_DISABLED === 'true',
|
||||
cookiebotId: process.env.COOKIEBOT_ID ?? null,
|
||||
@@ -49,6 +50,7 @@ export default defineConfig({
|
||||
dark: './src/assets/nx/Nx-light.png',
|
||||
replacesTitle: true,
|
||||
},
|
||||
disable404Route: true,
|
||||
head: [
|
||||
{
|
||||
tag: 'script',
|
||||
@@ -88,6 +90,7 @@ export default defineConfig({
|
||||
'./src/plugins/sidebar-reference-updater.middleware.ts',
|
||||
'./src/plugins/sidebar-icons.middleware.ts',
|
||||
'./src/plugins/og.middleware.ts',
|
||||
'./src/plugins/github-stars.middleware.ts',
|
||||
],
|
||||
markdown: {
|
||||
// this breaks the renderMarkdown function in the plugin loader due to starlight path normalization
|
||||
@@ -124,6 +127,29 @@ export default defineConfig({
|
||||
Sidebar: './src/components/layout/Sidebar.astro',
|
||||
TwoColumnContent: './src/components/layout/TwoColumnContent.astro',
|
||||
PageTitle: './src/components/layout/PageTitle.astro',
|
||||
TableOfContents: './src/components/layout/TableOfContents.astro',
|
||||
},
|
||||
pagefind: {
|
||||
ranking: {
|
||||
// termFrequency changes the ranking balance between
|
||||
// frequency of the term relative to document length
|
||||
// versus weighted term count.
|
||||
// default is 1.0
|
||||
termFrequency: 0.75,
|
||||
// pageLength changes the way ranking compares page lengths with the average page lengths on your site.
|
||||
// default 0.75
|
||||
pageLength: 0.5,
|
||||
// termSaturation controls how quickly a term “saturates” on a page.
|
||||
// Once a term has appeared on a page many times,
|
||||
// further appearances have a reduced impact on the page rank.
|
||||
// default: 1.4
|
||||
// termSaturation: 1.4,
|
||||
// termSimilarity changes the ranking based on
|
||||
// similarity of terms to the search query.
|
||||
// Currently this only takes the length of the term into account.
|
||||
// default is 1.0
|
||||
// termSimilarity: 1.0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
react(),
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('should apply system theme by default', async ({ page }) => {
|
||||
await page.goto('/docs/getting-started/intro');
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'What is Nx?' })
|
||||
).toBeVisible();
|
||||
|
||||
const themeSelector = page.getByRole('combobox', {
|
||||
name: /theme/i,
|
||||
});
|
||||
|
||||
await expect(themeSelector).toBeVisible();
|
||||
|
||||
await expect(themeSelector).toHaveValue('auto');
|
||||
|
||||
const dataTheme = await page.evaluate(
|
||||
() => document.documentElement.dataset.theme
|
||||
);
|
||||
// The data-theme should be either 'light' or 'dark' based on system preference
|
||||
// It won't be 'auto' on the document element
|
||||
expect(['light', 'dark']).toContain(dataTheme);
|
||||
});
|
||||
|
||||
test('should switch to between light and dark theme', async ({ page }) => {
|
||||
await page.goto('/docs/getting-started/intro');
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'What is Nx?' })
|
||||
).toBeVisible();
|
||||
|
||||
const themeSelector = page.getByRole('combobox', {
|
||||
name: /theme/i,
|
||||
});
|
||||
|
||||
await test.step('light theme renders', async () => {
|
||||
await expect(themeSelector).toBeVisible();
|
||||
|
||||
await themeSelector.selectOption('light');
|
||||
|
||||
await expect(themeSelector).toHaveValue('light');
|
||||
|
||||
const dataTheme = await page.evaluate(
|
||||
() => document.documentElement.dataset.theme
|
||||
);
|
||||
expect(dataTheme).toBe('light');
|
||||
});
|
||||
|
||||
await test.step('dark theme renders', async () => {
|
||||
await themeSelector.selectOption('dark');
|
||||
|
||||
await expect(themeSelector).toHaveValue('dark');
|
||||
|
||||
const dataTheme = await page.evaluate(
|
||||
() => document.documentElement.dataset.theme
|
||||
);
|
||||
expect(dataTheme).toBe('dark');
|
||||
});
|
||||
|
||||
await test.step('switch back to auto', async () => {
|
||||
await themeSelector.selectOption('auto');
|
||||
|
||||
await expect(themeSelector).toHaveValue('auto');
|
||||
|
||||
const dataTheme = await page.evaluate(
|
||||
() => document.documentElement.dataset.theme
|
||||
);
|
||||
expect(['light', 'dark']).toContain(dataTheme);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,8 @@
|
||||
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
|
||||
import {
|
||||
defineMarkdocConfig,
|
||||
component,
|
||||
Markdoc,
|
||||
} from '@astrojs/markdoc/config';
|
||||
import starlightMarkdoc from '@astrojs/starlight-markdoc';
|
||||
|
||||
export default defineMarkdocConfig({
|
||||
@@ -143,7 +147,6 @@ export default defineMarkdocConfig({
|
||||
},
|
||||
graph: {
|
||||
render: component('./src/components/markdoc/Graph.astro'),
|
||||
children: [],
|
||||
attributes: {
|
||||
jsonFile: {
|
||||
type: 'String',
|
||||
@@ -161,6 +164,24 @@ export default defineMarkdocConfig({
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
transform(node, config) {
|
||||
const attributes = node.transformAttributes(config);
|
||||
let rawContent = null;
|
||||
for (const child of node.children) {
|
||||
if (child.type === 'fence') {
|
||||
rawContent = child.attributes.content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Markdoc.Tag(
|
||||
this.render,
|
||||
{
|
||||
...attributes,
|
||||
astroRawData: rawContent,
|
||||
},
|
||||
[]
|
||||
);
|
||||
},
|
||||
},
|
||||
iframe: {
|
||||
render: component('./src/components/markdoc/Iframe.astro'),
|
||||
@@ -284,6 +305,24 @@ export default defineMarkdocConfig({
|
||||
type: 'Array',
|
||||
},
|
||||
},
|
||||
transform(node, config) {
|
||||
const attributes = node.transformAttributes(config);
|
||||
let rawContent = null;
|
||||
for (const child of node.children) {
|
||||
if (child.type === 'fence') {
|
||||
rawContent = child.attributes.content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Markdoc.Tag(
|
||||
this.render,
|
||||
{
|
||||
...attributes,
|
||||
astroRawData: rawContent,
|
||||
},
|
||||
[]
|
||||
);
|
||||
},
|
||||
},
|
||||
stackblitz_button: {
|
||||
render: component('./src/components/markdoc/StackblitzButton.astro'),
|
||||
@@ -384,14 +423,5 @@ export default defineMarkdocConfig({
|
||||
},
|
||||
},
|
||||
},
|
||||
side_by_side: {
|
||||
render: component('./src/components/markdoc/SideBySide.astro'),
|
||||
attributes: {
|
||||
align: {
|
||||
type: 'String',
|
||||
default: 'center',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# Permanent redirects (301 by default)
|
||||
|
||||
# Storybook docs consolidation
|
||||
[[redirects]]
|
||||
from = "/docs/technologies/test-tools/storybook/guides/storybook-9-setup"
|
||||
to = "/docs/technologies/test-tools/storybook/guides/upgrading-storybook"
|
||||
|
||||
[[redirects]]
|
||||
from = "/"
|
||||
to = "/docs/getting-started/intro"
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
"@astrojs/starlight": "0.34.6",
|
||||
"@astrojs/starlight-markdoc": "^0.4.0",
|
||||
"@astrojs/starlight-tailwind": "^4.0.1",
|
||||
"@nx/nx-dev-feature-analytics": "workspace:*",
|
||||
"@nx/nx-dev-ui-animations": "workspace:*",
|
||||
"@nx/nx-dev-ui-common": "workspace:*",
|
||||
"@nx/nx-dev-ui-icons": "workspace:*",
|
||||
"@nx/nx-dev-ui-markdoc": "workspace:*",
|
||||
@@ -17,6 +19,7 @@
|
||||
"astro": "^5.10.1",
|
||||
"astro-og-canvas": "^0.7.0",
|
||||
"canvaskit-wasm": "^0.40.0",
|
||||
"octokit": "^2.0.14",
|
||||
"tailwindcss": "4.1.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"continuous": true,
|
||||
"dependsOn": [
|
||||
{
|
||||
"projects": ["devkit", "create-nx-workspace"],
|
||||
"projects": ["devkit", "create-nx-workspace", "dotnet", "maven"],
|
||||
"target": "build"
|
||||
}
|
||||
],
|
||||
@@ -19,7 +19,7 @@
|
||||
"build": {
|
||||
"dependsOn": [
|
||||
{
|
||||
"projects": ["devkit", "create-nx-workspace"],
|
||||
"projects": ["devkit", "create-nx-workspace", "dotnet", "maven"],
|
||||
"target": "build"
|
||||
}
|
||||
],
|
||||
@@ -48,8 +48,8 @@
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["validate-links"],
|
||||
"command": "echo done"
|
||||
"executor": "nx:noop",
|
||||
"dependsOn": ["vite:test", "validate-links", "format"]
|
||||
},
|
||||
"pw-e2e": {
|
||||
"dependsOn": ["serve"],
|
||||
@@ -57,7 +57,10 @@
|
||||
},
|
||||
"e2e-ci--**/*": {
|
||||
"dependsOn": ["preview"],
|
||||
"parallelism": true
|
||||
"parallelism": true,
|
||||
"options": {
|
||||
"args": []
|
||||
}
|
||||
},
|
||||
"show-report": {
|
||||
"command": "playwright show-report dist/astro-docs/playwright-report"
|
||||
@@ -73,10 +76,18 @@
|
||||
"{projectRoot}/tsconfig.json",
|
||||
"{projectRoot}/package.json"
|
||||
],
|
||||
"command": "npx tsx validate-links.ts",
|
||||
"command": "tsx validate-links.ts",
|
||||
"options": {
|
||||
"cwd": "astro-docs"
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"cache": true,
|
||||
"//": "nx format doesn't respect overrides, so we manually run prettier for mdoc files",
|
||||
"command": "prettier **/*.mdoc --check"
|
||||
},
|
||||
"format:write": {
|
||||
"command": "prettier **/*.mdoc --write"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,40 @@
|
||||
(function () {
|
||||
// Open search modal if signaled via sessionStorage (e.g., from Cmd+K on non-docs pages)
|
||||
var SEARCH_STORAGE_KEY = 'nx-open-search';
|
||||
var SEARCH_EXPIRY_MS = 30000; // 30 seconds
|
||||
|
||||
function openSearchFromStorage() {
|
||||
var timestamp = sessionStorage.getItem(SEARCH_STORAGE_KEY);
|
||||
if (!timestamp) return;
|
||||
|
||||
// Clear immediately to prevent re-triggering
|
||||
sessionStorage.removeItem(SEARCH_STORAGE_KEY);
|
||||
|
||||
// Check if expired (older than 30 seconds)
|
||||
var age = Date.now() - parseInt(timestamp, 10);
|
||||
if (age > SEARCH_EXPIRY_MS) return;
|
||||
|
||||
var openSearchBtn = document.querySelector('button[data-open-modal]');
|
||||
if (openSearchBtn) {
|
||||
openSearchBtn.click();
|
||||
// Focus the search input after modal opens
|
||||
setTimeout(function () {
|
||||
var searchInput = document.querySelector('dialog[open] input');
|
||||
if (searchInput) {
|
||||
searchInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Check on load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', openSearchFromStorage);
|
||||
} else {
|
||||
// Small delay to ensure search component is initialized
|
||||
setTimeout(openSearchFromStorage, 100);
|
||||
}
|
||||
|
||||
const config = window.__CONFIG || {};
|
||||
if (!config.isProd) return;
|
||||
|
||||
@@ -108,16 +144,77 @@
|
||||
window.twq('config', 'obtp4');
|
||||
};
|
||||
|
||||
const SEARCH_DEBOUNCE_MS = 1000;
|
||||
let searchDebounceTimer;
|
||||
let lastSearchQuery = '';
|
||||
let currentSearchInput = null;
|
||||
let inputHandler = null;
|
||||
|
||||
function sendSearchEvent(eventType, data) {
|
||||
if (typeof window.gtag !== 'undefined')
|
||||
window.gtag('event', eventType, data);
|
||||
}
|
||||
|
||||
function trackSearchQuery(query) {
|
||||
if (!query || query === lastSearchQuery) return;
|
||||
|
||||
clearTimeout(searchDebounceTimer);
|
||||
searchDebounceTimer = setTimeout(() => {
|
||||
lastSearchQuery = query;
|
||||
sendSearchEvent('search_query', {
|
||||
query: query,
|
||||
});
|
||||
}, SEARCH_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
function setupSearchTracking() {
|
||||
const observer = new MutationObserver(() => {
|
||||
const searchDialog = document.querySelector(
|
||||
'dialog[open] .search-container'
|
||||
);
|
||||
// If dialog is found, then set up tracking
|
||||
if (searchDialog) {
|
||||
if (currentSearchInput && inputHandler) return; // Already tracking
|
||||
const searchInput = searchDialog.querySelector(
|
||||
'input[type="search"], input[type="text"]'
|
||||
);
|
||||
if (searchInput) {
|
||||
inputHandler = (e) => {
|
||||
const query = e.target.value.trim();
|
||||
trackSearchQuery(query);
|
||||
};
|
||||
searchInput.addEventListener('input', inputHandler);
|
||||
currentSearchInput = searchInput;
|
||||
}
|
||||
}
|
||||
// If dialog is not found but we have handler, etc. then it must be closed and we should clean up
|
||||
else if (currentSearchInput && inputHandler) {
|
||||
currentSearchInput.removeEventListener('input', inputHandler);
|
||||
currentSearchInput = null;
|
||||
inputHandler = null;
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
attributeFilter: ['open'],
|
||||
});
|
||||
}
|
||||
|
||||
const checkAndLoadScripts = () => {
|
||||
if (isCookiebotDisabled) {
|
||||
loadGoogleAnalytics();
|
||||
loadGTM();
|
||||
loadHubSpot();
|
||||
setupSearchTracking();
|
||||
} else if (window.Cookiebot && window.Cookiebot.consent) {
|
||||
// Statistics cookies (Google Analytics, GTM)
|
||||
// Statistics cookies (Google Analytics, GTM, Search Tracking)
|
||||
if (window.Cookiebot.consent.statistics) {
|
||||
loadGoogleAnalytics();
|
||||
loadGTM();
|
||||
setupSearchTracking();
|
||||
}
|
||||
|
||||
// Marketing cookies (HubSpot, Apollo, Hotjar, Twitter)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>C#</title><path d="M1.194 7.543v8.913c0 1.103.588 2.122 1.544 2.674l7.718 4.456a3.086 3.086 0 0 0 3.088 0l7.718-4.456a3.087 3.087 0 0 0 1.544-2.674V7.543a3.084 3.084 0 0 0-1.544-2.673L13.544.414a3.086 3.086 0 0 0-3.088 0L2.738 4.87a3.085 3.085 0 0 0-1.544 2.673Zm5.403 2.914v3.087a.77.77 0 0 0 .772.772.773.773 0 0 0 .772-.772.773.773 0 0 1 1.317-.546.775.775 0 0 1 .226.546 2.314 2.314 0 1 1-4.631 0v-3.087c0-.615.244-1.203.679-1.637a2.312 2.312 0 0 1 3.274 0c.434.434.678 1.023.678 1.637a.769.769 0 0 1-.226.545.767.767 0 0 1-1.091 0 .77.77 0 0 1-.226-.545.77.77 0 0 0-.772-.772.771.771 0 0 0-.772.772Zm12.35 3.087a.77.77 0 0 1-.772.772h-.772v.772a.773.773 0 0 1-1.544 0v-.772h-1.544v.772a.773.773 0 0 1-1.317.546.775.775 0 0 1-.226-.546v-.772H12a.771.771 0 1 1 0-1.544h.772v-1.543H12a.77.77 0 1 1 0-1.544h.772v-.772a.773.773 0 0 1 1.317-.546.775.775 0 0 1 .226.546v.772h1.544v-.772a.773.773 0 0 1 1.544 0v.772h.772a.772.772 0 0 1 0 1.544h-.772v1.543h.772a.776.776 0 0 1 .772.772Zm-3.088-2.315h-1.544v1.543h1.544v-1.543Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>.NET</title><path d="M24 8.77h-2.468v7.565h-1.425V8.77h-2.462V7.53H24zm-6.852 7.565h-4.821V7.53h4.63v1.24h-3.205v2.494h2.953v1.234h-2.953v2.604h3.396zm-6.708 0H8.882L4.78 9.863a2.896 2.896 0 0 1-.258-.51h-.036c.032.189.048.592.048 1.21v5.772H3.157V7.53h1.659l3.965 6.32c.167.261.275.442.323.54h.024c-.04-.233-.06-.629-.06-1.185V7.529h1.372zm-8.703-.693a.868.829 0 0 1-.869.829.868.829 0 0 1-.868-.83.868.829 0 0 1 .868-.828.868.829 0 0 1 .869.829Z"/></svg>
|
||||
|
After Width: | Height: | Size: 534 B |
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>F#</title><path d="M0 12 11.39.61v5.695L5.695 12l5.695 5.695v5.695L0 12zm7.322 0 4.068-4.068v8.136L7.322 12zM24 12 12.203.61v5.695L17.898 12l-5.695 5.695v5.695L24 12z"/></svg>
|
||||
|
After Width: | Height: | Size: 253 B |
@@ -1,9 +1 @@
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>Java</title>
|
||||
<path d="m16.5093 4.9869-.0607-.0347c-1.1014.369-4.4915 1.707-4.4915 4.202 0 1.411 1.378 2.1925 1.378 3.5158 0 .472-.2666.9146-.4836 1.1791l.1091.063c.5735-.3728 1.589-1.18 1.589-2.2222 0-.8825-1.2216-1.943-1.2216-3.0774 0-1.7875 2.357-3.1899 3.1813-3.6256zm-1.6642-3.27c0 3.6925-5.0604 5.1055-5.0604 7.7309 0 1.843 1.2222 2.9987 1.8983 3.7293l-.055.0317c-.8536-.534-3.0995-1.876-3.0995-4.0927 0-3.112 5.8123-4.599 5.8123-8.134 0-.435-.0644-.7683-.1095-.9482L14.2901 0c.1842.2315.555.8102.555 1.7168m.514 14.9392c-.5962.1688-1.9389.4441-3.859.4441-1.8844 0-3.424-.3226-3.4289-.7024-.0032-.2527.3024-.3628.3024-.3628l-.0544-.0316c-.9023.1595-1.7406.406-1.7357.7752.0084.6698 2.5697 1.1728 4.9129 1.1728 1.992 0 3.9053-.3343 4.7684-.7722zm-6.368 2.0708c-.4185.0832-1.3305.2926-1.3305.7361 0 .6144 1.9513 1.085 3.835 1.085 2.5922 0 3.6539-.667 3.702-.7016l-1.078-.6235c-.4583.1092-1.2306.2808-2.6214.2808-1.5521 0-2.5634-.2658-2.5634-.5569 0-.0617.0386-.135.1106-.1886zm10.5923-4.1337c-.0725 1.3911-1.3577 2.2573-2.6423 2.9893l.1164.067c1.3708-.3855 3.8166-1.5085 3.6144-3.2346-.1007-.8608-.8875-1.4758-1.9133-1.4758-.3194 0-.6036.0563-.834.1265l-.0007.0022-.0486.1224c.9175-.1796 1.7558.4904 1.7082 1.403zm-8.1232 8.1638c3.6058-.0313 7.6402-.737 7.6298-1.9232-.0019-.215-.1418-.3622-.2635-.4513l-.0592.034c-.3333.9188-3.1508 1.5977-7.3132 1.634-2.6859.0234-6.4063-.62-6.4128-1.3636-.0065-.7455 1.7625-1.1552 1.7625-1.1552l-.125-.0714c-1.1854.1632-3.3697.731-3.3625 1.5506.0104 1.185 5.0304 1.7734 8.1439 1.7461zm-.375.847c-1.4333.0126-3.1833-.1061-4.6555-.3535l-.1363.0784c1.4664.43 3.508.6896 5.7514.6702 4.4059-.0386 7.9779-1.1311 8.0485-2.446l-.051-.0297c-.2953.3604-2.2009 2.0216-8.9572 2.0806zm-5.5195-9.328c0-.6646 2.521-1.0374 3.6947-1.1277l.112.0647c-.451.082-2.26.401-2.26.8172 0 .4532 2.7747.7501 4.3853.7501 2.7355 0 4.595-.414 5.095-.5505l.6997.4072c-.4792.2346-2.5362.8495-5.7945.8495-3.6214 0-5.9322-.7086-5.9322-1.2105" />
|
||||
</svg>
|
||||
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 16.921875 2.25 C 16.71679725 2.26171875 16.4970705 2.3408205 16.2890625 2.5078125 C 15.40722675 3.2138669999999996 15.541992 3.5771482499999996 15.1171875 4.4296875 C 14.973633 4.9248045 14.736328499999999 4.962891 14.53125 4.5234375 C 14.28515625 4.08691425 14.16503925 3.5419919999999996 13.78125 3.2109375 C 13.16308575 2.67773475 12.4658205 3.0791017500000004 12.84375 3.6796875 C 13.2216795 4.28027325 13.376953499999999 4.91308575 13.5234375 5.90625 C 13.74316425 7.3857420000000005 13.125 9.03222675 12.3046875 9.8203125 C 10.822266 6.7880857500000005 8.885742 4.53808575 7.5234375 3.84375 C 7.1103517499999995 3.6328125 6.984375 3.80859375 6.984375 4.0078125 C 7.2421875 6.978516000000001 7.3359375 9.02929725 7.171875 10.546875 C 7.0986329999999995 11.2265625 5.49609375 13.734375 5.578125 14.3203125 C 5.66015625 14.9033205 6.12890625 15.817383 6.4453125 16.2890625 C 6.31640625 16.1953125 5.99121075 16.4091795 6.0703125 16.7109375 C 5.49902325 17.03027325 5.551758 17.51953125 6.140625 17.6484375 C 6.29296875 18.0439455 6.3251954999999995 18.24023475 6.75 18.421875 C 6.66796875 19.25683575 6.580078500000001 20.11523475 6.4921875 21.046875 C 6.873047250000001 22.921875 9.776367 19.67871075 10.1484375 19.40625 C 12.161133 17.9296875 12.46875 21.15234375 13.875 21.65625 C 16.2421875 22.5029295 15.474609749999999 17.52246075 13.5703125 12.6328125 C 13.34472675 9.489258 14.40234375 8.59277325 15.421875 8.1796875 C 15.958008 8.00390625 16.3564455 7.96875 17.0859375 8.1796875 C 18.33984375 8.54003925 18.60058575 7.11328125 17.484375 6.9375 C 17.0595705 6.8701170000000005 16.7519535 6.8759767499999995 16.359375 6.703125 C 16.5175785 6.0732420000000005 17.14453125 6.041016000000001 17.765625 5.953125 C 19.17773475 5.75390625 19.0546875 4.23046875 17.484375 4.59375 C 16.7988285 4.754883 16.49121075 5.16210975 16.2421875 5.15625 C 16.56152325 4.573242 17.10058575 4.072266 17.625 3.328125 C 18.0175785 2.7685545 17.5341795 2.21484375 16.921875 2.25 Z M 9.6328125 7.734375 C 9.817383 7.7109375 9.978516 7.72265625 10.1484375 7.78125 C 10.8251955 8.009766 11.05371075 8.87109375 10.640625 9.6796875 C 10.22753925 10.48828125 9.3251955 10.9394535 8.6484375 10.7109375 C 7.9716795000000005 10.48242225 7.7666017499999995 9.64453125 8.1796875 8.8359375 C 8.49023475 8.229492 9.07910175 7.8076170000000005 9.6328125 7.734375 Z M 8.90625 8.8359375 C 8.80371075 8.838867 8.698242 8.89746075 8.6015625 9 C 8.4082035 9.208008 8.34375 9.55078125 8.4609375 9.75 C 8.5810545 9.94921875 8.8300785 9.9345705 9.0234375 9.7265625 C 9.21679725 9.5185545 9.2841795 9.17578125 9.1640625 8.9765625 C 9.10546875 8.8769535 9.00878925 8.833008 8.90625 8.8359375 Z M 11.390625 10.7578125 C 12.521484749999999 12.919922249999999 13.587890999999999 15.48046875 13.8046875 18.3984375 C 13.90722675 19.78710975 12.791015999999999 18.28710975 12.65625 18.046875 C 10.359375 13.91015625 7.4091795000000005 22.40625 7.9921875 17.0859375 C 8.2939455 14.89453125 8.4404295 14.604492 8.5078125 12.046875 C 8.5078125 12.046875 10.265625 12.963867 11.390625 10.7578125 Z M 7.21875 13.2890625 C 7.1630857500000005 14.0126955 7.1484375 14.490234749999999 7.078125 15.234375 C 6.9228517499999995 14.830078499999999 6.7177732500000005 14.7890625 6.609375 14.4140625 C 6.8349607500000005 14.16796875 6.990234750000001 13.6875 7.21875 13.2890625 Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Visual Basic</title><path d="M6.363 17.719a7.57 7.57 0 0 1 .34-1.348L10.887 4.5h1.863l-5.473 15h-1.91L0 4.5h1.934l4.09 11.895c.078.218.14.437.187.656s.098.441.152.668zM20.66 11.53c.5.063.957.188 1.371.375s.766.442 1.055.762.512.691.668 1.113.238.89.246 1.406c0 .696-.133 1.31-.398 1.84s-.622.98-1.067 1.348-.96.645-1.547.832-1.203.285-1.851.293h-4.371v-15h4.265c.54 0 1.059.066 1.559.2s.95.335 1.348.609.714.628.949 1.066.355.957.363 1.559c0 .859-.227 1.601-.68 2.226s-1.09 1.067-1.91 1.324v.047zm-4.137-.597h1.793c.43 0 .832-.051 1.207-.153s.704-.258.985-.469.5-.488.656-.832.238-.746.246-1.207c0-.43-.078-.785-.234-1.066s-.367-.504-.633-.668-.57-.277-.914-.34-.707-.097-1.09-.105h-2.016v4.84zm2.38 6.972c.437 0 .85-.05 1.242-.152s.738-.262 1.043-.48.539-.5.703-.844.254-.762.27-1.254c0-.54-.102-.98-.306-1.324s-.476-.614-.82-.809-.73-.332-1.16-.41-.875-.117-1.336-.117h-2.016v5.39h2.38z"/></svg>
|
||||
|
After Width: | Height: | Size: 975 B |
@@ -108,8 +108,27 @@ export const sidebar: StarlightUserConfig['sidebar'] = [
|
||||
{
|
||||
label: 'Java',
|
||||
collapsed: true,
|
||||
// when we have maven this will change to not have gradle as the top docs for Java
|
||||
items: getPluginItems('gradle', 'java'),
|
||||
items: [
|
||||
{
|
||||
label: 'Introduction',
|
||||
link: 'technologies/java/introduction',
|
||||
},
|
||||
{
|
||||
label: 'Gradle',
|
||||
collapsed: true,
|
||||
items: getPluginItems('gradle', 'java'),
|
||||
},
|
||||
{
|
||||
label: 'Maven',
|
||||
collapsed: true,
|
||||
items: getPluginItems('maven', 'java'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '.NET',
|
||||
collapsed: true,
|
||||
items: getPluginItems('dotnet'),
|
||||
},
|
||||
{
|
||||
label: 'Module Federation',
|
||||
@@ -162,6 +181,11 @@ export const sidebar: StarlightUserConfig['sidebar'] = [
|
||||
collapsed: true,
|
||||
items: getPluginItems('rsbuild', 'build-tools'),
|
||||
},
|
||||
{
|
||||
label: 'Docker',
|
||||
collapsed: true,
|
||||
items: getPluginItems('docker', 'build-tools'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -173,6 +197,11 @@ export const sidebar: StarlightUserConfig['sidebar'] = [
|
||||
collapsed: true,
|
||||
items: getPluginItems('cypress', 'test-tools'),
|
||||
},
|
||||
{
|
||||
label: 'Vitest',
|
||||
collapsed: true,
|
||||
items: getPluginItems('vitest', 'test-tools'),
|
||||
},
|
||||
{
|
||||
label: 'Jest',
|
||||
collapsed: true,
|
||||
|
||||
@@ -5385,11 +5385,6 @@
|
||||
"hash": "04d21c10923d481ce024556edc1c49f845e225d1",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-10-0/update-decorate-cli.ts",
|
||||
"hash": "9334b9a991673222b3ed0282b748a6de9eca2ced",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-10-0/update-tasks-runner.ts",
|
||||
"hash": "37f930864bf0d5ff771eb4d691ab8cfcb9673802",
|
||||
@@ -5425,11 +5420,6 @@
|
||||
"hash": "addea9c1bc5a5eef2d856439b8f9bc4e4d0993e4",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-9-0/update-decorate-cli.ts",
|
||||
"hash": "eae7efc8c2562ec1948245df2a84223d41e63bce",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-14-0-0/change-npm-script-executor.spec.ts",
|
||||
"hash": "ba26be4f1b2644f191bfa3cb9ae4b0c8f8f75e9c",
|
||||
@@ -20656,11 +20646,6 @@
|
||||
"file": "packages/cli/jest.config.ts",
|
||||
"hash": "5a6bcdc5c0f2540e13206f7276ef09ccf886a305"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/lib/decorate-cli.ts",
|
||||
"hash": "fbb9636c447e0e8a3af4c1f6446ffd7103388431",
|
||||
"deps": ["nx"]
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/package.json",
|
||||
"hash": "9c5ad8ce7142606dc835b87ea36c40c649d5910f",
|
||||
@@ -22580,10 +22565,6 @@
|
||||
"npm:@angular-devkit/core"
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "packages/nx/src/adapter/decorate-cli.ts",
|
||||
"hash": "7126a16e8c98f8cb4c2eec1b80a3f8db3c65bff0"
|
||||
},
|
||||
{
|
||||
"file": "packages/nx/src/adapter/ngcli-adapter.ts",
|
||||
"hash": "16fd0f04b1dd33aee828d543d8a941e0a934905e",
|
||||
|
||||
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 387 KiB |
|
After Width: | Height: | Size: 322 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 397 KiB |
|
After Width: | Height: | Size: 453 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 281 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -5385,11 +5385,6 @@
|
||||
"hash": "04d21c10923d481ce024556edc1c49f845e225d1",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-10-0/update-decorate-cli.ts",
|
||||
"hash": "9334b9a991673222b3ed0282b748a6de9eca2ced",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-10-0/update-tasks-runner.ts",
|
||||
"hash": "37f930864bf0d5ff771eb4d691ab8cfcb9673802",
|
||||
@@ -5425,11 +5420,6 @@
|
||||
"hash": "addea9c1bc5a5eef2d856439b8f9bc4e4d0993e4",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-13-9-0/update-decorate-cli.ts",
|
||||
"hash": "eae7efc8c2562ec1948245df2a84223d41e63bce",
|
||||
"deps": ["devkit"]
|
||||
},
|
||||
{
|
||||
"file": "packages/workspace/src/migrations/update-14-0-0/change-npm-script-executor.spec.ts",
|
||||
"hash": "ba26be4f1b2644f191bfa3cb9ae4b0c8f8f75e9c",
|
||||
@@ -20656,11 +20646,6 @@
|
||||
"file": "packages/cli/jest.config.ts",
|
||||
"hash": "5a6bcdc5c0f2540e13206f7276ef09ccf886a305"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/lib/decorate-cli.ts",
|
||||
"hash": "fbb9636c447e0e8a3af4c1f6446ffd7103388431",
|
||||
"deps": ["nx"]
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/package.json",
|
||||
"hash": "9c5ad8ce7142606dc835b87ea36c40c649d5910f",
|
||||
@@ -22580,10 +22565,6 @@
|
||||
"npm:@angular-devkit/core"
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "packages/nx/src/adapter/decorate-cli.ts",
|
||||
"hash": "7126a16e8c98f8cb4c2eec1b80a3f8db3c65bff0"
|
||||
},
|
||||
{
|
||||
"file": "packages/nx/src/adapter/ngcli-adapter.ts",
|
||||
"hash": "16fd0f04b1dd33aee828d543d8a941e0a934905e",
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
import { useState, useMemo } from 'react';
|
||||
|
||||
export type PluginType = 'official' | 'community';
|
||||
|
||||
export interface Plugin {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
url: string;
|
||||
pluginType: PluginType;
|
||||
lastPublishedDate?: string;
|
||||
npmDownloads?: number;
|
||||
githubStars?: number;
|
||||
nxVersion?: string;
|
||||
}
|
||||
|
||||
type OrderByStatus =
|
||||
| 'lastPublishedDate'
|
||||
| 'npmDownloads'
|
||||
| 'githubStars'
|
||||
| 'nxVersion'
|
||||
| undefined;
|
||||
|
||||
interface Modifiers {
|
||||
term: string;
|
||||
orderBy: OrderByStatus;
|
||||
orderDirection: 'ASC' | 'DESC';
|
||||
}
|
||||
|
||||
function shortenNumber(num: number | undefined): string {
|
||||
if (!num) return '—';
|
||||
if (num >= 1_000_000) {
|
||||
return Math.floor(num / 1_000_000) + 'M';
|
||||
}
|
||||
if (num >= 1_000) {
|
||||
return Math.floor(num / 1_000) + 'k';
|
||||
}
|
||||
return num.toString();
|
||||
}
|
||||
|
||||
function formatDate(dateStr: string | undefined): string {
|
||||
if (!dateStr) return '—';
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
}).format(new Date(dateStr));
|
||||
}
|
||||
|
||||
function ClockIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function DownloadIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function StarIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function SearchIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function ArrowUpIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function ArrowDownIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function NxIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>Nx</title>
|
||||
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function GitHubIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
className={className}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>GitHub</title>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function PluginCard({ plugin }: { plugin: Plugin }) {
|
||||
const isExternal = plugin.pluginType === 'community';
|
||||
|
||||
return (
|
||||
<a
|
||||
href={plugin.url}
|
||||
target={isExternal ? '_blank' : undefined}
|
||||
rel={isExternal ? 'noopener noreferrer' : undefined}
|
||||
className="block h-full rounded-lg border border-slate-200 bg-gray-50 p-4 no-underline transition-colors hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-800/50 dark:hover:bg-slate-800"
|
||||
>
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="mb-3 flex items-center gap-3">
|
||||
<GitHubIcon className="h-6 w-6 flex-shrink-0 text-gray-600 dark:text-slate-400" />
|
||||
<h3 className="text-base font-medium leading-tight text-gray-900 dark:text-slate-100">
|
||||
{plugin.name}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<p className="mb-4 line-clamp-3 flex-grow text-sm text-gray-600 dark:text-slate-400">
|
||||
{plugin.description}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap items-center justify-between py-0.5 text-xs text-slate-700 dark:text-slate-400">
|
||||
{plugin.lastPublishedDate && (
|
||||
<div className="my-1 mr-1 flex items-center gap-1">
|
||||
<ClockIcon className="h-3.5 w-3.5" />
|
||||
<span>{formatDate(plugin.lastPublishedDate)}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="mx-1 my-1 flex items-center gap-1">
|
||||
<StarIcon className="h-4 w-4" />
|
||||
<span>{shortenNumber(plugin.githubStars)}</span>
|
||||
</div>
|
||||
<div className="mx-1 my-1 flex items-center gap-1">
|
||||
<DownloadIcon className="h-4 w-4" />
|
||||
<span>{shortenNumber(plugin.npmDownloads)}</span>
|
||||
</div>
|
||||
<div className="my-1 ml-1 flex flex-1 justify-end text-nowrap">
|
||||
{plugin.pluginType === 'official' ? (
|
||||
<span className="inline-flex items-center rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20 dark:bg-green-500/10 dark:text-green-400 dark:ring-green-500/20">
|
||||
Nx Open Source
|
||||
</span>
|
||||
) : plugin.nxVersion ? (
|
||||
<span className="inline-flex items-center rounded-full bg-amber-50 px-2 py-1 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20 dark:bg-amber-500/10 dark:text-amber-400 dark:ring-amber-500/20">
|
||||
Nx {plugin.nxVersion}
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-600/20 dark:bg-blue-500/10 dark:text-blue-400 dark:ring-blue-500/20">
|
||||
Community
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
interface OrderButtonProps {
|
||||
label: string;
|
||||
icon: React.ReactNode;
|
||||
orderKey: OrderByStatus;
|
||||
modifiers: Modifiers;
|
||||
onClick: (key: OrderByStatus) => void;
|
||||
}
|
||||
|
||||
function OrderButton({
|
||||
label,
|
||||
icon,
|
||||
orderKey,
|
||||
modifiers,
|
||||
onClick,
|
||||
}: OrderButtonProps) {
|
||||
const isActive = modifiers.orderBy === orderKey;
|
||||
|
||||
return (
|
||||
<button
|
||||
className={`flex items-center gap-1 rounded border px-1.5 py-0.5 font-medium transition
|
||||
${
|
||||
isActive
|
||||
? 'border-blue-500 bg-blue-50 text-blue-700 dark:border-blue-400 dark:bg-blue-900/30 dark:text-blue-300'
|
||||
: 'border-slate-200 bg-white hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700'
|
||||
}`}
|
||||
onClick={() => onClick(orderKey)}
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
{isActive && modifiers.orderDirection === 'ASC' && (
|
||||
<ArrowUpIcon className="h-3 w-3" />
|
||||
)}
|
||||
{isActive && modifiers.orderDirection === 'DESC' && (
|
||||
<ArrowDownIcon className="h-3 w-3" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function PluginDirectory({
|
||||
plugins: initialPlugins,
|
||||
}: {
|
||||
plugins: Plugin[];
|
||||
}) {
|
||||
const [modifiers, setModifiers] = useState<Modifiers>({
|
||||
term: '',
|
||||
orderBy: undefined,
|
||||
orderDirection: 'DESC',
|
||||
});
|
||||
|
||||
function setOrderBy(status: OrderByStatus) {
|
||||
if (modifiers.orderBy === status) {
|
||||
setModifiers({
|
||||
...modifiers,
|
||||
orderDirection: modifiers.orderDirection === 'ASC' ? 'DESC' : 'ASC',
|
||||
});
|
||||
} else {
|
||||
setModifiers({
|
||||
...modifiers,
|
||||
orderBy: status,
|
||||
orderDirection: 'DESC',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const filteredAndSortedPlugins = useMemo(() => {
|
||||
let result = [...initialPlugins];
|
||||
|
||||
// Filter by search term
|
||||
if (modifiers.term) {
|
||||
const term = modifiers.term.toLowerCase();
|
||||
result = result.filter(
|
||||
(plugin) =>
|
||||
plugin.name.toLowerCase().includes(term) ||
|
||||
plugin.description.toLowerCase().includes(term)
|
||||
);
|
||||
}
|
||||
|
||||
// Sort
|
||||
if (modifiers.orderBy) {
|
||||
const direction = modifiers.orderDirection === 'ASC' ? 1 : -1;
|
||||
|
||||
result.sort((a, b) => {
|
||||
switch (modifiers.orderBy) {
|
||||
case 'lastPublishDate': {
|
||||
const aTime = a.lastPublishedDate
|
||||
? new Date(a.lastPublishedDate).getTime()
|
||||
: 0;
|
||||
const bTime = b.lastPublishedDate
|
||||
? new Date(b.lastPublishedDate).getTime()
|
||||
: 0;
|
||||
return direction * (aTime - bTime);
|
||||
}
|
||||
case 'npmDownloads':
|
||||
return direction * ((a.npmDownloads || 0) - (b.npmDownloads || 0));
|
||||
case 'githubStars':
|
||||
return direction * ((a.githubStars || 0) - (b.githubStars || 0));
|
||||
case 'nxVersion': {
|
||||
const versionValueMap: Record<string, number> = {
|
||||
unknown: 0,
|
||||
'12': 12,
|
||||
'13': 13,
|
||||
'14': 14,
|
||||
'15': 15,
|
||||
'16': 16,
|
||||
'17': 17,
|
||||
'18': 18,
|
||||
'19': 19,
|
||||
'20': 20,
|
||||
'21': 21,
|
||||
'22': 22,
|
||||
'>= 15': 17,
|
||||
'>= 14': 16,
|
||||
'>= 13': 15,
|
||||
official: 1000,
|
||||
};
|
||||
function getValueFromVersion(
|
||||
version: string | undefined,
|
||||
pluginType: PluginType
|
||||
) {
|
||||
if (pluginType === 'official') return versionValueMap['official'];
|
||||
if (!version) return 0;
|
||||
const mapKey =
|
||||
Object.keys(versionValueMap).find((key) =>
|
||||
version.startsWith(key)
|
||||
) || 'unknown';
|
||||
return versionValueMap[mapKey];
|
||||
}
|
||||
return (
|
||||
direction *
|
||||
(getValueFromVersion(a.nxVersion, a.pluginType) -
|
||||
getValueFromVersion(b.nxVersion, b.pluginType))
|
||||
);
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [initialPlugins, modifiers]);
|
||||
|
||||
return (
|
||||
<div className="not-content">
|
||||
{/* Search and Order Controls */}
|
||||
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
{/* Search */}
|
||||
<div className="relative w-full sm:w-48">
|
||||
<label htmlFor="plugin-search" className="sr-only">
|
||||
Search plugins
|
||||
</label>
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-2.5">
|
||||
<SearchIcon className="h-4 w-4 text-slate-400" />
|
||||
</div>
|
||||
<input
|
||||
id="plugin-search"
|
||||
name="search"
|
||||
className="block w-full rounded-md border border-slate-300 bg-white py-1.5 pl-8 pr-3 text-sm placeholder-slate-500 transition focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:border-slate-700 dark:bg-slate-800 dark:placeholder-slate-400 dark:focus:border-blue-400 dark:focus:ring-blue-400"
|
||||
placeholder="Search..."
|
||||
value={modifiers.term}
|
||||
onChange={(event) =>
|
||||
setModifiers({ ...modifiers, term: event.target.value })
|
||||
}
|
||||
type="search"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Order By */}
|
||||
<div className="flex flex-wrap items-center gap-1.5 text-xs">
|
||||
<span className="text-slate-600 dark:text-slate-400">Order by:</span>
|
||||
<OrderButton
|
||||
label="Date"
|
||||
icon={<ClockIcon className="h-3.5 w-3.5" />}
|
||||
orderKey="lastPublishDate"
|
||||
modifiers={modifiers}
|
||||
onClick={setOrderBy}
|
||||
/>
|
||||
<OrderButton
|
||||
label="Downloads"
|
||||
icon={<DownloadIcon className="h-3.5 w-3.5" />}
|
||||
orderKey="npmDownloads"
|
||||
modifiers={modifiers}
|
||||
onClick={setOrderBy}
|
||||
/>
|
||||
<OrderButton
|
||||
label="Stars"
|
||||
icon={<StarIcon className="h-3.5 w-3.5" />}
|
||||
orderKey="githubStars"
|
||||
modifiers={modifiers}
|
||||
onClick={setOrderBy}
|
||||
/>
|
||||
<OrderButton
|
||||
label="Version"
|
||||
icon={<NxIcon className="h-3.5 w-3.5" />}
|
||||
orderKey="nxVersion"
|
||||
modifiers={modifiers}
|
||||
onClick={setOrderBy}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results count */}
|
||||
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
|
||||
Showing {filteredAndSortedPlugins.length} of {initialPlugins.length}{' '}
|
||||
plugins
|
||||
</p>
|
||||
|
||||
{/* Plugin Grid */}
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
{filteredAndSortedPlugins.map((plugin) => (
|
||||
<PluginCard key={plugin.id} plugin={plugin} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{filteredAndSortedPlugins.length === 0 && (
|
||||
<div className="py-12 text-center text-slate-500 dark:text-slate-400">
|
||||
<p className="text-lg">
|
||||
No plugins found matching "{modifiers.term}"
|
||||
</p>
|
||||
<p className="mt-2 text-sm">Try a different search term</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -18,8 +18,9 @@ type Crumb = {
|
||||
}
|
||||
|
||||
function findDocByPath (path: string) {
|
||||
return allDocs.find(d => d.id === `${path}.mdoc`)
|
||||
?? allDocs.find(d => d.id === `${path}/index.mdoc`);
|
||||
path = path.replace(/^docs\//, '');
|
||||
return allDocs.find(d => d.id === `${path}`)
|
||||
?? allDocs.find(d => d.id === `${path}/index`);
|
||||
}
|
||||
|
||||
function createNameFromSegment(segment: string): string {
|
||||
|
||||
@@ -11,291 +11,698 @@ import nxLogoLight from '../../assets/nx/Nx-light.svg';
|
||||
* Render the `Search` component if Pagefind is enabled or the default search component has been overridden.
|
||||
*/
|
||||
const shouldRenderSearch =
|
||||
config.pagefind || config.components.Search !== '@astrojs/starlight/components/Search.astro';
|
||||
config.pagefind ||
|
||||
config.components.Search !== '@astrojs/starlight/components/Search.astro';
|
||||
|
||||
// Get the base URL from environment
|
||||
const nxDevUrl = import.meta.env.SITE || 'https://nx.dev';
|
||||
|
||||
// Version options
|
||||
const versions = [
|
||||
{ version: 'v21', href: '/docs/getting-started/intro', current: true },
|
||||
{ version: 'v20', href: 'https://20.nx.dev/docs' },
|
||||
{ version: 'v19', href: 'https://19.nx.dev/docs' },
|
||||
{ version: 'v22', href: '/docs/getting-started/intro', current: true },
|
||||
{ version: 'v21', href: 'https://21.nx.dev/docs' },
|
||||
{ version: 'v20', href: 'https://20.nx.dev/docs' },
|
||||
{ version: 'v19', href: 'https://19.nx.dev/docs' },
|
||||
];
|
||||
|
||||
const currentVersion = versions.find(v => v.current);
|
||||
const currentVersion = versions.find((v) => v.current);
|
||||
---
|
||||
|
||||
<div class="flex items-center justify-between h-full gap-4">
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<a href={import.meta.env.SITE} class="flex items-center no-underline">
|
||||
<Image src={nxLogoDark} alt="Nx" class="h-12 w-auto dark:hidden" />
|
||||
<Image src={nxLogoLight} alt="Nx" class="h-12 w-auto hidden dark:block" />
|
||||
</a>
|
||||
<a href="/docs/getting-started/intro" class="px-3.5 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500">
|
||||
Docs
|
||||
</a>
|
||||
<!-- Version Switcher -->
|
||||
<div class="relative ml-1">
|
||||
<button class="version-trigger flex items-center gap-1 px-2 py-1 text-sm bg-transparent hover:text-blue-500" aria-expanded="false" aria-haspopup="true">
|
||||
<span>{currentVersion?.version}</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-3 h-3 transition-transform version-icon">
|
||||
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="version-menu absolute top-full left-0 mt-1 min-w-[8rem] bg-white border border-slate-200 rounded-md shadow-lg opacity-0 invisible translate-y-1 transition-all z-50 dark:bg-slate-900 dark:border-slate-800">
|
||||
<div class="py-1">
|
||||
{versions.map((item) => (
|
||||
<a
|
||||
href={item.href}
|
||||
class={`block px-4 py-2 text-sm no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60 ${item.current ? 'text-blue-600 font-semibold dark:text-sky-400' : 'text-slate-700 dark:text-slate-300'}`}
|
||||
aria-current={item.current ? 'page' : undefined}
|
||||
>
|
||||
<span class="flex items-center justify-between">
|
||||
{item.version}
|
||||
{item.current && <span class="text-blue-600 dark:text-sky-400">✓</span>}
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="hidden lg:flex items-center gap-1 ml-8 flex-shrink-0">
|
||||
<a href="https://nx.dev/blog" class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500">
|
||||
Blog
|
||||
</a>
|
||||
|
||||
<!-- Resources Dropdown -->
|
||||
<div class="relative nav-dropdown">
|
||||
<button class="dropdown-trigger flex items-center gap-1 px-3 py-2 text-sm bg-transparent hover:text-blue-500 rounded-md transition-colors whitespace-nowrap dark:text-slate-200 dark:hover:text-sky-500" aria-expanded="false" aria-haspopup="true">
|
||||
<span>Resources</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4 transition-transform dropdown-icon">
|
||||
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="dropdown-menu absolute top-full left-0 mt-2 w-[32rem] bg-slate-50/95 backdrop-blur-sm rounded-lg shadow-lg ring-1 ring-slate-200/40 opacity-0 invisible translate-y-1 transition-all z-50 dark:bg-slate-950/95 dark:ring-slate-800/60">
|
||||
<div class="grid grid-cols-2 gap-6 p-6">
|
||||
<!-- Learn Section -->
|
||||
<div class="space-y-1">
|
||||
<h5 class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400">Learn</h5>
|
||||
<a href="https://nx.dev/podcast" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Podcasts</span>
|
||||
</a>
|
||||
<a href="https://nx.dev/webinar" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Webinars</span>
|
||||
</a>
|
||||
<a href="https://nx.dev/courses" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.91 11.672a.375.375 0 0 1 0 .656l-5.603 3.113a.375.375 0 0 1-.557-.328V8.887c0-.286.307-.466.557-.327l5.603 3.112Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Nx Video Courses</span>
|
||||
</a>
|
||||
<a href="https://go.nrwl.io/nx-newsletter" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Newsletter</span>
|
||||
</a>
|
||||
<a href="https://nx.dev/community" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Community</span>
|
||||
</a>
|
||||
<a href="https://go.nx.dev/community" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Discord</span>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Right Column -->
|
||||
<div class="space-y-4">
|
||||
<!-- Events Section -->
|
||||
<div class="space-y-1">
|
||||
<h5 class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400">Events</h5>
|
||||
<a href="https://go.nx.dev/office-hours" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Office Hours</span>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@nxdevtools/streams" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Live Streams</span>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Company Section -->
|
||||
<div class="space-y-1">
|
||||
<h5 class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400">Company</h5>
|
||||
<a href="https://nx.dev/company" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">About Us</span>
|
||||
</a>
|
||||
<a href="https://nx.dev/customers" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Z" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Customers</span>
|
||||
</a>
|
||||
<a href="https://nx.dev/partners" class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60">
|
||||
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.712 4.33a9.027 9.027 0 0 1 1.652 1.306c.51.51.944 1.064 1.306 1.652M16.712 4.33l-3.448 4.138m3.448-4.138a9.014 9.014 0 0 0-9.424 0M19.67 7.288l-4.138 3.448m4.138-3.448a9.014 9.014 0 0 1 0 9.424m-1.306 1.652a9.027 9.027 0 0 1-1.652 1.306m0 0-3.448-4.138m3.448 4.138a9.014 9.014 0 0 1-9.424 0m5.976-4.138a3.765 3.765 0 0 1-2.528 0m0 0a3.736 3.736 0 0 1-1.388-.88 3.737 3.737 0 0 1-.88-1.388m2.268 2.268L7.288 19.67m0 0a9.024 9.024 0 0 1-1.652-1.306 9.027 9.027 0 0 1-1.306-1.652m0 0 4.138-3.448M4.33 16.712a9.014 9.014 0 0 1 0-9.424m4.138-3.448A9.027 9.027 0 0 1 7.162 5.146a9.024 9.024 0 0 1 1.306 1.652M4.33 7.288 8.468 10.736m0 0a3.736 3.736 0 0 1 .88-1.388 3.737 3.737 0 0 1 1.388-.88m-2.268 2.268L4.33 7.288m6.406 1.18L7.288 4.33m0 0a9.024 9.024 0 0 0-1.652 1.306A9.025 9.025 0 0 0 4.33 7.288" />
|
||||
</svg>
|
||||
<span class="text-sm font-medium text-slate-900 dark:text-slate-200">Partners</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-6 w-px bg-slate-200 mx-1 dark:bg-slate-700"></div>
|
||||
<a href="https://nx.dev/ai" class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500">
|
||||
AI
|
||||
</a>
|
||||
<a href="https://nx.dev/nx-cloud" class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500">
|
||||
Nx Cloud
|
||||
</a>
|
||||
<div class="h-6 w-px bg-slate-200 mx-1 dark:bg-slate-700"></div>
|
||||
<a href="https://nx.dev/enterprise" class="px-3 py-2 text-sm font-semibold text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500">
|
||||
Nx Enterprise
|
||||
</a>
|
||||
</nav>
|
||||
<div class="flex-1 max-w-sm mx-4 print:hidden">
|
||||
{shouldRenderSearch && <Search />}
|
||||
</div>
|
||||
<div class="hidden md:flex items-center gap-4 print:hidden">
|
||||
<!-- CTA Buttons - Hide on screens smaller than xl (1280px) -->
|
||||
<div class="hidden xl:flex items-center gap-2">
|
||||
<a
|
||||
href="https://nx.dev/contact"
|
||||
class="inline-flex items-center justify-center px-2.5 py-1.5 text-sm font-medium rounded-md transition no-underline border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700 shadow-sm"
|
||||
title="Contact Us"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<a
|
||||
href="https://cloud.nx.app?utm_source=nx-dev&utm_medium=header"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center justify-center px-2.5 py-1.5 text-sm font-medium rounded-md transition no-underline bg-blue-500 dark:bg-sky-500 text-white hover:bg-blue-600 dark:hover:bg-sky-600 shadow-sm"
|
||||
title="Login to Nx Cloud"
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
</div>
|
||||
<!-- Social Icons - Hide on screens smaller than 2xl (1536px) -->
|
||||
<div class="hidden 2xl:flex items-center gap-4">
|
||||
<SocialIcons />
|
||||
</div>
|
||||
<div class="after:content-[''] after:h-8 after:border-l after:border-slate-200 dark:after:border-slate-700"></div>
|
||||
<!-- Theme Switcher - Always visible (highest priority) -->
|
||||
<ThemeSelect />
|
||||
</div>
|
||||
<Image src={nxLogoDark} alt="Nx" class="h-12 w-auto dark:hidden" />
|
||||
<Image src={nxLogoLight} alt="Nx" class="h-12 w-auto hidden dark:block" />
|
||||
</a>
|
||||
<a
|
||||
id="header-docs-home-link"
|
||||
href="/docs/getting-started/intro"
|
||||
class="px-3.5 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
<!-- Version Switcher -->
|
||||
<div class="relative ml-1">
|
||||
<button
|
||||
class="version-trigger flex items-center gap-1 px-2 py-1 text-sm bg-transparent hover:text-blue-500"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
>
|
||||
<span>{currentVersion?.version}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-3 h-3 transition-transform version-icon"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div
|
||||
class="version-menu absolute top-full left-0 mt-1 min-w-[8rem] bg-white border border-slate-200 rounded-md shadow-lg opacity-0 invisible translate-y-1 transition-all z-50 dark:bg-slate-900 dark:border-slate-800"
|
||||
>
|
||||
<div class="py-1">
|
||||
{
|
||||
versions.map((item) => (
|
||||
<a
|
||||
href={item.href}
|
||||
class={`block px-4 py-2 text-sm no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60 ${item.current ? 'text-blue-600 font-semibold dark:text-sky-400' : 'text-slate-700 dark:text-slate-300'}`}
|
||||
aria-current={item.current ? 'page' : undefined}
|
||||
>
|
||||
<span class="flex items-center justify-between">
|
||||
{item.version}
|
||||
{item.current && (
|
||||
<span class="text-blue-600 dark:text-sky-400">✓</span>
|
||||
)}
|
||||
</span>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="hidden lg:flex items-center gap-1 ml-8 flex-shrink-0">
|
||||
<a
|
||||
href={`${nxDevUrl}/blog`}
|
||||
class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
Blog
|
||||
</a>
|
||||
|
||||
<!-- Resources Dropdown -->
|
||||
<div class="relative nav-dropdown">
|
||||
<button
|
||||
class="dropdown-trigger flex items-center gap-1 px-3 py-2 text-sm bg-transparent hover:text-blue-500 rounded-md transition-colors whitespace-nowrap dark:text-slate-200 dark:hover:text-sky-500"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
>
|
||||
<span>Resources</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4 transition-transform dropdown-icon"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div
|
||||
class="dropdown-menu absolute top-full left-0 mt-2 w-[32rem] bg-slate-50/95 backdrop-blur-sm rounded-lg shadow-lg ring-1 ring-slate-200/40 opacity-0 invisible translate-y-1 transition-all z-50 dark:bg-slate-950/95 dark:ring-slate-800/60"
|
||||
>
|
||||
<div class="grid grid-cols-2 gap-6 p-6">
|
||||
<!-- Learn Section -->
|
||||
<div class="space-y-1">
|
||||
<h5
|
||||
class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400"
|
||||
>
|
||||
Learn
|
||||
</h5>
|
||||
<a
|
||||
href={`${nxDevUrl}/podcast`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Podcasts</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/webinar`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Webinars</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/courses`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></path>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15.91 11.672a.375.375 0 0 1 0 .656l-5.603 3.113a.375.375 0 0 1-.557-.328V8.887c0-.286.307-.466.557-.327l5.603 3.112Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Nx Video Courses</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href="https://go.nrwl.io/nx-newsletter"
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Newsletter</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/community`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Community</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href="https://go.nx.dev/community"
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Discord</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/resources-library?filterBy=book`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Books</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/resources-library?filterBy=case-study`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Case Studies</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/resources-library?filterBy=whitepaper`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Whitepapers</span
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Right Column -->
|
||||
<div class="space-y-4">
|
||||
<!-- Events Section -->
|
||||
<div class="space-y-1">
|
||||
<h5
|
||||
class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400"
|
||||
>
|
||||
Events
|
||||
</h5>
|
||||
<a
|
||||
href="https://www.youtube.com/playlist?list=PLakNactNC1dE8KLQ5zd3fQwu_yQHjTmR5"
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Nx Live</span
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Company Section -->
|
||||
<div class="space-y-1">
|
||||
<h5
|
||||
class="text-xs font-semibold uppercase tracking-wider text-slate-500 px-2 pb-2 dark:text-slate-400"
|
||||
>
|
||||
Company
|
||||
</h5>
|
||||
<a
|
||||
href={`${nxDevUrl}/company`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>About Us</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/customers`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Customers</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`${nxDevUrl}/partners`}
|
||||
class="flex items-center gap-3 px-2 py-2 rounded-md no-underline hover:bg-slate-50 transition-colors dark:hover:bg-slate-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 text-slate-400 dark:text-slate-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.712 4.33a9.027 9.027 0 0 1 1.652 1.306c.51.51.944 1.064 1.306 1.652M16.712 4.33l-3.448 4.138m3.448-4.138a9.014 9.014 0 0 0-9.424 0M19.67 7.288l-4.138 3.448m4.138-3.448a9.014 9.014 0 0 1 0 9.424m-1.306 1.652a9.027 9.027 0 0 1-1.652 1.306m0 0-3.448-4.138m3.448 4.138a9.014 9.014 0 0 1-9.424 0m5.976-4.138a3.765 3.765 0 0 1-2.528 0m0 0a3.736 3.736 0 0 1-1.388-.88 3.737 3.737 0 0 1-.88-1.388m2.268 2.268L7.288 19.67m0 0a9.024 9.024 0 0 1-1.652-1.306 9.027 9.027 0 0 1-1.306-1.652m0 0 4.138-3.448M4.33 16.712a9.014 9.014 0 0 1 0-9.424m4.138-3.448A9.027 9.027 0 0 1 7.162 5.146a9.024 9.024 0 0 1 1.306 1.652M4.33 7.288 8.468 10.736m0 0a3.736 3.736 0 0 1 .88-1.388 3.737 3.737 0 0 1 1.388-.88m-2.268 2.268L4.33 7.288m6.406 1.18L7.288 4.33m0 0a9.024 9.024 0 0 0-1.652 1.306A9.025 9.025 0 0 0 4.33 7.288"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
class="text-sm font-medium text-slate-900 dark:text-slate-200"
|
||||
>Partners</span
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-6 w-px bg-slate-200 mx-1 dark:bg-slate-700"></div>
|
||||
<a
|
||||
id="header-ai-link"
|
||||
href={`${nxDevUrl}/ai`}
|
||||
class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
AI
|
||||
</a>
|
||||
<a
|
||||
id="header-nx-cloud-link"
|
||||
href={`${nxDevUrl}/nx-cloud`}
|
||||
class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
Nx Cloud
|
||||
</a>
|
||||
<a
|
||||
id="header-pricing-link"
|
||||
href={`${nxDevUrl}/nx-cloud#plans`}
|
||||
class="px-3 py-2 text-sm font-medium text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
Pricing
|
||||
</a>
|
||||
<div class="h-6 w-px bg-slate-200 mx-1 dark:bg-slate-700"></div>
|
||||
<a
|
||||
id="header-enterprise-link"
|
||||
href={`${nxDevUrl}/enterprise`}
|
||||
class="px-3 py-2 text-sm font-semibold text-slate-600 hover:text-blue-500 rounded-md transition-colors whitespace-nowrap no-underline dark:text-slate-200 dark:hover:text-sky-500"
|
||||
>
|
||||
Enterprise
|
||||
</a>
|
||||
</nav>
|
||||
<div class="flex-1 max-w-sm mx-4 print:hidden">
|
||||
{shouldRenderSearch && <Search />}
|
||||
</div>
|
||||
<div class="hidden md:flex items-center gap-4 print:hidden">
|
||||
<!-- CTA Buttons - Hide on screens smaller than xl (1280px) -->
|
||||
<div class="hidden xl:flex items-center gap-2">
|
||||
<a
|
||||
id="header-contact-btn"
|
||||
href={`${nxDevUrl}/contact`}
|
||||
class="inline-flex items-center justify-center px-2.5 py-1.5 text-sm font-medium rounded-md transition no-underline border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700 shadow-sm"
|
||||
title="Contact Us"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<a
|
||||
id="header-try-nx-cloud-btn"
|
||||
href="https://cloud.nx.app/get-started?utm_source=nx-dev&utm_medium=documentation-header&utm_campaign=try-nx-cloud"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center justify-center px-2.5 py-1.5 text-sm font-medium rounded-md transition no-underline bg-blue-500 dark:bg-sky-500 text-white hover:bg-blue-600 dark:hover:bg-sky-600 shadow-sm"
|
||||
title="Try Nx Cloud for free"
|
||||
>
|
||||
Try Nx Cloud for free
|
||||
</a>
|
||||
</div>
|
||||
<!-- Social Icons - Hide on screens smaller than 2xl (1536px) -->
|
||||
<div class="hidden 2xl:flex items-center gap-4">
|
||||
<SocialIcons />
|
||||
</div>
|
||||
<div
|
||||
class="after:content-[''] after:h-8 after:border-l after:border-slate-200 dark:after:border-slate-700"
|
||||
>
|
||||
</div>
|
||||
<!-- Theme Switcher - Always visible (highest priority) -->
|
||||
<ThemeSelect />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Handle dropdown interactions
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const dropdowns = document.querySelectorAll('.nav-dropdown');
|
||||
|
||||
dropdowns.forEach(dropdown => {
|
||||
const trigger = dropdown.querySelector('.dropdown-trigger');
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
let closeTimeout: number;
|
||||
|
||||
// Mouse interactions
|
||||
trigger?.addEventListener('mouseenter', () => {
|
||||
clearTimeout(closeTimeout);
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
menu?.classList.remove('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger.querySelector('.dropdown-icon')?.classList.add('rotate-180');
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mouseleave', () => {
|
||||
closeTimeout = window.setTimeout(() => {
|
||||
trigger?.setAttribute('aria-expanded', 'false');
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger?.querySelector('.dropdown-icon')?.classList.remove('rotate-180');
|
||||
}, 150);
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mouseenter', () => {
|
||||
clearTimeout(closeTimeout);
|
||||
});
|
||||
|
||||
// Keyboard interactions
|
||||
trigger?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const isOpen = trigger.getAttribute('aria-expanded') === 'true';
|
||||
trigger.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
if (isOpen) {
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger.querySelector('.dropdown-icon')?.classList.remove('rotate-180');
|
||||
} else {
|
||||
menu?.classList.remove('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger.querySelector('.dropdown-icon')?.classList.add('rotate-180');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Version switcher
|
||||
const versionSwitcher = document.querySelector('.version-trigger')?.parentElement;
|
||||
const versionTrigger = versionSwitcher?.querySelector('.version-trigger');
|
||||
const versionMenu = versionSwitcher?.querySelector('.version-menu');
|
||||
|
||||
versionTrigger?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const isOpen = versionTrigger.getAttribute('aria-expanded') === 'true';
|
||||
versionTrigger.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
if (isOpen) {
|
||||
versionMenu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
versionMenu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
versionTrigger.querySelector('.version-icon')?.classList.remove('rotate-180');
|
||||
} else {
|
||||
versionMenu?.classList.remove('opacity-0', 'invisible', 'translate-y-1');
|
||||
versionMenu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
versionTrigger.querySelector('.version-icon')?.classList.add('rotate-180');
|
||||
}
|
||||
});
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
// Close nav dropdowns
|
||||
if (!target.closest('.nav-dropdown')) {
|
||||
dropdowns.forEach(dropdown => {
|
||||
const trigger = dropdown.querySelector('.dropdown-trigger');
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
trigger?.setAttribute('aria-expanded', 'false');
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger?.querySelector('.dropdown-icon')?.classList.remove('rotate-180');
|
||||
});
|
||||
}
|
||||
|
||||
// Close version switcher
|
||||
if (!target.closest('.version-trigger') && !target.closest('.version-menu')) {
|
||||
versionTrigger?.setAttribute('aria-expanded', 'false');
|
||||
versionMenu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
versionMenu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
versionTrigger?.querySelector('.version-icon')?.classList.remove('rotate-180');
|
||||
}
|
||||
});
|
||||
});
|
||||
import { sendCustomEvent } from '@nx/nx-dev-feature-analytics';
|
||||
|
||||
function setupAnalyticsTracking() {
|
||||
const docsHomeLink = document.getElementById('header-docs-home-link');
|
||||
const aiLink = document.getElementById('header-ai-link');
|
||||
const nxCloudLink = document.getElementById('header-nx-cloud-link');
|
||||
const pricingLink = document.getElementById('header-pricing-link');
|
||||
const enterpriseLink = document.getElementById('header-enterprise-link');
|
||||
const contactBtn = document.getElementById('header-contact-btn');
|
||||
const tryNxCloudBtn = document.getElementById('header-try-nx-cloud-btn');
|
||||
|
||||
docsHomeLink?.addEventListener('click', () => {
|
||||
sendCustomEvent(
|
||||
'documentation-click',
|
||||
'header-navigation',
|
||||
'documentation-header'
|
||||
);
|
||||
});
|
||||
|
||||
aiLink?.addEventListener('click', () => {
|
||||
sendCustomEvent(
|
||||
'ai-click',
|
||||
'header-navigation',
|
||||
'documentation-header'
|
||||
);
|
||||
});
|
||||
|
||||
nxCloudLink?.addEventListener('click', () => {
|
||||
sendCustomEvent(
|
||||
'nx-cloud-click',
|
||||
'header-navigation',
|
||||
'documentation-header'
|
||||
);
|
||||
});
|
||||
|
||||
pricingLink?.addEventListener('click', () => {
|
||||
sendCustomEvent(
|
||||
'pricing-click',
|
||||
'header-navigation',
|
||||
'documentation-header'
|
||||
);
|
||||
});
|
||||
|
||||
enterpriseLink?.addEventListener('click', () => {
|
||||
sendCustomEvent(
|
||||
'enterprise-click',
|
||||
'header-navigation',
|
||||
'documentation-header'
|
||||
);
|
||||
});
|
||||
|
||||
contactBtn?.addEventListener('click', () => {
|
||||
sendCustomEvent('contact-click', 'header-cta', 'documentation-header');
|
||||
});
|
||||
|
||||
tryNxCloudBtn?.addEventListener('click', () => {
|
||||
sendCustomEvent('login-click', 'header-cta', 'documentation-header');
|
||||
});
|
||||
}
|
||||
|
||||
function setupDropdowns() {
|
||||
const dropdowns = document.querySelectorAll('.nav-dropdown');
|
||||
|
||||
dropdowns.forEach((dropdown) => {
|
||||
const trigger = dropdown.querySelector('.dropdown-trigger');
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
let closeTimeout: number;
|
||||
|
||||
// Mouse interactions
|
||||
trigger?.addEventListener('mouseenter', () => {
|
||||
clearTimeout(closeTimeout);
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
menu?.classList.remove('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger.querySelector('.dropdown-icon')?.classList.add('rotate-180');
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mouseleave', () => {
|
||||
closeTimeout = window.setTimeout(() => {
|
||||
trigger?.setAttribute('aria-expanded', 'false');
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger
|
||||
?.querySelector('.dropdown-icon')
|
||||
?.classList.remove('rotate-180');
|
||||
}, 150);
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mouseenter', () => {
|
||||
clearTimeout(closeTimeout);
|
||||
});
|
||||
|
||||
// Keyboard interactions
|
||||
trigger?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const isOpen = trigger.getAttribute('aria-expanded') === 'true';
|
||||
trigger.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
if (isOpen) {
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger
|
||||
.querySelector('.dropdown-icon')
|
||||
?.classList.remove('rotate-180');
|
||||
} else {
|
||||
menu?.classList.remove('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger.querySelector('.dropdown-icon')?.classList.add('rotate-180');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (!target.closest('.nav-dropdown')) {
|
||||
dropdowns.forEach((dropdown) => {
|
||||
const trigger = dropdown.querySelector('.dropdown-trigger');
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
trigger?.setAttribute('aria-expanded', 'false');
|
||||
menu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
menu?.classList.remove('opacity-100', 'visible', 'translate-y-0');
|
||||
trigger
|
||||
?.querySelector('.dropdown-icon')
|
||||
?.classList.remove('rotate-180');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setupVersionSwitcher() {
|
||||
const versionSwitcher =
|
||||
document.querySelector('.version-trigger')?.parentElement;
|
||||
const versionTrigger =
|
||||
versionSwitcher?.querySelector('.version-trigger') ?? null;
|
||||
const versionMenu = versionSwitcher?.querySelector('.version-menu') ?? null;
|
||||
|
||||
versionTrigger?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const isOpen = versionTrigger.getAttribute('aria-expanded') === 'true';
|
||||
versionTrigger.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
if (isOpen) {
|
||||
versionMenu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
versionMenu?.classList.remove(
|
||||
'opacity-100',
|
||||
'visible',
|
||||
'translate-y-0'
|
||||
);
|
||||
versionTrigger
|
||||
.querySelector('.version-icon')
|
||||
?.classList.remove('rotate-180');
|
||||
} else {
|
||||
versionMenu?.classList.remove(
|
||||
'opacity-0',
|
||||
'invisible',
|
||||
'translate-y-1'
|
||||
);
|
||||
versionMenu?.classList.add('opacity-100', 'visible', 'translate-y-0');
|
||||
versionTrigger
|
||||
.querySelector('.version-icon')
|
||||
?.classList.add('rotate-180');
|
||||
}
|
||||
});
|
||||
|
||||
// Close version switcher when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (
|
||||
!target.closest('.version-trigger') &&
|
||||
!target.closest('.version-menu')
|
||||
) {
|
||||
versionTrigger?.setAttribute('aria-expanded', 'false');
|
||||
versionMenu?.classList.add('opacity-0', 'invisible', 'translate-y-1');
|
||||
versionMenu?.classList.remove(
|
||||
'opacity-100',
|
||||
'visible',
|
||||
'translate-y-0'
|
||||
);
|
||||
versionTrigger
|
||||
?.querySelector('.version-icon')
|
||||
?.classList.remove('rotate-180');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setupAnalyticsTracking();
|
||||
setupDropdowns();
|
||||
setupVersionSwitcher();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
// Copied from https://github.com/withastro/starlight/blob/f14eb0c/packages/starlight/components/PageFrame.astro with modifications.
|
||||
import MobileMenuToggle from '@astrojs/starlight/components/MobileMenuToggle.astro';
|
||||
import { Footer } from '@nx/nx-dev-ui-common';
|
||||
import { Footer, GitHubStarWidget } from '@nx/nx-dev-ui-common';
|
||||
import { WebinarNotifier } from '@nx/nx-dev-ui-common/src/lib/webinar-notifier';
|
||||
|
||||
const { hasSidebar } = Astro.locals.starlightRoute;
|
||||
const githubStarsCount = Astro.locals.githubStarsCount ?? 0;
|
||||
---
|
||||
|
||||
<div class="page sl-flex">
|
||||
@@ -18,22 +20,25 @@ const { hasSidebar } = Astro.locals.starlightRoute;
|
||||
<!-- CTA Buttons for Mobile Menu - Show when not in header (below xl breakpoint) -->
|
||||
<div class="mobile-cta-buttons xl:hidden mt-auto pt-4 pb-4 border-t border-slate-800 dark:border-slate-700">
|
||||
<div class="flex flex-col gap-2">
|
||||
<a
|
||||
href="https://nx.dev/contact"
|
||||
class="w-full inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md transition no-underline border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700 shadow-sm"
|
||||
title="Contact Us"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<a
|
||||
href="https://cloud.nx.app?utm_source=nx-dev&utm_medium=header"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="w-full inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md transition no-underline bg-blue-500 dark:bg-sky-500 text-white hover:bg-blue-600 dark:hover:bg-sky-600 shadow-sm"
|
||||
title="Login to Nx Cloud"
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
<GitHubStarWidget starsCount={githubStarsCount} client:load />
|
||||
<div class="flex flex-col mx-2 gap-2">
|
||||
<a
|
||||
href="https://nx.dev/contact"
|
||||
class="w-full inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md transition no-underline border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700 shadow-sm"
|
||||
title="Contact Us"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<a
|
||||
href="https://cloud.nx.app?utm_source=nx-dev&utm_medium=header"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="w-full inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md transition no-underline bg-blue-500 dark:bg-sky-500 text-white hover:bg-blue-600 dark:hover:bg-sky-600 shadow-sm"
|
||||
title="Login to Nx Cloud"
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,7 +47,8 @@ const { hasSidebar } = Astro.locals.starlightRoute;
|
||||
)
|
||||
}
|
||||
<div class="main-frame"><slot /></div>
|
||||
<Footer disableThemeSwitcher={true} useDomainPrefix={true} className="mt-32 dark:bg-slate-900" />
|
||||
<Footer disableThemeSwitcher={true} useDomainPrefix={true} className="dark:bg-slate-900" />
|
||||
<WebinarNotifier client:load />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
import MobileMenuFooter from '@astrojs/starlight/components/MobileMenuFooter.astro'
|
||||
import SidebarPersister from '@astrojs/starlight/components/SidebarPersister.astro'
|
||||
import SidebarSublist from './SidebarSublist.astro'
|
||||
import { GitHubStarWidget } from '@nx/nx-dev-ui-common';
|
||||
|
||||
const { sidebar } = Astro.locals.starlightRoute
|
||||
const githubStarsCount = Astro.locals.githubStarsCount ?? 0;
|
||||
---
|
||||
|
||||
<div class="sidebar-wrapper" data-testid="sidebar-wrapper">
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
---
|
||||
// recreated from https://github.com/withastro/starlight/blob/main/packages/starlight/components/TableOfContents.astro
|
||||
import TableOfContentsList from './TableOfContentsList.astro';
|
||||
import { GitHubStarWidget } from '@nx/nx-dev-ui-common';
|
||||
|
||||
const { toc } = Astro.locals.starlightRoute;
|
||||
const githubStarsCount = Astro.locals.githubStarsCount ?? 0;
|
||||
---
|
||||
|
||||
{
|
||||
toc && (
|
||||
<custom-toc data-min-h={toc.minHeadingLevel} data-max-h={toc.maxHeadingLevel}>
|
||||
<div class="github-star-widget-container">
|
||||
<GitHubStarWidget starsCount={githubStarsCount} client:load />
|
||||
</div>
|
||||
<nav aria-labelledby="starlight__on-this-page">
|
||||
<h2 id="starlight__on-this-page">{Astro.locals.t('tableOfContents.onThisPage')}</h2>
|
||||
<div class="toc-container">
|
||||
<TableOfContentsList toc={toc.items} />
|
||||
</div>
|
||||
</nav>
|
||||
</custom-toc>
|
||||
)
|
||||
}
|
||||
|
||||
<script>
|
||||
// Define the constant locally since it's not exported from @astrojs/starlight
|
||||
const PAGE_TITLE_ID = 'starlight__overview';
|
||||
|
||||
class CustomTOC extends HTMLElement {
|
||||
private _current = this.querySelector<HTMLAnchorElement>('a[aria-current="true"]');
|
||||
private minH = parseInt(this.dataset.minH || '2', 10);
|
||||
private maxH = parseInt(this.dataset.maxH || '3', 10);
|
||||
private tocContainer: HTMLElement | null = null;
|
||||
|
||||
protected set current(link: HTMLAnchorElement) {
|
||||
if (link === this._current) return;
|
||||
if (this._current) this._current.removeAttribute('aria-current');
|
||||
link.setAttribute('aria-current', 'true');
|
||||
this._current = link;
|
||||
|
||||
// Auto-scroll the active item into view within the TOC container
|
||||
this.scrollActiveIntoView(link);
|
||||
}
|
||||
|
||||
private onIdle = (cb: IdleRequestCallback) =>
|
||||
(window.requestIdleCallback || ((cb) => setTimeout(cb, 1)))(cb);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.tocContainer = this.querySelector('.toc-container');
|
||||
this.onIdle(() => this.init());
|
||||
}
|
||||
|
||||
private scrollActiveIntoView(link: HTMLAnchorElement): void {
|
||||
if (!this.tocContainer) return;
|
||||
|
||||
// Check if user prefers reduced motion
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
// Get the position of the link relative to the TOC container
|
||||
const containerRect = this.tocContainer.getBoundingClientRect();
|
||||
const linkRect = link.getBoundingClientRect();
|
||||
|
||||
// Calculate if the link is outside the visible area
|
||||
const isAboveView = linkRect.top < containerRect.top;
|
||||
const isBelowView = linkRect.bottom > containerRect.bottom;
|
||||
|
||||
if (isAboveView || isBelowView) {
|
||||
// Scroll the link into view with some padding
|
||||
const offsetTop = link.offsetTop - this.tocContainer.offsetTop;
|
||||
const scrollPosition = offsetTop - this.tocContainer.clientHeight / 2 + link.clientHeight / 2;
|
||||
|
||||
this.tocContainer.scrollTo({
|
||||
top: Math.max(0, scrollPosition),
|
||||
behavior: prefersReducedMotion ? 'auto' : 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private init = (): void => {
|
||||
const links = Array.from(this.querySelectorAll('a'))
|
||||
|
||||
const getElementHeading = (el: Element): HTMLHeadingElement | null => {
|
||||
if (!el) return null;
|
||||
const isHeading = (el: Element): el is HTMLHeadingElement => {
|
||||
if (el instanceof HTMLHeadingElement) {
|
||||
if (el.id === PAGE_TITLE_ID) return true;
|
||||
const level = el.tagName[1];
|
||||
if (level) {
|
||||
const int = parseInt(level, 10);
|
||||
if (int >= this.minH && int <= this.maxH) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return isHeading(el) ? el : getElementHeading(el.parentElement!);
|
||||
};
|
||||
|
||||
const setCurrent: IntersectionObserverCallback = (entries) => {
|
||||
for (const { isIntersecting, target } of entries) {
|
||||
if (!isIntersecting) continue;
|
||||
const heading = getElementHeading(target);
|
||||
if (!heading) continue;
|
||||
const link = links.find((link) => link.hash === '#' + encodeURIComponent(heading.id));
|
||||
if (link) {
|
||||
this.current = link;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toObserve = document.querySelectorAll('main [id], main [id] ~ *, main .content > *');
|
||||
let observer: IntersectionObserver | undefined;
|
||||
|
||||
const observe = () => {
|
||||
if (observer) observer.disconnect();
|
||||
observer = new IntersectionObserver(setCurrent, { rootMargin: this.getRootMargin() });
|
||||
toObserve.forEach((h) => observer!.observe(h));
|
||||
};
|
||||
|
||||
observe();
|
||||
let timeout: NodeJS.Timeout;
|
||||
// Re-observe on resize to adjust for layout changes
|
||||
window.addEventListener('resize', () => {
|
||||
if(observer) {
|
||||
observer.disconnect();
|
||||
observer = undefined;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => this.onIdle(observe), 200)
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
private getRootMargin(): `-${number}px 0% ${number}px` {
|
||||
const navBarHeight = document.querySelector('header')?.getBoundingClientRect().height || 0;
|
||||
const mobileTocHeight = this.querySelector('summary')?.getBoundingClientRect().height || 0;
|
||||
// Account for footer by reducing bottom margin
|
||||
const footerHeight = document.querySelector('footer')?.getBoundingClientRect().height || 0;
|
||||
const top = navBarHeight + mobileTocHeight + 32;
|
||||
const bottom = top + 53;
|
||||
const height = document.documentElement.clientHeight;
|
||||
// Adjust for footer
|
||||
return `-${top}px 0% ${bottom - height + footerHeight}px`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-toc', CustomTOC);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@layer starlight.core {
|
||||
custom-toc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
custom-toc nav {
|
||||
display: block;
|
||||
}
|
||||
|
||||
custom-toc h2 {
|
||||
color: var(--sl-color-text);
|
||||
font-size: var(--sl-text-sm);
|
||||
font-weight: 600;
|
||||
line-height: var(--sl-line-height-headings);
|
||||
margin: 0 0 0.5rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* GitHub star widget styling */
|
||||
.github-star-widget-container {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Container with proper scrolling */
|
||||
.toc-container {
|
||||
/* Allow ToC to be its natural height - parent sticky container handles viewport constraints */
|
||||
max-height: calc(100vh - var(--sl-nav-height) - 4rem);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Only enable smooth scrolling if user doesn't prefer reduced motion */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.toc-container {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
.toc-container::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.toc-container::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.toc-container::-webkit-scrollbar-thumb {
|
||||
background: var(--sl-color-gray-5);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.toc-container:hover::-webkit-scrollbar-thumb {
|
||||
background: var(--sl-color-gray-4);
|
||||
}
|
||||
|
||||
/* Firefox scrollbar */
|
||||
.toc-container {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--sl-color-gray-5) transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
import type { TocItem } from '@astrojs/starlight/utils/generateToC';
|
||||
|
||||
interface Props {
|
||||
toc: TocItem[];
|
||||
depth?: number;
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
const { toc, isMobile = false, depth = 0 } = Astro.props;
|
||||
---
|
||||
|
||||
<ul class:list={{ isMobile }}>
|
||||
{
|
||||
toc.map((heading) => (
|
||||
<li>
|
||||
<a href={'#' + heading.slug}>
|
||||
<span>{heading.text}</span>
|
||||
</a>
|
||||
{heading.children.length > 0 && (
|
||||
<Astro.self toc={heading.children} depth={depth + 1} isMobile={isMobile} />
|
||||
)}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<style define:vars={{ depth }}>
|
||||
@layer starlight.core {
|
||||
ul {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
--pad-inline: 0.5rem;
|
||||
display: block;
|
||||
border-radius: 0.25rem;
|
||||
padding-block: 0.25rem;
|
||||
padding-inline: calc(1rem * var(--depth) + var(--pad-inline)) var(--pad-inline);
|
||||
line-height: 1.25;
|
||||
color: var(--sl-color-gray-3);
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
font-size: var(--sl-text-sm);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--sl-color-gray-2);
|
||||
}
|
||||
|
||||
a[aria-current='true'] {
|
||||
color: var(--sl-color-text-accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
a:focus-visible {
|
||||
outline: 2px solid var(--sl-color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@media (min-width: 50rem) {
|
||||
a {
|
||||
padding-inline-start: calc(1rem * var(--depth) + var(--pad-inline));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
// Copied from https://github.com/withastro/starlight/blob/f14eb0c/packages/starlight/components/TwoColumnContent.astro with modifications.
|
||||
const { data} = Astro.locals.starlightRoute.entry;
|
||||
---
|
||||
|
||||
<div class="lg:sl-flex">
|
||||
@@ -12,7 +13,8 @@
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
<div class="main-pane" data-testid="main-pane"><slot /></div>
|
||||
<div class="main-pane" data-testid="main-pane" data-pagefind-weight={data.weight} data-pagefind-filter={data.filter}
|
||||
><slot /></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -22,21 +24,27 @@
|
||||
}
|
||||
|
||||
@media (min-width: 72rem) {
|
||||
.lg\:sl-flex {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.right-sidebar-container {
|
||||
order: 2;
|
||||
position: relative;
|
||||
width: calc(
|
||||
var(--sl-sidebar-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2
|
||||
);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.right-sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
position: sticky;
|
||||
top: var(--sl-nav-height);
|
||||
border-inline-start: 1px solid var(--sl-color-hairline);
|
||||
padding-top: var(--sl-nav-height);
|
||||
padding-top: 1rem;
|
||||
width: 100%;
|
||||
height: auto; // MODIFIED: full height conflicts with footer
|
||||
max-height: calc(100vh - var(--sl-nav-height));
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,4 @@ import { type GraphProps, Graph as Default } from '@nx/nx-dev-ui-markdoc/src/lib
|
||||
type Props = GraphProps;
|
||||
---
|
||||
|
||||
<Default client:visible {...Astro.props} isAstro={true}>
|
||||
<slot />
|
||||
</Default>
|
||||
<Default client:visible={{rootMargin:"100px"}} {...Astro.props} />
|
||||
|
||||
@@ -48,10 +48,7 @@ const sortedPages = childPages.sort((a, b) => {
|
||||
const processedPages = sortedPages.map(page => {
|
||||
let href = `/${page.id.replace('.mdoc', '')}`;
|
||||
|
||||
// Check if this is a subdirectory index page
|
||||
const fileName = page.id.split('/').pop()?.replace('.mdoc', '');
|
||||
const isIndexPage = fileName === 'index';
|
||||
|
||||
// Check if this is a subdirectory index page
|
||||
const title = page.data.sidebar?.label || page.data.title || 'Untitled';
|
||||
|
||||
// Ensure href is never undefined
|
||||
@@ -68,7 +65,6 @@ const processedPages = sortedPages.map(page => {
|
||||
};
|
||||
}).filter(page => page.href !== '#'); // Filter out any pages with invalid hrefs
|
||||
---
|
||||
|
||||
{processedPages.length > 0 ? (
|
||||
<Cards>
|
||||
{processedPages.map(page => (
|
||||
|
||||
@@ -4,9 +4,7 @@ type Props = ProjectDetailsProps;
|
||||
---
|
||||
|
||||
<div class="pdv">
|
||||
<Default client:visible {...Astro.props} isAstro={true}>
|
||||
<slot />
|
||||
</Default>
|
||||
<Default client:visible {...Astro.props} />
|
||||
</div>
|
||||
|
||||
|
||||
|
||||