max / makenotwork
39 files changed,
+0 insertions,
-2422 deletions
| @@ -14,9 +14,7 @@ MNW/ | |||
| 14 | 14 | docengine/ Markdown rendering + documentation engine | |
| 15 | 15 | tagtree/ Hierarchical tag standard | |
| 16 | 16 | synckit-client/ SyncKit cloud sync client SDK | |
| 17 | - | theme-common/ Theme loading + parsing (TOML themes) | |
| 18 | 17 | s3-storage/ S3-compatible storage abstraction | |
| 19 | - | themes/ TOML theme definitions (24 themes) | |
| 20 | 18 | tauri-updater-ui/ OTA update UI components | |
| 21 | 19 | ``` | |
| 22 | 20 |
| @@ -1,504 +0,0 @@ | |||
| 1 | - | # This file is automatically @generated by Cargo. | |
| 2 | - | # It is not intended for manual editing. | |
| 3 | - | version = 4 | |
| 4 | - | ||
| 5 | - | [[package]] | |
| 6 | - | name = "anyhow" | |
| 7 | - | version = "1.0.102" | |
| 8 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | - | checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" | |
| 10 | - | ||
| 11 | - | [[package]] | |
| 12 | - | name = "bitflags" | |
| 13 | - | version = "2.11.0" | |
| 14 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 15 | - | checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" | |
| 16 | - | ||
| 17 | - | [[package]] | |
| 18 | - | name = "cfg-if" | |
| 19 | - | version = "1.0.4" | |
| 20 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 21 | - | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" | |
| 22 | - | ||
| 23 | - | [[package]] | |
| 24 | - | name = "equivalent" | |
| 25 | - | version = "1.0.2" | |
| 26 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 27 | - | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" | |
| 28 | - | ||
| 29 | - | [[package]] | |
| 30 | - | name = "errno" | |
| 31 | - | version = "0.3.14" | |
| 32 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 33 | - | checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" | |
| 34 | - | dependencies = [ | |
| 35 | - | "libc", | |
| 36 | - | "windows-sys", | |
| 37 | - | ] | |
| 38 | - | ||
| 39 | - | [[package]] | |
| 40 | - | name = "fastrand" | |
| 41 | - | version = "2.3.0" | |
| 42 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 43 | - | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" | |
| 44 | - | ||
| 45 | - | [[package]] | |
| 46 | - | name = "foldhash" | |
| 47 | - | version = "0.1.5" | |
| 48 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 49 | - | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" | |
| 50 | - | ||
| 51 | - | [[package]] | |
| 52 | - | name = "getrandom" | |
| 53 | - | version = "0.4.2" | |
| 54 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 55 | - | checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" | |
| 56 | - | dependencies = [ | |
| 57 | - | "cfg-if", | |
| 58 | - | "libc", | |
| 59 | - | "r-efi", | |
| 60 | - | "wasip2", | |
| 61 | - | "wasip3", | |
| 62 | - | ] | |
| 63 | - | ||
| 64 | - | [[package]] | |
| 65 | - | name = "hashbrown" | |
| 66 | - | version = "0.15.5" | |
| 67 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 68 | - | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" | |
| 69 | - | dependencies = [ | |
| 70 | - | "foldhash", | |
| 71 | - | ] | |
| 72 | - | ||
| 73 | - | [[package]] | |
| 74 | - | name = "hashbrown" | |
| 75 | - | version = "0.16.1" | |
| 76 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 77 | - | checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" | |
| 78 | - | ||
| 79 | - | [[package]] | |
| 80 | - | name = "heck" | |
| 81 | - | version = "0.5.0" | |
| 82 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 83 | - | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | |
| 84 | - | ||
| 85 | - | [[package]] | |
| 86 | - | name = "id-arena" | |
| 87 | - | version = "2.3.0" | |
| 88 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 89 | - | checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" | |
| 90 | - | ||
| 91 | - | [[package]] | |
| 92 | - | name = "indexmap" | |
| 93 | - | version = "2.13.0" | |
| 94 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 95 | - | checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" | |
| 96 | - | dependencies = [ | |
| 97 | - | "equivalent", | |
| 98 | - | "hashbrown 0.16.1", | |
| 99 | - | "serde", | |
| 100 | - | "serde_core", | |
| 101 | - | ] | |
| 102 | - | ||
| 103 | - | [[package]] | |
| 104 | - | name = "itoa" | |
| 105 | - | version = "1.0.18" | |
| 106 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 107 | - | checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" | |
| 108 | - | ||
| 109 | - | [[package]] | |
| 110 | - | name = "leb128fmt" | |
| 111 | - | version = "0.1.0" | |
| 112 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 113 | - | checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" | |
| 114 | - | ||
| 115 | - | [[package]] | |
| 116 | - | name = "libc" | |
| 117 | - | version = "0.2.183" | |
| 118 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 119 | - | checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" | |
| 120 | - | ||
| 121 | - | [[package]] | |
| 122 | - | name = "linux-raw-sys" | |
| 123 | - | version = "0.12.1" | |
| 124 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 125 | - | checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" | |
| 126 | - | ||
| 127 | - | [[package]] | |
| 128 | - | name = "log" | |
| 129 | - | version = "0.4.29" | |
| 130 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 131 | - | checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" | |
| 132 | - | ||
| 133 | - | [[package]] | |
| 134 | - | name = "memchr" | |
| 135 | - | version = "2.8.0" | |
| 136 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 137 | - | checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" | |
| 138 | - | ||
| 139 | - | [[package]] | |
| 140 | - | name = "once_cell" | |
| 141 | - | version = "1.21.4" | |
| 142 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 143 | - | checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" | |
| 144 | - | ||
| 145 | - | [[package]] | |
| 146 | - | name = "prettyplease" | |
| 147 | - | version = "0.2.37" | |
| 148 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 149 | - | checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" | |
| 150 | - | dependencies = [ | |
| 151 | - | "proc-macro2", | |
| 152 | - | "syn", | |
| 153 | - | ] | |
| 154 | - | ||
| 155 | - | [[package]] | |
| 156 | - | name = "proc-macro2" | |
| 157 | - | version = "1.0.106" | |
| 158 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 159 | - | checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" | |
| 160 | - | dependencies = [ | |
| 161 | - | "unicode-ident", | |
| 162 | - | ] | |
| 163 | - | ||
| 164 | - | [[package]] | |
| 165 | - | name = "quote" | |
| 166 | - | version = "1.0.45" | |
| 167 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 168 | - | checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" | |
| 169 | - | dependencies = [ | |
| 170 | - | "proc-macro2", | |
| 171 | - | ] | |
| 172 | - | ||
| 173 | - | [[package]] | |
| 174 | - | name = "r-efi" | |
| 175 | - | version = "6.0.0" | |
| 176 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 177 | - | checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" | |
| 178 | - | ||
| 179 | - | [[package]] | |
| 180 | - | name = "rustix" | |
| 181 | - | version = "1.1.4" | |
| 182 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 183 | - | checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" | |
| 184 | - | dependencies = [ | |
| 185 | - | "bitflags", | |
| 186 | - | "errno", | |
| 187 | - | "libc", | |
| 188 | - | "linux-raw-sys", | |
| 189 | - | "windows-sys", | |
| 190 | - | ] | |
| 191 | - | ||
| 192 | - | [[package]] | |
| 193 | - | name = "semver" | |
| 194 | - | version = "1.0.27" | |
| 195 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 196 | - | checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" | |
| 197 | - | ||
| 198 | - | [[package]] | |
| 199 | - | name = "serde" | |
| 200 | - | version = "1.0.228" | |
| 201 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 202 | - | checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" | |
| 203 | - | dependencies = [ | |
| 204 | - | "serde_core", | |
| 205 | - | "serde_derive", | |
| 206 | - | ] | |
| 207 | - | ||
| 208 | - | [[package]] | |
| 209 | - | name = "serde_core" | |
| 210 | - | version = "1.0.228" | |
| 211 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 212 | - | checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" | |
| 213 | - | dependencies = [ | |
| 214 | - | "serde_derive", | |
| 215 | - | ] | |
| 216 | - | ||
| 217 | - | [[package]] | |
| 218 | - | name = "serde_derive" | |
| 219 | - | version = "1.0.228" | |
| 220 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 221 | - | checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" | |
| 222 | - | dependencies = [ | |
| 223 | - | "proc-macro2", | |
| 224 | - | "quote", | |
| 225 | - | "syn", | |
| 226 | - | ] | |
| 227 | - | ||
| 228 | - | [[package]] | |
| 229 | - | name = "serde_json" | |
| 230 | - | version = "1.0.149" | |
| 231 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 232 | - | checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" | |
| 233 | - | dependencies = [ | |
| 234 | - | "itoa", | |
| 235 | - | "memchr", | |
| 236 | - | "serde", | |
| 237 | - | "serde_core", | |
| 238 | - | "zmij", | |
| 239 | - | ] | |
| 240 | - | ||
| 241 | - | [[package]] | |
| 242 | - | name = "serde_spanned" | |
| 243 | - | version = "0.6.9" | |
| 244 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 245 | - | checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" | |
| 246 | - | dependencies = [ | |
| 247 | - | "serde", | |
| 248 | - | ] | |
| 249 | - | ||
| 250 | - | [[package]] | |
| 251 | - | name = "syn" | |
| 252 | - | version = "2.0.117" | |
| 253 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 254 | - | checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" | |
| 255 | - | dependencies = [ | |
| 256 | - | "proc-macro2", | |
| 257 | - | "quote", | |
| 258 | - | "unicode-ident", | |
| 259 | - | ] | |
| 260 | - | ||
| 261 | - | [[package]] | |
| 262 | - | name = "tempfile" | |
| 263 | - | version = "3.27.0" | |
| 264 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 265 | - | checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" | |
| 266 | - | dependencies = [ | |
| 267 | - | "fastrand", | |
| 268 | - | "getrandom", | |
| 269 | - | "once_cell", | |
| 270 | - | "rustix", | |
| 271 | - | "windows-sys", | |
| 272 | - | ] | |
| 273 | - | ||
| 274 | - | [[package]] | |
| 275 | - | name = "theme-common" | |
| 276 | - | version = "0.7.0" | |
| 277 | - | dependencies = [ | |
| 278 | - | "serde", | |
| 279 | - | "tempfile", | |
| 280 | - | "toml", | |
| 281 | - | ] | |
| 282 | - | ||
| 283 | - | [[package]] | |
| 284 | - | name = "toml" | |
| 285 | - | version = "0.8.23" | |
| 286 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 287 | - | checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" | |
| 288 | - | dependencies = [ | |
| 289 | - | "serde", | |
| 290 | - | "serde_spanned", | |
| 291 | - | "toml_datetime", | |
| 292 | - | "toml_edit", | |
| 293 | - | ] | |
| 294 | - | ||
| 295 | - | [[package]] | |
| 296 | - | name = "toml_datetime" | |
| 297 | - | version = "0.6.11" | |
| 298 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 299 | - | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" | |
| 300 | - | dependencies = [ | |
| 301 | - | "serde", | |
| 302 | - | ] | |
| 303 | - | ||
| 304 | - | [[package]] | |
| 305 | - | name = "toml_edit" | |
| 306 | - | version = "0.22.27" | |
| 307 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 308 | - | checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" | |
| 309 | - | dependencies = [ | |
| 310 | - | "indexmap", | |
| 311 | - | "serde", | |
| 312 | - | "serde_spanned", | |
| 313 | - | "toml_datetime", | |
| 314 | - | "toml_write", | |
| 315 | - | "winnow", | |
| 316 | - | ] | |
| 317 | - | ||
| 318 | - | [[package]] | |
| 319 | - | name = "toml_write" | |
| 320 | - | version = "0.1.2" | |
| 321 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 322 | - | checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" | |
| 323 | - | ||
| 324 | - | [[package]] | |
| 325 | - | name = "unicode-ident" | |
| 326 | - | version = "1.0.24" | |
| 327 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 328 | - | checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" | |
| 329 | - | ||
| 330 | - | [[package]] | |
| 331 | - | name = "unicode-xid" | |
| 332 | - | version = "0.2.6" | |
| 333 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 334 | - | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" | |
| 335 | - | ||
| 336 | - | [[package]] | |
| 337 | - | name = "wasip2" | |
| 338 | - | version = "1.0.2+wasi-0.2.9" | |
| 339 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 340 | - | checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" | |
| 341 | - | dependencies = [ | |
| 342 | - | "wit-bindgen", | |
| 343 | - | ] | |
| 344 | - | ||
| 345 | - | [[package]] | |
| 346 | - | name = "wasip3" | |
| 347 | - | version = "0.4.0+wasi-0.3.0-rc-2026-01-06" | |
| 348 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 349 | - | checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" | |
| 350 | - | dependencies = [ | |
| 351 | - | "wit-bindgen", | |
| 352 | - | ] | |
| 353 | - | ||
| 354 | - | [[package]] | |
| 355 | - | name = "wasm-encoder" | |
| 356 | - | version = "0.244.0" | |
| 357 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 358 | - | checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" | |
| 359 | - | dependencies = [ | |
| 360 | - | "leb128fmt", | |
| 361 | - | "wasmparser", | |
| 362 | - | ] | |
| 363 | - | ||
| 364 | - | [[package]] | |
| 365 | - | name = "wasm-metadata" | |
| 366 | - | version = "0.244.0" | |
| 367 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 368 | - | checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" | |
| 369 | - | dependencies = [ | |
| 370 | - | "anyhow", | |
| 371 | - | "indexmap", | |
| 372 | - | "wasm-encoder", | |
| 373 | - | "wasmparser", | |
| 374 | - | ] | |
| 375 | - | ||
| 376 | - | [[package]] | |
| 377 | - | name = "wasmparser" | |
| 378 | - | version = "0.244.0" | |
| 379 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 380 | - | checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" | |
| 381 | - | dependencies = [ | |
| 382 | - | "bitflags", | |
| 383 | - | "hashbrown 0.15.5", | |
| 384 | - | "indexmap", | |
| 385 | - | "semver", | |
| 386 | - | ] | |
| 387 | - | ||
| 388 | - | [[package]] | |
| 389 | - | name = "windows-link" | |
| 390 | - | version = "0.2.1" | |
| 391 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 392 | - | checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" | |
| 393 | - | ||
| 394 | - | [[package]] | |
| 395 | - | name = "windows-sys" | |
| 396 | - | version = "0.61.2" | |
| 397 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 398 | - | checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" | |
| 399 | - | dependencies = [ | |
| 400 | - | "windows-link", | |
| 401 | - | ] | |
| 402 | - | ||
| 403 | - | [[package]] | |
| 404 | - | name = "winnow" | |
| 405 | - | version = "0.7.15" | |
| 406 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 407 | - | checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" | |
| 408 | - | dependencies = [ | |
| 409 | - | "memchr", | |
| 410 | - | ] | |
| 411 | - | ||
| 412 | - | [[package]] | |
| 413 | - | name = "wit-bindgen" | |
| 414 | - | version = "0.51.0" | |
| 415 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 416 | - | checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" | |
| 417 | - | dependencies = [ | |
| 418 | - | "wit-bindgen-rust-macro", | |
| 419 | - | ] | |
| 420 | - | ||
| 421 | - | [[package]] | |
| 422 | - | name = "wit-bindgen-core" | |
| 423 | - | version = "0.51.0" | |
| 424 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 425 | - | checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" | |
| 426 | - | dependencies = [ | |
| 427 | - | "anyhow", | |
| 428 | - | "heck", | |
| 429 | - | "wit-parser", | |
| 430 | - | ] | |
| 431 | - | ||
| 432 | - | [[package]] | |
| 433 | - | name = "wit-bindgen-rust" | |
| 434 | - | version = "0.51.0" | |
| 435 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 436 | - | checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" | |
| 437 | - | dependencies = [ | |
| 438 | - | "anyhow", | |
| 439 | - | "heck", | |
| 440 | - | "indexmap", | |
| 441 | - | "prettyplease", | |
| 442 | - | "syn", | |
| 443 | - | "wasm-metadata", | |
| 444 | - | "wit-bindgen-core", | |
| 445 | - | "wit-component", | |
| 446 | - | ] | |
| 447 | - | ||
| 448 | - | [[package]] | |
| 449 | - | name = "wit-bindgen-rust-macro" | |
| 450 | - | version = "0.51.0" | |
| 451 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 452 | - | checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" | |
| 453 | - | dependencies = [ | |
| 454 | - | "anyhow", | |
| 455 | - | "prettyplease", | |
| 456 | - | "proc-macro2", | |
| 457 | - | "quote", | |
| 458 | - | "syn", | |
| 459 | - | "wit-bindgen-core", | |
| 460 | - | "wit-bindgen-rust", | |
| 461 | - | ] | |
| 462 | - | ||
| 463 | - | [[package]] | |
| 464 | - | name = "wit-component" | |
| 465 | - | version = "0.244.0" | |
| 466 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 467 | - | checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" | |
| 468 | - | dependencies = [ | |
| 469 | - | "anyhow", | |
| 470 | - | "bitflags", | |
| 471 | - | "indexmap", | |
| 472 | - | "log", | |
| 473 | - | "serde", | |
| 474 | - | "serde_derive", | |
| 475 | - | "serde_json", | |
| 476 | - | "wasm-encoder", | |
| 477 | - | "wasm-metadata", | |
| 478 | - | "wasmparser", | |
| 479 | - | "wit-parser", | |
| 480 | - | ] | |
| 481 | - | ||
| 482 | - | [[package]] | |
| 483 | - | name = "wit-parser" | |
| 484 | - | version = "0.244.0" | |
| 485 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 486 | - | checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" | |
| 487 | - | dependencies = [ | |
| 488 | - | "anyhow", | |
| 489 | - | "id-arena", | |
| 490 | - | "indexmap", | |
| 491 | - | "log", | |
| 492 | - | "semver", | |
| 493 | - | "serde", | |
| 494 | - | "serde_derive", | |
| 495 | - | "serde_json", | |
| 496 | - | "unicode-xid", | |
| 497 | - | "wasmparser", | |
| 498 | - | ] | |
| 499 | - | ||
| 500 | - | [[package]] |
Lines truncated
| @@ -1,11 +0,0 @@ | |||
| 1 | - | [package] | |
| 2 | - | name = "theme-common" | |
| 3 | - | version = "0.7.0" | |
| 4 | - | edition = "2024" | |
| 5 | - | ||
| 6 | - | [dependencies] | |
| 7 | - | serde = { version = "1", features = ["derive"] } | |
| 8 | - | toml = "0.8" | |
| 9 | - | ||
| 10 | - | [dev-dependencies] | |
| 11 | - | tempfile = "3" |
| @@ -1,110 +0,0 @@ | |||
| 1 | - | # theme-common | |
| 2 | - | ||
| 3 | - | Shared theme loading logic for TOML-based theme files. Parses theme metadata and color values from `.toml` files on disk. | |
| 4 | - | ||
| 5 | - | Used by GoingsOn and Balanced Breakfast (Tauri apps that load themes at runtime). audiofiles uses a different compile-time embedding approach and does not use this crate. | |
| 6 | - | ||
| 7 | - | ## Usage | |
| 8 | - | ||
| 9 | - | ```rust | |
| 10 | - | use theme_common::{load_theme, list_themes_from_dirs, dev_themes_dir}; | |
| 11 | - | use std::path::PathBuf; | |
| 12 | - | ||
| 13 | - | // Set up theme directories (later entries override earlier ones) | |
| 14 | - | let bundled = PathBuf::from("/path/to/MNW/shared/themes"); | |
| 15 | - | let custom = PathBuf::from("/path/to/user/custom-themes"); | |
| 16 | - | let dirs = vec![(bundled, false), (custom, true)]; | |
| 17 | - | ||
| 18 | - | // List available themes (sorted by name) | |
| 19 | - | let themes = list_themes_from_dirs(&dirs); | |
| 20 | - | for t in &themes { | |
| 21 | - | println!("{} ({}, {})", t.name, t.id, t.variant); | |
| 22 | - | } | |
| 23 | - | ||
| 24 | - | // Load a specific theme by ID | |
| 25 | - | let theme = load_theme(&dirs, "catppuccin-mocha").unwrap(); | |
| 26 | - | println!("Name: {}", theme.meta.name); // "Catppuccin Mocha" | |
| 27 | - | println!("Variant: {}", theme.meta.variant); // "dark" | |
| 28 | - | println!("BG: {}", theme.colors["background.primary"]); // "#181825" | |
| 29 | - | ||
| 30 | - | // Dev helper: find MNW/shared/themes/ relative to CARGO_MANIFEST_DIR | |
| 31 | - | if let Some(dev_dir) = dev_themes_dir(Path::new(env!("CARGO_MANIFEST_DIR")), 3) { | |
| 32 | - | // dev_dir = .../Code/MNW/shared/themes | |
| 33 | - | } | |
| 34 | - | ``` | |
| 35 | - | ||
| 36 | - | ## Theme File Format | |
| 37 | - | ||
| 38 | - | Theme files are TOML with four color sections. See `../themes/` for the 16 bundled themes. | |
| 39 | - | ||
| 40 | - | ```toml | |
| 41 | - | # Attribution comment (optional, for credit) | |
| 42 | - | # Based on Catppuccin by Catppuccin Org -- MIT License | |
| 43 | - | ||
| 44 | - | [meta] | |
| 45 | - | name = "Theme Name" # Display name (required) | |
| 46 | - | variant = "dark" # "dark", "light", or "high-contrast" (default: "dark") | |
| 47 | - | ||
| 48 | - | [background] | |
| 49 | - | primary = "#181825" # Main background | |
| 50 | - | secondary = "#11111b" # Sidebar / panel background (optional) | |
| 51 | - | tertiary = "#313244" # Hover / selection background (optional) | |
| 52 | - | surface = "#1e1e2e" # Card / elevated surface (optional) | |
| 53 | - | ||
| 54 | - | [foreground] | |
| 55 | - | primary = "#cdd6f4" # Main text | |
| 56 | - | secondary = "#bac2de" # Secondary text (optional) | |
| 57 | - | muted = "#9399b2" # Placeholder / disabled text (optional) | |
| 58 | - | ||
| 59 | - | [accent] | |
| 60 | - | red = "#f38ba8" # Error, destructive actions | |
| 61 | - | green = "#a6e3a1" # Success, positive actions | |
| 62 | - | blue = "#89b4fa" # Links, primary accent | |
| 63 | - | yellow = "#f9e2af" # Warnings | |
| 64 | - | purple = "#cba6f7" # Tags, special elements | |
| 65 | - | cyan = "#89dceb" # Info, secondary accent | |
| 66 | - | ||
| 67 | - | [border] | |
| 68 | - | default = "#45475a" # Default border color | |
| 69 | - | ``` | |
| 70 | - | ||
| 71 | - | ### Color Key Flattening | |
| 72 | - | ||
| 73 | - | Colors are loaded into a flat `HashMap<String, String>` with dotted keys: | |
| 74 | - | ||
| 75 | - | ``` | |
| 76 | - | "background.primary" -> "#181825" | |
| 77 | - | "foreground.muted" -> "#9399b2" | |
| 78 | - | "accent.blue" -> "#89b4fa" | |
| 79 | - | "border.default" -> "#45475a" | |
| 80 | - | ``` | |
| 81 | - | ||
| 82 | - | Apps map these keys to CSS variables or egui color values. | |
| 83 | - | ||
| 84 | - | ### Theme ID | |
| 85 | - | ||
| 86 | - | The theme ID is the filename without `.toml` (e.g., `catppuccin-mocha.toml` has ID `catppuccin-mocha`). IDs must contain only alphanumeric characters, hyphens, and underscores. Path traversal characters are rejected. | |
| 87 | - | ||
| 88 | - | ## API | |
| 89 | - | ||
| 90 | - | | Function | Description | | |
| 91 | - | |----------|-------------| | |
| 92 | - | | `list_themes_from_dirs(dirs)` | Scan directories for `.toml` files, return sorted `Vec<ThemeMeta>` | | |
| 93 | - | | `load_theme(dirs, id)` | Load a theme by ID, returning `ThemeColors` (metadata + color map) | | |
| 94 | - | | `find_theme_path(dirs, id)` | Find the file path for a theme ID (highest-priority directory wins) | | |
| 95 | - | | `parse_meta(id, table, is_custom)` | Parse `[meta]` from a TOML table into `ThemeMeta` | | |
| 96 | - | | `extract_colors(table)` | Flatten color sections into a `HashMap<String, String>` | | |
| 97 | - | | `validate_theme_id(id)` | Check that an ID contains only safe characters | | |
| 98 | - | | `dev_themes_dir(manifest_dir, levels)` | Walk up parent directories to find `MNW/shared/themes/` (dev convenience) | | |
| 99 | - | ||
| 100 | - | ## Directory Priority | |
| 101 | - | ||
| 102 | - | `list_themes_from_dirs` and `load_theme` accept a list of `(PathBuf, bool)` pairs. Later directories override earlier ones by theme ID. The `bool` marks whether the directory contains user-custom themes (`is_custom` on `ThemeMeta`). | |
| 103 | - | ||
| 104 | - | Typical setup for a Tauri app: | |
| 105 | - | 1. Bundled themes from `MNW/shared/themes/` (is_custom = false) | |
| 106 | - | 2. User themes from an app data directory (is_custom = true) | |
| 107 | - | ||
| 108 | - | ## License | |
| 109 | - | ||
| 110 | - | PolyForm Noncommercial 1.0.0 |
| @@ -1,26 +0,0 @@ | |||
| 1 | - | # theme-common — Architecture | |
| 2 | - | ||
| 3 | - | Shared TOML theme loading for GO, BB, and AF. | |
| 4 | - | ||
| 5 | - | ## What It Does | |
| 6 | - | ||
| 7 | - | Parses TOML theme files with `[meta]`, `[background]`, `[foreground]`, `[accent]`, `[border]` sections. Provides metadata extraction, color flattening, filesystem scanning, import/export, and ID validation. | |
| 8 | - | ||
| 9 | - | ## Consumers | |
| 10 | - | ||
| 11 | - | | App | Usage | | |
| 12 | - | |-----|-------| | |
| 13 | - | | GO, BB | `list_themes_from_dirs`, `load_theme`, `import_theme`, `export_theme` (runtime filesystem) | | |
| 14 | - | | AF | `ThemeMeta`, `parse_meta`, `extract_colors` (compile-time embedded themes) | | |
| 15 | - | ||
| 16 | - | ## Key Types | |
| 17 | - | ||
| 18 | - | - `ThemeMeta` — id, name, variant, is_custom | |
| 19 | - | - `ThemeColors` — metadata + flattened color map (`background.primary` etc.) | |
| 20 | - | ||
| 21 | - | ## Key Paths | |
| 22 | - | ||
| 23 | - | | What | Where | | |
| 24 | - | |------|-------| | |
| 25 | - | | All code | `src/lib.rs` (single file, ~585 lines including tests) | | |
| 26 | - | | Theme files | `../themes/*.toml` (16 bundled themes) | |
| @@ -1,8 +0,0 @@ | |||
| 1 | - | fn main() { | |
| 2 | - | let id = std::env::args().nth(1).unwrap_or_else(|| "makenotwork".into()); | |
| 3 | - | let dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..").join("themes"); | |
| 4 | - | let t = theme_common::load_semantic(&[(dir, false)], &id).unwrap(); | |
| 5 | - | for (k, v) in &t.intents { | |
| 6 | - | println!(" --{k}: {v};"); | |
| 7 | - | } | |
| 8 | - | } |
| @@ -1,986 +0,0 @@ | |||
| 1 | - | //! Shared theme loading + intent resolution for TOML-based theme files. | |
| 2 | - | //! | |
| 3 | - | //! Used by GoingsOn, Balanced Breakfast (Tauri apps), audiofiles (egui), and the | |
| 4 | - | //! MNW web server. Themes are authored by **intent** ("human design"): colors are | |
| 5 | - | //! declared by role (surface / content / action / status / line / category), not | |
| 6 | - | //! by hue. This crate is the single place that resolves an authored theme into a | |
| 7 | - | //! full set of intent tokens — including the derived interactive states | |
| 8 | - | //! (hover/active/selection/row-stripe/contrast) that each app used to recompute | |
| 9 | - | //! itself — and emits them as CSS variables or RGB tuples. | |
| 10 | - | //! | |
| 11 | - | //! Theme file shape: | |
| 12 | - | //! ```text | |
| 13 | - | //! [meta] | |
| 14 | - | //! name = "Nord" | |
| 15 | - | //! variant = "dark" # or "light" | |
| 16 | - | //! | |
| 17 | - | //! [surface] # container backgrounds by role/elevation | |
| 18 | - | //! page = "#2e3440"; raised = "#3b4252"; sunken = "#434c5e"; overlay = "#3b4252" | |
| 19 | - | //! | |
| 20 | - | //! [content] # text/ink by emphasis | |
| 21 | - | //! primary = "#d8dee9"; secondary = "#e5e9f0"; muted = "#616e88" | |
| 22 | - | //! | |
| 23 | - | //! [action] # interactive / brand color | |
| 24 | - | //! primary = "#81a1c1" | |
| 25 | - | //! | |
| 26 | - | //! [status] # state semantics | |
| 27 | - | //! danger = "#bf616a"; success = "#a3be8c"; warning = "#ebcb8b"; info = "#88c0d0" | |
| 28 | - | //! | |
| 29 | - | //! [line] | |
| 30 | - | //! border = "#4c566a" | |
| 31 | - | //! | |
| 32 | - | //! [category] # distinct decorative colors for tags/badges/charts | |
| 33 | - | //! one = "#bf616a"; two = "#a3be8c"; three = "#81a1c1" | |
| 34 | - | //! four = "#ebcb8b"; five = "#b48ead"; six = "#88c0d0" | |
| 35 | - | //! ``` | |
| 36 | - | ||
| 37 | - | use serde::Serialize; | |
| 38 | - | use std::collections::{BTreeMap, HashMap}; | |
| 39 | - | use std::path::{Path, PathBuf}; | |
| 40 | - | ||
| 41 | - | /// The color sections an authored theme may declare. | |
| 42 | - | pub const COLOR_SECTIONS: &[&str] = &["surface", "content", "action", "status", "line", "category"]; | |
| 43 | - | ||
| 44 | - | /// Theme metadata parsed from the `[meta]` section. | |
| 45 | - | #[derive(Debug, Clone, Serialize)] | |
| 46 | - | #[serde(rename_all = "camelCase")] | |
| 47 | - | pub struct ThemeMeta { | |
| 48 | - | pub id: String, | |
| 49 | - | pub name: String, | |
| 50 | - | pub variant: String, | |
| 51 | - | pub is_custom: bool, | |
| 52 | - | } | |
| 53 | - | ||
| 54 | - | /// A loaded theme: metadata plus the authored colors, flattened to dotted keys | |
| 55 | - | /// (e.g. `"surface.page"`, `"status.danger"`, `"category.one"`). | |
| 56 | - | #[derive(Debug, Serialize)] | |
| 57 | - | #[serde(rename_all = "camelCase")] | |
| 58 | - | pub struct ThemeColors { | |
| 59 | - | pub meta: ThemeMeta, | |
| 60 | - | pub colors: HashMap<String, String>, | |
| 61 | - | } | |
| 62 | - | ||
| 63 | - | // ============================================================================ | |
| 64 | - | // Color math — perceptual (OKLab) derivations + WCAG contrast. | |
| 65 | - | // | |
| 66 | - | // Interactive states (hover/active/selection/surfaces) are derived in OKLab so | |
| 67 | - | // equal steps look equal across every theme's hues (Ottosson 2020; the modern | |
| 68 | - | // CIELAB). Text-on-color is picked by the WCAG 2.x contrast ratio, not a naive | |
| 69 | - | // luminance threshold, so the choice actually meets AA where achievable. | |
| 70 | - | // This is the single source of truth shared by every product. | |
| 71 | - | // ============================================================================ | |
| 72 | - | ||
| 73 | - | /// An sRGB color. Hex round-trips losslessly. | |
| 74 | - | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | |
| 75 | - | pub struct Rgb { | |
| 76 | - | pub r: u8, | |
| 77 | - | pub g: u8, | |
| 78 | - | pub b: u8, | |
| 79 | - | } | |
| 80 | - | ||
| 81 | - | impl Rgb { | |
| 82 | - | /// Parse `#rgb` or `#rrggbb` (case-insensitive). Returns `None` otherwise. | |
| 83 | - | pub fn from_hex(s: &str) -> Option<Rgb> { | |
| 84 | - | let h = s.strip_prefix('#')?; | |
| 85 | - | let (r, g, b) = match h.len() { | |
| 86 | - | 6 => ( | |
| 87 | - | u8::from_str_radix(&h[0..2], 16).ok()?, | |
| 88 | - | u8::from_str_radix(&h[2..4], 16).ok()?, | |
| 89 | - | u8::from_str_radix(&h[4..6], 16).ok()?, | |
| 90 | - | ), | |
| 91 | - | 3 => { | |
| 92 | - | let d = |c: &str| u8::from_str_radix(c, 16).ok().map(|v| v * 17); | |
| 93 | - | (d(&h[0..1])?, d(&h[1..2])?, d(&h[2..3])?) | |
| 94 | - | } | |
| 95 | - | _ => return None, | |
| 96 | - | }; | |
| 97 | - | Some(Rgb { r, g, b }) | |
| 98 | - | } | |
| 99 | - | ||
| 100 | - | /// Lowercase `#rrggbb`. | |
| 101 | - | pub fn to_hex(self) -> String { | |
| 102 | - | format!("#{:02x}{:02x}{:02x}", self.r, self.g, self.b) | |
| 103 | - | } | |
| 104 | - | ||
| 105 | - | pub fn tuple(self) -> (u8, u8, u8) { | |
| 106 | - | (self.r, self.g, self.b) | |
| 107 | - | } | |
| 108 | - | } | |
| 109 | - | ||
| 110 | - | /// A color in OKLab (perceptually uniform): `l` lightness in [0,1], `a`/`b` opponent axes. | |
| 111 | - | #[derive(Clone, Copy, Debug)] | |
| 112 | - | pub struct Oklab { | |
| 113 | - | pub l: f32, | |
| 114 | - | pub a: f32, | |
| 115 | - | pub b: f32, | |
| 116 | - | } | |
| 117 | - | ||
| 118 | - | fn srgb_to_linear(c: u8) -> f32 { | |
| 119 | - | let c = c as f32 / 255.0; | |
| 120 | - | if c <= 0.04045 { c / 12.92 } else { ((c + 0.055) / 1.055).powf(2.4) } | |
| 121 | - | } | |
| 122 | - | ||
| 123 | - | fn linear_to_srgb(c: f32) -> u8 { | |
| 124 | - | let c = c.clamp(0.0, 1.0); | |
| 125 | - | let v = if c <= 0.0031308 { c * 12.92 } else { 1.055 * c.powf(1.0 / 2.4) - 0.055 }; | |
| 126 | - | (v * 255.0).round().clamp(0.0, 255.0) as u8 | |
| 127 | - | } | |
| 128 | - | ||
| 129 | - | impl Rgb { | |
| 130 | - | /// Convert to OKLab (Ottosson's sRGB matrices). | |
| 131 | - | pub fn to_oklab(self) -> Oklab { | |
| 132 | - | let (r, g, b) = (srgb_to_linear(self.r), srgb_to_linear(self.g), srgb_to_linear(self.b)); | |
| 133 | - | let l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b; | |
| 134 | - | let m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b; | |
| 135 | - | let s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b; | |
| 136 | - | let (l_, m_, s_) = (l.cbrt(), m.cbrt(), s.cbrt()); | |
| 137 | - | Oklab { | |
| 138 | - | l: 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_, | |
| 139 | - | a: 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_, | |
| 140 | - | b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_, | |
| 141 | - | } | |
| 142 | - | } | |
| 143 | - | ||
| 144 | - | /// Convert from OKLab back to the nearest in-gamut sRGB. | |
| 145 | - | pub fn from_oklab(c: Oklab) -> Rgb { | |
| 146 | - | let l_ = c.l + 0.3963377774 * c.a + 0.2158037573 * c.b; | |
| 147 | - | let m_ = c.l - 0.1055613458 * c.a - 0.0638541728 * c.b; | |
| 148 | - | let s_ = c.l - 0.0894841775 * c.a - 1.2914855480 * c.b; | |
| 149 | - | let (l, m, s) = (l_ * l_ * l_, m_ * m_ * m_, s_ * s_ * s_); | |
| 150 | - | Rgb { | |
| 151 | - | r: linear_to_srgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s), | |
| 152 | - | g: linear_to_srgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s), | |
| 153 | - | b: linear_to_srgb(-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s), | |
| 154 | - | } | |
| 155 | - | } | |
| 156 | - | } | |
| 157 | - | ||
| 158 | - | /// WCAG 2.x relative luminance of an sRGB color. | |
| 159 | - | fn rel_luminance(c: Rgb) -> f32 { | |
| 160 | - | 0.2126 * srgb_to_linear(c.r) + 0.7152 * srgb_to_linear(c.g) + 0.0722 * srgb_to_linear(c.b) | |
| 161 | - | } | |
| 162 | - | ||
| 163 | - | /// WCAG 2.x contrast ratio between two colors, in [1, 21]. | |
| 164 | - | pub fn wcag_contrast(a: Rgb, b: Rgb) -> f32 { | |
| 165 | - | let (la, lb) = (rel_luminance(a), rel_luminance(b)); | |
| 166 | - | let (hi, lo) = if la >= lb { (la, lb) } else { (lb, la) }; | |
| 167 | - | (hi + 0.05) / (lo + 0.05) | |
| 168 | - | } | |
| 169 | - | ||
| 170 | - | /// Pick black or white for legible text on `bg`, by the higher WCAG contrast | |
| 171 | - | /// ratio (so the choice meets AA wherever the background allows it). | |
| 172 | - | pub fn readable_on(bg: Rgb) -> Rgb { | |
| 173 | - | let white = Rgb { r: 255, g: 255, b: 255 }; | |
| 174 | - | let black = Rgb { r: 0, g: 0, b: 0 }; | |
| 175 | - | if wcag_contrast(white, bg) >= wcag_contrast(black, bg) { white } else { black } | |
| 176 | - | } | |
| 177 | - | ||
| 178 | - | /// Shift OKLab lightness by `delta` (perceptually uniform). Positive lightens. | |
| 179 | - | pub fn lighten(c: Rgb, delta: f32) -> Rgb { | |
| 180 | - | let mut lab = c.to_oklab(); | |
| 181 | - | lab.l = (lab.l + delta).clamp(0.0, 1.0); | |
| 182 | - | Rgb::from_oklab(lab) | |
| 183 | - | } | |
| 184 | - | ||
| 185 | - | /// Shift OKLab lightness down by `delta` (perceptually uniform). | |
| 186 | - | pub fn darken(c: Rgb, delta: f32) -> Rgb { | |
| 187 | - | lighten(c, -delta) | |
| 188 | - | } | |
| 189 | - | ||
| 190 | - | /// Interpolate between `a` and `b` by `t` in [0,1] in OKLab (perceptual blend). | |
| 191 | - | pub fn mix(a: Rgb, b: Rgb, t: f32) -> Rgb { | |
| 192 | - | let (x, y) = (a.to_oklab(), b.to_oklab()); | |
| 193 | - | Rgb::from_oklab(Oklab { | |
| 194 | - | l: x.l + (y.l - x.l) * t, | |
| 195 | - | a: x.a + (y.a - x.a) * t, | |
| 196 | - | b: x.b + (y.b - x.b) * t, | |
| 197 | - | }) | |
| 198 | - | } | |
| 199 | - | ||
| 200 | - | // ============================================================================ | |
| 201 | - | // Intent resolution | |
| 202 | - | // ============================================================================ | |
| 203 | - | ||
| 204 | - | /// Authored base intents: (TOML dotted source key, canonical token key). | |
| 205 | - | /// These are read straight from the theme; the token key is the CSS-var stem | |
| 206 | - | /// (`--{token}`) and the `rgb()` lookup key. | |
| 207 | - | pub const BASE_INTENTS: &[(&str, &str)] = &[ | |
| 208 | - | ("surface.page", "surface-page"), | |
| 209 | - | ("surface.raised", "surface-raised"), | |
| 210 | - | ("surface.sunken", "surface-sunken"), | |
| 211 | - | ("surface.overlay", "surface-overlay"), | |
| 212 | - | ("content.primary", "content"), | |
| 213 | - | ("content.secondary", "content-secondary"), | |
| 214 | - | ("content.muted", "content-muted"), | |
| 215 | - | ("action.primary", "action"), | |
| 216 | - | ("status.danger", "danger"), | |
| 217 | - | ("status.success", "success"), | |
| 218 | - | ("status.warning", "warning"), | |
| 219 | - | ("status.info", "info"), | |
| 220 | - | ("line.border", "border"), | |
| 221 | - | ("category.one", "category-one"), | |
| 222 | - | ("category.two", "category-two"), | |
| 223 | - | ("category.three", "category-three"), | |
| 224 | - | ("category.four", "category-four"), | |
| 225 | - | ("category.five", "category-five"), | |
| 226 | - | ("category.six", "category-six"), | |
| 227 | - | ]; | |
| 228 | - | ||
| 229 | - | /// A fully resolved intent layer: every token key → concrete `#rrggbb`. | |
| 230 | - | /// Includes both authored base intents and the computed derived intents. | |
| 231 | - | #[derive(Debug, Clone, Serialize)] | |
| 232 | - | #[serde(rename_all = "camelCase")] | |
| 233 | - | pub struct SemanticTokens { | |
| 234 | - | pub meta: ThemeMeta, | |
| 235 | - | /// token-key → resolved hex. Stable, deterministic ordering. | |
| 236 | - | pub intents: BTreeMap<String, String>, | |
| 237 | - | } | |
| 238 | - | ||
| 239 | - | impl SemanticTokens { | |
| 240 | - | /// Resolved hex for a token key, if present. | |
| 241 | - | pub fn hex(&self, key: &str) -> Option<&str> { | |
| 242 | - | self.intents.get(key).map(String::as_str) | |
| 243 | - | } | |
| 244 | - | ||
| 245 | - | /// Resolved RGB tuple for a token key (for egui / native consumers). | |
| 246 | - | pub fn rgb(&self, key: &str) -> Option<(u8, u8, u8)> { | |
| 247 | - | self.intents.get(key).and_then(|h| Rgb::from_hex(h)).map(Rgb::tuple) | |
| 248 | - | } | |
| 249 | - | } | |
| 250 | - | ||
| 251 | - | /// Resolve an authored theme into the full intent token set. | |
| 252 | - | /// | |
| 253 | - | /// 1. Copy each present base intent from the authored colors. | |
| 254 | - | /// 2. Compute the derived interactive states from the base intents, using the | |
| 255 | - | /// same math the apps used to apply individually (so output is identical). | |
| 256 | - | /// Each derived token is emitted only when its source intents exist, mirroring | |
| 257 | - | /// the skip-missing behavior of the rest of the crate. | |
| 258 | - | pub fn resolve(theme: &ThemeColors) -> SemanticTokens { | |
| 259 | - | let mut intents: BTreeMap<String, String> = BTreeMap::new(); | |
| 260 | - | ||
| 261 | - | // 1. Base intents (authored). Copy only values that parse as a hex color and | |
| 262 | - | // re-emit them in canonical `#rrggbb` form, so an authored value can never | |
| 263 | - | // carry arbitrary bytes into the emitted CSS (the resolved tokens are inlined | |
| 264 | - | // raw into a `<style>` block by the web server). A malformed value is skipped, | |
| 265 | - | // mirroring the skip-missing behavior for absent intents. | |
| 266 | - | for (src, token) in BASE_INTENTS { | |
| 267 | - | if let Some(rgb) = theme.colors.get(*src).and_then(|v| Rgb::from_hex(v)) { | |
| 268 | - | intents.insert((*token).to_string(), rgb.to_hex()); | |
| 269 | - | } | |
| 270 | - | } | |
| 271 | - | ||
| 272 | - | // Helper: parse an already-resolved token to Rgb. | |
| 273 | - | let get = |m: &BTreeMap<String, String>, k: &str| m.get(k).and_then(|h| Rgb::from_hex(h)); | |
| 274 | - | ||
| 275 | - | // 2. Derived intents — perceptual (OKLab) steps + WCAG-picked text. | |
| 276 | - | // Lightness deltas are in OKLab L units; mix ratios interpolate in OKLab. | |
| 277 | - | let mut derived: Vec<(String, Rgb)> = Vec::new(); | |
| 278 | - | if let Some(action) = get(&intents, "action") { | |
| 279 | - | derived.push(("action-hover".into(), lighten(action, 0.05))); | |
| 280 | - | derived.push(("content-on-action".into(), readable_on(action))); | |
| 281 | - | derived.push(("focus-ring".into(), action)); | |
| 282 | - | } | |
| 283 | - | if let Some(page) = get(&intents, "surface-page") { | |
| 284 | - | // Modal scrim: a near-black tone carrying a faint hint of the theme's | |
| 285 | - | // hue, at 50% alpha. Anchored very dark (OKLab L=0.08) so it dims the | |
| 286 | - | // page on light *and* dark themes. Emitted as rgba (not a flat hex), so | |
| 287 | - | // it is inserted directly rather than through the hex loop below. | |
| 288 | - | let mut o = page.to_oklab(); | |
| 289 | - | o.l = 0.08; | |
| 290 | - | let s = Rgb::from_oklab(o); | |
| 291 | - | intents.insert("overlay".into(), format!("rgba({}, {}, {}, 0.5)", s.r, s.g, s.b)); | |
| 292 | - | } | |
| 293 | - | if let Some(sunken) = get(&intents, "surface-sunken") { | |
| 294 | - | derived.push(("hover-surface".into(), sunken)); | |
| 295 | - | } | |
| 296 | - | if let Some(border) = get(&intents, "border") { | |
| 297 | - | derived.push(("border-strong".into(), darken(border, 0.05))); | |
| 298 | - | } | |
| 299 | - | ||
| 300 | - | for (token, rgb) in derived { | |
| 301 | - | intents.insert(token, rgb.to_hex()); | |
| 302 | - | } | |
| 303 | - | ||
| 304 | - | SemanticTokens { meta: theme.meta.clone(), intents } | |
| 305 | - | } | |
| 306 | - | ||
| 307 | - | /// Emit the resolved intent layer as CSS declarations (no selector), one | |
| 308 | - | /// ` --token: #hex;` line each, in deterministic (BTreeMap) order. | |
| 309 | - | pub fn intent_css_declarations(tokens: &SemanticTokens) -> String { | |
| 310 | - | let mut out = String::new(); | |
| 311 | - | for (token, hex) in &tokens.intents { | |
| 312 | - | out.push_str(" --"); | |
| 313 | - | out.push_str(token); | |
| 314 | - | out.push_str(": "); | |
| 315 | - | out.push_str(hex); | |
| 316 | - | out.push_str(";\n"); | |
| 317 | - | } | |
| 318 | - | out | |
| 319 | - | } | |
| 320 | - | ||
| 321 | - | /// Emit the resolved intent layer as a `:root { … }` block — the single TOML → | |
| 322 | - | /// CSS mapping every web surface injects. | |
| 323 | - | pub fn intent_css_vars(tokens: &SemanticTokens) -> String { | |
| 324 | - | format!(":root {{\n{}}}\n", intent_css_declarations(tokens)) | |
| 325 | - | } | |
| 326 | - | ||
| 327 | - | // ============================================================================ | |
| 328 | - | // Loading / parsing | |
| 329 | - | // ============================================================================ | |
| 330 | - | ||
| 331 | - | /// Validate a theme ID contains only safe characters (alphanumeric, hyphens, underscores). | |
| 332 | - | pub fn validate_theme_id(id: &str) -> Result<(), String> { | |
| 333 | - | if !id | |
| 334 | - | .chars() | |
| 335 | - | .all(|c| c.is_alphanumeric() || c == '-' || c == '_') | |
| 336 | - | { | |
| 337 | - | return Err(format!("Invalid theme ID: {}", id)); | |
| 338 | - | } | |
| 339 | - | Ok(()) | |
| 340 | - | } | |
| 341 | - | ||
| 342 | - | /// Parse the `[meta]` section into `ThemeMeta`. | |
| 343 | - | /// | |
| 344 | - | /// Falls back to the file ID as the name and `"dark"` as the variant. | |
| 345 | - | pub fn parse_meta(id: &str, table: &toml::Table, is_custom: bool) -> ThemeMeta { | |
| 346 | - | let meta = table.get("meta").and_then(|m| m.as_table()); | |
| 347 | - | let name = meta | |
| 348 | - | .and_then(|m| m.get("name")) | |
| 349 | - | .and_then(|v| v.as_str()) | |
| 350 | - | .unwrap_or(id) | |
| 351 | - | .to_string(); | |
| 352 | - | let variant = meta | |
| 353 | - | .and_then(|m| m.get("variant")) | |
| 354 | - | .and_then(|v| v.as_str()) | |
| 355 | - | .unwrap_or("dark") | |
| 356 | - | .to_string(); | |
| 357 | - | ||
| 358 | - | ThemeMeta { id: id.to_string(), name, variant, is_custom } | |
| 359 | - | } | |
| 360 | - | ||
| 361 | - | /// Extract the intent color sections into a flat `HashMap` with dotted keys | |
| 362 | - | /// like `"surface.page"`, `"status.danger"`, `"category.one"`. | |
| 363 | - | pub fn extract_colors(table: &toml::Table) -> HashMap<String, String> { | |
| 364 | - | let mut colors = HashMap::new(); | |
| 365 | - | for section in COLOR_SECTIONS { | |
| 366 | - | if let Some(sect) = table.get(*section).and_then(|s| s.as_table()) { | |
| 367 | - | for (key, val) in sect { | |
| 368 | - | if let Some(color) = val.as_str() { | |
| 369 | - | colors.insert(format!("{}.{}", section, key), color.to_string()); | |
| 370 | - | } | |
| 371 | - | } | |
| 372 | - | } | |
| 373 | - | } | |
| 374 | - | colors | |
| 375 | - | } | |
| 376 | - | ||
| 377 | - | /// Scan directories for `.toml` theme files and return metadata for each. | |
| 378 | - | /// | |
| 379 | - | /// Directories are checked in order; later entries override earlier ones by ID. | |
| 380 | - | /// Each entry in `dirs` is `(path, is_custom)`. | |
| 381 | - | pub fn list_themes_from_dirs(dirs: &[(PathBuf, bool)]) -> Vec<ThemeMeta> { | |
| 382 | - | let mut seen: HashMap<String, ThemeMeta> = HashMap::new(); | |
| 383 | - | ||
| 384 | - | for (dir, is_custom) in dirs { | |
| 385 | - | let entries = match std::fs::read_dir(dir) { | |
| 386 | - | Ok(e) => e, | |
| 387 | - | Err(_) => continue, | |
| 388 | - | }; | |
| 389 | - | ||
| 390 | - | for entry in entries { | |
| 391 | - | let entry = match entry { | |
| 392 | - | Ok(e) => e, | |
| 393 | - | Err(_) => continue, | |
| 394 | - | }; | |
| 395 | - | let path = entry.path(); | |
| 396 | - | if path.extension().and_then(|e| e.to_str()) != Some("toml") { | |
| 397 | - | continue; | |
| 398 | - | } | |
| 399 | - | ||
| 400 | - | let id = path | |
| 401 | - | .file_stem() | |
| 402 | - | .and_then(|s| s.to_str()) | |
| 403 | - | .unwrap_or_default() | |
| 404 | - | .to_string(); | |
| 405 | - | ||
| 406 | - | let content = match std::fs::read_to_string(&path) { | |
| 407 | - | Ok(c) => c, | |
| 408 | - | Err(_) => continue, | |
| 409 | - | }; | |
| 410 | - | let table: toml::Table = match content.parse() { | |
| 411 | - | Ok(t) => t, | |
| 412 | - | Err(_) => continue, | |
| 413 | - | }; | |
| 414 | - | ||
| 415 | - | seen.insert(id.clone(), parse_meta(&id, &table, *is_custom)); | |
| 416 | - | } | |
| 417 | - | } | |
| 418 | - | ||
| 419 | - | let mut themes: Vec<ThemeMeta> = seen.into_values().collect(); | |
| 420 | - | themes.sort_by(|a, b| a.name.cmp(&b.name)); | |
| 421 | - | themes | |
| 422 | - | } | |
| 423 | - | ||
| 424 | - | /// Find a theme file by ID in the given directories. | |
| 425 | - | /// | |
| 426 | - | /// Checks directories in reverse order so the highest-priority directory wins. | |
| 427 | - | /// Returns `(path, is_custom)` or `None` if not found. | |
| 428 | - | pub fn find_theme_path(dirs: &[(PathBuf, bool)], id: &str) -> Option<(PathBuf, bool)> { | |
| 429 | - | let filename = format!("{}.toml", id); | |
| 430 | - | ||
| 431 | - | for (dir, is_custom) in dirs.iter().rev() { | |
| 432 | - | let path = dir.join(&filename); | |
| 433 | - | if path.is_file() { | |
| 434 | - | return Some((path, *is_custom)); | |
| 435 | - | } | |
| 436 | - | } | |
| 437 | - | ||
| 438 | - | None | |
| 439 | - | } | |
| 440 | - | ||
| 441 | - | /// Parse a complete theme (metadata + colors) from raw TOML content, with no | |
| 442 | - | /// filesystem access. For callers that embed themes at compile time. | |
| 443 | - | pub fn parse_theme_str(id: &str, content: &str, is_custom: bool) -> Result<ThemeColors, String> { | |
| 444 | - | validate_theme_id(id)?; | |
| 445 | - | let table: toml::Table = content | |
| 446 | - | .parse() | |
| 447 | - | .map_err(|e| format!("Failed to parse theme '{}': {}", id, e))?; | |
| 448 | - | let meta = parse_meta(id, &table, is_custom); | |
| 449 | - | let colors = extract_colors(&table); | |
| 450 | - | Ok(ThemeColors { meta, colors }) | |
| 451 | - | } | |
| 452 | - | ||
| 453 | - | /// Load a complete theme (metadata + colors) by ID from the given directories. | |
| 454 | - | pub fn load_theme(dirs: &[(PathBuf, bool)], id: &str) -> Result<ThemeColors, String> { | |
| 455 | - | validate_theme_id(id)?; | |
| 456 | - | ||
| 457 | - | let (path, is_custom) = | |
| 458 | - | find_theme_path(dirs, id).ok_or_else(|| format!("Theme '{}' not found", id))?; | |
| 459 | - | ||
| 460 | - | let content = std::fs::read_to_string(&path) | |
| 461 | - | .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; | |
| 462 | - | ||
| 463 | - | let table: toml::Table = content | |
| 464 | - | .parse() | |
| 465 | - | .map_err(|e| format!("Failed to parse {}: {}", path.display(), e))?; | |
| 466 | - | ||
| 467 | - | let meta = parse_meta(id, &table, is_custom); | |
| 468 | - | let colors = extract_colors(&table); | |
| 469 | - | ||
| 470 | - | Ok(ThemeColors { meta, colors }) | |
| 471 | - | } | |
| 472 | - | ||
| 473 | - | /// Load a theme and resolve it to the full intent token set in one step. | |
| 474 | - | pub fn load_semantic(dirs: &[(PathBuf, bool)], id: &str) -> Result<SemanticTokens, String> { | |
| 475 | - | Ok(resolve(&load_theme(dirs, id)?)) | |
| 476 | - | } | |
| 477 | - | ||
| 478 | - | /// Import a theme TOML file into the custom themes directory. | |
| 479 | - | /// | |
| 480 | - | /// Validates that the file is parseable TOML with at least one intent color | |
| 481 | - | /// section, then copies it to `custom_dir/{id}.toml`. Returns the theme metadata. | |
| 482 | - | pub fn import_theme(source_path: &Path, custom_dir: &Path) -> Result<ThemeMeta, String> { | |
| 483 | - | let content = std::fs::read_to_string(source_path) | |
| 484 | - | .map_err(|e| format!("Failed to read {}: {}", source_path.display(), e))?; | |
| 485 | - | ||
| 486 | - | let table: toml::Table = content | |
| 487 | - | .parse() | |
| 488 | - | .map_err(|e| format!("Invalid TOML: {}", e))?; | |
| 489 | - | ||
| 490 | - | let has_colors = COLOR_SECTIONS | |
| 491 | - | .iter() | |
| 492 | - | .any(|s| table.get(*s).and_then(|v| v.as_table()).is_some()); | |
| 493 | - | if !has_colors { | |
| 494 | - | return Err(format!( | |
| 495 | - | "Theme file must have at least one color section ({})", | |
| 496 | - | COLOR_SECTIONS.join(", ") | |
| 497 | - | )); | |
| 498 | - | } | |
| 499 | - | ||
| 500 | - | let id = source_path |
Lines truncated
| @@ -1,94 +0,0 @@ | |||
| 1 | - | # Themes | |
| 2 | - | ||
| 3 | - | 16 TOML color themes shared across GoingsOn, Balanced Breakfast, and audiofiles. | |
| 4 | - | ||
| 5 | - | ## Bundled Themes | |
| 6 | - | ||
| 7 | - | | File | Name | Variant | Source | | |
| 8 | - | |------|------|---------|--------| | |
| 9 | - | | `ayu-light.toml` | Ayu Light | light | [ayu-theme](https://github.com/ayu-theme) | | |
| 10 | - | | `catppuccin-latte.toml` | Catppuccin Latte | light | [Catppuccin](https://github.com/catppuccin/catppuccin) | | |
| 11 | - | | `catppuccin-mocha.toml` | Catppuccin Mocha | dark | [Catppuccin](https://github.com/catppuccin/catppuccin) | | |
| 12 | - | | `dracula.toml` | Dracula | dark | [Dracula](https://github.com/dracula/dracula-theme) | | |
| 13 | - | | `everforest.toml` | Everforest | dark | [Everforest](https://github.com/sainnhe/everforest) | | |
| 14 | - | | `flatwhite.toml` | Flatwhite | light | [Flatwhite](https://github.com/biletskyy/flatwhite-syntax) | | |
| 15 | - | | `gruvbox-dark.toml` | Gruvbox Dark | dark | [Gruvbox](https://github.com/morhetz/gruvbox) | | |
| 16 | - | | `gruvbox-light.toml` | Gruvbox Light | light | [Gruvbox](https://github.com/morhetz/gruvbox) | | |
| 17 | - | | `high-contrast.toml` | High Contrast | high-contrast | Original | | |
| 18 | - | | `kanagawa.toml` | Kanagawa | dark | [Kanagawa](https://github.com/rebelot/kanagawa.nvim) | | |
| 19 | - | | `neobrute.toml` | Neobrute | dark | Original | | |
| 20 | - | | `nord.toml` | Nord | dark | [Nord](https://github.com/nordtheme/nord) | | |
| 21 | - | | `rosepine-dawn.toml` | Rose Pine Dawn | light | [Rose Pine](https://github.com/rose-pine/rose-pine-theme) | | |
| 22 | - | | `rosepine.toml` | Rose Pine | dark | [Rose Pine](https://github.com/rose-pine/rose-pine-theme) | | |
| 23 | - | | `solarized-dark.toml` | Solarized Dark | dark | [Solarized](https://github.com/altercation/solarized) | | |
| 24 | - | | `tokyonight.toml` | Tokyo Night | dark | [Tokyo Night](https://github.com/folke/tokyonight.nvim) | | |
| 25 | - | ||
| 26 | - | ## File Format | |
| 27 | - | ||
| 28 | - | Each theme is a TOML file with four color sections: | |
| 29 | - | ||
| 30 | - | ```toml | |
| 31 | - | # Attribution (optional) | |
| 32 | - | # Based on Catppuccin by Catppuccin Org -- MIT License | |
| 33 | - | ||
| 34 | - | [meta] | |
| 35 | - | name = "Theme Name" # Display name (required) | |
| 36 | - | variant = "dark" # "dark", "light", or "high-contrast" | |
| 37 | - | ||
| 38 | - | [background] | |
| 39 | - | primary = "#181825" # Main background | |
| 40 | - | secondary = "#11111b" # Sidebar / panel background | |
| 41 | - | tertiary = "#313244" # Hover / selection background | |
| 42 | - | surface = "#1e1e2e" # Card / elevated surface | |
| 43 | - | ||
| 44 | - | [foreground] | |
| 45 | - | primary = "#cdd6f4" # Main text | |
| 46 | - | secondary = "#bac2de" # Secondary text | |
| 47 | - | muted = "#9399b2" # Placeholder / disabled text | |
| 48 | - | ||
| 49 | - | [accent] | |
| 50 | - | red = "#f38ba8" # Error, destructive actions | |
| 51 | - | green = "#a6e3a1" # Success, positive actions | |
| 52 | - | blue = "#89b4fa" # Links, primary accent | |
| 53 | - | yellow = "#f9e2af" # Warnings | |
| 54 | - | purple = "#cba6f7" # Tags, special elements | |
| 55 | - | cyan = "#89dceb" # Info, secondary accent | |
| 56 | - | ||
| 57 | - | [border] | |
| 58 | - | default = "#45475a" # Default border color | |
| 59 | - | ``` | |
| 60 | - | ||
| 61 | - | ### Required Fields | |
| 62 | - | ||
| 63 | - | - `[meta].name` -- falls back to the filename if missing | |
| 64 | - | - `[meta].variant` -- falls back to `"dark"` if missing | |
| 65 | - | - At least `[background].primary` and `[foreground].primary` for a usable theme | |
| 66 | - | ||
| 67 | - | All other fields are optional. Apps should fall back gracefully when a color key is missing. | |
| 68 | - | ||
| 69 | - | ### Theme ID | |
| 70 | - | ||
| 71 | - | The filename without `.toml` is the theme ID. IDs must contain only alphanumeric characters, hyphens, and underscores. Examples: `catppuccin-mocha`, `gruvbox-light`, `high-contrast`. | |
| 72 | - | ||
| 73 | - | ## How Apps Load Themes | |
| 74 | - | ||
| 75 | - | | App | Method | Crate | | |
| 76 | - | |-----|--------|-------| | |
| 77 | - | | GoingsOn | Runtime from disk via Tauri resource glob | `theme-common` | | |
| 78 | - | | Balanced Breakfast | Runtime from disk via Tauri resource glob | `theme-common` | | |
| 79 | - | | audiofiles | Compile-time embed via `include_str!` | Direct TOML parsing | | |
| 80 | - | ||
| 81 | - | GoingsOn and Balanced Breakfast include this directory as a Tauri resource (`../../../MNW/shared/themes/*.toml` in `tauri.conf.json`). The `theme-common` crate handles parsing and color extraction at runtime. | |
| 82 | - | ||
| 83 | - | audiofiles embeds theme files at compile time and parses TOML directly without the `theme-common` crate. | |
| 84 | - | ||
| 85 | - | ## Adding a New Theme | |
| 86 | - | ||
| 87 | - | 1. Create `your-theme-name.toml` in this directory | |
| 88 | - | 2. Add an attribution comment at the top if based on an existing theme | |
| 89 | - | 3. Fill in all sections (`meta`, `background`, `foreground`, `accent`, `border`) | |
| 90 | - | 4. The theme will be available automatically on next build (GO/BB pick it up via the resource glob, AF picks it up via compile-time include) | |
| 91 | - | ||
| 92 | - | ## License | |
| 93 | - | ||
| 94 | - | Individual theme color palettes are attributed to their original creators. The TOML files themselves are part of this project under PolyForm Noncommercial 1.0.0. |
| @@ -1,52 +0,0 @@ | |||
| 1 | - | # Based on Akari by Shu Kutsuzawa (cappyzawa) — MIT License | |
| 2 | - | # https://github.com/cappyzawa/akari-theme | |
| 3 | - | # | |
| 4 | - | # Akari Dawn — inspired by Japanese alleys lit by round lanterns. | |
| 5 | - | # Design principles from the source: light is singular (lantern-orange | |
| 6 | - | # is the only primary accent), blue is air not light (night sky), | |
| 7 | - | # purple stays muted, green is life, black is warm grey. Alloy adopts | |
| 8 | - | # this as its default light theme. | |
| 9 | - | # | |
| 10 | - | # Note on surface tiers: theme-common's convention is that `raised` | |
| 11 | - | # reads as elevated (lighter in light mode) and `sunken` as recessed | |
| 12 | - | # (darker). Akari's own Helix theme uses different semantics (a darker | |
| 13 | - | # "surface" for statusline / cursorline). The tiers below reinterpret | |
| 14 | - | # Akari's palette to theme-common's L-ordering while staying inside | |
| 15 | - | # the source's tonal range — page and sunken take Akari's own values; | |
| 16 | - | # raised and overlay are computed warmer/lighter tones that read as | |
| 17 | - | # "paper caught in more lamp light." | |
| 18 | - | ||
| 19 | - | [meta] | |
| 20 | - | name = "Akari Dawn" | |
| 21 | - | variant = "light" | |
| 22 | - | ||
| 23 | - | [surface] | |
| 24 | - | page = "#e4ded6" | |
| 25 | - | raised = "#ede7de" | |
| 26 | - | sunken = "#cfc4b6" | |
| 27 | - | overlay = "#f0ece4" | |
| 28 | - | ||
| 29 | - | [content] | |
| 30 | - | primary = "#1a1816" | |
| 31 | - | secondary = "#222d38" | |
| 32 | - | muted = "#514b45" | |
| 33 | - | ||
| 34 | - | [action] | |
| 35 | - | primary = "#8a4530" | |
| 36 | - | ||
| 37 | - | [status] | |
| 38 | - | danger = "#6a2828" | |
| 39 | - | success = "#3a5830" | |
| 40 | - | warning = "#b07840" | |
| 41 | - | info = "#304050" | |
| 42 | - | ||
| 43 | - | [line] | |
| 44 | - | border = "#cabeae" | |
| 45 | - | ||
| 46 | - | [category] | |
| 47 | - | one = "#8a4530" | |
| 48 | - | two = "#3a5830" | |
| 49 | - | three = "#304050" | |
| 50 | - | four = "#b07840" | |
| 51 | - | five = "#806080" | |
| 52 | - | six = "#305858" |
| @@ -1,42 +0,0 @@ | |||
| 1 | - | # Based on Akari by Shu Kutsuzawa (cappyzawa) — MIT License | |
| 2 | - | # https://github.com/cappyzawa/akari-theme | |
| 3 | - | # | |
| 4 | - | # Akari Night — dark counterpart to Akari Dawn. Same design principles: | |
| 5 | - | # lantern-orange is the only primary light source, blue is night sky | |
| 6 | - | # (not accent light), green is life, purple stays quiet. Alloy adopts | |
| 7 | - | # this as its default dark theme. | |
| 8 | - | ||
| 9 | - | [meta] | |
| 10 | - | name = "Akari Night" | |
| 11 | - | variant = "dark" | |
| 12 | - | ||
| 13 | - | [surface] | |
| 14 | - | page = "#25231f" | |
| 15 | - | raised = "#2e2c27" | |
| 16 | - | sunken = "#1c1a17" | |
| 17 | - | overlay = "#35322c" | |
| 18 | - | ||
| 19 | - | [content] | |
| 20 | - | primary = "#e6ded3" | |
| 21 | - | secondary = "#c0b8ad" | |
| 22 | - | muted = "#8e847a" | |
| 23 | - | ||
| 24 | - | [action] | |
| 25 | - | primary = "#e26a3b" | |
| 26 | - | ||
| 27 | - | [status] | |
| 28 | - | danger = "#d25046" | |
| 29 | - | success = "#7faf6a" | |
| 30 | - | warning = "#d4a05a" | |
| 31 | - | info = "#7a8fa2" | |
| 32 | - | ||
| 33 | - | [line] | |
| 34 | - | border = "#3d3a35" | |
| 35 | - | ||
| 36 | - | [category] | |
| 37 | - | one = "#e26a3b" | |
| 38 | - | two = "#7faf6a" | |
| 39 | - | three = "#7a8fa2" | |
| 40 | - | four = "#d4a05a" | |
| 41 | - | five = "#8e7ba0" | |
| 42 | - | six = "#6f8f8a" |
| @@ -1,39 +0,0 @@ | |||
| 1 | - | # audiofiles — the app's titular default skin. Cross-available as a universal | |
| 2 | - | # theme. Built from a 5-tone earthy palette: Ash Grey #CCDAD1 / #9CAEA9, | |
| 3 | - | # Grey Olive #788585, Dim Grey #6F6866, Deep Mocha #38302E. Accents are | |
| 4 | - | # desaturated naturals tuned to harmonize with the sage-to-mocha range. | |
| 5 | - | ||
| 6 | - | [meta] | |
| 7 | - | name = "audiofiles" | |
| 8 | - | variant = "light" | |
| 9 | - | ||
| 10 | - | [surface] | |
| 11 | - | page = "#CCDAD1" | |
| 12 | - | raised = "#DAE3DC" | |
| 13 | - | sunken = "#9CAEA9" | |
| 14 | - | overlay = "#B4C5BB" | |
| 15 | - | ||
| 16 | - | [content] | |
| 17 | - | primary = "#38302E" | |
| 18 | - | secondary = "#6F6866" | |
| 19 | - | muted = "#788585" | |
| 20 | - | ||
| 21 | - | [action] | |
| 22 | - | primary = "#5E7C8E" | |
| 23 | - | ||
| 24 | - | [status] | |
| 25 | - | danger = "#B05F4E" | |
| 26 | - | success = "#6F8A5C" | |
| 27 | - | warning = "#C19A53" | |
| 28 | - | info = "#5F8C82" | |
| 29 | - | ||
| 30 | - | [line] | |
| 31 | - | border = "#9CAEA9" | |
| 32 | - | ||
| 33 | - | [category] | |
| 34 | - | one = "#B05F4E" | |
| 35 | - | two = "#6F8A5C" | |
| 36 | - | three = "#5E7C8E" | |
| 37 | - | four = "#C19A53" | |
| 38 | - | five = "#836A80" | |
| 39 | - | six = "#5F8C82" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Ayu by Konstantin Pschera — MIT License | |
| 2 | - | # https://github.com/ayu-theme | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Ayu Light" | |
| 6 | - | variant = "light" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#e7eaed" | |
| 10 | - | raised = "#f2f4f6" | |
| 11 | - | sunken = "#d0d4d8" | |
| 12 | - | overlay = "#dde1e5" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#5c6166" | |
| 16 | - | secondary = "#6b7580" | |
| 17 | - | muted = "#8b9199" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#399ee6" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#f07171" | |
| 24 | - | success = "#86b300" | |
| 25 | - | warning = "#ffaa33" | |
| 26 | - | info = "#55b4d4" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#828c9a" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#f07171" | |
| 33 | - | two = "#86b300" | |
| 34 | - | three = "#399ee6" | |
| 35 | - | four = "#ffaa33" | |
| 36 | - | five = "#a37acc" | |
| 37 | - | six = "#55b4d4" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Ayu by dempfi — MIT License | |
| 2 | - | # https://github.com/ayu-theme/ayu-colors | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Ayu Mirage" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#1f2430" | |
| 10 | - | raised = "#242936" | |
| 11 | - | sunken = "#272d38" | |
| 12 | - | overlay = "#191e29" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#cccac2" | |
| 16 | - | secondary = "#b8b4aa" | |
| 17 | - | muted = "#707a8c" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#5ccfe6" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#f28779" | |
| 24 | - | success = "#bae67e" | |
| 25 | - | warning = "#ffd580" | |
| 26 | - | info = "#95e6cb" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#33415e" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#f28779" | |
| 33 | - | two = "#bae67e" | |
| 34 | - | three = "#5ccfe6" | |
| 35 | - | four = "#ffd580" | |
| 36 | - | five = "#d4bfff" | |
| 37 | - | six = "#95e6cb" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Carbonfox by EdenEast — MIT License | |
| 2 | - | # https://github.com/EdenEast/nightfox.nvim | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Carbonfox" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#161616" | |
| 10 | - | raised = "#252525" | |
| 11 | - | sunken = "#1e1e1e" | |
| 12 | - | overlay = "#101010" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#f2f4f8" | |
| 16 | - | secondary = "#dde1e6" | |
| 17 | - | muted = "#878d96" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#78a9ff" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#ee5396" | |
| 24 | - | success = "#25be6a" | |
| 25 | - | warning = "#08bdba" | |
| 26 | - | info = "#33b1ff" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#393939" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#ee5396" | |
| 33 | - | two = "#25be6a" | |
| 34 | - | three = "#78a9ff" | |
| 35 | - | four = "#08bdba" | |
| 36 | - | five = "#be95ff" | |
| 37 | - | six = "#33b1ff" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Catppuccin by Catppuccin Org — MIT License | |
| 2 | - | # https://github.com/catppuccin/catppuccin | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Catppuccin Frappé" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#303446" | |
| 10 | - | raised = "#232634" | |
| 11 | - | sunken = "#414559" | |
| 12 | - | overlay = "#292c3c" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#c6d0f5" | |
| 16 | - | secondary = "#b5bfe2" | |
| 17 | - | muted = "#a5adce" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#8caaee" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#e78284" | |
| 24 | - | success = "#a6d189" | |
| 25 | - | warning = "#e5c890" | |
| 26 | - | info = "#81c8be" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#626880" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#e78284" | |
| 33 | - | two = "#a6d189" | |
| 34 | - | three = "#8caaee" | |
| 35 | - | four = "#e5c890" | |
| 36 | - | five = "#ca9ee6" | |
| 37 | - | six = "#81c8be" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Catppuccin by Catppuccin Org — MIT License | |
| 2 | - | # https://github.com/catppuccin/catppuccin | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Catppuccin Latte" | |
| 6 | - | variant = "light" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#e6e9ef" | |
| 10 | - | raised = "#eff1f5" | |
| 11 | - | sunken = "#ccd0da" | |
| 12 | - | overlay = "#dce0e8" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#4c4f69" | |
| 16 | - | secondary = "#5c5f77" | |
| 17 | - | muted = "#6c6f82" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#1e66f5" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#d20f39" | |
| 24 | - | success = "#40a02b" | |
| 25 | - | warning = "#df8e1d" | |
| 26 | - | info = "#04a5e5" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#bcc0cc" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#d20f39" | |
| 33 | - | two = "#40a02b" | |
| 34 | - | three = "#1e66f5" | |
| 35 | - | four = "#df8e1d" | |
| 36 | - | five = "#8839ef" | |
| 37 | - | six = "#04a5e5" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Catppuccin by Catppuccin Org — MIT License | |
| 2 | - | # https://github.com/catppuccin/catppuccin | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Catppuccin Macchiato" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#24273a" | |
| 10 | - | raised = "#181926" | |
| 11 | - | sunken = "#363a4f" | |
| 12 | - | overlay = "#1e2030" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#cad3f5" | |
| 16 | - | secondary = "#b8c0e0" | |
| 17 | - | muted = "#a5adcb" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#8aadf4" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#ed8796" | |
| 24 | - | success = "#a6da95" | |
| 25 | - | warning = "#eed49f" | |
| 26 | - | info = "#8bd5ca" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#5b6078" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#ed8796" | |
| 33 | - | two = "#a6da95" | |
| 34 | - | three = "#8aadf4" | |
| 35 | - | four = "#eed49f" | |
| 36 | - | five = "#c6a0f6" | |
| 37 | - | six = "#8bd5ca" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Catppuccin by Catppuccin Org — MIT License | |
| 2 | - | # https://github.com/catppuccin/catppuccin | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Catppuccin Mocha" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#181825" | |
| 10 | - | raised = "#1e1e2e" | |
| 11 | - | sunken = "#313244" | |
| 12 | - | overlay = "#11111b" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#cdd6f4" | |
| 16 | - | secondary = "#bac2de" | |
| 17 | - | muted = "#9399b2" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#89b4fa" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#f38ba8" | |
| 24 | - | success = "#a6e3a1" | |
| 25 | - | warning = "#f9e2af" | |
| 26 | - | info = "#89dceb" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#45475a" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#f38ba8" | |
| 33 | - | two = "#a6e3a1" | |
| 34 | - | three = "#89b4fa" | |
| 35 | - | four = "#f9e2af" | |
| 36 | - | five = "#cba6f7" | |
| 37 | - | six = "#89dceb" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Dawnfox by EdenEast — MIT License | |
| 2 | - | # https://github.com/EdenEast/nightfox.nvim | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Dawnfox" | |
| 6 | - | variant = "light" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#faf4ed" | |
| 10 | - | raised = "#f5efe8" | |
| 11 | - | sunken = "#ebe0df" | |
| 12 | - | overlay = "#ebe5df" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#575279" | |
| 16 | - | secondary = "#625c87" | |
| 17 | - | muted = "#a8a3b3" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#286983" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#b4637a" | |
| 24 | - | success = "#618774" | |
| 25 | - | warning = "#ea9d34" | |
| 26 | - | info = "#56949f" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#bdbfc9" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#b4637a" | |
| 33 | - | two = "#618774" | |
| 34 | - | three = "#286983" | |
| 35 | - | four = "#ea9d34" | |
| 36 | - | five = "#907aa9" | |
| 37 | - | six = "#56949f" |
| @@ -1,37 +0,0 @@ | |||
| 1 | - | # Based on Dracula by Dracula Theme — MIT License | |
| 2 | - | # https://github.com/dracula/dracula-theme | |
| 3 | - | ||
| 4 | - | [meta] | |
| 5 | - | name = "Dracula" | |
| 6 | - | variant = "dark" | |
| 7 | - | ||
| 8 | - | [surface] | |
| 9 | - | page = "#222430" | |
| 10 | - | raised = "#282A36" | |
| 11 | - | sunken = "#44475a" | |
| 12 | - | overlay = "#191A21" | |
| 13 | - | ||
| 14 | - | [content] | |
| 15 | - | primary = "#f8f8f2" | |
| 16 | - | secondary = "#f8f8f2" | |
| 17 | - | muted = "#6272A4" | |
| 18 | - | ||
| 19 | - | [action] | |
| 20 | - | primary = "#8be9fd" | |
| 21 | - | ||
| 22 | - | [status] | |
| 23 | - | danger = "#ff5555" | |
| 24 | - | success = "#50fa7b" | |
| 25 | - | warning = "#f1fa8c" | |
| 26 | - | info = "#8be9fd" | |
| 27 | - | ||
| 28 | - | [line] | |
| 29 | - | border = "#44475a" | |
| 30 | - | ||
| 31 | - | [category] | |
| 32 | - | one = "#ff5555" | |
| 33 | - | two = "#50fa7b" | |
| 34 | - | three = "#8be9fd" | |
| 35 | - | four = "#f1fa8c" | |
| 36 | - | five = "#BD93F9" | |
| 37 | - | six = "#8be9fd" |