mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-21 20:55:12 -04:00
Compare commits
816 Commits
node
...
techmanual-wiki
| Author | SHA1 | Date | |
|---|---|---|---|
| d856e567c1 | |||
| a7f044e1aa | |||
| 1f7d78c6ce | |||
| 4137f39495 | |||
| 0163c8ba25 | |||
| 912b3270aa | |||
| 2bc3d69fb0 | |||
| aa20526963 | |||
| 47de9e45ff | |||
| 0c193238c5 | |||
| 3428e18e7d | |||
| 8fba92f447 | |||
| 38e7fe606c | |||
| 59e7584bf7 | |||
| 7f50bcebd2 | |||
| d7b83e200c | |||
| db33707e52 | |||
| 78fca9695c | |||
| 3dbae7907c | |||
| dcac254790 | |||
| 000114fcc8 | |||
| 062201d1dc | |||
| 8c8e914170 | |||
| 1141b1803b | |||
| fec38bd5d2 | |||
| a3d9d68c45 | |||
| 990f1c6ece | |||
| c0ae12f32f | |||
| 307e5ea2d7 | |||
| 5fdea7fd80 | |||
| 580447d00a | |||
| b6e67f3474 | |||
| 84efa664ca | |||
| 94746b5fae | |||
| c1fa5d0855 | |||
| 372542dcd8 | |||
| 694a22af85 | |||
| ef3b9a68e3 | |||
| 40ba5d4465 | |||
| 79f7938b33 | |||
| 2c9f9d785f | |||
| 5a88a6daa6 | |||
| 9350d826a3 | |||
| df923174ed | |||
| cde943d737 | |||
| f363bd6bcc | |||
| e0a21a936b | |||
| b312ff63a9 | |||
| 93bc353b6b | |||
| 14a0dea826 | |||
| 009f5445be | |||
| 3d37c73103 | |||
| 0b0f9fe13b | |||
| 1d189763b2 | |||
| a4b55776d2 | |||
| 0287be547a | |||
| 6a83ede33d | |||
| 1e3f546918 | |||
| faa60be211 | |||
| dde2b9c6f8 | |||
| 382dce65df | |||
| 63f4f202f1 | |||
| 366637026b | |||
| 608dfd515e | |||
| 9bd7b66228 | |||
| 5e4eb7fc53 | |||
| 45bccf13ff | |||
| 65f1760fad | |||
| b8d2d02466 | |||
| 058cb36640 | |||
| 5c3501caa4 | |||
| 1341bd9c92 | |||
| 760d1abec0 | |||
| 2b44fc48a4 | |||
| 99779171f5 | |||
| 64ebfb57c3 | |||
| 099d321dbd | |||
| 59bdfd2cb8 | |||
| 56d3436fda | |||
| 440ce0cd3b | |||
| 98346261ed | |||
| 38e4718826 | |||
| 38908baccd | |||
| 8d02d4270a | |||
| 9cf1cd2656 | |||
| 4c079b6ebe | |||
| e9e2e881e5 | |||
| 685b4f172b | |||
| 53e50d81b0 | |||
| 8f58d5788f | |||
| 306a6db8dc | |||
| 757d78252b | |||
| 6f2e026e4a | |||
| 22f114be59 | |||
| f993056fb1 | |||
| fdbbcd2dd2 | |||
| 7bec92ca99 | |||
| 5702914661 | |||
| f2a9e2d4e6 | |||
| 6398b5fb38 | |||
| 9ceebd4679 | |||
| 177f5c1431 | |||
| d6c2a88496 | |||
| 3ee7d0cd4f | |||
| 53d43dc44c | |||
| 637c619345 | |||
| 47fb441feb | |||
| d02b1fc05c | |||
| 480b5ff58b | |||
| c088c0c9d2 | |||
| f32abac06f | |||
| 697f0a82e6 | |||
| 98970417c3 | |||
| b5d48b2f0b | |||
| c48aba50f0 | |||
| f539930509 | |||
| 759cdb6276 | |||
| 3dae2a80ab | |||
| 7cc44a8829 | |||
| 90506f9e61 | |||
| c852b5fab0 | |||
| bd08b74ebc | |||
| 8f4dcb6bc6 | |||
| 17e1ebeb93 | |||
| ad25ce7b21 | |||
| 6e3aa693d5 | |||
| 2968017300 | |||
| ab76b4424a | |||
| b64daf6284 | |||
| 2b69004eb4 | |||
| a32bb58fb3 | |||
| 9e233fe587 | |||
| b1090a1dd8 | |||
| 344d9ca1a8 | |||
| b92a28242e | |||
| 695ac6a5d3 | |||
| a468201822 | |||
| 05ea9c86fb | |||
| 6e29210bdc | |||
| e81345ca2f | |||
| 6b8ee8ad11 | |||
| c2d4b529f6 | |||
| 999c0b2349 | |||
| 5ed28d6168 | |||
| bceb37e8ea | |||
| 2f4cba4e94 | |||
| d8e4055c6e | |||
| 6f9bcc53dc | |||
| 8962e5a4f0 | |||
| e55b7c6ce3 | |||
| 9b4574c7b0 | |||
| 6d355a803a | |||
| dee75bc759 | |||
| dc8e5d5394 | |||
| 282180ef1c | |||
| 3eea908636 | |||
| bfbd920b1d | |||
| 739fb8562f | |||
| cbd448e934 | |||
| b192c6823c | |||
| dccfefacd7 | |||
| 38876e135b | |||
| f652c2ca86 | |||
| 4f6c4bb95f | |||
| f5bb88a696 | |||
| b27c9dbf37 | |||
| 5fcb96f73c | |||
| 17df418935 | |||
| 2ccb95aec0 | |||
| 3c2692bdda | |||
| 756a65016d | |||
| a18d485283 | |||
| fcf6450ff0 | |||
| 09dd374722 | |||
| 9c9ce50b03 | |||
| edc2903106 | |||
| b15843f3a7 | |||
| 86333ab6f6 | |||
| 003e3b790d | |||
| 4048ced7e6 | |||
| 64b99f5a8c | |||
| b4af840240 | |||
| 8a502e886e | |||
| c7ee90922f | |||
| 530339ed8f | |||
| fece4e8b57 | |||
| afdcd42039 | |||
| 690b8648a8 | |||
| 7c1e968d41 | |||
| c0b3187029 | |||
| af1f7658c7 | |||
| b531962b1f | |||
| 8867a843ac | |||
| 6e972f4380 | |||
| 65282bf5ea | |||
| 3df9744d79 | |||
| 5a5bbfc8da | |||
| f66478b9da | |||
| 904c213d03 | |||
| d9c3f051b9 | |||
| 470a345296 | |||
| 0925ea56dd | |||
| 1f233b9e7d | |||
| 5c5d411588 | |||
| bbb88a2302 | |||
| 64c94b3623 | |||
| 42c2262576 | |||
| 4959bff060 | |||
| 1ded398468 | |||
| b016720696 | |||
| c639e44ca7 | |||
| b664bd3d1f | |||
| dfb7d7bb7f | |||
| 3e6a45cf8b | |||
| f47f5c1344 | |||
| 47f65da621 | |||
| c210ea3f89 | |||
| 50f076084f | |||
| 5cd98880ca | |||
| aabc82bedd | |||
| 84581b22aa | |||
| 3575fc3cc8 | |||
| 43523b73c4 | |||
| b98ebc696d | |||
| f802f18d68 | |||
| 919c2854d5 | |||
| cf8203a4db | |||
| cda79f3e5c | |||
| 07b0a2e0f0 | |||
| 5e81b542dc | |||
| 451cdcc3a9 | |||
| 5ff1d35272 | |||
| 8bde61fa27 | |||
| efd4071637 | |||
| 981ad1e242 | |||
| 49e9b84962 | |||
| 54c5454306 | |||
| 9b279ff671 | |||
| 20dcae68c1 | |||
| 52d1443cf8 | |||
| 848edb1f69 | |||
| 88fb0b3b75 | |||
| dc8becc610 | |||
| e99f229b57 | |||
| c810a02a79 | |||
| ed7dc4ef6e | |||
| 4636d824fa | |||
| 018d1ccd31 | |||
| d86df33b8c | |||
| b74d5becd5 | |||
| b87b2aff9a | |||
| 95b1548e5f | |||
| 0b1bc74c3b | |||
| ce9d23049a | |||
| 0338c5b222 | |||
| 1bf74024d4 | |||
| 63ee218d53 | |||
| 3d37478577 | |||
| 9d5d86bb09 | |||
| e2b7c3a62b | |||
| 1fb68af5af | |||
| b611c9c2b4 | |||
| ceb466ab9c | |||
| d09809ed12 | |||
| f558b4b8f6 | |||
| f26a2af38e | |||
| 75f5f45652 | |||
| 5cef1a8cf9 | |||
| bcb1da826e | |||
| 1f5f1a63a6 | |||
| 44828e2047 | |||
| bcef67e5a1 | |||
| b4ef786108 | |||
| d03fc43f03 | |||
| ca00f7c5d0 | |||
| dbbe2d7c98 | |||
| 1058c272a4 | |||
| 81e97a5643 | |||
| f105ea6677 | |||
| 6307f755f7 | |||
| fac698e39c | |||
| d54022a65a | |||
| 892a686462 | |||
| fbf9d06d84 | |||
| 06415d7f14 | |||
| d353eff1f6 | |||
| ce5add4a56 | |||
| 212a478161 | |||
| 33b31fb434 | |||
| b51dacb11c | |||
| 1e59b4efa4 | |||
| e31a9965d5 | |||
| 6c537cb134 | |||
| 6062a2e757 | |||
| ac83ff8817 | |||
| b55661b21e | |||
| 638e247a5f | |||
| ff4d4357b2 | |||
| 1460defa42 | |||
| 1053c7eb38 | |||
| c09b590cf6 | |||
| 63f9f6cba0 | |||
| 9112a0c4f5 | |||
| e754070a59 | |||
| afa202e2a8 | |||
| fc3d7ade11 | |||
| d192201e07 | |||
| c9bdfe57dd | |||
| 7e1c6c1c22 | |||
| 5d3778fb27 | |||
| f362f1c9f6 | |||
| fd68ad9bde | |||
| 7222c29c55 | |||
| 234beff00e | |||
| 90fe4d3816 | |||
| 5a188f7461 | |||
| 5d98fd2ab3 | |||
| 46400effb7 | |||
| 710da1d28d | |||
| f4b8753171 | |||
| aa1efcc7ea | |||
| 3e721d91a5 | |||
| badbcdcf25 | |||
| 4f35027d9f | |||
| de7c652706 | |||
| 0e59a233ed | |||
| b3e0f180b3 | |||
| a2c896f765 | |||
| c7cd03a2aa | |||
| e6604491a9 | |||
| 1d7f755b89 | |||
| 4f6e38f714 | |||
| 23ed342635 | |||
| 443760c0d1 | |||
| bb56ed479f | |||
| c5d7f95441 | |||
| 3ffe3957ba | |||
| 3189b365c8 | |||
| e19d059c0f | |||
| b8b999eab5 | |||
| 393d17a41b | |||
| 35911f3082 | |||
| 024f424bf5 | |||
| 1b8ccc05e1 | |||
| 77267a80e3 | |||
| 0ca540b671 | |||
| 5731ae0cdc | |||
| 5d562e8cd6 | |||
| 9432f780f2 | |||
| d06a75a2cd | |||
| 57c48f0c45 | |||
| a4792e29f5 | |||
| 52ebfa1d09 | |||
| 6cde970e0d | |||
| 188d318125 | |||
| f95eadab2f | |||
| 1349ecb4af | |||
| 268c66cd3d | |||
| 8d28317d0e | |||
| fc41bd1a70 | |||
| 773420fd65 | |||
| 45fffa514a | |||
| a8803784e1 | |||
| bfb4eee122 | |||
| 3325a8dbe9 | |||
| 13a4512601 | |||
| cdf50cbaab | |||
| f61916fffa | |||
| 00b0341839 | |||
| d5ab391a98 | |||
| d2a9b9b750 | |||
| 2348023b22 | |||
| 6e5d8eed19 | |||
| c33c8b5469 | |||
| 7b6074ccef | |||
| e085819fe2 | |||
| 155ef9e95f | |||
| 55c226cda6 | |||
| c242f5f625 | |||
| 859f153ec6 | |||
| c5de21ef61 | |||
| 36374fb3fb | |||
| 570c7a0d6b | |||
| c3be21e6e5 | |||
| 7410ac5cec | |||
| f5127147de | |||
| 1d144faed7 | |||
| 7b914e7f22 | |||
| 052addd67e | |||
| 3d162536aa | |||
| 2443aad01b | |||
| 08f6c1ad5e | |||
| 974376d404 | |||
| 1da80db048 | |||
| 42519581c1 | |||
| 1e3bbc57cc | |||
| 9bf0f624f5 | |||
| c6418789c4 | |||
| 62d6ef2287 | |||
| 8b909c54db | |||
| 9d029ac914 | |||
| 8644b3d163 | |||
| 426c5edf25 | |||
| d30623dad4 | |||
| 49d4fb499f | |||
| e4f89f072e | |||
| e12dadb33f | |||
| 991d8e4717 | |||
| 26cc7e2920 | |||
| 04eac3e7c5 | |||
| 7cf7575e6d | |||
| 0be9f439bc | |||
| 36fe942e24 | |||
| 06958a5281 | |||
| 033b123ae0 | |||
| b7d8593a4d | |||
| a5b05d211e | |||
| 111cea2381 | |||
| 896a3828f6 | |||
| eb02997836 | |||
| 8a33c171f5 | |||
| f87f279198 | |||
| 4cc019f038 | |||
| 34f4afad01 | |||
| 947b263b9c | |||
| 0a408e464a | |||
| 0d660277f6 | |||
| 33fef379ad | |||
| 0531369613 | |||
| c66f19108c | |||
| ef53367ba9 | |||
| f01d51f76a | |||
| d741b4d17a | |||
| f33ec0e2af | |||
| 726abf76ce | |||
| a7d74ed6d6 | |||
| bd69ffb4b7 | |||
| 648fbf99fa | |||
| b913e1c50d | |||
| 23a4bf6641 | |||
| ec470aa2c6 | |||
| ae335ac40c | |||
| 9ecad810b1 | |||
| f18cf76dde | |||
| 08c918f13e | |||
| 2e72c7f4ed | |||
| 614f393a5d | |||
| 75f7f4deac | |||
| 2a67698616 | |||
| 801879bddf | |||
| 7d8984b706 | |||
| 1a2847d953 | |||
| e71db24073 | |||
| f61de0c47c | |||
| 53b8bbb732 | |||
| aeaf447142 | |||
| 1e6e0a61b3 | |||
| dd696ba663 | |||
| be4c8cbdce | |||
| b6b54a8553 | |||
| 1d05051fd6 | |||
| 6bca8e2a2f | |||
| 630ba62cc3 | |||
| 8ac98262bc | |||
| 6057e9ada1 | |||
| 94e8b18ffa | |||
| 2ec20c4ed4 | |||
| c4fe2c7497 | |||
| df2d28f0e5 | |||
| d9bd6f9e7d | |||
| 1e0cc2ab17 | |||
| 835c7b6879 | |||
| 721e7f06b8 | |||
| a46bbeaa10 | |||
| e3a3c0c5f9 | |||
| 67964c7e23 | |||
| 9e5f9d37ef | |||
| 0c1234a35f | |||
| c6cc487fc6 | |||
| dd171f8320 | |||
| c22c786cf2 | |||
| c191471e1e | |||
| 0d0cb3fd93 | |||
| bb4b7dc533 | |||
| 8440fa42ea | |||
| 61f070744a | |||
| 2e6a561184 | |||
| 8703d684c4 | |||
| b0d2115f43 | |||
| 96802a271c | |||
| a91f4576f3 | |||
| ad080d02b3 | |||
| e9e7e02547 | |||
| 2ffc6c9601 | |||
| 3a9349d9f5 | |||
| bd3f2845f8 | |||
| 2d320c459b | |||
| ff9f4a8a0d | |||
| d7b94807cb | |||
| 2c16a37a68 | |||
| 717e4a2c1d | |||
| c225b4719f | |||
| 25f762c393 | |||
| b75561e3c7 | |||
| abaab89061 | |||
| e409086b34 | |||
| 532f1435d9 | |||
| 6cb61ade03 | |||
| a40219ba06 | |||
| 9c99f5ada2 | |||
| 2d72c8faa0 | |||
| b188fc6b6d | |||
| bfb22228cc | |||
| 9714d88d61 | |||
| bdddb91510 | |||
| 07bcaa65a9 | |||
| 5bf1805534 | |||
| 202685e8c4 | |||
| aba633e16e | |||
| da45ce689c | |||
| acea7e435e | |||
| cb4810cbbc | |||
| 5ec205b383 | |||
| ebc0b293a9 | |||
| 4608c321bd | |||
| c4243f41c6 | |||
| d95b8bc667 | |||
| 263c13c36e | |||
| ddceb36613 | |||
| ff8ec628be | |||
| 11a07df120 | |||
| 8befa4382b | |||
| 39006e4d71 | |||
| 812ed6b60d | |||
| 8b6c8eb35d | |||
| dcda9a5753 | |||
| d3733d4209 | |||
| ef6af96947 | |||
| d86ff0a536 | |||
| 2c9ea03fde | |||
| 4eae366bee | |||
| 117f7fa4b5 | |||
| 73ee84a1fb | |||
| 9c899d5308 | |||
| b60beaf508 | |||
| 796f741a92 | |||
| 8da1d9fbf3 | |||
| 5345986b5b | |||
| 3945abd7e9 | |||
| 053e4ee54b | |||
| 25d61a2e31 | |||
| 5e6131af24 | |||
| 2899ee5aef | |||
| 9d1674b13c | |||
| bfead58212 | |||
| 926c893c4f | |||
| 3cd31e4841 | |||
| c2be2ed76a | |||
| ac0dc7a8de | |||
| cba9169b2f | |||
| e9a0a06b77 | |||
| d80c06cd55 | |||
| d850726910 | |||
| 1b01f41ffd | |||
| ad00fa65f8 | |||
| 814babbf7a | |||
| 28334ec94d | |||
| 7d2110d75f | |||
| 94ccfa631e | |||
| c7c56a1357 | |||
| d40e4dac2f | |||
| 686247f0cb | |||
| dffeac41af | |||
| 6e496b7a4a | |||
| 71e843e1a3 | |||
| 61ba33043e | |||
| 943d78f268 | |||
| 5ac59e95dd | |||
| 03bbc0bc27 | |||
| 4c3457438d | |||
| 85bccdcc19 | |||
| 94c07b6b7a | |||
| 42000a7628 | |||
| f514cd85b1 | |||
| d53929cf68 | |||
| a4bd0ae100 | |||
| 283a071c86 | |||
| b5fbcd108f | |||
| 6350cfdb9c | |||
| 5e9da78e64 | |||
| f3b83b41f5 | |||
| 1d95da7a3a | |||
| 2a2ddf205a | |||
| 6c9e0aaa1a | |||
| d23038d386 | |||
| 248f67d1ab | |||
| f3fa1483d7 | |||
| 11102adb75 | |||
| 9f958abb08 | |||
| b72e71b0bd | |||
| 065b24a2ee | |||
| 758b94776d | |||
| e6f3b1f1ef | |||
| e62d5759e7 | |||
| c403a92542 | |||
| 269d6dde31 | |||
| 666c695c63 | |||
| 771eb31d3f | |||
| c05bbf3422 | |||
| 364f511a7c | |||
| 300022d8ac | |||
| 357fbf8c82 | |||
| 1acb675f5a | |||
| ab1086318c | |||
| 8c73ad088a | |||
| 25981092b1 | |||
| e6b55baed0 | |||
| 6adf1ff977 | |||
| b6e277f1ea | |||
| d0510f862a | |||
| 4a87df6426 | |||
| bf90867685 | |||
| 3dc5fd0e7e | |||
| a7650f1af3 | |||
| aadb2fee84 | |||
| bf391ad6ce | |||
| faba4a4e4e | |||
| 94e411aa7a | |||
| ffa21ddf0d | |||
| 6b2d080afc | |||
| 321a888921 | |||
| bf7fe2bf75 | |||
| 1fd9ba5dbf | |||
| 1fca6f25b8 | |||
| 0e6a17fc77 | |||
| 375c68775c | |||
| 827993a8c9 | |||
| 2aa1acfd95 | |||
| 2febbaf40b | |||
| e29876e7f6 | |||
| 3ce32438d6 | |||
| a17351e11e | |||
| 94f5886466 | |||
| 1a72b9e526 | |||
| 1eef2c2511 | |||
| 05289b171b | |||
| 33322be948 | |||
| 6f7f415747 | |||
| 7a4902862d | |||
| c20e84773b | |||
| 5c9a16bc88 | |||
| 07f58c023f | |||
| 08f0825561 | |||
| 2cda78d2db | |||
| ff85f2307f | |||
| af3d32a493 | |||
| c0c54c21e3 | |||
| 8be5e9d2eb | |||
| 589dfaf8cc | |||
| 3cd31b2290 | |||
| 65856409b6 | |||
| e408fedaf6 | |||
| d424b118ff | |||
| 492878754a | |||
| d86a183194 | |||
| 6325d726a5 | |||
| 553045e666 | |||
| 4733264fb3 | |||
| 0efac42d92 | |||
| be6634f919 | |||
| 2901369471 | |||
| 61d795af31 | |||
| 2bae6e06c0 | |||
| d9214b91b6 | |||
| 5348a6b2d8 | |||
| 35e9385f59 | |||
| bf5e66d69a | |||
| 3cacafff90 | |||
| e2ce5ea001 | |||
| 8f7194144d | |||
| 12cb5b0939 | |||
| 1ad118d877 | |||
| bf73610b0a | |||
| 8f1496cebe | |||
| 7efbee0646 | |||
| aec7417c14 | |||
| 026cbe050c | |||
| 8710cd446b | |||
| cad27301db | |||
| 98cb128fa2 | |||
| 9bb1039bbd | |||
| 7952dfa5e9 | |||
| 1666fc5649 | |||
| b19c737c82 | |||
| 2d3a9b800f | |||
| e60e9b2fdd | |||
| 94529549a9 | |||
| 90dfa5170c | |||
| c797fea1f7 | |||
| 841d897d0a | |||
| 9774e9627b | |||
| 888e0d4751 | |||
| 1595a4ece3 | |||
| 1cebfd1835 | |||
| 8ea50fbe7d | |||
| 349f902dc0 | |||
| 8b1df7ce85 | |||
| 892a0abe78 | |||
| a214b1b224 | |||
| eed4a83b71 | |||
| 17e2ee4a3b | |||
| b8085e9dc3 | |||
| 1952e4d49a | |||
| be65a10925 | |||
| 255c283ae4 | |||
| 84a8ca9d19 | |||
| 25064b427d | |||
| 1761fa0346 | |||
| dd29c5b09e | |||
| ef331f25e0 | |||
| 1bc1346f54 | |||
| 373b63c700 | |||
| 41444ccd58 | |||
| fe1e10297c | |||
| e483f4c3d3 | |||
| 574c5285b9 | |||
| 5e4eefa553 | |||
| 8ac409f03c | |||
| c4b3d48498 | |||
| 8f86bbc6ba | |||
| 97568300cb | |||
| bce24980cb | |||
| 33ca43a234 | |||
| d0ecf15f77 | |||
| e87055d583 | |||
| 9b52807c7e | |||
| a8eafbc309 | |||
| b0edf74aee | |||
| a8dce19902 | |||
| dcd828a117 | |||
| aa2466b2cc | |||
| a94ddc7947 | |||
| e6f272dd0c | |||
| 4160639d88 | |||
| 5fb3aadad9 | |||
| 3b4ae44fb3 | |||
| 2499c4057c | |||
| 71f8c0745c | |||
| d132344d11 | |||
| b4f1cedc20 | |||
| 5b89500acd | |||
| a35e9aef0e | |||
| fd950d4476 | |||
| d108de40d0 | |||
| 5f8da04cd8 | |||
| def5bc858f | |||
| a9fa6f14fb | |||
| 846c12806e | |||
| 70e938b767 | |||
| f54f80e698 | |||
| 8c480807d2 | |||
| bbeb243cea | |||
| 0123f4e5f3 | |||
| c232fb7dd5 | |||
| 69a5d62027 | |||
| ed506cabb5 | |||
| d49c9dce4f | |||
| 16ad27406d | |||
| 803b5e56fc | |||
| 29598d1744 | |||
| eba7dec1a5 | |||
| 09e455e17e | |||
| 2aac085bb8 | |||
| 733d6ec673 | |||
| 179931be88 | |||
| 9d5acc0f32 | |||
| 226cf356d6 | |||
| 4ade86f75c | |||
| 73d49f152a | |||
| 83e46037d2 | |||
| 95ae5191ce | |||
| e268802f3c | |||
| 55c7f2b575 | |||
| a69563cb9b | |||
| 33ebf08e81 | |||
| 02ea4d1116 | |||
| 27d8bae671 | |||
| 5dc2ecd741 | |||
| 6e6a2439c3 | |||
| 6249631a72 | |||
| b69b9c37cd | |||
| 7f22040a0c | |||
| 956ceb8aa4 | |||
| e47d67a9da | |||
| 6b919132aa | |||
| 5ca9afa9e8 | |||
| a4897adb83 | |||
| 0ba4be0571 | |||
| ca8707f32a | |||
| 18abcaccbb | |||
| 6ff7697cfd | |||
| 915a4d2149 | |||
| 3a4ffb13ad | |||
| 610c848ff4 | |||
| d06b70c28d | |||
| fde0da3b19 | |||
| b233c33f56 | |||
| e3b6884b86 | |||
| cdba9efb59 | |||
| eefd8b37b1 | |||
| 89ae241bf7 | |||
| a39b4c1637 | |||
| 4d332cd544 | |||
| 64dbdd97ba | |||
| 756f37e265 | |||
| 9e1ba442a9 |
@@ -1,24 +0,0 @@
|
|||||||
krill-parser.js
|
|
||||||
krill.pegjs
|
|
||||||
.eslintrc.json
|
|
||||||
server.js
|
|
||||||
tidal-sniffer.js
|
|
||||||
*.jsx
|
|
||||||
tunejs.js
|
|
||||||
out/**
|
|
||||||
postcss.config.js
|
|
||||||
postcss.config.cjs
|
|
||||||
tailwind.config.js
|
|
||||||
tailwind.config.cjs
|
|
||||||
vite.config.js
|
|
||||||
/**/dist/**/*
|
|
||||||
!**/*.mjs
|
|
||||||
**/*.tsx
|
|
||||||
**/*.ts
|
|
||||||
**/*.json
|
|
||||||
**/dev-dist
|
|
||||||
**/dist
|
|
||||||
/src-tauri/target/**/*
|
|
||||||
reverbGen.mjs
|
|
||||||
hydra.mjs
|
|
||||||
jsdoc-synonyms.js
|
|
||||||
+3
-1
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
|
"node": true,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es2021": true
|
"es2021": true
|
||||||
},
|
},
|
||||||
@@ -13,5 +14,6 @@
|
|||||||
"rules": {
|
"rules": {
|
||||||
"no-unused-vars": ["warn", { "destructuredArrayIgnorePattern": ".", "ignoreRestSiblings": false }],
|
"no-unused-vars": ["warn", { "destructuredArrayIgnorePattern": ".", "ignoreRestSiblings": false }],
|
||||||
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}]
|
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}]
|
||||||
}
|
},
|
||||||
|
"files": ["**/*.mjs", "**/*.js"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,6 @@ name: Build and Deploy
|
|||||||
|
|
||||||
on: [workflow_dispatch]
|
on: [workflow_dispatch]
|
||||||
|
|
||||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
deployments: write
|
|
||||||
|
|
||||||
# Allow one concurrent deployment
|
# Allow one concurrent deployment
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "pages"
|
group: "pages"
|
||||||
@@ -16,34 +9,29 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: docker
|
||||||
environment:
|
env:
|
||||||
name: github-pages
|
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8.11.0
|
version: 9.12.2
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
# cache: "pnpm"
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Setup Pages
|
- name: Deploy
|
||||||
uses: actions/configure-pages@v2
|
run: |
|
||||||
|
eval $(ssh-agent -s)
|
||||||
- name: Upload artifact
|
echo "$SSH_PRIVATE_KEY" | ssh-add -
|
||||||
uses: actions/upload-pages-artifact@v1
|
apt update && apt install -y rsync
|
||||||
with:
|
mkdir ~/.ssh
|
||||||
# Upload entire repository
|
ssh-keyscan matrix.toplap.org > ~/.ssh/known_hosts
|
||||||
path: "./website/dist"
|
rsync -atv --delete --delete-after --progress ./website/dist/ strudel@matrix.toplap.org:/home/strudel/deploy
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v1
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
name: Tauri Builder
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
platform: [macos-latest, ubuntu-latest, windows-latest]
|
|
||||||
include:
|
|
||||||
- os: ubuntu-latest
|
|
||||||
rust_target: x86_64-unknown-linux-gnu
|
|
||||||
- os: macos-latest
|
|
||||||
rust_target: x86_64-apple-darwin
|
|
||||||
- os: macos-latest
|
|
||||||
rust_target: aarch64-apple-darwin
|
|
||||||
- os: windows-latest
|
|
||||||
rust_target: x86_64-pc-windows-msvc
|
|
||||||
runs-on: ${{ matrix.platform }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
with:
|
|
||||||
version: 8.6.2
|
|
||||||
|
|
||||||
- name: Node.js setup
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: latest
|
|
||||||
# node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install Rust (Stable)
|
|
||||||
run:
|
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
|
||||||
|
|
||||||
- name: Install dependencies (ubuntu only)
|
|
||||||
if: matrix.platform == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf libasound2-dev
|
|
||||||
|
|
||||||
- name: Install app dependencies from lockfile and build web
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Build the app
|
|
||||||
uses: tauri-apps/tauri-action@v0
|
|
||||||
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
# tauri-action replaces \_\_VERSION\_\_ with the app version
|
|
||||||
tagName: ${{ github.ref_name }}
|
|
||||||
releaseName: "Strudel v__VERSION__"
|
|
||||||
releaseBody: |
|
|
||||||
See the assets to download this version and install.
|
|
||||||
releaseDraft: true
|
|
||||||
prerelease: false
|
|
||||||
@@ -4,20 +4,20 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: docker
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20]
|
node-version: [20]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8.11.0
|
version: 9.12.2
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
# cache: 'pnpm'
|
||||||
- run: pnpm install
|
- run: pnpm install
|
||||||
- run: pnpm run format-check
|
- run: pnpm run format-check
|
||||||
- run: pnpm run lint
|
- run: pnpm run lint
|
||||||
|
|||||||
@@ -130,3 +130,4 @@ fabric.properties
|
|||||||
|
|
||||||
samples/*
|
samples/*
|
||||||
!samples/README.md
|
!samples/README.md
|
||||||
|
.idea/
|
||||||
|
|||||||
@@ -11,3 +11,6 @@ pnpm-lock.yaml
|
|||||||
pnpm-workspace.yaml
|
pnpm-workspace.yaml
|
||||||
**/dev-dist
|
**/dev-dist
|
||||||
website/.astro
|
website/.astro
|
||||||
|
!tidal-drum-machines.json
|
||||||
|
!tidal-drum-machines-alias.json
|
||||||
|
.pnpm-store
|
||||||
|
|||||||
+27
-11
@@ -2,11 +2,21 @@
|
|||||||
|
|
||||||
Thanks for wanting to contribute!!! There are many ways you can add value to this project
|
Thanks for wanting to contribute!!! There are many ways you can add value to this project
|
||||||
|
|
||||||
|
## Move to codeberg
|
||||||
|
|
||||||
|
We are currently in the process of moving from github to codeberg -- not everything is working, please bear with us.
|
||||||
|
|
||||||
|
To update your local clone, you can run this command:
|
||||||
|
|
||||||
|
```
|
||||||
|
git remote set-url origin git@codeberg.org:uzu/strudel.git
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Communication Channels
|
## Communication Channels
|
||||||
|
|
||||||
To get in touch with the contributors, either
|
To get in touch with the contributors, either
|
||||||
|
|
||||||
- open a [github discussion](https://github.com/tidalcycles/strudel/discussions) or
|
|
||||||
- [join the Tidal Discord Channel](https://discord.gg/remJ6gQA) and go to the #strudel channel
|
- [join the Tidal Discord Channel](https://discord.gg/remJ6gQA) and go to the #strudel channel
|
||||||
- Find related discussions on the [tidal club forum](https://club.tidalcycles.org/)
|
- Find related discussions on the [tidal club forum](https://club.tidalcycles.org/)
|
||||||
|
|
||||||
@@ -32,7 +42,7 @@ Use one of the Communication Channels listed above.
|
|||||||
## Improve the Docs
|
## Improve the Docs
|
||||||
|
|
||||||
If you find some weak spots in the [docs](https://strudel.cc/workshop/getting-started/),
|
If you find some weak spots in the [docs](https://strudel.cc/workshop/getting-started/),
|
||||||
you can edit each file directly on github via the "Edit this page" link located in the right sidebar.
|
you can edit each file directly on codeburg. (we are currently fixing the "Edit this page" links in the right sidebar)
|
||||||
|
|
||||||
## Propose a Feature
|
## Propose a Feature
|
||||||
|
|
||||||
@@ -41,7 +51,7 @@ Maybe you even want to help with the implementation of that feature!
|
|||||||
|
|
||||||
## Report a Bug
|
## Report a Bug
|
||||||
|
|
||||||
If you've found a bug, or some behaviour that does not seem right, you are welcome to file an [issue](https://github.com/tidalcycles/strudel/issues).
|
If you've found a bug, or some behaviour that does not seem right, you are welcome to file an [issue](https://codeberg.org/uzu/strudel/issues).
|
||||||
Please check that it has not been reported before.
|
Please check that it has not been reported before.
|
||||||
|
|
||||||
## Fix a Bug
|
## Fix a Bug
|
||||||
@@ -71,7 +81,7 @@ To get the project up and running for development, make sure you have installed:
|
|||||||
then, do the following:
|
then, do the following:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/tidalcycles/strudel.git && cd strudel
|
git clone https://codeberg.org/uzu/strudel.git && cd strudel
|
||||||
pnpm i # install at root to symlink packages
|
pnpm i # install at root to symlink packages
|
||||||
pnpm start # start repl
|
pnpm start # start repl
|
||||||
```
|
```
|
||||||
@@ -113,7 +123,7 @@ You can run the same check with `pnpm check`
|
|||||||
|
|
||||||
## Package Workflow
|
## Package Workflow
|
||||||
|
|
||||||
The project is split into multiple [packages](https://github.com/tidalcycles/strudel/tree/main/packages) with independent versioning.
|
The project is split into multiple [packages](https://codeberg.org/uzu/strudel/src/branch/main/packages) with independent versioning.
|
||||||
When you run `pnpm i` on the root folder, [pnpm workspaces](https://pnpm.io/workspaces) will install all dependencies of all subpackages. This will allow any js file to import `@strudel/<package-name>` to get the local version,
|
When you run `pnpm i` on the root folder, [pnpm workspaces](https://pnpm.io/workspaces) will install all dependencies of all subpackages. This will allow any js file to import `@strudel/<package-name>` to get the local version,
|
||||||
allowing to develop multiple packages at the same time.
|
allowing to develop multiple packages at the same time.
|
||||||
|
|
||||||
@@ -130,20 +140,26 @@ npx lerna version --no-private
|
|||||||
# publish all packages inside /packages using pnpm! don't use lerna to publish!!
|
# publish all packages inside /packages using pnpm! don't use lerna to publish!!
|
||||||
pnpm --filter "./packages/**" publish --dry-run
|
pnpm --filter "./packages/**" publish --dry-run
|
||||||
|
|
||||||
# the last command was only a dry-run, make sure everything looks ok, if yes, run the same command without flag
|
# the last command was only a dry-run. if everything looks ok, run this:
|
||||||
|
|
||||||
|
pnpm --filter "./packages/**" publish --access public
|
||||||
```
|
```
|
||||||
|
|
||||||
To manually publish a single package, increase the version in the `package.json`, then run `pnpm publish`.
|
To manually publish a single package, increase the version in the `package.json`, then run `pnpm publish`.
|
||||||
Important: Always publish with `pnpm`, as `npm` does not support overriding main files in `publishConfig`, which is done in all the packages.
|
Important: Always publish with `pnpm`, as `npm` does not support overriding main files in `publishConfig`, which is done in all the packages.
|
||||||
|
|
||||||
### New Packages
|
|
||||||
|
|
||||||
To add a new package, you have to publish it manually the first time, using:
|
|
||||||
|
|
||||||
|
## useful commands
|
||||||
```sh
|
```sh
|
||||||
cd packages/<package-name> && pnpm publish --access public
|
#regenerate the test snapshots (ex: when updating or creating new pattern functions)
|
||||||
```
|
pnpm snapshot
|
||||||
|
|
||||||
|
#start the OSC server
|
||||||
|
pnpm run osc
|
||||||
|
|
||||||
|
#build the standalone version
|
||||||
|
pnpm tauri build
|
||||||
|
```
|
||||||
## Have Fun
|
## Have Fun
|
||||||
|
|
||||||
Remember to have fun, and that this project is driven by the passion of volunteers!
|
Remember to have fun, and that this project is driven by the passion of volunteers!
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# strudel
|
# strudel
|
||||||
|
|
||||||
[](https://github.com/tidalcycles/strudel/actions)
|
Live coding patterns on the web
|
||||||
|
https://strudel.cc/
|
||||||
|
|
||||||
An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using web technologies. This software is a bit more stable now, but please continue to tread carefully.
|
Development is moving to https://codeberg.org/uzu/strudel
|
||||||
|
|
||||||
- Try it here: <https://strudel.cc>
|
- Try it here: <https://strudel.cc>
|
||||||
- Docs: <https://strudel.cc/learn>
|
- Docs: <https://strudel.cc/learn>
|
||||||
@@ -14,10 +15,16 @@ An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using w
|
|||||||
|
|
||||||
After cloning the project, you can run the REPL locally:
|
After cloning the project, you can run the REPL locally:
|
||||||
|
|
||||||
```bash
|
1. Install [Node.js](https://nodejs.org/)
|
||||||
pnpm i
|
2. Install [pnpm](https://pnpm.io/installation)
|
||||||
pnpm dev
|
3. Install dependencies by running the following command:
|
||||||
```
|
```bash
|
||||||
|
pnpm i
|
||||||
|
```
|
||||||
|
4. Run the development server:
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
## Using Strudel In Your Project
|
## Using Strudel In Your Project
|
||||||
|
|
||||||
@@ -25,11 +32,15 @@ This project is organized into many [packages](./packages), which are also avail
|
|||||||
|
|
||||||
Read more about how to use these in your own project [here](https://strudel.cc/technical-manual/project-start).
|
Read more about how to use these in your own project [here](https://strudel.cc/technical-manual/project-start).
|
||||||
|
|
||||||
|
You will need to abide by the terms of the [GNU Affero Public Licence v3](LICENSE.md). As such, Strudel code can only be shared within free/open source projects under the same license -- see the license for details.
|
||||||
|
|
||||||
|
Licensing info for the default sound banks can be found over on the [dough-samples](https://github.com/felixroos/dough-samples/blob/main/README.md) repository.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
There are many ways to contribute to this project! See [contribution guide](./CONTRIBUTING.md).
|
There are many ways to contribute to this project! See [contribution guide](./CONTRIBUTING.md).
|
||||||
|
|
||||||
<a href="https://github.com/tidalcycles/strudel/graphs/contributors">
|
<a href="https://codeberg.org/uzu/strudel/activity/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=tidalcycles/strudel" />
|
<img src="https://contrib.rocks/image?repo=tidalcycles/strudel" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { queryCode, testCycles } from '../test/runtime.mjs';
|
||||||
|
import * as tunes from '../website/src/repl/tunes.mjs';
|
||||||
|
import { describe, bench } from 'vitest';
|
||||||
|
import { calculateSteps } from '../packages/core/index.mjs';
|
||||||
|
|
||||||
|
const tuneKeys = Object.keys(tunes);
|
||||||
|
|
||||||
|
describe('renders tunes', () => {
|
||||||
|
tuneKeys.forEach((key) => {
|
||||||
|
describe(key, () => {
|
||||||
|
calculateSteps(true);
|
||||||
|
bench(`+steps`, async () => {
|
||||||
|
await queryCode(tunes[key], testCycles[key] || 1);
|
||||||
|
});
|
||||||
|
calculateSteps(false);
|
||||||
|
bench(`-steps`, async () => {
|
||||||
|
await queryCode(tunes[key], testCycles[key] || 1);
|
||||||
|
});
|
||||||
|
calculateSteps(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import _import from 'eslint-plugin-import';
|
||||||
|
import { fixupPluginRules } from '@eslint/compat';
|
||||||
|
import globals from 'globals';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/krill-parser.js',
|
||||||
|
'**/krill.pegjs',
|
||||||
|
'**/.eslintrc.json',
|
||||||
|
'**/server.js',
|
||||||
|
'**/tidal-sniffer.js',
|
||||||
|
'**/*.jsx',
|
||||||
|
'**/tunejs.js',
|
||||||
|
'out/**/*',
|
||||||
|
'**/postcss.config.js',
|
||||||
|
'**/postcss.config.cjs',
|
||||||
|
'**/tailwind.config.js',
|
||||||
|
'**/tailwind.config.cjs',
|
||||||
|
'**/vite.config.js',
|
||||||
|
'**/dist/**/*',
|
||||||
|
'!**/*.mjs',
|
||||||
|
'**/*.tsx',
|
||||||
|
'**/*.ts',
|
||||||
|
'**/*.json',
|
||||||
|
'**/dev-dist',
|
||||||
|
'**/dist',
|
||||||
|
'src-tauri/target/**/*',
|
||||||
|
'**/reverbGen.mjs',
|
||||||
|
'**/hydra.mjs',
|
||||||
|
'**/jsdoc-synonyms.js',
|
||||||
|
'packages/hs2js/src/hs2js.mjs',
|
||||||
|
'**/samples',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...compat.extends('eslint:recommended').map((config) => ({
|
||||||
|
...config,
|
||||||
|
files: ['**/*.mjs', '**/*.js'],
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
files: ['**/*.mjs', '**/*.js'],
|
||||||
|
|
||||||
|
plugins: {
|
||||||
|
import: fixupPluginRules(_import),
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
...globals.browser,
|
||||||
|
},
|
||||||
|
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
destructuredArrayIgnorePattern: '.',
|
||||||
|
ignoreRestSiblings: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
devDependencies: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -1,9 +1,31 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
<html>
|
||||||
<button id="play">play</button>
|
<head>
|
||||||
<button id="stop">stop</button>
|
<meta charset="UTF-8" />
|
||||||
<script>
|
<!-- <script src="../../packages/web/dist/index.js"></script> -->
|
||||||
strudel.initStrudel();
|
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||||
document.getElementById('play').addEventListener('click', () => evaluate('note("c a f e").jux(rev)'));
|
</head>
|
||||||
document.getElementById('play').addEventListener('stop', () => hush());
|
<body style="background: #222">
|
||||||
</script>
|
<button id="play">play</button>
|
||||||
|
<button id="stop">stop</button>
|
||||||
|
<script>
|
||||||
|
strudel.initStrudel();
|
||||||
|
document.getElementById('play').addEventListener('click', () =>
|
||||||
|
evaluate(`
|
||||||
|
//@title washover @by Switch Angel
|
||||||
|
//@social https://www.instagram.com/_switch_angel/
|
||||||
|
|
||||||
|
n("{0 1 3 5 2 }%16")
|
||||||
|
.add(n(tri.range(0, 6).slow(3)))
|
||||||
|
.scale("C4:pentatonic")
|
||||||
|
.sound("sawtooth").att(saw.range(0, 0.05).fast(6))
|
||||||
|
.release(3).pan(rand).decay(rand.range(0.1, 0.3))
|
||||||
|
.lpf(tri.range(200, 8000).slow(5)).lpq(0)
|
||||||
|
.gain(.4).vib(1).vibmod(.1)
|
||||||
|
.scope({pos:.5})
|
||||||
|
`),
|
||||||
|
);
|
||||||
|
document.getElementById('stop').addEventListener('click', () => strudel.hush());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
<html>
|
||||||
<button id="a">A</button>
|
<head>
|
||||||
<button id="b">B</button>
|
<meta charset="UTF-8" />
|
||||||
<button id="c">C</button>
|
<!-- <script src="../../packages/web/dist/index.js"></script> -->
|
||||||
<button id="stop">stop</button>
|
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||||
<script>
|
</head>
|
||||||
initStrudel({
|
<body style="background: #222">
|
||||||
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
<button id="a">A</button>
|
||||||
});
|
<button id="b">B</button>
|
||||||
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
<button id="c">C</button>
|
||||||
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
|
<button id="stop">stop</button>
|
||||||
click('b', () => s('bd*2,hh(3,4),jvbass(5,8,1)').jux(rev).play());
|
<script>
|
||||||
click('c', () => s('bd*2,hh(3,4),jvbass:[0 4](5,8,1)').jux(rev).stack(s('~ sd')).play());
|
initStrudel({
|
||||||
click('stop', () => hush());
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
</script>
|
});
|
||||||
|
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
||||||
|
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
|
||||||
|
click('b', () => s('bd*2,hh(3,4),jvbass(5,8,1)').jux(rev).play());
|
||||||
|
click('c', () => s('bd*2,hh(3,4),jvbass:[0 4](5,8,1)').jux(rev).stack(s('~ sd')).play());
|
||||||
|
click('stop', () => hush());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<script src="https://unpkg.com/hs2js@0.0.4"></script>
|
||||||
|
<button id="hello">hello</button>
|
||||||
|
<script>
|
||||||
|
hs2js.setBase('https://unpkg.com/hs2js@0.0.4/dist/');
|
||||||
|
hs2js.loadParser();
|
||||||
|
document.getElementById('hello').addEventListener('click', () => {
|
||||||
|
hs2js.evaluate('alert "hello from haskell!"');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>tidal.html</title>
|
||||||
|
</head>
|
||||||
|
<body style="margin: 0; padding: 0">
|
||||||
|
<textarea id="code" style="width: 100%; height: 200px"></textarea>
|
||||||
|
<pre id="result"></pre>
|
||||||
|
<script src="https://unpkg.com/hs2js@0.0.8"></script>
|
||||||
|
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||||
|
<script>
|
||||||
|
const { initStrudel } = strudel;
|
||||||
|
const { run, parse, setBase, loadParser } = hs2js;
|
||||||
|
setBase('https://unpkg.com/hs2js@0.0.4/dist/');
|
||||||
|
const ready = loadParser();
|
||||||
|
initStrudel({
|
||||||
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const textarea = document.getElementById('code');
|
||||||
|
if (window.location.hash) {
|
||||||
|
textarea.value = atob(window.location.hash.slice(1));
|
||||||
|
} else {
|
||||||
|
textarea.value = 'd1 $ s "jvbass(3,8)"';
|
||||||
|
}
|
||||||
|
textarea.addEventListener('input', (e) => {
|
||||||
|
window.location.hash = btoa(e.target.value);
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
update();
|
||||||
|
|
||||||
|
function getInfixOperators() {
|
||||||
|
let operators = {
|
||||||
|
'>': 'set',
|
||||||
|
'#': 'set',
|
||||||
|
'+': 'add',
|
||||||
|
'-': 'sub',
|
||||||
|
'*': 'mul',
|
||||||
|
'/': 'div',
|
||||||
|
};
|
||||||
|
let alignments = {
|
||||||
|
in: (s) => '|' + s,
|
||||||
|
out: (s) => s + '|',
|
||||||
|
mix: (s) => '|' + s + '|',
|
||||||
|
};
|
||||||
|
let ops = {};
|
||||||
|
Object.entries(operators).forEach(([o, name]) => {
|
||||||
|
// operator without alignment
|
||||||
|
ops[o] = (l, r) => reify(l)[name](reify(r));
|
||||||
|
Object.entries(alignments).forEach(([a, getSymbol]) => {
|
||||||
|
// get symbol with alignment
|
||||||
|
let symbol = getSymbol(o);
|
||||||
|
ops[symbol] = (l, r) => reify(l)[name][a](reify(r));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ops['~>'] = (l, r) => reify(l).late(reify(r));
|
||||||
|
ops['<~'] = (l, r) => reify(l).early(reify(r));
|
||||||
|
ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right?
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
const ops = getInfixOperators();
|
||||||
|
|
||||||
|
async function update() {
|
||||||
|
let result, tree;
|
||||||
|
await ready;
|
||||||
|
try {
|
||||||
|
tree = parse(textarea.value);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('parse error');
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
console.log('parsed tree');
|
||||||
|
console.log(tree.rootNode.toString());
|
||||||
|
try {
|
||||||
|
let patterns = {};
|
||||||
|
window.p = (name, pattern) => {
|
||||||
|
patterns[name] = pattern;
|
||||||
|
};
|
||||||
|
window.d1 = (pat) => window.p(1, pat);
|
||||||
|
window.d2 = (pat) => window.p(2, pat);
|
||||||
|
window.d3 = (pat) => window.p(3, pat);
|
||||||
|
window.rot = late;
|
||||||
|
result = run(tree.rootNode, window, ops);
|
||||||
|
if (Object.values(patterns).length) {
|
||||||
|
stack(...Object.values(patterns)).play();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('eval error');
|
||||||
|
console.error(err);
|
||||||
|
result = 'ERROR: ' + err.message;
|
||||||
|
}
|
||||||
|
document.getElementById('result').innerHTML = 'Result: ' + result;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { StrudelMirror } from '@strudel/codemirror';
|
import { StrudelMirror } from '@strudel/codemirror';
|
||||||
import { funk42 } from './tunes';
|
import { funk42 } from './tunes';
|
||||||
import { drawPianoroll, evalScope } from '@strudel/core';
|
import { evalScope } from '@strudel/core';
|
||||||
|
import { drawPianoroll } from '@strudel/draw';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import { initAudioOnFirstClick } from '@strudel/webaudio';
|
import { initAudioOnFirstClick } from '@strudel/webaudio';
|
||||||
import { transpiler } from '@strudel/transpiler';
|
import { transpiler } from '@strudel/transpiler';
|
||||||
@@ -26,6 +27,7 @@ const editor = new StrudelMirror({
|
|||||||
initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
|
initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
|
||||||
const loadModules = evalScope(
|
const loadModules = evalScope(
|
||||||
import('@strudel/core'),
|
import('@strudel/core'),
|
||||||
|
import('@strudel/draw'),
|
||||||
import('@strudel/mini'),
|
import('@strudel/mini'),
|
||||||
import('@strudel/tonal'),
|
import('@strudel/tonal'),
|
||||||
import('@strudel/webaudio'),
|
import('@strudel/webaudio'),
|
||||||
|
|||||||
@@ -9,11 +9,12 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^6.0.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel/codemirror": "workspace:*",
|
"@strudel/codemirror": "workspace:*",
|
||||||
"@strudel/core": "workspace:*",
|
"@strudel/core": "workspace:*",
|
||||||
|
"@strudel/draw": "workspace:*",
|
||||||
"@strudel/mini": "workspace:*",
|
"@strudel/mini": "workspace:*",
|
||||||
"@strudel/soundfonts": "workspace:*",
|
"@strudel/soundfonts": "workspace:*",
|
||||||
"@strudel/tonal": "workspace:*",
|
"@strudel/tonal": "workspace:*",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^6.0.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel/web": "workspace:*"
|
"@strudel/web": "workspace:*"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^6.0.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel/core": "workspace:*",
|
"@strudel/core": "workspace:*",
|
||||||
|
|||||||
@@ -12,6 +12,6 @@
|
|||||||
"superdough": "workspace:*"
|
"superdough": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^6.0.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
public/tree-sitter.wasm
|
||||||
|
public/tree-sitter-haskell.wasm
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# @strudel/tidal
|
||||||
|
|
||||||
|
This is an experiment in implementing tree-sitter for parsing haskell.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pnpm i
|
||||||
|
cd haskell
|
||||||
|
pnpm copy-wasm
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Tree sitter test</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #121213;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
padding: 10px;
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin: 0; padding: 0">
|
||||||
|
<textarea id="code" style="width: 100%; height: 200px"></textarea>
|
||||||
|
<pre id="result"></pre>
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="/main.js
|
||||||
|
"
|
||||||
|
></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { run, parse, loadParser } from 'hs2js';
|
||||||
|
import { initStrudel, reify, late, samples, stack } from '@strudel/web';
|
||||||
|
|
||||||
|
initStrudel({
|
||||||
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const ready = loadParser();
|
||||||
|
|
||||||
|
const textarea = document.getElementById('code');
|
||||||
|
if (window.location.hash) {
|
||||||
|
textarea.value = atob(window.location.hash.slice(1));
|
||||||
|
} else {
|
||||||
|
textarea.value = 'd1 $ s "jvbass(3,8)"';
|
||||||
|
}
|
||||||
|
textarea.addEventListener('input', (e) => {
|
||||||
|
window.location.hash = btoa(e.target.value);
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
update();
|
||||||
|
|
||||||
|
function getInfixOperators() {
|
||||||
|
let operators = {
|
||||||
|
'>': 'set',
|
||||||
|
'#': 'set',
|
||||||
|
'+': 'add',
|
||||||
|
'-': 'sub',
|
||||||
|
'*': 'mul',
|
||||||
|
'/': 'div',
|
||||||
|
};
|
||||||
|
let alignments = {
|
||||||
|
in: (s) => '|' + s,
|
||||||
|
out: (s) => s + '|',
|
||||||
|
mix: (s) => '|' + s + '|',
|
||||||
|
};
|
||||||
|
let ops = {};
|
||||||
|
Object.entries(operators).forEach(([o, name]) => {
|
||||||
|
// operator without alignment
|
||||||
|
ops[o] = (l, r) => reify(l)[name](reify(r));
|
||||||
|
Object.entries(alignments).forEach(([a, getSymbol]) => {
|
||||||
|
// get symbol with alignment
|
||||||
|
let symbol = getSymbol(o);
|
||||||
|
ops[symbol] = (l, r) => reify(l)[name][a](reify(r));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ops['~>'] = (l, r) => reify(l).late(reify(r));
|
||||||
|
ops['<~'] = (l, r) => reify(l).early(reify(r));
|
||||||
|
ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right?
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
const ops = getInfixOperators();
|
||||||
|
|
||||||
|
async function update() {
|
||||||
|
let result, tree;
|
||||||
|
await ready;
|
||||||
|
try {
|
||||||
|
tree = parse(textarea.value);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('parse error');
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
console.log('parsed tree');
|
||||||
|
console.log(tree.rootNode.toString());
|
||||||
|
try {
|
||||||
|
let patterns = {};
|
||||||
|
window.p = (name, pattern) => {
|
||||||
|
patterns[name] = pattern;
|
||||||
|
};
|
||||||
|
window.d1 = (pat) => window.p(1, pat);
|
||||||
|
window.d2 = (pat) => window.p(2, pat);
|
||||||
|
window.d3 = (pat) => window.p(3, pat);
|
||||||
|
window.rot = late;
|
||||||
|
result = run(tree.rootNode, window, ops);
|
||||||
|
if (Object.values(patterns).length) {
|
||||||
|
stack(...Object.values(patterns)).play();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('eval error');
|
||||||
|
console.error(err);
|
||||||
|
result = 'ERROR: ' + err.message;
|
||||||
|
}
|
||||||
|
document.getElementById('result').innerHTML = 'Result: ' + result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "tidal-repl",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "pnpm copy-wasm && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"copy-wasm": "cp node_modules/hs2js/dist/tree-sitter.wasm public && cp node_modules/hs2js/dist/tree-sitter-haskell.wasm public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://codeberg.org/uzu/strudel.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"titdalcycles",
|
||||||
|
"strudel",
|
||||||
|
"pattern",
|
||||||
|
"livecoding",
|
||||||
|
"algorave"
|
||||||
|
],
|
||||||
|
"author": "Felix Roos <flix91@gmail.com>",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://codeberg.org/uzu/strudel/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://codeberg.org/uzu/strudel#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"@strudel/web": "workspace:*",
|
||||||
|
"hs2js": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite": "^6.0.11"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# public
|
||||||
|
|
||||||
|
this file is just here to make sure the public folder exists
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
jsdoc-synonyms.js - Add support for @synonym tag
|
jsdoc-synonyms.js - Add support for @synonym tag
|
||||||
Copyright (C) 2023 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/midi/midi.mjs>
|
Copyright (C) 2023 Strudel contributors - see <https://codeberg.org/uzu/strudel/activity/contributors>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+9
-13
@@ -5,22 +5,24 @@ made into a pattern swatch.
|
|||||||
|
|
||||||
Example: <https://felixroos.github.io/strudel/swatch/>
|
Example: <https://felixroos.github.io/strudel/swatch/>
|
||||||
|
|
||||||
|
Please note: These instructions have not been fully tested/adapted since strudel moved to codeberg from github. PRs welcome!
|
||||||
|
|
||||||
## deploy
|
## deploy
|
||||||
|
|
||||||
### 1. fork the [strudel repo on github](https://github.com/tidalcycles/strudel.git)
|
### 1. fork the [strudel repo on codeberg](https://codeberg.org/uzu/strudel.git)
|
||||||
|
|
||||||
### 2. clone your fork to your machine `git clone https://github.com/<your-username>/strudel.git strudel && cd strudel`
|
### 2. clone your fork to your machine `git clone https://codeberg.org/<your-username>/strudel.git strudel && cd strudel`
|
||||||
|
|
||||||
### 3. create a separate branch like `git branch patternuary && git checkout patternuary`
|
### 3. create a separate branch like `git branch patternuary && git checkout patternuary`
|
||||||
|
|
||||||
### 4. save one or more .txt files in the my-patterns folder
|
### 4. save one or more .txt files in the my-patterns folder
|
||||||
|
|
||||||
### 5. edit `website/public/CNAME` to contain `<your-username>.github.io/strudel`
|
### 5. edit `website/public/CNAME` to contain `<your-username>.codeberg.page/strudel`
|
||||||
|
|
||||||
### 6. edit `website/astro.config.mjs` to use site: `https://<your-username>.github.io` and base `/strudel`, like this
|
### 6. edit `website/astro.config.mjs` to use site: `https://<your-username>.codeberg.page` and base `/strudel`, like this
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const site = 'https://<your-username>.github.io';
|
const site = 'https://<your-username>.codeberg.page';
|
||||||
const base = '/strudel';
|
const base = '/strudel';
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -30,15 +32,9 @@ const base = '/strudel';
|
|||||||
git add . && git commit -m "site config" && git push --set-upstream origin
|
git add . && git commit -m "site config" && git push --set-upstream origin
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. deploy to github pages
|
### 8. deploy to codeberg pages
|
||||||
|
|
||||||
- go to settings -> pages and select "Github Actions" as source
|
### 9. view your patterns at `<your-username>.codeberg.page/strudel/swatch/`
|
||||||
- go to settings -> environments -> github-pages and press the edit button next to `main` and type in `patternuary` (under "Deployment branches")
|
|
||||||
- go to Actions -> `Build and Deploy` and click `Run workflow` with branch `patternuary`
|
|
||||||
|
|
||||||
### 9. view your patterns at `<your-username>.github.io/strudel/swatch/`
|
|
||||||
|
|
||||||
Alternatively, github pages allows you to use a custom domain, like https://mycooldomain.org/swatch/. [See their documentation for details](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site).
|
|
||||||
|
|
||||||
### 10. optional: automatic deployment
|
### 10. optional: automatic deployment
|
||||||
|
|
||||||
|
|||||||
+21
-16
@@ -11,6 +11,7 @@
|
|||||||
"test": "npm run pretest && vitest run --version",
|
"test": "npm run pretest && vitest run --version",
|
||||||
"test-ui": "npm run pretest && vitest --ui",
|
"test-ui": "npm run pretest && vitest --ui",
|
||||||
"test-coverage": "npm run pretest && vitest --coverage",
|
"test-coverage": "npm run pretest && vitest --coverage",
|
||||||
|
"bench": "npm run pretest && vitest bench",
|
||||||
"snapshot": "npm run pretest && vitest run -u --silent",
|
"snapshot": "npm run pretest && vitest run -u --silent",
|
||||||
"repl": "npm run prestart && cd website && npm run dev",
|
"repl": "npm run prestart && cd website && npm run dev",
|
||||||
"start": "npm run prestart && cd website && npm run dev",
|
"start": "npm run prestart && cd website && npm run dev",
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
"osc": "cd packages/osc && npm run server",
|
"osc": "cd packages/osc && npm run server",
|
||||||
"jsdoc": "jsdoc packages/ -c jsdoc/jsdoc.config.json",
|
"jsdoc": "jsdoc packages/ -c jsdoc/jsdoc.config.json",
|
||||||
"jsdoc-json": "jsdoc packages/ --template ./node_modules/jsdoc-json --destination doc.json -c jsdoc/jsdoc.config.json",
|
"jsdoc-json": "jsdoc packages/ --template ./node_modules/jsdoc-json --destination doc.json -c jsdoc/jsdoc.config.json",
|
||||||
"lint": "eslint . --ext mjs,js --quiet",
|
"lint": "eslint . --quiet",
|
||||||
"codeformat": "prettier --write .",
|
"codeformat": "prettier --write .",
|
||||||
"format-check": "prettier --check .",
|
"format-check": "prettier --check .",
|
||||||
"report-undocumented": "npm run jsdoc-json && node jsdoc/undocumented.mjs > undocumented.json",
|
"report-undocumented": "npm run jsdoc-json && node jsdoc/undocumented.mjs > undocumented.json",
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/tidalcycles/strudel.git"
|
"url": "git+https://codeberg.org/uzu/strudel.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"tidalcycles",
|
"tidalcycles",
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
"author": "Alex McLean <alex@slab.org> (https://slab.org)",
|
"author": "Alex McLean <alex@slab.org> (https://slab.org)",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/tidalcycles/strudel/issues"
|
"url": "https://codeberg.org/uzu/strudel/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://strudel.cc",
|
"homepage": "https://strudel.cc",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -54,19 +55,23 @@
|
|||||||
"@strudel/xen": "workspace:*"
|
"@strudel/xen": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^1.5.9",
|
"@eslint/compat": "^1.2.5",
|
||||||
"@vitest/ui": "^1.1.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
"acorn": "^8.11.3",
|
"@eslint/js": "^9.19.0",
|
||||||
"dependency-tree": "^10.0.9",
|
"@tauri-apps/cli": "^2.2.7",
|
||||||
"eslint": "^8.56.0",
|
"@vitest/coverage-v8": "3.0.4",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"@vitest/ui": "^3.0.4",
|
||||||
|
"acorn": "^8.14.0",
|
||||||
|
"dependency-tree": "^11.0.1",
|
||||||
|
"eslint": "^9.19.0",
|
||||||
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"jsdoc": "^4.0.2",
|
"globals": "^15.14.0",
|
||||||
|
"jsdoc": "^4.0.4",
|
||||||
"jsdoc-json": "^2.0.2",
|
"jsdoc-json": "^2.0.2",
|
||||||
"jsdoc-to-markdown": "^8.0.0",
|
"lerna": "^8.1.9",
|
||||||
"lerna": "^8.0.1",
|
"prettier": "^3.4.2",
|
||||||
"prettier": "^3.1.1",
|
"vitest": "^3.0.4",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"vite-plugin-bundle-audioworklet": "workspace:*"
|
||||||
"vitest": "^1.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
Each folder represents one of the @strudel/* packages [published to npm](https://www.npmjs.com/org/strudel).
|
Each folder represents one of the @strudel/* packages [published to npm](https://www.npmjs.com/org/strudel).
|
||||||
|
|
||||||
To understand how those pieces connect, refer to the [Technical Manual](https://github.com/tidalcycles/strudel/wiki/Technical-Manual) or the individual READMEs.
|
To understand how those pieces connect, refer to the [Technical Manual](https://codeberg.org/uzu/strudel/wiki/Technical-Manual) or the individual READMEs.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { closeBrackets } from '@codemirror/autocomplete';
|
import { closeBrackets } from '@codemirror/autocomplete';
|
||||||
|
export { toggleComment, toggleBlockComment, toggleLineComment, toggleBlockCommentByLine } from '@codemirror/commands';
|
||||||
// import { search, highlightSelectionMatches } from '@codemirror/search';
|
// import { search, highlightSelectionMatches } from '@codemirror/search';
|
||||||
import { history } from '@codemirror/commands';
|
import { history } from '@codemirror/commands';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
@@ -12,7 +13,7 @@ import {
|
|||||||
lineNumbers,
|
lineNumbers,
|
||||||
drawSelection,
|
drawSelection,
|
||||||
} from '@codemirror/view';
|
} from '@codemirror/view';
|
||||||
import { Pattern, repl } from '@strudel/core';
|
import { repl, registerControl } from '@strudel/core';
|
||||||
import { Drawer, cleanupDraw } from '@strudel/draw';
|
import { Drawer, cleanupDraw } from '@strudel/draw';
|
||||||
import { isAutoCompletionEnabled } from './autocomplete.mjs';
|
import { isAutoCompletionEnabled } from './autocomplete.mjs';
|
||||||
import { isTooltipEnabled } from './tooltip.mjs';
|
import { isTooltipEnabled } from './tooltip.mjs';
|
||||||
@@ -66,6 +67,7 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo
|
|||||||
const initialSettings = Object.keys(compartments).map((key) =>
|
const initialSettings = Object.keys(compartments).map((key) =>
|
||||||
compartments[key].of(extensions[key](parseBooleans(settings[key]))),
|
compartments[key].of(extensions[key](parseBooleans(settings[key]))),
|
||||||
);
|
);
|
||||||
|
|
||||||
initTheme(settings.theme);
|
initTheme(settings.theme);
|
||||||
let state = EditorState.create({
|
let state = EditorState.create({
|
||||||
doc: initialCode,
|
doc: initialCode,
|
||||||
@@ -98,10 +100,8 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Alt-.',
|
key: 'Alt-.',
|
||||||
run: (_, e) => {
|
preventDefault: true,
|
||||||
e.preventDefault();
|
run: () => onStop?.(),
|
||||||
onStop?.();
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
/* {
|
/* {
|
||||||
key: 'Ctrl-Shift-.',
|
key: 'Ctrl-Shift-.',
|
||||||
@@ -134,57 +134,50 @@ export class StrudelMirror {
|
|||||||
autodraw,
|
autodraw,
|
||||||
prebake,
|
prebake,
|
||||||
bgFill = true,
|
bgFill = true,
|
||||||
|
solo = true,
|
||||||
...replOptions
|
...replOptions
|
||||||
} = options;
|
} = options;
|
||||||
this.code = initialCode;
|
this.code = initialCode;
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.miniLocations = [];
|
this.miniLocations = [];
|
||||||
this.widgets = [];
|
this.widgets = [];
|
||||||
this.painters = [];
|
|
||||||
this.drawTime = drawTime;
|
this.drawTime = drawTime;
|
||||||
this.drawContext = drawContext;
|
this.drawContext = drawContext;
|
||||||
this.onDraw = onDraw || this.draw;
|
this.onDraw = onDraw || this.draw;
|
||||||
this.id = id || s4();
|
this.id = id || s4();
|
||||||
|
this.solo = solo;
|
||||||
|
|
||||||
this.drawer = new Drawer((haps, time) => {
|
this.drawer = new Drawer((haps, time, _, painters) => {
|
||||||
const currentFrame = haps.filter((hap) => hap.isActive(time));
|
const currentFrame = haps.filter((hap) => hap.isActive(time));
|
||||||
this.highlight(currentFrame, time);
|
this.highlight(currentFrame, time);
|
||||||
this.onDraw(haps, time, this.painters);
|
this.onDraw(haps, time, painters);
|
||||||
}, drawTime);
|
}, drawTime);
|
||||||
|
|
||||||
this.prebaked = prebake();
|
this.prebaked = prebake();
|
||||||
autodraw && this.drawFirstFrame();
|
autodraw && this.drawFirstFrame();
|
||||||
|
|
||||||
this.repl = repl({
|
this.repl = repl({
|
||||||
...replOptions,
|
...replOptions,
|
||||||
|
id,
|
||||||
onToggle: (started) => {
|
onToggle: (started) => {
|
||||||
replOptions?.onToggle?.(started);
|
replOptions?.onToggle?.(started);
|
||||||
if (started) {
|
if (started) {
|
||||||
this.adjustDrawTime();
|
|
||||||
this.drawer.start(this.repl.scheduler);
|
this.drawer.start(this.repl.scheduler);
|
||||||
// stop other repls when this one is started
|
if (this.solo) {
|
||||||
document.dispatchEvent(
|
// stop other repls when this one is started
|
||||||
new CustomEvent('start-repl', {
|
document.dispatchEvent(
|
||||||
detail: this.id,
|
new CustomEvent('start-repl', {
|
||||||
}),
|
detail: this.id,
|
||||||
);
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.drawer.stop();
|
this.drawer.stop();
|
||||||
updateMiniLocations(this.editor, []);
|
updateMiniLocations(this.editor, []);
|
||||||
cleanupDraw(false);
|
cleanupDraw(true, id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeEval: async () => {
|
beforeEval: async () => {
|
||||||
cleanupDraw();
|
cleanupDraw(true, id);
|
||||||
this.painters = [];
|
|
||||||
const self = this;
|
|
||||||
// this is similar to repl.mjs > injectPatternMethods
|
|
||||||
// maybe there is a solution without prototype hacking, but hey, it works
|
|
||||||
// we need to do this befor every eval to make sure it works with multiple StrudelMirror's side by side
|
|
||||||
Pattern.prototype.onPaint = function (onPaint) {
|
|
||||||
self.painters.push(onPaint);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
await this.prebaked;
|
await this.prebaked;
|
||||||
await replOptions?.beforeEval?.();
|
await replOptions?.beforeEval?.();
|
||||||
},
|
},
|
||||||
@@ -198,8 +191,11 @@ export class StrudelMirror {
|
|||||||
updateWidgets(this.editor, widgets);
|
updateWidgets(this.editor, widgets);
|
||||||
updateMiniLocations(this.editor, this.miniLocations);
|
updateMiniLocations(this.editor, this.miniLocations);
|
||||||
replOptions?.afterEval?.(options);
|
replOptions?.afterEval?.(options);
|
||||||
this.adjustDrawTime();
|
// if no painters are set (.onPaint was not called), then we only need the present moment (for highlighting)
|
||||||
this.drawer.invalidate();
|
const drawTime = options.pattern.getPainters().length ? this.drawTime : [0, 0];
|
||||||
|
this.drawer.setDrawTime(drawTime);
|
||||||
|
// invalidate drawer after we've set the appropriate drawTime
|
||||||
|
this.drawer.invalidate(this.repl.scheduler);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.editor = initEditor({
|
this.editor = initEditor({
|
||||||
@@ -228,19 +224,14 @@ export class StrudelMirror {
|
|||||||
|
|
||||||
// stop this repl when another repl is started
|
// stop this repl when another repl is started
|
||||||
this.onStartRepl = (e) => {
|
this.onStartRepl = (e) => {
|
||||||
if (e.detail !== this.id) {
|
if (this.solo && e.detail !== this.id) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
document.addEventListener('start-repl', this.onStartRepl);
|
document.addEventListener('start-repl', this.onStartRepl);
|
||||||
}
|
}
|
||||||
// adjusts draw time depending on if there are painters
|
draw(haps, time, painters) {
|
||||||
adjustDrawTime() {
|
painters?.forEach((painter) => painter(this.drawContext, time, haps, this.drawTime));
|
||||||
// when no painters are set, [0,0] is enough (just highlighting)
|
|
||||||
this.drawer.setDrawTime(this.painters.length ? this.drawTime : [0, 0]);
|
|
||||||
}
|
|
||||||
draw(haps, time) {
|
|
||||||
this.painters?.forEach((painter) => painter(this.drawContext, time, haps, this.drawTime));
|
|
||||||
}
|
}
|
||||||
async drawFirstFrame() {
|
async drawFirstFrame() {
|
||||||
if (!this.onDraw) {
|
if (!this.onDraw) {
|
||||||
@@ -252,7 +243,7 @@ export class StrudelMirror {
|
|||||||
await this.repl.evaluate(this.code, false);
|
await this.repl.evaluate(this.code, false);
|
||||||
this.drawer.invalidate(this.repl.scheduler, -0.001);
|
this.drawer.invalidate(this.repl.scheduler, -0.001);
|
||||||
// draw at -0.001 to avoid haps at 0 to be visualized as active
|
// draw at -0.001 to avoid haps at 0 to be visualized as active
|
||||||
this.onDraw?.(this.drawer.visibleHaps, -0.001, this.painters);
|
this.onDraw?.(this.drawer.visibleHaps, -0.001, this.drawer.painters);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('first frame could not be painted');
|
console.warn('first frame could not be painted');
|
||||||
}
|
}
|
||||||
@@ -345,6 +336,17 @@ export class StrudelMirror {
|
|||||||
clear() {
|
clear() {
|
||||||
this.onStartRepl && document.removeEventListener('start-repl', this.onStartRepl);
|
this.onStartRepl && document.removeEventListener('start-repl', this.onStartRepl);
|
||||||
}
|
}
|
||||||
|
getCursorLocation() {
|
||||||
|
return this.editor.state.selection.main.head;
|
||||||
|
}
|
||||||
|
setCursorLocation(col) {
|
||||||
|
return this.editor.dispatch({ selection: { anchor: col } });
|
||||||
|
}
|
||||||
|
appendCode(code) {
|
||||||
|
const cursor = this.getCursorLocation();
|
||||||
|
this.setCode(this.code + code);
|
||||||
|
this.setCursorLocation(cursor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBooleans(value) {
|
function parseBooleans(value) {
|
||||||
@@ -357,3 +359,12 @@ function s4() {
|
|||||||
.toString(16)
|
.toString(16)
|
||||||
.substring(1);
|
.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the css of highlighted events. Make sure to use single quotes!
|
||||||
|
* @name markcss
|
||||||
|
* @example
|
||||||
|
* note("c a f e")
|
||||||
|
* .markcss('text-decoration:underline')
|
||||||
|
*/
|
||||||
|
export const markcss = registerControl('markcss');
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ export const flashField = StateField.define({
|
|||||||
for (let e of tr.effects) {
|
for (let e of tr.effects) {
|
||||||
if (e.is(setFlash)) {
|
if (e.is(setFlash)) {
|
||||||
if (e.value && tr.newDoc.length > 0) {
|
if (e.value && tr.newDoc.length > 0) {
|
||||||
const mark = Decoration.mark({ attributes: { style: `background-color: #FFCA2880` } });
|
const mark = Decoration.mark({
|
||||||
|
attributes: { style: `background-color: rgba(255,255,255, .4); filter: invert(10%)` },
|
||||||
|
});
|
||||||
flash = Decoration.set([mark.range(0, tr.newDoc.length)]);
|
flash = Decoration.set([mark.range(0, tr.newDoc.length)]);
|
||||||
} else {
|
} else {
|
||||||
flash = Decoration.set([]);
|
flash = Decoration.set([]);
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ const miniLocationHighlights = EditorView.decorations.compute([miniLocations, vi
|
|||||||
if (haps.has(id)) {
|
if (haps.has(id)) {
|
||||||
const hap = haps.get(id);
|
const hap = haps.get(id);
|
||||||
const color = hap.value?.color ?? 'var(--foreground)';
|
const color = hap.value?.color ?? 'var(--foreground)';
|
||||||
|
const style = hap.value?.markcss || `outline: solid 2px ${color}`;
|
||||||
// Get explicit channels for color values
|
// Get explicit channels for color values
|
||||||
/*
|
/*
|
||||||
const swatch = document.createElement('div');
|
const swatch = document.createElement('div');
|
||||||
@@ -114,7 +115,7 @@ const miniLocationHighlights = EditorView.decorations.compute([miniLocations, vi
|
|||||||
to,
|
to,
|
||||||
Decoration.mark({
|
Decoration.mark({
|
||||||
// attributes: { style: `outline: solid 2px rgba(${channels.join(', ')})` },
|
// attributes: { style: `outline: solid 2px rgba(${channels.join(', ')})` },
|
||||||
attributes: { style: `outline: solid 2px ${color}` },
|
attributes: { style },
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/codemirror",
|
"name": "@strudel/codemirror",
|
||||||
"version": "1.0.1",
|
"version": "1.2.2",
|
||||||
"description": "Codemirror Extensions for Strudel",
|
"description": "Codemirror Extensions for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/tidalcycles/strudel.git"
|
"url": "git+https://codeberg.org/uzu/strudel.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"tidalcycles",
|
"tidalcycles",
|
||||||
@@ -28,30 +28,28 @@
|
|||||||
],
|
],
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/tidalcycles/strudel/issues"
|
"url": "https://codeberg.org/uzu/strudel/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://codeberg.org/uzu/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.11.1",
|
"@codemirror/autocomplete": "^6.18.4",
|
||||||
"@codemirror/commands": "^6.3.3",
|
"@codemirror/commands": "^6.8.0",
|
||||||
"@codemirror/lang-javascript": "^6.2.1",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@codemirror/language": "^6.10.0",
|
"@codemirror/language": "^6.10.8",
|
||||||
"@codemirror/search": "^6.5.5",
|
"@codemirror/search": "^6.5.8",
|
||||||
"@codemirror/state": "^6.4.0",
|
"@codemirror/state": "^6.5.1",
|
||||||
"@codemirror/view": "^6.23.0",
|
"@codemirror/view": "^6.36.2",
|
||||||
"@lezer/highlight": "^1.2.0",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@nanostores/persistent": "^0.9.1",
|
"@nanostores/persistent": "^0.10.2",
|
||||||
"@replit/codemirror-emacs": "^6.0.1",
|
"@replit/codemirror-emacs": "^6.1.0",
|
||||||
"@replit/codemirror-vim": "^6.1.0",
|
"@replit/codemirror-vim": "^6.2.1",
|
||||||
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
||||||
"@strudel/core": "workspace:*",
|
"@strudel/core": "workspace:*",
|
||||||
"@strudel/draw": "workspace:*",
|
"@strudel/draw": "workspace:*",
|
||||||
"@strudel/transpiler": "workspace:*",
|
"@strudel/transpiler": "workspace:*",
|
||||||
"@uiw/codemirror-themes": "^4.21.21",
|
"nanostores": "^0.11.3"
|
||||||
"@uiw/codemirror-themes-all": "^4.21.21",
|
|
||||||
"nanostores": "^0.9.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^6.0.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+84
-407
@@ -1,440 +1,117 @@
|
|||||||
import {
|
import strudelTheme, { settings as strudelThemeSettings } from './themes/strudel-theme.mjs';
|
||||||
abcdef,
|
import bluescreen, { settings as bluescreenSettings } from './themes/bluescreen.mjs';
|
||||||
androidstudio,
|
import blackscreen, { settings as blackscreenSettings } from './themes/blackscreen.mjs';
|
||||||
atomone,
|
import whitescreen, { settings as whitescreenSettings } from './themes/whitescreen.mjs';
|
||||||
aura,
|
import teletext, { settings as teletextSettings } from './themes/teletext.mjs';
|
||||||
bespin,
|
import algoboy, { settings as algoboySettings } from './themes/algoboy.mjs';
|
||||||
darcula,
|
import CutiePi, { settings as CutiePiSettings } from './themes/CutiePi.mjs';
|
||||||
dracula,
|
import sonicPink, { settings as sonicPinkSettings } from './themes/sonic-pink.mjs';
|
||||||
duotoneDark,
|
import redText, { settings as redTextSettings } from './themes/red-text.mjs';
|
||||||
eclipse,
|
import greenText, { settings as greenTextSettings } from './themes/green-text.mjs';
|
||||||
githubDark,
|
import androidstudio, { settings as androidstudioSettings } from './themes/androidstudio.mjs';
|
||||||
gruvboxDark,
|
import atomone, { settings as atomOneSettings } from './themes/atomone.mjs';
|
||||||
materialDark,
|
import aura, { settings as auraSettings } from './themes/aura.mjs';
|
||||||
nord,
|
import darcula, { settings as darculaSettings } from './themes/darcula.mjs';
|
||||||
okaidia,
|
import dracula, { settings as draculaSettings } from './themes/dracula.mjs';
|
||||||
solarizedDark,
|
import duotoneDark, { settings as duotoneDarkSettings } from './themes/duotoneDark.mjs';
|
||||||
sublime,
|
import eclipse, { settings as eclipseSettings } from './themes/eclipse.mjs';
|
||||||
tokyoNight,
|
import githubDark, { settings as githubDarkSettings } from './themes/githubDark.mjs';
|
||||||
tokyoNightStorm,
|
import githubLight, { settings as githubLightSettings } from './themes/githubLight.mjs';
|
||||||
vscodeDark,
|
import gruvboxDark, { settings as gruvboxDarkSettings } from './themes/gruvboxDark.mjs';
|
||||||
xcodeDark,
|
import gruvboxLight, { settings as gruvboxLightSettings } from './themes/gruvboxLight.mjs';
|
||||||
bbedit,
|
import materialDark, { settings as materialDarkSettings } from './themes/materialDark.mjs';
|
||||||
duotoneLight,
|
import materialLight, { settings as materialLightSettings } from './themes/materialLight.mjs';
|
||||||
githubLight,
|
import nord, { settings as nordSettings } from './themes/nord.mjs';
|
||||||
gruvboxLight,
|
import monokai, { settings as monokaiSettings } from './themes/monokai.mjs';
|
||||||
materialLight,
|
import solarizedDark, { settings as solarizedDarkSettings } from './themes/solarizedDark.mjs';
|
||||||
noctisLilac,
|
import solarizedLight, { settings as solarizedLightSettings } from './themes/solarizedLight.mjs';
|
||||||
solarizedLight,
|
import sublime, { settings as sublimeSettings } from './themes/sublime.mjs';
|
||||||
tokyoNightDay,
|
import tokyoNight, { settings as tokyoNightSettings } from './themes/tokyoNight.mjs';
|
||||||
xcodeLight,
|
import tokyoNightStorm, { settings as tokyoNightStormSettings } from './themes/tokioNightStorm.mjs';
|
||||||
} from '@uiw/codemirror-themes-all';
|
import tokyoNightDay, { settings as tokyoNightDaySettings } from './themes/tokyoNightDay.mjs';
|
||||||
|
import vscodeDark, { settings as vscodeDarkSettings } from './themes/vscodeDark.mjs';
|
||||||
|
import vscodeLight, { settings as vscodeLightSettings } from './themes/vscodeLight.mjs';
|
||||||
|
import xcodeLight, { settings as xcodeLightSettings } from './themes/xcodeLight.mjs';
|
||||||
|
import bbedit, { settings as bbeditSettings } from './themes/bbedit.mjs';
|
||||||
|
import noctisLilac, { settings as noctisLilacSettings } from './themes/noctisLilac.mjs';
|
||||||
|
|
||||||
import strudelTheme from './themes/strudel-theme';
|
|
||||||
import bluescreen, { settings as bluescreenSettings } from './themes/bluescreen';
|
|
||||||
import blackscreen, { settings as blackscreenSettings } from './themes/blackscreen';
|
|
||||||
import whitescreen, { settings as whitescreenSettings } from './themes/whitescreen';
|
|
||||||
import teletext, { settings as teletextSettings } from './themes/teletext';
|
|
||||||
import algoboy, { settings as algoboySettings } from './themes/algoboy';
|
|
||||||
import terminal, { settings as terminalSettings } from './themes/terminal';
|
|
||||||
import { setTheme } from '@strudel/draw';
|
import { setTheme } from '@strudel/draw';
|
||||||
|
|
||||||
export const themes = {
|
export const themes = {
|
||||||
strudelTheme,
|
strudelTheme,
|
||||||
bluescreen,
|
|
||||||
blackscreen,
|
|
||||||
whitescreen,
|
|
||||||
teletext,
|
|
||||||
algoboy,
|
algoboy,
|
||||||
terminal,
|
|
||||||
abcdef,
|
|
||||||
androidstudio,
|
androidstudio,
|
||||||
atomone,
|
atomone,
|
||||||
aura,
|
aura,
|
||||||
bespin,
|
bbedit,
|
||||||
|
blackscreen,
|
||||||
|
bluescreen,
|
||||||
|
CutiePi,
|
||||||
darcula,
|
darcula,
|
||||||
dracula,
|
dracula,
|
||||||
duotoneDark,
|
duotoneDark,
|
||||||
eclipse,
|
eclipse,
|
||||||
githubDark,
|
githubDark,
|
||||||
|
githubLight,
|
||||||
|
greenText,
|
||||||
gruvboxDark,
|
gruvboxDark,
|
||||||
|
gruvboxLight,
|
||||||
|
sonicPink,
|
||||||
materialDark,
|
materialDark,
|
||||||
|
materialLight,
|
||||||
|
monokai,
|
||||||
|
noctisLilac,
|
||||||
nord,
|
nord,
|
||||||
okaidia,
|
redText,
|
||||||
solarizedDark,
|
solarizedDark,
|
||||||
|
solarizedLight,
|
||||||
sublime,
|
sublime,
|
||||||
|
teletext,
|
||||||
tokyoNight,
|
tokyoNight,
|
||||||
|
tokyoNightDay,
|
||||||
tokyoNightStorm,
|
tokyoNightStorm,
|
||||||
vscodeDark,
|
vscodeDark,
|
||||||
xcodeDark,
|
vscodeLight,
|
||||||
bbedit,
|
whitescreen,
|
||||||
duotoneLight,
|
|
||||||
githubLight,
|
|
||||||
gruvboxLight,
|
|
||||||
materialLight,
|
|
||||||
noctisLilac,
|
|
||||||
solarizedLight,
|
|
||||||
tokyoNightDay,
|
|
||||||
xcodeLight,
|
xcodeLight,
|
||||||
};
|
};
|
||||||
|
|
||||||
// lineBackground is background with 50% opacity, to make sure the selection below is visible
|
|
||||||
|
|
||||||
export const settings = {
|
export const settings = {
|
||||||
strudelTheme: {
|
strudelTheme: strudelThemeSettings,
|
||||||
background: '#222',
|
|
||||||
lineBackground: '#22222299',
|
|
||||||
foreground: '#fff',
|
|
||||||
// foreground: '#75baff',
|
|
||||||
caret: '#ffcc00',
|
|
||||||
selection: 'rgba(128, 203, 196, 0.5)',
|
|
||||||
selectionMatch: '#036dd626',
|
|
||||||
// lineHighlight: '#8a91991a', // original
|
|
||||||
lineHighlight: '#00000050',
|
|
||||||
gutterBackground: 'transparent',
|
|
||||||
// gutterForeground: '#8a919966',
|
|
||||||
gutterForeground: '#8a919966',
|
|
||||||
},
|
|
||||||
bluescreen: bluescreenSettings,
|
bluescreen: bluescreenSettings,
|
||||||
blackscreen: blackscreenSettings,
|
blackscreen: blackscreenSettings,
|
||||||
whitescreen: whitescreenSettings,
|
whitescreen: whitescreenSettings,
|
||||||
teletext: teletextSettings,
|
teletext: teletextSettings,
|
||||||
algoboy: algoboySettings,
|
algoboy: algoboySettings,
|
||||||
terminal: terminalSettings,
|
androidstudio: androidstudioSettings,
|
||||||
abcdef: {
|
atomone: atomOneSettings,
|
||||||
background: '#0f0f0f',
|
aura: auraSettings,
|
||||||
lineBackground: '#0f0f0f99',
|
bbedit: bbeditSettings,
|
||||||
foreground: '#defdef',
|
darcula: darculaSettings,
|
||||||
caret: '#00FF00',
|
dracula: draculaSettings,
|
||||||
selection: '#515151',
|
duotoneDark: duotoneDarkSettings,
|
||||||
selectionMatch: '#515151',
|
eclipse: eclipseSettings,
|
||||||
gutterBackground: '#555',
|
CutiePi: CutiePiSettings,
|
||||||
gutterForeground: '#FFFFFF',
|
sonicPink: sonicPinkSettings,
|
||||||
lineHighlight: '#314151',
|
githubLight: githubLightSettings,
|
||||||
},
|
githubDark: githubDarkSettings,
|
||||||
androidstudio: {
|
greenText: greenTextSettings,
|
||||||
background: '#282b2e',
|
gruvboxDark: gruvboxDarkSettings,
|
||||||
lineBackground: '#282b2e99',
|
gruvboxLight: gruvboxLightSettings,
|
||||||
foreground: '#a9b7c6',
|
materialDark: materialDarkSettings,
|
||||||
caret: '#00FF00',
|
materialLight: materialLightSettings,
|
||||||
selection: '#343739',
|
noctisLilac: noctisLilacSettings,
|
||||||
selectionMatch: '#343739',
|
nord: nordSettings,
|
||||||
lineHighlight: '#343739',
|
monokai: monokaiSettings,
|
||||||
},
|
redText: redTextSettings,
|
||||||
atomone: {
|
solarizedLight: solarizedLightSettings,
|
||||||
background: '#272C35',
|
solarizedDark: solarizedDarkSettings,
|
||||||
lineBackground: '#272C3599',
|
sublime: sublimeSettings,
|
||||||
foreground: '#9d9b97',
|
tokyoNight: tokyoNightSettings,
|
||||||
caret: '#797977',
|
tokyoNightStorm: tokyoNightStormSettings,
|
||||||
selection: '#ffffff30',
|
vscodeDark: vscodeDarkSettings,
|
||||||
selectionMatch: '#2B323D',
|
vscodeLight: vscodeLightSettings,
|
||||||
gutterBackground: '#272C35',
|
xcodeLight: xcodeLightSettings,
|
||||||
gutterForeground: '#465063',
|
tokyoNightDay: tokyoNightDaySettings,
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#2B323D',
|
|
||||||
},
|
|
||||||
aura: {
|
|
||||||
background: '#21202e',
|
|
||||||
lineBackground: '#21202e99',
|
|
||||||
foreground: '#edecee',
|
|
||||||
caret: '#a277ff',
|
|
||||||
selection: '#3d375e7f',
|
|
||||||
selectionMatch: '#3d375e7f',
|
|
||||||
gutterBackground: '#21202e',
|
|
||||||
gutterForeground: '#edecee',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#a394f033',
|
|
||||||
},
|
|
||||||
bbedit: {
|
|
||||||
light: true,
|
|
||||||
background: '#FFFFFF',
|
|
||||||
lineBackground: '#FFFFFF99',
|
|
||||||
foreground: '#000000',
|
|
||||||
caret: '#FBAC52',
|
|
||||||
selection: '#FFD420',
|
|
||||||
selectionMatch: '#FFD420',
|
|
||||||
gutterBackground: '#f5f5f5',
|
|
||||||
gutterForeground: '#4D4D4C',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#00000012',
|
|
||||||
},
|
|
||||||
bespin: {
|
|
||||||
background: '#28211c',
|
|
||||||
lineBackground: '#28211c99',
|
|
||||||
foreground: '#9d9b97',
|
|
||||||
caret: '#797977',
|
|
||||||
selection: '#36312e',
|
|
||||||
selectionMatch: '#4f382b',
|
|
||||||
gutterBackground: '#28211c',
|
|
||||||
gutterForeground: '#666666',
|
|
||||||
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
},
|
|
||||||
darcula: {
|
|
||||||
background: '#2B2B2B',
|
|
||||||
lineBackground: '#2B2B2B99',
|
|
||||||
foreground: '#f8f8f2',
|
|
||||||
caret: '#FFFFFF',
|
|
||||||
selection: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
|
||||||
gutterBackground: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
gutterForeground: '#999',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
},
|
|
||||||
dracula: {
|
|
||||||
background: '#282a36',
|
|
||||||
lineBackground: '#282a3699',
|
|
||||||
foreground: '#f8f8f2',
|
|
||||||
caret: '#f8f8f0',
|
|
||||||
selection: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
|
||||||
gutterBackground: '#282a36',
|
|
||||||
gutterForeground: '#6D8A88',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
},
|
|
||||||
duotoneLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#faf8f5',
|
|
||||||
lineBackground: '#faf8f599',
|
|
||||||
foreground: '#b29762',
|
|
||||||
caret: '#93abdc',
|
|
||||||
selection: '#e3dcce',
|
|
||||||
selectionMatch: '#e3dcce',
|
|
||||||
gutterBackground: '#faf8f5',
|
|
||||||
gutterForeground: '#cdc4b1',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#EFEFEF',
|
|
||||||
},
|
|
||||||
duotoneDark: {
|
|
||||||
background: '#2a2734',
|
|
||||||
lineBackground: '#2a273499',
|
|
||||||
foreground: '#6c6783',
|
|
||||||
caret: '#ffad5c',
|
|
||||||
selection: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
gutterBackground: '#2a2734',
|
|
||||||
gutterForeground: '#545167',
|
|
||||||
lineHighlight: '#36334280',
|
|
||||||
},
|
|
||||||
eclipse: {
|
|
||||||
light: true,
|
|
||||||
background: '#fff',
|
|
||||||
lineBackground: '#ffffff99',
|
|
||||||
foreground: '#000',
|
|
||||||
caret: '#FFFFFF',
|
|
||||||
selection: '#d7d4f0',
|
|
||||||
selectionMatch: '#d7d4f0',
|
|
||||||
gutterBackground: '#f7f7f7',
|
|
||||||
gutterForeground: '#999',
|
|
||||||
lineHighlight: '#e8f2ff',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
},
|
|
||||||
githubLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#fff',
|
|
||||||
lineBackground: '#ffffff99',
|
|
||||||
foreground: '#24292e',
|
|
||||||
selection: '#BBDFFF',
|
|
||||||
selectionMatch: '#BBDFFF',
|
|
||||||
gutterBackground: '#fff',
|
|
||||||
gutterForeground: '#6e7781',
|
|
||||||
},
|
|
||||||
githubDark: {
|
|
||||||
background: '#0d1117',
|
|
||||||
lineBackground: '#0d111799',
|
|
||||||
foreground: '#c9d1d9',
|
|
||||||
caret: '#c9d1d9',
|
|
||||||
selection: '#003d73',
|
|
||||||
selectionMatch: '#003d73',
|
|
||||||
lineHighlight: '#36334280',
|
|
||||||
},
|
|
||||||
gruvboxDark: {
|
|
||||||
background: '#282828',
|
|
||||||
lineBackground: '#28282899',
|
|
||||||
foreground: '#ebdbb2',
|
|
||||||
caret: '#ebdbb2',
|
|
||||||
selection: '#bdae93',
|
|
||||||
selectionMatch: '#bdae93',
|
|
||||||
lineHighlight: '#3c3836',
|
|
||||||
gutterBackground: '#282828',
|
|
||||||
gutterForeground: '#7c6f64',
|
|
||||||
},
|
|
||||||
gruvboxLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#fbf1c7',
|
|
||||||
lineBackground: '#fbf1c799',
|
|
||||||
foreground: '#3c3836',
|
|
||||||
caret: '#af3a03',
|
|
||||||
selection: '#ebdbb2',
|
|
||||||
selectionMatch: '#bdae93',
|
|
||||||
lineHighlight: '#ebdbb2',
|
|
||||||
gutterBackground: '#ebdbb2',
|
|
||||||
gutterForeground: '#665c54',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
},
|
|
||||||
materialDark: {
|
|
||||||
background: '#2e3235',
|
|
||||||
lineBackground: '#2e323599',
|
|
||||||
foreground: '#bdbdbd',
|
|
||||||
caret: '#a0a4ae',
|
|
||||||
selection: '#d7d4f0',
|
|
||||||
selectionMatch: '#d7d4f0',
|
|
||||||
gutterBackground: '#2e3235',
|
|
||||||
gutterForeground: '#999',
|
|
||||||
gutterActiveForeground: '#4f5b66',
|
|
||||||
lineHighlight: '#545b61',
|
|
||||||
},
|
|
||||||
materialLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#FAFAFA',
|
|
||||||
lineBackground: '#FAFAFA99',
|
|
||||||
foreground: '#90A4AE',
|
|
||||||
caret: '#272727',
|
|
||||||
selection: '#80CBC440',
|
|
||||||
selectionMatch: '#FAFAFA',
|
|
||||||
gutterBackground: '#FAFAFA',
|
|
||||||
gutterForeground: '#90A4AE',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#CCD7DA50',
|
|
||||||
},
|
|
||||||
noctisLilac: {
|
|
||||||
light: true,
|
|
||||||
background: '#f2f1f8',
|
|
||||||
lineBackground: '#f2f1f899',
|
|
||||||
foreground: '#0c006b',
|
|
||||||
caret: '#5c49e9',
|
|
||||||
selection: '#d5d1f2',
|
|
||||||
selectionMatch: '#d5d1f2',
|
|
||||||
gutterBackground: '#f2f1f8',
|
|
||||||
gutterForeground: '#0c006b70',
|
|
||||||
lineHighlight: '#e1def3',
|
|
||||||
},
|
|
||||||
nord: {
|
|
||||||
background: '#2e3440',
|
|
||||||
lineBackground: '#2e344099',
|
|
||||||
foreground: '#FFFFFF',
|
|
||||||
caret: '#FFFFFF',
|
|
||||||
selection: '#3b4252',
|
|
||||||
selectionMatch: '#e5e9f0',
|
|
||||||
gutterBackground: '#2e3440',
|
|
||||||
gutterForeground: '#4c566a',
|
|
||||||
gutterActiveForeground: '#d8dee9',
|
|
||||||
lineHighlight: '#4c566a',
|
|
||||||
},
|
|
||||||
okaidia: {
|
|
||||||
background: '#272822',
|
|
||||||
lineBackground: '#27282299',
|
|
||||||
foreground: '#FFFFFF',
|
|
||||||
caret: '#FFFFFF',
|
|
||||||
selection: '#49483E',
|
|
||||||
selectionMatch: '#49483E',
|
|
||||||
gutterBackground: '#272822',
|
|
||||||
gutterForeground: '#FFFFFF70',
|
|
||||||
lineHighlight: '#00000059',
|
|
||||||
},
|
|
||||||
solarizedLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#fdf6e3',
|
|
||||||
lineBackground: '#fdf6e399',
|
|
||||||
foreground: '#657b83',
|
|
||||||
caret: '#586e75',
|
|
||||||
selection: '#dfd9c8',
|
|
||||||
selectionMatch: '#dfd9c8',
|
|
||||||
gutterBackground: '#00000010',
|
|
||||||
gutterForeground: '#657b83',
|
|
||||||
lineHighlight: '#dfd9c8',
|
|
||||||
},
|
|
||||||
solarizedDark: {
|
|
||||||
background: '#002b36',
|
|
||||||
lineBackground: '#002b3699',
|
|
||||||
foreground: '#93a1a1',
|
|
||||||
caret: '#839496',
|
|
||||||
selection: '#173541',
|
|
||||||
selectionMatch: '#aafe661a',
|
|
||||||
gutterBackground: '#00252f',
|
|
||||||
gutterForeground: '#839496',
|
|
||||||
lineHighlight: '#173541',
|
|
||||||
},
|
|
||||||
sublime: {
|
|
||||||
background: '#303841',
|
|
||||||
lineBackground: '#30384199',
|
|
||||||
foreground: '#FFFFFF',
|
|
||||||
caret: '#FBAC52',
|
|
||||||
selection: '#4C5964',
|
|
||||||
selectionMatch: '#3A546E',
|
|
||||||
gutterBackground: '#303841',
|
|
||||||
gutterForeground: '#FFFFFF70',
|
|
||||||
lineHighlight: '#00000059',
|
|
||||||
},
|
|
||||||
tokyoNightDay: {
|
|
||||||
light: true,
|
|
||||||
background: '#e1e2e7',
|
|
||||||
lineBackground: '#e1e2e799',
|
|
||||||
foreground: '#3760bf',
|
|
||||||
caret: '#3760bf',
|
|
||||||
selection: '#99a7df',
|
|
||||||
selectionMatch: '#99a7df',
|
|
||||||
gutterBackground: '#e1e2e7',
|
|
||||||
gutterForeground: '#3760bf',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#5f5faf11',
|
|
||||||
},
|
|
||||||
tokyoNightStorm: {
|
|
||||||
background: '#24283b',
|
|
||||||
lineBackground: '#24283b99',
|
|
||||||
foreground: '#7982a9',
|
|
||||||
caret: '#c0caf5',
|
|
||||||
selection: '#6f7bb630',
|
|
||||||
selectionMatch: '#1f2335',
|
|
||||||
gutterBackground: '#24283b',
|
|
||||||
gutterForeground: '#7982a9',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#292e42',
|
|
||||||
},
|
|
||||||
tokyoNight: {
|
|
||||||
background: '#1a1b26',
|
|
||||||
lineBackground: '#1a1b2699',
|
|
||||||
foreground: '#787c99',
|
|
||||||
caret: '#c0caf5',
|
|
||||||
selection: '#515c7e40',
|
|
||||||
selectionMatch: '#16161e',
|
|
||||||
gutterBackground: '#1a1b26',
|
|
||||||
gutterForeground: '#787c99',
|
|
||||||
gutterBorder: 'transparent',
|
|
||||||
lineHighlight: '#1e202e',
|
|
||||||
},
|
|
||||||
vscodeDark: {
|
|
||||||
background: '#1e1e1e',
|
|
||||||
lineBackground: '#1e1e1e99',
|
|
||||||
foreground: '#9cdcfe',
|
|
||||||
caret: '#c6c6c6',
|
|
||||||
selection: '#6199ff2f',
|
|
||||||
selectionMatch: '#72a1ff59',
|
|
||||||
lineHighlight: '#ffffff0f',
|
|
||||||
gutterBackground: '#1e1e1e',
|
|
||||||
gutterForeground: '#838383',
|
|
||||||
gutterActiveForeground: '#fff',
|
|
||||||
},
|
|
||||||
xcodeLight: {
|
|
||||||
light: true,
|
|
||||||
background: '#fff',
|
|
||||||
lineBackground: '#ffffff99',
|
|
||||||
foreground: '#3D3D3D',
|
|
||||||
selection: '#BBDFFF',
|
|
||||||
selectionMatch: '#BBDFFF',
|
|
||||||
gutterBackground: '#fff',
|
|
||||||
gutterForeground: '#AFAFAF',
|
|
||||||
lineHighlight: '#EDF4FF',
|
|
||||||
},
|
|
||||||
xcodeDark: {
|
|
||||||
background: '#292A30',
|
|
||||||
lineBackground: '#292A3099',
|
|
||||||
foreground: '#CECFD0',
|
|
||||||
caret: '#fff',
|
|
||||||
selection: '#727377',
|
|
||||||
selectionMatch: '#727377',
|
|
||||||
lineHighlight: '#2F3239',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getColors(str) {
|
function getColors(str) {
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Cutie Pi
|
||||||
|
* by Switch Angel
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
const deepPurple = '#5c019a';
|
||||||
|
const yellowPink = '#fbeffc';
|
||||||
|
const grey = '#272C35';
|
||||||
|
const pinkAccent = '#fee1ff';
|
||||||
|
const lightGrey = '#465063';
|
||||||
|
const bratGreen = '#9acd3f';
|
||||||
|
const lighterGrey = '#97a1b7';
|
||||||
|
const pink = '#f6a6fd';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: 'white',
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: deepPurple,
|
||||||
|
caret: '#797977',
|
||||||
|
selection: yellowPink,
|
||||||
|
selectionMatch: '#2B323D',
|
||||||
|
gutterBackground: grey,
|
||||||
|
gutterForeground: lightGrey,
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: pinkAccent,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: deepPurple,
|
||||||
|
},
|
||||||
|
{ tag: [t.tagName, t.heading], color: settings.foreground },
|
||||||
|
{ tag: t.comment, color: lighterGrey },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: pink },
|
||||||
|
{ tag: [t.attributeName, t.number], color: '#d19a66' },
|
||||||
|
{ tag: t.className, color: grey },
|
||||||
|
{ tag: t.keyword, color: deepPurple },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: bratGreen },
|
||||||
|
],
|
||||||
|
});
|
||||||
+51
-32
@@ -1,42 +1,61 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const palettes = {
|
||||||
|
// https://www.deviantart.com/advancedfan2020/art/Game-Boy-Palette-Set-Color-HEX-Part-09-920495662
|
||||||
|
'Central Florida A': ['#FFF630', '#B3AC22', '#666213', '#191905'],
|
||||||
|
'Central Florida B': ['#38CEBA', '#279082', '#16524A', '#061513'],
|
||||||
|
'Central Florida C': ['#FF8836', '#B35F26', '#663616', '#190E05'],
|
||||||
|
'Central Florida D': ['#E07070', '#9D4E4E', '#5A2D2D', '#160B0B'],
|
||||||
|
'Central Florida E': ['#7AA4CB', '#55738E', '#314251', '#0C1014'],
|
||||||
|
'Feminine Energy A': ['#DC5686', '#9A415E', '#582536', '#16090D'],
|
||||||
|
'Feminine Energy B': ['#D0463C', '#92312A', '#531c18', '#150706'],
|
||||||
|
'Feminine Energy C': ['#D86918', '#974A11', '#562A0A', '#160A02'],
|
||||||
|
'Feminine Energy D': ['#EFC54F', '#A78A36', '#604F20', '#181408'],
|
||||||
|
'Feminine Energy E': ['#866399', '#5e456b', '#36283d', '#0d0a0f'],
|
||||||
|
'Sour Watermelon A': ['#993366', '#6B2447', '#3D1429', '#0F050A'],
|
||||||
|
'Sour Watermelon B': ['#996666', '#6B4747', '#3D2929', '#0F0A0A'],
|
||||||
|
'Sour Watermelon C': ['#999966', '#686B47', '#3d3d29', '#0f0f0A'],
|
||||||
|
'Sour Watermelon D': ['#99cc66', '#6b8f47', '#3d5229', '#0f140a'],
|
||||||
|
'Sour Watermelon E': ['#99ff66', '#6bb347', '#3d6629', '#0f190a'],
|
||||||
|
//https://www.deviantart.com/advancedfan2020/art/Game-Boy-Palette-Set-Color-HEX-Part-02-920073260
|
||||||
|
'Peri Peaceful A': ['#909BE9', '#656DA3', '#3A3E5D', '#0e0f17'],
|
||||||
|
'Peri Peaceful B': ['#68628d', '#494563', '#2a2738', '#0a0a0e'], // pretty dim
|
||||||
|
'Peri Peaceful E': ['#b5a0a9', '#7f7076', '#484044', '#121011'],
|
||||||
|
'Hichem Palette B': ['#4fa3a5', '#377273', '#204142', '#081010'],
|
||||||
|
'Hichem Palette C': ['#Fe6f9b', '#b24e6d', '#662c3e', '#190b0f'],
|
||||||
|
'Hichem Palette D': ['#ffbb5a', '#b3833f', '#664b24', '#191309'],
|
||||||
|
'JSR2 A': ['#E0EFC0', '#9da786', '#5a604d', '#161813'],
|
||||||
|
};
|
||||||
|
const palette = palettes['Sour Watermelon B'];
|
||||||
export const settings = {
|
export const settings = {
|
||||||
background: '#9bbc0f',
|
background: palette[3],
|
||||||
foreground: '#0f380f', // whats that?
|
foreground: palette[1],
|
||||||
caret: '#0f380f',
|
caret: palette[0],
|
||||||
selection: '#306230',
|
selection: palette[0],
|
||||||
selectionMatch: '#ffffff26',
|
selectionMatch: palette[1],
|
||||||
lineHighlight: '#8bac0f',
|
lineHighlight: palette[3],
|
||||||
lineBackground: '#9bbc0f50',
|
lineBackground: palette[3] + '90',
|
||||||
//lineBackground: 'transparent',
|
//lineBackground: 'transparent',
|
||||||
gutterBackground: 'transparent',
|
gutterBackground: 'transparent',
|
||||||
gutterForeground: '#0f380f',
|
gutterForeground: palette[0],
|
||||||
light: true,
|
light: false,
|
||||||
customStyle: '.cm-line { line-height: 1 }',
|
// customStyle: '.cm-line { line-height: 1 }',
|
||||||
};
|
};
|
||||||
export default createTheme({
|
export default createTheme({
|
||||||
theme: 'light',
|
theme: 'dark',
|
||||||
settings,
|
settings,
|
||||||
styles: [
|
styles: [
|
||||||
{ tag: t.labelName, color: '#0f380f' },
|
{ tag: t.comment, color: palette[2] },
|
||||||
{ tag: t.keyword, color: '#0f380f' },
|
{ tag: t.string, color: palette[1] },
|
||||||
{ tag: t.operator, color: '#0f380f' },
|
{ tag: [t.atom, t.number], color: palette[1] },
|
||||||
{ tag: t.special(t.variableName), color: '#0f380f' },
|
{ tag: [t.meta, t.labelName, t.variableName], color: palette[0] },
|
||||||
{ tag: t.typeName, color: '#0f380f' },
|
{
|
||||||
{ tag: t.atom, color: '#0f380f' },
|
tag: [t.keyword, t.tagName, t.arithmeticOperator],
|
||||||
{ tag: t.number, color: '#0f380f' },
|
color: palette[1],
|
||||||
{ tag: t.definition(t.variableName), color: '#0f380f' },
|
},
|
||||||
{ tag: t.string, color: '#0f380f' },
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: palette[0] },
|
||||||
{ tag: t.special(t.string), color: '#0f380f' },
|
{ tag: [t.function(t.variableName), t.propertyName], color: palette[0] },
|
||||||
{ tag: t.comment, color: '#0f380f' },
|
{ tag: t.atom, color: palette[1] },
|
||||||
{ tag: t.variableName, color: '#0f380f' },
|
|
||||||
{ tag: t.tagName, color: '#0f380f' },
|
|
||||||
{ tag: t.bracket, color: '#0f380f' },
|
|
||||||
{ tag: t.meta, color: '#0f380f' },
|
|
||||||
{ tag: t.attributeName, color: '#0f380f' },
|
|
||||||
{ tag: t.propertyName, color: '#0f380f' },
|
|
||||||
{ tag: t.className, color: '#0f380f' },
|
|
||||||
{ tag: t.invalid, color: '#0f380f' },
|
|
||||||
{ tag: [t.unit, t.punctuation], color: '#0f380f' },
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* androidstudio
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#282b2e',
|
||||||
|
lineBackground: '#282b2e99',
|
||||||
|
foreground: '#a9b7c6',
|
||||||
|
caret: '#00FF00',
|
||||||
|
selection: '#343739',
|
||||||
|
selectionMatch: '#343739',
|
||||||
|
lineHighlight: '#343739',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#282b2e',
|
||||||
|
foreground: '#a9b7c6',
|
||||||
|
caret: '#00FF00',
|
||||||
|
selection: '#4e5254',
|
||||||
|
selectionMatch: '#4e5254',
|
||||||
|
gutterForeground: '#cccccc50',
|
||||||
|
lineHighlight: '#7f85891f',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.labelName, color: 'inherit' },
|
||||||
|
{ tag: [t.keyword, t.deleted, t.className], color: '#a9b7c6' },
|
||||||
|
{ tag: [t.number, t.literal], color: '#6897bb' },
|
||||||
|
//{ tag: [t.link, t.variableName], color: '#629755' },
|
||||||
|
{ tag: [t.link, t.variableName], color: '#a9b7c6' },
|
||||||
|
{ tag: [t.comment, t.quote], color: 'grey' },
|
||||||
|
{ tag: [t.meta, t.documentMeta], color: '#bbb529' },
|
||||||
|
//{ tag: [t.string, t.propertyName, t.attributeValue], color: '#6a8759' },
|
||||||
|
{ tag: [t.propertyName, t.attributeValue], color: '#a9b7c6' },
|
||||||
|
{ tag: [t.string], color: '#6a8759' },
|
||||||
|
{ tag: [t.heading, t.typeName], color: '#ffc66d' },
|
||||||
|
{ tag: [t.attributeName], color: '#a9b7c6' },
|
||||||
|
{ tag: [t.emphasis], fontStyle: 'italic' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Atom One
|
||||||
|
* Atom One dark syntax theme
|
||||||
|
*
|
||||||
|
* https://github.com/atom/one-dark-syntax
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#272C35',
|
||||||
|
lineBackground: '#272C3599',
|
||||||
|
foreground: 'hsl(220, 14%, 71%)',
|
||||||
|
caret: '#797977',
|
||||||
|
selection: '#ffffff30',
|
||||||
|
selectionMatch: '#2B323D',
|
||||||
|
gutterBackground: '#272C35',
|
||||||
|
gutterForeground: '#465063',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#2B323D',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#272C35',
|
||||||
|
foreground: '#9d9b97',
|
||||||
|
caret: '#797977',
|
||||||
|
selection: '#3d4c64',
|
||||||
|
selectionMatch: '#3d4c64',
|
||||||
|
gutterBackground: '#272C35',
|
||||||
|
gutterForeground: '#465063',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#2e3f5940',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: 'hsl(207, 82%, 66%)',
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: 'hsl( 29, 54%, 61%)' },
|
||||||
|
{ tag: [t.tagName, t.heading], color: '#e06c75' },
|
||||||
|
{ tag: t.comment, color: '#54636D' },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: 'hsl(220, 14%, 71%)' },
|
||||||
|
{ tag: [t.attributeName, t.number], color: 'hsl( 29, 54%, 61%)' },
|
||||||
|
{ tag: t.className, color: 'hsl( 39, 67%, 69%)' },
|
||||||
|
{ tag: t.keyword, color: 'hsl(286, 60%, 67%)' },
|
||||||
|
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: '#98c379' },
|
||||||
|
],
|
||||||
|
});
|
||||||
Vendored
+51
@@ -0,0 +1,51 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#21202e',
|
||||||
|
lineBackground: '#21202e99',
|
||||||
|
foreground: '#edecee',
|
||||||
|
caret: '#a277ff',
|
||||||
|
selection: '#3d375e7f',
|
||||||
|
selectionMatch: '#3d375e7f',
|
||||||
|
gutterBackground: '#21202e',
|
||||||
|
gutterForeground: '#edecee',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#a394f033',
|
||||||
|
};
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#21202e',
|
||||||
|
foreground: '#edecee',
|
||||||
|
caret: '#a277ff',
|
||||||
|
selection: '#5a51898f',
|
||||||
|
selectionMatch: '#5a51898f',
|
||||||
|
gutterBackground: '#21202e',
|
||||||
|
gutterForeground: '#edecee',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#a394f033',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#a277ff' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#edecee' },
|
||||||
|
{ tag: [t.propertyName], color: '#ffca85' },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: '#61ffca' },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: '#ffca85' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#61ffca' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#edecee' },
|
||||||
|
{ tag: [t.className], color: '#82e2ff' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#61ffca' },
|
||||||
|
{ tag: [t.typeName], color: '#82e2ff' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#a277ff' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#61ffca' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#6d6d6d' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#a277ff' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#edecee' },
|
||||||
|
{ tag: t.invalid, color: '#ff6767' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#FFFFFF',
|
||||||
|
lineBackground: '#FFFFFF99',
|
||||||
|
foreground: '#000000',
|
||||||
|
caret: '#FBAC52',
|
||||||
|
selection: '#FFD420',
|
||||||
|
selectionMatch: '#FFD420',
|
||||||
|
gutterBackground: '#f5f5f5',
|
||||||
|
gutterForeground: '#4D4D4C',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#00000012',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#FFFFFF',
|
||||||
|
foreground: '#000000',
|
||||||
|
caret: '#FBAC52',
|
||||||
|
selection: '#FFD420',
|
||||||
|
selectionMatch: '#FFD420',
|
||||||
|
gutterBackground: '#f5f5f5',
|
||||||
|
gutterForeground: '#4D4D4C',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#00000012',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.meta, t.comment], color: '#804000' },
|
||||||
|
{ tag: [t.keyword, t.strong], color: '#0000FF' },
|
||||||
|
{ tag: [t.number], color: '#FF0080' },
|
||||||
|
{ tag: [t.string], color: '#FF0080' },
|
||||||
|
{ tag: [t.variableName], color: '#006600' },
|
||||||
|
{ tag: [t.escape], color: '#33CC33' },
|
||||||
|
{ tag: [t.tagName], color: '#1C02FF' },
|
||||||
|
{ tag: [t.heading], color: '#0C07FF' },
|
||||||
|
{ tag: [t.quote], color: '#000000' },
|
||||||
|
{ tag: [t.list], color: '#B90690' },
|
||||||
|
{ tag: [t.documentMeta], color: '#888888' },
|
||||||
|
{ tag: [t.function(t.variableName)], color: '#0000A2' },
|
||||||
|
{ tag: [t.definition(t.typeName), t.typeName], color: '#6D79DE' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+21
-21
@@ -1,5 +1,5 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
export const settings = {
|
export const settings = {
|
||||||
background: 'black',
|
background: 'black',
|
||||||
foreground: 'white', // whats that?
|
foreground: 'white', // whats that?
|
||||||
@@ -15,25 +15,25 @@ export default createTheme({
|
|||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
settings,
|
settings,
|
||||||
styles: [
|
styles: [
|
||||||
{ tag: t.labelName, color: 'white' },
|
{ tag: t.labelName, color: 'inherit' },
|
||||||
{ tag: t.keyword, color: 'white' },
|
{ tag: t.keyword, color: 'inherit' },
|
||||||
{ tag: t.operator, color: 'white' },
|
{ tag: t.operator, color: 'inherit' },
|
||||||
{ tag: t.special(t.variableName), color: 'white' },
|
{ tag: t.special(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.typeName, color: 'white' },
|
{ tag: t.typeName, color: 'inherit' },
|
||||||
{ tag: t.atom, color: 'white' },
|
{ tag: t.atom, color: 'inherit' },
|
||||||
{ tag: t.number, color: 'white' },
|
{ tag: t.number, color: 'inherit' },
|
||||||
{ tag: t.definition(t.variableName), color: 'white' },
|
{ tag: t.definition(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.string, color: 'white' },
|
{ tag: t.string, color: 'inherit' },
|
||||||
{ tag: t.special(t.string), color: 'white' },
|
{ tag: t.special(t.string), color: 'inherit' },
|
||||||
{ tag: t.comment, color: 'white' },
|
{ tag: t.comment, color: 'inherit' },
|
||||||
{ tag: t.variableName, color: 'white' },
|
{ tag: t.variableName, color: 'inherit' },
|
||||||
{ tag: t.tagName, color: 'white' },
|
{ tag: t.tagName, color: 'inherit' },
|
||||||
{ tag: t.bracket, color: 'white' },
|
{ tag: t.bracket, color: 'inherit' },
|
||||||
{ tag: t.meta, color: 'white' },
|
{ tag: t.meta, color: 'inherit' },
|
||||||
{ tag: t.attributeName, color: 'white' },
|
{ tag: t.attributeName, color: 'inherit' },
|
||||||
{ tag: t.propertyName, color: 'white' },
|
{ tag: t.propertyName, color: 'inherit' },
|
||||||
{ tag: t.className, color: 'white' },
|
{ tag: t.className, color: 'inherit' },
|
||||||
{ tag: t.invalid, color: 'white' },
|
{ tag: t.invalid, color: 'inherit' },
|
||||||
{ tag: [t.unit, t.punctuation], color: 'white' },
|
{ tag: [t.unit, t.punctuation], color: 'inherit' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
+21
-21
@@ -1,5 +1,5 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
export const settings = {
|
export const settings = {
|
||||||
background: '#051DB5',
|
background: '#051DB5',
|
||||||
lineBackground: '#051DB550',
|
lineBackground: '#051DB550',
|
||||||
@@ -18,25 +18,25 @@ export default createTheme({
|
|||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
settings,
|
settings,
|
||||||
styles: [
|
styles: [
|
||||||
{ tag: t.labelName, color: 'white' },
|
{ tag: t.labelName, color: 'inherit' },
|
||||||
{ tag: t.keyword, color: 'white' },
|
{ tag: t.keyword, color: 'inherit' },
|
||||||
{ tag: t.operator, color: 'white' },
|
{ tag: t.operator, color: 'inherit' },
|
||||||
{ tag: t.special(t.variableName), color: 'white' },
|
{ tag: t.special(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.typeName, color: 'white' },
|
{ tag: t.typeName, color: 'inherit' },
|
||||||
{ tag: t.atom, color: 'white' },
|
{ tag: t.atom, color: 'inherit' },
|
||||||
{ tag: t.number, color: 'white' },
|
{ tag: t.number, color: 'inherit' },
|
||||||
{ tag: t.definition(t.variableName), color: 'white' },
|
{ tag: t.definition(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.string, color: 'white' },
|
{ tag: t.string, color: 'inherit' },
|
||||||
{ tag: t.special(t.string), color: 'white' },
|
{ tag: t.special(t.string), color: 'inherit' },
|
||||||
{ tag: t.comment, color: 'white' },
|
{ tag: t.comment, color: 'inherit' },
|
||||||
{ tag: t.variableName, color: 'white' },
|
{ tag: t.variableName, color: 'inherit' },
|
||||||
{ tag: t.tagName, color: 'white' },
|
{ tag: t.tagName, color: 'inherit' },
|
||||||
{ tag: t.bracket, color: 'white' },
|
{ tag: t.bracket, color: 'inherit' },
|
||||||
{ tag: t.meta, color: 'white' },
|
{ tag: t.meta, color: 'inherit' },
|
||||||
{ tag: t.attributeName, color: 'white' },
|
{ tag: t.attributeName, color: 'inherit' },
|
||||||
{ tag: t.propertyName, color: 'white' },
|
{ tag: t.propertyName, color: 'inherit' },
|
||||||
{ tag: t.className, color: 'white' },
|
{ tag: t.className, color: 'inherit' },
|
||||||
{ tag: t.invalid, color: 'white' },
|
{ tag: t.invalid, color: 'inherit' },
|
||||||
{ tag: [t.unit, t.punctuation], color: 'white' },
|
{ tag: [t.unit, t.punctuation], color: 'inherit' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* darcula
|
||||||
|
* Name: IntelliJ IDEA darcula theme
|
||||||
|
* From IntelliJ IDEA by JetBrains
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
export const settings = {
|
||||||
|
background: '#242424',
|
||||||
|
lineBackground: '#24242499',
|
||||||
|
foreground: '#f8f8f2',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||||
|
gutterBackground: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#242424',
|
||||||
|
foreground: '#f8f8f2',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||||
|
gutterBackground: 'transparent',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.labelName, color: '#CCCCCC' },
|
||||||
|
{ tag: [t.atom, t.number], color: '#7A9EC2' },
|
||||||
|
{ tag: [t.comment], color: '#707070' },
|
||||||
|
{ tag: [t.string], color: '#6A8759' },
|
||||||
|
{ tag: [t.variableName, t.operator], color: '#CCCCCC' },
|
||||||
|
{ tag: [t.function(t.variableName), t.propertyName], color: '#FFC66D' },
|
||||||
|
{ tag: [t.meta, t.className], color: '#FFC66D' },
|
||||||
|
{ tag: [t.propertyName], color: '#FFC66D' },
|
||||||
|
{ tag: [t.keyword], color: '#CC7832' },
|
||||||
|
{ tag: [t.tagName], color: '#ff79c6' },
|
||||||
|
{ tag: [t.typeName], color: '#ffb86c' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* @name dracula
|
||||||
|
* Michael Kaminsky (http://github.com/mkaminsky11)
|
||||||
|
* Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme)
|
||||||
|
*/
|
||||||
|
// this is different from https://thememirror.net/dracula
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#282a36',
|
||||||
|
lineBackground: '#282a3699',
|
||||||
|
foreground: '#f8f8f2',
|
||||||
|
caret: '#f8f8f0',
|
||||||
|
selection: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||||
|
gutterBackground: '#282a36',
|
||||||
|
gutterForeground: '#6272a4',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
};
|
||||||
|
|
||||||
|
const purple = '#BD93F9';
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#282a36',
|
||||||
|
foreground: '#f8f8f2',
|
||||||
|
caret: '#f8f8f0',
|
||||||
|
selection: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||||
|
gutterBackground: '#282a36',
|
||||||
|
gutterForeground: '#6272a4',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.comment, color: '#6272a4' },
|
||||||
|
{ tag: t.string, color: '#f1fa8c' },
|
||||||
|
{ tag: [t.atom, t.number], color: purple },
|
||||||
|
{ tag: [t.meta, t.labelName, t.variableName], color: '#f8f8f2' },
|
||||||
|
{
|
||||||
|
tag: [t.keyword, t.tagName, t.arithmeticOperator],
|
||||||
|
color: '#ff79c6',
|
||||||
|
},
|
||||||
|
{ tag: [t.function(t.variableName), t.propertyName], color: '#50fa7b' },
|
||||||
|
{ tag: t.atom, color: '#bd93f9' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* duotone
|
||||||
|
* author Bram de Haan
|
||||||
|
* by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#2a2734',
|
||||||
|
lineBackground: '#2a273499',
|
||||||
|
foreground: '#eeebff',
|
||||||
|
caret: '#ffad5c',
|
||||||
|
selection: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
gutterBackground: '#2a2734',
|
||||||
|
gutterForeground: '#545167',
|
||||||
|
lineHighlight: '#36334280',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#2a2734',
|
||||||
|
foreground: '#6c6783',
|
||||||
|
caret: '#ffad5c',
|
||||||
|
selection: '#9a86fd',
|
||||||
|
selectionMatch: '#9a86fd',
|
||||||
|
gutterBackground: '#2a2734',
|
||||||
|
gutterForeground: '#545167',
|
||||||
|
lineHighlight: '#36334280',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.comment, t.bracket, t.operator], color: '#6c6783' },
|
||||||
|
{ tag: [t.atom, t.number, t.keyword, t.link, t.attributeName, t.quote], color: '#ffcc99' },
|
||||||
|
{ tag: [t.emphasis, t.heading, t.tagName, t.propertyName, t.className, t.variableName], color: '#eeebff' },
|
||||||
|
{ tag: [t.typeName, t.url], color: '#eeebff' },
|
||||||
|
{ tag: t.string, color: '#ffb870' },
|
||||||
|
/* { tag: [t.propertyName], color: '#9a86fd' }, */
|
||||||
|
{ tag: [t.propertyName], color: '#eeebff' },
|
||||||
|
{ tag: t.labelName, color: '#eeebff' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* duotone
|
||||||
|
* author Bram de Haan
|
||||||
|
* by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#faf8f5',
|
||||||
|
lineBackground: '#faf8f599',
|
||||||
|
foreground: '#b29762',
|
||||||
|
caret: '#93abdc',
|
||||||
|
selection: '#e3dcce',
|
||||||
|
selectionMatch: '#e3dcce',
|
||||||
|
gutterBackground: '#faf8f5',
|
||||||
|
gutterForeground: '#cdc4b1',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#EFEFEF',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#faf8f5',
|
||||||
|
foreground: '#b29762',
|
||||||
|
caret: '#93abdc',
|
||||||
|
selection: '#e3dcce',
|
||||||
|
selectionMatch: '#e3dcce',
|
||||||
|
gutterBackground: '#faf8f5',
|
||||||
|
gutterForeground: '#cdc4b1',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#ddceb154',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.comment, t.bracket], color: '#b6ad9a' },
|
||||||
|
{ tag: [t.atom, t.number, t.keyword, t.link, t.attributeName, t.quote], color: '#063289' },
|
||||||
|
{ tag: [t.emphasis, t.heading, t.tagName, t.propertyName, t.variableName], color: '#2d2006' },
|
||||||
|
{ tag: [t.typeName, t.url, t.string], color: '#896724' },
|
||||||
|
{ tag: [t.operator, t.string], color: '#1659df' },
|
||||||
|
{ tag: [t.propertyName], color: '#b29762' },
|
||||||
|
{ tag: [t.unit, t.punctuation], color: '#063289' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#fff',
|
||||||
|
lineBackground: '#ffffff99',
|
||||||
|
foreground: '#000',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#d7d4f0',
|
||||||
|
selectionMatch: '#d7d4f0',
|
||||||
|
gutterBackground: '#f7f7f7',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
lineHighlight: '#e8f2ff',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#fff',
|
||||||
|
foreground: '#000',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#d7d4f0',
|
||||||
|
selectionMatch: '#d7d4f0',
|
||||||
|
gutterBackground: '#f7f7f7',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
lineHighlight: '#006fff1c',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.comment], color: '#3F7F5F' },
|
||||||
|
{ tag: [t.documentMeta], color: '#FF1717' },
|
||||||
|
{ tag: t.keyword, color: '#7F0055', fontWeight: 'bold' },
|
||||||
|
{ tag: t.atom, color: '#00f' },
|
||||||
|
{ tag: t.number, color: '#164' },
|
||||||
|
{ tag: t.propertyName, color: '#164' },
|
||||||
|
{ tag: [t.variableName, t.definition(t.variableName)], color: '#0000C0' },
|
||||||
|
{ tag: t.function(t.variableName), color: '#0000C0' },
|
||||||
|
{ tag: t.string, color: '#2A00FF' },
|
||||||
|
{ tag: t.operator, color: 'black' },
|
||||||
|
{ tag: t.tagName, color: '#170' },
|
||||||
|
{ tag: t.attributeName, color: '#00c' },
|
||||||
|
{ tag: t.link, color: '#219' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#0d1117',
|
||||||
|
lineBackground: '#0d111799',
|
||||||
|
foreground: '#c9d1d9',
|
||||||
|
caret: '#c9d1d9',
|
||||||
|
selection: '#003d73',
|
||||||
|
selectionMatch: '#003d73',
|
||||||
|
lineHighlight: '#36334280',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#0d1117',
|
||||||
|
foreground: '#c9d1d9',
|
||||||
|
caret: '#c9d1d9',
|
||||||
|
selection: '#003d73',
|
||||||
|
selectionMatch: '#003d73',
|
||||||
|
lineHighlight: '#36334280',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.labelName, color: '#d2a8ff' },
|
||||||
|
{ tag: [t.standard(t.tagName), t.tagName], color: '#7ee787' },
|
||||||
|
{ tag: [t.comment, t.bracket], color: '#8b949e' },
|
||||||
|
{ tag: [t.className, t.propertyName], color: '#d2a8ff' },
|
||||||
|
{ tag: [t.variableName, t.attributeName], color: '#d2a8ff' },
|
||||||
|
{ tag: [t.number, t.operator], color: '#79c0ff' },
|
||||||
|
{ tag: [t.keyword, t.typeName, t.typeOperator, t.typeName], color: '#ff7b72' },
|
||||||
|
{ tag: [t.string, t.meta, t.regexp], color: '#a5d6ff' },
|
||||||
|
{ tag: [t.name, t.quote], color: '#7ee787' },
|
||||||
|
{ tag: [t.heading, t.strong], color: '#d2a8ff', fontWeight: 'bold' },
|
||||||
|
{ tag: [t.emphasis], color: '#d2a8ff', fontStyle: 'italic' },
|
||||||
|
{ tag: [t.deleted], color: '#ffdcd7', backgroundColor: 'ffeef0' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#ffab70' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.invalid, color: '#f97583' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#fff',
|
||||||
|
lineBackground: '#ffffff99',
|
||||||
|
foreground: '#24292e',
|
||||||
|
selection: '#BBDFFF',
|
||||||
|
selectionMatch: '#BBDFFF',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#6e7781',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#fff',
|
||||||
|
foreground: '#24292e',
|
||||||
|
selection: '#BBDFFF',
|
||||||
|
selectionMatch: '#BBDFFF',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#6e7781',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.standard(t.tagName), t.tagName], color: '#116329' },
|
||||||
|
{ tag: [t.comment, t.bracket], color: '#6a737d' },
|
||||||
|
{ tag: [t.className, t.propertyName], color: '#6f42c1' },
|
||||||
|
{ tag: [t.variableName, t.attributeName, t.number, t.operator], color: '#005cc5' },
|
||||||
|
{ tag: [t.keyword, t.typeName, t.typeOperator, t.typeName], color: '#d73a49' },
|
||||||
|
{ tag: [t.string, t.meta, t.regexp], color: '#032f62' },
|
||||||
|
{ tag: [t.name, t.quote], color: '#22863a' },
|
||||||
|
{ tag: [t.heading, t.strong], color: '#24292e', fontWeight: 'bold' },
|
||||||
|
{ tag: [t.emphasis], color: '#24292e', fontStyle: 'italic' },
|
||||||
|
{ tag: [t.deleted], color: '#b31d28', backgroundColor: 'ffeef0' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#e36209' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#032f62' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.invalid, color: '#cb2431' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Atom One
|
||||||
|
* Atom One dark syntax theme
|
||||||
|
*
|
||||||
|
* https://github.com/atom/one-dark-syntax
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = ['#000000', '#8ed675', '#56bd2a', '#54636D', '#171717'];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: hex[0],
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[2],
|
||||||
|
selection: hex[4],
|
||||||
|
selectionMatch: hex[0],
|
||||||
|
gutterBackground: hex[0],
|
||||||
|
gutterForeground: hex[3],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[2],
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: hex[1] },
|
||||||
|
{ tag: t.comment, color: hex[3] },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: hex[2] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[1] },
|
||||||
|
{ tag: t.keyword, color: hex[2] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[1] },
|
||||||
|
],
|
||||||
|
});
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* gruvbox-dark
|
||||||
|
* author morhetz
|
||||||
|
* From github.com/codemirror/codemirror5/blob/master/theme/gruvbox-dark.css
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#282828',
|
||||||
|
lineBackground: '#28282899',
|
||||||
|
foreground: '#ebdbb2',
|
||||||
|
caret: '#ebdbb2',
|
||||||
|
selection: '#bdae93',
|
||||||
|
selectionMatch: '#bdae93',
|
||||||
|
lineHighlight: '#3c3836',
|
||||||
|
gutterBackground: '#282828',
|
||||||
|
gutterForeground: '#7c6f64',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#282828',
|
||||||
|
foreground: '#ebdbb2',
|
||||||
|
caret: '#ebdbb2',
|
||||||
|
selection: '#b99d555c',
|
||||||
|
selectionMatch: '#b99d555c',
|
||||||
|
lineHighlight: '#baa1602b',
|
||||||
|
gutterBackground: '#282828',
|
||||||
|
gutterForeground: '#7c6f64',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#fb4934' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], color: '#8ec07c' },
|
||||||
|
{ tag: [t.variableName], color: '#83a598' },
|
||||||
|
{ tag: [t.function(t.variableName)], color: '#8ec07c', fontStyle: 'bold' },
|
||||||
|
{ tag: [t.labelName], color: '#ebdbb2' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#d3869b' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#ebdbb2' },
|
||||||
|
{ tag: [t.brace], color: '#ebdbb2' },
|
||||||
|
{ tag: [t.annotation], color: '#fb4934d' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#d3869b' },
|
||||||
|
{ tag: [t.typeName, t.className], color: '#fabd2f' },
|
||||||
|
{ tag: [t.operatorKeyword], color: '#fb4934' },
|
||||||
|
{
|
||||||
|
tag: [t.tagName],
|
||||||
|
color: '#8ec07c',
|
||||||
|
fontStyle: 'bold',
|
||||||
|
},
|
||||||
|
{ tag: [t.squareBracket], color: '#fe8019' },
|
||||||
|
{ tag: [t.angleBracket], color: '#83a598' },
|
||||||
|
{ tag: [t.attributeName], color: '#8ec07c' },
|
||||||
|
{ tag: [t.regexp], color: '#8ec07c' },
|
||||||
|
{ tag: [t.quote], color: '#928374' },
|
||||||
|
{ tag: [t.string], color: '#ebdbb2' },
|
||||||
|
{
|
||||||
|
tag: t.link,
|
||||||
|
color: '#a89984',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
textUnderlinePosition: 'under',
|
||||||
|
},
|
||||||
|
{ tag: [t.url, t.escape, t.special(t.string)], color: '#d3869b' },
|
||||||
|
{ tag: [t.meta], color: '#fabd2f' },
|
||||||
|
{ tag: [t.comment], color: '#928374', fontStyle: 'italic' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold', color: '#fe8019' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic', color: '#b8bb26' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#b8bb26' },
|
||||||
|
{ tag: [t.heading1, t.heading2], fontWeight: 'bold', color: '#b8bb26' },
|
||||||
|
{
|
||||||
|
tag: [t.heading3, t.heading4],
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#fabd2f',
|
||||||
|
},
|
||||||
|
{ tag: [t.heading5, t.heading6], color: '#fabd2f' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#d3869b' },
|
||||||
|
{ tag: [t.processingInstruction, t.inserted], color: '#83a598' },
|
||||||
|
{ tag: [t.contentSeparator], color: '#fb4934' },
|
||||||
|
{ tag: t.invalid, color: '#fe8019', borderBottom: `1px dotted #fb4934d` },
|
||||||
|
],
|
||||||
|
});
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* gruvbox-light
|
||||||
|
* author morhetz
|
||||||
|
* From github.com/codemirror/codemirror5/blob/master/theme/gruvbox-light.css
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#fbf1c7',
|
||||||
|
lineBackground: '#fbf1c799',
|
||||||
|
foreground: '#3c3836',
|
||||||
|
caret: '#af3a03',
|
||||||
|
selection: '#ebdbb2',
|
||||||
|
selectionMatch: '#bdae93',
|
||||||
|
lineHighlight: '#ebdbb2',
|
||||||
|
gutterBackground: '#ebdbb2',
|
||||||
|
gutterForeground: '#665c54',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#fbf1c7',
|
||||||
|
foreground: '#3c3836',
|
||||||
|
caret: '#af3a03',
|
||||||
|
selection: '#bdae9391',
|
||||||
|
selectionMatch: '#bdae9391',
|
||||||
|
lineHighlight: '#a37f2238',
|
||||||
|
gutterBackground: '#ebdbb2',
|
||||||
|
gutterForeground: '#665c54',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#9d0006' },
|
||||||
|
{
|
||||||
|
tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
|
||||||
|
color: '#427b58',
|
||||||
|
},
|
||||||
|
{ tag: [t.variableName], color: '#076678' },
|
||||||
|
{ tag: [t.function(t.variableName)], color: '#79740e', fontStyle: 'bold' },
|
||||||
|
{ tag: [t.labelName], color: '#3c3836' },
|
||||||
|
{
|
||||||
|
tag: [t.color, t.constant(t.name), t.standard(t.name)],
|
||||||
|
color: '#8f3f71',
|
||||||
|
},
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#3c3836' },
|
||||||
|
{ tag: [t.brace], color: '#3c3836' },
|
||||||
|
{
|
||||||
|
tag: [t.annotation],
|
||||||
|
color: '#9d0006',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
|
||||||
|
color: '#8f3f71',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.typeName, t.className],
|
||||||
|
color: '#b57614',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.operator, t.operatorKeyword],
|
||||||
|
color: '#9d0006',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.tagName],
|
||||||
|
color: '#427b58',
|
||||||
|
fontStyle: 'bold',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.squareBracket],
|
||||||
|
color: '#af3a03',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.angleBracket],
|
||||||
|
color: '#076678',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.attributeName],
|
||||||
|
color: '#427b58',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.regexp],
|
||||||
|
color: '#427b58',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.quote],
|
||||||
|
color: '#928374',
|
||||||
|
},
|
||||||
|
{ tag: [t.string], color: '#3c3836' },
|
||||||
|
{
|
||||||
|
tag: t.link,
|
||||||
|
color: '#7c6f64',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
textUnderlinePosition: 'under',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.url, t.escape, t.special(t.string)],
|
||||||
|
color: '#8f3f71',
|
||||||
|
},
|
||||||
|
{ tag: [t.meta], color: '#b57614' },
|
||||||
|
{ tag: [t.comment], color: '#928374', fontStyle: 'italic' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold', color: '#af3a03' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic', color: '#79740e' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#79740e' },
|
||||||
|
{ tag: [t.heading1, t.heading2], fontWeight: 'bold', color: '#79740e' },
|
||||||
|
{
|
||||||
|
tag: [t.heading3, t.heading4],
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#b57614',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.heading5, t.heading6],
|
||||||
|
color: '#b57614',
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#8f3f71' },
|
||||||
|
{
|
||||||
|
tag: [t.processingInstruction, t.inserted],
|
||||||
|
color: '#076678',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: [t.contentSeparator],
|
||||||
|
color: '#9d0006',
|
||||||
|
},
|
||||||
|
{ tag: t.invalid, color: '#af3a03', borderBottom: `1px dotted #9d0006` },
|
||||||
|
],
|
||||||
|
});
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#212121',
|
||||||
|
lineBackground: '#21212199',
|
||||||
|
foreground: '#bdbdbd',
|
||||||
|
caret: '#a0a4ae',
|
||||||
|
selection: '#d7d4f0',
|
||||||
|
selectionMatch: '#d7d4f0',
|
||||||
|
gutterBackground: '#212121',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
gutterActiveForeground: '#4f5b66',
|
||||||
|
lineHighlight: '#111111',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#212121',
|
||||||
|
foreground: '#bdbdbd',
|
||||||
|
caret: '#a0a4ae',
|
||||||
|
selection: '#d7d4f063',
|
||||||
|
selectionMatch: '#d7d4f063',
|
||||||
|
gutterBackground: '#212121',
|
||||||
|
gutterForeground: '#999',
|
||||||
|
gutterActiveForeground: '#4f5b66',
|
||||||
|
lineHighlight: '#333333',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#cf6edf' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#56c8d8' },
|
||||||
|
{ tag: [t.propertyName], color: '#82AAFF' },
|
||||||
|
{ tag: [t.variableName], color: '#bdbdbd' },
|
||||||
|
{ tag: [t.function(t.variableName)], color: '#82AAFF' },
|
||||||
|
{ tag: [t.labelName], color: '#cf6edf' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#facf4e' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#56c8d8' },
|
||||||
|
{ tag: [t.brace], color: '#cf6edf' },
|
||||||
|
{ tag: [t.annotation], color: '#f07178' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#f07178' },
|
||||||
|
{ tag: [t.typeName, t.className], color: '#f07178' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#82AAFF' },
|
||||||
|
{ tag: [t.tagName], color: '#99d066' },
|
||||||
|
{ tag: [t.squareBracket], color: '#f07178' },
|
||||||
|
{ tag: [t.angleBracket], color: '#606f7a' },
|
||||||
|
{ tag: [t.attributeName], color: '#bdbdbd' },
|
||||||
|
{ tag: [t.regexp], color: '#f07178' },
|
||||||
|
{ tag: [t.quote], color: '#6abf69' },
|
||||||
|
{ tag: [t.string], color: '#99d066' },
|
||||||
|
{
|
||||||
|
tag: t.link,
|
||||||
|
color: '#56c8d8',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
textUnderlinePosition: 'under',
|
||||||
|
},
|
||||||
|
{ tag: [t.url, t.escape, t.special(t.string)], color: '#facf4e' },
|
||||||
|
{ tag: [t.meta], color: '#707d8b' },
|
||||||
|
{ tag: [t.comment], color: '#707d8b', fontStyle: 'italic' },
|
||||||
|
{ tag: t.monospace, color: '#bdbdbd' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold', color: '#f07178' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic', color: '#99d066' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#facf4e' },
|
||||||
|
{ tag: t.heading1, fontWeight: 'bold', color: '#facf4e' },
|
||||||
|
{
|
||||||
|
tag: [t.heading2, t.heading3, t.heading4],
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#facf4e',
|
||||||
|
},
|
||||||
|
{ tag: [t.heading5, t.heading6], color: '#facf4e' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#56c8d8' },
|
||||||
|
{ tag: [t.processingInstruction, t.inserted], color: '#f07178' },
|
||||||
|
{ tag: [t.contentSeparator], color: '#56c8d8' },
|
||||||
|
{ tag: t.invalid, color: '#606f7a', borderBottom: `1px dotted #f07178` },
|
||||||
|
],
|
||||||
|
});
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#FAFAFA',
|
||||||
|
lineBackground: '#FAFAFA99',
|
||||||
|
foreground: '#90A4AE',
|
||||||
|
caret: '#272727',
|
||||||
|
selection: '#80CBC440',
|
||||||
|
selectionMatch: '#FAFAFA',
|
||||||
|
gutterBackground: '#FAFAFA',
|
||||||
|
gutterForeground: '#90A4AE',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#CCD7DA50',
|
||||||
|
};
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#FAFAFA',
|
||||||
|
foreground: '#90A4AE',
|
||||||
|
caret: '#272727',
|
||||||
|
selection: '#80CBC440',
|
||||||
|
selectionMatch: '#80CBC440',
|
||||||
|
gutterBackground: '#FAFAFA',
|
||||||
|
gutterForeground: '#90A4AE',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#CCD7DA50',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#39ADB5' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#90A4AE' },
|
||||||
|
{ tag: [t.propertyName], color: '#6182B8' },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: '#91B859' },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: '#6182B8' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#39ADB5' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#90A4AE' },
|
||||||
|
{ tag: [t.className], color: '#E2931D' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#F76D47' },
|
||||||
|
{ tag: [t.typeName], color: '#E2931D', fontStyle: '#E2931D' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#39ADB5' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#91B859' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#90A4AE' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#39ADB5' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#90A4AE' },
|
||||||
|
{ tag: t.invalid, color: '#E5393570' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#272822',
|
||||||
|
lineBackground: '#27282299',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#49483E',
|
||||||
|
selectionMatch: '#49483E',
|
||||||
|
gutterBackground: '#272822',
|
||||||
|
gutterForeground: '#FFFFFF70',
|
||||||
|
lineHighlight: '#00000059',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#272822',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#49483E',
|
||||||
|
selectionMatch: '#49483E',
|
||||||
|
gutterBackground: '#272822',
|
||||||
|
gutterForeground: '#FFFFFF70',
|
||||||
|
lineHighlight: '#0000003b',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.labelName, color: '#bababa' },
|
||||||
|
{ tag: [t.comment, t.documentMeta], color: '#8292a2' },
|
||||||
|
{ tag: [t.number, t.bool, t.null, t.atom], color: '#ae81ff' },
|
||||||
|
{ tag: [t.attributeValue, t.className, t.name], color: '#e6db74' },
|
||||||
|
{ tag: [t.propertyName, t.attributeName], color: '#a6e22e' },
|
||||||
|
{ tag: [t.variableName], color: '#9effff' },
|
||||||
|
{ tag: [t.squareBracket], color: '#bababa' },
|
||||||
|
{ tag: [t.string, t.special(t.brace)], color: '#e6db74' },
|
||||||
|
{ tag: [t.regexp, t.className, t.typeName, t.definition(t.typeName)], color: '#66d9ef' },
|
||||||
|
{
|
||||||
|
tag: [t.definition(t.variableName), t.definition(t.propertyName), t.function(t.variableName)],
|
||||||
|
color: '#a6e22e',
|
||||||
|
},
|
||||||
|
// { tag: t.keyword, color: '#f92672' },
|
||||||
|
{ tag: [t.keyword, t.definitionKeyword, t.modifier, t.tagName, t.angleBracket], color: '#f92672' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#f2f1f8',
|
||||||
|
lineBackground: '#f2f1f899',
|
||||||
|
foreground: '#0c006b',
|
||||||
|
caret: '#5c49e9',
|
||||||
|
selection: '#d5d1f2',
|
||||||
|
selectionMatch: '#d5d1f2',
|
||||||
|
gutterBackground: '#f2f1f8',
|
||||||
|
gutterForeground: '#0c006b70',
|
||||||
|
lineHighlight: '#e1def3',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#f2f1f8',
|
||||||
|
foreground: '#0c006b',
|
||||||
|
caret: '#5c49e9',
|
||||||
|
selection: '#d5d1f2',
|
||||||
|
selectionMatch: '#d5d1f2',
|
||||||
|
gutterBackground: '#f2f1f8',
|
||||||
|
gutterForeground: '#0c006b70',
|
||||||
|
lineHighlight: '#16067911',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.comment, color: '#9995b7' },
|
||||||
|
{
|
||||||
|
tag: t.keyword,
|
||||||
|
color: '#ff5792',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
{ tag: [t.definitionKeyword, t.modifier], color: '#ff5792' },
|
||||||
|
{ tag: [t.className, t.tagName, t.definition(t.typeName)], color: '#0094f0' },
|
||||||
|
{ tag: [t.number, t.bool, t.null, t.special(t.brace)], color: '#5842ff' },
|
||||||
|
{ tag: [t.definition(t.propertyName), t.function(t.variableName)], color: '#0095a8' },
|
||||||
|
{ tag: t.typeName, color: '#b3694d' },
|
||||||
|
{ tag: [t.propertyName, t.variableName], color: '#fa8900' },
|
||||||
|
{ tag: t.operator, color: '#ff5792' },
|
||||||
|
{ tag: t.self, color: '#e64100' },
|
||||||
|
{ tag: [t.string, t.regexp], color: '#00b368' },
|
||||||
|
{ tag: [t.paren, t.bracket], color: '#0431fa' },
|
||||||
|
{ tag: t.labelName, color: '#00bdd6' },
|
||||||
|
{ tag: t.attributeName, color: '#e64100' },
|
||||||
|
{ tag: t.angleBracket, color: '#9995b7' },
|
||||||
|
],
|
||||||
|
});
|
||||||
Vendored
+78
@@ -0,0 +1,78 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#2e3440',
|
||||||
|
lineBackground: '#2e344099',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#3b4252',
|
||||||
|
selectionMatch: '#e5e9f0',
|
||||||
|
gutterBackground: '#2e3440',
|
||||||
|
gutterForeground: '#4c566a',
|
||||||
|
gutterActiveForeground: '#d8dee9',
|
||||||
|
lineHighlight: '#4c566a',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Colors from https://www.nordtheme.com/docs/colors-and-palettes
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#2e3440',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FFFFFF',
|
||||||
|
selection: '#00000073',
|
||||||
|
selectionMatch: '#00000073',
|
||||||
|
gutterBackground: '#2e3440',
|
||||||
|
gutterForeground: '#4c566a',
|
||||||
|
gutterActiveForeground: '#d8dee9',
|
||||||
|
lineHighlight: '#4c566a29',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#5e81ac' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], color: '#88c0d0' },
|
||||||
|
{ tag: [t.variableName], color: '#8fbcbb' },
|
||||||
|
{ tag: [t.function(t.variableName)], color: '#8fbcbb' },
|
||||||
|
{ tag: [t.labelName], color: '#81a1c1' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#5e81ac' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#a3be8c' },
|
||||||
|
{ tag: [t.brace], color: '#8fbcbb' },
|
||||||
|
{ tag: [t.annotation], color: '#d30102' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#b48ead' },
|
||||||
|
{ tag: [t.typeName, t.className], color: '#ebcb8b' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#a3be8c' },
|
||||||
|
{ tag: [t.tagName], color: '#b48ead' },
|
||||||
|
{ tag: [t.squareBracket], color: '#bf616a' },
|
||||||
|
{ tag: [t.angleBracket], color: '#d08770' },
|
||||||
|
{ tag: [t.attributeName], color: '#ebcb8b' },
|
||||||
|
{ tag: [t.regexp], color: '#5e81ac' },
|
||||||
|
{ tag: [t.quote], color: '#b48ead' },
|
||||||
|
{ tag: [t.string], color: '#a3be8c' },
|
||||||
|
{
|
||||||
|
tag: t.link,
|
||||||
|
color: '#a3be8c',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
textUnderlinePosition: 'under',
|
||||||
|
},
|
||||||
|
{ tag: [t.url, t.escape, t.special(t.string)], color: '#8fbcbb' },
|
||||||
|
{ tag: [t.meta], color: '#88c0d0' },
|
||||||
|
{ tag: [t.monospace], color: '#d8dee9', fontStyle: 'italic' },
|
||||||
|
{ tag: [t.comment], color: '#4c566a', fontStyle: 'italic' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold', color: '#5e81ac' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic', color: '#5e81ac' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#5e81ac' },
|
||||||
|
{ tag: t.special(t.heading1), fontWeight: 'bold', color: '#5e81ac' },
|
||||||
|
{ tag: t.heading1, fontWeight: 'bold', color: '#5e81ac' },
|
||||||
|
{
|
||||||
|
tag: [t.heading2, t.heading3, t.heading4],
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#5e81ac',
|
||||||
|
},
|
||||||
|
{ tag: [t.heading5, t.heading6], color: '#5e81ac' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#d08770' },
|
||||||
|
{ tag: [t.processingInstruction, t.inserted], color: '#8fbcbb' },
|
||||||
|
{ tag: [t.contentSeparator], color: '#ebcb8b' },
|
||||||
|
{ tag: t.invalid, color: '#434c5e', borderBottom: `1px dotted #d30102` },
|
||||||
|
],
|
||||||
|
});
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Atom One
|
||||||
|
* Atom One dark syntax theme
|
||||||
|
*
|
||||||
|
* https://github.com/atom/one-dark-syntax
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = ['#000000', '#ff5356', '#bd312a', '#54636D', '#171717'];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: hex[0],
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[2],
|
||||||
|
selection: hex[4],
|
||||||
|
selectionMatch: hex[0],
|
||||||
|
gutterBackground: hex[0],
|
||||||
|
gutterForeground: hex[3],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[2],
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: hex[1] },
|
||||||
|
{ tag: t.comment, color: hex[3] },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: hex[2] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[1] },
|
||||||
|
{ tag: t.keyword, color: hex[2] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[1] },
|
||||||
|
],
|
||||||
|
});
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#002b36',
|
||||||
|
lineBackground: '#002b3699',
|
||||||
|
foreground: '#93a1a1',
|
||||||
|
caret: '#839496',
|
||||||
|
selection: '#173541',
|
||||||
|
selectionMatch: '#aafe661a',
|
||||||
|
gutterBackground: '#00252f',
|
||||||
|
gutterForeground: '#839496',
|
||||||
|
lineHighlight: '#173541',
|
||||||
|
};
|
||||||
|
|
||||||
|
const c = {
|
||||||
|
background: '#002B36',
|
||||||
|
foreground: '#839496',
|
||||||
|
selection: '#004454AA',
|
||||||
|
selectionMatch: '#005A6FAA',
|
||||||
|
cursor: '#D30102',
|
||||||
|
dropdownBackground: '#00212B',
|
||||||
|
dropdownBorder: '#2AA19899',
|
||||||
|
activeLine: '#00cafe11',
|
||||||
|
matchingBracket: '#073642',
|
||||||
|
keyword: '#859900',
|
||||||
|
storage: '#93A1A1',
|
||||||
|
variable: '#268BD2',
|
||||||
|
parameter: '#268BD2',
|
||||||
|
function: '#268BD2',
|
||||||
|
string: '#2AA198',
|
||||||
|
constant: '#CB4B16',
|
||||||
|
type: '#859900',
|
||||||
|
class: '#268BD2',
|
||||||
|
number: '#D33682',
|
||||||
|
comment: '#586E75',
|
||||||
|
heading: '#268BD2',
|
||||||
|
invalid: '#DC322F',
|
||||||
|
regexp: '#DC322F',
|
||||||
|
tag: '#268BD2',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: c.background,
|
||||||
|
foreground: c.foreground,
|
||||||
|
caret: c.cursor,
|
||||||
|
selection: c.selection,
|
||||||
|
selectionMatch: c.selection,
|
||||||
|
gutterBackground: c.background,
|
||||||
|
gutterForeground: c.foreground,
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: c.activeLine,
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: c.keyword },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: c.variable },
|
||||||
|
{ tag: [t.propertyName], color: c.function },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: c.string },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: c.function },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: c.constant },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: c.variable },
|
||||||
|
{ tag: [t.className], color: c.class },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: c.number },
|
||||||
|
{ tag: [t.typeName], color: c.type, fontStyle: c.type },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: c.keyword },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: c.regexp },
|
||||||
|
{ tag: [t.meta, t.comment], color: c.comment },
|
||||||
|
{ tag: t.tagName, color: c.tag },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: c.heading },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: c.variable },
|
||||||
|
{ tag: t.invalid, color: c.invalid },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
// this is slightly different from https://thememirror.net/solarized-light
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#fdf6e3',
|
||||||
|
lineBackground: '#fdf6e399',
|
||||||
|
foreground: '#657b83',
|
||||||
|
caret: '#586e75',
|
||||||
|
selection: '#dfd9c8',
|
||||||
|
selectionMatch: '#dfd9c8',
|
||||||
|
gutterBackground: '#00000010',
|
||||||
|
gutterForeground: '#657b83',
|
||||||
|
lineHighlight: '#dfd9c8',
|
||||||
|
};
|
||||||
|
|
||||||
|
const c = {
|
||||||
|
background: '#FDF6E3',
|
||||||
|
foreground: '#657B83',
|
||||||
|
selection: '#EEE8D5',
|
||||||
|
selectionMatch: '#EEE8D5',
|
||||||
|
cursor: '#657B83',
|
||||||
|
dropdownBackground: '#EEE8D5',
|
||||||
|
dropdownBorder: '#D3AF86',
|
||||||
|
activeLine: '#3d392d11',
|
||||||
|
matchingBracket: '#EEE8D5',
|
||||||
|
keyword: '#859900',
|
||||||
|
storage: '#586E75',
|
||||||
|
variable: '#268BD2',
|
||||||
|
parameter: '#268BD2',
|
||||||
|
function: '#268BD2',
|
||||||
|
string: '#2AA198',
|
||||||
|
constant: '#CB4B16',
|
||||||
|
type: '#859900',
|
||||||
|
class: '#268BD2',
|
||||||
|
number: '#D33682',
|
||||||
|
comment: '#93A1A1',
|
||||||
|
heading: '#268BD2',
|
||||||
|
invalid: '#DC322F',
|
||||||
|
regexp: '#DC322F',
|
||||||
|
tag: '#268BD2',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: c.background,
|
||||||
|
foreground: c.foreground,
|
||||||
|
caret: c.cursor,
|
||||||
|
selection: c.selection,
|
||||||
|
selectionMatch: c.selectionMatch,
|
||||||
|
gutterBackground: c.background,
|
||||||
|
gutterForeground: c.foreground,
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: c.activeLine,
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: c.keyword },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: c.variable },
|
||||||
|
{ tag: [t.propertyName], color: c.function },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: c.string },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: c.function },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: c.constant },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: c.variable },
|
||||||
|
{ tag: [t.className], color: c.class },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: c.number },
|
||||||
|
{ tag: [t.typeName], color: c.type, fontStyle: c.type },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: c.keyword },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: c.regexp },
|
||||||
|
{ tag: [t.meta, t.comment], color: c.comment },
|
||||||
|
{ tag: t.tagName, color: c.tag },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: c.heading },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: c.variable },
|
||||||
|
{ tag: t.invalid, color: c.invalid },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Atom One
|
||||||
|
* Atom One dark syntax theme
|
||||||
|
*
|
||||||
|
* https://github.com/atom/one-dark-syntax
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = ['#1e1e1e', '#fbde2d', '#ff1493', '#4c83ff', '#ededed', '#cccccc', '#ffffff30', '#dc2f8c'];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#000000',
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[4],
|
||||||
|
selection: hex[6],
|
||||||
|
gutterBackground: hex[0],
|
||||||
|
gutterForeground: hex[5],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[4],
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: hex[3] },
|
||||||
|
|
||||||
|
{ tag: t.comment, color: '#54636D' },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: hex[4] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[3] },
|
||||||
|
{ tag: t.keyword, color: hex[1] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[2] },
|
||||||
|
],
|
||||||
|
});
|
||||||
+16
-13
@@ -1,20 +1,23 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#222',
|
||||||
|
lineBackground: '#22222299',
|
||||||
|
foreground: '#fff',
|
||||||
|
caret: '#ffcc00',
|
||||||
|
selection: 'rgba(128, 203, 196, 0.5)',
|
||||||
|
selectionMatch: '#036dd626',
|
||||||
|
lineHighlight: '#00000050',
|
||||||
|
gutterBackground: 'transparent',
|
||||||
|
gutterForeground: '#8a919966',
|
||||||
|
};
|
||||||
|
|
||||||
export default createTheme({
|
export default createTheme({
|
||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
settings: {
|
settings,
|
||||||
background: '#222',
|
|
||||||
foreground: '#75baff', // whats that?
|
|
||||||
caret: '#ffcc00',
|
|
||||||
selection: 'rgba(128, 203, 196, 0.5)',
|
|
||||||
selectionMatch: '#036dd626',
|
|
||||||
// lineHighlight: '#8a91991a', // original
|
|
||||||
lineHighlight: '#00000050',
|
|
||||||
gutterBackground: 'transparent',
|
|
||||||
// gutterForeground: '#8a919966',
|
|
||||||
gutterForeground: '#8a919966',
|
|
||||||
},
|
|
||||||
styles: [
|
styles: [
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#89ddff' },
|
||||||
{ tag: t.labelName, color: '#89ddff' },
|
{ tag: t.labelName, color: '#89ddff' },
|
||||||
{ tag: t.keyword, color: '#c792ea' },
|
{ tag: t.keyword, color: '#c792ea' },
|
||||||
{ tag: t.operator, color: '#89ddff' },
|
{ tag: t.operator, color: '#89ddff' },
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#303841',
|
||||||
|
lineBackground: '#30384199',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FBAC52',
|
||||||
|
selection: '#4C5964',
|
||||||
|
selectionMatch: '#3A546E',
|
||||||
|
gutterBackground: '#303841',
|
||||||
|
gutterForeground: '#FFFFFF70',
|
||||||
|
lineHighlight: '#00000059',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#303841',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
|
caret: '#FBAC52',
|
||||||
|
selection: '#4C5964',
|
||||||
|
selectionMatch: '#3A546E',
|
||||||
|
gutterBackground: '#303841',
|
||||||
|
gutterForeground: '#FFFFFF70',
|
||||||
|
lineHighlight: '#00000059',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.labelName, color: '#A2A9B5' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#A2A9B5' },
|
||||||
|
{ tag: [t.attributeName, t.keyword], color: '#B78FBA' },
|
||||||
|
{ tag: t.function(t.variableName), color: '#5AB0B0' },
|
||||||
|
{ tag: [t.string, t.regexp, t.attributeValue], color: '#99C592' },
|
||||||
|
{ tag: t.operator, color: '#f47954' },
|
||||||
|
// { tag: t.moduleKeyword, color: 'red' },
|
||||||
|
{ tag: [t.tagName, t.modifier], color: '#E35F63' },
|
||||||
|
{ tag: [t.number, t.definition(t.tagName), t.className, t.definition(t.variableName)], color: '#fbac52' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#E35F63' },
|
||||||
|
{ tag: t.variableName, color: '#539ac4' },
|
||||||
|
{ tag: [t.propertyName, t.typeName], color: '#629ccd' },
|
||||||
|
{ tag: t.propertyName, color: '#36b7b5' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
let colorA = '#6edee4';
|
let colorA = '#6edee4';
|
||||||
//let colorB = 'magenta';
|
//let colorB = 'magenta';
|
||||||
@@ -17,7 +17,7 @@ export const settings = {
|
|||||||
lineBackground: '#00000040',
|
lineBackground: '#00000040',
|
||||||
gutterBackground: 'transparent',
|
gutterBackground: 'transparent',
|
||||||
gutterForeground: '#8a919966',
|
gutterForeground: '#8a919966',
|
||||||
customStyle: '.cm-line { line-height: 1 }',
|
// customStyle: '.cm-line { line-height: 1 }',
|
||||||
};
|
};
|
||||||
|
|
||||||
let punctuation = colorD;
|
let punctuation = colorD;
|
||||||
|
|||||||
+20
-20
@@ -1,5 +1,5 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
export const settings = {
|
export const settings = {
|
||||||
background: 'black',
|
background: 'black',
|
||||||
foreground: '#41FF00', // whats that?
|
foreground: '#41FF00', // whats that?
|
||||||
@@ -14,24 +14,24 @@ export default createTheme({
|
|||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
settings,
|
settings,
|
||||||
styles: [
|
styles: [
|
||||||
{ tag: t.labelName, color: '#41FF00' },
|
{ tag: t.labelName, color: 'inherit' },
|
||||||
{ tag: t.keyword, color: '#41FF00' },
|
{ tag: t.keyword, color: 'inherit' },
|
||||||
{ tag: t.operator, color: '#41FF00' },
|
{ tag: t.operator, color: 'inherit' },
|
||||||
{ tag: t.special(t.variableName), color: '#41FF00' },
|
{ tag: t.special(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.typeName, color: '#41FF00' },
|
{ tag: t.typeName, color: 'inherit' },
|
||||||
{ tag: t.atom, color: '#41FF00' },
|
{ tag: t.atom, color: 'inherit' },
|
||||||
{ tag: t.number, color: '#41FF00' },
|
{ tag: t.number, color: 'inherit' },
|
||||||
{ tag: t.definition(t.variableName), color: '#41FF00' },
|
{ tag: t.definition(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.string, color: '#41FF00' },
|
{ tag: t.string, color: 'inherit' },
|
||||||
{ tag: t.special(t.string), color: '#41FF00' },
|
{ tag: t.special(t.string), color: 'inherit' },
|
||||||
{ tag: t.comment, color: '#41FF00' },
|
{ tag: t.comment, color: 'inherit' },
|
||||||
{ tag: t.variableName, color: '#41FF00' },
|
{ tag: t.variableName, color: 'inherit' },
|
||||||
{ tag: t.tagName, color: '#41FF00' },
|
{ tag: t.tagName, color: 'inherit' },
|
||||||
{ tag: t.bracket, color: '#41FF00' },
|
{ tag: t.bracket, color: 'inherit' },
|
||||||
{ tag: t.meta, color: '#41FF00' },
|
{ tag: t.meta, color: 'inherit' },
|
||||||
{ tag: t.attributeName, color: '#41FF00' },
|
{ tag: t.attributeName, color: 'inherit' },
|
||||||
{ tag: t.propertyName, color: '#41FF00' },
|
{ tag: t.propertyName, color: 'inherit' },
|
||||||
{ tag: t.className, color: '#41FF00' },
|
{ tag: t.className, color: 'inherit' },
|
||||||
{ tag: t.invalid, color: '#41FF00' },
|
{ tag: t.invalid, color: 'inherit' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
import { EditorView } from '@codemirror/view';
|
||||||
|
import { syntaxHighlighting } from '@codemirror/language';
|
||||||
|
import { HighlightStyle } from '@codemirror/language';
|
||||||
|
|
||||||
|
export const createTheme = ({ theme, settings, styles }) => {
|
||||||
|
const _theme = EditorView.theme(
|
||||||
|
{
|
||||||
|
'&': {
|
||||||
|
color: settings.foreground,
|
||||||
|
backgroundColor: settings.background,
|
||||||
|
},
|
||||||
|
'.cm-gutters': {
|
||||||
|
backgroundColor: settings.gutterBackground,
|
||||||
|
color: settings.gutterForeground,
|
||||||
|
//borderRightColor: settings.gutterBorder
|
||||||
|
},
|
||||||
|
'.cm-content': {
|
||||||
|
caretColor: settings.caret,
|
||||||
|
},
|
||||||
|
'.cm-cursor, .cm-dropCursor': {
|
||||||
|
borderLeftColor: settings.caret,
|
||||||
|
},
|
||||||
|
'.cm-activeLineGutter': {
|
||||||
|
// color: settings.gutterActiveForeground
|
||||||
|
backgroundColor: settings.lineHighlight,
|
||||||
|
},
|
||||||
|
'.cm-activeLine': {
|
||||||
|
backgroundColor: settings.lineHighlight,
|
||||||
|
},
|
||||||
|
'&.cm-focused .cm-selectionBackground, & .cm-line::selection, & .cm-selectionLayer .cm-selectionBackground, .cm-content ::selection':
|
||||||
|
{
|
||||||
|
background: settings.selection + ' !important',
|
||||||
|
},
|
||||||
|
'& .cm-selectionMatch': {
|
||||||
|
backgroundColor: settings.selectionMatch,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ dark: theme === 'dark' },
|
||||||
|
);
|
||||||
|
const highlightStyle = HighlightStyle.define(styles);
|
||||||
|
return [_theme, syntaxHighlighting(highlightStyle)];
|
||||||
|
};
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#24283b',
|
||||||
|
lineBackground: '#24283b99',
|
||||||
|
foreground: '#7982a9',
|
||||||
|
caret: '#c0caf5',
|
||||||
|
selection: '#6f7bb630',
|
||||||
|
selectionMatch: '#1f2335',
|
||||||
|
gutterBackground: '#24283b',
|
||||||
|
gutterForeground: '#7982a9',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#292e42',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#24283b',
|
||||||
|
foreground: '#7982a9',
|
||||||
|
caret: '#c0caf5',
|
||||||
|
selection: '#6f7bb630',
|
||||||
|
selectionMatch: '#343b5f',
|
||||||
|
gutterBackground: '#24283b',
|
||||||
|
gutterForeground: '#7982a9',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#292e427a',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#bb9af7' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#c0caf5' },
|
||||||
|
{ tag: [t.propertyName], color: '#7aa2f7' },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: '#9ece6a' },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: '#7aa2f7' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#bb9af7' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#c0caf5' },
|
||||||
|
{ tag: [t.className], color: '#c0caf5' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#ff9e64' },
|
||||||
|
{ tag: [t.typeName], color: '#2ac3de', fontStyle: '#2ac3de' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#bb9af7' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#b4f9f8' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#565f89' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#89ddff' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#c0caf5' },
|
||||||
|
{ tag: t.invalid, color: '#ff5370' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#1a1b26',
|
||||||
|
lineBackground: '#1a1b2699',
|
||||||
|
foreground: '#787c99',
|
||||||
|
caret: '#c0caf5',
|
||||||
|
selection: '#515c7e40',
|
||||||
|
selectionMatch: '#16161e',
|
||||||
|
gutterBackground: '#1a1b26',
|
||||||
|
gutterForeground: '#787c99',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#1e202e',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#1a1b26',
|
||||||
|
foreground: '#787c99',
|
||||||
|
caret: '#c0caf5',
|
||||||
|
selection: '#515c7e40',
|
||||||
|
selectionMatch: '#16161e',
|
||||||
|
gutterBackground: '#1a1b26',
|
||||||
|
gutterForeground: '#787c99',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#474b6611',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#bb9af7' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#c0caf5' },
|
||||||
|
{ tag: [t.propertyName], color: '#7aa2f7' },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: '#9ece6a' },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: '#7aa2f7' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#bb9af7' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#c0caf5' },
|
||||||
|
{ tag: [t.className], color: '#c0caf5' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#ff9e64' },
|
||||||
|
{ tag: [t.typeName], color: '#0db9d7' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#bb9af7' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#b4f9f8' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#444b6a' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#89ddff' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#c0caf5' },
|
||||||
|
{ tag: t.invalid, color: '#ff5370' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#e1e2e7',
|
||||||
|
lineBackground: '#e1e2e799',
|
||||||
|
foreground: '#3760bf',
|
||||||
|
caret: '#3760bf',
|
||||||
|
selection: '#99a7df',
|
||||||
|
selectionMatch: '#99a7df',
|
||||||
|
gutterBackground: '#e1e2e7',
|
||||||
|
gutterForeground: '#3760bf',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#5f5faf11',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#e1e2e7',
|
||||||
|
foreground: '#3760bf',
|
||||||
|
caret: '#3760bf',
|
||||||
|
selection: '#99a7df',
|
||||||
|
selectionMatch: '#99a7df',
|
||||||
|
gutterBackground: '#e1e2e7',
|
||||||
|
gutterForeground: '#3760bf',
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: '#5f5faf11',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: t.keyword, color: '#007197' },
|
||||||
|
{ tag: [t.name, t.deleted, t.character, t.macroName], color: '#3760bf' },
|
||||||
|
{ tag: [t.propertyName], color: '#3760bf' },
|
||||||
|
{ tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: '#587539' },
|
||||||
|
{ tag: [t.function(t.variableName), t.labelName], color: '#3760bf' },
|
||||||
|
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: '#3760bf' },
|
||||||
|
{ tag: [t.definition(t.name), t.separator], color: '#3760bf' },
|
||||||
|
{ tag: [t.className], color: '#3760bf' },
|
||||||
|
{ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: '#b15c00' },
|
||||||
|
{ tag: [t.typeName], color: '#007197', fontStyle: '#007197' },
|
||||||
|
{ tag: [t.operator, t.operatorKeyword], color: '#007197' },
|
||||||
|
{ tag: [t.url, t.escape, t.regexp, t.link], color: '#587539' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#848cb5' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.link, textDecoration: 'underline' },
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#b15c00' },
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: '#3760bf' },
|
||||||
|
{ tag: t.invalid, color: '#f52a65' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#1e1e1e',
|
||||||
|
lineBackground: '#1e1e1e99',
|
||||||
|
foreground: '#fff',
|
||||||
|
caret: '#c6c6c6',
|
||||||
|
selection: '#6199ff2f',
|
||||||
|
selectionMatch: '#72a1ff59',
|
||||||
|
lineHighlight: '#ffffff0f',
|
||||||
|
gutterBackground: '#1e1e1e',
|
||||||
|
gutterForeground: '#838383',
|
||||||
|
gutterActiveForeground: '#fff',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings: {
|
||||||
|
background: '#1e1e1e',
|
||||||
|
foreground: '#fff',
|
||||||
|
caret: '#c6c6c6',
|
||||||
|
selection: '#6199ff2f',
|
||||||
|
selectionMatch: '#72a1ff59',
|
||||||
|
lineHighlight: '#ffffff0f',
|
||||||
|
gutterBackground: '#1e1e1e',
|
||||||
|
gutterForeground: '#838383',
|
||||||
|
gutterActiveForeground: '#fff',
|
||||||
|
fontFamily: 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [
|
||||||
|
t.keyword,
|
||||||
|
t.operatorKeyword,
|
||||||
|
t.modifier,
|
||||||
|
t.color,
|
||||||
|
t.constant(t.name),
|
||||||
|
t.standard(t.name),
|
||||||
|
t.standard(t.tagName),
|
||||||
|
t.special(t.brace),
|
||||||
|
t.atom,
|
||||||
|
t.bool,
|
||||||
|
t.special(t.variableName),
|
||||||
|
],
|
||||||
|
color: '#569cd6',
|
||||||
|
},
|
||||||
|
{ tag: [t.controlKeyword, t.moduleKeyword], color: '#c586c0' },
|
||||||
|
{
|
||||||
|
tag: [
|
||||||
|
t.name,
|
||||||
|
t.deleted,
|
||||||
|
t.character,
|
||||||
|
t.macroName,
|
||||||
|
t.propertyName,
|
||||||
|
t.variableName,
|
||||||
|
t.labelName,
|
||||||
|
t.definition(t.name),
|
||||||
|
],
|
||||||
|
color: '#9cdcfe',
|
||||||
|
},
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#9cdcfe' },
|
||||||
|
{
|
||||||
|
tag: [t.typeName, t.className, t.tagName, t.number, t.changed, t.annotation, t.self, t.namespace],
|
||||||
|
color: '#4ec9b0',
|
||||||
|
},
|
||||||
|
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: '#dcdcaa' },
|
||||||
|
{ tag: [t.number], color: '#b5cea8' },
|
||||||
|
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape, t.regexp], color: '#d4d4d4' },
|
||||||
|
{ tag: [t.regexp], color: '#d16969' },
|
||||||
|
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: '#ce9178' },
|
||||||
|
{ tag: [t.angleBracket], color: '#808080' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#6a9955' },
|
||||||
|
{ tag: t.link, color: '#6a9955', textDecoration: 'underline' },
|
||||||
|
{ tag: t.invalid, color: '#ff0000' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: '#ffffff',
|
||||||
|
lineBackground: '#ffffff50',
|
||||||
|
foreground: '#383a42',
|
||||||
|
caret: '#000',
|
||||||
|
selection: '#add6ff',
|
||||||
|
selectionMatch: '#a8ac94',
|
||||||
|
lineHighlight: '#99999926',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#237893',
|
||||||
|
gutterActiveForeground: '#0b216f',
|
||||||
|
fontFamily: 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#ffffff',
|
||||||
|
foreground: '#383a42',
|
||||||
|
caret: '#000',
|
||||||
|
selection: '#add6ff',
|
||||||
|
selectionMatch: '#a8ac94',
|
||||||
|
lineHighlight: '#99999926',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#237893',
|
||||||
|
gutterActiveForeground: '#0b216f',
|
||||||
|
fontFamily: 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [
|
||||||
|
t.keyword,
|
||||||
|
t.operatorKeyword,
|
||||||
|
t.modifier,
|
||||||
|
t.color,
|
||||||
|
t.constant(t.name),
|
||||||
|
t.standard(t.name),
|
||||||
|
t.standard(t.tagName),
|
||||||
|
t.special(t.brace),
|
||||||
|
t.atom,
|
||||||
|
t.bool,
|
||||||
|
t.special(t.variableName),
|
||||||
|
],
|
||||||
|
color: '#0000ff',
|
||||||
|
},
|
||||||
|
{ tag: [t.moduleKeyword, t.controlKeyword], color: '#af00db' },
|
||||||
|
{
|
||||||
|
tag: [
|
||||||
|
t.name,
|
||||||
|
t.deleted,
|
||||||
|
t.character,
|
||||||
|
t.macroName,
|
||||||
|
t.propertyName,
|
||||||
|
t.variableName,
|
||||||
|
t.labelName,
|
||||||
|
t.definition(t.name),
|
||||||
|
],
|
||||||
|
color: '#0070c1',
|
||||||
|
},
|
||||||
|
{ tag: t.heading, fontWeight: 'bold', color: '#0070c1' },
|
||||||
|
{
|
||||||
|
tag: [t.typeName, t.className, t.tagName, t.number, t.changed, t.annotation, t.self, t.namespace],
|
||||||
|
color: '#267f99',
|
||||||
|
},
|
||||||
|
{ tag: [t.function(t.variableName), t.function(t.propertyName)], color: '#795e26' },
|
||||||
|
{ tag: [t.number], color: '#098658' },
|
||||||
|
{ tag: [t.operator, t.punctuation, t.separator, t.url, t.escape, t.regexp], color: '#383a42' },
|
||||||
|
{ tag: [t.regexp], color: '#af00db' },
|
||||||
|
{ tag: [t.special(t.string), t.processingInstruction, t.string, t.inserted], color: '#a31515' },
|
||||||
|
{ tag: [t.angleBracket], color: '#383a42' },
|
||||||
|
{ tag: t.strong, fontWeight: 'bold' },
|
||||||
|
{ tag: t.emphasis, fontStyle: 'italic' },
|
||||||
|
{ tag: t.strikethrough, textDecoration: 'line-through' },
|
||||||
|
{ tag: [t.meta, t.comment], color: '#008000' },
|
||||||
|
{ tag: t.link, color: '#4078f2', textDecoration: 'underline' },
|
||||||
|
{ tag: t.invalid, color: '#e45649' },
|
||||||
|
],
|
||||||
|
});
|
||||||
+20
-20
@@ -1,5 +1,5 @@
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import { createTheme } from '@uiw/codemirror-themes';
|
import { createTheme } from './theme-helper.mjs';
|
||||||
export const settings = {
|
export const settings = {
|
||||||
background: 'white',
|
background: 'white',
|
||||||
foreground: 'black', // whats that?
|
foreground: 'black', // whats that?
|
||||||
@@ -16,24 +16,24 @@ export default createTheme({
|
|||||||
theme: 'light',
|
theme: 'light',
|
||||||
settings,
|
settings,
|
||||||
styles: [
|
styles: [
|
||||||
{ tag: t.labelName, color: 'black' },
|
{ tag: t.labelName, color: 'inherit' },
|
||||||
{ tag: t.keyword, color: 'black' },
|
{ tag: t.keyword, color: 'inherit' },
|
||||||
{ tag: t.operator, color: 'black' },
|
{ tag: t.operator, color: 'inherit' },
|
||||||
{ tag: t.special(t.variableName), color: 'black' },
|
{ tag: t.special(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.typeName, color: 'black' },
|
{ tag: t.typeName, color: 'inherit' },
|
||||||
{ tag: t.atom, color: 'black' },
|
{ tag: t.atom, color: 'inherit' },
|
||||||
{ tag: t.number, color: 'black' },
|
{ tag: t.number, color: 'inherit' },
|
||||||
{ tag: t.definition(t.variableName), color: 'black' },
|
{ tag: t.definition(t.variableName), color: 'inherit' },
|
||||||
{ tag: t.string, color: 'black' },
|
{ tag: t.string, color: 'inherit' },
|
||||||
{ tag: t.special(t.string), color: 'black' },
|
{ tag: t.special(t.string), color: 'inherit' },
|
||||||
{ tag: t.comment, color: 'black' },
|
{ tag: t.comment, color: 'inherit' },
|
||||||
{ tag: t.variableName, color: 'black' },
|
{ tag: t.variableName, color: 'inherit' },
|
||||||
{ tag: t.tagName, color: 'black' },
|
{ tag: t.tagName, color: 'inherit' },
|
||||||
{ tag: t.bracket, color: 'black' },
|
{ tag: t.bracket, color: 'inherit' },
|
||||||
{ tag: t.meta, color: 'black' },
|
{ tag: t.meta, color: 'inherit' },
|
||||||
{ tag: t.attributeName, color: 'black' },
|
{ tag: t.attributeName, color: 'inherit' },
|
||||||
{ tag: t.propertyName, color: 'black' },
|
{ tag: t.propertyName, color: 'inherit' },
|
||||||
{ tag: t.className, color: 'black' },
|
{ tag: t.className, color: 'inherit' },
|
||||||
{ tag: t.invalid, color: 'black' },
|
{ tag: t.invalid, color: 'inherit' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
light: true,
|
||||||
|
background: '#fff',
|
||||||
|
lineBackground: '#ffffff99',
|
||||||
|
foreground: '#3D3D3D',
|
||||||
|
selection: '#BBDFFF',
|
||||||
|
selectionMatch: '#BBDFFF',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#AFAFAF',
|
||||||
|
lineHighlight: '#EDF4FF',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'light',
|
||||||
|
settings: {
|
||||||
|
background: '#fff',
|
||||||
|
foreground: '#3D3D3D',
|
||||||
|
selection: '#BBDFFF',
|
||||||
|
selectionMatch: '#BBDFFF',
|
||||||
|
gutterBackground: '#fff',
|
||||||
|
gutterForeground: '#AFAFAF',
|
||||||
|
lineHighlight: '#d5e6ff69',
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: [t.comment, t.quote], color: '#707F8D' },
|
||||||
|
{ tag: [t.typeName, t.typeOperator], color: '#aa0d91' },
|
||||||
|
{ tag: [t.keyword], color: '#aa0d91', fontWeight: 'bold' },
|
||||||
|
{ tag: [t.string, t.meta], color: '#D23423' },
|
||||||
|
{ tag: [t.name], color: '#032f62' },
|
||||||
|
{ tag: [t.typeName], color: '#522BB2' },
|
||||||
|
{ tag: [t.variableName], color: '#23575C' },
|
||||||
|
{ tag: [t.definition(t.variableName)], color: '#327A9E' },
|
||||||
|
{ tag: [t.regexp, t.link], color: '#0e0eff' },
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -133,3 +133,10 @@ registerWidget('_pitchwheel', (id, options = {}, pat) => {
|
|||||||
const ctx = getCanvasWidget(id, options).getContext('2d');
|
const ctx = getCanvasWidget(id, options).getContext('2d');
|
||||||
return pat.pitchwheel({ ...options, ctx, id });
|
return pat.pitchwheel({ ...options, ctx, id });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerWidget('_spectrum', (id, options = {}, pat) => {
|
||||||
|
let _size = options.size || 200;
|
||||||
|
options = { width: _size, height: _size, ...options, size: _size / 5 };
|
||||||
|
const ctx = getCanvasWidget(id, options).getContext('2d');
|
||||||
|
return pat.spectrum({ ...options, ctx, id });
|
||||||
|
});
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { describe, bench } from 'vitest';
|
||||||
|
|
||||||
|
import { calculateTactus, sequence, stack } from '../index.mjs';
|
||||||
|
|
||||||
|
const pat64 = sequence(...Array(64).keys());
|
||||||
|
|
||||||
|
describe('steps', () => {
|
||||||
|
calculateTactus(true);
|
||||||
|
bench(
|
||||||
|
'+tactus',
|
||||||
|
() => {
|
||||||
|
pat64.iter(64).fast(64).firstCycle();
|
||||||
|
},
|
||||||
|
{ time: 1000 },
|
||||||
|
);
|
||||||
|
|
||||||
|
calculateTactus(false);
|
||||||
|
bench(
|
||||||
|
'-tactus',
|
||||||
|
() => {
|
||||||
|
pat64.iter(64).fast(64).firstCycle();
|
||||||
|
},
|
||||||
|
{ time: 1000 },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('stack', () => {
|
||||||
|
calculateTactus(true);
|
||||||
|
bench(
|
||||||
|
'+tactus',
|
||||||
|
() => {
|
||||||
|
stack(pat64, pat64, pat64, pat64, pat64, pat64, pat64, pat64).fast(64).firstCycle();
|
||||||
|
},
|
||||||
|
{ time: 1000 },
|
||||||
|
);
|
||||||
|
|
||||||
|
calculateTactus(false);
|
||||||
|
bench(
|
||||||
|
'-tactus',
|
||||||
|
() => {
|
||||||
|
stack(pat64, pat64, pat64, pat64, pat64, pat64, pat64, pat64).fast(64).firstCycle();
|
||||||
|
},
|
||||||
|
{ time: 1000 },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
calculateTactus(true);
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
// import createClock from './zyklus.mjs';
|
// import createClock from './zyklus.mjs';
|
||||||
|
|
||||||
function getTime() {
|
function getTime() {
|
||||||
const precision = 10 ** 4;
|
const seconds = performance.now() * 0.001;
|
||||||
const seconds = performance.now() / 1000;
|
return seconds;
|
||||||
return Math.round(seconds * precision) / precision;
|
// return Math.round(seconds * precision) / precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_cycles_at_cps_change = 0;
|
let num_cycles_at_cps_change = 0;
|
||||||
@@ -24,27 +24,20 @@ const sendMessage = (type, payload) => {
|
|||||||
|
|
||||||
const sendTick = (phase, duration, tick, time) => {
|
const sendTick = (phase, duration, tick, time) => {
|
||||||
const num_seconds_since_cps_change = num_ticks_since_cps_change * duration;
|
const num_seconds_since_cps_change = num_ticks_since_cps_change * duration;
|
||||||
|
|
||||||
const tickdeadline = phase - time;
|
const tickdeadline = phase - time;
|
||||||
const lastTick = time + tickdeadline;
|
const lastTick = time + tickdeadline;
|
||||||
const num_cycles_since_cps_change = num_seconds_since_cps_change * cps;
|
const num_cycles_since_cps_change = num_seconds_since_cps_change * cps;
|
||||||
|
|
||||||
const begin = num_cycles_at_cps_change + num_cycles_since_cps_change;
|
const begin = num_cycles_at_cps_change + num_cycles_since_cps_change;
|
||||||
const secondsSinceLastTick = time - lastTick - duration;
|
const secondsSinceLastTick = time - lastTick - duration;
|
||||||
|
|
||||||
const eventLength = duration * cps;
|
const eventLength = duration * cps;
|
||||||
const end = begin + eventLength;
|
const end = begin + eventLength;
|
||||||
|
|
||||||
const cycle = begin + secondsSinceLastTick * cps;
|
const cycle = begin + secondsSinceLastTick * cps;
|
||||||
|
|
||||||
sendMessage('tick', {
|
sendMessage('tick', {
|
||||||
begin,
|
begin,
|
||||||
end,
|
end,
|
||||||
cps,
|
cps,
|
||||||
tickdeadline,
|
time,
|
||||||
num_cycles_at_cps_change,
|
|
||||||
num_seconds_at_cps_change,
|
|
||||||
num_seconds_since_cps_change,
|
|
||||||
cycle,
|
cycle,
|
||||||
});
|
});
|
||||||
num_ticks_since_cps_change++;
|
num_ticks_since_cps_change++;
|
||||||
@@ -120,7 +113,7 @@ self.onconnect = function (e) {
|
|||||||
port.start(); // Required when using addEventListener. Otherwise called implicitly by onmessage setter.
|
port.start(); // Required when using addEventListener. Otherwise called implicitly by onmessage setter.
|
||||||
};
|
};
|
||||||
|
|
||||||
// used to consistently schedule events, for use in a service worker - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/clockworker.mjs>
|
// used to consistently schedule events, for use in a service worker - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/clockworker.mjs>
|
||||||
function createClock(
|
function createClock(
|
||||||
getTime,
|
getTime,
|
||||||
callback, // called slightly before each cycle
|
callback, // called slightly before each cycle
|
||||||
|
|||||||
+336
-42
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
controls.mjs - <short description TODO>
|
controls.mjs - Registers audio controls for pattern manipulation and effects.
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/controls.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/controls.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -47,12 +47,16 @@ export function createParam(names) {
|
|||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerControl(names, ...aliases) {
|
// maps control alias names to the "main" control name
|
||||||
|
const controlAlias = new Map();
|
||||||
|
|
||||||
|
export function registerControl(names, ...aliases) {
|
||||||
const name = Array.isArray(names) ? names[0] : names;
|
const name = Array.isArray(names) ? names[0] : names;
|
||||||
let bag = {};
|
let bag = {};
|
||||||
bag[name] = createParam(names);
|
bag[name] = createParam(names);
|
||||||
aliases.forEach((alias) => {
|
aliases.forEach((alias) => {
|
||||||
bag[alias] = bag[name];
|
bag[alias] = bag[name];
|
||||||
|
controlAlias.set(alias, name);
|
||||||
Pattern.prototype[alias] = Pattern.prototype[name];
|
Pattern.prototype[alias] = Pattern.prototype[name];
|
||||||
});
|
});
|
||||||
return bag;
|
return bag;
|
||||||
@@ -92,7 +96,7 @@ export const { source, src } = registerControl('source', 'src');
|
|||||||
* @example
|
* @example
|
||||||
* s("bd sd [~ bd] sd,hh*6").n("<0 1>")
|
* s("bd sd [~ bd] sd,hh*6").n("<0 1>")
|
||||||
*/
|
*/
|
||||||
// also see https://github.com/tidalcycles/strudel/pull/63
|
// also see https://codeberg.org/uzu/strudel/pulls/63
|
||||||
export const { n } = registerControl('n');
|
export const { n } = registerControl('n');
|
||||||
/**
|
/**
|
||||||
* Plays the given note name or midi number. A note name consists of
|
* Plays the given note name or midi number. A note name consists of
|
||||||
@@ -191,7 +195,7 @@ export const { attack, att } = registerControl('attack', 'att');
|
|||||||
* note("c e g b g e")
|
* note("c e g b g e")
|
||||||
* .fm(4)
|
* .fm(4)
|
||||||
* .fmh("<1 2 1.5 1.61>")
|
* .fmh("<1 2 1.5 1.61>")
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmh } = registerControl(['fmh', 'fmi'], 'fmh');
|
export const { fmh } = registerControl(['fmh', 'fmi'], 'fmh');
|
||||||
@@ -205,7 +209,7 @@ export const { fmh } = registerControl(['fmh', 'fmi'], 'fmh');
|
|||||||
* @example
|
* @example
|
||||||
* note("c e g b g e")
|
* note("c e g b g e")
|
||||||
* .fm("<0 1 2 8 32>")
|
* .fm("<0 1 2 8 32>")
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmi, fm } = registerControl(['fmi', 'fmh'], 'fm');
|
export const { fmi, fm } = registerControl(['fmi', 'fmh'], 'fm');
|
||||||
@@ -221,7 +225,7 @@ export const { fmi, fm } = registerControl(['fmi', 'fmh'], 'fm');
|
|||||||
* .fmdecay(.2)
|
* .fmdecay(.2)
|
||||||
* .fmsustain(0)
|
* .fmsustain(0)
|
||||||
* .fmenv("<exp lin>")
|
* .fmenv("<exp lin>")
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmenv } = registerControl('fmenv');
|
export const { fmenv } = registerControl('fmenv');
|
||||||
@@ -234,7 +238,7 @@ export const { fmenv } = registerControl('fmenv');
|
|||||||
* note("c e g b g e")
|
* note("c e g b g e")
|
||||||
* .fm(4)
|
* .fm(4)
|
||||||
* .fmattack("<0 .05 .1 .2>")
|
* .fmattack("<0 .05 .1 .2>")
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmattack } = registerControl('fmattack');
|
export const { fmattack } = registerControl('fmattack');
|
||||||
@@ -248,7 +252,7 @@ export const { fmattack } = registerControl('fmattack');
|
|||||||
* .fm(4)
|
* .fm(4)
|
||||||
* .fmdecay("<.01 .05 .1 .2>")
|
* .fmdecay("<.01 .05 .1 .2>")
|
||||||
* .fmsustain(.4)
|
* .fmsustain(.4)
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmdecay } = registerControl('fmdecay');
|
export const { fmdecay } = registerControl('fmdecay');
|
||||||
@@ -262,7 +266,7 @@ export const { fmdecay } = registerControl('fmdecay');
|
|||||||
* .fm(4)
|
* .fm(4)
|
||||||
* .fmdecay(.1)
|
* .fmdecay(.1)
|
||||||
* .fmsustain("<1 .75 .5 0>")
|
* .fmsustain("<1 .75 .5 0>")
|
||||||
* .scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmsustain } = registerControl('fmsustain');
|
export const { fmsustain } = registerControl('fmsustain');
|
||||||
@@ -344,7 +348,7 @@ export const { bandf, bpf, bp } = registerControl(['bandf', 'bandq', 'bpenv'], '
|
|||||||
* s("bd sd [~ bd] sd").bpf(500).bpq("<0 1 2 3>")
|
* s("bd sd [~ bd] sd").bpf(500).bpq("<0 1 2 3>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// currently an alias of 'bandq' https://github.com/tidalcycles/strudel/issues/496
|
// currently an alias of 'bandq' https://codeberg.org/uzu/strudel/issues/496
|
||||||
// ['bpq'],
|
// ['bpq'],
|
||||||
export const { bandq, bpq } = registerControl('bandq', 'bpq');
|
export const { bandq, bpq } = registerControl('bandq', 'bpq');
|
||||||
/**
|
/**
|
||||||
@@ -392,7 +396,7 @@ export const { loop } = registerControl('loop');
|
|||||||
* @synonyms loopb
|
* @synonyms loopb
|
||||||
* @example
|
* @example
|
||||||
* s("space").loop(1)
|
* s("space").loop(1)
|
||||||
* .loopBegin("<0 .125 .25>").scope()
|
* .loopBegin("<0 .125 .25>")._scope()
|
||||||
*/
|
*/
|
||||||
export const { loopBegin, loopb } = registerControl('loopBegin', 'loopb');
|
export const { loopBegin, loopb } = registerControl('loopBegin', 'loopb');
|
||||||
/**
|
/**
|
||||||
@@ -405,7 +409,7 @@ export const { loopBegin, loopb } = registerControl('loopBegin', 'loopb');
|
|||||||
* @synonyms loope
|
* @synonyms loope
|
||||||
* @example
|
* @example
|
||||||
* s("space").loop(1)
|
* s("space").loop(1)
|
||||||
* .loopEnd("<1 .75 .5 .25>").scope()
|
* .loopEnd("<1 .75 .5 .25>")._scope()
|
||||||
*/
|
*/
|
||||||
export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
||||||
/**
|
/**
|
||||||
@@ -430,6 +434,43 @@ export const { crush } = registerControl('crush');
|
|||||||
*/
|
*/
|
||||||
export const { coarse } = registerControl('coarse');
|
export const { coarse } = registerControl('coarse');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* filter overdrive for supported filter types
|
||||||
|
*
|
||||||
|
* @name drive
|
||||||
|
* @param {number | Pattern} amount
|
||||||
|
* @example
|
||||||
|
* note("{f g g c d a a#}%16".sub(17)).s("supersaw").lpenv(8).lpf(150).lpq(.8).ftype('ladder').drive("<.5 4>")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { drive } = registerControl('drive');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create byte beats with custom expressions
|
||||||
|
*
|
||||||
|
* @name byteBeatExpression
|
||||||
|
* @synonyms bbexpr
|
||||||
|
*
|
||||||
|
* @param {number | Pattern} byteBeatExpression bitwise expression for creating bytebeat
|
||||||
|
* @example
|
||||||
|
* s("bytebeat").bbexpr('t*(t>>15^t>>66)')
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { byteBeatExpression, bbexpr } = registerControl('byteBeatExpression', 'bbexpr');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create byte beats with custom expressions
|
||||||
|
*
|
||||||
|
* @name byteBeatStartTime
|
||||||
|
* @synonyms bbst
|
||||||
|
*
|
||||||
|
* @param {number | Pattern} byteBeatStartTime in samples (t)
|
||||||
|
* @example
|
||||||
|
* note("c3!8".add("{0 0 12 0 7 5 3}%8")).s("bytebeat:5").bbst("<3 1>".mul(10000))._scope()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { byteBeatStartTime, bbst } = registerControl('byteBeatStartTime', 'bbst');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows you to set the output channels on the interface
|
* Allows you to set the output channels on the interface
|
||||||
*
|
*
|
||||||
@@ -443,8 +484,40 @@ export const { coarse } = registerControl('coarse');
|
|||||||
*/
|
*/
|
||||||
export const { channels, ch } = registerControl('channels', 'ch');
|
export const { channels, ch } = registerControl('channels', 'ch');
|
||||||
|
|
||||||
// superdirt only
|
/**
|
||||||
export const { phaserrate, phasr } = registerControl('phaserrate', 'phasr');
|
* controls the pulsewidth of the pulse oscillator
|
||||||
|
*
|
||||||
|
* @name pw
|
||||||
|
* @param {number | Pattern} pulsewidth
|
||||||
|
* @example
|
||||||
|
* note("{f a c e}%16").s("pulse").pw(".8:1:.2")
|
||||||
|
* @example
|
||||||
|
* n(run(8)).scale("D:pentatonic").s("pulse").pw("0 .75 .5 1")
|
||||||
|
*/
|
||||||
|
export const { pw } = registerControl(['pw', 'pwrate', 'pwsweep']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controls the lfo rate for the pulsewidth of the pulse oscillator
|
||||||
|
*
|
||||||
|
* @name pwrate
|
||||||
|
* @param {number | Pattern} rate
|
||||||
|
* @example
|
||||||
|
* n(run(8)).scale("D:pentatonic").s("pulse").pw("0.5").pwrate("<5 .1 25>").pwsweep("<0.3 .8>")
|
||||||
|
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { pwrate } = registerControl('pwrate');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controls the lfo sweep for the pulsewidth of the pulse oscillator
|
||||||
|
*
|
||||||
|
* @name pwsweep
|
||||||
|
* @param {number | Pattern} sweep
|
||||||
|
* @example
|
||||||
|
* n(run(8)).scale("D:pentatonic").s("pulse").pw("0.5").pwrate("<5 .1 25>").pwsweep("<0.3 .8>")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { pwsweep } = registerControl('pwsweep');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phaser audio effect that approximates popular guitar pedals.
|
* Phaser audio effect that approximates popular guitar pedals.
|
||||||
@@ -457,7 +530,11 @@ export const { phaserrate, phasr } = registerControl('phaserrate', 'phasr');
|
|||||||
* .phaser("<1 2 4 8>")
|
* .phaser("<1 2 4 8>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { phaser, ph } = registerControl(['phaser', 'phaserdepth', 'phasercenter', 'phasersweep'], 'ph');
|
export const { phaserrate, ph, phaser } = registerControl(
|
||||||
|
['phaserrate', 'phaserdepth', 'phasercenter', 'phasersweep'],
|
||||||
|
'ph',
|
||||||
|
'phaser',
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The frequency sweep range of the lfo for the phaser effect. Defaults to 2000
|
* The frequency sweep range of the lfo for the phaser effect. Defaults to 2000
|
||||||
@@ -542,7 +619,7 @@ export const { cutoff, ctf, lpf, lp } = registerControl(['cutoff', 'resonance',
|
|||||||
* @example
|
* @example
|
||||||
* note("c2 e2 f2 g2")
|
* note("c2 e2 f2 g2")
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .lpf(500)
|
* .lpf(300)
|
||||||
* .lpa(.5)
|
* .lpa(.5)
|
||||||
* .lpenv("<4 2 1 0 -1 -2 -4>/4")
|
* .lpenv("<4 2 1 0 -1 -2 -4>/4")
|
||||||
*/
|
*/
|
||||||
@@ -581,7 +658,7 @@ export const { bpenv, bpe } = registerControl('bpenv', 'bpe');
|
|||||||
* @example
|
* @example
|
||||||
* note("c2 e2 f2 g2")
|
* note("c2 e2 f2 g2")
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .lpf(500)
|
* .lpf(300)
|
||||||
* .lpa("<.5 .25 .1 .01>/4")
|
* .lpa("<.5 .25 .1 .01>/4")
|
||||||
* .lpenv(4)
|
* .lpenv(4)
|
||||||
*/
|
*/
|
||||||
@@ -620,9 +697,8 @@ export const { bpattack, bpa } = registerControl('bpattack', 'bpa');
|
|||||||
* @example
|
* @example
|
||||||
* note("c2 e2 f2 g2")
|
* note("c2 e2 f2 g2")
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .lpf(500)
|
* .lpf(300)
|
||||||
* .lpd("<.5 .25 .1 0>/4")
|
* .lpd("<.5 .25 .1 0>/4")
|
||||||
* .lps(0.2)
|
|
||||||
* .lpenv(4)
|
* .lpenv(4)
|
||||||
*/
|
*/
|
||||||
export const { lpdecay, lpd } = registerControl('lpdecay', 'lpd');
|
export const { lpdecay, lpd } = registerControl('lpdecay', 'lpd');
|
||||||
@@ -662,7 +738,7 @@ export const { bpdecay, bpd } = registerControl('bpdecay', 'bpd');
|
|||||||
* @example
|
* @example
|
||||||
* note("c2 e2 f2 g2")
|
* note("c2 e2 f2 g2")
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .lpf(500)
|
* .lpf(300)
|
||||||
* .lpd(.5)
|
* .lpd(.5)
|
||||||
* .lps("<0 .25 .5 1>/4")
|
* .lps("<0 .25 .5 1>/4")
|
||||||
* .lpenv(4)
|
* .lpenv(4)
|
||||||
@@ -705,7 +781,7 @@ export const { bpsustain, bps } = registerControl('bpsustain', 'bps');
|
|||||||
* note("c2 e2 f2 g2")
|
* note("c2 e2 f2 g2")
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .clip(.5)
|
* .clip(.5)
|
||||||
* .lpf(500)
|
* .lpf(300)
|
||||||
* .lpenv(4)
|
* .lpenv(4)
|
||||||
* .lpr("<.5 .25 .1 0>/4")
|
* .lpr("<.5 .25 .1 0>/4")
|
||||||
* .release(.5)
|
* .release(.5)
|
||||||
@@ -742,17 +818,28 @@ export const { hprelease, hpr } = registerControl('hprelease', 'hpr');
|
|||||||
*/
|
*/
|
||||||
export const { bprelease, bpr } = registerControl('bprelease', 'bpr');
|
export const { bprelease, bpr } = registerControl('bprelease', 'bpr');
|
||||||
/**
|
/**
|
||||||
* Sets the filter type. The 24db filter is more aggressive. More types might be added in the future.
|
* Sets the filter type. The ladder filter is more aggressive. More types might be added in the future.
|
||||||
* @name ftype
|
* @name ftype
|
||||||
* @param {number | Pattern} type 12db (default) or 24db
|
* @param {number | Pattern} type 12db (0), ladder (1), or 24db (2)
|
||||||
* @example
|
* @example
|
||||||
* note("c2 e2 f2 g2")
|
* note("{f g g c d a a#}%8").s("sawtooth").lpenv(4).lpf(500).ftype("<0 1 2>").lpq(1)
|
||||||
|
* @example
|
||||||
|
* note("c f g g a c d4").fast(2)
|
||||||
* .sound('sawtooth')
|
* .sound('sawtooth')
|
||||||
* .lpf(500)
|
* .lpf(200).fanchor(0)
|
||||||
* .bpenv(4)
|
* .lpenv(3).lpq(1)
|
||||||
* .ftype("12db 24db")
|
* .ftype("<ladder 12db 24db>")
|
||||||
*/
|
*/
|
||||||
export const { ftype } = registerControl('ftype');
|
export const { ftype } = registerControl('ftype');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controls the center of the filter envelope. 0 is unipolar positive, .5 is bipolar, 1 is unipolar negative
|
||||||
|
* @name fanchor
|
||||||
|
* @param {number | Pattern} center 0 to 1
|
||||||
|
* @example
|
||||||
|
* note("{f g g c d a a#}%8").s("sawtooth").lpf("{1000}%2")
|
||||||
|
* .lpenv(8).fanchor("<0 .5 1>")
|
||||||
|
*/
|
||||||
export const { fanchor } = registerControl('fanchor');
|
export const { fanchor } = registerControl('fanchor');
|
||||||
/**
|
/**
|
||||||
* Applies the cutoff frequency of the **h**igh-**p**ass **f**ilter.
|
* Applies the cutoff frequency of the **h**igh-**p**ass **f**ilter.
|
||||||
@@ -768,7 +855,7 @@ export const { fanchor } = registerControl('fanchor');
|
|||||||
* s("bd sd [~ bd] sd,hh*8").hpf("<2000 2000:25>")
|
* s("bd sd [~ bd] sd,hh*8").hpf("<2000 2000:25>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// currently an alias of 'hcutoff' https://github.com/tidalcycles/strudel/issues/496
|
// currently an alias of 'hcutoff' https://codeberg.org/uzu/strudel/issues/496
|
||||||
// ['hpf'],
|
// ['hpf'],
|
||||||
/**
|
/**
|
||||||
* Applies a vibrato to the frequency of the oscillator.
|
* Applies a vibrato to the frequency of the oscillator.
|
||||||
@@ -779,10 +866,12 @@ export const { fanchor } = registerControl('fanchor');
|
|||||||
* @example
|
* @example
|
||||||
* note("a e")
|
* note("a e")
|
||||||
* .vib("<.5 1 2 4 8 16>")
|
* .vib("<.5 1 2 4 8 16>")
|
||||||
|
* ._scope()
|
||||||
* @example
|
* @example
|
||||||
* // change the modulation depth with ":"
|
* // change the modulation depth with ":"
|
||||||
* note("a e")
|
* note("a e")
|
||||||
* .vib("<.5 1 2 4 8 16>:12")
|
* .vib("<.5 1 2 4 8 16>:12")
|
||||||
|
* ._scope()
|
||||||
*/
|
*/
|
||||||
export const { vib, vibrato, v } = registerControl(['vib', 'vibmod'], 'vibrato', 'v');
|
export const { vib, vibrato, v } = registerControl(['vib', 'vibmod'], 'vibrato', 'v');
|
||||||
/**
|
/**
|
||||||
@@ -803,10 +892,12 @@ export const { noise } = registerControl('noise');
|
|||||||
* @example
|
* @example
|
||||||
* note("a e").vib(4)
|
* note("a e").vib(4)
|
||||||
* .vibmod("<.25 .5 1 2 12>")
|
* .vibmod("<.25 .5 1 2 12>")
|
||||||
|
* ._scope()
|
||||||
* @example
|
* @example
|
||||||
* // change the vibrato frequency with ":"
|
* // change the vibrato frequency with ":"
|
||||||
* note("a e")
|
* note("a e")
|
||||||
* .vibmod("<.25 .5 1 2 12>:8")
|
* .vibmod("<.25 .5 1 2 12>:8")
|
||||||
|
* ._scope()
|
||||||
*/
|
*/
|
||||||
export const { vibmod, vmod } = registerControl(['vibmod', 'vib'], 'vmod');
|
export const { vibmod, vmod } = registerControl(['vibmod', 'vib'], 'vmod');
|
||||||
export const { hcutoff, hpf, hp } = registerControl(['hcutoff', 'hresonance', 'hpenv'], 'hpf', 'hp');
|
export const { hcutoff, hpf, hp } = registerControl(['hcutoff', 'hresonance', 'hpenv'], 'hpf', 'hp');
|
||||||
@@ -831,7 +922,7 @@ export const { hresonance, hpq } = registerControl('hresonance', 'hpq');
|
|||||||
* s("bd sd [~ bd] sd,hh*8").lpf(2000).lpq("<0 10 20 30>")
|
* s("bd sd [~ bd] sd,hh*8").lpf(2000).lpq("<0 10 20 30>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// currently an alias of 'resonance' https://github.com/tidalcycles/strudel/issues/496
|
// currently an alias of 'resonance' https://codeberg.org/uzu/strudel/issues/496
|
||||||
export const { resonance, lpq } = registerControl('resonance', 'lpq');
|
export const { resonance, lpq } = registerControl('resonance', 'lpq');
|
||||||
/**
|
/**
|
||||||
* DJ filter, below 0.5 is low pass filter, above is high pass filter.
|
* DJ filter, below 0.5 is low pass filter, above is high pass filter.
|
||||||
@@ -1197,7 +1288,7 @@ export const { semitone } = registerControl('semitone');
|
|||||||
|
|
||||||
// TODO: synth param
|
// TODO: synth param
|
||||||
export const { voice } = registerControl('voice');
|
export const { voice } = registerControl('voice');
|
||||||
// voicings // https://github.com/tidalcycles/strudel/issues/506
|
// voicings // https://codeberg.org/uzu/strudel/issues/506
|
||||||
// chord to voice, like C Eb Fm7 G7. the symbols can be defined via addVoicings
|
// chord to voice, like C Eb Fm7 G7. the symbols can be defined via addVoicings
|
||||||
export const { chord } = registerControl('chord');
|
export const { chord } = registerControl('chord');
|
||||||
// which dictionary to use for the voicings
|
// which dictionary to use for the voicings
|
||||||
@@ -1358,6 +1449,17 @@ export const { compressorRelease } = registerControl('compressorRelease');
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { speed } = registerControl('speed');
|
export const { speed } = registerControl('speed');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the speed of sample playback, i.e. a cheap way of changing pitch.
|
||||||
|
*
|
||||||
|
* @name stretch
|
||||||
|
* @param {number | Pattern} factor -inf to inf, negative numbers play the sample backwards.
|
||||||
|
* @example
|
||||||
|
* s("gm_flute").stretch("1 2 .5")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { stretch } = registerControl('stretch');
|
||||||
/**
|
/**
|
||||||
* Used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
* Used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
||||||
*
|
*
|
||||||
@@ -1368,6 +1470,7 @@ export const { speed } = registerControl('speed');
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const { unit } = registerControl('unit');
|
export const { unit } = registerControl('unit');
|
||||||
/**
|
/**
|
||||||
* Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:
|
* Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:
|
||||||
@@ -1419,7 +1522,7 @@ export const { vowel } = registerControl('vowel');
|
|||||||
* @name waveloss
|
* @name waveloss
|
||||||
*/
|
*/
|
||||||
export const { waveloss } = registerControl('waveloss');
|
export const { waveloss } = registerControl('waveloss');
|
||||||
/*
|
/**
|
||||||
* Noise crackle density
|
* Noise crackle density
|
||||||
*
|
*
|
||||||
* @name density
|
* @name density
|
||||||
@@ -1471,20 +1574,11 @@ export const { scram } = registerControl('scram');
|
|||||||
export const { binshift } = registerControl('binshift');
|
export const { binshift } = registerControl('binshift');
|
||||||
export const { hbrick } = registerControl('hbrick');
|
export const { hbrick } = registerControl('hbrick');
|
||||||
export const { lbrick } = registerControl('lbrick');
|
export const { lbrick } = registerControl('lbrick');
|
||||||
export const { midichan } = registerControl('midichan');
|
|
||||||
export const { control } = registerControl('control');
|
|
||||||
export const { ccn } = registerControl('ccn');
|
|
||||||
export const { ccv } = registerControl('ccv');
|
|
||||||
export const { polyTouch } = registerControl('polyTouch');
|
|
||||||
export const { midibend } = registerControl('midibend');
|
|
||||||
export const { miditouch } = registerControl('miditouch');
|
|
||||||
export const { ctlNum } = registerControl('ctlNum');
|
|
||||||
export const { frameRate } = registerControl('frameRate');
|
export const { frameRate } = registerControl('frameRate');
|
||||||
export const { frames } = registerControl('frames');
|
export const { frames } = registerControl('frames');
|
||||||
export const { hours } = registerControl('hours');
|
export const { hours } = registerControl('hours');
|
||||||
export const { midicmd } = registerControl('midicmd');
|
|
||||||
export const { minutes } = registerControl('minutes');
|
export const { minutes } = registerControl('minutes');
|
||||||
export const { progNum } = registerControl('progNum');
|
|
||||||
export const { seconds } = registerControl('seconds');
|
export const { seconds } = registerControl('seconds');
|
||||||
export const { songPtr } = registerControl('songPtr');
|
export const { songPtr } = registerControl('songPtr');
|
||||||
export const { uid } = registerControl('uid');
|
export const { uid } = registerControl('uid');
|
||||||
@@ -1576,3 +1670,203 @@ export const ar = register('ar', (t, pat) => {
|
|||||||
const [attack, release = attack] = t;
|
const [attack, release = attack] = t;
|
||||||
return pat.set({ attack, release });
|
return pat.set({ attack, release });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//MIDI
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI channel: Sets the MIDI channel for the event.
|
||||||
|
*
|
||||||
|
* @name midichan
|
||||||
|
* @param {number | Pattern} channel MIDI channel number (0-15)
|
||||||
|
* @example
|
||||||
|
* note("c4").midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { midichan } = registerControl('midichan');
|
||||||
|
|
||||||
|
export const { midimap } = registerControl('midimap');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI port: Sets the MIDI port for the event.
|
||||||
|
*
|
||||||
|
* @name midiport
|
||||||
|
* @param {number | Pattern} port MIDI port
|
||||||
|
* @example
|
||||||
|
* note("c a f e").midiport("<0 1 2 3>").midi()
|
||||||
|
*/
|
||||||
|
export const { midiport } = registerControl('midiport');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI command: Sends a MIDI command message.
|
||||||
|
*
|
||||||
|
* @name midicmd
|
||||||
|
* @param {number | Pattern} command MIDI command
|
||||||
|
* @example
|
||||||
|
* midicmd("clock*48,<start stop>/2").midi()
|
||||||
|
*/
|
||||||
|
export const { midicmd } = registerControl('midicmd');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI control: Sends a MIDI control change message.
|
||||||
|
*
|
||||||
|
* @name control
|
||||||
|
* @param {number | Pattern} MIDI control number (0-127)
|
||||||
|
* @param {number | Pattern} MIDI controller value (0-127)
|
||||||
|
*/
|
||||||
|
export const control = register('control', (args, pat) => {
|
||||||
|
if (!Array.isArray(args)) {
|
||||||
|
throw new Error('control expects an array of [ccn, ccv]');
|
||||||
|
}
|
||||||
|
const [_ccn, _ccv] = args;
|
||||||
|
return pat.ccn(_ccn).ccv(_ccv);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI control number: Sends a MIDI control change message.
|
||||||
|
*
|
||||||
|
* @name ccn
|
||||||
|
* @param {number | Pattern} MIDI control number (0-127)
|
||||||
|
*/
|
||||||
|
export const { ccn } = registerControl('ccn');
|
||||||
|
/**
|
||||||
|
* MIDI control value: Sends a MIDI control change message.
|
||||||
|
*
|
||||||
|
* @name ccv
|
||||||
|
* @param {number | Pattern} MIDI control value (0-127)
|
||||||
|
*/
|
||||||
|
export const { ccv } = registerControl('ccv');
|
||||||
|
export const { ctlNum } = registerControl('ctlNum');
|
||||||
|
// TODO: ctlVal?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI NRPN non-registered parameter number: Sends a MIDI NRPN non-registered parameter number message.
|
||||||
|
* @name nrpnn
|
||||||
|
* @param {number | Pattern} nrpnn MIDI NRPN non-registered parameter number (0-127)
|
||||||
|
* @example
|
||||||
|
* note("c4").nrpnn("1:8").nrpv("123").midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { nrpnn } = registerControl('nrpnn');
|
||||||
|
/**
|
||||||
|
* MIDI NRPN non-registered parameter value: Sends a MIDI NRPN non-registered parameter value message.
|
||||||
|
* @name nrpv
|
||||||
|
* @param {number | Pattern} nrpv MIDI NRPN non-registered parameter value (0-127)
|
||||||
|
* @example
|
||||||
|
* note("c4").nrpnn("1:8").nrpv("123").midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { nrpv } = registerControl('nrpv');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI program number: Sends a MIDI program change message.
|
||||||
|
*
|
||||||
|
* @name progNum
|
||||||
|
* @param {number | Pattern} program MIDI program number (0-127)
|
||||||
|
* @example
|
||||||
|
* note("c4").progNum(10).midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { progNum } = registerControl('progNum');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI sysex: Sends a MIDI sysex message.
|
||||||
|
* @name sysex
|
||||||
|
* @param {number | Pattern} id Sysex ID
|
||||||
|
* @param {number | Pattern} data Sysex data
|
||||||
|
* @example
|
||||||
|
* note("c4").sysex(["0x77", "0x01:0x02:0x03:0x04"]).midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const sysex = register('sysex', (args, pat) => {
|
||||||
|
if (!Array.isArray(args)) {
|
||||||
|
throw new Error('sysex expects an array of [id, data]');
|
||||||
|
}
|
||||||
|
const [id, data] = args;
|
||||||
|
return pat.sysexid(id).sysexdata(data);
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* MIDI sysex ID: Sends a MIDI sysex identifier message.
|
||||||
|
* @name sysexid
|
||||||
|
* @param {number | Pattern} id Sysex ID
|
||||||
|
* @example
|
||||||
|
* note("c4").sysexid("0x77").sysexdata("0x01:0x02:0x03:0x04").midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { sysexid } = registerControl('sysexid');
|
||||||
|
/**
|
||||||
|
* MIDI sysex data: Sends a MIDI sysex message.
|
||||||
|
* @name sysexdata
|
||||||
|
* @param {number | Pattern} data Sysex data
|
||||||
|
* @example
|
||||||
|
* note("c4").sysexid("0x77").sysexdata("0x01:0x02:0x03:0x04").midichan(1).midi()
|
||||||
|
*/
|
||||||
|
export const { sysexdata } = registerControl('sysexdata');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIDI pitch bend: Sends a MIDI pitch bend message.
|
||||||
|
* @name midibend
|
||||||
|
* @param {number | Pattern} midibend MIDI pitch bend (-1 - 1)
|
||||||
|
* @example
|
||||||
|
* note("c4").midibend(sine.slow(4).range(-0.4,0.4)).midi()
|
||||||
|
*/
|
||||||
|
export const { midibend } = registerControl('midibend');
|
||||||
|
/**
|
||||||
|
* MIDI key after touch: Sends a MIDI key after touch message.
|
||||||
|
* @name miditouch
|
||||||
|
* @param {number | Pattern} miditouch MIDI key after touch (0-1)
|
||||||
|
* @example
|
||||||
|
* note("c4").miditouch(sine.slow(4).range(0,1)).midi()
|
||||||
|
*/
|
||||||
|
export const { miditouch } = registerControl('miditouch');
|
||||||
|
|
||||||
|
// TODO: what is this?
|
||||||
|
export const { polyTouch } = registerControl('polyTouch');
|
||||||
|
|
||||||
|
export const getControlName = (alias) => {
|
||||||
|
if (controlAlias.has(alias)) {
|
||||||
|
return controlAlias.get(alias);
|
||||||
|
}
|
||||||
|
return alias;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets properties in a batch.
|
||||||
|
*
|
||||||
|
* @name as
|
||||||
|
* @param {String | Array} mapping the control names that are set
|
||||||
|
* @example
|
||||||
|
* "c:.5 a:1 f:.25 e:.8".as("note:clip")
|
||||||
|
* @example
|
||||||
|
* "{0@2 0.25 0 0.5 .3 .5}%8".as("begin").s("sax_vib").clip(1)
|
||||||
|
*/
|
||||||
|
export const as = register('as', (mapping, pat) => {
|
||||||
|
mapping = Array.isArray(mapping) ? mapping : [mapping];
|
||||||
|
return pat.fmap((v) => {
|
||||||
|
v = Array.isArray(v) ? v : [v];
|
||||||
|
v = Object.fromEntries(mapping.map((prop, i) => [getControlName(prop), v[i]]));
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to scrub an audio file like a tape loop by passing values that represents the position in the audio file
|
||||||
|
* in the optional array syntax ex: "0.5:2", the second value controls the speed of playback
|
||||||
|
* @name scrub
|
||||||
|
* @memberof Pattern
|
||||||
|
* @returns Pattern
|
||||||
|
* @example
|
||||||
|
* samples('github:switchangel/pad')
|
||||||
|
* s("swpad:0").scrub("{0.1!2 .25@3 0.7!2 <0.8:1.5>}%8")
|
||||||
|
* @example
|
||||||
|
* samples('github:yaxu/clean-breaks/main');
|
||||||
|
* s("amen/4").fit().scrub("{0@3 0@2 4@3}%8".div(16))
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const scrub = register(
|
||||||
|
'scrub',
|
||||||
|
(beginPat, pat) => {
|
||||||
|
return beginPat.outerBind((v) => {
|
||||||
|
if (!Array.isArray(v)) {
|
||||||
|
v = [v];
|
||||||
|
}
|
||||||
|
const [beginVal, speedMultiplier = 1] = v;
|
||||||
|
|
||||||
|
return pat.begin(beginVal).mul(speed(speedMultiplier)).clip(1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
cyclist.mjs - event scheduler for a single strudel instance. for multi-instance scheduler, see - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/neocyclist.mjs>
|
cyclist.mjs - event scheduler for a single strudel instance. for multi-instance scheduler, see - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/neocyclist.mjs>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/cyclist.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/cyclist.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -8,8 +8,19 @@ import createClock from './zyklus.mjs';
|
|||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
|
|
||||||
export class Cyclist {
|
export class Cyclist {
|
||||||
constructor({ interval, onTrigger, onToggle, onError, getTime, latency = 0.1, setInterval, clearInterval }) {
|
constructor({
|
||||||
|
interval,
|
||||||
|
onTrigger,
|
||||||
|
onToggle,
|
||||||
|
onError,
|
||||||
|
getTime,
|
||||||
|
latency = 0.1,
|
||||||
|
setInterval,
|
||||||
|
clearInterval,
|
||||||
|
beforeStart,
|
||||||
|
}) {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
|
this.beforeStart = beforeStart;
|
||||||
this.cps = 0.5;
|
this.cps = 0.5;
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_cps_change = 0;
|
||||||
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
@@ -54,9 +65,13 @@ export class Cyclist {
|
|||||||
(hap.whole.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency;
|
(hap.whole.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency;
|
||||||
const duration = hap.duration / this.cps;
|
const duration = hap.duration / this.cps;
|
||||||
// the following line is dumb and only here for backwards compatibility
|
// the following line is dumb and only here for backwards compatibility
|
||||||
// see https://github.com/tidalcycles/strudel/pull/1004
|
// see https://codeberg.org/uzu/strudel/pulls/1004
|
||||||
const deadline = targetTime - phase;
|
const deadline = targetTime - phase;
|
||||||
onTrigger?.(hap, deadline, duration, this.cps, targetTime);
|
onTrigger?.(hap, deadline, duration, this.cps, targetTime);
|
||||||
|
if (hap.value.cps !== undefined && this.cps != hap.value.cps) {
|
||||||
|
this.cps = hap.value.cps;
|
||||||
|
this.num_ticks_since_cps_change = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -82,7 +97,8 @@ export class Cyclist {
|
|||||||
this.started = v;
|
this.started = v;
|
||||||
this.onToggle?.(v);
|
this.onToggle?.(v);
|
||||||
}
|
}
|
||||||
start() {
|
async start() {
|
||||||
|
await this.beforeStart?.();
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_cps_change = 0;
|
||||||
this.num_cycles_at_cps_change = 0;
|
this.num_cycles_at_cps_change = 0;
|
||||||
if (!this.pattern) {
|
if (!this.pattern) {
|
||||||
@@ -103,10 +119,10 @@ export class Cyclist {
|
|||||||
this.lastEnd = 0;
|
this.lastEnd = 0;
|
||||||
this.setStarted(false);
|
this.setStarted(false);
|
||||||
}
|
}
|
||||||
setPattern(pat, autostart = false) {
|
async setPattern(pat, autostart = false) {
|
||||||
this.pattern = pat;
|
this.pattern = pat;
|
||||||
if (autostart && !this.started) {
|
if (autostart && !this.started) {
|
||||||
this.start();
|
await this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCps(cps = 0.5) {
|
setCps(cps = 0.5) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
drawLine.mjs - <short description TODO>
|
drawLine.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/drawLine.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/drawLine.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+23
-24
@@ -2,7 +2,7 @@
|
|||||||
euclid.mjs - Bjorklund/Euclidean/Diaspora rhythms
|
euclid.mjs - Bjorklund/Euclidean/Diaspora rhythms
|
||||||
Copyright (C) 2023 Rohan Drape and strudel contributors
|
Copyright (C) 2023 Rohan Drape and strudel contributors
|
||||||
|
|
||||||
See <https://github.com/tidalcycles/strudel/blob/main/packages/core/euclid.mjs> for authors of this file.
|
See <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/euclid.mjs> for authors of this file.
|
||||||
|
|
||||||
The Bjorklund algorithm implementation is ported from the Haskell Music Theory Haskell module by Rohan Drape -
|
The Bjorklund algorithm implementation is ported from the Haskell Music Theory Haskell module by Rohan Drape -
|
||||||
https://rohandrape.net/?t=hmt
|
https://rohandrape.net/?t=hmt
|
||||||
@@ -10,9 +10,9 @@ https://rohandrape.net/?t=hmt
|
|||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Pattern, timeCat, register, silence } from './pattern.mjs';
|
import { timeCat, register, silence } from './pattern.mjs';
|
||||||
import { rotate, flatten, splitAt, zipWith } from './util.mjs';
|
import { rotate, flatten, splitAt, zipWith } from './util.mjs';
|
||||||
import Fraction from './fraction.mjs';
|
import Fraction, { lcm } from './fraction.mjs';
|
||||||
|
|
||||||
const left = function (n, x) {
|
const left = function (n, x) {
|
||||||
const [ons, offs] = n;
|
const [ons, offs] = n;
|
||||||
@@ -42,29 +42,26 @@ const _bjork = function (n, x) {
|
|||||||
|
|
||||||
export const bjork = function (ons, steps) {
|
export const bjork = function (ons, steps) {
|
||||||
const inverted = ons < 0;
|
const inverted = ons < 0;
|
||||||
ons = Math.abs(ons);
|
const absOns = Math.abs(ons);
|
||||||
const offs = steps - ons;
|
const offs = steps - absOns;
|
||||||
const x = Array(ons).fill([1]);
|
const ones = Array(absOns).fill([1]);
|
||||||
const y = Array(offs).fill([0]);
|
const zeros = Array(offs).fill([0]);
|
||||||
const result = _bjork([ons, offs], [x, y]);
|
const result = _bjork([absOns, offs], [ones, zeros]);
|
||||||
const p = flatten(result[1][0]).concat(flatten(result[1][1]));
|
const pattern = flatten(result[1][0]).concat(flatten(result[1][1]));
|
||||||
if (inverted) {
|
return inverted ? pattern.map((x) => 1 - x) : pattern;
|
||||||
return p.map((x) => (x === 0 ? 1 : 0));
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the structure of the pattern to form an euclidean rhythm.
|
* Changes the structure of the pattern to form an Euclidean rhythm.
|
||||||
* Euclidian rhythms are rhythms obtained using the greatest common
|
* Euclidean rhythms are rhythms obtained using the greatest common
|
||||||
* divisor of two numbers. They were described in 2004 by Godfried
|
* divisor of two numbers. They were described in 2004 by Godfried
|
||||||
* Toussaint, a canadian computer scientist. Euclidian rhythms are
|
* Toussaint, a Canadian computer scientist. Euclidean rhythms are
|
||||||
* really useful for computer/algorithmic music because they can
|
* really useful for computer/algorithmic music because they can
|
||||||
* describe a large number of rhythms with a couple of numbers.
|
* describe a large number of rhythms with a couple of numbers.
|
||||||
*
|
*
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @name euclid
|
* @name euclid
|
||||||
* @param {number} pulses the number of onsets / beats
|
* @param {number} pulses the number of onsets/beats
|
||||||
* @param {number} steps the number of steps to fill
|
* @param {number} steps the number of steps to fill
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
@@ -76,7 +73,7 @@ export const bjork = function (ons, steps) {
|
|||||||
* Like `euclid`, but has an additional parameter for 'rotating' the resulting sequence.
|
* Like `euclid`, but has an additional parameter for 'rotating' the resulting sequence.
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @name euclidRot
|
* @name euclidRot
|
||||||
* @param {number} pulses the number of onsets / beats
|
* @param {number} pulses the number of onsets/beats
|
||||||
* @param {number} steps the number of steps to fill
|
* @param {number} steps the number of steps to fill
|
||||||
* @param {number} rotation offset in steps
|
* @param {number} rotation offset in steps
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
@@ -86,13 +83,13 @@ export const bjork = function (ons, steps) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @example // A thirteenth century Persian rhythm called Khafif-e-ramal.
|
* @example // A thirteenth-century Persian rhythm called Khafif-e-ramal.
|
||||||
* note("c3").euclid(2,5)
|
* note("c3").euclid(2,5)
|
||||||
* @example // The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.
|
* @example // The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.
|
||||||
* note("c3").euclid(3,4)
|
* note("c3").euclid(3,4)
|
||||||
* @example // Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.
|
* @example // Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.
|
||||||
* note("c3").euclidRot(3,5,2)
|
* note("c3").euclidRot(3,5,2)
|
||||||
* @example // A Ruchenitza rhythm used in a Bulgarian folk-dance.
|
* @example // A Ruchenitza rhythm used in a Bulgarian folk dance.
|
||||||
* note("c3").euclid(3,7)
|
* note("c3").euclid(3,7)
|
||||||
* @example // The Cuban tresillo pattern.
|
* @example // The Cuban tresillo pattern.
|
||||||
* note("c3").euclid(3,8)
|
* note("c3").euclid(3,8)
|
||||||
@@ -151,8 +148,10 @@ export const { euclidrot, euclidRot } = register(['euclidrot', 'euclidRot'], fun
|
|||||||
* so there will be no gaps.
|
* so there will be no gaps.
|
||||||
* @name euclidLegato
|
* @name euclidLegato
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @param {number} pulses the number of onsets / beats
|
* @param {number} pulses the number of onsets/beats
|
||||||
* @param {number} steps the number of steps to fill
|
* @param {number} steps the number of steps to fill
|
||||||
|
* @param rotation offset in steps
|
||||||
|
* @param pat
|
||||||
* @example
|
* @example
|
||||||
* note("c3").euclidLegato(3,8)
|
* note("c3").euclidLegato(3,8)
|
||||||
*/
|
*/
|
||||||
@@ -161,13 +160,13 @@ const _euclidLegato = function (pulses, steps, rotation, pat) {
|
|||||||
if (pulses < 1) {
|
if (pulses < 1) {
|
||||||
return silence;
|
return silence;
|
||||||
}
|
}
|
||||||
const bin_pat = _euclidRot(pulses, steps, rotation);
|
const bin_pat = _euclidRot(pulses, steps, 0);
|
||||||
const gapless = bin_pat
|
const gapless = bin_pat
|
||||||
.join('')
|
.join('')
|
||||||
.split('1')
|
.split('1')
|
||||||
.slice(1)
|
.slice(1)
|
||||||
.map((s) => [s.length + 1, true]);
|
.map((s) => [s.length + 1, true]);
|
||||||
return pat.struct(timeCat(...gapless));
|
return pat.struct(timeCat(...gapless)).late(Fraction(rotation).div(steps));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const euclidLegato = register(['euclidLegato'], function (pulses, steps, pat) {
|
export const euclidLegato = register(['euclidLegato'], function (pulses, steps, pat) {
|
||||||
@@ -180,7 +179,7 @@ export const euclidLegato = register(['euclidLegato'], function (pulses, steps,
|
|||||||
* the resulting sequence
|
* the resulting sequence
|
||||||
* @name euclidLegatoRot
|
* @name euclidLegatoRot
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @param {number} pulses the number of onsets / beats
|
* @param {number} pulses the number of onsets/beats
|
||||||
* @param {number} steps the number of steps to fill
|
* @param {number} steps the number of steps to fill
|
||||||
* @param {number} rotation offset in steps
|
* @param {number} rotation offset in steps
|
||||||
* @example
|
* @example
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
evaluate.mjs - <short description TODO>
|
evaluate.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/evaluate.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/evaluate.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isPattern } from './index.mjs';
|
|
||||||
|
|
||||||
export const evalScope = async (...args) => {
|
export const evalScope = async (...args) => {
|
||||||
const results = await Promise.allSettled(args);
|
const results = await Promise.allSettled(args);
|
||||||
const modules = results.filter((result) => result.status === 'fulfilled').map((r) => r.value);
|
const modules = results.filter((result) => result.status === 'fulfilled').map((r) => r.value);
|
||||||
@@ -37,11 +35,12 @@ function safeEval(str, options = {}) {
|
|||||||
return Function(body)();
|
return Function(body)();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const evaluate = async (code, transpiler) => {
|
export const evaluate = async (code, transpiler, transpilerOptions) => {
|
||||||
let meta = {};
|
let meta = {};
|
||||||
|
|
||||||
if (transpiler) {
|
if (transpiler) {
|
||||||
// transform syntactically correct js code to semantically usable code
|
// transform syntactically correct js code to semantically usable code
|
||||||
const transpiled = transpiler(code);
|
const transpiled = transpiler(code, transpilerOptions);
|
||||||
code = transpiled.output;
|
code = transpiled.output;
|
||||||
meta = transpiled;
|
meta = transpiled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
fraction.mjs - <short description TODO>
|
fraction.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/fraction.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/fraction.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -119,10 +119,10 @@ export const lcm = (...fractions) => {
|
|||||||
if (fractions.length === 0) {
|
if (fractions.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const x = fractions.pop();
|
||||||
return fractions.reduce(
|
return fractions.reduce(
|
||||||
(lcm, fraction) => (lcm === undefined || fraction === undefined ? undefined : lcm.lcm(fraction)),
|
(lcm, fraction) => (lcm === undefined || fraction === undefined ? undefined : lcm.lcm(fraction)),
|
||||||
fraction(1),
|
x,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
hap.mjs - <short description TODO>
|
hap.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/hap.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/hap.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import Fraction from './fraction.mjs';
|
import Fraction from './fraction.mjs';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
index.mjs - <short description TODO>
|
index.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/index.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/index.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ export * from './controls.mjs';
|
|||||||
export * from './hap.mjs';
|
export * from './hap.mjs';
|
||||||
export * from './pattern.mjs';
|
export * from './pattern.mjs';
|
||||||
export * from './signal.mjs';
|
export * from './signal.mjs';
|
||||||
|
export * from './pick.mjs';
|
||||||
export * from './state.mjs';
|
export * from './state.mjs';
|
||||||
export * from './timespan.mjs';
|
export * from './timespan.mjs';
|
||||||
export * from './util.mjs';
|
export * from './util.mjs';
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
neocyclist.mjs - event scheduler like cyclist, except recieves clock pulses from clockworker in order to sync across multiple instances.
|
neocyclist.mjs - event scheduler like cyclist, except recieves clock pulses from clockworker in order to sync across multiple instances.
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/neocyclist.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/neocyclist.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
|
import { ClockCollator, cycleToSeconds } from './util.mjs';
|
||||||
|
|
||||||
export class NeoCyclist {
|
export class NeoCyclist {
|
||||||
constructor({ onTrigger, onToggle, getTime }) {
|
constructor({ onTrigger, onToggle, getTime }) {
|
||||||
@@ -13,79 +14,38 @@ export class NeoCyclist {
|
|||||||
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
this.getTime = getTime; // get absolute time
|
this.getTime = getTime; // get absolute time
|
||||||
this.time_at_last_tick_message = 0;
|
this.time_at_last_tick_message = 0;
|
||||||
|
// the clock of the worker and the audio context clock can drift apart over time
|
||||||
this.num_cycles_at_cps_change = 0;
|
// aditionally, the message time of the worker pinging the callback to process haps can be inconsistent.
|
||||||
|
// we need to keep a rolling average of the time difference between the worker clock and audio context clock
|
||||||
|
// in order to schedule events consistently.
|
||||||
|
this.collator = new ClockCollator({ getTargetClockTime: getTime });
|
||||||
this.onToggle = onToggle;
|
this.onToggle = onToggle;
|
||||||
this.latency = 0.1; // fixed trigger time offset
|
this.latency = 0.1; // fixed trigger time offset
|
||||||
this.cycle = 0;
|
this.cycle = 0;
|
||||||
this.id = Math.round(Date.now() * Math.random());
|
this.id = Math.round(Date.now() * Math.random());
|
||||||
this.worker_time_dif;
|
|
||||||
this.worker = new SharedWorker(new URL('./clockworker.js', import.meta.url));
|
this.worker = new SharedWorker(new URL('./clockworker.js', import.meta.url));
|
||||||
this.worker.port.start();
|
this.worker.port.start();
|
||||||
|
|
||||||
this.channel = new BroadcastChannel('strudeltick');
|
this.channel = new BroadcastChannel('strudeltick');
|
||||||
let weight = 0; // the amount of weight that is applied to the current average when averaging a new time dif
|
|
||||||
const maxWeight = 20;
|
|
||||||
const precision = 10 ** 3; //round off time diff to prevent accumulating outliers
|
|
||||||
|
|
||||||
// the clock of the worker and the audio context clock can drift apart over time
|
|
||||||
// aditionally, the message time of the worker pinging the callback to process haps can be inconsistent.
|
|
||||||
// we need to keep a rolling weighted average of the time difference between the worker clock and audio context clock
|
|
||||||
// in order to schedule events consistently.
|
|
||||||
const setTimeReference = (num_seconds_at_cps_change, num_seconds_since_cps_change, tickdeadline) => {
|
|
||||||
const time_dif = getTime() - (num_seconds_at_cps_change + num_seconds_since_cps_change) + tickdeadline;
|
|
||||||
if (this.worker_time_dif == null) {
|
|
||||||
this.worker_time_dif = time_dif;
|
|
||||||
} else {
|
|
||||||
const w = 1; //weight of new time diff;
|
|
||||||
const new_dif =
|
|
||||||
Math.round(((this.worker_time_dif * weight + time_dif * w) / (weight + w)) * precision) / precision;
|
|
||||||
|
|
||||||
if (new_dif != this.worker_time_dif) {
|
|
||||||
// reset the weight so the clock recovers faster from an audio context freeze/dropout if it happens
|
|
||||||
weight = 4;
|
|
||||||
}
|
|
||||||
this.worker_time_dif = new_dif;
|
|
||||||
}
|
|
||||||
weight = Math.min(weight + 1, maxWeight);
|
|
||||||
};
|
|
||||||
|
|
||||||
const tickCallback = (payload) => {
|
const tickCallback = (payload) => {
|
||||||
const {
|
const { cps, begin, end, cycle, time } = payload;
|
||||||
num_cycles_at_cps_change,
|
|
||||||
cps,
|
|
||||||
num_seconds_at_cps_change,
|
|
||||||
num_seconds_since_cps_change,
|
|
||||||
begin,
|
|
||||||
end,
|
|
||||||
tickdeadline,
|
|
||||||
cycle,
|
|
||||||
} = payload;
|
|
||||||
this.cps = cps;
|
this.cps = cps;
|
||||||
this.cycle = cycle;
|
this.cycle = cycle;
|
||||||
|
const currentTime = this.collator.calculateOffset(time) + time;
|
||||||
setTimeReference(num_seconds_at_cps_change, num_seconds_since_cps_change, tickdeadline);
|
processHaps(begin, end, currentTime);
|
||||||
|
this.time_at_last_tick_message = currentTime;
|
||||||
processHaps(begin, end, num_cycles_at_cps_change, num_seconds_at_cps_change);
|
|
||||||
|
|
||||||
this.time_at_last_tick_message = this.getTime();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const processHaps = (begin, end, num_cycles_at_cps_change, seconds_at_cps_change) => {
|
const processHaps = (begin, end, currentTime) => {
|
||||||
if (this.started === false) {
|
if (this.started === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const haps = this.pattern.queryArc(begin, end, { _cps: this.cps });
|
const haps = this.pattern.queryArc(begin, end, { _cps: this.cps });
|
||||||
|
|
||||||
haps.forEach((hap) => {
|
haps.forEach((hap) => {
|
||||||
if (hap.hasOnset()) {
|
if (hap.hasOnset()) {
|
||||||
const targetTime =
|
const timeUntilTrigger = cycleToSeconds(hap.whole.begin - this.cycle, this.cps);
|
||||||
(hap.whole.begin - num_cycles_at_cps_change) / this.cps +
|
const targetTime = timeUntilTrigger + currentTime + this.latency;
|
||||||
seconds_at_cps_change +
|
const duration = cycleToSeconds(hap.duration, this.cps);
|
||||||
this.latency +
|
|
||||||
this.worker_time_dif;
|
|
||||||
const duration = hap.duration / this.cps;
|
|
||||||
onTrigger?.(hap, 0, duration, this.cps, targetTime);
|
onTrigger?.(hap, 0, duration, this.cps, targetTime);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -129,8 +89,8 @@ export class NeoCyclist {
|
|||||||
this.setStarted(true);
|
this.setStarted(true);
|
||||||
}
|
}
|
||||||
stop() {
|
stop() {
|
||||||
this.worker_time_dif = null;
|
|
||||||
logger('[cyclist] stop');
|
logger('[cyclist] stop');
|
||||||
|
this.collator.reset();
|
||||||
this.setStarted(false);
|
this.setStarted(false);
|
||||||
}
|
}
|
||||||
setPattern(pat, autostart = false) {
|
setPattern(pat, autostart = false) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/core",
|
"name": "@strudel/core",
|
||||||
"version": "1.0.1",
|
"version": "1.2.2",
|
||||||
"description": "Port of Tidal Cycles to JavaScript",
|
"description": "Port of Tidal Cycles to JavaScript",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -9,12 +9,13 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
"bench": "vitest bench",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"prepublishOnly": "pnpm build"
|
"prepublishOnly": "pnpm build"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/tidalcycles/strudel.git"
|
"url": "git+https://codeberg.org/uzu/strudel.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"tidalcycles",
|
"tidalcycles",
|
||||||
@@ -26,15 +27,15 @@
|
|||||||
"author": "Alex McLean <alex@slab.org> (https://slab.org)",
|
"author": "Alex McLean <alex@slab.org> (https://slab.org)",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/tidalcycles/strudel/issues"
|
"url": "https://codeberg.org/uzu/strudel/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://strudel.cc",
|
"homepage": "https://strudel.cc",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fraction.js": "^4.3.7"
|
"fraction.js": "^5.2.1"
|
||||||
},
|
},
|
||||||
"gitHead": "0e26d4e741500f5bae35b023608f062a794905c2",
|
"gitHead": "0e26d4e741500f5bae35b023608f062a794905c2",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10",
|
"vite": "^6.0.11",
|
||||||
"vitest": "^1.1.0"
|
"vitest": "^3.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+614
-246
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
pick.mjs - methods that use one pattern to pick events from other patterns.
|
||||||
|
Copyright (C) 2024 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/signal.mjs>
|
||||||
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Pattern, reify, silence, register } from './pattern.mjs';
|
||||||
|
|
||||||
|
import { _mod, clamp, objectMap } from './util.mjs';
|
||||||
|
|
||||||
|
const _pick = function (lookup, pat, modulo = true) {
|
||||||
|
const array = Array.isArray(lookup);
|
||||||
|
const len = Object.keys(lookup).length;
|
||||||
|
|
||||||
|
lookup = objectMap(lookup, reify);
|
||||||
|
|
||||||
|
if (len === 0) {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
return pat.fmap((i) => {
|
||||||
|
let key = i;
|
||||||
|
if (array) {
|
||||||
|
key = modulo ? Math.round(key) % len : clamp(Math.round(key), 0, lookup.length - 1);
|
||||||
|
}
|
||||||
|
return lookup[key];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||||
|
* Similar to `inhabit`, but maintains the structure of the original patterns.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* note("<0 1 2!2 3>".pick(["g a", "e f", "f g f g" , "g c d"]))
|
||||||
|
* @example
|
||||||
|
* sound("<0 1 [2,0]>".pick(["bd sd", "cp cp", "hh hh"]))
|
||||||
|
* @example
|
||||||
|
* sound("<0!2 [0,1] 1>".pick(["bd(3,8)", "sd sd"]))
|
||||||
|
* @example
|
||||||
|
* s("<a!2 [a,b] b>".pick({a: "bd(3,8)", b: "sd sd"}))
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const pick = function (lookup, pat) {
|
||||||
|
// backward compatibility - the args used to be flipped
|
||||||
|
if (Array.isArray(pat)) {
|
||||||
|
[pat, lookup] = [lookup, pat];
|
||||||
|
}
|
||||||
|
return __pick(lookup, pat);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __pick = register('pick', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).innerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pick`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||||
|
* second one.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const pickmod = register('pickmod', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).innerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * pickF lets you use a pattern of numbers to pick which function to apply to another pattern.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {Pattern} lookup a pattern of indices
|
||||||
|
* @param {function[]} funcs the array of functions from which to pull
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* s("bd [rim hh]").pickF("<0 1 2>", [rev,jux(rev),fast(2)])
|
||||||
|
* @example
|
||||||
|
* note("<c2 d2>(3,8)").s("square")
|
||||||
|
* .pickF("<0 2> 1", [jux(rev),fast(2),x=>x.lpf(800)])
|
||||||
|
*/
|
||||||
|
export const pickF = register('pickF', function (lookup, funcs, pat) {
|
||||||
|
return pat.apply(pick(lookup, funcs));
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickF`, but if you pick a number greater than the size of the functions list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {Pattern} lookup a pattern of indices
|
||||||
|
* @param {function[]} funcs the array of functions from which to pull
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodF = register('pickmodF', function (lookup, funcs, pat) {
|
||||||
|
return pat.apply(pickmod(lookup, funcs));
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but it applies an outerJoin instead of an innerJoin.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickOut = register('pickOut', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).outerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickOut`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodOut = register('pickmodOut', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).outerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but the choosen pattern is restarted when its index is triggered.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickRestart = register('pickRestart', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).restartJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickRestart`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* "<a@2 b@2 c@2 d@2>".pickRestart({
|
||||||
|
a: n("0 1 2 0"),
|
||||||
|
b: n("2 3 4 ~"),
|
||||||
|
c: n("[4 5] [4 3] 2 0"),
|
||||||
|
d: n("0 -3 0 ~")
|
||||||
|
}).scale("C:major").s("piano")
|
||||||
|
*/
|
||||||
|
export const pickmodRestart = register('pickmodRestart', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).restartJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but the choosen pattern is reset when its index is triggered.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickReset = register('pickReset', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).resetJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickReset`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodReset = register('pickmodReset', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).resetJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||||
|
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
||||||
|
* @name inhabit
|
||||||
|
* @synonyms pickSqueeze
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* "<a b [a,b]>".inhabit({a: s("bd(3,8)"),
|
||||||
|
b: s("cp sd")
|
||||||
|
})
|
||||||
|
* @example
|
||||||
|
* s("a@2 [a b] a".inhabit({a: "bd(3,8)", b: "sd sd"})).slow(4)
|
||||||
|
*/
|
||||||
|
export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).squeezeJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `inhabit`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||||
|
* second one.
|
||||||
|
* @name inhabitmod
|
||||||
|
* @synonyms pickmodSqueeze
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const { inhabitmod, pickmodSqueeze } = register(['inhabitmod', 'pickmodSqueeze'], function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).squeezeJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick from the list of values (or patterns of values) via the index using the given
|
||||||
|
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* note(squeeze("<0@2 [1!2] 2>", ["g a", "f g f g" , "g a c d"]))
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const squeeze = (pat, xs) => {
|
||||||
|
xs = xs.map(reify);
|
||||||
|
if (xs.length == 0) {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
return pat
|
||||||
|
.fmap((i) => {
|
||||||
|
const key = _mod(Math.round(i), xs.length);
|
||||||
|
return xs[key];
|
||||||
|
})
|
||||||
|
.squeezeJoin();
|
||||||
|
};
|
||||||
+53
-7
@@ -10,6 +10,7 @@ export function repl({
|
|||||||
defaultOutput,
|
defaultOutput,
|
||||||
onEvalError,
|
onEvalError,
|
||||||
beforeEval,
|
beforeEval,
|
||||||
|
beforeStart,
|
||||||
afterEval,
|
afterEval,
|
||||||
getTime,
|
getTime,
|
||||||
transpiler,
|
transpiler,
|
||||||
@@ -19,6 +20,7 @@ export function repl({
|
|||||||
sync = false,
|
sync = false,
|
||||||
setInterval,
|
setInterval,
|
||||||
clearInterval,
|
clearInterval,
|
||||||
|
id,
|
||||||
}) {
|
}) {
|
||||||
const state = {
|
const state = {
|
||||||
schedulerError: undefined,
|
schedulerError: undefined,
|
||||||
@@ -32,6 +34,10 @@ export function repl({
|
|||||||
started: false,
|
started: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const transpilerOptions = {
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
|
||||||
const updateState = (update) => {
|
const updateState = (update) => {
|
||||||
Object.assign(state, update);
|
Object.assign(state, update);
|
||||||
state.isDirty = state.code !== state.activeCode;
|
state.isDirty = state.code !== state.activeCode;
|
||||||
@@ -48,6 +54,7 @@ export function repl({
|
|||||||
},
|
},
|
||||||
setInterval,
|
setInterval,
|
||||||
clearInterval,
|
clearInterval,
|
||||||
|
beforeStart,
|
||||||
};
|
};
|
||||||
|
|
||||||
// NeoCyclist uses a shared worker to communicate between instances, which is not supported on mobile chrome
|
// NeoCyclist uses a shared worker to communicate between instances, which is not supported on mobile chrome
|
||||||
@@ -56,17 +63,20 @@ export function repl({
|
|||||||
let pPatterns = {};
|
let pPatterns = {};
|
||||||
let anonymousIndex = 0;
|
let anonymousIndex = 0;
|
||||||
let allTransform;
|
let allTransform;
|
||||||
|
let eachTransform;
|
||||||
|
|
||||||
const hush = function () {
|
const hush = function () {
|
||||||
pPatterns = {};
|
pPatterns = {};
|
||||||
anonymousIndex = 0;
|
anonymousIndex = 0;
|
||||||
allTransform = undefined;
|
allTransform = undefined;
|
||||||
|
eachTransform = undefined;
|
||||||
return silence;
|
return silence;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setPattern = (pattern, autostart = true) => {
|
const setPattern = async (pattern, autostart = true) => {
|
||||||
pattern = editPattern?.(pattern) || pattern;
|
pattern = editPattern?.(pattern) || pattern;
|
||||||
scheduler.setPattern(pattern, autostart);
|
await scheduler.setPattern(pattern, autostart);
|
||||||
|
return pattern;
|
||||||
};
|
};
|
||||||
setTime(() => scheduler.now()); // TODO: refactor?
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
|
|
||||||
@@ -76,15 +86,42 @@ export function repl({
|
|||||||
const toggle = () => scheduler.toggle();
|
const toggle = () => scheduler.toggle();
|
||||||
const setCps = (cps) => scheduler.setCps(cps);
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
||||||
|
|
||||||
|
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
||||||
|
|
||||||
|
/** Applies a function to all the running patterns. Note that the patterns are groups together into a single `stack` before the function is applied. This is probably what you want, but see `each` for
|
||||||
|
* a version that applies the function to each pattern separately.
|
||||||
|
* ```
|
||||||
|
* $: sound("bd - cp sd")
|
||||||
|
* $: sound("hh*8")
|
||||||
|
* all(fast("<2 3>"))
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
* $: sound("bd - cp sd")
|
||||||
|
* $: sound("hh*8")
|
||||||
|
* all(x => x.pianoroll())
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
const all = function (transform) {
|
const all = function (transform) {
|
||||||
allTransform = transform;
|
allTransform = transform;
|
||||||
return silence;
|
return silence;
|
||||||
};
|
};
|
||||||
|
/** Applies a function to each of the running patterns separately. This is intended for future use with upcoming 'stepwise' features. See `all` for a version that applies the function to all the patterns stacked together into a single pattern.
|
||||||
|
* ```
|
||||||
|
* $: sound("bd - cp sd")
|
||||||
|
* $: sound("hh*8")
|
||||||
|
* each(fast("<2 3>"))
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
const each = function (transform) {
|
||||||
|
eachTransform = transform;
|
||||||
|
return silence;
|
||||||
|
};
|
||||||
|
|
||||||
// set pattern methods that use this repl via closure
|
// set pattern methods that use this repl via closure
|
||||||
const injectPatternMethods = () => {
|
const injectPatternMethods = () => {
|
||||||
Pattern.prototype.p = function (id) {
|
Pattern.prototype.p = function (id) {
|
||||||
if (id.startsWith('_') || id.endsWith('_')) {
|
if (typeof id === 'string' && (id.startsWith('_') || id.endsWith('_'))) {
|
||||||
// allows muting a pattern x with x_ or _x
|
// allows muting a pattern x with x_ or _x
|
||||||
return silence;
|
return silence;
|
||||||
}
|
}
|
||||||
@@ -123,6 +160,7 @@ export function repl({
|
|||||||
});
|
});
|
||||||
return evalScope({
|
return evalScope({
|
||||||
all,
|
all,
|
||||||
|
each,
|
||||||
hush,
|
hush,
|
||||||
cpm,
|
cpm,
|
||||||
setCps,
|
setCps,
|
||||||
@@ -139,11 +177,19 @@ export function repl({
|
|||||||
try {
|
try {
|
||||||
updateState({ code, pending: true });
|
updateState({ code, pending: true });
|
||||||
await injectPatternMethods();
|
await injectPatternMethods();
|
||||||
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
await beforeEval?.({ code });
|
await beforeEval?.({ code });
|
||||||
shouldHush && hush();
|
shouldHush && hush();
|
||||||
let { pattern, meta } = await _evaluate(code, transpiler);
|
let { pattern, meta } = await _evaluate(code, transpiler, transpilerOptions);
|
||||||
if (Object.keys(pPatterns).length) {
|
if (Object.keys(pPatterns).length) {
|
||||||
pattern = stack(...Object.values(pPatterns));
|
let patterns = Object.values(pPatterns);
|
||||||
|
if (eachTransform) {
|
||||||
|
// Explicit lambda so only element (not index and array) are passed
|
||||||
|
patterns = patterns.map((x) => eachTransform(x));
|
||||||
|
}
|
||||||
|
pattern = stack(...patterns);
|
||||||
|
} else if (eachTransform) {
|
||||||
|
pattern = eachTransform(pattern);
|
||||||
}
|
}
|
||||||
if (allTransform) {
|
if (allTransform) {
|
||||||
pattern = allTransform(pattern);
|
pattern = allTransform(pattern);
|
||||||
@@ -153,7 +199,7 @@ export function repl({
|
|||||||
throw new Error(message + (typeof evaluated === 'function' ? ', did you forget to call a function?' : '.'));
|
throw new Error(message + (typeof evaluated === 'function' ? ', did you forget to call a function?' : '.'));
|
||||||
}
|
}
|
||||||
logger(`[eval] code updated`);
|
logger(`[eval] code updated`);
|
||||||
setPattern(pattern, autostart);
|
pattern = await setPattern(pattern, autostart);
|
||||||
updateState({
|
updateState({
|
||||||
miniLocations: meta?.miniLocations || [],
|
miniLocations: meta?.miniLocations || [],
|
||||||
widgets: meta?.widgets || [],
|
widgets: meta?.widgets || [],
|
||||||
@@ -179,7 +225,7 @@ export function repl({
|
|||||||
export const getTrigger =
|
export const getTrigger =
|
||||||
({ getTime, defaultOutput }) =>
|
({ getTime, defaultOutput }) =>
|
||||||
async (hap, deadline, duration, cps, t) => {
|
async (hap, deadline, duration, cps, t) => {
|
||||||
// TODO: get rid of deadline after https://github.com/tidalcycles/strudel/pull/1004
|
// TODO: get rid of deadline after https://codeberg.org/uzu/strudel/pulls/1004
|
||||||
try {
|
try {
|
||||||
if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
|
if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
|
||||||
await defaultOutput(hap, deadline, duration, cps, t);
|
await defaultOutput(hap, deadline, duration, cps, t);
|
||||||
|
|||||||
+322
-235
@@ -1,13 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
signal.mjs - <short description TODO>
|
signal.mjs - continuous patterns
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/signal.mjs>
|
Copyright (C) 2024 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/signal.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Hap } from './hap.mjs';
|
import { Hap } from './hap.mjs';
|
||||||
import { Pattern, fastcat, reify, silence, stack, register } from './pattern.mjs';
|
import { Pattern, fastcat, pure, register, reify, silence, stack, sequenceP } from './pattern.mjs';
|
||||||
import Fraction from './fraction.mjs';
|
import Fraction from './fraction.mjs';
|
||||||
import { id, _mod, clamp, objectMap } from './util.mjs';
|
|
||||||
|
import { id, keyAlias, getCurrentKeyboardState } from './util.mjs';
|
||||||
|
|
||||||
export function steady(value) {
|
export function steady(value) {
|
||||||
// A continuous value
|
// A continuous value
|
||||||
@@ -15,13 +16,10 @@ export function steady(value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const signal = (func) => {
|
export const signal = (func) => {
|
||||||
const query = (state) => [new Hap(undefined, state.span, func(state.span.midpoint()))];
|
const query = (state) => [new Hap(undefined, state.span, func(state.span.begin))];
|
||||||
return new Pattern(query);
|
return new Pattern(query);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isaw = signal((t) => 1 - (t % 1));
|
|
||||||
export const isaw2 = isaw.toBipolar();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sawtooth signal between 0 and 1.
|
* A sawtooth signal between 0 and 1.
|
||||||
*
|
*
|
||||||
@@ -35,8 +33,40 @@ export const isaw2 = isaw.toBipolar();
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const saw = signal((t) => t % 1);
|
export const saw = signal((t) => t % 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sawtooth signal between -1 and 1 (like `saw`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
export const saw2 = saw.toBipolar();
|
export const saw2 = saw.toBipolar();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sawtooth signal between 1 and 0 (like `saw`, but flipped).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
* @example
|
||||||
|
* note("<c3 [eb3,g3] g2 [g3,bb3]>*8")
|
||||||
|
* .clip(isaw.slow(2))
|
||||||
|
* @example
|
||||||
|
* n(isaw.range(0,8).segment(8))
|
||||||
|
* .scale('C major')
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const isaw = signal((t) => 1 - (t % 1));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sawtooth signal between 1 and -1 (like `saw2`, but flipped).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
|
export const isaw2 = isaw.toBipolar();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sine signal between -1 and 1 (like `sine`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +90,12 @@ export const sine = sine2.fromBipolar();
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const cosine = sine._early(Fraction(1).div(4));
|
export const cosine = sine._early(Fraction(1).div(4));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cosine signal between -1 and 1 (like `cosine`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
export const cosine2 = sine2._early(Fraction(1).div(4));
|
export const cosine2 = sine2._early(Fraction(1).div(4));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,6 +107,12 @@ export const cosine2 = sine2._early(Fraction(1).div(4));
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const square = signal((t) => Math.floor((t * 2) % 2));
|
export const square = signal((t) => Math.floor((t * 2) % 2));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A square signal between -1 and 1 (like `square`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
export const square2 = square.toBipolar();
|
export const square2 = square.toBipolar();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,11 +123,71 @@ export const square2 = square.toBipolar();
|
|||||||
* n(tri.segment(8).range(0,7)).scale("C:minor")
|
* n(tri.segment(8).range(0,7)).scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const tri = fastcat(isaw, saw);
|
export const tri = fastcat(saw, isaw);
|
||||||
export const tri2 = fastcat(isaw2, saw2);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A triangle signal between -1 and 1 (like `tri`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
|
export const tri2 = fastcat(saw2, isaw2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An inverted triangle signal between 1 and 0 (like `tri`, but flipped).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
* @example
|
||||||
|
* n(itri.segment(8).range(0,7)).scale("C:minor")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const itri = fastcat(isaw, saw);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An inverted triangle signal between -1 and 1 (like `itri`, but bipolar).
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
|
export const itri2 = fastcat(isaw2, saw2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A signal representing the cycle time.
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
*/
|
||||||
export const time = signal(id);
|
export const time = signal(id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mouse's x position value ranges from 0 to 1.
|
||||||
|
* @name mousex
|
||||||
|
* @return {Pattern}
|
||||||
|
* @example
|
||||||
|
* n(mousex.segment(4).range(0,7)).scale("C:minor")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mouse's y position value ranges from 0 to 1.
|
||||||
|
* @name mousey
|
||||||
|
* @return {Pattern}
|
||||||
|
* @example
|
||||||
|
* n(mousey.segment(4).range(0,7)).scale("C:minor")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
let _mouseY = 0,
|
||||||
|
_mouseX = 0;
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
//document.onmousemove = (e) => {
|
||||||
|
document.addEventListener('mousemove', (e) => {
|
||||||
|
_mouseY = e.clientY / document.body.clientHeight;
|
||||||
|
_mouseX = e.clientX / document.body.clientWidth;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mousey = signal(() => _mouseY);
|
||||||
|
export const mouseY = signal(() => _mouseY);
|
||||||
|
export const mousex = signal(() => _mouseX);
|
||||||
|
export const mouseX = signal(() => _mouseX);
|
||||||
|
|
||||||
// random signals
|
// random signals
|
||||||
|
|
||||||
const xorwise = (x) => {
|
const xorwise = (x) => {
|
||||||
@@ -106,7 +208,7 @@ const timeToRand = (x) => Math.abs(intSeedToRand(timeToIntSeed(x)));
|
|||||||
const timeToRandsPrime = (seed, n) => {
|
const timeToRandsPrime = (seed, n) => {
|
||||||
const result = [];
|
const result = [];
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
for (let i = 0; i < n; ++n) {
|
for (let i = 0; i < n; ++i) {
|
||||||
result.push(intSeedToRand(seed));
|
result.push(intSeedToRand(seed));
|
||||||
seed = xorwise(seed);
|
seed = xorwise(seed);
|
||||||
}
|
}
|
||||||
@@ -125,7 +227,82 @@ const timeToRands = (t, n) => timeToRandsPrime(timeToIntSeed(t), n);
|
|||||||
* n(run(4)).scale("C4:pentatonic")
|
* n(run(4)).scale("C4:pentatonic")
|
||||||
* // n("0 1 2 3").scale("C4:pentatonic")
|
* // n("0 1 2 3").scale("C4:pentatonic")
|
||||||
*/
|
*/
|
||||||
export const run = (n) => saw.range(0, n).floor().segment(n);
|
export const run = (n) => saw.range(0, n).round().segment(n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a pattern from a binary number.
|
||||||
|
*
|
||||||
|
* @name binary
|
||||||
|
* @param {number} n - input number to convert to binary
|
||||||
|
* @example
|
||||||
|
* "hh".s().struct(binary(5))
|
||||||
|
* // "hh".s().struct("1 0 1")
|
||||||
|
*/
|
||||||
|
export const binary = (n) => {
|
||||||
|
const nBits = reify(n).log2(0).floor().add(1);
|
||||||
|
return binaryN(n, nBits);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a pattern from a binary number, padded to n bits long.
|
||||||
|
*
|
||||||
|
* @name binaryN
|
||||||
|
* @param {number} n - input number to convert to binary
|
||||||
|
* @param {number} nBits - pattern length, defaults to 16
|
||||||
|
* @example
|
||||||
|
* "hh".s().struct(binaryN(55532, 16))
|
||||||
|
* // "hh".s().struct("1 1 0 1 1 0 0 0 1 1 1 0 1 1 0 0")
|
||||||
|
*/
|
||||||
|
export const binaryN = (n, nBits = 16) => {
|
||||||
|
nBits = reify(nBits);
|
||||||
|
// Shift and mask, putting msb on the right-side
|
||||||
|
const bitPos = run(nBits).mul(-1).add(nBits.sub(1));
|
||||||
|
return reify(n).segment(nBits).brshift(bitPos).band(pure(1));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const randrun = (n) => {
|
||||||
|
return signal((t) => {
|
||||||
|
// Without adding 0.5, the first cycle is always 0,1,2,3,...
|
||||||
|
const rands = timeToRands(t.floor().add(0.5), n);
|
||||||
|
const nums = rands
|
||||||
|
.map((n, i) => [n, i])
|
||||||
|
.sort((a, b) => a[0] > b[0] - a[0] < b[0])
|
||||||
|
.map((x) => x[1]);
|
||||||
|
const i = t.cyclePos().mul(n).floor() % n;
|
||||||
|
return nums[i];
|
||||||
|
})._segment(n);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _rearrangeWith = (ipat, n, pat) => {
|
||||||
|
const pats = [...Array(n).keys()].map((i) => pat.zoom(Fraction(i).div(n), Fraction(i + 1).div(n)));
|
||||||
|
return ipat.fmap((i) => pats[i].repeatCycles(n)._fast(n)).innerJoin();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slices a pattern into the given number of parts, then plays those parts in random order.
|
||||||
|
* Each part will be played exactly once per cycle.
|
||||||
|
* @name shuffle
|
||||||
|
* @example
|
||||||
|
* note("c d e f").sound("piano").shuffle(4)
|
||||||
|
* @example
|
||||||
|
* note("c d e f".shuffle(4), "g").sound("piano")
|
||||||
|
*/
|
||||||
|
export const shuffle = register('shuffle', (n, pat) => {
|
||||||
|
return _rearrangeWith(randrun(n), n, pat);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slices a pattern into the given number of parts, then plays those parts at random. Similar to `shuffle`,
|
||||||
|
* but parts might be played more than once, or not at all, per cycle.
|
||||||
|
* @name scramble
|
||||||
|
* @example
|
||||||
|
* note("c d e f").sound("piano").scramble(4)
|
||||||
|
* @example
|
||||||
|
* note("c d e f".scramble(4), "g").sound("piano")
|
||||||
|
*/
|
||||||
|
export const scramble = register('scramble', (n, pat) => {
|
||||||
|
return _rearrangeWith(_irand(n)._segment(n), n, pat);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A continuous pattern of random numbers, between 0 and 1.
|
* A continuous pattern of random numbers, between 0 and 1.
|
||||||
@@ -177,204 +354,6 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i));
|
|||||||
*/
|
*/
|
||||||
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
|
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
|
||||||
|
|
||||||
const _pick = function (lookup, pat, modulo = true) {
|
|
||||||
const array = Array.isArray(lookup);
|
|
||||||
const len = Object.keys(lookup).length;
|
|
||||||
|
|
||||||
lookup = objectMap(lookup, reify);
|
|
||||||
|
|
||||||
if (len === 0) {
|
|
||||||
return silence;
|
|
||||||
}
|
|
||||||
return pat.fmap((i) => {
|
|
||||||
let key = i;
|
|
||||||
if (array) {
|
|
||||||
key = modulo ? Math.round(key) % len : clamp(Math.round(key), 0, lookup.length - 1);
|
|
||||||
}
|
|
||||||
return lookup[key];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
|
||||||
* Similar to `inhabit`, but maintains the structure of the original patterns.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
* @example
|
|
||||||
* note("<0 1 2!2 3>".pick(["g a", "e f", "f g f g" , "g c d"]))
|
|
||||||
* @example
|
|
||||||
* sound("<0 1 [2,0]>".pick(["bd sd", "cp cp", "hh hh"]))
|
|
||||||
* @example
|
|
||||||
* sound("<0!2 [0,1] 1>".pick(["bd(3,8)", "sd sd"]))
|
|
||||||
* @example
|
|
||||||
* s("<a!2 [a,b] b>".pick({a: "bd(3,8)", b: "sd sd"}))
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const pick = function (lookup, pat) {
|
|
||||||
// backward compatibility - the args used to be flipped
|
|
||||||
if (Array.isArray(pat)) {
|
|
||||||
[pat, lookup] = [lookup, pat];
|
|
||||||
}
|
|
||||||
return __pick(lookup, pat);
|
|
||||||
};
|
|
||||||
|
|
||||||
const __pick = register('pick', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, false).innerJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `pick`, but if you pick a number greater than the size of the list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
|
||||||
* second one.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const pickmod = register('pickmod', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, true).innerJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * pickF lets you use a pattern of numbers to pick which function to apply to another pattern.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {Pattern} lookup a pattern of indices
|
|
||||||
* @param {function[]} funcs the array of functions from which to pull
|
|
||||||
* @returns {Pattern}
|
|
||||||
* @example
|
|
||||||
* s("bd [rim hh]").pickF("<0 1 2>", [rev,jux(rev),fast(2)])
|
|
||||||
* @example
|
|
||||||
* note("<c2 d2>(3,8)").s("square")
|
|
||||||
* .pickF("<0 2> 1", [jux(rev),fast(2),x=>x.lpf(800)])
|
|
||||||
*/
|
|
||||||
export const pickF = register('pickF', function (lookup, funcs, pat) {
|
|
||||||
return pat.apply(pick(lookup, funcs));
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `pickF`, but if you pick a number greater than the size of the functions list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {Pattern} lookup a pattern of indices
|
|
||||||
* @param {function[]} funcs the array of functions from which to pull
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickmodF = register('pickmodF', function (lookup, funcs, pat) {
|
|
||||||
return pat.apply(pickmod(lookup, funcs));
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * Similar to `pick`, but it applies an outerJoin instead of an innerJoin.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickOut = register('pickOut', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, false).outerJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `pickOut`, but if you pick a number greater than the size of the list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickmodOut = register('pickmodOut', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, true).outerJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * Similar to `pick`, but the choosen pattern is restarted when its index is triggered.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickRestart = register('pickRestart', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, false).restartJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `pickRestart`, but if you pick a number greater than the size of the list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickmodRestart = register('pickmodRestart', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, true).restartJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * Similar to `pick`, but the choosen pattern is reset when its index is triggered.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickReset = register('pickReset', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, false).resetJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `pickReset`, but if you pick a number greater than the size of the list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
export const pickmodReset = register('pickmodReset', function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, true).resetJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
|
||||||
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
|
||||||
* @name inhabit
|
|
||||||
* @synonyms pickSqueeze
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
* @example
|
|
||||||
* "<a b [a,b]>".inhabit({a: s("bd(3,8)"),
|
|
||||||
b: s("cp sd")
|
|
||||||
})
|
|
||||||
* @example
|
|
||||||
* s("a@2 [a b] a".inhabit({a: "bd(3,8)", b: "sd sd"})).slow(4)
|
|
||||||
*/
|
|
||||||
export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, false).squeezeJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/** * The same as `inhabit`, but if you pick a number greater than the size of the list,
|
|
||||||
* it wraps around, rather than sticking at the maximum value.
|
|
||||||
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
|
||||||
* second one.
|
|
||||||
* @name inhabitmod
|
|
||||||
* @synonyms pickmodSqueeze
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const { inhabitmod, pickmodSqueeze } = register(['inhabitmod', 'pickmodSqueeze'], function (lookup, pat) {
|
|
||||||
return _pick(lookup, pat, true).squeezeJoin();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pick from the list of values (or patterns of values) via the index using the given
|
|
||||||
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
|
||||||
* @param {Pattern} pat
|
|
||||||
* @param {*} xs
|
|
||||||
* @returns {Pattern}
|
|
||||||
* @example
|
|
||||||
* note(squeeze("<0@2 [1!2] 2>", ["g a", "f g f g" , "g a c d"]))
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const squeeze = (pat, xs) => {
|
|
||||||
xs = xs.map(reify);
|
|
||||||
if (xs.length == 0) {
|
|
||||||
return silence;
|
|
||||||
}
|
|
||||||
return pat
|
|
||||||
.fmap((i) => {
|
|
||||||
const key = _mod(Math.round(i), xs.length);
|
|
||||||
return xs[key];
|
|
||||||
})
|
|
||||||
.squeezeJoin();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const __chooseWith = (pat, xs) => {
|
export const __chooseWith = (pat, xs) => {
|
||||||
xs = xs.map(reify);
|
xs = xs.map(reify);
|
||||||
if (xs.length == 0) {
|
if (xs.length == 0) {
|
||||||
@@ -454,19 +433,30 @@ export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs);
|
|||||||
export const randcat = chooseCycles;
|
export const randcat = chooseCycles;
|
||||||
|
|
||||||
const _wchooseWith = function (pat, ...pairs) {
|
const _wchooseWith = function (pat, ...pairs) {
|
||||||
|
// A list of patterns of values
|
||||||
const values = pairs.map((pair) => reify(pair[0]));
|
const values = pairs.map((pair) => reify(pair[0]));
|
||||||
|
|
||||||
|
// A list of weight patterns
|
||||||
const weights = [];
|
const weights = [];
|
||||||
let accum = 0;
|
|
||||||
|
let total = pure(0);
|
||||||
for (const pair of pairs) {
|
for (const pair of pairs) {
|
||||||
accum += pair[1];
|
// 'add' accepts either values or patterns of values here, so no need
|
||||||
weights.push(accum);
|
// to explicitly reify
|
||||||
|
total = total.add(pair[1]);
|
||||||
|
// accumulate our list of weight patterns
|
||||||
|
weights.push(total);
|
||||||
}
|
}
|
||||||
const total = accum;
|
// a pattern of lists of weights
|
||||||
|
const weightspat = sequenceP(weights);
|
||||||
|
|
||||||
|
// Takes a number from 0-1, returns a pattern of patterns of values
|
||||||
const match = function (r) {
|
const match = function (r) {
|
||||||
const find = r * total;
|
const findpat = total.mul(r);
|
||||||
return values[weights.findIndex((x) => x > find, weights)];
|
return weightspat.fmap((weights) => (find) => values[weights.findIndex((x) => x > find, weights)]).appLeft(findpat);
|
||||||
};
|
};
|
||||||
return pat.fmap(match);
|
// This returns a pattern of patterns.. The innerJoin is in wchooseCycles
|
||||||
|
return pat.bind(match);
|
||||||
};
|
};
|
||||||
|
|
||||||
const wchooseWith = (...args) => _wchooseWith(...args).outerJoin();
|
const wchooseWith = (...args) => _wchooseWith(...args).outerJoin();
|
||||||
@@ -488,18 +478,42 @@ export const wchoose = (...pairs) => wchooseWith(rand, ...pairs);
|
|||||||
* wchooseCycles(["bd",10], ["hh",1], ["sd",1]).s().fast(8)
|
* wchooseCycles(["bd",10], ["hh",1], ["sd",1]).s().fast(8)
|
||||||
* @example
|
* @example
|
||||||
* wchooseCycles(["bd bd bd",5], ["hh hh hh",3], ["sd sd sd",1]).fast(4).s()
|
* wchooseCycles(["bd bd bd",5], ["hh hh hh",3], ["sd sd sd",1]).fast(4).s()
|
||||||
|
* @example
|
||||||
|
* // The probability can itself be a pattern
|
||||||
|
* wchooseCycles(["bd(3,8)","<5 0>"], ["hh hh hh",3]).fast(4).s()
|
||||||
*/
|
*/
|
||||||
export const wchooseCycles = (...pairs) => _wchooseWith(rand.segment(1), ...pairs).innerJoin();
|
export const wchooseCycles = (...pairs) => _wchooseWith(rand.segment(1), ...pairs).innerJoin();
|
||||||
|
|
||||||
export const wrandcat = wchooseCycles;
|
export const wrandcat = wchooseCycles;
|
||||||
|
|
||||||
// this function expects pat to be a pattern of floats...
|
function _perlin(t) {
|
||||||
export const perlinWith = (pat) => {
|
let ta = Math.floor(t);
|
||||||
const pata = pat.fmap(Math.floor);
|
let tb = ta + 1;
|
||||||
const patb = pat.fmap((t) => Math.floor(t) + 1);
|
|
||||||
const smootherStep = (x) => 6.0 * x ** 5 - 15.0 * x ** 4 + 10.0 * x ** 3;
|
const smootherStep = (x) => 6.0 * x ** 5 - 15.0 * x ** 4 + 10.0 * x ** 3;
|
||||||
const interp = (x) => (a) => (b) => a + smootherStep(x) * (b - a);
|
const interp = (x) => (a) => (b) => a + smootherStep(x) * (b - a);
|
||||||
return pat.sub(pata).fmap(interp).appBoth(pata.fmap(timeToRand)).appBoth(patb.fmap(timeToRand));
|
const v = interp(t - ta)(timeToRand(ta))(timeToRand(tb));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
export const perlinWith = (tpat) => {
|
||||||
|
return tpat.fmap(_perlin);
|
||||||
|
};
|
||||||
|
|
||||||
|
function _berlin(t) {
|
||||||
|
const prevRidgeStartIndex = Math.floor(t);
|
||||||
|
const nextRidgeStartIndex = prevRidgeStartIndex + 1;
|
||||||
|
|
||||||
|
const prevRidgeBottomPoint = timeToRand(prevRidgeStartIndex);
|
||||||
|
const nextRidgeTopPoint = timeToRand(nextRidgeStartIndex) + prevRidgeBottomPoint;
|
||||||
|
|
||||||
|
const currentPercent = (t - prevRidgeStartIndex) / (nextRidgeStartIndex - prevRidgeStartIndex);
|
||||||
|
const interp = (a, b, t) => {
|
||||||
|
return a + (b - a) * t;
|
||||||
|
};
|
||||||
|
return interp(prevRidgeBottomPoint, nextRidgeTopPoint, currentPercent) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const berlinWith = (tpat) => {
|
||||||
|
return tpat.fmap(_berlin);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -513,8 +527,23 @@ export const perlinWith = (pat) => {
|
|||||||
*/
|
*/
|
||||||
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
||||||
|
|
||||||
export const degradeByWith = register('degradeByWith', (withPat, x, pat) =>
|
/**
|
||||||
pat.fmap((a) => (_) => a).appLeft(withPat.filterValues((v) => v > x)),
|
* Generates a continuous pattern of [berlin noise](conceived by Jame Coyne and Jade Rowland as a joke but turned out to be surprisingly cool and useful,
|
||||||
|
* like perlin noise but with sawtooth waves), in the range 0..1.
|
||||||
|
*
|
||||||
|
* @name berlin
|
||||||
|
* @example
|
||||||
|
* // ascending arpeggios
|
||||||
|
* n("0!16".add(berlin.fast(4).mul(14))).scale("d:minor")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const berlin = berlinWith(time.fmap((v) => Number(v)));
|
||||||
|
|
||||||
|
export const degradeByWith = register(
|
||||||
|
'degradeByWith',
|
||||||
|
(withPat, x, pat) => pat.fmap((a) => (_) => a).appLeft(withPat.filterValues((v) => v > x)),
|
||||||
|
true,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -530,10 +559,18 @@ export const degradeByWith = register('degradeByWith', (withPat, x, pat) =>
|
|||||||
* s("hh*8").degradeBy(0.2)
|
* s("hh*8").degradeBy(0.2)
|
||||||
* @example
|
* @example
|
||||||
* s("[hh?0.2]*8")
|
* s("[hh?0.2]*8")
|
||||||
|
* @example
|
||||||
|
* //beat generator
|
||||||
|
* s("bd").segment(16).degradeBy(.5).ribbon(16,1)
|
||||||
*/
|
*/
|
||||||
export const degradeBy = register('degradeBy', function (x, pat) {
|
export const degradeBy = register(
|
||||||
return pat._degradeByWith(rand, x);
|
'degradeBy',
|
||||||
});
|
function (x, pat) {
|
||||||
|
return pat._degradeByWith(rand, x);
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -547,7 +584,7 @@ export const degradeBy = register('degradeBy', function (x, pat) {
|
|||||||
* @example
|
* @example
|
||||||
* s("[hh?]*8")
|
* s("[hh?]*8")
|
||||||
*/
|
*/
|
||||||
export const degrade = register('degrade', (pat) => pat._degradeBy(0.5));
|
export const degrade = register('degrade', (pat) => pat._degradeBy(0.5), true, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inverse of `degradeBy`: Randomly removes events from the pattern by a given amount.
|
* Inverse of `degradeBy`: Randomly removes events from the pattern by a given amount.
|
||||||
@@ -567,12 +604,17 @@ export const degrade = register('degrade', (pat) => pat._degradeBy(0.5));
|
|||||||
* x => x.undegradeBy(0.8).pan(1)
|
* x => x.undegradeBy(0.8).pan(1)
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
export const undegradeBy = register('undegradeBy', function (x, pat) {
|
export const undegradeBy = register(
|
||||||
return pat._degradeByWith(
|
'undegradeBy',
|
||||||
rand.fmap((r) => 1 - r),
|
function (x, pat) {
|
||||||
x,
|
return pat._degradeByWith(
|
||||||
);
|
rand.fmap((r) => 1 - r),
|
||||||
});
|
x,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inverse of `degrade`: Randomly removes 50% of events from the pattern. Shorthand for `.undegradeBy(0.5)`
|
* Inverse of `degrade`: Randomly removes 50% of events from the pattern. Shorthand for `.undegradeBy(0.5)`
|
||||||
@@ -589,7 +631,7 @@ export const undegradeBy = register('undegradeBy', function (x, pat) {
|
|||||||
* x => x.undegrade().pan(1)
|
* x => x.undegrade().pan(1)
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5));
|
export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5), true, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -748,3 +790,48 @@ export const never = register('never', function (_, pat) {
|
|||||||
export const always = register('always', function (func, pat) {
|
export const always = register('always', function (func, pat) {
|
||||||
return func(pat);
|
return func(pat);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//keyname: string | Array<string>
|
||||||
|
//keyname reference: https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
|
||||||
|
export function _keyDown(keyname) {
|
||||||
|
if (Array.isArray(keyname) === false) {
|
||||||
|
keyname = [keyname];
|
||||||
|
}
|
||||||
|
const keyState = getCurrentKeyboardState();
|
||||||
|
return keyname.every((x) => {
|
||||||
|
const keyName = keyAlias.get(x) ?? x;
|
||||||
|
return keyState[keyName];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Do something on a keypress, or array of keypresses
|
||||||
|
* [Key name reference](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values)
|
||||||
|
*
|
||||||
|
* @name whenKey
|
||||||
|
* @memberof Pattern
|
||||||
|
* @returns Pattern
|
||||||
|
* @example
|
||||||
|
* s("bd(5,8)").whenKey("Control:j", x => x.segment(16).color("red")).whenKey("Control:i", x => x.fast(2).color("blue"))
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const whenKey = register('whenKey', function (input, func, pat) {
|
||||||
|
return pat.when(_keyDown(input), func);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* returns true when a key or array of keys is held
|
||||||
|
* [Key name reference](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values)
|
||||||
|
*
|
||||||
|
* @name keyDown
|
||||||
|
* @memberof Pattern
|
||||||
|
* @returns Pattern
|
||||||
|
* @example
|
||||||
|
* keyDown("Control:j").pick([s("bd(5,8)"), s("cp(3,8)")])
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const keyDown = register('keyDown', function (pat) {
|
||||||
|
return pat.fmap(_keyDown);
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
speak.mjs - <short description TODO>
|
speak.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/speak.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/speak.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
state.mjs - <short description TODO>
|
state.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/state.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/state.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
controls.test.mjs - <short description TODO>
|
controls.test.mjs - <short description TODO>
|
||||||
Copyright (C) 2023 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/controls.test.mjs>
|
Copyright (C) 2023 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/controls.test.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { s, pan } from '../controls.mjs';
|
import { s, pan, getControlName } from '../controls.mjs';
|
||||||
import { mini } from '../../mini/mini.mjs';
|
import { mini } from '../../mini/mini.mjs';
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import Fraction from '../fraction.mjs';
|
import Fraction from '../fraction.mjs';
|
||||||
@@ -30,13 +30,17 @@ describe('controls', () => {
|
|||||||
expect(s(mini('bd').pan(1)).firstCycleValues).toEqual([{ s: 'bd', pan: 1 }]);
|
expect(s(mini('bd').pan(1)).firstCycleValues).toEqual([{ s: 'bd', pan: 1 }]);
|
||||||
expect(s(mini('bd:1').pan(1)).firstCycleValues).toEqual([{ s: 'bd', n: 1, pan: 1 }]);
|
expect(s(mini('bd:1').pan(1)).firstCycleValues).toEqual([{ s: 'bd', n: 1, pan: 1 }]);
|
||||||
});
|
});
|
||||||
it('preserves tactus of the left pattern', () => {
|
it('preserves step count of the left pattern', () => {
|
||||||
expect(s(mini('bd cp mt').pan(mini('1 2 3 4'))).tactus).toEqual(Fraction(3));
|
expect(s(mini('bd cp mt').pan(mini('1 2 3 4')))._steps).toEqual(Fraction(3));
|
||||||
});
|
});
|
||||||
it('preserves tactus of the right pattern for .out', () => {
|
it('preserves step count of the right pattern for .out', () => {
|
||||||
expect(s(mini('bd cp mt').set.out(pan(mini('1 2 3 4')))).tactus).toEqual(Fraction(4));
|
expect(s(mini('bd cp mt').set.out(pan(mini('1 2 3 4'))))._steps).toEqual(Fraction(4));
|
||||||
});
|
});
|
||||||
it('combines tactus of the pattern for .mix as lcm', () => {
|
it('combines step count of the pattern for .mix as lcm', () => {
|
||||||
expect(s(mini('bd cp mt').set.mix(pan(mini('1 2 3 4')))).tactus).toEqual(Fraction(12));
|
expect(s(mini('bd cp mt').set.mix(pan(mini('1 2 3 4'))))._steps).toEqual(Fraction(12));
|
||||||
|
});
|
||||||
|
it('finds control name by alias', () => {
|
||||||
|
expect(getControlName('lpf')).toEqual('cutoff');
|
||||||
|
expect(getControlName('cutoff')).toEqual('cutoff');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
drawLine.test.mjs - <short description TODO>
|
drawLine.test.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/drawLine.test.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/drawLine.test.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import { bjork } from '../euclid.mjs';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { fastcat } from '../pattern.mjs';
|
||||||
|
|
||||||
|
describe('bjork', () => {
|
||||||
|
it('should apply bjorklund to ons and steps', () => {
|
||||||
|
expect(bjork(3, 8)).toStrictEqual([1, 0, 0, 1, 0, 0, 1, 0]);
|
||||||
|
expect(bjork(-3, 8)).toStrictEqual([0, 1, 1, 0, 1, 1, 0, 1]);
|
||||||
|
expect(bjork(8, 8)).toStrictEqual([1, 1, 1, 1, 1, 1, 1, 1]);
|
||||||
|
expect(bjork(-8, 8)).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
expect(bjork(5, 8)).toStrictEqual([1, 0, 1, 1, 0, 1, 1, 0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('euclid', () => {
|
||||||
|
it('Can create euclid', () => {
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclid(3, 8)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/8: a', '3/8 → 1/2: a', '3/4 → 7/8: a']);
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclid(5, 8)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/8: a', '1/4 → 3/8: a', '3/8 → 1/2: a', '5/8 → 3/4: a', '3/4 → 7/8: a']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('euclidRot', () => {
|
||||||
|
it('Can create euclidRot', () => {
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidRot(3, 8, 2)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/8: a', '1/4 → 3/8: a', '5/8 → 3/4: a']);
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidRot(5, 8, 2)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/8: a', '1/4 → 3/8: a', '1/2 → 5/8: a', '5/8 → 3/4: a', '7/8 → 1/1: a']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('euclidLegato', () => {
|
||||||
|
it('Can create euclidLegato', () => {
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidLegato(3, 8)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 3/8: a', '3/8 → 3/4: a', '3/4 → 1/1: a']);
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidLegato(5, 8)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/4: a', '1/4 → 3/8: a', '3/8 → 5/8: a', '5/8 → 3/4: a', '3/4 → 1/1: a']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('euclidLegatoRot', () => {
|
||||||
|
it('Can create euclidLegatoRot', () => {
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidLegatoRot(3, 8, 2)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/4: a', '1/4 → 5/8: a', '5/8 → 1/1: a']);
|
||||||
|
expect(
|
||||||
|
fastcat('a')
|
||||||
|
.euclidLegatoRot(5, 8, 2)
|
||||||
|
.firstCycle()
|
||||||
|
.sort((a, b) => a.part.begin.sub(b.part.begin))
|
||||||
|
.map((a) => a.showWhole(true)),
|
||||||
|
).toStrictEqual(['0/1 → 1/4: a', '1/4 → 1/2: a', '1/2 → 5/8: a', '5/8 → 7/8: a', '7/8 → 1/1: a']);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
fraction.test.mjs - <short description TODO>
|
fraction.test.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/fraction.test.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/fraction.test.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
pattern.test.mjs - <short description TODO>
|
pattern.test.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/pattern.test.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/pattern.test.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,8 +21,7 @@ import {
|
|||||||
cat,
|
cat,
|
||||||
sequence,
|
sequence,
|
||||||
palindrome,
|
palindrome,
|
||||||
s_polymeter,
|
polymeter,
|
||||||
s_polymeterSteps,
|
|
||||||
polyrhythm,
|
polyrhythm,
|
||||||
silence,
|
silence,
|
||||||
fast,
|
fast,
|
||||||
@@ -46,12 +45,13 @@ import {
|
|||||||
rev,
|
rev,
|
||||||
time,
|
time,
|
||||||
run,
|
run,
|
||||||
|
binaryN,
|
||||||
pick,
|
pick,
|
||||||
stackLeft,
|
stackLeft,
|
||||||
stackRight,
|
stackRight,
|
||||||
stackCentre,
|
stackCentre,
|
||||||
s_cat,
|
stepcat,
|
||||||
calculateTactus,
|
sometimes,
|
||||||
} from '../index.mjs';
|
} from '../index.mjs';
|
||||||
|
|
||||||
import { steady } from '../signal.mjs';
|
import { steady } from '../signal.mjs';
|
||||||
@@ -608,19 +608,12 @@ describe('Pattern', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('s_polymeter()', () => {
|
describe('polymeter()', () => {
|
||||||
it('Can layer up cycles, stepwise, with lists', () => {
|
it('Can layer up cycles, stepwise, with lists', () => {
|
||||||
expect(s_polymeterSteps(3, ['d', 'e']).firstCycle()).toStrictEqual(
|
expect(polymeter(['a', 'b', 'c'], ['d', 'e']).fast(2).firstCycle()).toStrictEqual(
|
||||||
fastcat(pure('d'), pure('e'), pure('d')).firstCycle(),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(s_polymeter(['a', 'b', 'c'], ['d', 'e']).fast(2).firstCycle()).toStrictEqual(
|
|
||||||
stack(sequence('a', 'b', 'c', 'a', 'b', 'c'), sequence('d', 'e', 'd', 'e', 'd', 'e')).firstCycle(),
|
stack(sequence('a', 'b', 'c', 'a', 'b', 'c'), sequence('d', 'e', 'd', 'e', 'd', 'e')).firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Can layer up cycles, stepwise, with weighted patterns', () => {
|
|
||||||
sameFirst(s_polymeterSteps(3, sequence('a', 'b')).fast(2), sequence('a', 'b', 'a', 'b', 'a', 'b'));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('firstOf()', () => {
|
describe('firstOf()', () => {
|
||||||
@@ -735,21 +728,15 @@ describe('Pattern', () => {
|
|||||||
describe('signal()', () => {
|
describe('signal()', () => {
|
||||||
it('Can make saw/saw2', () => {
|
it('Can make saw/saw2', () => {
|
||||||
expect(saw.struct(true, true, true, true).firstCycle()).toStrictEqual(
|
expect(saw.struct(true, true, true, true).firstCycle()).toStrictEqual(
|
||||||
sequence(1 / 8, 3 / 8, 5 / 8, 7 / 8).firstCycle(),
|
sequence(0, 1 / 4, 1 / 2, 3 / 4).firstCycle(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(saw2.struct(true, true, true, true).firstCycle()).toStrictEqual(
|
expect(saw2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(-1, -0.5, 0, 0.5).firstCycle());
|
||||||
sequence(-3 / 4, -1 / 4, 1 / 4, 3 / 4).firstCycle(),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('Can make isaw/isaw2', () => {
|
it('Can make isaw/isaw2', () => {
|
||||||
expect(isaw.struct(true, true, true, true).firstCycle()).toStrictEqual(
|
expect(isaw.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0.75, 0.5, 0.25).firstCycle());
|
||||||
sequence(7 / 8, 5 / 8, 3 / 8, 1 / 8).firstCycle(),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(isaw2.struct(true, true, true, true).firstCycle()).toStrictEqual(
|
expect(isaw2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0.5, 0, -0.5).firstCycle());
|
||||||
sequence(3 / 4, 1 / 4, -1 / 4, -3 / 4).firstCycle(),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('_setContext()', () => {
|
describe('_setContext()', () => {
|
||||||
@@ -887,7 +874,7 @@ describe('Pattern', () => {
|
|||||||
.squeezeJoin()
|
.squeezeJoin()
|
||||||
.queryArc(3, 4)
|
.queryArc(3, 4)
|
||||||
.map((x) => x.value),
|
.map((x) => x.value),
|
||||||
).toStrictEqual([Fraction(3.5)]);
|
).toStrictEqual([Fraction(3)]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('ply', () => {
|
describe('ply', () => {
|
||||||
@@ -937,6 +924,9 @@ describe('Pattern', () => {
|
|||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('Can chop chops', () => {
|
||||||
|
expect(pure({ s: 'bev' }).chop(2).chop(2).firstCycle()).toStrictEqual(pure({ s: 'bev' }).chop(4).firstCycle());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('range', () => {
|
describe('range', () => {
|
||||||
it('Can be patterned', () => {
|
it('Can be patterned', () => {
|
||||||
@@ -955,6 +945,18 @@ describe('Pattern', () => {
|
|||||||
expect(run(4).firstCycle()).toStrictEqual(sequence(0, 1, 2, 3).firstCycle());
|
expect(run(4).firstCycle()).toStrictEqual(sequence(0, 1, 2, 3).firstCycle());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('binaryN', () => {
|
||||||
|
it('Can make a binary pattern from a decimal', () => {
|
||||||
|
expect(binaryN(55532).firstCycle()).toStrictEqual(
|
||||||
|
sequence(1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0).firstCycle(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Can make a binary pattern from patterned inputs', () => {
|
||||||
|
expect(binaryN(pure(0x1337), pure(14)).firstCycle()).toStrictEqual(
|
||||||
|
sequence(0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1).firstCycle(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('ribbon', () => {
|
describe('ribbon', () => {
|
||||||
it('Can ribbon', () => {
|
it('Can ribbon', () => {
|
||||||
expect(cat(0, 1, 2, 3, 4, 5, 6, 7).ribbon(2, 4).fast(4).firstCycle()).toStrictEqual(
|
expect(cat(0, 1, 2, 3, 4, 5, 6, 7).ribbon(2, 4).fast(4).firstCycle()).toStrictEqual(
|
||||||
@@ -1124,89 +1126,145 @@ describe('Pattern', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('tactus', () => {
|
describe('_steps', () => {
|
||||||
it('Is correctly preserved/calculated through transformations', () => {
|
it('Is correctly preserved/calculated through transformations', () => {
|
||||||
expect(sequence(0, 1, 2, 3).linger(4).tactus).toStrictEqual(Fraction(4));
|
expect(sequence(0, 1, 2, 3).linger(4)._steps).toStrictEqual(Fraction(4));
|
||||||
expect(sequence(0, 1, 2, 3).iter(4).tactus).toStrictEqual(Fraction(4));
|
expect(sequence(0, 1, 2, 3).iter(4)._steps).toStrictEqual(Fraction(4));
|
||||||
expect(sequence(0, 1, 2, 3).fast(4).tactus).toStrictEqual(Fraction(4));
|
expect(sequence(0, 1, 2, 3).fast(4)._steps).toStrictEqual(Fraction(4));
|
||||||
expect(sequence(0, 1, 2, 3).hurry(4).tactus).toStrictEqual(Fraction(4));
|
expect(sequence(0, 1, 2, 3).hurry(4)._steps).toStrictEqual(Fraction(4));
|
||||||
expect(sequence(0, 1, 2, 3).rev().tactus).toStrictEqual(Fraction(4));
|
expect(sequence(0, 1, 2, 3).rev()._steps).toStrictEqual(Fraction(4));
|
||||||
expect(sequence(1).segment(10).tactus).toStrictEqual(Fraction(10));
|
expect(sequence(1).segment(10)._steps).toStrictEqual(Fraction(10));
|
||||||
expect(sequence(1, 0, 1).invert().tactus).toStrictEqual(Fraction(3));
|
expect(sequence(1, 0, 1).invert()._steps).toStrictEqual(Fraction(3));
|
||||||
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).chop(4).tactus).toStrictEqual(Fraction(8));
|
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).chop(4)._steps).toStrictEqual(Fraction(8));
|
||||||
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).striate(4).tactus).toStrictEqual(Fraction(8));
|
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).striate(4)._steps).toStrictEqual(Fraction(8));
|
||||||
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).slice(4, sequence(0, 1, 2, 3)).tactus).toStrictEqual(
|
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).slice(4, sequence(0, 1, 2, 3))._steps).toStrictEqual(
|
||||||
Fraction(4),
|
Fraction(4),
|
||||||
);
|
);
|
||||||
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).splice(4, sequence(0, 1, 2, 3)).tactus).toStrictEqual(
|
expect(sequence({ s: 'bev' }, { s: 'amenbreak' }).splice(4, sequence(0, 1, 2, 3))._steps).toStrictEqual(
|
||||||
Fraction(4),
|
Fraction(4),
|
||||||
);
|
);
|
||||||
expect(sequence({ n: 0 }, { n: 1 }, { n: 2 }).chop(4).tactus).toStrictEqual(Fraction(12));
|
expect(sequence({ n: 0 }, { n: 1 }, { n: 2 }).chop(4)._steps).toStrictEqual(Fraction(12));
|
||||||
expect(
|
expect(
|
||||||
pure((x) => x + 1)
|
pure((x) => x + 1)
|
||||||
.setTactus(3)
|
.setSteps(3)
|
||||||
.appBoth(pure(1).setTactus(2)).tactus,
|
.appBoth(pure(1).setSteps(2))._steps,
|
||||||
).toStrictEqual(Fraction(6));
|
).toStrictEqual(Fraction(6));
|
||||||
expect(
|
expect(
|
||||||
pure((x) => x + 1)
|
pure((x) => x + 1)
|
||||||
.setTactus(undefined)
|
.setSteps(undefined)
|
||||||
.appBoth(pure(1).setTactus(2)).tactus,
|
.appBoth(pure(1).setSteps(2))._steps,
|
||||||
).toStrictEqual(Fraction(2));
|
).toStrictEqual(Fraction(2));
|
||||||
expect(
|
expect(
|
||||||
pure((x) => x + 1)
|
pure((x) => x + 1)
|
||||||
.setTactus(3)
|
.setSteps(3)
|
||||||
.appBoth(pure(1).setTactus(undefined)).tactus,
|
.appBoth(pure(1).setSteps(undefined))._steps,
|
||||||
).toStrictEqual(Fraction(3));
|
).toStrictEqual(Fraction(3));
|
||||||
expect(stack(fastcat(0, 1, 2), fastcat(3, 4)).tactus).toStrictEqual(Fraction(6));
|
expect(stack(fastcat(0, 1, 2), fastcat(3, 4))._steps).toStrictEqual(Fraction(6));
|
||||||
expect(stack(fastcat(0, 1, 2), fastcat(3, 4).setTactus(undefined)).tactus).toStrictEqual(Fraction(3));
|
expect(stack(fastcat(0, 1, 2), fastcat(3, 4).setSteps(undefined))._steps).toStrictEqual(Fraction(3));
|
||||||
expect(stackLeft(fastcat(0, 1, 2, 3), fastcat(3, 4)).tactus).toStrictEqual(Fraction(4));
|
expect(stackLeft(fastcat(0, 1, 2, 3), fastcat(3, 4))._steps).toStrictEqual(Fraction(4));
|
||||||
expect(stackRight(fastcat(0, 1, 2), fastcat(3, 4)).tactus).toStrictEqual(Fraction(3));
|
expect(stackRight(fastcat(0, 1, 2), fastcat(3, 4))._steps).toStrictEqual(Fraction(3));
|
||||||
// maybe this should double when they are either all even or all odd
|
// maybe this should double when they are either all even or all odd
|
||||||
expect(stackCentre(fastcat(0, 1, 2), fastcat(3, 4)).tactus).toStrictEqual(Fraction(3));
|
expect(stackCentre(fastcat(0, 1, 2), fastcat(3, 4))._steps).toStrictEqual(Fraction(3));
|
||||||
expect(fastcat(0, 1).ply(3).tactus).toStrictEqual(Fraction(6));
|
expect(fastcat(0, 1).ply(3)._steps).toStrictEqual(Fraction(6));
|
||||||
expect(fastcat(0, 1).setTactus(undefined).ply(3).tactus).toStrictEqual(undefined);
|
expect(fastcat(0, 1).setSteps(undefined).ply(3)._steps).toStrictEqual(undefined);
|
||||||
expect(fastcat(0, 1).fast(3).tactus).toStrictEqual(Fraction(2));
|
expect(fastcat(0, 1).fast(3)._steps).toStrictEqual(Fraction(2));
|
||||||
expect(fastcat(0, 1).setTactus(undefined).fast(3).tactus).toStrictEqual(undefined);
|
expect(fastcat(0, 1).setSteps(undefined).fast(3)._steps).toStrictEqual(undefined);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('s_cat', () => {
|
describe('stepcat', () => {
|
||||||
it('can cat', () => {
|
it('can cat', () => {
|
||||||
expect(sameFirst(s_cat(fastcat(0, 1, 2, 3), fastcat(4, 5)), fastcat(0, 1, 2, 3, 4, 5)));
|
expect(sameFirst(stepcat(fastcat(0, 1, 2, 3), fastcat(4, 5)), fastcat(0, 1, 2, 3, 4, 5)));
|
||||||
expect(sameFirst(s_cat(pure(1), pure(2), pure(3)), fastcat(1, 2, 3)));
|
expect(sameFirst(stepcat(pure(1), pure(2), pure(3)), fastcat(1, 2, 3)));
|
||||||
});
|
});
|
||||||
it('calculates undefined tactuses as the average', () => {
|
it('calculates undefined steps as the average', () => {
|
||||||
expect(sameFirst(s_cat(pure(1), pure(2), pure(3).setTactus(undefined)), fastcat(1, 2, 3)));
|
expect(sameFirst(stepcat(pure(1), pure(2), pure(3).setSteps(undefined)), fastcat(1, 2, 3)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('s_taper', () => {
|
describe('shrink', () => {
|
||||||
it('can taper', () => {
|
it('can shrink', () => {
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_taper(1, 5), sequence(0, 1, 2, 3, 4, 0, 1, 2, 3, 0, 1, 2, 0, 1, 0)));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).shrink(1), sequence(0, 1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 3, 4, 4)));
|
||||||
});
|
});
|
||||||
it('can taper backwards', () => {
|
it('can shrink backwards', () => {
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_taper(-1, 5), sequence(0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4)));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).shrink(-1), sequence(0, 1, 2, 3, 4, 0, 1, 2, 3, 0, 1, 2, 0, 1, 0)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('s_add and s_sub', () => {
|
describe('grow', () => {
|
||||||
it('can add from the left', () => {
|
it('can grow', () => {
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_add(2), sequence(0, 1)));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).grow(1), sequence(0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4)));
|
||||||
});
|
});
|
||||||
it('can sub to the left', () => {
|
it('can grow backwards', () => {
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_sub(2), sequence(0, 1, 2)));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).grow(-1), sequence(4, 3, 4, 2, 3, 4, 1, 2, 3, 4, 0, 1, 2, 3, 4)));
|
||||||
});
|
});
|
||||||
it('can add from the right', () => {
|
});
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_add(-2), sequence(3, 4)));
|
describe('take and drop', () => {
|
||||||
|
it('can take from the left', () => {
|
||||||
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).take(2), sequence(0, 1)));
|
||||||
});
|
});
|
||||||
it('can sub to the right', () => {
|
it('can drop from the left', () => {
|
||||||
expect(sameFirst(sequence(0, 1, 2, 3, 4).s_sub(-2), sequence(2, 3, 4)));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).drop(2), sequence(2, 3, 4)));
|
||||||
});
|
});
|
||||||
it('can subtract nothing', () => {
|
it('can take from the right', () => {
|
||||||
expect(sameFirst(pure('a').s_sub(0), pure('a')));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).take(-2), sequence(3, 4)));
|
||||||
});
|
});
|
||||||
it('can subtract nothing, repeatedly', () => {
|
it('can drop from the right', () => {
|
||||||
expect(sameFirst(pure('a').s_sub(0, 0), fastcat('a', 'a')));
|
expect(sameFirst(sequence(0, 1, 2, 3, 4).drop(-2), sequence(0, 1, 2)));
|
||||||
|
});
|
||||||
|
it('can drop nothing', () => {
|
||||||
|
expect(sameFirst(pure('a').drop(0), pure('a')));
|
||||||
|
});
|
||||||
|
it('can drop nothing, repeatedly', () => {
|
||||||
|
expect(sameFirst(pure('a').drop(0, 0), fastcat('a', 'a')));
|
||||||
for (var i = 0; i < 100; ++i) {
|
for (var i = 0; i < 100; ++i) {
|
||||||
expect(sameFirst(pure('a').s_sub(...Array(i).fill(0)), fastcat(...Array(i).fill('a'))));
|
expect(sameFirst(pure('a').drop(...Array(i).fill(0)), fastcat(...Array(i).fill('a'))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('expand', () => {
|
||||||
|
it('can expand four things in half', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(sequence(0, 1, 2, 3).expand(1, 0.5), stepcat(sequence(0, 1, 2, 3), sequence(0, 1, 2, 3).expand(0.5))),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('can expand five things in half', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence(0, 1, 2, 3, 4).expand(1, 0.5),
|
||||||
|
stepcat(sequence(0, 1, 2, 3, 4), sequence(0, 1, 2, 3, 4).expand(0.5)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('stepJoin', () => {
|
||||||
|
it('can join a pattern with steps of 2', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence(pure(pure('a')), pure(pure('b').setSteps(2))).stepJoin(),
|
||||||
|
stepcat(pure('a'), pure('b').setSteps(2)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('can join a pattern with steps of 0.5', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence(pure(pure('a')), pure(pure('b').setSteps(0.5))).stepJoin(),
|
||||||
|
stepcat(pure('a'), pure('b').setSteps(0.5)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('loopAt', () => {
|
||||||
|
it('maintains steps', () => {
|
||||||
|
expect(s('bev').chop(8).loopAt(2)._steps).toStrictEqual(Fraction(4));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('bite', () => {
|
||||||
|
it('works with uneven patterns', () => {
|
||||||
|
sameFirst(
|
||||||
|
fastcat(slowcat('a', 'b', 'c', 'd', 'e'), slowcat(1, 2, 3, 4, 5))
|
||||||
|
.bite(2, stepcat(pure(0), pure(1).expand(2)))
|
||||||
|
.fast(5),
|
||||||
|
stepcat(slowcat('a', 'b', 'c', 'd', 'e'), slowcat(1, 2, 3, 4, 5).expand(2)).fast(5),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
util.test.mjs - Tests for the core 'util' module
|
util.test.mjs - Tests for the core 'util' module
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/util.test.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/util.test.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { pure } from '../pattern.mjs';
|
import { pure } from '../pattern.mjs';
|
||||||
import {
|
import {
|
||||||
isNote,
|
|
||||||
tokenizeNote,
|
|
||||||
noteToMidi,
|
|
||||||
midiToFreq,
|
|
||||||
freqToMidi,
|
|
||||||
_mod,
|
_mod,
|
||||||
compose,
|
compose,
|
||||||
|
flatten,
|
||||||
|
fractionalArgs,
|
||||||
|
freqToMidi,
|
||||||
getFrequency,
|
getFrequency,
|
||||||
getPlayableNoteValue,
|
getPlayableNoteValue,
|
||||||
parseNumeral,
|
isNote,
|
||||||
parseFractional,
|
midiToFreq,
|
||||||
|
noteToMidi,
|
||||||
numeralArgs,
|
numeralArgs,
|
||||||
fractionalArgs,
|
parseFractional,
|
||||||
|
parseNumeral,
|
||||||
|
rotate,
|
||||||
|
splitAt,
|
||||||
|
tokenizeNote,
|
||||||
|
zipWith,
|
||||||
} from '../util.mjs';
|
} from '../util.mjs';
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
describe('isNote', () => {
|
describe('isNote', () => {
|
||||||
it('should recognize notes without accidentals', () => {
|
it('should recognize notes without accidentals', () => {
|
||||||
@@ -233,3 +237,46 @@ describe('fractionalArgs', () => {
|
|||||||
expect(add('q', 2)).toBe(2.25);
|
expect(add('q', 2)).toBe(2.25);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('rotate', () => {
|
||||||
|
it('should rotate array to the left', () => {
|
||||||
|
expect(rotate([0, 1, 2, 3], 2)).toStrictEqual([2, 3, 0, 1]);
|
||||||
|
expect(rotate([0, 1, 2, 3], 0)).toStrictEqual([0, 1, 2, 3]);
|
||||||
|
expect(rotate([0, 1, 2, 3], -3)).toStrictEqual([1, 2, 3, 0]);
|
||||||
|
expect(rotate([0, 1, 2, 3], 3)).toStrictEqual([3, 0, 1, 2]);
|
||||||
|
expect(rotate([0], 3)).toStrictEqual([0]);
|
||||||
|
expect(rotate([], 3)).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('flatten', () => {
|
||||||
|
it('should flatten array by one level', () => {
|
||||||
|
expect(flatten([0, 1, 2, 3])).toStrictEqual([0, 1, 2, 3]);
|
||||||
|
expect(flatten([0, 1, [2, 3]])).toStrictEqual([0, 1, 2, 3]);
|
||||||
|
expect(flatten([0, [1, [2, 3]]])).toStrictEqual([0, 1, [2, 3]]);
|
||||||
|
expect(flatten([0])).toStrictEqual([0]);
|
||||||
|
expect(flatten([])).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('splitAt', () => {
|
||||||
|
it('should split array into two', () => {
|
||||||
|
expect(splitAt(2, [0, 1, 2, 3])).toStrictEqual([
|
||||||
|
[0, 1],
|
||||||
|
[2, 3],
|
||||||
|
]);
|
||||||
|
expect(splitAt(0, [0, 1, 2, 3])).toStrictEqual([[], [0, 1, 2, 3]]);
|
||||||
|
expect(splitAt(-3, [0, 1, 2, 3])).toStrictEqual([[0], [1, 2, 3]]);
|
||||||
|
expect(splitAt(3, [0, 1, 2, 3])).toStrictEqual([[0, 1, 2], [3]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('zipWith', () => {
|
||||||
|
it('should use the function to combine the two arrays element-wise', () => {
|
||||||
|
expect(zipWith((a, b) => a + b, [0, 1, 2, 3], [0, 1, 2, 3])).toStrictEqual([0, 2, 4, 6]);
|
||||||
|
expect(zipWith((a, b) => a + b, [0, 1, 2, 3], [0, 1, 2])).toStrictEqual([0, 2, 4, NaN]);
|
||||||
|
expect(zipWith((a, b) => a + b, [0, 1, 2], [0, 1, 2, 3])).toStrictEqual([0, 2, 4]);
|
||||||
|
expect(zipWith((a) => a, [0, 1, 2], [1, 2, 3, 0])).toStrictEqual([0, 1, 2]);
|
||||||
|
expect(zipWith((a, b) => b, [0, 1, 2], [1, 2, 3, 0])).toStrictEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
value.test.mjs - <short description TODO>
|
value.test.mjs - <short description TODO>
|
||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/value.test.mjs>
|
Copyright (C) 2025 Strudel contributors - see <https://codeberg.org/uzu/strudel/activity/contributors>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user